VirtualBox

Ignore:
Timestamp:
Jul 16, 2019 7:00:06 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132192
Message:

Dhcpd: Fixed address assignments. bugref:9288

File:
1 edited

Legend:

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

    r79568 r79818  
    7070    if (b->m_state == Binding::FREE)
    7171        cb += pfnOutput(pvArgOutput, RT_STR_TUPLE(" free"));
     72    else if (b->m_fFixed)
     73        cb += pfnOutput(pvArgOutput, RT_STR_TUPLE(" fixed"));
    7274    else
    7375    {
     
    8789}
    8890
     91
     92/**
     93 * Used to update the client ID of a fixed address assignment.
     94 *
     95 * We only have the MAC address when prepraring the binding, so the full client
     96 * ID must be supplied when the client requests it.
     97 *
     98 * @param   a_ridClient         The client ID.
     99 * @throws  std::bad_alloc
     100 */
     101void Binding::idUpdate(const ClientId &a_ridClient)
     102{
     103    AssertReturnVoid(isFixed());
     104    m_id = a_ridClient;
     105}
     106
     107
     108/**
     109 * Get the state as a string for the XML lease database.
     110 */
    89111const char *Binding::stateName() const RT_NOEXCEPT
    90112{
     
    108130
    109131
     132/**
     133 * Sets the state by name (reverse of Binding::stateName()).
     134 */
    110135Binding &Binding::setState(const char *pszStateName) RT_NOEXCEPT
    111136{
     
    139164bool Binding::expire(Timestamp tsDeadline) RT_NOEXCEPT
    140165{
    141     if (m_state <= Binding::EXPIRED)
     166    if (m_state <= Binding::EXPIRED || m_fFixed)
    142167        return false;
    143168
     
    338363    m_pConfig = pConfig;
    339364
    340     return m_pool.init(pConfig->getIPv4PoolFirst(), pConfig->getIPv4PoolLast());
     365    int rc = m_pool.init(pConfig->getIPv4PoolFirst(), pConfig->getIPv4PoolLast());
     366    if (RT_SUCCESS(rc))
     367    {
     368        /*
     369         * If the server IP is in the dynamic range, preallocate it like a fixed assignment.
     370         */
     371        rc = i_enterFixedAddressAssignment(pConfig->getIPv4Address(), pConfig->getMacAddress());
     372        if (RT_SUCCESS(rc))
     373        {
     374            /*
     375             * Preallocate any fixed address assignments:
     376             */
     377            Config::HostConfigVec vecHostConfigs;
     378            rc = pConfig->getFixedAddressConfigs(vecHostConfigs);
     379            for (Config::HostConfigVec::const_iterator it = vecHostConfigs.begin();
     380                 it != vecHostConfigs.end() && RT_SUCCESS(rc); ++it)
     381                rc = i_enterFixedAddressAssignment((*it)->getFixedAddress(), (*it)->getMACAddress());
     382        }
     383    }
     384
     385    return rc;
     386}
     387
     388
     389/**
     390 * Used by Db::init() to register a fixed address assignment.
     391 *
     392 * @returns IPRT status code.
     393 * @param   a_rAddress      The IPv4 address assignment.
     394 * @param   a_rMACAddress   The MAC address.
     395 */
     396int Db::i_enterFixedAddressAssignment(RTNETADDRIPV4 const &a_rAddress, RTMAC const &a_rMACAddress) RT_NOEXCEPT
     397{
     398    LogRelFunc(("%RTmac: %RTnaipv4\n", &a_rMACAddress, a_rAddress));
     399    Assert(m_pConfig->isInIPv4Network(a_rAddress)); /* should've been checked elsewhere already */
     400
     401    /*
     402     * If the address is part of the pool, we have to allocate it to
     403     * prevent it from being used again.
     404     */
     405    if (m_pool.contains(a_rAddress))
     406    {
     407        if (!m_pool.allocate(a_rAddress))
     408        {
     409            LogRelFunc(("%RTnaipv4 already allocated?\n", a_rAddress));
     410            return VERR_ADDRESS_CONFLICT;
     411        }
     412    }
     413
     414    /*
     415     * Create the binding.
     416     */
     417    Binding *pBinding = NULL;
     418    try
     419    {
     420        pBinding = new Binding(a_rAddress, a_rMACAddress, true /*fFixed*/);
     421        m_bindings.push_front(pBinding);
     422    }
     423    catch (std::bad_alloc &)
     424    {
     425        if (pBinding)
     426            delete pBinding;
     427        return VERR_NO_MEMORY;
     428    }
     429    return VINF_SUCCESS;
    341430}
    342431
     
    442531        /*
    443532         * We've already seen this client, give it its old binding.
     533         *
     534         * If the client's MAC address is configured with a fixed
     535         * address, give its preconfigured binding.  Fixed bindings
     536         * are always at the head of the m_bindings list, so we
     537         * won't be confused by any old leases of the client.
    444538         */
    445539        if (b->m_id == id)
    446540        {
    447541            LogRel(("> ... found existing binding %R[binding]\n", b));
     542            return b;
     543        }
     544        if (b->isFixed() && b->id().mac() == id.mac())
     545        {
     546            b->idUpdate(id);
     547            LogRel(("> ... found fixed binding %R[binding]\n", b));
    448548            return b;
    449549        }
     
    552652Binding *Db::allocateBinding(const DhcpClientMessage &req)
    553653{
    554     /** @todo XXX: handle fixed address assignments */
     654    const ClientId &id(req.clientId());
    555655
    556656    /*
    557657     * Get and validate the requested address (if present).
     658     *
     659     * Fixed assignments are often outside the dynamic range, so we much detect
     660     * those to make sure they aren't rejected based on IP range.  ASSUMES fixed
     661     * assignments are at the head of the binding list.
    558662     */
    559663    OptRequestedAddress reqAddr(req);
    560664    if (reqAddr.present() && !addressBelongs(reqAddr.value()))
    561665    {
    562         if (req.messageType() == RTNET_DHCP_MT_DISCOVER)
     666        bool fIsFixed = false;
     667        for (bindings_t::iterator it = m_bindings.begin(); it != m_bindings.end() && (*it)->isFixed(); ++it)
     668            if (reqAddr.value().u == (*it)->addr().u)
     669            {
     670                if (   (*it)->id() == id
     671                    || (*it)->id().mac() == id.mac())
     672                {
     673                    fIsFixed = true;
     674                    break;
     675                }
     676            }
     677        if (fIsFixed)
     678            reqAddr = OptRequestedAddress();
     679        else if (req.messageType() == RTNET_DHCP_MT_DISCOVER)
    563680        {
    564681            LogRel(("DISCOVER: ignoring invalid requested address\n"));
     
    572689     * Allocate the address.
    573690     */
    574     const ClientId &id(req.clientId());
    575 
    576691    Binding *b = i_allocateAddress(id, reqAddr.value());
    577692    if (b != NULL)
     
    668783            {
    669784                LogRel2(("Db::cancelOffer: cancelling %R[binding]\n", b));
    670                 b->setLeaseTime(0);
    671                 b->setState(Binding::RELEASED);
     785                if (!b->isFixed())
     786                {
     787                    b->setLeaseTime(0);
     788                    b->setState(Binding::RELEASED);
     789                }
     790                else
     791                    b->setState(Binding::ACKED);
    672792            }
    673793            else
     
    699819        {
    700820            LogRel2(("Db::releaseBinding: releasing %R[binding]\n", b));
    701             b->setState(Binding::RELEASED);
    702             return true;
     821            if (!b->isFixed())
     822            {
     823                b->setState(Binding::RELEASED);
     824                return true;
     825            }
     826            b->setState(Binding::ACKED);
     827            return false;
    703828        }
    704829    }
     
    741866        {
    742867            const Binding *b = *it;
    743             b->toXML(pElmRoot);
     868            if (!b->isFixed())
     869                b->toXML(pElmRoot);
    744870        }
    745871    }
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