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? |
@@ -2957,6 +2985,7 @@ The possible fields are:
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) |
@@ -3030,6 +3059,9 @@ The possible macros are:
| ETHERNET | NETWORK | FORWARD | FLOW | 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) |
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:
|