diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index e6b3449..15f3f0c 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -155,6 +155,10 @@ typedef enum TOKEN_ARP_HARD_LENGTH, TOKEN_ARP_PROT_LENGTH, TOKEN_ARP_OPCODE, + TOKEN_ARP_SRC_HARD_ADDR, + TOKEN_ARP_SRC_PROT_ADDR, + TOKEN_ARP_DST_HARD_ADDR, + TOKEN_ARP_DST_PROT_ADDR, TOKEN_LAYER_FLOW, TOKEN_LAYER_SOCKET, TOKEN_LAYER_NETWORK, @@ -732,11 +736,15 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, {"UDP", TOKEN_MACRO_UDP }, {"and", TOKEN_AND }, {"arp", TOKEN_ARP }, + {"arp.DstHardAddr", TOKEN_ARP_DST_HARD_ADDR }, + {"arp.DstProtAddr", TOKEN_ARP_DST_PROT_ADDR }, {"arp.HardLength", TOKEN_ARP_HARD_LENGTH }, {"arp.Hardware", TOKEN_ARP_HARDWARE }, + {"arp.Opcode", TOKEN_ARP_OPCODE }, {"arp.ProtLength", TOKEN_ARP_PROT_LENGTH }, {"arp.Protocol", TOKEN_ARP_PROTOCOL }, - {"arp.Opcode", TOKEN_ARP_OPCODE }, + {"arp.SrcHardAddr", TOKEN_ARP_SRC_HARD_ADDR }, + {"arp.SrcProtAddr", TOKEN_ARP_SRC_PROT_ADDR }, {"b", TOKEN_BYTES }, {"endpointId", TOKEN_ENDPOINT_ID }, {"eth.DstAddr", TOKEN_ETH_DST_ADDR }, @@ -1162,6 +1170,10 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error) {{{0}}, TOKEN_ARP_HARD_LENGTH}, {{{0}}, TOKEN_ARP_PROT_LENGTH}, {{{0}}, TOKEN_ARP_OPCODE}, + {{{0}}, TOKEN_ARP_SRC_HARD_ADDR}, + {{{0}}, TOKEN_ARP_SRC_PROT_ADDR}, + {{{0}}, TOKEN_ARP_DST_HARD_ADDR}, + {{{0}}, TOKEN_ARP_DST_PROT_ADDR}, }; // Binary search: @@ -1341,6 +1353,10 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) case TOKEN_ARP_HARD_LENGTH: case TOKEN_ARP_PROT_LENGTH: case TOKEN_ARP_OPCODE: + case TOKEN_ARP_SRC_HARD_ADDR: + case TOKEN_ARP_SRC_PROT_ADDR: + case TOKEN_ARP_DST_HARD_ADDR: + case TOKEN_ARP_DST_PROT_ADDR: case TOKEN_IP_HDR_LENGTH: case TOKEN_IP_TOS: case TOKEN_IP_LENGTH: @@ -1623,6 +1639,7 @@ static PEXPR WinDivertParseFilter(HANDLE pool, TOKEN *toks, UINT *i, INT depth, /* * Simplify a test if possible. */ +#include static void WinDivertSimplifyTest(PEXPR test) { PEXPR var = test->arg[0]; @@ -1799,12 +1816,17 @@ static void WinDivertSimplifyTest(PEXPR test) ub[0] = 0xFFFFFFFF; ub[1] = 0xFFFF; break; + case TOKEN_ARP_SRC_PROT_ADDR: + case TOKEN_ARP_DST_PROT_ADDR: + type = TOKEN_ARP; + goto ipv6_addr; case TOKEN_IPV6_SRC_ADDR: case TOKEN_IPV6_DST_ADDR: type = TOKEN_IPV6; // Fallthrough case TOKEN_LOCAL_ADDR: case TOKEN_REMOTE_ADDR: + ipv6_addr: lb[0] = lb[1] = lb[2] = lb[3] = 0; ub[0] = ub[1] = ub[2] = ub[3] = 0xFFFFFFFF; break; @@ -1815,6 +1837,10 @@ static void WinDivertSimplifyTest(PEXPR test) ub[1] = 0x7FFFFFFF; neg_lb = TRUE; break; + case TOKEN_ARP_SRC_HARD_ADDR: + case TOKEN_ARP_DST_HARD_ADDR: + type = TOKEN_ARP; + // Fallthrough case TOKEN_ETH_DST_ADDR: case TOKEN_ETH_SRC_ADDR: lb[0] = lb[1] = 0; @@ -2080,6 +2106,14 @@ static UINT32 WinDivertKindToField(KIND kind) return WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH; case TOKEN_ARP_OPCODE: return WINDIVERT_FILTER_FIELD_ARP_OPCODE; + case TOKEN_ARP_SRC_HARD_ADDR: + return WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR; + case TOKEN_ARP_SRC_PROT_ADDR: + return WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR; + case TOKEN_ARP_DST_HARD_ADDR: + return WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR; + case TOKEN_ARP_DST_PROT_ADDR: + return WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR; case TOKEN_IP_HDR_LENGTH: return WINDIVERT_FILTER_FIELD_IP_HDRLENGTH; case TOKEN_IP_TOS: @@ -3026,6 +3060,8 @@ static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream, case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: case WINDIVERT_FILTER_FIELD_LOCALADDR: case WINDIVERT_FILTER_FIELD_REMOTEADDR: + case WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR: for (i = 1; i < 4; i++) { if (!WinDivertDeserializeNumber(stream, 7, &filter->arg[i])) @@ -3039,6 +3075,8 @@ static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream, case WINDIVERT_FILTER_FIELD_TIMESTAMP: case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR: case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR: if (!WinDivertDeserializeNumber(stream, 7, &filter->arg[1])) { return FALSE; @@ -3251,6 +3289,14 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test) kind = TOKEN_ARP_PROT_LENGTH; break; case WINDIVERT_FILTER_FIELD_ARP_OPCODE: kind = TOKEN_ARP_OPCODE; break; + case WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR: + kind = TOKEN_ARP_SRC_HARD_ADDR; break; + case WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR: + kind = TOKEN_ARP_SRC_PROT_ADDR; break; + case WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR: + kind = TOKEN_ARP_DST_HARD_ADDR; break; + case WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR: + kind = TOKEN_ARP_DST_PROT_ADDR; break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: kind = TOKEN_IP_HDR_LENGTH; break; case WINDIVERT_FILTER_FIELD_IP_TOS: @@ -3980,6 +4026,8 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, break; case TOKEN_ETH_SRC_ADDR: case TOKEN_ETH_DST_ADDR: + case TOKEN_ARP_SRC_HARD_ADDR: + case TOKEN_ARP_DST_HARD_ADDR: if (val->val[2] != 0 || val->val[3] != 0 || val->val[1] > 0xFFFF) { break; @@ -3998,6 +4046,8 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case TOKEN_IPV6_DST_ADDR: case TOKEN_LOCAL_ADDR: case TOKEN_REMOTE_ADDR: + case TOKEN_ARP_SRC_PROT_ADDR: + case TOKEN_ARP_DST_PROT_ADDR: is_ipv6_addr = TRUE; break; case TOKEN_LAYER: @@ -4313,6 +4363,14 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertPutString(stream, "arp.ProtLength"); return; case TOKEN_ARP_OPCODE: WinDivertPutString(stream, "arp.Opcode"); return; + case TOKEN_ARP_SRC_HARD_ADDR: + WinDivertPutString(stream, "arp.SrcHardAddr"); return; + case TOKEN_ARP_SRC_PROT_ADDR: + WinDivertPutString(stream, "arp.SrcProtAddr"); return; + case TOKEN_ARP_DST_HARD_ADDR: + WinDivertPutString(stream, "arp.DstHardAddr"); return; + case TOKEN_ARP_DST_PROT_ADDR: + WinDivertPutString(stream, "arp.DstProtAddr"); return; case TOKEN_IP_HDR_LENGTH: WinDivertPutString(stream, "ip.HdrLength"); return; case TOKEN_IP_TOS: diff --git a/dll/windivert_shared.c b/dll/windivert_shared.c index 577cfc9..ed95ce1 100644 --- a/dll/windivert_shared.c +++ b/dll/windivert_shared.c @@ -339,6 +339,8 @@ static void WinDivertSerializeTest(PWINDIVERT_STREAM stream, case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: case WINDIVERT_FILTER_FIELD_LOCALADDR: case WINDIVERT_FILTER_FIELD_REMOTEADDR: + case WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR: for (i = 1; i < 4; i++) { WinDivertSerializeNumber(stream, filter->arg[i]); @@ -349,6 +351,8 @@ static void WinDivertSerializeTest(PWINDIVERT_STREAM stream, case WINDIVERT_FILTER_FIELD_TIMESTAMP: case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR: case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR: WinDivertSerializeNumber(stream, filter->arg[1]); break; case WINDIVERT_FILTER_FIELD_PACKET: @@ -448,6 +452,12 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, goto WinDivertHelperParsePacketExit; } arp_header = (PWINDIVERT_ARPHDR)data; + if (data_len < sizeof(WINDIVERT_ARPHDR) + + 2 * arp_header->HardLength + + 2 * arp_header->ProtLength) + { + goto WinDivertHelperParsePacketExit; + } data = (PVOID)(arp_header + 1); data_len -= sizeof(WINDIVERT_ARPHDR); header_len += sizeof(WINDIVERT_ARPHDR); @@ -1062,6 +1072,10 @@ static BOOL WinDivertValidateField(WINDIVERT_LAYER layer, UINT32 field) LE_____, /* WINDIVERT_FILTER_FIELD_ARP_HARD_LENGTH */ LE_____, /* WINDIVERT_FILTER_FIELD_ARP_PROT_LENGTH */ LE_____, /* WINDIVERT_FILTER_FIELD_ARP_OPCODE */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR */ + LE_____, /* WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR */ }; if (field > WINDIVERT_FILTER_FIELD_MAX) @@ -1204,6 +1218,13 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( case WINDIVERT_FILTER_FIELD_ARP_OPCODE: result = (arp_header != NULL); break; + case WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR: + result = WINDIVERT_ARPHDR_VALIDATE(arp_header, + packet_len - sizeof(WINDIVERT_ETHHDR)); + break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: case WINDIVERT_FILTER_FIELD_IP_TOS: case WINDIVERT_FILTER_FIELD_IP_LENGTH: @@ -1507,6 +1528,56 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter( case WINDIVERT_FILTER_FIELD_ARP_OPCODE: val[0] = (UINT32)ntohs(arp_header->Opcode); break; + case WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR: + big = TRUE; + result = WINDIVERT_GET_DATA(packet, packet_len, + 0, packet_len, + sizeof(WINDIVERT_ETHHDR) + (filter[ip].field == + WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR? + WINDIVERT_ARPHDR_GET_SRCHARDADDR_OFFSET(arp_header): + WINDIVERT_ARPHDR_GET_DSTHARDADDR_OFFSET(arp_header)), + (UINT8 *)&val64, /*addr_len=*/6); + val[0] = ((val64.HighPart >> 8) & 0x000000FF) | + ((val64.HighPart << 8) & 0x0000FF00) | + ((val64.LowPart >> 8) & 0x00FF0000) | + ((val64.LowPart << 8) & 0xFF000000); + val[1] = ((val64.LowPart << 8) & 0xFF00) | + ((val64.LowPart >> 8) & 0x00FF); + val[2] = val[3] = 0; + break; + case WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR: + big = TRUE; + data16 = sizeof(WINDIVERT_ETHHDR) + (filter[ip].field == + WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR? + WINDIVERT_ARPHDR_GET_SRCPROTADDR_OFFSET(arp_header): + WINDIVERT_ARPHDR_GET_DSTPROTADDR_OFFSET(arp_header)); + switch (ntohs(arp_header->Protocol)) + { + case ETHERTYPE_IP: + val[3] = val[2] = 0; + val[1] = 0x0000FFFF; + result = WINDIVERT_GET_DATA(packet, packet_len, + 0, packet_len, /*offset=*/data16, + (UINT8 *)&val[0], sizeof(val[0])); + val[0] = (UINT32)ntohl(val[0]); + break; + case ETHERTYPE_IPV6: + result = WINDIVERT_GET_DATA(packet, packet_len, + 0, packet_len, /*offset=*/data16, + (UINT8 *)val, sizeof(val)); + data32 = ntohl(val[0]); + val[0] = ntohl(val[3]); + val[3] = data32; + data32 = ntohl(val[1]); + val[1] = ntohl(val[2]); + val[2] = data32; + break; + default: + return -1; + } + 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 2f2cdf5..76c7efc 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -2095,6 +2095,7 @@ typedef struct UINT8 HardLength; UINT8 ProtLength; UINT16 Opcode; + ... } WINDIVERT_ARPHDR, *PWINDIVERT_ARPHDR; @@ -2106,6 +2107,27 @@ for more information.

Remarks
ARP header definition. +

+The following fields can only be accessed via pointers obtained from the following macro +definitions: +

+ +

+Here hdr points to the base of the ARP header, and len is the +total header length. +These macros evaluate to NULL if the header cannot be parsed or +the type does not match.

diff --git a/examples/netdump/netdump.c b/examples/netdump/netdump.c index 910e2c3..5a46247 100644 --- a/examples/netdump/netdump.c +++ b/examples/netdump/netdump.c @@ -65,7 +65,7 @@ int __cdecl main(int argc, char **argv) WINDIVERT_LAYER layer = WINDIVERT_LAYER_NETWORK; INT16 priority = 0; unsigned char packet[MAXBUF]; - UINT packet_len; + UINT packet_len, arp_len; WINDIVERT_ADDRESS addr; PWINDIVERT_ETHHDR eth_header; PWINDIVERT_ARPHDR arp_header; @@ -75,8 +75,8 @@ int __cdecl main(int argc, char **argv) PWINDIVERT_ICMPV6HDR icmpv6_header; PWINDIVERT_TCPHDR tcp_header; PWINDIVERT_UDPHDR udp_header; - UINT8 src_mac[6], dst_mac[6]; - UINT32 src_addr[4], dst_addr[4]; + UINT8 src_mac[6], dst_mac[6], *mac_ptr; + UINT32 src_addr[4], dst_addr[4], *ip_ptr; UINT64 hash; char src_str[INET6_ADDRSTRLEN+1], dst_str[INET6_ADDRSTRLEN+1]; const char *err_str; @@ -136,8 +136,8 @@ int __cdecl main(int argc, char **argv) { err = GetLastError(); if (err == ERROR_INVALID_PARAMETER && - !WinDivertHelperCompileFilter(argv[1], WINDIVERT_LAYER_NETWORK, - NULL, 0, &err_str, NULL)) + !WinDivertHelperCompileFilter(argv[1], layer, NULL, 0, &err_str, + NULL)) { fprintf(stderr, "error: invalid filter \"%s\"\n", err_str); exit(EXIT_FAILURE); @@ -213,13 +213,67 @@ int __cdecl main(int argc, char **argv) src_str, dst_str, ntohs(eth_header->Type)); if (arp_header != NULL) { + arp_len = packet_len - sizeof(WINDIVERT_ETHHDR); SetConsoleTextAttribute(console, FOREGROUND_GREEN); printf("ARP [Hardware=%u Protocol=%u HardLength=%u " - "ProtLength=%u Opcode=%u]\n", + "ProtLength=%u Opcode=%u", ntohs(arp_header->Hardware), ntohs(arp_header->Protocol), arp_header->HardLength, arp_header->ProtLength, ntohs(arp_header->Opcode)); + mac_ptr = WINDIVERT_ARPHDR_GET_SRCMACADDR_PTR(arp_header, + arp_len); + if (mac_ptr != NULL) + { + WinDivertHelperNtohMACAddress(mac_ptr, src_mac); + WinDivertHelperFormatMACAddress(src_mac, src_str, + sizeof(src_str)); + printf(" SrcHardAddr=%s", src_str); + } + ip_ptr = WINDIVERT_ARPHDR_GET_SRCIPV4ADDR_PTR(arp_header, + arp_len); + if (ip_ptr != NULL) + { + WinDivertHelperFormatIPv4Address(ntohl(ip_ptr[0]), + src_str, sizeof(src_str)); + printf(" SrcProtAddr=%s", src_str); + } + ip_ptr = WINDIVERT_ARPHDR_GET_SRCIPV6ADDR_PTR(arp_header, + arp_len); + if (ip_ptr != NULL) + { + WinDivertHelperNtohIPv6Address(ip_ptr, src_addr); + WinDivertHelperFormatIPv6Address(src_addr, src_str, + sizeof(src_str)); + printf(" SrcProtAddr=%s", src_str); + } + mac_ptr = WINDIVERT_ARPHDR_GET_DSTMACADDR_PTR(arp_header, + arp_len); + if (mac_ptr != NULL) + { + WinDivertHelperNtohMACAddress(mac_ptr, dst_mac); + WinDivertHelperFormatMACAddress(dst_mac, dst_str, + sizeof(dst_str)); + printf(" DstHardAddr=%s", dst_str); + } + ip_ptr = WINDIVERT_ARPHDR_GET_DSTIPV4ADDR_PTR(arp_header, + arp_len); + if (ip_ptr != NULL) + { + WinDivertHelperFormatIPv4Address(ntohl(ip_ptr[0]), + dst_str, sizeof(dst_str)); + printf(" DstProtAddr=%s", dst_str); + } + ip_ptr = WINDIVERT_ARPHDR_GET_DSTIPV6ADDR_PTR(arp_header, + arp_len); + if (ip_ptr != NULL) + { + WinDivertHelperNtohIPv6Address(ip_ptr, dst_addr); + WinDivertHelperFormatIPv6Address(dst_addr, dst_str, + sizeof(dst_str)); + printf(" DstProtAddr=%s", dst_str); + } + printf("]\n"); } } else diff --git a/include/windivert.h b/include/windivert.h index 6a1360c..3d0e64d 100644 --- a/include/windivert.h +++ b/include/windivert.h @@ -368,6 +368,52 @@ typedef struct UINT16 Opcode; } WINDIVERT_ARPHDR, *PWINDIVERT_ARPHDR; +#define WINDIVERT_ARPHDR_VALIDATE(hdr, len) \ + ((hdr) != NULL && \ + (len) >= sizeof(WINDIVERT_ARPHDR) && \ + (len) >= sizeof(WINDIVERT_ARPHDR) + \ + 2 * (hdr)->HardLength + 2 * (hdr)->ProtLength && \ + (hdr)->Hardware == 0x0100 && \ + (hdr)->HardLength == 6 && \ + (((hdr)->Protocol == 0x0008 && \ + (hdr)->ProtLength == 4) || \ + ((hdr)->Protocol == 0xDD86 && \ + (hdr)->ProtLength == 16))) + +#define WINDIVERT_ARPHDR_GET_SRCHARDADDR_OFFSET(hdr) \ + (sizeof(WINDIVERT_ARPHDR)) +#define WINDIVERT_ARPHDR_GET_SRCPROTADDR_OFFSET(hdr) \ + (sizeof(WINDIVERT_ARPHDR)+(hdr)->HardLength) +#define WINDIVERT_ARPHDR_GET_DSTHARDADDR_OFFSET(hdr) \ + (sizeof(WINDIVERT_ARPHDR)+(hdr)->HardLength+(hdr)->ProtLength) +#define WINDIVERT_ARPHDR_GET_DSTPROTADDR_OFFSET(hdr) \ + (sizeof(WINDIVERT_ARPHDR)+2*(hdr)->HardLength+(hdr)->ProtLength) + +#define WINDIVERT_ARPHDR_GET_SRCMACADDR_PTR(hdr, len) \ + (!WINDIVERT_ARPHDR_VALIDATE(hdr, len) || \ + (hdr)->Hardware != 0x0100? NULL: \ + (((UINT8 *)(hdr))+WINDIVERT_ARPHDR_GET_SRCHARDADDR_OFFSET(hdr))) +#define WINDIVERT_ARPHDR_GET_SRCIPV4ADDR_PTR(hdr, len) \ + (!WINDIVERT_ARPHDR_VALIDATE(hdr, len) || \ + (hdr)->Protocol != 0x0008? NULL: \ + ((UINT32 *)(((UINT8 *)(hdr))+WINDIVERT_ARPHDR_GET_SRCPROTADDR_OFFSET(hdr)))) +#define WINDIVERT_ARPHDR_GET_SRCIPV6ADDR_PTR(hdr, len) \ + (!WINDIVERT_ARPHDR_VALIDATE(hdr, len) || \ + (hdr)->Protocol != 0xDD86? NULL: \ + ((UINT32 *)(((UINT8 *)(hdr))+WINDIVERT_ARPHDR_GET_SRCPROTADDR_OFFSET(hdr)))) +#define WINDIVERT_ARPHDR_GET_DSTMACADDR_PTR(hdr, len) \ + (!WINDIVERT_ARPHDR_VALIDATE(hdr, len) || \ + (hdr)->Hardware != 0x0100? NULL: \ + (((UINT8 *)(hdr))+WINDIVERT_ARPHDR_GET_DSTHARDADDR_OFFSET(hdr))) +#define WINDIVERT_ARPHDR_GET_DSTIPV4ADDR_PTR(hdr, len) \ + (!WINDIVERT_ARPHDR_VALIDATE(hdr, len) || \ + (hdr)->Protocol != 0x0008? NULL: \ + ((UINT32 *)(((UINT8 *)(hdr))+WINDIVERT_ARPHDR_GET_DSTPROTADDR_OFFSET(hdr)))) +#define WINDIVERT_ARPHDR_GET_DSTIPV6ADDR_PTR(hdr, len) \ + (!WINDIVERT_ARPHDR_VALIDATE(hdr, len) || \ + (hdr)->Protocol != 0xDD86? NULL: \ + ((UINT32 *)(((UINT8 *)(hdr))+WINDIVERT_ARPHDR_GET_DSTPROTADDR_OFFSET(hdr)))) + typedef struct { UINT8 HdrLength:4; diff --git a/include/windivert_device.h b/include/windivert_device.h index 87a6e83..7a17396 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -159,8 +159,12 @@ #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_ARP_SRC_HARD_ADDR 95 +#define WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR 96 +#define WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR 97 +#define WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR 98 #define WINDIVERT_FILTER_FIELD_MAX \ - WINDIVERT_FILTER_FIELD_ARP_OPCODE + WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR #define WINDIVERT_FILTER_TEST_EQ 0 #define WINDIVERT_FILTER_TEST_NEQ 1 diff --git a/sys/windivert.c b/sys/windivert.c index be39102..5619dfd 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -6448,6 +6448,8 @@ static const WINDIVERT_FILTER *windivert_filter_compile( break; case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR: case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_SRC_HARD_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_HARD_ADDR: ub[0] = 0xFFFFFFFF; ub[1] = 0x0000FFFF; break; @@ -6461,6 +6463,8 @@ static const WINDIVERT_FILTER *windivert_filter_compile( case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: ub[0] = ub[1] = 0xFFFFFFFF; break; + case WINDIVERT_FILTER_FIELD_ARP_SRC_PROT_ADDR: + case WINDIVERT_FILTER_FIELD_ARP_DST_PROT_ADDR: case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: case WINDIVERT_FILTER_FIELD_LOCALADDR: