Changeset 11049 in vbox for trunk/src/VBox/Runtime/common/checksum
- Timestamp:
- Jul 31, 2008 9:19:52 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 33944
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/checksum/ipv4.cpp
r11044 r11049 549 549 } 550 550 551 552 /** 553 * Minimal validation of a DHCP packet. 554 * 555 * This will fail on BOOTP packets (if sufficient data is supplied). 556 * It will not verify the source and destination ports, that's the 557 * caller's responsibility. 558 * 559 * This function will ASSUME that the hardware type is ethernet 560 * and use that for htype/hlen validation. 561 * 562 * @returns true if valid, false if invalid. 563 * @param pUdpHdr Pointer to the UDP header, in network endian (big). 564 * This is assumed to be valid and fully mapped. 565 * @param pDhcp Pointer to the DHCP packet. 566 * This might not be the entire thing, see cbDhcp. 567 * @param cbDhcp The number of valid bytes that pDhcp points to. 568 * @param pMsgType Where to store the message type (if found). 569 * This will be set to 0 if not found and on failure. 570 */ 571 RTDECL(bool) RTNetIPv4IsDHCPValid(PCRTNETUDP pUdpHdr, PCRTNETBOOTP pDhcp, size_t cbDhcp, uint8_t *pMsgType) 572 { 573 AssertPtrNull(pMsgType); 574 if (pMsgType) 575 *pMsgType = 0; 576 577 /* 578 * Validate all the header fields we're able to... 579 */ 580 if (cbDhcp < RT_OFFSETOF(RTNETBOOTP, bp_op) + sizeof(pDhcp->bp_op)) 581 return true; 582 if (RT_UNLIKELY( pDhcp->bp_op != RTNETBOOTP_OP_REQUEST 583 && pDhcp->bp_op != RTNETBOOTP_OP_REPLY)) 584 return false; 585 586 if (cbDhcp < RT_OFFSETOF(RTNETBOOTP, bp_htype) + sizeof(pDhcp->bp_htype)) 587 return true; 588 if (RT_UNLIKELY(pDhcp->bp_htype != RTNET_ARP_ETHER)) 589 return false; 590 591 if (cbDhcp < RT_OFFSETOF(RTNETBOOTP, bp_hlen) + sizeof(pDhcp->bp_hlen)) 592 return true; 593 if (RT_UNLIKELY(pDhcp->bp_hlen != sizeof(RTMAC))) 594 return false; 595 596 if (cbDhcp < RT_OFFSETOF(RTNETBOOTP, bp_flags) + sizeof(pDhcp->bp_flags)) 597 return true; 598 if (RT_UNLIKELY(RT_BE2H_U16(pDhcp->bp_flags) & ~(RTNET_DHCP_FLAGS_NO_BROADCAST))) 599 return false; 600 601 /* 602 * Check the DHCP cookie and make sure it isn't followed by an END option 603 * (because that seems to be indicating that it's BOOTP and not DHCP). 604 */ 605 ssize_t cbLeft = (ssize_t)cbDhcp - RT_OFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_cookie) + sizeof(pDhcp->bp_vend.Dhcp.dhcp_cookie); 606 if (cbLeft < 0) 607 return true; 608 if (RT_UNLIKELY(RT_BE2H_U32(pDhcp->bp_vend.Dhcp.dhcp_cookie) != RTNET_DHCP_COOKIE)) 609 return false; 610 if (cbLeft < 1) 611 return true; 612 PCRTNETDHCPOPT pOpt = (PCRTNETDHCPOPT)&pDhcp->bp_vend.Dhcp.dhcp_opts[0]; 613 if (pOpt->dhcp_opt == RTNET_DHCP_OPT_END) 614 return false; 615 616 /* 617 * Scan the options until we find the message type or run out of message. 618 * 619 * We're not strict about termination (END) for many reasons, however, 620 * we don't accept END without MSG_TYPE. 621 */ 622 uint8_t MsgType = 0; 623 while (cbLeft > 0) 624 { 625 if (pOpt->dhcp_opt == RTNET_DHCP_OPT_END) 626 { 627 /* Fail if no MSG_TYPE. */ 628 if (!MsgType) 629 return false; 630 break; 631 } 632 if (pOpt->dhcp_opt == RTNET_DHCP_OPT_PAD) 633 { 634 pOpt = (PCRTNETDHCPOPT)((uint8_t const *)pOpt + 1); 635 cbLeft--; 636 } 637 else 638 { 639 switch (pOpt->dhcp_opt) 640 { 641 case RTNET_DHCP_OPT_MSG_TYPE: 642 { 643 if (cbLeft < 3) 644 return true; 645 MsgType = *(const uint8_t *)(pOpt + 1); 646 switch (MsgType) 647 { 648 case RTNET_DHCP_MT_DISCOVER: 649 case RTNET_DHCP_MT_OFFER: 650 case RTNET_DHCP_MT_REQUEST: 651 case RTNET_DHCP_MT_DECLINE: 652 case RTNET_DHCP_MT_ACK: 653 case RTNET_DHCP_MT_NAC: 654 case RTNET_DHCP_MT_RELEASE: 655 case RTNET_DHCP_MT_INFORM: 656 break; 657 658 default: 659 /* we don't know this message type, fail. */ 660 return false; 661 } 662 663 /* Found a known message type, consider the job done. */ 664 if (pMsgType) 665 *pMsgType = MsgType; 666 return true; 667 } 668 } 669 670 /* Skip the option. */ 671 cbLeft -= pOpt->dhcp_len + sizeof(*pOpt); 672 pOpt = (PCRTNETDHCPOPT)((uint8_t const *)pOpt + pOpt->dhcp_len + sizeof(*pOpt)); 673 } 674 } 675 676 return true; 677 } 678
Note:
See TracChangeset
for help on using the changeset viewer.