VirtualBox

Changeset 17786 in vbox for trunk/src


Ignore:
Timestamp:
Mar 13, 2009 1:34:03 AM (16 years ago)
Author:
vboxsync
Message:

VBoxNetDHCP: made windows happy.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp

    r17782 r17786  
    3838#include <iprt/param.h>
    3939#include <iprt/getopt.h>
     40#include <iprt/string.h>
    4041
    4142#include <VBox/sup.h>
     
    379380    void                makeDhcpReply(uint8_t uMsgType, VBoxNetDhcpLease *pLease, PCRTNETBOOTP pDhcpMsg, size_t cb);
    380381
    381     VBoxNetDhcpLease   *findLeaseByMacAddress(PCRTMAC pMacAddress);
    382     VBoxNetDhcpLease   *findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress);
     382    VBoxNetDhcpLease   *findLeaseByMacAddress(PCRTMAC pMacAddress, bool fAnyState);
     383    VBoxNetDhcpLease   *findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress, bool fAnyState);
    383384    VBoxNetDhcpLease   *newLease(PCRTNETBOOTP pDhcpMsg, size_t cb);
    384385
     
    440441{
    441442    m_enmState = kState_Offer;
     443    m_xid = xid;
    442444    RTTimeNow(&m_ExpireTime);
    443445    RTTimeSpecAddSeconds(&m_ExpireTime, 60);
     
    538540    pDefCfg->m_DNSes.push_back(Addr);
    539541    pDefCfg->m_DomainName     = "vboxnetdhcp.org";
     542#if 0
    540543    pDefCfg->m_cSecLease      = 60*60; /* 1 hour */
     544#else
     545    pDefCfg->m_cSecLease      = 30; /* sec */
     546#endif
    541547    pDefCfg->m_TftpServer     = "10.0.2.3"; //??
    542548    this->addConfig(pDefCfg);
     
    942948        {
    943949            size_t  cb;
    944             void   *pv = VBoxNetUDPMatch(m_pIfBuf, 67 /* bootps */, &m_MacAddress,
     950            void   *pv = VBoxNetUDPMatch(m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m_MacAddress,
    945951                                         VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST | VBOXNETUDP_MATCH_CHECKSUM
    946952                                         | (m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
     
    10271033{
    10281034    /*
    1029      * First, see if there is already a lease for this client. It may have rebooted,
    1030      * crashed or whatever that have caused it to forget its existing lease.
    1031      * If none was found, create a new lease for it and then construct a reply.
    1032      */
    1033     VBoxNetDhcpLease *pLease = findLeaseByMacAddress(&pDhcpMsg->bp_chaddr.Mac);
    1034     if (    !pLease
    1035         ||  !pLease->isInCurrentConfig())
    1036         pLease = newLease(pDhcpMsg, cb);
     1035     * The newLease() method contains logic for finding current leases
     1036     * and reusing them in case the client is forgetful.
     1037     */
     1038    VBoxNetDhcpLease *pLease = newLease(pDhcpMsg, cb);
    10371039    if (!pLease)
    10381040        return false;
     
    10631065    /** @todo Probably need to match the server IP here to work correctly with
    10641066     *        other servers. */
    1065     /** @todo check this against the RFC and real code. the code is kind of
    1066      *        fishy... */
    1067 
    1068     /*
    1069      * Windows will reissue these requests when rejoining a network if it thinks it
    1070      * already has an address on the network. If we cannot find a valid lease,
    1071      * make a new one and return NAC.
    1072      */
    1073     RTNETADDRIPV4 IPv4Addr;
    1074     if (findOptionIPv4Addr(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cb, &IPv4Addr))
    1075     {
    1076         VBoxNetDhcpLease *pLease = findLeaseByIpv4AndMacAddresses(IPv4Addr, &pDhcpMsg->bp_chaddr.Mac);
    1077         if (    pLease
    1078             &&  pLease->isInCurrentConfig())
    1079         {
    1080             if (pLease->isBeingOffered())
     1067    /** @todo This code isn't entirely correct and quite a bit of a hack, but it
     1068     *        will have to do for now as the right thing (tm) is very complex.
     1069     *        Part of the fun is verifying that the request is something we can
     1070     *        and should handle. */
     1071
     1072    /*
     1073     * Try find the lease by the requested address + client MAC address.
     1074     */
     1075    VBoxNetDhcpLease   *pLease = NULL;
     1076    RTNETADDRIPV4       IPv4Addr;
     1077    bool                fReqAddr = findOptionIPv4Addr(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cb, &IPv4Addr);
     1078    if (fReqAddr)
     1079    {
     1080        fReqAddr = true;
     1081        pLease = findLeaseByIpv4AndMacAddresses(IPv4Addr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */);
     1082    }
     1083
     1084    /*
     1085     * Try find the lease by the client IP address + client MAC address.
     1086     */
     1087    if (    !pLease
     1088        &&  pDhcpMsg->bp_ciaddr.u)
     1089        pLease = findLeaseByIpv4AndMacAddresses(pDhcpMsg->bp_ciaddr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */);
     1090
     1091#if 0 /** @todo client id stuff - it doesn't make sense here imho, we need IP + MAC. What would make sense
     1092                though is to compare the client id with what we've got in the lease and use it to root out
     1093                bad requests. */
     1094    /*
     1095     * Try find the lease by using the client id.
     1096     */
     1097    if (!pLease)
     1098    {
     1099        size_t          cbClientID = 0;
     1100        uint8_t const  *pbClientID  = findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cb, &cbClientID);
     1101        if (    pbClientID
     1102            &&  cbClientID == sizeof(RTMAC) + 1
     1103            &&  pbClientID[0] == RTNET_ARP_ETHER
     1104            &&
     1105                )
     1106        {
     1107            pLease = findLeaseByIpv4AndMacAddresses(pDhcpMsg->bp_ciaddr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */);
     1108        }
     1109    }
     1110#endif
     1111
     1112    /*
     1113     * Validate the lease that's requested.
     1114     * We've already check the MAC and IP addresses.
     1115     */
     1116    bool fAckIt = false;
     1117    if (pLease)
     1118    {
     1119        if (pLease->isBeingOffered())
     1120        {
     1121            if (pLease->m_xid == pDhcpMsg->bp_xid)
     1122            {
     1123                fAckIt = true;
    10811124                debugPrint(2, true, "REQUEST for offered lease.");
    1082             else
    1083                 debugPrint(1, true, "REQUEST for lease not on offer.");
    1084 
    1085             /* Check if the xid matches, if it doesn't it's not our call. */
    1086 #if 0      /** @todo check how windows treats bp_xid here, it should match I think. If
    1087             *        it doesn't we've no way of filtering out broadcast replies to other
    1088             *        DHCP servers. Fix this later.
    1089             */
    1090             if (pDhcpMsg->bp_xid != pLease->m_xid)
    1091             {
    1092                 debugPrint(1, true, "bp_xid %#x != lease %#x", pDhcpMsg->bp_xid, pLease->m_xid);
    1093                 return true;
    1094             }
    1095 #endif
    1096             /* Check if the config has changed since the offer was given? NAK it then? */
    1097 
    1098             /*
    1099              * Ack it.
    1100              */
    1101             pLease->activate(pDhcpMsg->bp_xid);
    1102             makeDhcpReply(RTNET_DHCP_MT_ACK, pLease, pDhcpMsg, cb);
    1103         }
    1104         else
    1105         {
    1106             /*
    1107              * Try make a new offer and see if we get the requested IP and config, that
    1108              * will make the (windows) client happy apparently...
    1109              */
    1110             pLease = newLease(pDhcpMsg, cb);
    1111             if (    pLease
    1112                 &&  pLease->m_IPv4Address.u == IPv4Addr.u
    1113                 /** @todo match requested config later */)
    1114             {
    1115                 /* ACK it. */
    1116                 debugPrint(1, true, "REQUEST for lease not on offer, new lease matches.");
    11171125                pLease->activate();
    1118                 makeDhcpReply(RTNET_DHCP_MT_ACK, pLease, pDhcpMsg, cb);
    11191126            }
    11201127            else
    1121             {
    1122                 /* NAK it */
    1123                 debugPrint(1, true, "REQUEST for lease not on offer, NACnig it.");
    1124                 if (pLease)
    1125                     pLease->release();
    1126                 pLease->activate();
    1127                 makeDhcpReply(RTNET_DHCP_MT_NAC, NULL, pDhcpMsg, cb);
    1128             }
    1129         }
     1128                debugPrint(2, true, "REQUEST for offered lease, xid mismatch. Expected %#x, got %#x.",
     1129                           pLease->m_xid, pDhcpMsg->bp_xid);
     1130        }
     1131        else if (!pLease->isInCurrentConfig())
     1132            debugPrint(1, true, "REQUEST for obsolete lease -> NAK");
     1133        else if (fReqAddr != (pDhcpMsg->bp_ciaddr.u != 0)) // ???
     1134        {
     1135            /** @todo this ain't safe. */
     1136            debugPrint(1, true, "REQUEST for lease not on offer, assuming renewal. lease_xid=%#x bp_xid=%#x",
     1137                       pLease->m_xid, pDhcpMsg->bp_xid);
     1138            fAckIt = true;
     1139            pLease->activate(pDhcpMsg->bp_xid);
     1140        }
     1141        else
     1142            debugPrint(1, true, "REQUEST for lease not on offer, NAK it.");
     1143    }
     1144
     1145    /*
     1146     * NAK if if no lease was found.
     1147     */
     1148    if (fAckIt)
     1149    {
     1150        debugPrint(1, false, "ACK'ing DHCP_REQUEST");
     1151        makeDhcpReply(RTNET_DHCP_MT_ACK, pLease, pDhcpMsg, cb);
    11301152    }
    11311153    else
    1132         debugPrint(1, true, "No requested address option");
     1154    {
     1155        debugPrint(1, false, "NAK'ing DHCP_REQUEST");
     1156        makeDhcpReply(RTNET_DHCP_MT_NAC, NULL, pDhcpMsg, cb);
     1157    }
    11331158
    11341159    return true;
     
    11561181
    11571182    /** @todo this is not required in the initial implementation, do it later. */
     1183    debugPrint(1, true, "DECLINE is not implemented");
    11581184    return true;
    11591185}
     
    11921218
    11931219    /** @todo this is not required in the initial implementation, do it later. */
     1220    debugPrint(1, true, "RELEASE is not implemented");
    11941221    return true;
    11951222}
     
    12051232    uint8_t        *m_pbEnd;       /**< The end the current option space. */
    12061233    uint8_t        *m_pfOverload;  /**< Pointer to the flags of the overload option. */
     1234    uint8_t         m_fUsed;       /**< Overload fields that have been used. */
    12071235    PRTNETDHCPOPT   m_pOpt;        /**< The current option. */
    12081236    PRTNETBOOTP     m_pDhcp;       /**< The DHCP packet. */
     
    12151243        m_pbEnd((uint8_t *)pDhcp + cbDhcp),
    12161244        m_pfOverload(NULL),
     1245        m_fUsed(0),
    12171246        m_pOpt(NULL),
    12181247        m_pDhcp(pDhcp),
     
    12321261
    12331262    /**
     1263     * Try use the bp_file field.
     1264     * @returns true if not overloaded, false otherwise.
     1265     */
     1266    bool useBpFile(void)
     1267    {
     1268        if (    m_pfOverload
     1269            &&  (*m_pfOverload & 1))
     1270            return false;
     1271        m_fUsed |= 1 /* bp_file flag*/;
     1272        return true;
     1273    }
     1274
     1275
     1276    /**
    12341277     * Try overload more BOOTP fields
    12351278     */
     
    12391282        uint8_t    *pbNew;
    12401283        uint8_t    *pbNewEnd;
     1284        uint8_t     fField;
     1285        if (!(m_fUsed & 1))
     1286        {
     1287            fField     = 1;
     1288            pbNew      = &m_pDhcp->bp_file[0];
     1289            pbNewEnd   = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)];
     1290        }
     1291        else if (!(m_fUsed & 2))
     1292        {
     1293            fField     = 2;
     1294            pbNew      = &m_pDhcp->bp_sname[0];
     1295            pbNewEnd   = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)];
     1296        }
     1297        else
     1298            return false;
     1299
    12411300        if (!m_pfOverload)
    12421301        {
    12431302            /* Add an overload option. */
    12441303            *m_pbCur++ = RTNET_DHCP_OPT_OPTION_OVERLOAD;
    1245             *m_pbCur++ = 1;
     1304            *m_pbCur++ = fField;
    12461305            m_pfOverload = m_pbCur;
    12471306            *m_pbCur++ = 1;     /* bp_file flag */
    1248 
    1249             pbNew      = &m_pDhcp->bp_file[0];
    1250             pbNewEnd   = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)];
    1251         }
    1252         else if (!(*m_pfOverload & 2))
    1253         {
    1254             *m_pfOverload |= 2; /* bp_sname flag */
    1255 
    1256             pbNew      = &m_pDhcp->bp_sname[0];
    1257             pbNewEnd   = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)];
    12581307        }
    12591308        else
    1260             return false;
     1309            *m_pfOverload |= fField;
    12611310
    12621311        /* pad current option field */
     
    12641313            *m_pbCur++ = RTNET_DHCP_OPT_PAD; /** @todo not sure if this stuff is at all correct... */
    12651314
     1315        /* switch */
    12661316        m_pbCur = pbNew;
    12671317        m_pbEnd = pbNewEnd;
     
    12851335
    12861336        /* Check if we need to overload more stuff. */
    1287         if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 3)
     1337        if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + (m_pfOverload ? 1 : 3))
    12881338        {
    12891339            m_pOpt = NULL;
     
    12931343                AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
    12941344            }
    1295             if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 3)
     1345            if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 1)
    12961346            {
    12971347                m_fOverflowed = true;
     
    15111561    pReply->bp_ciaddr.u = 0;
    15121562    pReply->bp_yiaddr.u = pLease ? pLease->m_IPv4Address.u : 0xffffffff;
    1513     pReply->bp_siaddr.u = pLease && pLease->m_pCfg ? pLease->m_pCfg->m_TftpServerAddr.u : 0;
     1563    pReply->bp_siaddr.u = pLease && pLease->m_pCfg ? pLease->m_pCfg->m_TftpServerAddr.u : 0; /* (next server == TFTP)*/
    15141564    pReply->bp_giaddr.u = 0;
    15151565    memset(&pReply->bp_chaddr, '\0', sizeof(pReply->bp_chaddr));
     
    15431593
    15441594        /* The PXE config. */
     1595        if (pCfg->m_BootfileName.size())
     1596        {
     1597            if (Cursor.useBpFile())
     1598                RTStrPrintf((char *)&pReply->bp_file[0], sizeof(pReply->bp_file), "%s", pCfg->m_BootfileName.c_str());
     1599            else
     1600                Cursor.optStr(RTNET_DHCP_OPT_BOOTFILE_NAME, pCfg->m_BootfileName);
     1601        }
    15451602    }
    15461603
     
    15541611    int rc;
    15551612#if 0
    1556     if (pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)
     1613    if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */
    15571614    {
    15581615        RTNETADDRIPV4 IPv4AddrBrdCast;
     
    15741631
    15751632
    1576 
    15771633/**
    15781634 * Look up a lease by MAC address.
     
    15801636 * @returns Pointer to the lease if found, NULL if not found.
    15811637 * @param   pMacAddress             The mac address.
    1582  */
    1583 VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByMacAddress(PCRTMAC pMacAddress)
     1638 * @param   fAnyState       Any state.
     1639 */
     1640VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByMacAddress(PCRTMAC pMacAddress, bool fAnyState)
    15841641{
    15851642    size_t iLease = m_Leases.size();
     
    15901647            &&  pLease->m_MacAddress.au16[0] == pMacAddress->au16[0]
    15911648            &&  pLease->m_MacAddress.au16[1] == pMacAddress->au16[1]
    1592             &&  pLease->m_MacAddress.au16[2] == pMacAddress->au16[2])
     1649            &&  pLease->m_MacAddress.au16[2] == pMacAddress->au16[2]
     1650            &&  (   fAnyState
     1651                 || (pLease->m_enmState != VBoxNetDhcpLease::kState_Free)) )
    15931652            return pLease;
    15941653    }
     
    16041663 * @param   IPv4Addr        The IPv4 address.
    16051664 * @param   pMacAddress     The mac address.
    1606  */
    1607 VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress)
     1665 * @param   fAnyState       Any state.
     1666 */
     1667VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress, bool fAnyState)
    16081668{
    16091669    size_t iLease = m_Leases.size();
     
    16151675            &&  pLease->m_MacAddress.au16[0] == pMacAddress->au16[0]
    16161676            &&  pLease->m_MacAddress.au16[1] == pMacAddress->au16[1]
    1617             &&  pLease->m_MacAddress.au16[2] == pMacAddress->au16[2])
     1677            &&  pLease->m_MacAddress.au16[2] == pMacAddress->au16[2]
     1678            &&  (   fAnyState
     1679                 || (pLease->m_enmState != VBoxNetDhcpLease::kState_Free)) )
    16181680            return pLease;
    16191681    }
     
    18441906        {
    18451907            const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
    1846             RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d\n",
     1908            RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d xid=%#x\n",
    18471909                         pszMsg,
    18481910                         &m_pCurMsg->bp_chaddr,
    18491911                         m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],
    18501912                         m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],
    1851                          m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3]);
     1913                         m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3],
     1914                         m_pCurMsg->bp_xid);
    18521915        }
    18531916    }
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