Skip to content

Commit ab50ffe

Browse files
committed
Minor API improvements.
- addr.Pseudo*Checksum flags replaced by simpler addr.*Checksum flags. - WinDivertHelperParsePacket() can now handle batched packets. - WinDivertHelperParsePacket() can now return the transport protocol. - WinDivertHelperCalcChecksums() can now handle batched packets. - WinDivertHelperCalcChecksums() now sets address checksum flags that were calculated. - A bunch of WINDIVERT_* macros have been moved to windivert.h for windivert_device.h.
1 parent 42bf883 commit ab50ffe

File tree

11 files changed

+218
-232
lines changed

11 files changed

+218
-232
lines changed

dll/windivert_helper.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -284,19 +284,6 @@ static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
284284
static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
285285
WINDIVERT_LAYER layer, BOOL top_level, BOOL and);
286286

287-
/*
288-
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
289-
*/
290-
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
291-
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
292-
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
293-
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
294-
UINT *pDataLen)
295-
{
296-
return WinDivertParsePacket((PVOID)pPacket, packetLen, ppIpHdr, ppIpv6Hdr,
297-
ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, NULL, ppData, pDataLen);
298-
}
299-
300287
/*
301288
* Parse an IPv4 address.
302289
*/
@@ -2446,9 +2433,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
24462433
SetLastError(ERROR_INVALID_PARAMETER);
24472434
return FALSE;
24482435
}
2449-
WinDivertParsePacket((PVOID)packet, packet_len, &iphdr, &ipv6hdr,
2450-
&icmphdr, &icmpv6hdr, &tcphdr, &udphdr, &protocol, NULL,
2451-
&payload_len);
2436+
WinDivertHelperParsePacket((PVOID)packet, packet_len, &protocol,
2437+
&iphdr, &ipv6hdr, &icmphdr, &icmpv6hdr, &tcphdr, &udphdr,
2438+
NULL, &payload_len, NULL, NULL);
24522439
header_len = packet_len - payload_len;
24532440
if ((addr->IPv6 && ipv6hdr == NULL) ||
24542441
(!addr->IPv6 && iphdr == NULL))
@@ -4599,9 +4586,9 @@ extern UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
45994586
PWINDIVERT_TCPHDR tcp_header = NULL;
46004587
PWINDIVERT_UDPHDR udp_header = NULL;
46014588

4602-
WinDivertParsePacket((PVOID)pPacket, packetLen, &ip_header, &ipv6_header,
4603-
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
4604-
NULL, NULL);
4589+
WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL, &ip_header,
4590+
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, &udp_header,
4591+
NULL, NULL, NULL, NULL);
46054592
return WinDivertHashPacket(seed, ip_header, ipv6_header, icmp_header,
46064593
icmpv6_header, tcp_header, udp_header);
46074594
}
@@ -4635,7 +4622,7 @@ extern UINT64 WinDivertHelperHtonll(UINT64 x)
46354622
}
46364623
static void WinDivertByteSwap128(const UINT *inAddr, UINT *outAddr)
46374624
{
4638-
UINT32 tmp[4], i; // tmp[] allows overlapping
4625+
UINT32 tmp[4], i; // tmp[] allows overlapping inAddr/outAddr
46394626
for (i = 0; i < 4; i++)
46404627
{
46414628
tmp[3-i] = BYTESWAP32(inAddr[0]);

dll/windivert_shared.c

Lines changed: 102 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,11 @@ static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
283283
/*
284284
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
285285
*/
286-
static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
287-
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
286+
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
287+
UINT8 *pProtocol, PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
288288
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
289-
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, UINT8 *pProto,
290-
PVOID *ppData, UINT *pDataLen)
289+
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
290+
UINT *pDataLen, PVOID *ppNext, UINT *pNextLen)
291291
{
292292
PWINDIVERT_IPHDR ip_header = NULL;
293293
PWINDIVERT_IPV6HDR ipv6_header = NULL;
@@ -297,15 +297,15 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
297297
PWINDIVERT_UDPHDR udp_header = NULL;
298298
UINT16 header_len;
299299
UINT8 trans_proto = 0;
300-
PVOID data = NULL;
301-
UINT data_len = 0;
302-
BOOL success;
300+
PVOID data = NULL, next = NULL;
301+
UINT data_len = 0, next_len = 0, packet_len;
302+
BOOL success = FALSE;
303303

304-
if (pPacket == NULL || packetLen < sizeof(UINT8))
304+
if (pPacket == NULL || packetLen < sizeof(WINDIVERT_IPHDR))
305305
{
306306
goto WinDivertHelperParsePacketExit;
307307
}
308-
data = pPacket;
308+
data = (PVOID)pPacket;
309309
data_len = packetLen;
310310

311311
ip_header = (PWINDIVERT_IPHDR)data;
@@ -315,36 +315,49 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
315315
if (data_len < sizeof(WINDIVERT_IPHDR) ||
316316
ip_header->HdrLength < 5 ||
317317
data_len < ip_header->HdrLength*sizeof(UINT32) ||
318-
ntohs(ip_header->Length) != data_len)
318+
(UINT)ntohs(ip_header->Length) > data_len)
319319
{
320320
ip_header = NULL;
321321
goto WinDivertHelperParsePacketExit;
322322
}
323323
trans_proto = ip_header->Protocol;
324+
packet_len = (UINT)ntohs(ip_header->Length);
324325
header_len = ip_header->HdrLength*sizeof(UINT32);
326+
if (packet_len < data_len)
327+
{
328+
next = (PVOID)((UINT8 *)data + packet_len);
329+
next_len = data_len - packet_len;
330+
}
325331
data = (PVOID)((UINT8 *)data + header_len);
326-
data_len -= header_len;
332+
data_len = packet_len - header_len;
327333
break;
328334
case 6:
329335
ip_header = NULL;
330336
ipv6_header = (PWINDIVERT_IPV6HDR)data;
331337
if (data_len < sizeof(WINDIVERT_IPV6HDR) ||
332-
ntohs(ipv6_header->Length) !=
333-
data_len - sizeof(WINDIVERT_IPV6HDR))
338+
ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR) >
339+
data_len)
334340
{
335341
ipv6_header = NULL;
336342
goto WinDivertHelperParsePacketExit;
337343
}
338344
trans_proto = ipv6_header->NextHdr;
345+
packet_len = ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR);
346+
if (packet_len < data_len)
347+
{
348+
next = (PVOID)((UINT8 *)data + packet_len);
349+
next_len = data_len - packet_len;
350+
}
339351
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
340-
data_len -= sizeof(WINDIVERT_IPV6HDR);
352+
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
341353
trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data,
342354
&data_len);
343355
break;
344356
default:
345357
ip_header = NULL;
346358
goto WinDivertHelperParsePacketExit;
347359
}
360+
success = TRUE;
348361
switch (trans_proto)
349362
{
350363
case IPPROTO_TCP:
@@ -403,58 +416,59 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
403416
}
404417

405418
WinDivertHelperParsePacketExit:
406-
success = TRUE;
419+
if (pProtocol != NULL)
420+
{
421+
*pProtocol = trans_proto;
422+
}
407423
if (ppIpHdr != NULL)
408424
{
409425
*ppIpHdr = ip_header;
410-
success = success && (ip_header != NULL);
411426
}
412427
if (ppIpv6Hdr != NULL)
413428
{
414429
*ppIpv6Hdr = ipv6_header;
415-
success = success && (ipv6_header != NULL);
416430
}
417431
if (ppIcmpHdr != NULL)
418432
{
419433
*ppIcmpHdr = icmp_header;
420-
success = success && (icmp_header != NULL);
421434
}
422435
if (ppIcmpv6Hdr != NULL)
423436
{
424437
*ppIcmpv6Hdr = icmpv6_header;
425-
success = success && (icmpv6_header != NULL);
426438
}
427439
if (ppTcpHdr != NULL)
428440
{
429441
*ppTcpHdr = tcp_header;
430-
success = success && (tcp_header != NULL);
431442
}
432443
if (ppUdpHdr != NULL)
433444
{
434445
*ppUdpHdr = udp_header;
435-
success = success && (udp_header != NULL);
436-
}
437-
if (pProto != NULL)
438-
{
439-
*pProto = trans_proto;
440446
}
441447
if (ppData != NULL)
442448
{
443449
*ppData = data;
444-
success = success && (data != NULL);
445450
}
446451
if (pDataLen != NULL)
447452
{
448453
*pDataLen = data_len;
449454
}
455+
if (ppNext != NULL)
456+
{
457+
*ppNext = next;
458+
}
459+
if (pNextLen != NULL)
460+
{
461+
*pNextLen = next_len;
462+
}
463+
450464
return success;
451465
}
452466

453467
/*
454468
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
455469
*/
456470
extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
457-
const WINDIVERT_ADDRESS *pAddr, UINT64 flags)
471+
WINDIVERT_ADDRESS *pAddr, UINT64 flags)
458472
{
459473
UINT8 pseudo_header[
460474
MAX(sizeof(WINDIVERT_PSEUDOHDR), sizeof(WINDIVERT_PSEUDOV6HDR))];
@@ -468,83 +482,78 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
468482
UINT payload_len, checksum_len;
469483
UINT count = 0;
470484

471-
WinDivertParsePacket(pPacket, packetLen, &ip_header, &ipv6_header,
472-
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, NULL,
473-
&payload_len);
474-
475-
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
485+
while (WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header,
486+
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
487+
&udp_header, NULL, &payload_len, &pPacket, &packetLen))
476488
{
477-
ip_header->Checksum = 0;
478-
if (pAddr == NULL || pAddr->PseudoIPChecksum == 0)
479-
{
480-
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0,
481-
ip_header, ip_header->HdrLength*sizeof(UINT32));
482-
}
483-
count++;
484-
}
485489

486-
if (icmp_header != NULL)
487-
{
488-
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
490+
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
489491
{
490-
return count;
492+
ip_header->Checksum = 0;
493+
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0, ip_header,
494+
ip_header->HdrLength*sizeof(UINT32));
495+
if (pAddr != NULL)
496+
{
497+
pAddr->IPChecksum = 1;
498+
}
499+
count++;
491500
}
492-
icmp_header->Checksum = 0;
493-
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
494-
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
495-
count++;
496-
return count;
497-
}
498-
499-
if (icmpv6_header != NULL)
500-
{
501-
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
501+
502+
if (icmp_header != NULL)
502503
{
503-
return count;
504+
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
505+
{
506+
continue;
507+
}
508+
icmp_header->Checksum = 0;
509+
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
510+
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
511+
count++;
512+
continue;
504513
}
505-
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
506-
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
507-
IPPROTO_ICMPV6, checksum_len, pseudo_header);
508-
icmpv6_header->Checksum = 0;
509-
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
510-
pseudo_header_len, icmpv6_header, checksum_len);
511-
count++;
512-
return count;
513-
}
514-
515-
if (tcp_header != NULL)
516-
{
517-
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
514+
515+
if (icmpv6_header != NULL)
518516
{
519-
return count;
517+
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
518+
{
519+
continue;
520+
}
521+
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
522+
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
523+
IPPROTO_ICMPV6, checksum_len, pseudo_header);
524+
icmpv6_header->Checksum = 0;
525+
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
526+
pseudo_header_len, icmpv6_header, checksum_len);
527+
count++;
528+
continue;
520529
}
521-
if (pAddr == NULL || pAddr->PseudoTCPChecksum == 0)
530+
531+
if (tcp_header != NULL)
522532
{
523-
// Full TCP checksum
533+
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
534+
{
535+
continue;
536+
}
524537
checksum_len = payload_len + tcp_header->HdrLength*sizeof(UINT32);
525538
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
526539
ipv6_header, IPPROTO_TCP, checksum_len, pseudo_header);
527540
tcp_header->Checksum = 0;
528541
tcp_header->Checksum = WinDivertCalcChecksum(
529542
pseudo_header, pseudo_header_len, tcp_header, checksum_len);
543+
if (pAddr != NULL)
544+
{
545+
pAddr->TCPChecksum = 1;
546+
}
547+
count++;
548+
continue;
530549
}
531-
else if (pAddr->Outbound)
532-
{
533-
// Pseudo TCP checksum
534-
tcp_header->Checksum = 0;
535-
}
536-
count++;
537-
return count;
538-
}
539-
540-
if (udp_header != NULL)
541-
{
542-
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
543-
{
544-
return count;
545-
}
546-
if (pAddr == NULL || pAddr->PseudoUDPChecksum == 0)
550+
551+
if (udp_header != NULL)
547552
{
553+
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
554+
{
555+
continue;
556+
}
548557
// Full UDP checksum
549558
checksum_len = payload_len + sizeof(WINDIVERT_UDPHDR);
550559
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
@@ -556,14 +565,14 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
556565
{
557566
udp_header->Checksum = 0xFFFF;
558567
}
568+
if (pAddr != NULL)
569+
{
570+
pAddr->UDPChecksum = 1;
571+
}
572+
count++;
559573
}
560-
else if (pAddr->Outbound)
561-
{
562-
// Pseudo UDP checksum
563-
udp_header->Checksum = 0;
564-
}
565-
count++;
566574
}
575+
567576
return count;
568577
}
569578

examples/netdump/netdump.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ int __cdecl main(int argc, char **argv)
147147
}
148148

149149
// Print info about the matching packet.
150-
WinDivertHelperParsePacket(packet, packet_len, &ip_header,
150+
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
151151
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
152-
&udp_header, NULL, NULL);
152+
&udp_header, NULL, NULL, NULL, NULL);
153153
if (ip_header == NULL && ipv6_header == NULL)
154154
{
155155
fprintf(stderr, "warning: junk packet\n");

0 commit comments

Comments
 (0)