@@ -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
405418WinDivertHelperParsePacketExit :
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 */
456470extern 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
0 commit comments