From: David Gwynne Subject: libpcap: teach gencode how to match ipv6 and ipv4 packets for DLT_RAW To: tech@openbsd.org Date: Thu, 5 Jun 2025 16:00:06 +1000 this allows you filter on ip and ip6 packets like you do on other DLTs by looking at the first nibble. before this libpcap would just say "yes" if you asked for just ip or ip6: xdlg@oak ~$ tcpdump -r erspan.raw.pcap -d ip (000) ret #116 xdlg@oak ~$ tcpdump -r erspan.raw.pcap -d ip6 (000) ret #116 or worse: xdlg@oak ~$ tcpdump -r erspan.raw.pcap -d mpls (000) ldh [-1] (001) jeq #0x8847 jt 2 jf 3 (002) ret #116 (003) ret #0 xdlg@oak ~$ tcpdump -r erspan.raw.pcap -d arp (000) ldh [-1] (001) jeq #0x806 jt 2 jf 3 (002) ret #116 (003) ret #0 with this diff it can match on the packet: xdlg@pitcher ~$ tcpdump -r erspan.raw.pcap -d ip (000) ldb [x + 0] (001) rsh #4 (002) jeq #0x4 jt 3 jf 4 (003) ret #116 (004) ret #0 xdlg@pitcher ~$ tcpdump -r erspan.raw.pcap -d ip6 (000) ldb [x + 0] (001) rsh #4 (002) jeq #0x6 jt 3 jf 4 (003) ret #116 (004) ret #0 we also get this: xdlg@pitcher ~$ tcpdump -r erspan.raw.pcap -d arp tcpdump: expression rejects all packets ok? Index: gencode.c =================================================================== RCS file: /cvs/src/lib/libpcap/gencode.c,v diff -u -p -r1.67 gencode.c --- gencode.c 15 Sep 2024 07:14:58 -0000 1.67 +++ gencode.c 5 Jun 2025 05:51:30 -0000 @@ -768,12 +768,14 @@ init_linktype(int type) off_nl = 12; return; - case DLT_USBPCAP: - /* FALLTHROUGH */ case DLT_RAW: - off_linktype = -1; + off_linktype = 0; off_nl = 0; return; + case DLT_USBPCAP: + off_linktype = -1; + off_nl = 0; + break; } bpf_error("unknown data link type 0x%x", linktype); /* NOTREACHED */ @@ -910,6 +912,38 @@ gen_linktype(int proto) return (gen_cmp(0, BPF_W, (bpf_int32)v)); break; } + case DLT_RAW: { + struct slist *s0, *s1; + struct block *b; + int v; + + switch (proto) { + case ETHERTYPE_IP: + v = 4; + break; + case ETHERTYPE_IPV6: + v = 6; + break; + default: + return gen_false(); + } + + /* A = p[X+off_linktype] */ + s0 = new_stmt(BPF_LD|BPF_B|BPF_IND); + s0->s.k = off_linktype; + + /* A = A >> 4 */ + s1 = new_stmt(BPF_ALU|BPF_RSH|BPF_K); + s1->s.k = 4; + sappend(s0, s1); + + b0 = new_block(JMP(BPF_JEQ)); + b0->stmts = s0; + b0->s.k = v; + + return (b0); + } + case DLT_PFLOG: if (proto == ETHERTYPE_IP) return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,