libnetfilter_log 1.0.2
libipulog_compat.c
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <net/if.h>
8#include <netinet/in.h>
9#include <libnfnetlink/libnfnetlink.h>
10#include <libnetfilter_log/libnetfilter_log.h>
11#include <libnetfilter_log/libipulog.h>
12
13/* private */
14#define PAYLOAD_SIZE 0xffff
15
16
17struct ipulog_handle
18{
19 struct nflog_handle *nfulh;
20 struct nflog_g_handle *nful_gh;
21 struct nlmsghdr *last_nlh;
22#if 0
23 int fd;
24 uint8_t blocking;
25 struct sockaddr_nl local;
26 struct sockaddr_nl peer;
27#endif
28 struct ulog_packet_msg upmsg; /* has to be last in structure */
29};
30
31static const struct ipulog_errmap_t
32{
33 int errcode;
34 const char *message;
35} ipulog_errmap[] =
36{
37 { IPULOG_ERR_NONE, "No error" },
38 { IPULOG_ERR_IMPL, "Not implemented yet" },
39 { IPULOG_ERR_HANDLE, "Unable to create netlink handle" },
40 { IPULOG_ERR_SOCKET, "Unable to create netlink socket" },
41 { IPULOG_ERR_BIND, "Unable to bind netlink socket" },
42 { IPULOG_ERR_RECVBUF, "Receive buffer size invalid" },
43 { IPULOG_ERR_RECV, "Error during netlink receive" },
44 { IPULOG_ERR_NLEOF, "Received EOF on netlink socket" },
45 { IPULOG_ERR_TRUNC, "Receive message truncated" },
46 { IPULOG_ERR_INVGR, "Invalid group specified" },
47 { IPULOG_ERR_INVNL, "Invalid netlink message" },
48};
49
50/* obviously this only finds the highest group in the mask */
51static unsigned int gmask2group(unsigned int gmask)
52{
53 int bit;
54
55 for (bit = sizeof(gmask)*4 -1; bit >= 0; bit--) {
56 if (gmask & (1 << bit))
57 return bit+1;
58 }
59 return 0;
60}
61
62
63
64/* public */
65
66int ipulog_errno = IPULOG_ERR_NONE;
67
68const char *ipulog_strerror(int errcode)
69{
70 if (errcode < 0 || errcode > IPULOG_MAXERR)
71 errcode = IPULOG_ERR_IMPL;
72 return ipulog_errmap[errcode].message;
73}
74
75/* convert a netlink group (1-32) to a group_mask suitable for create_handle */
76uint32_t ipulog_group2gmask(uint32_t group)
77{
78 if (group < 1 || group > 32)
79 {
80 ipulog_errno = IPULOG_ERR_INVGR;
81 return 0;
82 }
83 return (1 << (group - 1));
84}
85
86/* create a ipulog handle for the reception of packets sent to gmask */
87struct ipulog_handle *ipulog_create_handle(uint32_t gmask,
88 uint32_t rcvbufsize)
89{
90 int rv;
91 struct ipulog_handle *h;
92 unsigned int group = gmask2group(gmask);
93
94 h = calloc(1, sizeof(*h)+PAYLOAD_SIZE);
95 if (! h) {
96 ipulog_errno = IPULOG_ERR_HANDLE;
97 return NULL;
98 }
99 h->nfulh = nflog_open();
100 if (!h->nfulh)
101 goto out_free;
102
103 /* bind_pf returns EEXIST if we are already registered */
104 rv = nflog_bind_pf(h->nfulh, AF_INET);
105 if (rv < 0 && rv != -EEXIST)
106 goto out_free;
107
108 h->nful_gh = nflog_bind_group(h->nfulh, group);
109 if (!h->nful_gh)
110 goto out_free;
111
112 return h;
113
114out_free:
115 ipulog_errno = IPULOG_ERR_HANDLE;
116 free(h);
117 return NULL;
118}
119
120void ipulog_destroy_handle(struct ipulog_handle *h)
121{
122 nflog_unbind_group(h->nful_gh);
123 nflog_close(h->nfulh);
124 free(h);
125}
126
127ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h,
128 const unsigned char *buf,
129 size_t len)
130{
131 struct nlmsghdr *nlh;
132 struct nfattr *tb[NFULA_MAX];
133 struct nfulnl_msg_packet_hdr *hdr;
134
135 if (!h->last_nlh) {
136 printf("first\n");
137 nlh = nfnl_get_msg_first(nflog_nfnlh(h->nfulh), buf, len);
138 }else {
139next_msg: printf("next\n");
140 nlh = nfnl_get_msg_next(nflog_nfnlh(h->nfulh), buf, len);
141 }
142 h->last_nlh = nlh;
143
144 if (!nlh)
145 return NULL;
146
147 nfnl_parse_attr(tb, NFULA_MAX, NFM_NFA(NLMSG_DATA(nlh)),
148 NFM_PAYLOAD(nlh));
149
150 if (!tb[NFULA_PACKET_HDR-1])
151 goto next_msg;
152
153 /* now build the fake ulog_packet_msg */
154 hdr = NFA_DATA(tb[NFULA_PACKET_HDR-1]);
155 h->upmsg.hook = hdr->hook;
156
157 if (tb[NFULA_MARK-1])
158 h->upmsg.mark = ntohl(*(uint32_t *)NFA_DATA(tb[NFULA_MARK-1]));
159 else
160 h->upmsg.mark = 0;
161
162 if (tb[NFULA_TIMESTAMP-1]) {
163 struct nfulnl_msg_packet_timestamp *ts;
164 ts = NFA_DATA(tb[NFULA_TIMESTAMP-1]);
165
166 h->upmsg.timestamp_sec = __be64_to_cpu(ts->sec);
167 h->upmsg.timestamp_usec = __be64_to_cpu(ts->usec);
168 } else
169 h->upmsg.timestamp_sec = h->upmsg.timestamp_usec = 0;
170
171 if (tb[NFULA_IFINDEX_INDEV-1]) {
172 void *indev_ptr = NFA_DATA(tb[NFULA_IFINDEX_INDEV-1]);
173 uint32_t indev_idx = ntohl(*(uint32_t *)indev_ptr);
174
175 if (!if_indextoname(indev_idx, h->upmsg.indev_name))
176 h->upmsg.indev_name[0] = '\0';
177 } else
178 h->upmsg.indev_name[0] = '\0';
179
180 if (tb[NFULA_IFINDEX_OUTDEV-1]) {
181 void *outdev_ptr = NFA_DATA(tb[NFULA_IFINDEX_OUTDEV-1]);
182 uint32_t outdev_idx = ntohl(*(uint32_t *)outdev_ptr);
183
184 if (!if_indextoname(outdev_idx, h->upmsg.outdev_name))
185 h->upmsg.outdev_name[0] = '\0';
186 } else
187 h->upmsg.outdev_name[0] = '\0';
188
189 if (tb[NFULA_HWADDR-1]) {
190 struct nfulnl_msg_packet_hw *phw = NFA_DATA(tb[NFULA_HWADDR-1]);
191 h->upmsg.mac_len = ntohs(phw->hw_addrlen);
192 memcpy(h->upmsg.mac, phw->hw_addr, 8);
193 } else
194 h->upmsg.mac_len = 0;
195
196 if (tb[NFULA_PREFIX-1]) {
197 int plen = NFA_PAYLOAD(tb[NFULA_PREFIX-1]);
198 if (ULOG_PREFIX_LEN < plen)
199 plen = ULOG_PREFIX_LEN;
200 memcpy(h->upmsg.prefix, NFA_DATA(tb[NFULA_PREFIX-1]), plen);
201 h->upmsg.prefix[ULOG_PREFIX_LEN-1] = '\0';
202 }
203
204 if (tb[NFULA_PAYLOAD-1]) {
205 memcpy(h->upmsg.payload, NFA_DATA(tb[NFULA_PAYLOAD-1]),
206 NFA_PAYLOAD(tb[NFULA_PAYLOAD-1]));
207 h->upmsg.data_len = NFA_PAYLOAD(tb[NFULA_PAYLOAD-1]);
208 } else
209 h->upmsg.data_len = 0;
210
211 return &h->upmsg;
212}
213
214ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf,
215 size_t len, int timeout)
216{
217 /* 'timeout' was never implemented in the original libipulog,
218 * so we don't bother emulating it */
219 return nfnl_recv(nflog_nfnlh(h->nfulh), buf, len);
220}
221
222/* print a human readable description of the last error to stderr */
223void ipulog_perror(const char *s)
224{
225 if (s)
226 fputs(s, stderr);
227 else
228 fputs("ERROR", stderr);
229 if (ipulog_errno)
230 fprintf(stderr, ": %s", ipulog_strerror(ipulog_errno));
231 if (errno)
232 fprintf(stderr, ": %s", strerror(errno));
233 fputc('\n', stderr);
234}
struct nflog_handle * nflog_open(void)
int nflog_bind_pf(struct nflog_handle *h, uint16_t pf)
int nflog_close(struct nflog_handle *h)
struct nflog_g_handle * nflog_bind_group(struct nflog_handle *h, uint16_t num)
int nflog_unbind_group(struct nflog_g_handle *gh)