From a255d6776e6aecbb2213122c09ad3aaaf853f9d9 Mon Sep 17 00:00:00 2001
From: basil00
Date: Wed, 15 Mar 2023 06:29:26 +0800
Subject: [PATCH] Add support for the remaining ARP fields
- SrcHardAddr
- SrcProtAddr
- DstHardAddr
- DstProtAddr
---
dll/windivert_helper.c | 60 +++++++++++++++++++++++++++++++-
dll/windivert_shared.c | 71 ++++++++++++++++++++++++++++++++++++++
doc/windivert.html | 22 ++++++++++++
examples/netdump/netdump.c | 66 +++++++++++++++++++++++++++++++----
include/windivert.h | 46 ++++++++++++++++++++++++
include/windivert_device.h | 6 +++-
sys/windivert.c | 4 +++
7 files changed, 267 insertions(+), 8 deletions(-)
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:
+
+
+- SrcHardAddr with
+
WINDIVERT_ARPHDR_GET_SRCMACADDR_PTR(hdr, len)
+- SrcProtAddr with
+
WINDIVERT_ARPHDR_GET_SRCIPV4ADDR_PTR(hdr, len) or
+ WINDIVERT_ARPHDR_GET_SRCIPV6ADDR_PTR(hdr, len)
+- DstHardAddr with
+
WINDIVERT_ARPHDR_GET_DSTMACADDR_PTR(hdr, len)
+- DstProtAddr with
+
WINDIVERT_ARPHDR_GET_DSTIPV4ADDR_PTR(hdr, len) or
+ WINDIVERT_ARPHDR_GET_DSTIPV6ADDR_PTR(hdr, len)
+
+
+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: