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 
17 struct 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 
31 static 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 */
51 static 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 
66 int ipulog_errno = IPULOG_ERR_NONE;
67 
68 const 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 */
76 uint32_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 */
87 struct 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 
114 out_free:
115  ipulog_errno = IPULOG_ERR_HANDLE;
116  free(h);
117  return NULL;
118 }
119 
120 void 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 
127 ulog_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 {
139 next_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 
214 ssize_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 */
223 void 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)