the-tcpdump-group / libpcap

the LIBpcap interface to various kernel packet capture mechanism
https://www.tcpdump.org/
Other
2.72k stars 855 forks source link

BPF code for PPP assumes HDLC headers and thus does not support Address-and-Control-Field-Compression #321

Open krazyace78 opened 11 years ago

krazyace78 commented 11 years ago

I have a PCAP with packets using PPP in HDLC framing between two nodes.

Node 1 in the session sends frames that contain the full Address and Control Field with PPP in HDLC framing (0xFF030021).

Node 2 in the session uses Address-and-Control-Field-Compression (see section 3.2 of RFC 1549) and sends frames that contain a single byte used for the PPP header (0x21).

I then write a BPF rule to hit on IP address pairs with IP protocol and TCP ports (ip host 192.168.20.10 and ip host 192.168.20.11 and ip proto 6 and tcp port 29581 and tcp port 80) and only the packets that contain the full PPP with HDLC framing headers are returned when I call pcap_next_ex().

If I manually modify one of the packets with the compressed header by adding the full PPP in HDLC framing header (0x21 --> 0xFF030021) and I adjust the packet header incl_len and orig_len fields accordingly, the modified packet is returned by the pcap_next_ex() call.

This issue occurs both with libpcap in Linux and winpcap in Windows.

guyharris commented 11 years ago

Perhaps libpcap should, for PPP DLT_ values that might or might not include the HDLC-like headers, generate BPF code that checks for the FF 03 and skips it if it's present, rather than assuming it's always present.

krazyace78 commented 11 years ago

I forgot to mention that the PCAP's I have use PPP Protocol Field Compression (PFC) enabled (section 6.5 of RFC 1661) which allows for one byte and two byte PPP headers. When I encountered the issue above, I checked it against both 0x0021 and 0x21 and I observed the same issue with Address-and-Control-Field-Compression.

guyharris commented 11 years ago

The generated BPF code doesn't handle protocol field compression either:

$ ./filtertest PPP ip
(000) ldh      [2]
(001) jeq      #0x21            jt 2    jf 3
(002) ret      #68
(003) ret      #0

(i.e., it's assuming a 2-byte protocol field).