]> The Tcpdump Group git mirrors - libpcap/blob - pcap-netfilter-linux.c
Revert "findalldevstest: temporary test to see if this squelches Valgrind warnings."
[libpcap] / pcap-netfilter-linux.c
1 /*
2 * Copyright (c) 2011 Jakub Zawadzki
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote
15 * products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include "pcap-int.h"
36 #include "diag-control.h"
37
38 #ifdef NEED_STRERROR_H
39 #include "strerror.h"
40 #endif
41
42 #include <errno.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <sys/socket.h>
47 #include <arpa/inet.h>
48
49 #include <time.h>
50 #include <sys/time.h>
51 #include <netinet/in.h>
52 #include <linux/types.h>
53
54 #include <linux/netlink.h>
55 #include <linux/netfilter.h>
56 #include <linux/netfilter/nfnetlink.h>
57 #include <linux/netfilter/nfnetlink_log.h>
58 #include <linux/netfilter/nfnetlink_queue.h>
59
60 /* NOTE: if your program drops privileges after pcap_activate() it WON'T work with nfqueue.
61 * It took me quite some time to debug ;/
62 *
63 * Sending any data to nfnetlink socket requires CAP_NET_ADMIN privileges,
64 * and in nfqueue we need to send verdict reply after recving packet.
65 *
66 * In tcpdump you can disable dropping privileges with -Z root
67 */
68
69 #include "pcap-netfilter-linux.h"
70
71 #define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
72
73 #define NFLOG_IFACE "nflog"
74 #define NFQUEUE_IFACE "nfqueue"
75
76 typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t;
77
78 /*
79 * Private data for capturing on Linux netfilter sockets.
80 */
81 struct pcap_netfilter {
82 u_int packets_read; /* count of packets read with recvfrom() */
83 u_int packets_nobufs; /* ENOBUFS counter */
84 };
85
86 static int nfqueue_send_verdict(const pcap_t *handle, uint16_t group_id, u_int32_t id, u_int32_t verdict);
87
88
89 static int
90 netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
91 {
92 struct pcap_netfilter *handlep = handle->priv;
93 register u_char *bp, *ep;
94 int count = 0;
95 ssize_t len;
96
97 /*
98 * Has "pcap_breakloop()" been called?
99 */
100 if (handle->break_loop) {
101 /*
102 * Yes - clear the flag that indicates that it
103 * has, and return PCAP_ERROR_BREAK to indicate
104 * that we were told to break out of the loop.
105 */
106 handle->break_loop = 0;
107 return PCAP_ERROR_BREAK;
108 }
109 len = handle->cc;
110 if (len == 0) {
111 /*
112 * The buffer is empty; refill it.
113 *
114 * We ignore EINTR, as that might just be due to a signal
115 * being delivered - if the signal should interrupt the
116 * loop, the signal handler should call pcap_breakloop()
117 * to set handle->break_loop (we ignore it on other
118 * platforms as well).
119 */
120 do {
121 len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
122 if (handle->break_loop) {
123 handle->break_loop = 0;
124 return PCAP_ERROR_BREAK;
125 }
126 if (errno == ENOBUFS)
127 handlep->packets_nobufs++;
128 } while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
129
130 if (len < 0) {
131 pcap_fmt_errmsg_for_errno(handle->errbuf,
132 PCAP_ERRBUF_SIZE, errno, "Can't receive packet");
133 return PCAP_ERROR;
134 }
135
136 bp = (unsigned char *)handle->buffer;
137 } else
138 bp = handle->bp;
139 ep = bp + len;
140 while (bp < ep) {
141 const struct nlmsghdr *nlh = (const struct nlmsghdr *) bp;
142 uint32_t msg_len;
143 nftype_t type = OTHER;
144 /*
145 * Has "pcap_breakloop()" been called?
146 * If so, return immediately - if we haven't read any
147 * packets, clear the flag and return PCAP_ERROR_BREAK
148 * to indicate that we were told to break out of the loop,
149 * otherwise leave the flag set, so that the *next* call
150 * will break out of the loop without having read any
151 * packets, and return the number of packets we've
152 * processed so far.
153 */
154 if (handle->break_loop) {
155 handle->bp = bp;
156 handle->cc = (int)(ep - bp);
157 if (count == 0) {
158 handle->break_loop = 0;
159 return PCAP_ERROR_BREAK;
160 } else
161 return count;
162 }
163 /*
164 * NLMSG_SPACE(0) might be signed or might be unsigned,
165 * depending on whether the kernel defines NLMSG_ALIGNTO
166 * as 4, which older kernels do, or as 4U, which newer
167 * kernels do.
168 *
169 * ep - bp is of type ptrdiff_t, which is signed.
170 *
171 * To squelch warnings, we cast both to size_t, which
172 * is unsigned; ep >= bp, so the cast is safe.
173 */
174 if ((size_t)(ep - bp) < (size_t)NLMSG_SPACE(0)) {
175 /*
176 * There's less than one netlink message left
177 * in the buffer. Give up.
178 */
179 break;
180 }
181
182 if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || (u_int)len < nlh->nlmsg_len) {
183 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %zd) (nlmsg_len: %u)", len, nlh->nlmsg_len);
184 return -1;
185 }
186
187 if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG &&
188 NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET)
189 type = NFLOG;
190 else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE &&
191 NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET)
192 type = NFQUEUE;
193
194 if (type != OTHER) {
195 const unsigned char *payload = NULL;
196 struct pcap_pkthdr pkth;
197
198 const struct nfgenmsg *nfg = NULL;
199 int id = 0;
200
201 if (handle->linktype != DLT_NFLOG) {
202 const struct nfattr *payload_attr = NULL;
203
204 if (nlh->nlmsg_len < HDR_LENGTH) {
205 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
206 return -1;
207 }
208
209 nfg = NLMSG_DATA(nlh);
210 if (nlh->nlmsg_len > HDR_LENGTH) {
211 struct nfattr *attr = NFM_NFA(nfg);
212 int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH);
213
214 while (NFA_OK(attr, attr_len)) {
215 if (type == NFQUEUE) {
216 switch (NFA_TYPE(attr)) {
217 case NFQA_PACKET_HDR:
218 {
219 const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr);
220
221 id = ntohl(pkt_hdr->packet_id);
222 break;
223 }
224 case NFQA_PAYLOAD:
225 payload_attr = attr;
226 break;
227 }
228
229 } else if (type == NFLOG) {
230 switch (NFA_TYPE(attr)) {
231 case NFULA_PAYLOAD:
232 payload_attr = attr;
233 break;
234 }
235 }
236 attr = NFA_NEXT(attr, attr_len);
237 }
238 }
239
240 if (payload_attr) {
241 payload = NFA_DATA(payload_attr);
242 pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr);
243 }
244
245 } else {
246 payload = NLMSG_DATA(nlh);
247 pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr));
248 }
249
250 if (payload) {
251 /* pkth.caplen = min (payload_len, handle->snapshot); */
252
253 gettimeofday(&pkth.ts, NULL);
254 if (handle->fcode.bf_insns == NULL ||
255 pcap_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
256 {
257 handlep->packets_read++;
258 callback(user, &pkth, payload);
259 count++;
260 }
261 }
262
263 if (type == NFQUEUE) {
264 /* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */
265 /* if type == NFQUEUE, handle->linktype is always != DLT_NFLOG,
266 so nfg is always initialized to NLMSG_DATA(nlh). */
267 if (nfg != NULL)
268 nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
269 }
270 }
271
272 msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
273 /*
274 * If the message length would run past the end of the
275 * buffer, truncate it to the remaining space in the
276 * buffer.
277 *
278 * To squelch warnings, we cast ep - bp to uint32_t, which
279 * is unsigned and is the type of msg_len; ep >= bp, and
280 * len should fit in 32 bits (either it's set from an int
281 * or it's set from a recv() call with a buffer size that's
282 * an int, and we're assuming either ILP32 or LP64), so
283 * the cast is safe.
284 */
285 if (msg_len > (uint32_t)(ep - bp))
286 msg_len = (uint32_t)(ep - bp);
287
288 bp += msg_len;
289 if (count >= max_packets && !PACKET_COUNT_IS_UNLIMITED(max_packets)) {
290 handle->bp = bp;
291 handle->cc = (int)(ep - bp);
292 if (handle->cc < 0)
293 handle->cc = 0;
294 return count;
295 }
296 }
297
298 handle->cc = 0;
299 return count;
300 }
301
302 static int
303 netfilter_set_datalink(pcap_t *handle, int dlt)
304 {
305 handle->linktype = dlt;
306 return 0;
307 }
308
309 static int
310 netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
311 {
312 struct pcap_netfilter *handlep = handle->priv;
313
314 stats->ps_recv = handlep->packets_read;
315 stats->ps_drop = handlep->packets_nobufs;
316 stats->ps_ifdrop = 0;
317 return 0;
318 }
319
320 static int
321 netfilter_inject_linux(pcap_t *handle, const void *buf _U_, int size _U_)
322 {
323 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
324 "Packet injection is not supported on netfilter devices");
325 return (-1);
326 }
327
328 struct my_nfattr {
329 uint16_t nfa_len;
330 uint16_t nfa_type;
331 void *data;
332 };
333
334 static int
335 netfilter_send_config_msg(const pcap_t *handle, uint16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
336 {
337 char buf[1024] __attribute__ ((aligned));
338 memset(buf, 0, sizeof(buf));
339
340 struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
341 struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr));
342
343 struct sockaddr_nl snl;
344 static unsigned int seq_id;
345
346 if (!seq_id)
347 DIAG_OFF_NARROWING
348 seq_id = time(NULL);
349 DIAG_ON_NARROWING
350 ++seq_id;
351
352 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg));
353 nlh->nlmsg_type = msg_type;
354 nlh->nlmsg_flags = NLM_F_REQUEST | (ack ? NLM_F_ACK : 0);
355 nlh->nlmsg_pid = 0; /* to kernel */
356 nlh->nlmsg_seq = seq_id;
357
358 nfg->nfgen_family = family;
359 nfg->version = NFNETLINK_V0;
360 nfg->res_id = htons(res_id);
361
362 if (mynfa) {
363 struct nfattr *nfa = (struct nfattr *) (buf + NLMSG_ALIGN(nlh->nlmsg_len));
364
365 nfa->nfa_type = mynfa->nfa_type;
366 nfa->nfa_len = NFA_LENGTH(mynfa->nfa_len);
367 memcpy(NFA_DATA(nfa), mynfa->data, mynfa->nfa_len);
368 nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + NFA_ALIGN(nfa->nfa_len);
369 }
370
371 memset(&snl, 0, sizeof(snl));
372 snl.nl_family = AF_NETLINK;
373
374 if (sendto(handle->fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) &snl, sizeof(snl)) == -1)
375 return -1;
376
377 if (!ack)
378 return 0;
379
380 /* waiting for reply loop */
381 do {
382 socklen_t addrlen = sizeof(snl);
383 int len;
384
385 /* ignore interrupt system call error */
386 do {
387 /*
388 * The buffer is not so big that its size won't
389 * fit into an int.
390 */
391 len = (int)recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen);
392 } while ((len == -1) && (errno == EINTR));
393
394 if (len <= 0)
395 return len;
396
397 if (addrlen != sizeof(snl) || snl.nl_family != AF_NETLINK) {
398 errno = EINVAL;
399 return -1;
400 }
401
402 nlh = (struct nlmsghdr *) buf;
403 if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq) /* if not from kernel or wrong sequence skip */
404 continue;
405
406 while ((u_int)len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, (u_int)len)) {
407 if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) {
408 if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) {
409 errno = EBADMSG;
410 return -1;
411 }
412 errno = -(*((int *)NLMSG_DATA(nlh)));
413 return (errno == 0) ? 0 : -1;
414 }
415 nlh = NLMSG_NEXT(nlh, len);
416 }
417 } while (1);
418
419 return -1; /* never here */
420 }
421
422 static int
423 nflog_send_config_msg(const pcap_t *handle, uint8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
424 {
425 return netfilter_send_config_msg(handle, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG, 1, family, group_id, mynfa);
426 }
427
428 static int
429 nflog_send_config_cmd(const pcap_t *handle, uint16_t group_id, u_int8_t cmd, u_int8_t family)
430 {
431 struct nfulnl_msg_config_cmd msg;
432 struct my_nfattr nfa;
433
434 msg.command = cmd;
435
436 nfa.data = &msg;
437 nfa.nfa_type = NFULA_CFG_CMD;
438 nfa.nfa_len = sizeof(msg);
439
440 return nflog_send_config_msg(handle, family, group_id, &nfa);
441 }
442
443 static int
444 nflog_send_config_mode(const pcap_t *handle, uint16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
445 {
446 struct nfulnl_msg_config_mode msg;
447 struct my_nfattr nfa;
448
449 msg.copy_range = htonl(copy_range);
450 msg.copy_mode = copy_mode;
451
452 nfa.data = &msg;
453 nfa.nfa_type = NFULA_CFG_MODE;
454 nfa.nfa_len = sizeof(msg);
455
456 return nflog_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
457 }
458
459 static int
460 nfqueue_send_verdict(const pcap_t *handle, uint16_t group_id, u_int32_t id, u_int32_t verdict)
461 {
462 struct nfqnl_msg_verdict_hdr msg;
463 struct my_nfattr nfa;
464
465 msg.id = htonl(id);
466 msg.verdict = htonl(verdict);
467
468 nfa.data = &msg;
469 nfa.nfa_type = NFQA_VERDICT_HDR;
470 nfa.nfa_len = sizeof(msg);
471
472 return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT, 0, AF_UNSPEC, group_id, &nfa);
473 }
474
475 static int
476 nfqueue_send_config_msg(const pcap_t *handle, uint8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
477 {
478 return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG, 1, family, group_id, mynfa);
479 }
480
481 static int
482 nfqueue_send_config_cmd(const pcap_t *handle, uint16_t group_id, u_int8_t cmd, u_int16_t pf)
483 {
484 struct nfqnl_msg_config_cmd msg;
485 struct my_nfattr nfa;
486
487 msg.command = cmd;
488 msg.pf = htons(pf);
489
490 nfa.data = &msg;
491 nfa.nfa_type = NFQA_CFG_CMD;
492 nfa.nfa_len = sizeof(msg);
493
494 return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
495 }
496
497 static int
498 nfqueue_send_config_mode(const pcap_t *handle, uint16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
499 {
500 struct nfqnl_msg_config_params msg;
501 struct my_nfattr nfa;
502
503 msg.copy_range = htonl(copy_range);
504 msg.copy_mode = copy_mode;
505
506 nfa.data = &msg;
507 nfa.nfa_type = NFQA_CFG_PARAMS;
508 nfa.nfa_len = sizeof(msg);
509
510 return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
511 }
512
513 static int
514 netfilter_activate(pcap_t* handle)
515 {
516 const char *dev = handle->opt.device;
517 unsigned short groups[32];
518 int group_count = 0;
519 nftype_t type = OTHER;
520 int i;
521
522 if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) {
523 dev += strlen(NFLOG_IFACE);
524 type = NFLOG;
525
526 } else if (strncmp(dev, NFQUEUE_IFACE, strlen(NFQUEUE_IFACE)) == 0) {
527 dev += strlen(NFQUEUE_IFACE);
528 type = NFQUEUE;
529 }
530
531 if (type != OTHER && *dev == ':') {
532 dev++;
533 while (*dev) {
534 long int group_id;
535 char *end_dev;
536
537 if (group_count == 32) {
538 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
539 "Maximum 32 netfilter groups! dev: %s",
540 handle->opt.device);
541 return PCAP_ERROR;
542 }
543
544 group_id = strtol(dev, &end_dev, 0);
545 if (end_dev != dev) {
546 if (group_id < 0 || group_id > 65535) {
547 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
548 "Netfilter group range from 0 to 65535 (got %ld)",
549 group_id);
550 return PCAP_ERROR;
551 }
552
553 groups[group_count++] = (unsigned short) group_id;
554 dev = end_dev;
555 }
556 if (*dev != ',')
557 break;
558 dev++;
559 }
560 }
561
562 if (type == OTHER || *dev) {
563 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
564 "Can't get netfilter group(s) index from %s",
565 handle->opt.device);
566 return PCAP_ERROR;
567 }
568
569 /* if no groups, add default: 0 */
570 if (!group_count) {
571 groups[0] = 0;
572 group_count = 1;
573 }
574
575 /*
576 * Turn a negative snapshot value (invalid), a snapshot value of
577 * 0 (unspecified), or a value bigger than the normal maximum
578 * value, into the maximum allowed value.
579 *
580 * If some application really *needs* a bigger snapshot
581 * length, we should just increase MAXIMUM_SNAPLEN.
582 */
583 if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
584 handle->snapshot = MAXIMUM_SNAPLEN;
585
586 /* Initialize some components of the pcap structure. */
587 handle->bufsize = 128 + handle->snapshot;
588 handle->offset = 0;
589 handle->read_op = netfilter_read_linux;
590 handle->inject_op = netfilter_inject_linux;
591 handle->setfilter_op = install_bpf_program; /* no kernel filtering */
592 handle->setdirection_op = NULL;
593 handle->set_datalink_op = netfilter_set_datalink;
594 handle->getnonblock_op = pcap_getnonblock_fd;
595 handle->setnonblock_op = pcap_setnonblock_fd;
596 handle->stats_op = netfilter_stats_linux;
597
598 /* Create netlink socket */
599 handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
600 if (handle->fd < 0) {
601 pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
602 errno, "Can't create raw socket");
603 return PCAP_ERROR;
604 }
605
606 if (type == NFLOG) {
607 handle->linktype = DLT_NFLOG;
608 handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
609 if (handle->dlt_list != NULL) {
610 handle->dlt_list[0] = DLT_NFLOG;
611 handle->dlt_list[1] = DLT_IPV4;
612 handle->dlt_count = 2;
613 }
614
615 } else
616 handle->linktype = DLT_IPV4;
617
618 handle->buffer = malloc(handle->bufsize);
619 if (!handle->buffer) {
620 pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
621 errno, "Can't allocate dump buffer");
622 goto close_fail;
623 }
624
625 if (type == NFLOG) {
626 if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
627 pcap_fmt_errmsg_for_errno(handle->errbuf,
628 PCAP_ERRBUF_SIZE, errno,
629 "NFULNL_CFG_CMD_PF_UNBIND");
630 goto close_fail;
631 }
632
633 if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
634 pcap_fmt_errmsg_for_errno(handle->errbuf,
635 PCAP_ERRBUF_SIZE, errno, "NFULNL_CFG_CMD_PF_BIND");
636 goto close_fail;
637 }
638
639 /* Bind socket to the nflog groups */
640 for (i = 0; i < group_count; i++) {
641 if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
642 pcap_fmt_errmsg_for_errno(handle->errbuf,
643 PCAP_ERRBUF_SIZE, errno,
644 "Can't listen on group index");
645 goto close_fail;
646 }
647
648 if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
649 pcap_fmt_errmsg_for_errno(handle->errbuf,
650 PCAP_ERRBUF_SIZE, errno,
651 "NFULNL_COPY_PACKET");
652 goto close_fail;
653 }
654 }
655
656 } else {
657 if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
658 pcap_fmt_errmsg_for_errno(handle->errbuf,
659 PCAP_ERRBUF_SIZE, errno, "NFQNL_CFG_CMD_PF_UNBIND");
660 goto close_fail;
661 }
662
663 if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
664 pcap_fmt_errmsg_for_errno(handle->errbuf,
665 PCAP_ERRBUF_SIZE, errno, "NFQNL_CFG_CMD_PF_BIND");
666 goto close_fail;
667 }
668
669 /* Bind socket to the nfqueue groups */
670 for (i = 0; i < group_count; i++) {
671 if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
672 pcap_fmt_errmsg_for_errno(handle->errbuf,
673 PCAP_ERRBUF_SIZE, errno,
674 "Can't listen on group index");
675 goto close_fail;
676 }
677
678 if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) {
679 pcap_fmt_errmsg_for_errno(handle->errbuf,
680 PCAP_ERRBUF_SIZE, errno,
681 "NFQNL_COPY_PACKET");
682 goto close_fail;
683 }
684 }
685 }
686
687 if (handle->opt.rfmon) {
688 /*
689 * Monitor mode doesn't apply to netfilter devices.
690 */
691 pcap_cleanup_live_common(handle);
692 return PCAP_ERROR_RFMON_NOTSUP;
693 }
694
695 if (handle->opt.buffer_size != 0) {
696 /*
697 * Set the socket buffer size to the specified value.
698 */
699 if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
700 pcap_fmt_errmsg_for_errno(handle->errbuf,
701 PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF");
702 goto close_fail;
703 }
704 }
705
706 handle->selectable_fd = handle->fd;
707 return 0;
708
709 close_fail:
710 pcap_cleanup_live_common(handle);
711 return PCAP_ERROR;
712 }
713
714 pcap_t *
715 netfilter_create(const char *device, char *ebuf, int *is_ours)
716 {
717 const char *cp;
718 pcap_t *p;
719
720 /* Does this look like an netfilter device? */
721 cp = strrchr(device, '/');
722 if (cp == NULL)
723 cp = device;
724
725 /* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */
726 if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0)
727 cp += sizeof NFLOG_IFACE - 1;
728 else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0)
729 cp += sizeof NFQUEUE_IFACE - 1;
730 else {
731 /* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */
732 *is_ours = 0;
733 return NULL;
734 }
735
736 /*
737 * Yes - is that either the end of the name, or is it followed
738 * by a colon?
739 */
740 if (*cp != ':' && *cp != '\0') {
741 /* Nope */
742 *is_ours = 0;
743 return NULL;
744 }
745
746 /* OK, it's probably ours. */
747 *is_ours = 1;
748
749 p = PCAP_CREATE_COMMON(ebuf, struct pcap_netfilter);
750 if (p == NULL)
751 return (NULL);
752
753 p->activate_op = netfilter_activate;
754 return (p);
755 }
756
757 int
758 netfilter_findalldevs(pcap_if_list_t *devlistp, char *err_str)
759 {
760 int sock;
761
762 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
763 if (sock < 0) {
764 /* if netlink is not supported this is not fatal */
765 if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
766 return 0;
767 pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
768 errno, "Can't open netlink socket");
769 return -1;
770 }
771 close(sock);
772
773 /*
774 * The notion of "connected" vs. "disconnected" doesn't apply.
775 * XXX - what about "up" and "running"?
776 */
777 if (add_dev(devlistp, NFLOG_IFACE,
778 PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
779 "Linux netfilter log (NFLOG) interface", err_str) == NULL)
780 return -1;
781 if (add_dev(devlistp, NFQUEUE_IFACE,
782 PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
783 "Linux netfilter queue (NFQUEUE) interface", err_str) == NULL)
784 return -1;
785 return 0;
786 }