From 9dd14dfc7c709ef43d2d95952a3530b3a0d4b57f Mon Sep 17 00:00:00 2001 From: bol-van Date: Wed, 14 Jan 2026 19:13:46 +0300 Subject: [PATCH] nfqws2: check ipv6 plen --- nfq2/darkmagic.c | 57 ++++++++++-------------------------------------- nfq2/darkmagic.h | 2 +- nfq2/lua.c | 3 +++ 3 files changed, 15 insertions(+), 47 deletions(-) diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index 5727641..612be1f 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -341,18 +341,25 @@ bool proto_check_ipv6(const uint8_t *data, size_t len) { return len >= sizeof(struct ip6_hdr) && (data[0] & 0xF0) == 0x60; } +bool proto_check_ipv6_payload(const uint8_t *data, size_t len) +{ + return len >= (ntohs(((struct ip6_hdr*)data)->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr)); +} // move to transport protocol // proto_type = 0 => error void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, const uint8_t **last_header_type) { size_t hdrlen; uint8_t HeaderType; + uint16_t plen; if (proto_type) *proto_type = 0; // put error in advance HeaderType = (*data)[6]; // NextHeader field if (last_header_type) *last_header_type = (*data)+6; + plen = ntohs(((struct ip6_hdr*)data)->ip6_ctlun.ip6_un1.ip6_un1_plen); *data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header + if (plen < *len) *len = plen; while (*len) // need at least one byte for NextHeader field { switch (HeaderType) @@ -391,60 +398,18 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, con // we have garbage } -bool proto_set_last_ip6_proto(struct ip6_hdr *ip6, size_t len, uint8_t proto) -{ - size_t hdrlen; - uint8_t HeaderType, *pproto, *data; - - if (lenip6_ctlun.ip6_un1.ip6_un1_nxt; - data = (uint8_t*)(ip6+1); - len -= sizeof(struct ip6_hdr); - while (len) // need at least one byte for NextHeader field - { - switch (*pproto) - { - case IPPROTO_HOPOPTS: - case IPPROTO_ROUTING: - case IPPROTO_DSTOPTS: - case IPPROTO_MH: // mobility header - case IPPROTO_HIP: // Host Identity Protocol Version v2 - case IPPROTO_SHIM6: - if (len < 2) return false; // error - hdrlen = 8 + (data[1] << 3); - break; - case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved - hdrlen = 8; - break; - case IPPROTO_AH: - // special case. length in ah header is in 32-bit words minus 2 - if (len < 2) return false; // error - hdrlen = 8 + (data[1] << 2); - break; - default: - // we found some meaningful payload. it can be tcp, udp, icmp or some another exotic shit - *pproto = proto; - return true; - } - if (len < hdrlen) return false; // error - pproto = data; - len -= hdrlen; data += hdrlen; - } - *pproto = proto; - return true; -} - uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto) { size_t hdrlen; uint8_t HeaderType, last_proto, *data; + uint16_t plen; if (lenip6_ctlun.ip6_un1.ip6_un1_plen); last_proto = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt; data = (uint8_t*)(ip6+1); len -= sizeof(struct ip6_hdr); + if (plen < len) len = plen; while (len) // need at least one byte for NextHeader field { if (last_proto==proto) return data; // found @@ -497,7 +462,7 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis) proto_skip_ipv4(&data, &len); dis->len_l3 = data-p; } - else if (proto_check_ipv6(data, len)) + else if (proto_check_ipv6(data, len) && proto_check_ipv6_payload(data, len)) { dis->ip6 = (const struct ip6_hdr *) data; p = data; diff --git a/nfq2/darkmagic.h b/nfq2/darkmagic.h index 3f1bdb8..9f0f276 100644 --- a/nfq2/darkmagic.h +++ b/nfq2/darkmagic.h @@ -135,8 +135,8 @@ void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr); bool proto_check_ipv4(const uint8_t *data, size_t len); void proto_skip_ipv4(const uint8_t **data, size_t *len); bool proto_check_ipv6(const uint8_t *data, size_t len); +bool proto_check_ipv6_payload(const uint8_t *data, size_t len); void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, const uint8_t **last_header_type); -bool proto_set_last_ip6_proto(struct ip6_hdr *ip6, size_t len, uint8_t proto); uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto); bool proto_check_tcp(const uint8_t *data, size_t len); void proto_skip_tcp(const uint8_t **data, size_t *len); diff --git a/nfq2/lua.c b/nfq2/lua.c index 58a2f58..1cca74b 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -1296,6 +1296,7 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len) // assume ipv6 packet structure was already checked for validity size_t hdrlen; uint8_t HeaderType, *data; + uint16_t plen; lua_Integer idx = 1; lua_pushliteral(L, "exthdr"); @@ -1305,6 +1306,8 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len) HeaderType = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt; data=(uint8_t*)(ip6+1); len-=sizeof(struct ip6_hdr); + plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); + if (plen < len) len = plen; while (len > 0) // need at least one byte for NextHeader field { switch (HeaderType)