VirtualBox

Changeset 11049

Show
Ignore:
Timestamp:
07/31/08 23:19:52 (4 months ago)
Author:
vboxsync
Message:

IPRT/RTNetIPv4: Rewrote the RTNETDHCP header as RTNETBOOTP and associated structures and defines. Added RTNetIPv4IsDHCPValid for validating a DHCP packet and dig out the message type option

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/iprt/net.h

    r11044 r11049  
    245245RTDECL(bool)     RTNetIPv4IsUDPValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData, size_t cbPktMax); 
    246246 
     247/** 
     248 * IPv4 BOOTP / DHCP packet. 
     249 */ 
     250#pragma pack(1) 
     251typedef 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) 
     301AssertCompileSize(RTNETBOOTP, 0xec + 128); 
     302/** Pointer to a BOOTP / DHCP packet. */ 
     303typedef RTNETBOOTP *PRTNETBOOTP; 
     304/** Pointer to a const BOOTP / DHCP packet. */ 
     305typedef 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 */ 
     324typedef 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; 
     332AssertCompileSize(RTNETDHCPOPT, 2); 
     333/** Pointer to a DHCP option header. */ 
     334typedef RTNETDHCPOPT *PRTNETDHCPOPT; 
     335/** Pointer to a const DHCP option header. */ 
     336typedef 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 
     360RTDECL(bool) RTNetIPv4IsDHCPValid(PCRTNETUDP pUdpHdr, PCRTNETBOOTP pDhcp, size_t cbDhcp, uint8_t *pMsgType); 
     361 
    247362 
    248363/** 
    249364 * IPv4 DHCP packet. 
     365 * @obsolete Use RTNETBOOTP. 
    250366 */ 
    251367#pragma pack(1) 
    252368typedef struct RTNETDHCP 
    253369{ 
     370    /** 00 - The packet opcode. */ 
    254371    uint8_t         Op; 
    255372    /** Hardware address type. */ 
  • trunk/src/VBox/Runtime/common/checksum/ipv4.cpp

    r11044 r11049  
    549549} 
    550550 
     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 */ 
     571RTDECL(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 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy