]> The Tcpdump Group git mirrors - libpcap/commitdiff
From Pawel Pokrywka: add support for requesting that only received
authorguy <guy>
Tue, 3 May 2005 18:53:58 +0000 (18:53 +0000)
committerguy <guy>
Tue, 3 May 2005 18:53:58 +0000 (18:53 +0000)
packets, only sent packets, or all packets be accepted, with an
implementation for Linux.

Add an implementation for BPF platforms that support BIOCSSEESENT.

15 files changed:
CREDITS
pcap-bpf.c
pcap-dag.c
pcap-dlpi.c
pcap-dos.c
pcap-int.h
pcap-linux.c
pcap-nit.c
pcap-pf.c
pcap-snit.c
pcap-snoop.c
pcap-win32.c
pcap.3
pcap.c
pcap.h

diff --git a/CREDITS b/CREDITS
index 7c0e9cc08f41a8a186f1f4435095a5c52d08dfea..7797b9eeed7a8543cc4c79160c863900d072cf7c 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -71,6 +71,7 @@ Additional people who have contributed patches:
        Patrick Marie                   <[email protected]>
        Paul Mundt                      <[email protected]>
        Pavel Kankovsky                 <[email protected]>
+       Pawel Pokrywka                  <[email protected]>
        Peter Fales                     <[email protected]>
        Peter Jeremy                    <[email protected]>
        Phil Wood                       <[email protected]>
index 491d4ed2c2e250f7b961669f8391f34ec1d1565a..42318a1dc481572fb4ef207df9e69903fe6f2c83 100644 (file)
@@ -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)
 {
index 5aba689b0ecbe25c81836037fb7e9dc014953740..13d6d173246c698a993df7b857df658c8b9b0ba4 100644 (file)
@@ -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;
index 22c1dfd36de54228a6447f02eb02eef2d918d662..a9fa6b8292b5b435953e1d4f86d689f652608c70 100644 (file)
@@ -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;
index 26a925b372095cfdf8e3cc0b47ffc7abadbd1060..9e4df2b3a7cee1db4e973dd8c0779ab8bd37898b 100644 (file)
@@ -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 <stdio.h>
@@ -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 */
index 0c50473fae70b5d0b77f05e7662c4ed067249bfd..cd2d4f00b5f3dda741dab6a9818684c4a98efb1a 100644 (file)
@@ -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 *);
index 3daa661ed22ed29cada7631204cc0fb53a778377..307da05c0a5dd17db58563106ae56dd04cf2f59d 100644 (file)
@@ -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
index 6a8d318699c346ff9b2d78e1170bedf6b1ee81f1..3ef524525abb5f25d8ad79091b0886e93b21f9c6 100644 (file)
@@ -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;
index db6c7e7d4e9797f45a27394c328b17708b798516..5a479dd839b163bec889e821c0a013d1f0fbaee4 100644 (file)
--- 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;
index 447f343fa3ed96ad12202c5f2b3db8c5e3b3cb9f..350048150abf1c38dac67bd6d66bff1197042e0d 100644 (file)
@@ -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;
index 7a27b10b174b5406e198f85ffecd91fcb4e57472..e4545c44c8bcb1b7e7af095d550f93ddf60db2e0 100644 (file)
@@ -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;
index f6e37cf042a9a995cf8aa7c71bbe7ec56d48344f..f2bab6065aacab4e24ce57e9d1a445dc88e44840 100644 (file)
@@ -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 <pcap-int.h>
@@ -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 25e2f4708496d1edf10af4a3d3aef6d372fe06dc..e4dc880296cd6076b6d6b0fd7dd2002078ff1ae6 100644 (file)
--- 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 8aba35a3f76b7d2d33ded2d0ffff437ae4cde7eb..dcb31249396019b34214c73e8453d8a0acc7c29b 100644 (file)
--- 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 bfa819921e5991b7f5ece7808bdd441920c2da3e..f8a8f0351fce15a240c6a39b9eb965d044e1cd21 100644 (file)
--- 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 *);