Changeset 11049
- Timestamp:
- 07/31/08 23:19:52 (4 months ago)
- Files:
-
- trunk/include/iprt/net.h (modified) (1 diff)
- trunk/src/VBox/Runtime/common/checksum/ipv4.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/iprt/net.h
r11044 r11049 245 245 RTDECL(bool) RTNetIPv4IsUDPValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData, size_t cbPktMax); 246 246 247 /** 248 * IPv4 BOOTP / DHCP packet. 249 */ 250 #pragma pack(1) 251 typedef struct RTNETBOOTP 252 { 253 /** 00 - The packet opcode. */ 254 uint8_t bp_op; 255 /** 01 - Hardware address type. Same as RTNETARPHDR::ar_htype. */ 256 uint8_t bp_htype; 257 /** 02 - Hardware address length. */ 258 uint8_t bp_hlen; 259 /** 03 - Gateway hops. */ 260 uint8_t bp_hops; 261 /** 04 - Transaction ID. */ 262 uint32_t bp_xid; 263 /** 08 - Seconds since boot started. */ 264 uint16_t bp_secs; 265 /** 0a - Unused (BOOTP) / Flags (DHCP). */ 266 uint16_t bp_flags; 267 /** 0c - Client IPv4 address. */ 268 RTNETADDRIPV4 bp_ciaddr; 269 /** 10 - Your IPv4 address. */ 270 RTNETADDRIPV4 bp_yiaddr; 271 /** 14 - Server IPv4 address. */ 272 RTNETADDRIPV4 bp_siaddr; 273 /** 18 - Gateway IPv4 address. */ 274 RTNETADDRIPV4 bp_giaddr; 275 /** 1c - Client hardware address. */ 276 union 277 { 278 uint8_t au8[16]; 279 RTMAC Mac; 280 } bp_chaddr; 281 /** 2c - Server name. */ 282 uint8_t bp_sname[64]; 283 /** 6c - File name / more DHCP options. */ 284 uint8_t bp_file[128]; 285 /** ec - Vendor specific area (BOOTP) / Options (DHCP). 286 * @remark This is really 312 bytes in the DHCP version. */ 287 union 288 { 289 uint8_t au8[128]; 290 struct DHCP 291 { 292 /** ec - The DHCP cookie (RTNET_DHCP_COOKIE). */ 293 uint32_t dhcp_cookie; 294 /** f0 - The DHCP options. */ 295 uint8_t dhcp_opts[124]; 296 } Dhcp; 297 } bp_vend; 298 299 } RTNETBOOTP; 300 #pragma pack(0) 301 AssertCompileSize(RTNETBOOTP, 0xec + 128); 302 /** Pointer to a BOOTP / DHCP packet. */ 303 typedef RTNETBOOTP *PRTNETBOOTP; 304 /** Pointer to a const BOOTP / DHCP packet. */ 305 typedef RTNETBOOTP const *PCRTNETBOOTP; 306 307 /** @name BOOTP packet opcode values 308 * @{ */ 309 #define RTNETBOOTP_OP_REQUEST 1 310 #define RTNETBOOTP_OP_REPLY 2 311 /** @} */ 312 313 /** @name DHCP flags (RTNETBOOTP::bp_flags) 314 * @{ */ 315 #define RTNET_DHCP_FLAGS_NO_BROADCAST UINT16_C(0x8000) /** @todo check test!!! */ 316 /** @} */ 317 318 /** The DHCP cookie (network endian). */ 319 #define RTNET_DHCP_COOKIE UINT32_C(0x63825363) 320 321 /** 322 * An IPv4 DHCP option header. 323 */ 324 typedef struct RTNETDHCPOPT 325 { 326 /** 00 - The DHCP option. */ 327 uint8_t dhcp_opt; 328 /** 01 - The data length (excluding this header). */ 329 uint8_t dhcp_len; 330 /* 02 - The option data follows here, optional and of variable length. */ 331 } RTNETDHCPOPT; 332 AssertCompileSize(RTNETDHCPOPT, 2); 333 /** Pointer to a DHCP option header. */ 334 typedef RTNETDHCPOPT *PRTNETDHCPOPT; 335 /** Pointer to a const DHCP option header. */ 336 typedef RTNETDHCPOPT const *PCRTNETDHCPOPT; 337 338 /** @name DHCP options 339 * @{ */ 340 /** 1 byte padding, this has no dhcp_len field. */ 341 #define RTNET_DHCP_OPT_PAD 0 342 /** Have a 8-bit message type value as data, see RTNET_DHCP_MT_*. */ 343 #define RTNET_DHCP_OPT_MSG_TYPE 53 344 /** Marks the end of the DHCP options, this has no dhcp_len field. */ 345 #define RTNET_DHCP_OPT_END 255 346 /** @} */ 347 348 /** @name DHCP Message Types (option 53) 349 * @{ */ 350 #define RTNET_DHCP_MT_DISCOVER 1 351 #define RTNET_DHCP_MT_OFFER 2 352 #define RTNET_DHCP_MT_REQUEST 3 353 #define RTNET_DHCP_MT_DECLINE 4 354 #define RTNET_DHCP_MT_ACK 5 355 #define RTNET_DHCP_MT_NAC 6 356 #define RTNET_DHCP_MT_RELEASE 7 357 #define RTNET_DHCP_MT_INFORM 8 358 /** @} */ 359 360 RTDECL(bool) RTNetIPv4IsDHCPValid(PCRTNETUDP pUdpHdr, PCRTNETBOOTP pDhcp, size_t cbDhcp, uint8_t *pMsgType); 361 247 362 248 363 /** 249 364 * IPv4 DHCP packet. 365 * @obsolete Use RTNETBOOTP. 250 366 */ 251 367 #pragma pack(1) 252 368 typedef struct RTNETDHCP 253 369 { 370 /** 00 - The packet opcode. */ 254 371 uint8_t Op; 255 372 /** Hardware address type. */ 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

