]> The Tcpdump Group git mirrors - libpcap/commitdiff
Merge branch 'master' of git+ssh://bpf.tcpdump.org/tcpdump/master/git/libpcap
authorGuy Harris <[email protected]>
Wed, 21 Dec 2011 21:55:37 +0000 (13:55 -0800)
committerGuy Harris <[email protected]>
Wed, 21 Dec 2011 21:55:37 +0000 (13:55 -0800)
gencode.c
pcap-linux.c

index 7c8501a69f23f91d43d9bce61d6d7e3be75b2384..be8176b6017f87199ec74f94e09b3d7088c9f634 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -84,6 +84,10 @@ static const char rcsid[] _U_ =
 #include "pcap/sll.h"
 #include "pcap/ipnet.h"
 #include "arcnet.h"
+#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+#endif
 #ifdef HAVE_NET_PFVAR_H
 #include <sys/socket.h>
 #include <net/if.h>
@@ -7481,9 +7485,13 @@ gen_multicast(proto)
 }
 
 /*
- * generate command for inbound/outbound.  It's here so we can
- * make it link-type specific.  'dir' = 0 implies "inbound",
- * = 1 implies "outbound".
+ * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
+ * Outbound traffic is sent by this machine, while inbound traffic is
+ * sent by a remote machine (and may include packets destined for a
+ * unicast or multicast link-layer address we are not subscribing to).
+ * These are the same definitions implemented by pcap_setdirection().
+ * Capturing only unicast traffic destined for this host is probably
+ * better accomplished using a higher-layer filter.
  */
 struct block *
 gen_inbound(dir)
@@ -7513,23 +7521,11 @@ gen_inbound(dir)
                break;
 
        case DLT_LINUX_SLL:
-               if (dir) {
-                       /*
-                        * Match packets sent by this machine.
-                        */
-                       b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
-               } else {
-                       /*
-                        * Match packets sent to this machine.
-                        * (No broadcast or multicast packets, or
-                        * packets sent to some other machine and
-                        * received promiscuously.)
-                        *
-                        * XXX - packets sent to other machines probably
-                        * shouldn't be matched, but what about broadcast
-                        * or multicast packets we received?
-                        */
-                       b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
+               /* match outgoing packets */
+               b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
+               if (!dir) {
+                       /* to filter on inbound traffic, invert the match */
+                       gen_not(b0);
                }
                break;
 
@@ -7585,10 +7581,20 @@ gen_inbound(dir)
                break;
 
        default:
+#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+               /* match outgoing packets */
+               b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
+                            PACKET_OUTGOING);
+               if (!dir) {
+                       /* to filter on inbound traffic, invert the match */
+                       gen_not(b0);
+               }
+#else /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
                bpf_error("inbound/outbound not supported on linktype %d",
                    linktype);
                b0 = NULL;
                /* NOTREACHED */
+#endif /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
        }
        return (b0);
 }
index d4f50b7d16e323df0e8afc438eb7a2f37482ece8..c722badf5704b45021ac65c915ba3f164345a3aa 100644 (file)
@@ -5403,13 +5403,19 @@ fix_offset(struct bpf_insn *p)
                 * header.
                 */
                p->k -= SLL_HDR_LEN;
+       } else if (p->k == 0) {
+               /*
+                * It's the packet type field; map it to the special magic
+                * kernel offset for that field.
+                */
+               p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
        } else if (p->k == 14) {
                /*
                 * It's the protocol field; map it to the special magic
                 * kernel offset for that field.
                 */
                p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
-       } else {
+       } else if ((bpf_int32)(p->k) > 0) {
                /*
                 * It's within the header, but it's not one of those
                 * fields; we can't do that in the kernel, so punt