From: Claudio Jeker Subject: Re: libpcap: teach gencode how to match ipv6 and ipv4 packets for DLT_RAW To: David Gwynne Cc: tech@openbsd.org Date: Thu, 5 Jun 2025 08:55:38 +0200 On Thu, Jun 05, 2025 at 04:43:51PM +1000, David Gwynne wrote: > On Thu, Jun 05, 2025 at 08:25:03AM +0200, Claudio Jeker wrote: > > On Thu, Jun 05, 2025 at 04:00:06PM +1000, David Gwynne wrote: > > > 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; > > > > Shouldn't this be a return? > > yep. > > > > + /* 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; > > > > I trust you that this is producing the right bpf commands. It kind of > > makes sense to me. > > i shouldn't be using indirect loads here. > > 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 06:41:41 -0000 > @@ -768,9 +768,11 @@ init_linktype(int type) > off_nl = 12; > return; > > - case DLT_USBPCAP: > - /* FALLTHROUGH */ > case DLT_RAW: > + off_linktype = 0; > + off_nl = 0; > + return; > + case DLT_USBPCAP: > off_linktype = -1; > off_nl = 0; > return; > @@ -910,6 +912,37 @@ gen_linktype(int proto) > return (gen_cmp(0, BPF_W, (bpf_int32)v)); > break; > } > + case DLT_RAW: { > + struct slist *s0, *s1; > + int ipv; > + > + switch (proto) { > + case ETHERTYPE_IP: > + ipv = 4; > + break; > + case ETHERTYPE_IPV6: > + ipv = 6; > + break; > + default: > + return gen_false(); > + } > + > + /* A = p[X+off_linktype] */ > + s0 = new_stmt(BPF_LD|BPF_ABS|BPF_B); > + 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 = ipv; > + > + return (b0); > + } > + > case DLT_PFLOG: > if (proto == ETHERTYPE_IP) > return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B, > OK claudio@ -- :wq Claudio