diff --git a/dll/windivert_hash.c b/dll/windivert_hash.c index df85523..2f6b999 100644 --- a/dll/windivert_hash.c +++ b/dll/windivert_hash.c @@ -105,11 +105,16 @@ static UINT64 WinDivertXXH64Avalanche(UINT64 h64) /* * WinDivert packet hash function. */ -static UINT64 WinDivertHashPacket(UINT64 seed, - const WINDIVERT_ETHHDR *eth_header, const WINDIVERT_IPHDR *ip_header, - const WINDIVERT_IPV6HDR *ipv6_header, const WINDIVERT_ICMPHDR *icmp_header, +static UINT64 WinDivertHashPacket( + UINT64 seed, + const WINDIVERT_ETHHDR *eth_header, + const WINDIVERT_ARPHDR *arp_header, + const WINDIVERT_IPHDR *ip_header, + const WINDIVERT_IPV6HDR *ipv6_header, + const WINDIVERT_ICMPHDR *icmp_header, const WINDIVERT_ICMPV6HDR *icmpv6_header, - const WINDIVERT_TCPHDR *tcp_header, const WINDIVERT_UDPHDR *udp_header) + const WINDIVERT_TCPHDR *tcp_header, + const WINDIVERT_UDPHDR *udp_header) { UINT64 h64, v1, v2, v3, v4, v[4]; const UINT64 *data64; @@ -207,6 +212,11 @@ static UINT64 WinDivertHashPacket(UINT64 seed, v1 = WinDivertXXH64Round(v1, data64[0] & 0xFFFFFFFFFFFFull); data64 = (const UINT64 *)eth_header->SrcAddr; v2 = WinDivertXXH64Round(v2, data64[0]); + if (arp_header != NULL) + { + data64 = (const UINT64 *)arp_header; + v3 = WinDivertXXH64Round(v3, data64[0]); + } } h64 = WINDIVERT_ROTL64(v1, 1) + WINDIVERT_ROTL64(v2, 7) + diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 9261fd8..e6b3449 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -49,6 +49,9 @@ #define IPPROTO_ICMPV6 58 #define IPPROTO_NONE 59 #define IPPROTO_DSTOPTS 60 +#define ETHERTYPE_ARP 0x0806 +#define ETHERTYPE_IP 0x0800 +#define ETHERTYPE_IPV6 0x86dd /* * Filter tokens. @@ -146,6 +149,12 @@ typedef enum TOKEN_ETH_DST_ADDR, TOKEN_ETH_SRC_ADDR, TOKEN_ETH_TYPE, + TOKEN_ARP, + TOKEN_ARP_HARDWARE, + TOKEN_ARP_PROTOCOL, + TOKEN_ARP_HARD_LENGTH, + TOKEN_ARP_PROT_LENGTH, + TOKEN_ARP_OPCODE, TOKEN_LAYER_FLOW, TOKEN_LAYER_SOCKET, TOKEN_LAYER_NETWORK, @@ -168,6 +177,9 @@ typedef enum TOKEN_MACRO_UDP, TOKEN_MACRO_ICMP, TOKEN_MACRO_ICMPV6, + TOKEN_MACRO_ARP, + TOKEN_MACRO_IP, + TOKEN_MACRO_IPV6, TOKEN_OPEN, TOKEN_CLOSE, TOKEN_SQUARE_OPEN, @@ -515,12 +527,20 @@ static PTOKEN_INFO WinDivertTokenLookup(PTOKEN_INFO token_info, /* * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet. */ -BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen, - WINDIVERT_LAYER layer, PWINDIVERT_ETHHDR *ppEthHeader, - PWINDIVERT_IPHDR *ppIPHeader, PWINDIVERT_IPV6HDR *ppIPv6Header, - UINT8 *pProtocol, PWINDIVERT_ICMPHDR *ppICMPHeader, - PWINDIVERT_ICMPV6HDR *ppICMPv6Header, PWINDIVERT_TCPHDR *ppTCPHeader, - PWINDIVERT_UDPHDR *ppUDPHeader, PVOID *ppData, UINT *pDataLen) +BOOL WinDivertHelperParsePacket( + const VOID *pPacket, + UINT packetLen, + WINDIVERT_LAYER layer, + PWINDIVERT_ETHHDR *ppEthHeader, + PWINDIVERT_ARPHDR *ppArpHeader, + PWINDIVERT_IPHDR *ppIPHeader, + PWINDIVERT_IPV6HDR *ppIPv6Header, + UINT8 *pProtocol, + PWINDIVERT_ICMPHDR *ppICMPHeader, + PWINDIVERT_ICMPV6HDR *ppICMPv6Header, + PWINDIVERT_TCPHDR *ppTCPHeader, + PWINDIVERT_UDPHDR *ppUDPHeader, + PVOID *ppData, UINT *pDataLen) { WINDIVERT_PACKET info; if (!WinDivertHelperParsePacketEx(pPacket, packetLen, layer, &info)) @@ -540,6 +560,10 @@ BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen, { *ppEthHeader = info.EthHeader; } + if (ppArpHeader != NULL) + { + *ppArpHeader = info.ArpHeader; + } if (ppIPHeader != NULL) { *ppIPHeader = info.IPHeader; @@ -659,6 +683,15 @@ static BOOL WinDivertExpandMacro(KIND kind, WINDIVERT_LAYER layer, UINT32 *val) case TOKEN_MACRO_ICMPV6: *val = IPPROTO_ICMPV6; return TRUE; + case TOKEN_MACRO_ARP: + *val = ETHERTYPE_ARP; + return (layer == WINDIVERT_LAYER_ETHERNET); + case TOKEN_MACRO_IP: + *val = ETHERTYPE_IP; + return (layer == WINDIVERT_LAYER_ETHERNET); + case TOKEN_MACRO_IPV6: + *val = ETHERTYPE_IPV6; + return (layer == WINDIVERT_LAYER_ETHERNET); default: return FALSE; } @@ -673,6 +706,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, static const TOKEN_INFO token_info[] = { {"ACCEPT", TOKEN_EVENT_ACCEPT }, + {"ARP", TOKEN_MACRO_ARP }, {"BIND", TOKEN_EVENT_BIND }, {"CLOSE", TOKEN_EVENT_CLOSE }, {"CONNECT", TOKEN_EVENT_CONNECT }, @@ -684,6 +718,8 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, {"FLOW", TOKEN_LAYER_FLOW }, {"ICMP", TOKEN_MACRO_ICMP }, {"ICMPV6", TOKEN_MACRO_ICMPV6 }, + {"IP", TOKEN_MACRO_IP }, + {"IPV6", TOKEN_MACRO_IPV6 }, {"LISTEN", TOKEN_EVENT_LISTEN }, {"NETWORK", TOKEN_LAYER_NETWORK }, {"NETWORK_FORWARD", TOKEN_LAYER_NETWORK_FORWARD}, @@ -695,6 +731,12 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, {"TRUE", TOKEN_MACRO_TRUE }, {"UDP", TOKEN_MACRO_UDP }, {"and", TOKEN_AND }, + {"arp", TOKEN_ARP }, + {"arp.HardLength", TOKEN_ARP_HARD_LENGTH }, + {"arp.Hardware", TOKEN_ARP_HARDWARE }, + {"arp.ProtLength", TOKEN_ARP_PROT_LENGTH }, + {"arp.Protocol", TOKEN_ARP_PROTOCOL }, + {"arp.Opcode", TOKEN_ARP_OPCODE }, {"b", TOKEN_BYTES }, {"endpointId", TOKEN_ENDPOINT_ID }, {"eth.DstAddr", TOKEN_ETH_DST_ADDR }, @@ -1114,6 +1156,12 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error) {{{0}}, TOKEN_ETH_DST_ADDR}, {{{0}}, TOKEN_ETH_SRC_ADDR}, {{{0}}, TOKEN_ETH_TYPE}, + {{{0}}, TOKEN_ARP}, + {{{0}}, TOKEN_ARP_HARDWARE}, + {{{0}}, TOKEN_ARP_PROTOCOL}, + {{{0}}, TOKEN_ARP_HARD_LENGTH}, + {{{0}}, TOKEN_ARP_PROT_LENGTH}, + {{{0}}, TOKEN_ARP_OPCODE}, }; // Binary search: @@ -1268,6 +1316,7 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) case TOKEN_SUB_IF_IDX: case TOKEN_LOOPBACK: case TOKEN_IMPOSTOR: + case TOKEN_ARP: case TOKEN_IP: case TOKEN_IPV6: case TOKEN_ICMP: @@ -1287,6 +1336,11 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) case TOKEN_ETH_DST_ADDR: case TOKEN_ETH_SRC_ADDR: case TOKEN_ETH_TYPE: + case TOKEN_ARP_HARDWARE: + case TOKEN_ARP_PROTOCOL: + case TOKEN_ARP_HARD_LENGTH: + case TOKEN_ARP_PROT_LENGTH: + case TOKEN_ARP_OPCODE: case TOKEN_IP_HDR_LENGTH: case TOKEN_IP_TOS: case TOKEN_IP_LENGTH: @@ -1617,6 +1671,7 @@ static void WinDivertSimplifyTest(PEXPR test) case TOKEN_INBOUND: case TOKEN_OUTBOUND: case TOKEN_FRAGMENT: + case TOKEN_ARP: case TOKEN_IP: case TOKEN_IPV6: case TOKEN_ICMP: @@ -1633,6 +1688,11 @@ static void WinDivertSimplifyTest(PEXPR test) type = TOKEN_TCP; lb[0] = 0; ub[0] = 0x0F; break; + case TOKEN_ARP_HARD_LENGTH: + case TOKEN_ARP_PROT_LENGTH: + type = TOKEN_ARP; + lb[0] = 0; ub[0] = 0xFF; + break; case TOKEN_IP_TTL: case TOKEN_IP_PROTOCOL: type = TOKEN_IP; @@ -1674,6 +1734,12 @@ static void WinDivertSimplifyTest(PEXPR test) case TOKEN_ETH_TYPE: lb[0] = 0; ub[0] = 0xFFFF; break; + case TOKEN_ARP_HARDWARE: + case TOKEN_ARP_PROTOCOL: + case TOKEN_ARP_OPCODE: + type = TOKEN_ARP; + lb[0] = 0; ub[0] = 0xFFFF; + break; case TOKEN_IP_TOS: case TOKEN_IP_LENGTH: case TOKEN_IP_ID: @@ -1984,6 +2050,8 @@ static UINT32 WinDivertKindToField(KIND kind) return WINDIVERT_FILTER_FIELD_LAYER; case TOKEN_PRIORITY: return WINDIVERT_FILTER_FIELD_PRIORITY; + case TOKEN_ARP: + return WINDIVERT_FILTER_FIELD_ARP; case TOKEN_IP: return WINDIVERT_FILTER_FIELD_IP; case TOKEN_IPV6: @@ -2002,6 +2070,16 @@ static UINT32 WinDivertKindToField(KIND kind) return WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR; case TOKEN_ETH_TYPE: return WINDIVERT_FILTER_FIELD_ETH_TYPE; + case TOKEN_ARP_HARDWARE: + return WINDIVERT_FILTER_FIELD_ARP_HARDWARE; + case TOKEN_ARP_PROTOCOL: + return WINDIVERT_FILTER_FIELD_ARP_PROTOCOL; + case TOKEN_ARP_HARD_LENGTH: + return WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH; + case TOKEN_ARP_PROT_LENGTH: + return WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH; + case TOKEN_ARP_OPCODE: + return WINDIVERT_FILTER_FIELD_ARP_OPCODE; case TOKEN_IP_HDR_LENGTH: return WINDIVERT_FILTER_FIELD_IP_HDRLENGTH; case TOKEN_IP_TOS: @@ -2613,6 +2691,7 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, DWORD error; WINDIVERT_PACKET info; PWINDIVERT_ETHHDR eth_header = NULL; + PWINDIVERT_ARPHDR arp_header = NULL; PWINDIVERT_IPHDR ip_header = NULL; PWINDIVERT_IPV6HDR ipv6_header = NULL; PWINDIVERT_ICMPHDR icmp_header = NULL; @@ -2655,6 +2734,7 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, } protocol = info.Protocol; eth_header = info.EthHeader; + arp_header = info.ArpHeader; ip_header = info.IPHeader; ipv6_header = info.IPv6Header; icmp_header = info.ICMPHeader; @@ -2743,6 +2823,7 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, socket_data, reflect_data, eth_header, + arp_header, ip_header, ipv6_header, icmp_header, @@ -3140,6 +3221,8 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test) kind = TOKEN_IF_IDX; break; case WINDIVERT_FILTER_FIELD_SUBIFIDX: kind = TOKEN_SUB_IF_IDX; break; + case WINDIVERT_FILTER_FIELD_ARP: + kind = TOKEN_ARP; break; case WINDIVERT_FILTER_FIELD_IP: kind = TOKEN_IP; break; case WINDIVERT_FILTER_FIELD_IPV6: @@ -3158,6 +3241,16 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test) kind = TOKEN_ETH_SRC_ADDR; break; case WINDIVERT_FILTER_FIELD_ETH_TYPE: kind = TOKEN_ETH_TYPE; break; + case WINDIVERT_FILTER_FIELD_ARP_HARDWARE: + kind = TOKEN_ARP_HARDWARE; break; + case WINDIVERT_FILTER_FIELD_ARP_PROTOCOL: + kind = TOKEN_ARP_PROTOCOL; break; + case WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH: + kind = TOKEN_ARP_HARD_LENGTH; break; + case WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH: + kind = TOKEN_ARP_PROT_LENGTH; break; + case WINDIVERT_FILTER_FIELD_ARP_OPCODE: + kind = TOKEN_ARP_OPCODE; break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: kind = TOKEN_IP_HDR_LENGTH; break; case WINDIVERT_FILTER_FIELD_IP_TOS: @@ -3847,6 +3940,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case TOKEN_INBOUND: case TOKEN_OUTBOUND: case TOKEN_FRAGMENT: + case TOKEN_ARP: case TOKEN_IP: case TOKEN_IPV6: case TOKEN_ICMP: @@ -3928,6 +4022,9 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case TOKEN_ICMP_CHECKSUM: case TOKEN_ICMPV6_CHECKSUM: case TOKEN_ETH_TYPE: + case TOKEN_ARP_HARDWARE: + case TOKEN_ARP_PROTOCOL: + case TOKEN_ARP_OPCODE: is_hex = TRUE; break; default: @@ -4186,6 +4283,8 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertPutString(stream, "ifIdx"); return; case TOKEN_SUB_IF_IDX: WinDivertPutString(stream, "subIfIdx"); return; + case TOKEN_ARP: + WinDivertPutString(stream, "arp"); return; case TOKEN_IP: WinDivertPutString(stream, "ip"); return; case TOKEN_IPV6: @@ -4204,6 +4303,16 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertPutString(stream, "eth.SrcAddr"); return; case TOKEN_ETH_TYPE: WinDivertPutString(stream, "eth.Type"); return; + case TOKEN_ARP_HARDWARE: + WinDivertPutString(stream, "arp.Hardware"); return; + case TOKEN_ARP_PROTOCOL: + WinDivertPutString(stream, "arp.Protocol"); return; + case TOKEN_ARP_HARD_LENGTH: + WinDivertPutString(stream, "arp.HardLength"); return; + case TOKEN_ARP_PROT_LENGTH: + WinDivertPutString(stream, "arp.ProtLength"); return; + case TOKEN_ARP_OPCODE: + WinDivertPutString(stream, "arp.Opcode"); return; case TOKEN_IP_HDR_LENGTH: WinDivertPutString(stream, "ip.HdrLength"); return; case TOKEN_IP_TOS: @@ -4458,6 +4567,7 @@ UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen, WINDIVERT_LAYER layer, UINT64 seed) { PWINDIVERT_ETHHDR eth_header = NULL; + PWINDIVERT_ARPHDR arp_header = NULL; PWINDIVERT_IPHDR ip_header = NULL; PWINDIVERT_IPV6HDR ipv6_header = NULL; PWINDIVERT_ICMPHDR icmp_header = NULL; @@ -4466,13 +4576,14 @@ UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen, PWINDIVERT_UDPHDR udp_header = NULL; if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, layer, - ð_header, &ip_header, &ipv6_header, NULL, &icmp_header, - &icmpv6_header, &tcp_header, &udp_header, NULL, NULL)) + ð_header, &arp_header, &ip_header, &ipv6_header, NULL, + &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, + NULL)) { return 0; } - return WinDivertHashPacket(seed, eth_header, ip_header, ipv6_header, - icmp_header, icmpv6_header, tcp_header, udp_header); + return WinDivertHashPacket(seed, eth_header, arp_header, ip_header, + ipv6_header, icmp_header, icmpv6_header, tcp_header, udp_header); } /* diff --git a/dll/windivert_shared.c b/dll/windivert_shared.c index f708d6a..577cfc9 100644 --- a/dll/windivert_shared.c +++ b/dll/windivert_shared.c @@ -1,6 +1,6 @@ /* * windivert_shared.c - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -68,6 +68,7 @@ #define ntohl48(x) BYTESWAP48(x) #define htonl48(x) BYTESWAP48(x) +#define ETHERTYPE_ARP 0x0806 #define ETHERTYPE_IP 0x0800 #define ETHERTYPE_IPV6 0x86DD @@ -188,6 +189,7 @@ typedef struct UINT32 Extended:1; UINT32 Reserved1:6; PWINDIVERT_ETHHDR EthHeader; + PWINDIVERT_ARPHDR ArpHeader; PWINDIVERT_IPHDR IPHeader; PWINDIVERT_IPV6HDR IPv6Header; PWINDIVERT_ICMPHDR ICMPHeader; @@ -393,6 +395,7 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen, WINDIVERT_LAYER layer, PWINDIVERT_PACKET pInfo) { PWINDIVERT_ETHHDR eth_header = NULL; + PWINDIVERT_ARPHDR arp_header = NULL; PWINDIVERT_IPHDR ip_header = NULL; PWINDIVERT_IPV6HDR ipv6_header = NULL; PWINDIVERT_ICMPHDR icmp_header = NULL; @@ -439,6 +442,16 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, goto WinDivertHelperParsePacketExit; } break; + case ETHERTYPE_ARP: + if (data_len < sizeof(WINDIVERT_ARPHDR)) + { + goto WinDivertHelperParsePacketExit; + } + arp_header = (PWINDIVERT_ARPHDR)data; + data = (PVOID)(arp_header + 1); + data_len -= sizeof(WINDIVERT_ARPHDR); + header_len += sizeof(WINDIVERT_ARPHDR); + goto WinDivertHelperParsePacketExit; default: goto WinDivertHelperParsePacketExit; } @@ -626,6 +639,7 @@ WinDivertHelperParsePacketExit: pInfo->Extended = (ip_total_len < ip_packet_len? 1: 0); pInfo->Reserved1 = 0; pInfo->EthHeader = eth_header; + pInfo->ArpHeader = arp_header; pInfo->IPHeader = ip_header; pInfo->IPv6Header = ipv6_header; pInfo->ICMPHeader = icmp_header; @@ -1042,6 +1056,12 @@ static BOOL WinDivertValidateField(WINDIVERT_LAYER layer, UINT32 field) LE_____, /* WINDIVERT_FILTER_FIELD_ETH_DST_ADDR */ LE_____, /* WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR */ LE_____, /* WINDIVERT_FILTER_FIELD_ETH_TYPE */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_HARDWARE */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_PROTOCOL */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_OPCODE */ }; if (field > WINDIVERT_FILTER_FIELD_MAX) @@ -1124,6 +1144,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( const WINDIVERT_DATA_SOCKET *socket_data, const WINDIVERT_DATA_REFLECT *reflect_data, const WINDIVERT_ETHHDR *eth_header, + const WINDIVERT_ARPHDR *arp_header, const WINDIVERT_IPHDR *ip_header, const WINDIVERT_IPV6HDR *ipv6_header, const WINDIVERT_ICMPHDR *icmp_header, @@ -1166,8 +1187,8 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( if (random64 == 0) { random64 = WinDivertHashPacket((UINT64)timestamp, - eth_header, ip_header, ipv6_header, icmp_header, - icmpv6_header, tcp_header, udp_header); + eth_header, arp_header, ip_header, ipv6_header, + icmp_header, icmpv6_header, tcp_header, udp_header); random64 |= 0xFF00000000000000ull; // Make non-zero. } break; @@ -1176,6 +1197,13 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( case WINDIVERT_FILTER_FIELD_ETH_TYPE: result = (eth_header != NULL); break; + case WINDIVERT_FILTER_FIELD_ARP_HARDWARE: + case WINDIVERT_FILTER_FIELD_ARP_PROTOCOL: + case WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH: + case WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH: + case WINDIVERT_FILTER_FIELD_ARP_OPCODE: + result = (arp_header != NULL); + break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: case WINDIVERT_FILTER_FIELD_IP_TOS: case WINDIVERT_FILTER_FIELD_IP_LENGTH: @@ -1358,6 +1386,9 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( case WINDIVERT_FILTER_FIELD_IMPOSTOR: val[0] = (UINT32)impostor; break; + case WINDIVERT_FILTER_FIELD_ARP: + val[0] = (UINT32)(arp_header != NULL); + break; case WINDIVERT_FILTER_FIELD_IP: val[0] = (UINT32)(ip_header != NULL); break; @@ -1446,21 +1477,36 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( break; case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR: case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR: - big = TRUE; - eth_addr = - (filter[ip].field == WINDIVERT_FILTER_FIELD_ETH_DST_ADDR? - eth_header->DstAddr: eth_header->SrcAddr); - val[0] = ((UINT32)eth_addr[2] << 24) | - ((UINT32)eth_addr[3] << 16) | - ((UINT32)eth_addr[4] << 8) | - ((UINT32)eth_addr[5]); - val[1] = ((UINT32)eth_addr[0] << 8) | - ((UINT32)eth_addr[1]); - val[2] = val[3] = 0; - break; + big = TRUE; + eth_addr = + (filter[ip].field == WINDIVERT_FILTER_FIELD_ETH_DST_ADDR? + eth_header->DstAddr: eth_header->SrcAddr); + val[0] = ((UINT32)eth_addr[2] << 24) | + ((UINT32)eth_addr[3] << 16) | + ((UINT32)eth_addr[4] << 8) | + ((UINT32)eth_addr[5]); + val[1] = ((UINT32)eth_addr[0] << 8) | + ((UINT32)eth_addr[1]); + val[2] = val[3] = 0; + break; case WINDIVERT_FILTER_FIELD_ETH_TYPE: - val[0] = (UINT32)ntohs(eth_header->Type); - break; + val[0] = (UINT32)ntohs(eth_header->Type); + break; + case WINDIVERT_FILTER_FIELD_ARP_HARDWARE: + val[0] = (UINT32)ntohs(arp_header->Hardware); + break; + case WINDIVERT_FILTER_FIELD_ARP_PROTOCOL: + val[0] = (UINT32)ntohs(arp_header->Protocol); + break; + case WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH: + val[0] = (UINT32)arp_header->HardLength; + break; + case WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH: + val[0] = (UINT32)arp_header->ProtLength; + break; + case WINDIVERT_FILTER_FIELD_ARP_OPCODE: + val[0] = (UINT32)ntohs(arp_header->Opcode); + break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: val[0] = (UINT32)ip_header->HdrLength; break; diff --git a/doc/windivert.html b/doc/windivert.html index 06ca083..a6abc55 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -35,27 +35,28 @@
  • 6. Helper Programming API
  • 7. Filter Language @@ -2084,7 +2085,31 @@ Ethernet frame header definition.

    -

    6.2 WINDIVERT_IPHDR

    +

    6.2 WINDIVERT_ARPHDR

    +
    +
    +typedef struct
    +{
    +    UINT16 Hardware;
    +    UINT16 Protocol;
    +    UINT8 HardLength;
    +    UINT8 ProtLength;
    +    UINT16 Opcode;
    +} WINDIVERT_ARPHDR, *PWINDIVERT_ARPHDR;
    +
    +
    +
    +

    +Fields
    +See here +for more information. +

    +Remarks
    +ARP header definition. +

    +
    + +

    6.3 WINDIVERT_IPHDR

     typedef struct
    @@ -2127,7 +2152,7 @@ definitions:
     
     
     
    -

    6.3 WINDIVERT_IPV6HDR

    +

    6.4 WINDIVERT_IPV6HDR

     typedef struct
    @@ -2163,7 +2188,7 @@ definitions:
     
     
     
    -

    6.4 WINDIVERT_ICMPHDR

    +

    6.5 WINDIVERT_ICMPHDR

     typedef struct
    @@ -2186,7 +2211,7 @@ ICMP header definition.
     

    -

    6.5 WINDIVERT_ICMPV6HDR

    +

    6.6 WINDIVERT_ICMPV6HDR

     typedef struct
    @@ -2209,7 +2234,7 @@ ICMPv6 header definition.
     

    -

    6.6 WINDIVERT_TCPHDR

    +

    6.7 WINDIVERT_TCPHDR

     typedef struct
    @@ -2244,7 +2269,7 @@ TCP header definition.
     

    -

    6.7 WINDIVERT_UDPHDR

    +

    6.8 WINDIVERT_UDPHDR

     typedef struct
    @@ -2267,7 +2292,7 @@ UDP header definition.
     

    -

    6.8 WinDivertHelperParsePacket

    +

    6.9 WinDivertHelperParsePacket

     BOOL WinDivertHelperParsePacket(
    @@ -2275,6 +2300,7 @@ BOOL WinDivertHelperParsePacket(
         __in UINT packetLen,
         __in WINDIVERT_LAYER layer,
         __out_opt PWINDIVERT_ETHHDR *ppEthHdr,
    +    __out_opt PWINDIVERT_ARPHDR *ppArpHdr,
         __out_opt PWINDIVERT_IPHDR *ppIpHdr,
         __out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
         __out_opt UINT8 *pProtocol,
    @@ -2294,6 +2320,7 @@ BOOL WinDivertHelperParsePacket(
     
  • packetLen: The total length of the packet(s) pPacket.
  • layer: The layer.
  • ppEthHdr: Output pointer to a WINDIVERT_ETHHDR.
  • +
  • ppArpHdr: Output pointer to an WINDIVERT_ARPHDR.
  • ppIpHdr: Output pointer to a WINDIVERT_IPHDR.
  • ppIpv6Hdr: Output pointer to a WINDIVERT_IPV6HDR.
  • pProtocol: Output transport protocol.
  • @@ -2333,7 +2360,7 @@ for parsing. This function will succeed if at least one header can be parsed.

    -

    6.9 WinDivertHelperHashPacket

    +

    6.10 WinDivertHelperHashPacket

     UINT64 WinDivertHelperHashPacket(
    @@ -2370,7 +2397,7 @@ The optional seed value is also incorporated into the hash.
     

    -

    6.10 WinDivertHelperParseMACAddress

    +

    6.11 WinDivertHelperParseMACAddress

     BOOL WinDivertHelperParseMACAddress(
    @@ -2400,7 +2427,7 @@ to convert the result into network-byte-order.
     

    -

    6.11 WinDivertHelperParseIPv4Address

    +

    6.12 WinDivertHelperParseIPv4Address

     BOOL WinDivertHelperParseIPv4Address(
    @@ -2429,7 +2456,7 @@ to convert the result into network-byte-order.
     

    -

    6.12 WinDivertHelperParseIPv6Address

    +

    6.13 WinDivertHelperParseIPv6Address

     BOOL WinDivertHelperParseIPv6Address(
    @@ -2459,10 +2486,10 @@ to convert the result into network-byte-order.
     

    -

    6.13 WinDivertHelperParseMacAddress

    +

    6.14 WinDivertHelperParseMACAddress

    -BOOL WinDivertHelperFormatMacAddress(
    +BOOL WinDivertHelperFormatMACAddress(
         __in const UINT8 *addr,
         __out char *buffer,
         __in UINT bufLen
    @@ -2472,7 +2499,7 @@ BOOL WinDivertHelperFormatMacAddress(
     

    Parameters

      -
    • addr: The Mac address in host-byte order.
    • +
    • addr: The MAC address in host-byte order.
    • buffer: The buffer to store the formatted string.
    • bufLen: The length of buffer.
    @@ -2482,11 +2509,11 @@ BOOL WinDivertHelperFormatMacAddress( Use GetLastError() to get the reason for the error.

    Remarks
    -Convert a Mac address into a string. +Convert a MAC address into a string.

    -

    6.14 WinDivertHelperParseIPv4Address

    +

    6.15 WinDivertHelperParseIPv4Address

     BOOL WinDivertHelperFormatIPv4Address(
    @@ -2513,7 +2540,7 @@ Convert an IPv4 address into a string.
     

    -

    6.15 WinDivertHelperParseIPv6Address

    +

    6.16 WinDivertHelperParseIPv6Address

     BOOL WinDivertHelperFormatIPv6Address(
    @@ -2540,7 +2567,7 @@ Convert an IPv6 address into a string.
     

    -

    6.16 WinDivertHelperCalcChecksums

    +

    6.17 WinDivertHelperCalcChecksums

     BOOL WinDivertHelperCalcChecksums(
    @@ -2600,7 +2627,7 @@ packet injection.
     

    -

    6.17 WinDivertHelperDecrementTTL

    +

    6.18 WinDivertHelperDecrementTTL

     BOOL WinDivertHelperDecrementTTL(
    @@ -2636,7 +2663,7 @@ This function updates the checksum field incrementally.
     

    -

    6.18 WinDivertHelperCompileFilter

    +

    6.19 WinDivertHelperCompileFilter

     BOOL WinDivertHelperCompileFilter(
    @@ -2687,7 +2714,7 @@ objects, and therefore do not need to be deallocated.
     

    -

    6.19 WinDivertHelperEvalFilter

    +

    6.20 WinDivertHelperEvalFilter

     BOOL WinDivertHelperEvalFilter(
    @@ -2733,7 +2760,7 @@ function.
     

    -

    6.20 WinDivertHelperFormatFilter

    +

    6.21 WinDivertHelperFormatFilter

     BOOL WinDivertHelperFormatFilter(
    @@ -2767,7 +2794,7 @@ returned by WinDivertRecv().
     

    -

    6.21 WinDivertHelperNtoh*

    +

    6.22 WinDivertHelperNtoh*

     UINT16 WinDivertHelperNtohs(
    @@ -2801,11 +2828,11 @@ void WinDivertHelperNtohIPv6Address(
     The output value in host byte order.
     

    Remarks
    -Converts a value/IPv6-address from network to host byte-order. +Converts a value/MAC-address/IPv6-address from network to host byte-order.

    -

    6.22 WinDivertHelperHton*

    +

    6.23 WinDivertHelperHton*

    + @@ -2957,6 +2985,7 @@ The possible fields are: + @@ -3030,6 +3059,9 @@ The possible macros are: + + + diff --git a/examples/netdump/netdump.c b/examples/netdump/netdump.c index 1118068..910e2c3 100644 --- a/examples/netdump/netdump.c +++ b/examples/netdump/netdump.c @@ -1,6 +1,6 @@ /* * netdump.c - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -68,6 +68,7 @@ int __cdecl main(int argc, char **argv) UINT packet_len; WINDIVERT_ADDRESS addr; PWINDIVERT_ETHHDR eth_header; + PWINDIVERT_ARPHDR arp_header; PWINDIVERT_IPHDR ip_header; PWINDIVERT_IPV6HDR ipv6_header; PWINDIVERT_ICMPHDR icmp_header; @@ -186,8 +187,9 @@ int __cdecl main(int argc, char **argv) // Print info about the matching packet. WinDivertHelperParsePacket(packet, packet_len, addr.Layer, - ð_header, &ip_header, &ipv6_header, NULL, &icmp_header, - &icmpv6_header, &tcp_header, &udp_header, NULL, NULL); + ð_header, &arp_header, &ip_header, &ipv6_header, NULL, + &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, + NULL); // Dump packet info: putchar('\n'); @@ -209,6 +211,16 @@ int __cdecl main(int argc, char **argv) FOREGROUND_GREEN | FOREGROUND_BLUE); printf("Ethernet [SrcAddr=%s DstAddr=%s Type=0x%.4X]\n", src_str, dst_str, ntohs(eth_header->Type)); + if (arp_header != NULL) + { + SetConsoleTextAttribute(console, + FOREGROUND_GREEN); + printf("ARP [Hardware=%u Protocol=%u HardLength=%u " + "ProtLength=%u Opcode=%u]\n", + ntohs(arp_header->Hardware), ntohs(arp_header->Protocol), + arp_header->HardLength, arp_header->ProtLength, + ntohs(arp_header->Opcode)); + } } else { diff --git a/examples/netfilter/netfilter.c b/examples/netfilter/netfilter.c index 23a0984..68487d8 100644 --- a/examples/netfilter/netfilter.c +++ b/examples/netfilter/netfilter.c @@ -1,6 +1,6 @@ /* * netfilter.c - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -202,7 +202,7 @@ int __cdecl main(int argc, char **argv) // Print info about the matching packet. WinDivertHelperParsePacket(packet, packet_len, recv_addr.Layer, NULL, - &ip_header, &ipv6_header, NULL, &icmp_header, &icmpv6_header, + NULL, &ip_header, &ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, &payload_len); if (ip_header == NULL && ipv6_header == NULL) { diff --git a/examples/streamdump/streamdump.c b/examples/streamdump/streamdump.c index b6c7493..eeb9b58 100644 --- a/examples/streamdump/streamdump.c +++ b/examples/streamdump/streamdump.c @@ -1,6 +1,6 @@ /* * streamdump.c - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -193,7 +193,7 @@ int __cdecl main(int argc, char **argv) continue; } - WinDivertHelperParsePacket(packet, packet_len, addr.Layer, NULL, + WinDivertHelperParsePacket(packet, packet_len, addr.Layer, NULL, NULL, &ip_header, NULL, NULL, NULL, NULL, &tcp_header, NULL, NULL, NULL); if (ip_header == NULL || tcp_header == NULL) { diff --git a/examples/webfilter/webfilter.c b/examples/webfilter/webfilter.c index d4723fe..0d56876 100644 --- a/examples/webfilter/webfilter.c +++ b/examples/webfilter/webfilter.c @@ -1,6 +1,6 @@ /* * webfilter.c - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -204,7 +204,7 @@ int __cdecl main(int argc, char **argv) continue; } - WinDivertHelperParsePacket(packet, packet_len, addr.Layer, NULL, + WinDivertHelperParsePacket(packet, packet_len, addr.Layer, NULL, NULL, &ip_header, NULL, NULL, NULL, NULL, &tcp_header, NULL, &payload, &payload_len); if (ip_header == NULL || tcp_header == NULL || payload == NULL || diff --git a/include/windivert.h b/include/windivert.h index e878adb..6a1360c 100644 --- a/include/windivert.h +++ b/include/windivert.h @@ -1,6 +1,6 @@ /* * windivert.h - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -350,7 +350,7 @@ WINDIVERTEXPORT BOOL WinDivertGetParam( #endif /* - * Ethernet/IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions. + * Ethernet/ARP/IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions. */ typedef struct { @@ -359,6 +359,15 @@ typedef struct UINT16 Type; } WINDIVERT_ETHHDR, *PWINDIVERT_ETHHDR; +typedef struct +{ + UINT16 Hardware; + UINT16 Protocol; + UINT8 HardLength; + UINT8 ProtLength; + UINT16 Opcode; +} WINDIVERT_ARPHDR, *PWINDIVERT_ARPHDR; + typedef struct { UINT8 HdrLength:4; @@ -526,6 +535,7 @@ WINDIVERTEXPORT BOOL WinDivertHelperParsePacket( __in UINT packetLen, __in WINDIVERT_LAYER layer, __out_opt PWINDIVERT_ETHHDR *ppEthHdr, + __out_opt PWINDIVERT_ARPHDR *ppArpHdr, __out_opt PWINDIVERT_IPHDR *ppIpHdr, __out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr, __out_opt UINT8 *pProtocol, diff --git a/include/windivert_device.h b/include/windivert_device.h index 55de7b3..87a6e83 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -1,6 +1,6 @@ /* * windivert_device.h - * (C) 2019, all rights reserved, + * (C) 2023, all rights reserved, * * This file is part of WinDivert. * @@ -153,8 +153,14 @@ #define WINDIVERT_FILTER_FIELD_ETH_DST_ADDR 86 #define WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR 87 #define WINDIVERT_FILTER_FIELD_ETH_TYPE 88 +#define WINDIVERT_FILTER_FIELD_ARP 89 +#define WINDIVERT_FILTER_FIELD_ARP_HARDWARE 90 +#define WINDIVERT_FILTER_FIELD_ARP_PROTOCOL 91 +#define WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH 92 +#define WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH 93 +#define WINDIVERT_FILTER_FIELD_ARP_OPCODE 94 #define WINDIVERT_FILTER_FIELD_MAX \ - WINDIVERT_FILTER_FIELD_ETH_TYPE + WINDIVERT_FILTER_FIELD_ARP_OPCODE #define WINDIVERT_FILTER_TEST_EQ 0 #define WINDIVERT_FILTER_TEST_NEQ 1 diff --git a/sys/windivert.c b/sys/windivert.c index b3acef5..be39102 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -489,8 +489,8 @@ static BOOL windivert_get_data(PNET_BUFFER buffer, UINT length, INT min, INT max, INT idx, PVOID data, UINT size); static BOOL windivert_parse_headers(PNET_BUFFER buffer, WINDIVERT_LAYER layer, BOOL ipv4, BOOL *fragment_ptr, PWINDIVERT_ETHHDR *eth_header_ptr, - PWINDIVERT_IPHDR *ip_header_ptr, PWINDIVERT_IPV6HDR *ipv6_header_ptr, - PWINDIVERT_ICMPHDR *icmp_header_ptr, + PWINDIVERT_ARPHDR *arp_header, PWINDIVERT_IPHDR *ip_header_ptr, + PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr, PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr, PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr, UINT *payload_len_ptr); @@ -1517,7 +1517,6 @@ static void windivert_driver_unload(void) static NTSTATUS windivert_install_provider() { FWPM_PROVIDER0 provider; - NTSTATUS status; RtlZeroMemory(&provider, sizeof(provider)); provider.providerKey = WINDIVERT_PROVIDER_GUID; @@ -5811,15 +5810,20 @@ static BOOL windivert_get_data(PNET_BUFFER buffer, UINT length, INT min, */ static WINDIVERT_INLINE BOOL windivert_parse_headers(PNET_BUFFER buffer, WINDIVERT_LAYER layer, BOOL ipv4, BOOL *fragment_ptr, - PWINDIVERT_ETHHDR *eth_header_ptr, PWINDIVERT_IPHDR *ip_header_ptr, - PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr, - PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr, - PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr, - UINT *payload_len_ptr) + PWINDIVERT_ETHHDR *eth_header_ptr, + PWINDIVERT_ARPHDR *arp_header_ptr, + PWINDIVERT_IPHDR *ip_header_ptr, + PWINDIVERT_IPV6HDR *ipv6_header_ptr, + PWINDIVERT_ICMPHDR *icmp_header_ptr, + PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, + PWINDIVERT_TCPHDR *tcp_header_ptr, + PWINDIVERT_UDPHDR *udp_header_ptr, + UINT8 *proto_ptr, UINT *header_len_ptr, UINT *payload_len_ptr) { UINT min_len, total_len, ip_header_len, header_len, packet_len, payload_len, advance_len; PWINDIVERT_ETHHDR eth_header = NULL; + PWINDIVERT_ARPHDR arp_header = NULL; PWINDIVERT_IPHDR ip_header = NULL; PWINDIVERT_IPV6HDR ipv6_header = NULL; PWINDIVERT_ICMPHDR icmp_header = NULL; @@ -5856,6 +5860,9 @@ static WINDIVERT_INLINE BOOL windivert_parse_headers(PNET_BUFFER buffer, min_len = 64 - sizeof(UINT32); min_len = (total_len < min_len? total_len: min_len); min_len -= sizeof(WINDIVERT_ETHHDR); + NdisAdvanceNetBufferDataStart(buffer, sizeof(WINDIVERT_ETHHDR), + FALSE, NULL); + advance_len += sizeof(WINDIVERT_ETHHDR); switch (RtlUshortByteSwap(eth_header->Type)) { case ETHERTYPE_IP: @@ -5864,12 +5871,20 @@ static WINDIVERT_INLINE BOOL windivert_parse_headers(PNET_BUFFER buffer, case ETHERTYPE_IPV6: ipv4 = FALSE; break; + case ETHERTYPE_ARP: + arp_header = (PWINDIVERT_ARPHDR)NdisGetDataBuffer(buffer, + sizeof(WINDIVERT_ARPHDR), NULL, 1, 0); + if (arp_header == NULL) + { + DEBUG("FILTER: REJECT (failed to get ARP header)"); + return FALSE; + } + header_len += sizeof(WINDIVERT_ARPHDR); + payload_len -= sizeof(WINDIVERT_ARPHDR); + goto windivert_parse_headers_exit; default: goto windivert_parse_headers_exit; } - NdisAdvanceNetBufferDataStart(buffer, sizeof(WINDIVERT_ETHHDR), - FALSE, NULL); - advance_len += sizeof(WINDIVERT_ETHHDR); } // Get the IP header. @@ -6073,6 +6088,7 @@ windivert_parse_headers_exit: *fragment_ptr = fragment; *eth_header_ptr = eth_header; + *arp_header_ptr = arp_header; *ip_header_ptr = ip_header; *ipv6_header_ptr = ipv6_header; *icmp_header_ptr = icmp_header; @@ -6103,6 +6119,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, const WINDIVERT_FILTER *filter) { PWINDIVERT_ETHHDR eth_header = NULL; + PWINDIVERT_ARPHDR arp_header = NULL; PWINDIVERT_IPHDR ip_header = NULL; PWINDIVERT_IPV6HDR ipv6_header = NULL; PWINDIVERT_ICMPHDR icmp_header = NULL; @@ -6125,9 +6142,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, case WINDIVERT_LAYER_NETWORK: case WINDIVERT_LAYER_NETWORK_FORWARD: if (!windivert_parse_headers(buffer, layer, ipv4, &fragment, - ð_header, &ip_header, &ipv6_header, &icmp_header, - &icmpv6_header, &tcp_header, &udp_header, &protocol, - &header_len, &payload_len)) + ð_header, &arp_header, &ip_header, &ipv6_header, + &icmp_header, &icmpv6_header, &tcp_header, &udp_header, + &protocol, &header_len, &payload_len)) { return FALSE; } @@ -6174,6 +6191,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, socket_data, reflect_data, eth_header, + arp_header, ip_header, ipv6_header, icmp_header, @@ -6365,6 +6383,8 @@ static const WINDIVERT_FILTER *windivert_filter_compile( case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: ub[0] = 0x0F; break; + case WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH: + case WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH: case WINDIVERT_FILTER_FIELD_IP_TOS: case WINDIVERT_FILTER_FIELD_IP_TTL: case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: @@ -6386,6 +6406,9 @@ static const WINDIVERT_FILTER *windivert_filter_compile( ub[0] = 0x1FFF; break; case WINDIVERT_FILTER_FIELD_ETH_TYPE: + case WINDIVERT_FILTER_FIELD_ARP_HARDWARE: + case WINDIVERT_FILTER_FIELD_ARP_PROTOCOL: + case WINDIVERT_FILTER_FIELD_ARP_OPCODE: case WINDIVERT_FILTER_FIELD_IP_LENGTH: case WINDIVERT_FILTER_FIELD_IP_ID: case WINDIVERT_FILTER_FIELD_IP_CHECKSUM:
     UINT16 WinDivertHelperHtons(
    @@ -2839,7 +2866,7 @@ void WinDivertHelperHtonIPv6Address(
     The output value in network byte order.
     

    Remarks
    -Converts a value/IPv6-address from host to network byte-order. +Converts a value/MAC-address/IPv6-address from host to network byte-order.

    @@ -2945,6 +2972,7 @@ The possible fields are:
    packet16[i]✔✔✔The ith 16-bit word of the packet
    packet32[i]✔✔✔The ith 32-bit word of the packet
    length✔✔✔The packet length
    arp✔Is ARP?
    ip✔✔✔✔✔Is IPv4?
    ipv6✔✔✔✔✔Is IPv6?
    icmp✔✔✔✔✔Is ICMP?
    remoteAddr✔✔✔✔The remote address
    remotePort✔✔✔✔The remote port
    eth.*✔Ethernet fields (see WINDIVERT_ETHHDR)
    arp.*✔ARP fields (see WINDIVERT_ARPHDR)
    ip.*✔✔✔IPv4 fields (see WINDIVERT_IPHDR)
    ipv6.*✔✔✔IPv6 fields (see WINDIVERT_IPV6HDR)
    icmp.*✔✔✔ICMP fields (see WINDIVERT_ICMPHDR)
    ETHERNETNETWORKFORWARDFLOW   SOCKET REFLECT
    TRUE✔✔✔✔✔✔1
    FALSE✔✔✔✔✔✔0
    IP✔ETHERTYPE_IP (0x0800)
    IPV6✔ETHERTYPE_IPV6 (0x86dd)
    ARP✔ETHERTYPE_ARP (0x0806)
    TCP✔✔✔✔✔✔IPPROTO_TCP (6)
    UDP✔✔✔✔✔✔IPPROTO_UDP (17)
    ICMP✔✔✔✔✔✔IPPROTO_ICMP (1)