VirtualBox

Changeset 64299 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Oct 17, 2016 1:56:50 PM (8 years ago)
Author:
vboxsync
Message:

bugref:8563: bootp fixes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/bootp.c

    r63562 r64299  
    4949    uint32_t xid;
    5050    bool allocated;
    51     uint8_t macaddr[6];
     51    uint8_t macaddr[ETH_ALEN];
    5252    struct in_addr addr;
    5353    int number;
     
    6363static void bootp_reply(PNATState pData, struct mbuf *m0, int offReply, uint16_t flags);
    6464
    65 static uint8_t *dhcp_find_option(uint8_t *vend, uint8_t tag)
    66 {
    67     uint8_t *q = vend;
    68     uint8_t len;
    69     /** @todo magic validation */
    70     q += 4; /*magic*/
    71     while(*q != RFC1533_END)
    72     {
    73         if (*q == RFC1533_PAD)
    74         {
    75             q++;
     65
     66static uint8_t *dhcp_find_option(uint8_t *vendor, size_t vlen, uint8_t tag, ssize_t checklen)
     67{
     68    uint8_t *q = vendor;
     69    size_t len = vlen;
     70
     71    q += sizeof(rfc1533_cookie);
     72    len -= sizeof(rfc1533_cookie);
     73
     74    while (len > 0)
     75    {
     76        uint8_t *optptr = q;
     77        uint8_t opt;
     78        uint8_t optlen;
     79
     80        opt = *q++;
     81        --len;
     82
     83        if (opt == RFC1533_END)
     84            break;
     85
     86        if (opt == RFC1533_PAD)
    7687            continue;
    77         }
    78         if (*q == tag)
    79             return q;
    80         q++;
    81         len = *q;
    82         q += 1 + len;
    83     }
     88
     89        if (len == 0)
     90            break;              /* no option length byte */
     91
     92        optlen = *q++;
     93        --len;
     94
     95        if (len < optlen)
     96            break;              /* option value truncated */
     97
     98        if (opt == tag)
     99        {
     100            if (checklen > 0 && optlen != checklen)
     101                break;          /* wrong option size */
     102
     103            return optptr;
     104        }
     105
     106        q += optlen;
     107        len -= optlen;
     108    }
     109
    84110    return NULL;
    85111}
     
    399425};
    400426
    401 static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, struct mbuf *m)
     427static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, size_t vlen, struct mbuf *m)
    402428{
    403429    BOOTPClient *bc = NULL;
     
    410436
    411437    /* need to understand which type of request we get */
    412     req_ip = dhcp_find_option(&bp->bp_vend[0], RFC2132_REQ_ADDR);
    413     server_ip = dhcp_find_option(&bp->bp_vend[0], RFC2132_SRV_ID);
     438    req_ip = dhcp_find_option(bp->bp_vend, vlen,
     439                              RFC2132_REQ_ADDR, sizeof(struct in_addr));
     440    server_ip = dhcp_find_option(bp->bp_vend, vlen,
     441                                 RFC2132_SRV_ID, sizeof(struct in_addr));
    414442
    415443    bc = find_addr(pData, &daddr, bp->bp_hwaddr);
     
    498526               }
    499527
    500                Assert((bp->bp_hlen == ETH_ALEN));
    501                memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);
     528               memcpy(bc->macaddr, bp->bp_hwaddr, ETH_ALEN);
    502529               bc->addr.s_addr = bp->bp_ciaddr.s_addr;
    503530            }
     
    544571                }
    545572            }
    546             Assert((bp->bp_hlen == ETH_ALEN));
    547             memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);
     573
     574            memcpy(bc->macaddr, bp->bp_hwaddr, ETH_ALEN);
    548575            bc->addr.s_addr = ui32;
    549576            break;
     
    584611                return -1;
    585612            }
    586             memcpy(bc->macaddr, bp->bp_hwaddr, 6);
     613            memcpy(bc->macaddr, bp->bp_hwaddr, ETH_ALEN);
    587614        }
    588615
     
    679706 *
    680707 */
    681 static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size)
     708static void dhcp_decode(PNATState pData, struct bootp_t *bp, size_t vlen)
    682709{
    683710    const uint8_t *pu8RawDhcpObject;
     
    688715    struct mbuf *m = NULL;
    689716
    690     pu8RawDhcpObject = buf;
    691     if (size < 5)
     717    if (memcmp(bp->bp_vend, rfc1533_cookie, sizeof(rfc1533_cookie)) != 0)
    692718        return;
    693719
    694     if (memcmp(pu8RawDhcpObject, rfc1533_cookie, 4) != 0)
     720    pu8RawDhcpObject = dhcp_find_option(bp->bp_vend, vlen, RFC2132_MSG_TYPE, 1);
     721    if (pu8RawDhcpObject == NULL)
    695722        return;
    696 
    697     /* note: pu8RawDhcpObject doesn't point to parameter buf */
    698     pu8RawDhcpObject = dhcp_find_option(bp->bp_vend, RFC2132_MSG_TYPE);
    699     Assert(pu8RawDhcpObject);
    700     if (!pu8RawDhcpObject)
     723    if (pu8RawDhcpObject[1] != 1) /* option length */
    701724        return;
     725
    702726    /**
    703727     * We're going update dns list at least once per DHCP transaction (!not on every operation
     
    720744            || pData->fUseHostResolver))
    721745    {
    722         uint8_t i = 2; /* i = 0 - tag, i == 1 - length */
    723         parameter_list = dhcp_find_option(&bp->bp_vend[0], RFC2132_PARAM_LIST);
    724         for (;parameter_list && i < parameter_list[1]; ++i)
    725         {
    726             if (parameter_list[i] == RFC1533_DNS)
     746        uint8_t i;
     747
     748        parameter_list = dhcp_find_option(bp->bp_vend, vlen, RFC2132_PARAM_LIST, -1);
     749        for (i = 0; parameter_list && i < parameter_list[1]; ++i)
     750        {
     751            if (parameter_list[2 + i] == RFC1533_DNS)
    727752            {
    728753                /* XXX: How differs it from host Suspend/Resume? */
     
    754779
    755780        case DHCPREQUEST:
    756             rc = dhcp_decode_request(pData, bp, m);
     781            rc = dhcp_decode_request(pData, bp, vlen, m);
    757782            if (rc > 0)
    758783                goto reply;
     
    765790
    766791        case DHCPDECLINE:
    767             /* note: pu8RawDhcpObject doesn't point to DHCP header, now it's expected it points
    768              * to Dhcp Option RFC2132_REQ_ADDR
    769              */
    770             pu8RawDhcpObject = dhcp_find_option(&bp->bp_vend[0], RFC2132_REQ_ADDR);
    771             if (!pu8RawDhcpObject)
     792            pu8RawDhcpObject = dhcp_find_option(bp->bp_vend, vlen,
     793                                                RFC2132_REQ_ADDR, sizeof(struct in_addr));
     794            if (pu8RawDhcpObject == NULL)
    772795            {
    773796                Log(("NAT: RFC2132_REQ_ADDR not found\n"));
    774797                break;
    775798            }
     799
    776800            req_ip.s_addr = *(uint32_t *)(pu8RawDhcpObject + 2);
    777801            rc = bootp_cache_lookup_ether_by_ip(pData, req_ip.s_addr, NULL);
     
    843867{
    844868    struct bootp_t *bp = mtod(m, struct bootp_t *);
    845 
    846     if (bp->bp_op == BOOTP_REQUEST)
    847         dhcp_decode(pData, bp, bp->bp_vend, DHCP_OPT_LEN);
     869    u_int mlen = m_length(m, NULL);
     870    size_t vlen;
     871
     872    if (mlen < RT_OFFSETOF(struct bootp_t, bp_vend) + BOOTP_VENDOR_LEN)
     873        return;
     874
     875    if (bp->bp_op != BOOTP_REQUEST)
     876        return;
     877
     878    if (bp->bp_htype != RTNET_ARP_ETHER)
     879        return;
     880
     881    if (bp->bp_hlen != ETH_ALEN)
     882        return;
     883
     884    if (bp->bp_hops != 0)
     885        return;
     886
     887    vlen = mlen - RT_OFFSETOF(struct bootp_t, bp_vend);
     888    dhcp_decode(pData, bp, vlen);
    848889}
    849890
Note: See TracChangeset for help on using the changeset viewer.

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