fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcap/+/42845?usp=email )
Change subject: client: honor IPv4 header length in GPRS filter ......................................................................
client: honor IPv4 header length in GPRS filter
The GPRS-NS/BSSGP filter assumed a fixed 20-byte IPv4 header (IP_LEN) when locating the UDP header and payload. When the captured packet carries IPv4 options (ip_hl > 5), udp_data/payload_data pointed into the middle of the headers and check_gprs() parsed garbage, classifying packets incorrectly.
Use the actual header length from ip_hl, reject malformed headers (ip_hl < 5), and re-validate that the larger headers fit within the captured length before computing the payload.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Change-Id: Iac1fa9cc2a3c06cbe19c3e7799a0b335f2e3dda9 --- M src/osmo_client_core.c 1 file changed, 13 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-pcap refs/changes/45/42845/1
diff --git a/src/osmo_client_core.c b/src/osmo_client_core.c index dbc2588..61e7cc0 100644 --- a/src/osmo_client_core.c +++ b/src/osmo_client_core.c @@ -108,6 +108,7 @@ { int ll_type; int offset; + size_t ip_hdr_len; struct ip *ip_hdr; const u_char *ip_data; const u_char *udp_data; @@ -145,9 +146,19 @@ if (ip_hdr->ip_p != 17) return 1;
- udp_data = ip_data + IP_LEN; + /* Honour the actual IPv4 header length (ip_hl), which may be larger + * than IP_LEN when IP options are present. */ + ip_hdr_len = ip_hdr->ip_hl * 4; + if (ip_hdr_len < IP_LEN) + return 1; /* malformed IPv4 header */ + + /* Re-check that the (possibly larger) headers fit within the capture */ + if (offset + ip_hdr_len + UDP_LEN + NS_LEN > hdr->caplen) + return 1; + + udp_data = ip_data + ip_hdr_len; payload_data = udp_data + UDP_LEN; - payload_len = hdr->caplen - offset - IP_LEN - UDP_LEN; + payload_len = hdr->caplen - offset - ip_hdr_len - UDP_LEN;
return check_gprs(payload_data, payload_len); }