VirtualBox

Ignore:
Timestamp:
Jul 31, 2008 9:19:52 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33944
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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette