Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
Re: libpcap: teach gencode how to match ipv6 and ipv4 packets for DLT_RAW
To:
David Gwynne <david@gwynne.id.au>
Cc:
tech@openbsd.org
Date:
Thu, 5 Jun 2025 08:25:03 +0200

Download raw body.

Thread
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?

>  	}
>  	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;

I trust you that this is producing the right bpf commands. It kind of
makes sense to me.

> +
> +		return (b0);
> +	}
> +
>  	case DLT_PFLOG:
>  		if (proto == ETHERTYPE_IP)
>  			return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
> 

-- 
:wq Claudio