diff --git a/dll/windivert.c b/dll/windivert.c index 5ed8b4a..c647bdc 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -204,6 +204,7 @@ static BOOL WinDivertParseFilter(FILTER_TOKEN *tokens, UINT16 *tp, windivert_ioctl_filter_t filter, UINT16 *fp, FILTER_TOKEN_KIND op); static void WinDivertFilterUpdate(windivert_ioctl_filter_t filter, UINT16 s, UINT16 e, UINT16 success, UINT16 failure); +static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len); static void WinDivertInitPseudoHeader(PWINDIVERT_IPHDR ip_header, PWINDIVERT_PSEUDOHDR pseudo_header, UINT8 protocol, UINT len); static void WinDivertInitPseudoHeaderV6(PWINDIVERT_IPV6HDR ipv6_header, @@ -1402,6 +1403,53 @@ static void WinDivertFilterUpdate(windivert_ioctl_filter_t filter, UINT16 s, /* WINDIVERT HELPER IMPLEMENTATION */ /****************************************************************************/ +/* + * Skip well-known IPv6 extension headers. + */ +static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len) +{ + UINT hdrlen; + + while (TRUE) + { + if (*len <= 2) + { + return IPPROTO_NONE; + } + + hdrlen = (UINT)*(*header + 1); + switch (proto) + { + case IPPROTO_FRAGMENT: + hdrlen = 8; + break; + case IPPROTO_AH: + hdrlen += 2; + hdrlen *= 4; + break; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: + hdrlen++; + hdrlen *= 8; + break; + case IPPROTO_NONE: + return proto; + default: + return proto; + } + + if (hdrlen >= *len) + { + return IPPROTO_NONE; + } + + proto = **header; + *header += hdrlen; + *len -= hdrlen; + } +} + /* * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet. */ @@ -1460,6 +1508,8 @@ extern BOOL WinDivertHelperParsePacket(PVOID pPacket, UINT packetLen, trans_proto = ipv6_header->NextHdr; data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR)); data_len -= sizeof(WINDIVERT_IPV6HDR); + trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data, + &data_len); break; default: ip_header = NULL; diff --git a/sys/windivert.c b/sys/windivert.c index 99bc35b..906e407 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -2543,7 +2543,6 @@ static UINT16 windivert_checksum(const void *pseudo_header, */ static UINT8 windivert_skip_headers(UINT8 proto, UINT8 **header, size_t *len) { - UINT8 *hdrlen_ptr; size_t hdrlen; while (TRUE) @@ -2669,7 +2668,7 @@ static void windivert_update_checksums(void *header, size_t len, // Skip extension headers: proto = windivert_skip_headers(ipv6_header->NextHdr, - &(UINT8 *)trans_header, &trans_len); + (UINT8 **)&trans_header, &trans_len); break; default: