VirtualBox

Ignore:
Timestamp:
Jul 6, 2019 11:42:51 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131858
Message:

Dhcpd: Went over the DhcpMessage a little as well as revisiting the lease reading code in the database. Logging is LogRel() or similar, no cout, RTPrintf or similar. The debug & release loggers can both output to stderr/out/whatever as needed. bugref:9288

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/Dhcpd/Db.cpp

    r79563 r79568  
    159159 * Serializes the binding to XML for the lease database.
    160160 *
    161  * @throw  std::bad_alloc
     161 * @throw   std::bad_alloc
     162 * @note    DHCPServerImpl.cpp contains a reader, keep it in sync.
    162163 */
    163164void Binding::toXML(xml::ElementNode *pElmParent) const
     
    204205 * Deserializes the binding from the XML lease database.
    205206 *
    206  * @param   pElmLease   The "Lease" element.
     207 * @param   pElmLease   The "Lease" element to serialize into.
    207208 * @return  Pointer to the resulting binding, NULL on failure.
    208209 * @throw   std::bad_alloc
     210 * @note    DHCPServerImpl.cpp contains a similar reader, keep it in sync.
    209211 */
    210212Binding *Binding::fromXML(const xml::ElementNode *pElmLease)
    211213{
    212     /* Lease/@network seems to always have bogus value, ignore it. */
    213 
    214     /*
    215      * Lease/@mac
    216      */
    217     RTCString strMac;
    218     bool fHasMac = pElmLease->getAttributeValue("mac", &strMac);
    219     if (!fHasMac)
    220         return NULL;
     214    /* Note! Lease/@network seems to always have bogus value, ignore it. */
     215    /* Note! We parse the mandatory attributes and elements first, then
     216             the optional ones.  This means things appear a little jumbled. */
     217
     218    /*
     219     * Lease/@mac - mandatory.
     220     */
     221    const char *pszMacAddress = pElmLease->findAttributeValue("mac");
     222    if (!pszMacAddress)
     223        DHCP_LOG_RET_NULL(("Binding::fromXML: <Lease> element without 'mac' attribute! Skipping lease.\n"));
    221224
    222225    RTMAC mac;
    223     int rc = RTNetStrToMacAddr(strMac.c_str(), &mac);
     226    int rc = RTNetStrToMacAddr(pszMacAddress, &mac);
    224227    if (RT_FAILURE(rc))
    225         return NULL;
    226 
    227     OptClientId id;
    228     RTCString strId;
    229     bool fHasId = pElmLease->getAttributeValue("id", &strId);
    230     if (fHasId)
    231     {
    232         /*
    233          * Decode from "de:ad:be:ef".
    234          */
    235         /** @todo RTStrConvertHexBytes() doesn't grok colons */
    236         size_t   cbBytes = strId.length() / 2;
    237         uint8_t *pbBytes = new uint8_t[cbBytes];
    238         rc = RTStrConvertHexBytes(strId.c_str(), pbBytes, cbBytes, 0);
    239         if (RT_SUCCESS(rc))
    240         {
    241             try
    242             {
    243                 std::vector<uint8_t> rawopt(pbBytes, pbBytes + cbBytes);
    244                 id = OptClientId(rawopt);
    245             }
    246             catch (std::bad_alloc &)
    247             {
    248                 delete[] pbBytes;
    249                 throw;
    250             }
    251         }
    252         delete[] pbBytes;
    253     }
    254 
    255     /*
    256      * Lease/@state - not present in old leases file.  We will try to
    257      * infer from lease time below.
    258      */
    259     RTCString strState;
    260     bool fHasState = pElmLease->getAttributeValue("state", &strState);
    261 
    262     /*
    263      * Lease/Address
    264      */
    265     const xml::ElementNode *ndAddress = pElmLease->findChildElement("Address");
    266     if (ndAddress == NULL)
    267         return NULL;
    268 
    269     /*
    270      * Lease/Address/@value
    271      */
    272     RTCString strAddress;
    273     bool fHasValue = ndAddress->getAttributeValue("value", &strAddress);
    274     if (!fHasValue)
    275         return NULL;
     228        DHCP_LOG_RET_NULL(("Binding::fromXML: Malformed mac address attribute value '%s': %Rrc - Skipping lease.\n",
     229                           pszMacAddress, rc));
     230
     231    /*
     232     * Lease/Address/@value - mandatory.
     233     */
     234    const char *pszAddress = pElmLease->findChildElementAttributeValue("Address", "value");
     235    if (!pszAddress)
     236        DHCP_LOG_RET_NULL(("Binding::fromXML: Could not find <Address> with a 'value' attribute! Skipping lease.\n"));
    276237
    277238    RTNETADDRIPV4 addr;
    278     rc = RTNetStrToIPv4Addr(strAddress.c_str(), &addr);
     239    rc = RTNetStrToIPv4Addr(pszAddress, &addr);
    279240    if (RT_FAILURE(rc))
    280         return NULL;
    281 
    282     /*
    283      * Lease/Time
    284      */
    285     const xml::ElementNode *ndTime = pElmLease->findChildElement("Time");
    286     if (ndTime == NULL)
    287         return NULL;
    288 
    289     /*
    290      * Lease/Time/@issued
    291      */
    292     int64_t issued;
    293     bool fHasIssued = ndTime->getAttributeValue("issued", &issued);
    294     if (!fHasIssued)
    295         return NULL;
    296 
    297     /*
    298      * Lease/Time/@expiration
    299      */
    300     uint32_t duration;
    301     bool fHasExpiration = ndTime->getAttributeValue("expiration", &duration);
    302     if (!fHasExpiration)
    303         return NULL;
     241        DHCP_LOG_RET_NULL(("Binding::fromXML: Malformed IPv4 address value '%s': %Rrc - Skipping lease.\n", pszAddress, rc));
     242
     243    /*
     244     * Lease/Time - mandatory.
     245     */
     246    const xml::ElementNode *pElmTime = pElmLease->findChildElement("Time");
     247    if (pElmTime == NULL)
     248        DHCP_LOG_RET_NULL(("Binding::fromXML: No <Time> element under <Lease mac=%RTmac>! Skipping lease.\n", &mac));
     249
     250    /*
     251     * Lease/Time/@issued - mandatory.
     252     */
     253    int64_t secIssued;
     254    if (!pElmTime->getAttributeValue("issued", &secIssued))
     255        DHCP_LOG_RET_NULL(("Binding::fromXML: <Time> element for %RTmac has no valid 'issued' attribute! Skipping lease.\n", &mac));
     256
     257    /*
     258     * Lease/Time/@expiration - mandatory.
     259     */
     260    uint32_t cSecToLive;
     261    if (!pElmTime->getAttributeValue("expiration", &cSecToLive))
     262        DHCP_LOG_RET_NULL(("Binding::fromXML: <Time> element for %RTmac has no valid 'expiration' attribute! Skipping lease.\n", &mac));
    304263
    305264    std::unique_ptr<Binding> b(new Binding(addr));
    306     b->m_id = ClientId(mac, id);
    307 
    308     if (fHasState)
    309     {
    310         b->m_issued = Timestamp::absSeconds(issued);
    311         b->m_secLease = duration;
    312         b->setState(strState.c_str());
     265
     266    /*
     267     * Lease/@state - mandatory but not present in old leases file, so pretent
     268     *                we're loading an expired one if absent.
     269     */
     270    const char *pszState = pElmLease->findAttributeValue("state");
     271    if (pszState)
     272    {
     273        b->m_issued = Timestamp::absSeconds(secIssued);
     274        b->setState(pszState);
    313275    }
    314276    else
    315277    {   /** @todo XXX: old code wrote timestamps instead of absolute time. */
    316278        /* pretend that lease has just ended */
    317         Timestamp fakeIssued = Timestamp::now();
    318         fakeIssued.subSeconds(duration);
    319         b->m_issued = fakeIssued;
    320         b->m_secLease = duration;
    321         b->m_state = Binding::EXPIRED;
    322     }
     279        LogRel(("Binding::fromXML: No 'state' attribute for <Lease mac=%RTmac> (ts=%RI64 ttl=%RU32)! Assuming EXPIRED.\n",
     280                &mac, secIssued, cSecToLive));
     281        b->m_issued = Timestamp::now().subSeconds(cSecToLive);
     282        b->m_state  = Binding::EXPIRED;
     283    }
     284    b->m_secLease   = cSecToLive;
     285
     286
     287    /*
     288     * Lease/@id - optional, ignore if bad.
     289     * Value format: "deadbeef..." or "de:ad:be:ef...".
     290     */
     291    const char *pszClientId = pElmLease->findAttributeValue("id");
     292    if (pszClientId)
     293    {
     294        uint8_t abBytes[255];
     295        size_t  cbActual;
     296        rc = RTStrConvertHexBytesEx(pszClientId, abBytes, sizeof(abBytes), RTSTRCONVERTHEXBYTES_F_SEP_COLON, NULL, &cbActual);
     297        if (RT_SUCCESS(rc))
     298        {
     299            b->m_id = ClientId(mac, OptClientId(std::vector<uint8_t>(&abBytes[0], &abBytes[cbActual]))); /* throws bad_alloc */
     300            if (rc != VINF_BUFFER_UNDERFLOW && rc != VINF_SUCCESS)
     301                LogRel(("Binding::fromXML: imperfect 'id' attribute: rc=%Rrc, cbActual=%u, '%s'\n", rc, cbActual, pszClientId));
     302        }
     303        else
     304        {
     305            LogRel(("Binding::fromXML: ignoring malformed 'id' attribute: rc=%Rrc, cbActual=%u, '%s'\n",
     306                    rc, cbActual, pszClientId));
     307            b->m_id = ClientId(mac, OptClientId());
     308        }
     309    }
     310    else
     311        b->m_id = ClientId(mac, OptClientId());
    323312
    324313    return b.release();
     
    433422
    434423    if (addr.u != 0)
    435         LogDHCP(("> allocateAddress %RTnaipv4 to client %R[id]\n", addr.u, &id));
     424        LogRel(("> allocateAddress %RTnaipv4 to client %R[id]\n", addr.u, &id));
    436425    else
    437         LogDHCP(("> allocateAddress to client %R[id]\n", &id));
     426        LogRel(("> allocateAddress to client %R[id]\n", &id));
    438427
    439428    /*
     
    456445        if (b->m_id == id)
    457446        {
    458             LogDHCP(("> ... found existing binding %R[binding]\n", b));
     447            LogRel(("> ... found existing binding %R[binding]\n", b));
    459448            return b;
    460449        }
     
    464453            Assert(addrBinding == NULL);
    465454            addrBinding = b;
    466             LogDHCP(("> .... noted existing binding %R[binding]\n", addrBinding));
     455            LogRel(("> .... noted existing binding %R[binding]\n", addrBinding));
    467456        }
    468457
     
    473462            {
    474463                freeBinding = b;
    475                 LogDHCP(("> .... noted free binding %R[binding]\n", freeBinding));
     464                LogRel(("> .... noted free binding %R[binding]\n", freeBinding));
    476465                continue;
    477466            }
     
    485474                {
    486475                    reuseBinding = b;
    487                     LogDHCP(("> .... noted released binding %R[binding]\n", reuseBinding));
     476                    LogRel(("> .... noted released binding %R[binding]\n", reuseBinding));
    488477                }
    489478            }
     
    495484                {
    496485                    reuseBinding = b;
    497                     LogDHCP(("> .... noted expired binding %R[binding]\n", reuseBinding));
     486                    LogRel(("> .... noted expired binding %R[binding]\n", reuseBinding));
    498487                }
    499488            }
     
    510499            addrBinding = i_createBinding(addr, id);
    511500            Assert(addrBinding != NULL);
    512             LogDHCP(("> .... creating new binding for this address %R[binding]\n", addrBinding));
     501            LogRel(("> .... creating new binding for this address %R[binding]\n", addrBinding));
    513502            return addrBinding;
    514503        }
     
    516505        if (addrBinding->m_state <= Binding::EXPIRED) /* not in use */
    517506        {
    518             LogDHCP(("> .... reusing %s binding for this address\n", addrBinding->stateName()));
     507            LogRel(("> .... reusing %s binding for this address\n", addrBinding->stateName()));
    519508            addrBinding->giveTo(id);
    520509            return addrBinding;
    521510        }
    522         LogDHCP(("> .... cannot reuse %s binding for this address\n", addrBinding->stateName()));
     511        LogRel(("> .... cannot reuse %s binding for this address\n", addrBinding->stateName()));
    523512    }
    524513
     
    530519    {
    531520        idBinding = freeBinding;
    532         LogDHCP(("> .... reusing free binding\n"));
     521        LogRel(("> .... reusing free binding\n"));
    533522    }
    534523    else
     
    536525        idBinding = i_createBinding();
    537526        if (idBinding != NULL)
    538             LogDHCP(("> .... creating new binding\n"));
     527            LogRel(("> .... creating new binding\n"));
    539528        else
    540529        {
    541530            idBinding = reuseBinding;
    542531            if (idBinding != NULL)
    543                 LogDHCP(("> .... reusing %s binding %R[binding]\n", reuseBinding->stateName(), reuseBinding));
     532                LogRel(("> .... reusing %s binding %R[binding]\n", reuseBinding->stateName(), reuseBinding));
    544533            else
    545             {
    546                 LogDHCP(("> .... failed to allocate binding\n"));
    547                 return NULL;
    548             }
     534                DHCP_LOG_RET_NULL(("> .... failed to allocate binding\n"));
    549535        }
    550536    }
    551537
    552538    idBinding->giveTo(id);
    553     LogDHCP(("> .... allocated %R[binding]\n", idBinding));
     539    LogRel(("> .... allocated %R[binding]\n", idBinding));
    554540
    555541    return idBinding;
     
    576562        if (req.messageType() == RTNET_DHCP_MT_DISCOVER)
    577563        {
    578             LogDHCP(("DISCOVER: ignoring invalid requested address\n"));
     564            LogRel(("DISCOVER: ignoring invalid requested address\n"));
    579565            reqAddr = OptRequestedAddress();
    580566        }
    581567        else
    582         {
    583             LogDHCP(("rejecting invalid requested address\n"));
    584             return NULL;
    585         }
     568            DHCP_LOG_RET_NULL(("rejecting invalid requested address\n"));
    586569    }
    587570
     
    621604    if (!addressBelongs(pNewBinding->m_addr))
    622605    {
    623         LogDHCP(("Binding for out of range address %RTnaipv4 ignored\n", pNewBinding->m_addr.u));
     606        LogRel(("Binding for out of range address %RTnaipv4 ignored\n", pNewBinding->m_addr.u));
    624607        return VERR_OUT_OF_RANGE;
    625608    }
     
    631614        if (pNewBinding->m_addr.u == b->m_addr.u)
    632615        {
    633             LogDHCP(("> ADD: %R[binding]\n", pNewBinding));
    634             LogDHCP(("> .... duplicate ip: %R[binding]\n", b));
     616            LogRel(("> ADD: %R[binding]\n", pNewBinding));
     617            LogRel(("> .... duplicate ip: %R[binding]\n", b));
    635618            return VERR_DUPLICATE;
    636619        }
     
    638621        if (pNewBinding->m_id == b->m_id)
    639622        {
    640             LogDHCP(("> ADD: %R[binding]\n", pNewBinding));
    641             LogDHCP(("> .... duplicate id: %R[binding]\n", b));
     623            LogRel(("> ADD: %R[binding]\n", pNewBinding));
     624            LogRel(("> .... duplicate id: %R[binding]\n", b));
    642625            return VERR_DUPLICATE;
    643626        }
     
    734717int Db::writeLeases(const RTCString &strFilename) const RT_NOEXCEPT
    735718{
    736     LogDHCP(("writing leases to %s\n", strFilename.c_str()));
     719    LogRel(("writing leases to %s\n", strFilename.c_str()));
    737720
    738721    /** @todo This could easily be written directly to the file w/o going thru
     
    777760    catch (const xml::EIPRTFailure &e)
    778761    {
    779         LogDHCP(("%s\n", e.what()));
     762        LogRel(("%s\n", e.what()));
    780763        return e.rc();
    781764    }
    782765    catch (const RTCError &e)
    783766    {
    784         LogDHCP(("%s\n", e.what()));
     767        LogRel(("%s\n", e.what()));
    785768        return VERR_GENERAL_FAILURE;
    786769    }
    787770    catch (...)
    788771    {
    789         LogDHCP(("Unknown exception while writing '%s'\n", strFilename.c_str()));
     772        LogRel(("Unknown exception while writing '%s'\n", strFilename.c_str()));
    790773        return VERR_UNEXPECTED_EXCEPTION;
    791774    }
     
    806789int Db::loadLeases(const RTCString &strFilename) RT_NOEXCEPT
    807790{
    808     LogDHCP(("loading leases from %s\n", strFilename.c_str()));
     791    LogRel(("loading leases from %s\n", strFilename.c_str()));
    809792
    810793    /*
     
    819802    catch (const xml::EIPRTFailure &e)
    820803    {
    821         LogDHCP(("%s\n", e.what()));
     804        LogRel(("%s\n", e.what()));
    822805        return e.rc();
    823806    }
    824807    catch (const RTCError &e)
    825808    {
    826         LogDHCP(("%s\n", e.what()));
     809        LogRel(("%s\n", e.what()));
    827810        return VERR_GENERAL_FAILURE;
    828811    }
    829812    catch (...)
    830813    {
    831         LogDHCP(("Unknown exception while reading and parsing '%s'\n", strFilename.c_str()));
     814        LogRel(("Unknown exception while reading and parsing '%s'\n", strFilename.c_str()));
    832815        return VERR_UNEXPECTED_EXCEPTION;
    833816    }
     
    839822    if (!pElmRoot)
    840823    {
    841         LogDHCP(("No root element in '%s'\n", strFilename.c_str()));
     824        LogRel(("No root element in '%s'\n", strFilename.c_str()));
    842825        return VERR_NOT_FOUND;
    843826    }
    844827    if (!pElmRoot->nameEquals("Leases"))
    845828    {
    846         LogDHCP(("No root element is not 'Leases' in '%s', but '%s'\n", strFilename.c_str(), pElmRoot->getName()));
     829        LogRel(("No root element is not 'Leases' in '%s', but '%s'\n", strFilename.c_str(), pElmRoot->getName()));
    847830        return VERR_NOT_FOUND;
    848831    }
     
    864847        }
    865848        else
    866             LogDHCP(("Ignoring unexpected element '%s' under 'Leases'...\n", pElmLease->getName()));
     849            LogRel(("Ignoring unexpected element '%s' under 'Leases'...\n", pElmLease->getName()));
    867850    }
    868851
     
    892875        bool fExpired = pBinding->expire();
    893876        if (!fExpired)
    894             LogDHCP(("> LOAD:         lease %R[binding]\n", pBinding));
     877            LogRel(("> LOAD:         lease %R[binding]\n", pBinding));
    895878        else
    896             LogDHCP(("> LOAD: EXPIRED lease %R[binding]\n", pBinding));
     879            LogRel(("> LOAD: EXPIRED lease %R[binding]\n", pBinding));
    897880
    898881        int rc = i_addBinding(pBinding);
     
    901884        return rc;
    902885    }
    903     LogDHCP(("> LOAD: failed to load lease!\n"));
     886    LogRel(("> LOAD: failed to load lease!\n"));
    904887    return VERR_PARSE_ERROR;
    905888}
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