From: guy Date: Tue, 3 May 2005 18:53:58 +0000 (+0000) Subject: From Pawel Pokrywka: add support for requesting that only received X-Git-Tag: libpcap-1.1.0~623 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/e987a615e2b8d2c9215eb3b6c14ec18845c20daa From Pawel Pokrywka: add support for requesting that only received packets, only sent packets, or all packets be accepted, with an implementation for Linux. Add an implementation for BPF platforms that support BIOCSSEESENT. --- diff --git a/CREDITS b/CREDITS index 7c0e9cc0..7797b9ee 100644 --- a/CREDITS +++ b/CREDITS @@ -71,6 +71,7 @@ Additional people who have contributed patches: Patrick Marie Paul Mundt Pavel Kankovsky + Pawel Pokrywka Peter Fales Peter Jeremy Phil Wood diff --git a/pcap-bpf.c b/pcap-bpf.c index 491d4ed2..42318a1d 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.88 2005-04-21 02:41:12 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.89 2005-05-03 18:53:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -105,6 +105,7 @@ static int odmlockid = 0; #include "gencode.h" /* for "no_optimize" */ static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp); +static int pcap_setdirection_bpf(pcap_t *, direction_t); static int pcap_set_datalink_bpf(pcap_t *p, int dlt); static int @@ -1019,6 +1020,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_bpf; p->inject_op = pcap_inject_bpf; p->setfilter_op = pcap_setfilter_bpf; + p->setdirection_op = pcap_setdirection_bpf; p->set_datalink_op = pcap_set_datalink_bpf; p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; @@ -1088,6 +1090,42 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) return (0); } +/* + * Set direction flag: Which packets do we accept on a forwarding + * single device? IN, OUT or both? + */ +static int +pcap_setdirection_bpf(pcap_t *p, direction_t d) +{ +#ifdef BIOCSSEESENT + u_int seesent; +#endif + + /* + * We don't support D_OUT. + */ + if (d == D_OUT) { + snprintf(p->errbuf, sizeof(p->errbuf), + "Setting direction to D_OUT is not supported on BPF"); + return -1; + } +#ifdef BIOCSSEESENT + seesent = (d == D_INOUT); + if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) { + (void) snprintf(p->errbuf, sizeof(p->errbuf), + "Cannot set direction to %s: %s", + (d == D_INOUT) ? "D_INOUT" : "D_IN", + strerror(errno)); + return (-1); + } + return (0); +#else + (void) snprintf(p->errbuf, sizeof(p->errbuf), + "This system doesn't support BIOCSSEESENT, so the direction can't be set"); + return (-1); +#endif +} + static int pcap_set_datalink_bpf(pcap_t *p, int dlt) { diff --git a/pcap-dag.c b/pcap-dag.c index 5aba689b..13d6d173 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -15,7 +15,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21 2005-04-03 23:56:47 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.22 2005-05-03 18:53:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -507,6 +507,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu handle->read_op = dag_read; handle->inject_op = dag_inject; handle->setfilter_op = dag_setfilter; + handle->setdirection_op = NULL; /* Not implemented.*/ handle->set_datalink_op = dag_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = dag_setnonblock; diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 22c1dfd3..a9fa6b82 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -70,7 +70,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.113 2005-04-17 17:25:51 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.114 2005-05-03 18:53:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -933,6 +933,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_dlpi; p->inject_op = pcap_inject_dlpi; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented.*/ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/pcap-dos.c b/pcap-dos.c index 26a925b3..9e4df2b3 100644 --- a/pcap-dos.c +++ b/pcap-dos.c @@ -5,7 +5,7 @@ * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode * network drivers. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1 2004-12-18 08:52:10 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.2 2005-05-03 18:53:59 guy Exp $ (LBL) */ #include @@ -172,6 +172,7 @@ pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc, pcap->stats_op = pcap_stats_dos; pcap->inject_op = pcap_sendpacket_dos; pcap->setfilter_op = pcap_setfilter_dos; + pcap->setdirection_op = NULL; /* Not implemented.*/ pcap->fd = ++ref_count; if (pcap->fd == 1) /* first time we're called */ diff --git a/pcap-int.h b/pcap-int.h index 0c50473f..cd2d4f00 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.70 2005-04-07 02:47:34 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.71 2005-05-03 18:53:59 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -150,12 +150,16 @@ struct pcap { */ u_char *pkt; + /* We're accepting only packets in this direction/these directions. */ + direction_t direction; + /* * Methods. */ int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *); int (*inject_op)(pcap_t *, const void *, size_t); int (*setfilter_op)(pcap_t *, struct bpf_program *); + int (*setdirection_op)(pcap_t *, direction_t); int (*set_datalink_op)(pcap_t *, int); int (*getnonblock_op)(pcap_t *, char *); int (*setnonblock_op)(pcap_t *, int, char *); diff --git a/pcap-linux.c b/pcap-linux.c index 3daa661e..307da05c 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -27,7 +27,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110 2004-10-19 07:06:12 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.111 2005-05-03 18:53:59 guy Exp $ (LBL)"; #endif /* @@ -191,6 +191,7 @@ static int pcap_read_packet(pcap_t *, pcap_handler, u_char *); static int pcap_inject_linux(pcap_t *, const void *, size_t); static int pcap_stats_linux(pcap_t *, struct pcap_stat *); static int pcap_setfilter_linux(pcap_t *, struct bpf_program *); +static int pcap_setdirection_linux(pcap_t *, direction_t); static void pcap_close_linux(pcap_t *); /* @@ -407,6 +408,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, handle->read_op = pcap_read_linux; handle->inject_op = pcap_inject_linux; handle->setfilter_op = pcap_setfilter_linux; + handle->setdirection_op = pcap_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; @@ -504,19 +506,37 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) } #ifdef HAVE_PF_PACKET_SOCKETS - /* - * If this is from the loopback device, reject outgoing packets; - * we'll see the packet as an incoming packet as well, and - * we don't want to see it twice. - * - * We can only do this if we're using PF_PACKET; the address - * returned for SOCK_PACKET is a "sockaddr_pkt" which lacks - * the relevant packet type information. - */ - if (!handle->md.sock_packet && - from.sll_ifindex == handle->md.lo_ifindex && - from.sll_pkttype == PACKET_OUTGOING) - return 0; + if (!handle->md.sock_packet) { + /* + * Do checks based on packet direction. + * We can only do this if we're using PF_PACKET; the + * address returned for SOCK_PACKET is a "sockaddr_pkt" + * which lacks the relevant packet type information. + */ + if (from.sll_pkttype == PACKET_OUTGOING) { + /* + * Outgoing packet. + * If this is from the loopback device, reject it; + * we'll see the packet as an incoming packet as well, + * and we don't want to see it twice. + */ + if (from.sll_ifindex == handle->md.lo_ifindex) + return 0; + + /* + * If the user only wants incoming packets, reject it. + */ + if (handle->direction == D_IN) + return 0; + } else { + /* + * Incoming packet. + * If the user only wants outgoing packets, reject it. + */ + if (handle->direction == D_OUT) + return 0; + } + } #endif #ifdef HAVE_PF_PACKET_SOCKETS @@ -974,6 +994,28 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) return 0; } +/* + * Set direction flag: Which packets do we accept on a forwarding + * single device? IN, OUT or both? + */ +static int +pcap_setdirection_linux(pcap_t *handle, direction_t d) +{ +#ifdef HAVE_PF_PACKET_SOCKETS + if (!handle->md.sock_packet) { + handle->direction = d; + return 0; + } +#endif + /* + * We're not using PF_PACKET sockets, so we can't determine + * the direction of the packet. + */ + snprintf(handle->errbuf, sizeof(handle->errbuf), + "Setting direction is not supported on SOCK_PACKET sockets"); + return -1; +} + /* * Linux uses the ARP hardware type to identify the type of an * interface. pcap uses the DLT_xxx constants for this. This diff --git a/pcap-nit.c b/pcap-nit.c index 6a8d3186..3ef52452 100644 --- a/pcap-nit.c +++ b/pcap-nit.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57 2004-10-19 07:06:13 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.58 2005-05-03 18:54:00 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -334,6 +334,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_nit; p->inject_op = pcap_inject_nit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/pcap-pf.c b/pcap-pf.c index db6c7e7d..5a479dd8 100644 --- a/pcap-pf.c +++ b/pcap-pf.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.92 2005-04-19 00:55:48 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.93 2005-05-03 18:54:00 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -497,6 +497,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->read_op = pcap_read_pf; p->inject_op = pcap_inject_pf; p->setfilter_op = pcap_setfilter_pf; + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/pcap-snit.c b/pcap-snit.c index 447f343f..35004815 100644 --- a/pcap-snit.c +++ b/pcap-snit.c @@ -25,7 +25,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72 2004-10-19 07:06:13 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.73 2005-05-03 18:54:00 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -397,6 +397,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_snit; p->inject_op = pcap_inject_snit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/pcap-snoop.c b/pcap-snoop.c index 7a27b10b..e4545c44 100644 --- a/pcap-snoop.c +++ b/pcap-snoop.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54 2004-10-19 07:06:14 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.55 2005-05-03 18:54:00 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -379,6 +379,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, p->read_op = pcap_read_snoop; p->inject_op = pcap_inject_snoop; p->setfilter_op = install_bpf_program; /* no kernel filtering */ + p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; diff --git a/pcap-win32.c b/pcap-win32.c index f6e37cf0..f2bab606 100644 --- a/pcap-win32.c +++ b/pcap-win32.c @@ -32,7 +32,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25 2005-02-26 21:58:06 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.26 2005-05-03 18:54:01 guy Exp $ (LBL)"; #endif #include @@ -602,6 +602,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, #ifdef HAVE_DAG_API } #endif /* HAVE_DAG_API */ + p->setdirection_op = NULL; /* Not implemented. */ + /* XXX - can this be implemented on some versions of Windows? */ p->inject_op = pcap_inject_win32; p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_win32; diff --git a/pcap.3 b/pcap.3 index 25e2f470..e4dc8802 100644 --- a/pcap.3 +++ b/pcap.3 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.65 2005-04-13 18:59:41 mcr Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.66 2005-05-03 18:54:01 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -79,7 +79,8 @@ int pcap_compile(pcap_t *p, struct bpf_program *fp, .ti +8 char *str, int optimize, bpf_u_int32 netmask) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) -void pcap_freecode(struct bpf_program *); +void pcap_freecode(struct bpf_program *) +int pcap_setdirection(pcap_t *p, direction_t d) .ft .LP .ft B @@ -777,6 +778,30 @@ when that BPF program is no longer needed, for example after it has been made the filter program for a pcap structure by a call to .BR pcap_setfilter() . .PP +.B pcap_setdirection() +is used to specify a direction that packets will be captured. +.I direction_t +is one of the constants +.BR D_IN , +.B D_OUT +or +.BR D_INOUT . +.B D_IN +will only capture packets received by the device, +.B D_OUT +will only capture packets sent by the device and +.B D_INOUT +will capture packets received by or sent by the device. +.B D_INOUT +is the default setting if this function is not called. This isn't +necessarily supported on all platforms; some platforms might return an +error, and some other platforms might not support +.BR D_OUT . +.B \-1 +is returned on failure, +.B 0 +is returned on success. +.PP .B pcap_datalink() returns the link layer type; link layer types it can return include: .PP diff --git a/pcap.c b/pcap.c index 8aba35a3..dcb31249 100644 --- a/pcap.c +++ b/pcap.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88 2005-02-08 20:03:15 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.89 2005-05-03 18:54:01 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -685,6 +685,23 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp) return p->setfilter_op(p, fp); } +/* + * Set direction flag, which controls whether we accept only incoming + * packets, only outgoing packets, or both. + * Note that, depending on the platform, some or all direction arguments + * might not be supported. + */ +int +pcap_setdirection(pcap_t *p, direction_t d) +{ + if (p->setdirection_op == NULL) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Setting direction is not implemented on this platform"); + return -1; + } else + return p->setdirection_op(p, d); +} + int pcap_stats(pcap_t *p, struct pcap_stat *ps) { diff --git a/pcap.h b/pcap.h index bfa81992..f8a8f035 100644 --- a/pcap.h +++ b/pcap.h @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52 2004-12-18 08:52:11 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.53 2005-05-03 18:54:02 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -120,6 +120,12 @@ struct pcap_file_header { bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; +typedef enum { + D_INOUT = 0, + D_IN, + D_OUT +} direction_t; + /* * Each packet in the dump file is prepended with this generic header. * This gets around the problem of different headers for different @@ -218,6 +224,7 @@ int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); void pcap_breakloop(pcap_t *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_setdirection(pcap_t *, direction_t); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); void pcap_perror(pcap_t *, char *);