VirtualBox

Changeset 79529 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 4, 2019 6:17:50 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131814
Message:

Dhcpd: Went over the Db and IPv4Pool code adding comments and and such. bugref:9288

Location:
trunk/src/VBox/NetworkServices/Dhcpd
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/Dhcpd/ClientId.h

    r79524 r79529  
    5757    const OptClientId &id() const   { return m_id; }
    5858
    59     /** @name String formatting stuff
     59    /** @name String formatting of %R[id].
    6060     * @{ */
    61     static void registerFormat(); /* %R[id] */
     61    static void registerFormat();
    6262private:
    6363    static DECLCALLBACK(size_t) rtStrFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char *pszType,
  • trunk/src/VBox/NetworkServices/Dhcpd/Db.cpp

    r79526 r79529  
    1616 */
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include "DhcpdInternal.h"
    1923#include <iprt/errcore.h>
    20 #include <iprt/stream.h>
    2124
    2225#include "Db.h"
    2326
    2427
    25 Db::Db()
    26   : m_pConfig(NULL)
    27 {
    28     return;
    29 }
    30 
    31 
    32 Db::~Db()
    33 {
    34     /** @todo free bindings */
    35 }
    36 
    37 
    38 int Db::init(const Config *pConfig)
    39 {
    40     Binding::registerFormat();
    41 
    42     m_pConfig = pConfig;
    43 
    44     m_pool.init(pConfig->getIPv4PoolFirst(),
    45                 pConfig->getIPv4PoolLast());
    46 
    47     return VINF_SUCCESS;
    48 }
    49 
    50 
     28/*********************************************************************************************************************************
     29*   Global Variables                                                                                                             *
     30*********************************************************************************************************************************/
     31/** Indicates whether has been called successfully yet. */
    5132bool Binding::g_fFormatRegistered = false;
    5233
    5334
     35/**
     36 * Registers the ClientId format type callback ("%R[binding]").
     37 */
    5438void Binding::registerFormat()
    5539{
    56     if (g_fFormatRegistered)
    57         return;
    58 
    59     int rc = RTStrFormatTypeRegister("binding", rtStrFormat, NULL);
    60     AssertRC(rc);
    61 
    62     g_fFormatRegistered = true;
    63 }
    64 
    65 
     40    if (!g_fFormatRegistered)
     41    {
     42        int rc = RTStrFormatTypeRegister("binding", rtStrFormat, NULL);
     43        AssertRC(rc);
     44        g_fFormatRegistered = true;
     45    }
     46}
     47
     48
     49/**
     50 * @callback_method_impl{FNRTSTRFORMATTYPE, Formats ClientId via "%R[binding]".}
     51 */
    6652DECLCALLBACK(size_t)
    6753Binding::rtStrFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
     
    7056                     void *pvUser)
    7157{
    72     const Binding *b = static_cast<const Binding *>(pvValue);
    73     size_t cb = 0;
    7458
    7559    AssertReturn(strcmp(pszType, "binding") == 0, 0);
     
    7963    RT_NOREF(pvUser);
    8064
     65    const Binding *b = static_cast<const Binding *>(pvValue);
    8166    if (b == NULL)
    82     {
    83         return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
    84                            "<NULL>");
    85     }
    86 
    87     cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
    88                       "%RTnaipv4", b->m_addr.u);
    89 
     67        return pfnOutput(pvArgOutput, RT_STR_TUPLE("<NULL>"));
     68
     69    size_t cb = RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%RTnaipv4", b->m_addr.u);
    9070    if (b->m_state == Binding::FREE)
    91     {
    92         cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
    93                           " free");
    94     }
     71        cb += pfnOutput(pvArgOutput, RT_STR_TUPLE(" free"));
    9572    else
    9673    {
    97         cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
    98                           " to %R[id], %s, valid from ",
    99                           &b->m_id, b->stateName());
     74        cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, " to %R[id], %s, valid from ", &b->m_id, b->stateName());
    10075
    10176        Timestamp tsIssued = b->issued();
    10277        cb += tsIssued.strFormatHelper(pfnOutput, pvArgOutput);
    10378
    104         cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
    105                           " for %ds until ",
    106                           b->leaseTime());
     79        cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, " for %ds until ", b->leaseTime());
    10780
    10881        Timestamp tsValid = b->issued();
     
    11689const char *Binding::stateName() const
    11790{
    118     switch (m_state) {
    119     case FREE:
    120         return "free";
    121     case RELEASED:
    122         return "released";
    123     case EXPIRED:
    124         return "expired";
    125     case OFFERED:
    126         return "offered";
    127     case ACKED:
    128         return "acked";
    129     default:
    130         return "released";
     91    switch (m_state)
     92    {
     93        case FREE:
     94            return "free";
     95        case RELEASED:
     96            return "released";
     97        case EXPIRED:
     98            return "expired";
     99        case OFFERED:
     100            return "offered";
     101        case ACKED:
     102            return "acked";
     103        default:
     104            AssertMsgFailed(("%d\n", m_state));
     105            return "released";
    131106    }
    132107}
     
    146121        m_state = Binding::ACKED;
    147122    else
     123    {
     124        AssertMsgFailed(("%d\n", m_state));
    148125        m_state = Binding::RELEASED;
     126    }
    149127
    150128    return *this;
     
    152130
    153131
    154 bool Binding::expire(Timestamp deadline)
     132/**
     133 * Expires the binding if it's past the specified deadline.
     134 *
     135 * @returns False if already expired, released or freed, otherwise true (i.e.
     136 *          does not indicate whether action was taken or not).
     137 * @param   tsDeadline          The expiry deadline to use.
     138 */
     139bool Binding::expire(Timestamp tsDeadline)
    155140{
    156141    if (m_state <= Binding::EXPIRED)
    157142        return false;
    158143
    159     Timestamp t = m_issued;
    160     t.addSeconds(m_secLease);
    161 
    162     if (t < deadline)
     144    Timestamp tsExpire = m_issued;
     145    tsExpire.addSeconds(m_secLease);
     146
     147    if (tsExpire < tsDeadline)
    163148    {
    164149        if (m_state == Binding::OFFERED)
     
    171156
    172157
    173 int Binding::toXML(xml::ElementNode *ndParent) const
    174 {
    175     int rc;
    176 
     158/**
     159 * Serializes the binding to XML for the lease database.
     160 *
     161 * @throw  std::bad_alloc
     162 */
     163void Binding::toXML(xml::ElementNode *pElmParent) const
     164{
    177165    /*
    178166     * Lease
    179167     */
    180     xml::ElementNode *ndLease = ndParent->createChild("Lease");
    181     if (ndLease == NULL)
    182         return VERR_GENERAL_FAILURE;
    183 
    184     /* XXX: arrange for lease to get deleted if anything below fails */
    185 
    186 
    187     ndLease->setAttribute("mac", RTCStringFmt("%RTmac", &m_id.mac()));
     168    xml::ElementNode *pElmLease = pElmParent->createChild("Lease");
     169
     170    pElmLease->setAttribute("mac", RTCStringFmt("%RTmac", &m_id.mac()));
    188171    if (m_id.id().present())
    189172    {
     
    191174        size_t cbStrId = m_id.id().value().size() * 2 + 1;
    192175        char *pszId = new char[cbStrId];
    193         rc = RTStrPrintHexBytes(pszId, cbStrId,
    194                                 &m_id.id().value().front(), m_id.id().value().size(),
    195                                 0);
    196         ndLease->setAttribute("id", pszId);
     176        int rc = RTStrPrintHexBytes(pszId, cbStrId,
     177                                    &m_id.id().value().front(), m_id.id().value().size(),
     178                                    0);
     179        AssertRC(rc);
     180        pElmLease->setAttribute("id", pszId);
    197181        delete[] pszId;
    198182    }
    199183
    200184    /* unused but we need it to keep the old code happy */
    201     ndLease->setAttribute("network", "0.0.0.0");
    202 
    203     ndLease->setAttribute("state", stateName());
    204 
     185    pElmLease->setAttribute("network", "0.0.0.0");
     186    pElmLease->setAttribute("state", stateName());
    205187
    206188    /*
    207189     * Lease/Address
    208190     */
    209     xml::ElementNode *ndAddr = ndLease->createChild("Address");
    210     ndAddr->setAttribute("value", RTCStringFmt("%RTnaipv4", m_addr.u));
    211 
     191    xml::ElementNode *pElmAddr = pElmLease->createChild("Address");
     192    pElmAddr->setAttribute("value", RTCStringFmt("%RTnaipv4", m_addr.u));
    212193
    213194    /*
    214195     * Lease/Time
    215196     */
    216     xml::ElementNode *ndTime = ndLease->createChild("Time");
    217     ndTime->setAttribute("issued", m_issued.getAbsSeconds());
    218     ndTime->setAttribute("expiration", m_secLease);
    219 
    220     return VINF_SUCCESS;
    221 }
    222 
    223 
    224 Binding *Binding::fromXML(const xml::ElementNode *ndLease)
     197    xml::ElementNode *pElmTime = pElmLease->createChild("Time");
     198    pElmTime->setAttribute("issued", m_issued.getAbsSeconds());
     199    pElmTime->setAttribute("expiration", m_secLease);
     200}
     201
     202
     203/**
     204 * Deserializes the binding from the XML lease database.
     205 *
     206 * @param   pElmLease   The "Lease" element.
     207 * @return  Pointer to the resulting binding, NULL on failure.
     208 * @throw   std::bad_alloc
     209 */
     210Binding *Binding::fromXML(const xml::ElementNode *pElmLease)
    225211{
    226212    /* Lease/@network seems to always have bogus value, ignore it. */
     
    230216     */
    231217    RTCString strMac;
    232     bool fHasMac = ndLease->getAttributeValue("mac", &strMac);
     218    bool fHasMac = pElmLease->getAttributeValue("mac", &strMac);
    233219    if (!fHasMac)
    234220        return NULL;
     
    241227    OptClientId id;
    242228    RTCString strId;
    243     bool fHasId = ndLease->getAttributeValue("id", &strId);
     229    bool fHasId = pElmLease->getAttributeValue("id", &strId);
    244230    if (fHasId)
    245231    {
     
    264250     */
    265251    RTCString strState;
    266     bool fHasState = ndLease->getAttributeValue("state", &strState);
     252    bool fHasState = pElmLease->getAttributeValue("state", &strState);
    267253
    268254    /*
    269255     * Lease/Address
    270256     */
    271     const xml::ElementNode *ndAddress = ndLease->findChildElement("Address");
     257    const xml::ElementNode *ndAddress = pElmLease->findChildElement("Address");
    272258    if (ndAddress == NULL)
    273259        return NULL;
     
    289275     * Lease/Time
    290276     */
    291     const xml::ElementNode *ndTime = ndLease->findChildElement("Time");
     277    const xml::ElementNode *ndTime = pElmLease->findChildElement("Time");
    292278    if (ndTime == NULL)
    293279        return NULL;
     
    332318
    333319
     320
     321/*********************************************************************************************************************************
     322*   Class Db Implementation                                                                                                      *
     323*********************************************************************************************************************************/
     324
     325Db::Db()
     326    : m_pConfig(NULL)
     327{
     328}
     329
     330
     331Db::~Db()
     332{
     333    /** @todo free bindings */
     334}
     335
     336
     337int Db::init(const Config *pConfig)
     338{
     339    Binding::registerFormat();
     340
     341    m_pConfig = pConfig;
     342
     343    m_pool.init(pConfig->getIPv4PoolFirst(),
     344                pConfig->getIPv4PoolLast());
     345
     346    return VINF_SUCCESS;
     347}
     348
     349
     350/**
     351 * Expire old binding (leases).
     352 */
    334353void Db::expire()
    335354{
    336355    const Timestamp now = Timestamp::now();
    337 
    338     for (bindings_t::iterator it = m_bindings.begin();
    339          it != m_bindings.end(); ++it)
     356    for (bindings_t::iterator it = m_bindings.begin(); it != m_bindings.end(); ++it)
    340357    {
    341358        Binding *b = *it;
     
    345362
    346363
     364/**
     365 * Internal worker that creates a binding for the given client, allocating new
     366 * IPv4 address for it.
     367 *
     368 * @returns Pointer to the binding.
     369 * @param   id          The client ID.
     370 */
    347371Binding *Db::createBinding(const ClientId &id)
    348372{
     373    Binding      *pBinding = NULL;
    349374    RTNETADDRIPV4 addr = m_pool.allocate();
    350     if (addr.u == 0)
    351         return NULL;
    352 
    353     Binding *b = new Binding(addr, id);
    354     m_bindings.push_front(b);
    355     return b;
    356 }
    357 
    358 
     375    if (addr.u != 0)
     376    {
     377        try
     378        {
     379            pBinding = new Binding(addr, id);
     380            m_bindings.push_front(pBinding);
     381        }
     382        catch (std::bad_alloc &)
     383        {
     384            if (pBinding)
     385                delete pBinding;
     386            /** @todo free address (no pool method for that)  */
     387        }
     388    }
     389    return pBinding;
     390}
     391
     392
     393/**
     394 * Internal worker that creates a binding to the specified IPv4 address for the
     395 * given client.
     396 *
     397 * @returns Pointer to the binding.
     398 *          NULL if the address is in use or we ran out of memory.
     399 * @param   addr        The IPv4 address.
     400 * @param   id          The client.
     401 */
    359402Binding *Db::createBinding(RTNETADDRIPV4 addr, const ClientId &id)
    360403{
     
    362405    if (!fAvailable)
    363406    {
    364         /*
     407        /** @todo
    365408         * XXX: this should not happen.  If the address is from the
    366409         * pool, which we have verified before, then either it's in
     
    376419
    377420
     421/**
     422 * Internal worker that allocates an IPv4 address for the given client, taking
     423 * the preferred address (@a addr) into account when possible and if non-zero.
     424 */
    378425Binding *Db::allocateAddress(const ClientId &id, RTNETADDRIPV4 addr)
    379426{
    380427    Assert(addr.u == 0 || addressBelongs(addr));
    381 
    382     Binding *addrBinding = NULL;
    383     Binding *freeBinding = NULL;
    384     Binding *reuseBinding = NULL;
    385428
    386429    if (addr.u != 0)
     
    394437     * addresses that can be reused.
    395438     */
    396     const Timestamp now = Timestamp::now();
    397     for (bindings_t::iterator it = m_bindings.begin();
    398          it != m_bindings.end(); ++it)
     439    Binding        *addrBinding  = NULL;
     440    Binding        *freeBinding  = NULL;
     441    Binding        *reuseBinding = NULL;
     442    const Timestamp now          = Timestamp::now();
     443    for (bindings_t::iterator it = m_bindings.begin(); it != m_bindings.end(); ++it)
    399444    {
    400445        Binding *b = *it;
     
    460505            addrBinding = createBinding(addr, id);
    461506            Assert(addrBinding != NULL);
    462             LogDHCP(("> .... creating new binding for this address %R[binding]\n",
    463                      addrBinding));
     507            LogDHCP(("> .... creating new binding for this address %R[binding]\n", addrBinding));
    464508            return addrBinding;
    465509        }
     
    467511        if (addrBinding->m_state <= Binding::EXPIRED) /* not in use */
    468512        {
    469             LogDHCP(("> .... reusing %s binding for this address\n",
    470                      addrBinding->stateName()));
     513            LogDHCP(("> .... reusing %s binding for this address\n", addrBinding->stateName()));
    471514            addrBinding->giveTo(id);
    472515            return addrBinding;
    473516        }
    474         LogDHCP(("> .... cannot reuse %s binding for this address\n",
    475                  addrBinding->stateName()));
     517        LogDHCP(("> .... cannot reuse %s binding for this address\n", addrBinding->stateName()));
    476518    }
    477519
     
    489531        idBinding = createBinding();
    490532        if (idBinding != NULL)
    491         {
    492533            LogDHCP(("> .... creating new binding\n"));
    493         }
    494534        else
    495535        {
    496536            idBinding = reuseBinding;
    497             LogDHCP(("> .... reusing %s binding %R[binding]\n",
    498                      reuseBinding->stateName(), reuseBinding));
    499         }
    500     }
    501 
    502     if (idBinding == NULL)
    503     {
    504         LogDHCP(("> .... failed to allocate binding\n"));
    505         return NULL;
     537            if (idBinding != NULL)
     538                LogDHCP(("> .... reusing %s binding %R[binding]\n", reuseBinding->stateName(), reuseBinding));
     539            else
     540            {
     541                LogDHCP(("> .... failed to allocate binding\n"));
     542                return NULL;
     543            }
     544        }
    506545    }
    507546
     
    514553
    515554
     555/**
     556 * Called by DHCPD to allocate a binding for the specified request.
     557 *
     558 * @returns Pointer to the binding, NULL on failure.
     559 * @param   req                 The DHCP request being served.
     560 */
    516561Binding *Db::allocateBinding(const DhcpClientMessage &req)
    517562{
    518563    /** @todo XXX: handle fixed address assignments */
     564
     565    /*
     566     * Get and validate the requested address (if present).
     567     */
    519568    OptRequestedAddress reqAddr(req);
    520569    if (reqAddr.present() && !addressBelongs(reqAddr.value()))
     
    532581    }
    533582
     583    /*
     584     * Allocate the address.
     585     */
    534586    const ClientId &id(req.clientId());
    535587
    536588    Binding *b = allocateAddress(id, reqAddr.value());
    537     if (b == NULL)
    538         return NULL;
    539 
    540     Assert(b->id() == id);
    541 
    542     /** @todo
    543      * XXX: handle requests for specific lease time!
    544      * XXX: old lease might not have expired yet?
    545      */
    546     // OptLeaseTime reqLeaseTime(req);
    547     b->setLeaseTime(1200);
     589    if (b != NULL)
     590    {
     591        Assert(b->id() == id);
     592
     593        /** @todo
     594         * XXX: handle requests for specific lease time!
     595         * XXX: old lease might not have expired yet?
     596         * Make lease time configurable.
     597         */
     598        // OptLeaseTime reqLeaseTime(req);
     599        b->setLeaseTime(1200);
     600    }
    548601    return b;
    549602}
    550603
    551604
    552 int Db::addBinding(Binding *newb)
    553 {
    554     if (!addressBelongs(newb->m_addr))
    555     {
    556         LogDHCP(("Binding for out of range address %RTnaipv4 ignored\n",
    557                  newb->m_addr.u));
    558         return VERR_INVALID_PARAMETER;
    559     }
    560 
    561     for (bindings_t::iterator it = m_bindings.begin();
    562          it != m_bindings.end(); ++it)
     605/**
     606 * Internal worker used by loadLease().
     607 *
     608 * @returns IPRT status code.
     609 * @param   newb                .
     610 */
     611int Db::addBinding(Binding *pNewBinding)
     612{
     613    /*
     614     * Validate the binding against the range and existing bindings.
     615     */
     616    if (!addressBelongs(pNewBinding->m_addr))
     617    {
     618        LogDHCP(("Binding for out of range address %RTnaipv4 ignored\n", pNewBinding->m_addr.u));
     619        return VERR_OUT_OF_RANGE;
     620    }
     621
     622    for (bindings_t::iterator it = m_bindings.begin(); it != m_bindings.end(); ++it)
    563623    {
    564624        Binding *b = *it;
    565625
    566         if (newb->m_addr.u == b->m_addr.u)
    567         {
    568             LogDHCP(("> ADD: %R[binding]\n", newb));
     626        if (pNewBinding->m_addr.u == b->m_addr.u)
     627        {
     628            LogDHCP(("> ADD: %R[binding]\n", pNewBinding));
    569629            LogDHCP(("> .... duplicate ip: %R[binding]\n", b));
    570             return VERR_INVALID_PARAMETER;
    571         }
    572 
    573         if (newb->m_id == b->m_id)
    574         {
    575             LogDHCP(("> ADD: %R[binding]\n", newb));
     630            return VERR_DUPLICATE;
     631        }
     632
     633        if (pNewBinding->m_id == b->m_id)
     634        {
     635            LogDHCP(("> ADD: %R[binding]\n", pNewBinding));
    576636            LogDHCP(("> .... duplicate id: %R[binding]\n", b));
    577             return VERR_INVALID_PARAMETER;
    578         }
    579     }
    580 
    581     bool ok = m_pool.allocate(newb->m_addr);
    582     if (!ok)
    583     {
    584         LogDHCP(("> ADD: failed to claim IP %R[binding]\n", newb));
    585         return VERR_INVALID_PARAMETER;
    586     }
    587 
    588     m_bindings.push_back(newb);
     637            return VERR_DUPLICATE;
     638        }
     639    }
     640
     641    /*
     642     * Allocate the address and add the binding to the list.
     643     */
     644    AssertLogRelMsgReturn(m_pool.allocate(pNewBinding->m_addr),
     645                          ("> ADD: failed to claim IP %R[binding]\n", pNewBinding),
     646                          VERR_INTERNAL_ERROR);
     647    try
     648    {
     649        m_bindings.push_back(pNewBinding);
     650    }
     651    catch (std::bad_alloc &)
     652    {
     653        return VERR_NO_MEMORY;
     654    }
    589655    return VINF_SUCCESS;
    590656}
    591657
    592658
     659/**
     660 * Called by DHCP to cancel an offset.
     661 *
     662 * @param   req                 The DHCP request.
     663 */
    593664void Db::cancelOffer(const DhcpClientMessage &req)
    594665{
     
    598669
    599670    const RTNETADDRIPV4 addr = reqAddr.value();
    600     const ClientId &id(req.clientId());
    601 
    602     for (bindings_t::iterator it = m_bindings.begin();
    603          it != m_bindings.end(); ++it)
     671    const ClientId     &id(req.clientId());
     672
     673    for (bindings_t::iterator it = m_bindings.begin(); it != m_bindings.end(); ++it)
    604674    {
    605675        Binding *b = *it;
     
    609679            if (b->state() == Binding::OFFERED)
    610680            {
     681                LogRel2(("Db::cancelOffer: cancelling %R[binding]\n", b));
    611682                b->setLeaseTime(0);
    612683                b->setState(Binding::RELEASED);
    613684            }
     685            else
     686                LogRel2(("Db::cancelOffer: not offered state: %R[binding]\n", b));
    614687            return;
    615688        }
    616689    }
    617 }
    618 
    619 
     690    LogRel2(("Db::cancelOffer: not found (%RTnaipv4, %R[id])\n", addr.u, &id));
     691}
     692
     693
     694/**
     695 * Called by DHCP to cancel an offset.
     696 *
     697 * @param   req                 The DHCP request.
     698 * @returns true if found and released, otherwise false.
     699 */
    620700bool Db::releaseBinding(const DhcpClientMessage &req)
    621701{
    622702    const RTNETADDRIPV4 addr = req.ciaddr();
    623     const ClientId &id(req.clientId());
    624 
    625     for (bindings_t::iterator it = m_bindings.begin();
    626          it != m_bindings.end(); ++it)
     703    const ClientId     &id(req.clientId());
     704
     705    for (bindings_t::iterator it = m_bindings.begin(); it != m_bindings.end(); ++it)
    627706    {
    628707        Binding *b = *it;
     
    630709        if (b->addr().u == addr.u && b->id() == id)
    631710        {
     711            LogRel2(("Db::releaseBinding: releasing %R[binding]\n", b));
    632712            b->setState(Binding::RELEASED);
    633713            return true;
     
    635715    }
    636716
     717    LogRel2(("Db::releaseBinding: not found (%RTnaipv4, %R[id])\n", addr.u, &id));
    637718    return false;
    638719}
    639720
    640721
    641 int Db::writeLeases(const RTCString &strFileName) const
    642 {
    643     LogDHCP(("writing leases to %s\n", strFileName.c_str()));
    644 
     722/**
     723 * Called by DHCPD to write out the lease database to @a strFilename.
     724 *
     725 * @returns IPRT status code.
     726 * @param   strFilename         The file to write it to.
     727 */
     728int Db::writeLeases(const RTCString &strFilename) const
     729{
     730    LogDHCP(("writing leases to %s\n", strFilename.c_str()));
     731
     732    /*
     733     * Create the document and root element.
     734     */
    645735    xml::Document doc;
    646 
    647     xml::ElementNode *root = doc.createRootElement("Leases");
    648     if (root == NULL)
    649         return VERR_INTERNAL_ERROR;
    650 
    651     root->setAttribute("version", "1.0");
    652 
    653     for (bindings_t::const_iterator it = m_bindings.begin();
    654          it != m_bindings.end(); ++it)
    655     {
    656         const Binding *b = *it;
    657         b->toXML(root);
    658     }
    659 
    660     try {
     736    try
     737    {
     738        xml::ElementNode *pElmRoot = doc.createRootElement("Leases");
     739        pElmRoot->setAttribute("version", "1.0");
     740
     741        /*
     742         * Add the leases.
     743         */
     744        for (bindings_t::const_iterator it = m_bindings.begin(); it != m_bindings.end(); ++it)
     745        {
     746            const Binding *b = *it;
     747            b->toXML(pElmRoot);
     748        }
     749    }
     750    catch (std::bad_alloc &)
     751    {
     752        return VERR_NO_MEMORY;
     753    }
     754
     755    /*
     756     * Write the document to the specified file in a safe manner (written to temporary
     757     * file, renamed to destination on success)
     758     */
     759    try
     760    {
    661761        xml::XmlFileWriter writer(doc);
    662         writer.write(strFileName.c_str(), true);
     762        writer.write(strFilename.c_str(), true /*fSafe*/);
    663763    }
    664764    catch (const xml::EIPRTFailure &e)
     
    674774    catch (...)
    675775    {
    676         LogDHCP(("Unknown exception while writing '%s'\n",
    677                  strFileName.c_str()));
    678         return VERR_GENERAL_FAILURE;
     776        LogDHCP(("Unknown exception while writing '%s'\n", strFilename.c_str()));
     777        return VERR_UNEXPECTED_EXCEPTION;
    679778    }
    680779
     
    683782
    684783
    685 int Db::loadLeases(const RTCString &strFileName)
    686 {
    687     LogDHCP(("loading leases from %s\n", strFileName.c_str()));
    688 
     784/**
     785 * Called by DHCPD to load the lease database to @a strFilename.
     786 *
     787 * @note Does not clear the database state before doing the load.
     788 *
     789 * @returns IPRT status code.
     790 * @param   strFilename         The file to load it from.
     791 */
     792int Db::loadLeases(const RTCString &strFilename)
     793{
     794    LogDHCP(("loading leases from %s\n", strFilename.c_str()));
     795
     796    /*
     797     * Load the file into an XML document.
     798     */
    689799    xml::Document doc;
    690800    try
    691801    {
    692802        xml::XmlFileParser parser;
    693         parser.read(strFileName.c_str(), doc);
     803        parser.read(strFilename.c_str(), doc);
    694804    }
    695805    catch (const xml::EIPRTFailure &e)
     
    705815    catch (...)
    706816    {
    707         LogDHCP(("Unknown exception while reading and parsing '%s'\n",
    708                  strFileName.c_str()));
    709         return VERR_GENERAL_FAILURE;
    710     }
    711 
    712     xml::ElementNode *ndRoot = doc.getRootElement();
    713     if (ndRoot == NULL || !ndRoot->nameEquals("Leases"))
    714     {
     817        LogDHCP(("Unknown exception while reading and parsing '%s'\n", strFilename.c_str()));
     818        return VERR_UNEXPECTED_EXCEPTION;
     819    }
     820
     821    /*
     822     * Check that the root element is "Leases" and process its children.
     823     */
     824    xml::ElementNode *pElmRoot = doc.getRootElement();
     825    if (!pElmRoot)
     826    {
     827        LogDHCP(("No root element in '%s'\n", strFilename.c_str()));
    715828        return VERR_NOT_FOUND;
    716829    }
    717 
    718     xml::NodesLoop it(*ndRoot);
    719     const xml::ElementNode *node;
    720     while ((node = it.forAllNodes()) != NULL)
    721     {
    722         if (!node->nameEquals("Lease"))
    723             continue;
    724 
    725         loadLease(node);
    726     }
    727 
    728     return VINF_SUCCESS;
    729 }
    730 
    731 
    732 void Db::loadLease(const xml::ElementNode *ndLease)
    733 {
    734     Binding *b = Binding::fromXML(ndLease);
    735     bool expired = b->expire();
    736 
    737     if (!expired)
    738         LogDHCP(("> LOAD: lease %R[binding]\n", b));
    739     else
    740         LogDHCP(("> LOAD: EXPIRED lease %R[binding]\n", b));
    741 
    742     addBinding(b);
    743 }
     830    if (!pElmRoot->nameEquals("Leases"))
     831    {
     832        LogDHCP(("No root element is not 'Leases' in '%s', but '%s'\n", strFilename.c_str(), pElmRoot->getName()));
     833        return VERR_NOT_FOUND;
     834    }
     835
     836    int                     rc = VINF_SUCCESS;
     837    xml::NodesLoop          it(*pElmRoot);
     838    const xml::ElementNode *pElmLease;
     839    while ((pElmLease = it.forAllNodes()) != NULL)
     840    {
     841        if (pElmLease->nameEquals("Lease"))
     842        {
     843            int rc2 = loadLease(pElmLease);
     844            if (RT_SUCCESS(rc2))
     845            { /* likely */ }
     846            else if (rc2 == VERR_NO_MEMORY)
     847                return rc2;
     848            else
     849                rc = -rc2;
     850        }
     851        else
     852            LogDHCP(("Ignoring unexpected element '%s' under 'Leases'...\n", pElmLease->getName()));
     853    }
     854
     855    return rc;
     856}
     857
     858
     859/**
     860 * Internal worker for loadLeases() that handles one 'Lease' element.
     861 *
     862 * @param   pElmLease           The 'Lease' element to handle.
     863 * @return  IPRT status code.
     864 */
     865int Db::loadLease(const xml::ElementNode *pElmLease)
     866{
     867    Binding *pBinding = NULL;
     868    try
     869    {
     870        pBinding = Binding::fromXML(pElmLease);
     871    }
     872    catch (std::bad_alloc &)
     873    {
     874        return VERR_NO_MEMORY;
     875    }
     876    if (pBinding)
     877    {
     878        bool fExpired = pBinding->expire();
     879        if (!fExpired)
     880            LogDHCP(("> LOAD: lease %R[binding]\n", pBinding));
     881        else
     882            LogDHCP(("> LOAD: EXPIRED lease %R[binding]\n", pBinding));
     883
     884        int rc = addBinding(pBinding);
     885        if (RT_FAILURE(rc))
     886            delete pBinding;
     887        return rc;
     888    }
     889    LogDHCP(("> LOAD: failed to load lease!\n"));
     890    return VERR_PARSE_ERROR;
     891}
  • trunk/src/VBox/NetworkServices/Dhcpd/Db.h

    r79524 r79529  
    3737
    3838
     39/**
     40 * Address binding in the lease database.
     41 */
    3942class Binding
    4043{
     
    5558    Binding(const Binding &);
    5659
    57     explicit Binding(RTNETADDRIPV4 addrParam)
    58       : m_addr(addrParam), m_state(FREE),
    59         m_issued(), m_secLease() {}
     60    explicit Binding(RTNETADDRIPV4 a_Addr)
     61        : m_addr(a_Addr), m_state(FREE), m_issued(), m_secLease()
     62    {}
    6063
    61     Binding(RTNETADDRIPV4 addrParam, const ClientId &idParam)
    62       : m_addr(addrParam), m_state(FREE), m_id(idParam),
    63         m_issued(), m_secLease() {}
     64    Binding(RTNETADDRIPV4 a_Addr, const ClientId &a_id)
     65        : m_addr(a_Addr), m_state(FREE), m_id(a_id), m_issued(), m_secLease()
     66    {}
    6467
    6568
    66     RTNETADDRIPV4 addr() const { return m_addr; }
     69    /** @name Attribute accessors
     70     * @{ */
     71    RTNETADDRIPV4   addr() const        { return m_addr; }
    6772
    68     State state() const { return m_state; }
    69     const char *stateName() const;
     73    const ClientId &id() const          { return m_id; }
    7074
    71     const ClientId &id() const { return m_id; }
     75    uint32_t        leaseTime() const   { return m_secLease; }
     76    Timestamp       issued() const      { return m_issued; }
    7277
    73     uint32_t leaseTime() const { return m_secLease; }
    74     Timestamp issued() const { return m_issued; }
    75 
    76     Binding &setState(State stateParam)
     78    State           state() const       { return m_state; }
     79    const char     *stateName() const;
     80    Binding        &setState(const char *pszStateName);
     81    Binding        &setState(State stateParam)
    7782    {
    7883        m_state = stateParam;
    7984        return *this;
    8085    }
     86    /** @} */
    8187
    82     Binding &setState(const char *pszStateName);
    8388
    8489    Binding &setLeaseTime(uint32_t secLease)
     
    8994    }
    9095
    91     Binding &giveTo(const ClientId &idParam)
     96    /** Reassigns the binding to the given client.   */
     97    Binding &giveTo(const ClientId &a_id)
    9298    {
    93         m_id = idParam;
     99        m_id = a_id;
    94100        m_state = FREE;
    95101        return *this;
     
    102108    }
    103109
    104     bool expire(Timestamp deadline);
     110    bool expire(Timestamp tsDeadline);
    105111    bool expire() { return expire(Timestamp::now()); }
    106112
    107     static Binding *fromXML(const xml::ElementNode *ndLease);
    108     int toXML(xml::ElementNode *ndParent) const;
     113    /** @name Serialization
     114     * @{ */
     115    static Binding *fromXML(const xml::ElementNode *pElmLease);
     116    void            toXML(xml::ElementNode *pElmParent) const;
     117    /** @} */
    109118
    110 public:
    111     static void registerFormat(); /* %R[binding] */
    112 
     119    /** @name String formatting of %R[binding].
     120     * @{ */
     121    static void registerFormat();
    113122private:
     123    static DECLCALLBACK(size_t) rtStrFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char *pszType,
     124                                            void const *pvValue, int cchWidth, int cchPrecision, unsigned fFlags, void *pvUser);
    114125    static bool g_fFormatRegistered;
    115     static DECLCALLBACK(size_t) rtStrFormat(
    116         PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
    117         const char *pszType, void const *pvValue,
    118         int cchWidth, int cchPrecision, unsigned fFlags,
    119         void *pvUser);
     126    /** @} */
    120127};
    121128
    122129
     130/**
     131 * The lease database.
     132 */
    123133class Db
    124134{
     
    126136    typedef std::list<Binding *> bindings_t;
    127137
    128     const Config *m_pConfig;
    129     bindings_t m_bindings;
    130     IPv4Pool m_pool;
     138    /** Configuration (set at init). */
     139    const Config   *m_pConfig;
     140    /** The lease database. */
     141    bindings_t      m_bindings;
     142    /** Address allocation pool. */
     143    IPv4Pool        m_pool;
    131144
    132145public:
     
    134147    ~Db();
    135148
    136     int init(const Config *pConfig);
     149    int      init(const Config *pConfig);
    137150
    138     bool addressBelongs(RTNETADDRIPV4 addr) const { return m_pool.contains(addr); }
     151    /** Check if @a addr belonges to this lease database. */
     152    bool     addressBelongs(RTNETADDRIPV4 addr) const { return m_pool.contains(addr); }
    139153
    140154    Binding *allocateBinding(const DhcpClientMessage &req);
    141     bool releaseBinding(const DhcpClientMessage &req);
     155    bool     releaseBinding(const DhcpClientMessage &req);
    142156
    143     void cancelOffer(const DhcpClientMessage &req);
     157    void     cancelOffer(const DhcpClientMessage &req);
    144158
    145     void expire();
     159    void     expire();
    146160
     161    /** @name Database serialization methods
     162     * @{ */
     163    int      loadLeases(const RTCString &strFilename);
     164private:
     165    int      loadLease(const xml::ElementNode *pElmLease);
    147166public:
    148     int loadLeases(const RTCString &strFileName);
    149     void loadLease(const xml::ElementNode *ndLease);
    150 
    151     int writeLeases(const RTCString &strFileName) const;
     167    int      writeLeases(const RTCString &strFilename) const;
     168    /** @} */
    152169
    153170private:
     
    158175
    159176    /* add binding e.g. from the leases file */
    160     int addBinding(Binding *b);
     177    int      addBinding(Binding *b);
    161178};
    162179
  • trunk/src/VBox/NetworkServices/Dhcpd/IPv4Pool.cpp

    r79524 r79529  
    11/* $Id$ */
    22/** @file
    3  * DHCP server - a pool of IPv4 addresses
     3 * DHCP server - A pool of IPv4 addresses.
    44 */
    55
     
    1616 */
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include "DhcpdInternal.h"
    1923#include <iprt/errcore.h>
    20 #include <iprt/stream.h>
    2124
    2225#include "IPv4Pool.h"
     
    2528int IPv4Pool::init(const IPv4Range &aRange)
    2629{
    27     if (!aRange.isValid())
    28         return VERR_INVALID_PARAMETER;
     30    AssertReturn(aRange.isValid(), VERR_INVALID_PARAMETER);
    2931
    3032    m_range = aRange;
     
    3638int IPv4Pool::init(RTNETADDRIPV4 aFirstAddr, RTNETADDRIPV4 aLastAddr)
    3739{
    38     IPv4Range range(aFirstAddr, aLastAddr);
     40    return init(IPv4Range(aFirstAddr, aLastAddr));
     41}
    3942
    40     if (!range.isValid())
    41         return VERR_INVALID_PARAMETER;
    4243
    43     m_range = range;
    44     m_pool.insert(m_range);
     44/**
     45 * Internal worker for inserting a range into the pool of available addresses.
     46 *
     47 * @returns IPRT status code (asserted).
     48 * @param   a_Range         The range to insert.
     49 */
     50int IPv4Pool::insert(const IPv4Range &a_Range)
     51{
     52    /*
     53     * Check preconditions. Asserting because nobody checks the return code.
     54     */
     55    AssertReturn(m_range.isValid(), VERR_INVALID_STATE);
     56    AssertReturn(a_Range.isValid(), VERR_INVALID_PARAMETER);
     57    AssertReturn(m_range.contains(a_Range), VERR_INVALID_PARAMETER);
     58
     59    /*
     60     * Check that the incoming range doesn't overlap with existing ranges in the pool.
     61     */
     62    it_t itHint = m_pool.upper_bound(IPv4Range(a_Range.LastAddr)); /* successor, insertion hint */
     63#if 0 /** @todo r=bird: This code is wrong.  It has no end() check for starters.  Since the method is
     64       *                only for internal consumption, I've replaced it with a strict build assertion. */
     65    if (itHint != m_pool.begin())
     66    {
     67        it_t prev(itHint);
     68        --prev;
     69        if (a_Range.FirstAddr <= prev->LastAddr)
     70        {
     71            LogDHCP(("%08x-%08x conflicts with %08x-%08x\n",
     72                     a_Range.FirstAddr, a_Range.LastAddr,
     73                     prev->FirstAddr, prev->LastAddr));
     74            return VERR_INVALID_PARAMETER;
     75        }
     76    }
     77#endif
     78#ifdef VBOX_STRICT
     79    for (it_t it2 = m_pool.begin(); it2 != m_pool.end(); ++it2)
     80        AssertMsg(it2->LastAddr < a_Range.FirstAddr || it2->FirstAddr > a_Range.LastAddr,
     81                  ("%08RX32-%08RX32 conflicts with %08RX32-%08RX32\n",
     82                   a_Range.FirstAddr, a_Range.LastAddr, it2->FirstAddr, it2->LastAddr));
     83#endif
     84
     85    /*
     86     * No overlaps, insert it.
     87     */
     88    m_pool.insert(itHint, a_Range);
    4589    return VINF_SUCCESS;
    4690}
    4791
    4892
    49 int IPv4Pool::insert(const IPv4Range &range)
     93/**
     94 * Allocates an available IPv4 address from the pool.
     95 *
     96 * @returns Non-zero network order IPv4 address on success, zero address
     97 *          (0.0.0.0) on failure.
     98 */
     99RTNETADDRIPV4 IPv4Pool::allocate()
    50100{
    51     if (!m_range.isValid())
    52         return VERR_INVALID_PARAMETER;
     101    RTNETADDRIPV4 RetAddr;
     102    if (!m_pool.empty())
     103    {
     104        /* Grab the first address in the pool: */
     105        it_t itBeg = m_pool.begin();
     106        RetAddr.u = RT_H2N_U32(itBeg->FirstAddr);
    53107
    54     if (!m_range.contains(range))
    55         return VERR_INVALID_PARAMETER;
    56 
    57     it_t it = m_pool.upper_bound(IPv4Range(range.LastAddr)); /* successor */
    58     if (it != m_pool.begin())
    59     {
    60         it_t prev(it);
    61         --prev;
    62         if (range.FirstAddr <= prev->LastAddr) {
    63 #if 1 /* XXX */
    64             RTPrintf("%08x-%08x conflicts with %08x-%08x\n",
    65                      range.FirstAddr, range.LastAddr,
    66                      prev->FirstAddr, prev->LastAddr);
    67 #endif
    68             return VERR_INVALID_PARAMETER;
     108        if (itBeg->FirstAddr == itBeg->LastAddr)
     109            m_pool.erase(itBeg);
     110        else
     111        {
     112            /* Trim the entry (re-inserting it): */
     113            IPv4Range trimmed = *itBeg;
     114            trimmed.FirstAddr += 1;
     115            m_pool.erase(itBeg);
     116            m_pool.insert(trimmed);
    69117        }
    70118    }
    71 
    72     m_pool.insert(it, range);
    73     return VINF_SUCCESS;
     119    else
     120        RetAddr.u = 0;
     121    return RetAddr;
    74122}
    75123
    76124
    77 RTNETADDRIPV4 IPv4Pool::allocate()
     125/**
     126 * Allocate the given address.
     127 *
     128 * @returns Success indicator.
     129 * @param   a_Addr      The IP address to allocate (network order).
     130 */
     131bool IPv4Pool::allocate(RTNETADDRIPV4 a_Addr)
    78132{
    79     if (m_pool.empty())
     133    /*
     134     * Find the range containing a_Addr.
     135     */
     136    it_t it = m_pool.lower_bound(IPv4Range(a_Addr)); /* candidate range */
     137    if (it != m_pool.end())
    80138    {
    81         RTNETADDRIPV4 res = { 0 };
    82         return res;
    83     }
     139        Assert(RT_N2H_U32(a_Addr.u) <= it->LastAddr); /* by definition of < and lower_bound */
    84140
    85     it_t beg = m_pool.begin();
    86     ip_haddr_t addr = beg->FirstAddr;
     141        if (it->contains(a_Addr))
     142        {
     143            /*
     144             * Remove a_Addr from the range by way of re-insertion.
     145             */
     146            const IPV4HADDR haddr = RT_N2H_U32(a_Addr.u);
     147            IPV4HADDR       first = it->FirstAddr;
     148            IPV4HADDR       last  = it->LastAddr;
    87149
    88     if (beg->FirstAddr == beg->LastAddr)
    89     {
    90         m_pool.erase(beg);
    91     }
    92     else
    93     {
    94         IPv4Range trimmed = *beg;
    95         ++trimmed.FirstAddr;
    96         m_pool.erase(beg);
    97         m_pool.insert(trimmed);
    98     }
     150            m_pool.erase(it);
     151            if (first != last)
     152            {
     153                if (haddr == first)
     154                    insert(++first, last);
     155                else if (haddr == last)
     156                    insert(first, --last);
     157                else
     158                {
     159                    insert(first, haddr - 1);
     160                    insert(haddr + 1, last);
     161                }
     162            }
    99163
    100     RTNETADDRIPV4 res = { RT_H2N_U32(addr) };
    101     return res;
    102 }
    103 
    104 
    105 bool IPv4Pool::allocate(RTNETADDRIPV4 addr)
    106 {
    107     it_t it = m_pool.lower_bound(IPv4Range(addr)); /* candidate range */
    108     if (it == m_pool.end())
    109         return false;
    110 
    111     Assert(RT_N2H_U32(addr.u) <= it->LastAddr); /* by definition of < and lower_bound */
    112 
    113     if (!it->contains(addr))
    114         return false;
    115 
    116     const ip_haddr_t haddr = RT_N2H_U32(addr.u);
    117     ip_haddr_t first = it->FirstAddr;
    118     ip_haddr_t last = it->LastAddr;
    119 
    120     m_pool.erase(it);
    121     if (first != last)
    122     {
    123         if (haddr == first)
    124         {
    125             insert(++first, last);
    126         }
    127         else if (haddr == last)
    128         {
    129             insert(first, --last);
    130         }
    131         else
    132         {
    133             insert(first, haddr - 1);
    134             insert(haddr + 1, last);
     164            return true;
    135165        }
    136166    }
    137 
    138     return true;
     167    return false;
    139168}
  • trunk/src/VBox/NetworkServices/Dhcpd/IPv4Pool.h

    r76576 r79529  
    2727#include <set>
    2828
    29 typedef uint32_t ip_haddr_t;    /* in host order */
     29
     30/** Host order IPv4 address. */
     31typedef uint32_t IPV4HADDR;
    3032
    3133
    32 /*
     34/**
    3335 * A range of IPv4 addresses (in host order).
    3436 */
    3537struct IPv4Range
    3638{
    37     ip_haddr_t FirstAddr;
    38     ip_haddr_t LastAddr;        /* inclusive */
     39    IPV4HADDR FirstAddr;       /**< Lowest address. */
     40    IPV4HADDR LastAddr;        /**< Higest address (inclusive). */
    3941
    4042    IPv4Range()
    41       : FirstAddr(), LastAddr() {}
     43        : FirstAddr(0), LastAddr(0)
     44    {}
    4245
    43     explicit IPv4Range(ip_haddr_t aSingleAddr)
    44       : FirstAddr(aSingleAddr), LastAddr(aSingleAddr) {}
     46    explicit IPv4Range(IPV4HADDR aSingleAddr)
     47        : FirstAddr(aSingleAddr), LastAddr(aSingleAddr)
     48    {}
    4549
    46     IPv4Range(ip_haddr_t aFirstAddr, ip_haddr_t aLastAddr)
    47       : FirstAddr(aFirstAddr), LastAddr(aLastAddr) {}
     50    IPv4Range(IPV4HADDR aFirstAddr, IPV4HADDR aLastAddr)
     51        : FirstAddr(aFirstAddr), LastAddr(aLastAddr)
     52    {}
    4853
    4954    explicit IPv4Range(RTNETADDRIPV4 aSingleAddr)
    50       : FirstAddr(RT_N2H_U32(aSingleAddr.u)), LastAddr(RT_N2H_U32(aSingleAddr.u)) {}
     55        : FirstAddr(RT_N2H_U32(aSingleAddr.u)), LastAddr(RT_N2H_U32(aSingleAddr.u))
     56    {}
    5157
    5258    IPv4Range(RTNETADDRIPV4 aFirstAddr, RTNETADDRIPV4 aLastAddr)
    53       : FirstAddr(RT_N2H_U32(aFirstAddr.u)), LastAddr(RT_N2H_U32(aLastAddr.u)) {}
     59        : FirstAddr(RT_N2H_U32(aFirstAddr.u)), LastAddr(RT_N2H_U32(aLastAddr.u))
     60    {}
    5461
    5562    bool isValid() const
     
    5865    }
    5966
    60     bool contains(ip_haddr_t addr) const
     67    bool contains(IPV4HADDR addr) const
    6168    {
    6269        return FirstAddr <= addr && addr <= LastAddr;
     
    6875    }
    6976
    70     bool contains(const IPv4Range &range) const
     77    /** Checks if this range includes the @a a_rRange. */
     78    bool contains(const IPv4Range &a_rRange) const
    7179    {
    72         return range.isValid() && FirstAddr <= range.FirstAddr && range.LastAddr <= LastAddr;
     80        return a_rRange.isValid()
     81            && FirstAddr <= a_rRange.FirstAddr
     82            && a_rRange.LastAddr <= LastAddr;
    7383    }
    7484};
     
    8797
    8898
     99/**
     100 * IPv4 address pool.
     101 *
     102 * This manages a single range of IPv4 addresses (m_range).   Unallocated
     103 * addresses are tracked as a set of sub-ranges in the m_pool set.
     104 *
     105 */
    89106class IPv4Pool
    90107{
     
    92109    typedef set_t::iterator it_t;
    93110
    94     IPv4Range m_range;
    95     set_t m_pool;
     111    /** The IPv4 range of this pool. */
     112    IPv4Range   m_range;
     113    /** Pool of available IPv4 ranges. */
     114    set_t       m_pool;
    96115
    97116public:
    98     IPv4Pool() {}
     117    IPv4Pool()
     118    {}
    99119
    100120    int init(const IPv4Range &aRange);
    101121    int init(RTNETADDRIPV4 aFirstAddr, RTNETADDRIPV4 aLastAddr);
    102122
     123    /**
     124     * Checks if the pool range includes @a addr (allocation status not considered).
     125     */
    103126    bool contains(RTNETADDRIPV4 addr) const
    104       { return m_range.contains(addr); }
    105 
    106     int insert(const IPv4Range &range);
    107 
    108 #if 0
    109     int insert(ip_haddr_t single)
    110       { return insert(IPv4Range(single)); }
    111 #endif
    112 
    113     int insert(ip_haddr_t first, ip_haddr_t last)
    114       { return insert(IPv4Range(first, last)); }
    115 
    116     int insert(RTNETADDRIPV4 single)
    117       { return insert(IPv4Range(single)); }
    118 
    119     int insert(RTNETADDRIPV4 first, RTNETADDRIPV4 last)
    120       { return insert(IPv4Range(first, last)); }
     127    {
     128        return m_range.contains(addr);
     129    }
    121130
    122131    RTNETADDRIPV4 allocate();
    123     bool allocate(RTNETADDRIPV4);
     132    bool          allocate(RTNETADDRIPV4);
     133
     134private:
     135    int insert(const IPv4Range &range);
     136#if 0
     137    int insert(IPV4HADDR single)                            { return insert(IPv4Range(single)); }
     138#endif
     139    int insert(IPV4HADDR first, IPV4HADDR last)             { return insert(IPv4Range(first, last)); }
     140    int insert(RTNETADDRIPV4 single)                        { return insert(IPv4Range(single)); }
     141    int insert(RTNETADDRIPV4 first, RTNETADDRIPV4 last)     { return insert(IPv4Range(first, last)); }
    124142};
    125143
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