VirtualBox

Changeset 79818 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 16, 2019 7:00:06 PM (5 years ago)
Author:
vboxsync
Message:

Dhcpd: Fixed address assignments. bugref:9288

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

Legend:

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

    r79810 r79818  
    264264    i_logInit();
    265265
     266    /** @todo the MAC address is always generated, no XML config option for it ... */
    266267    bool fMACGenerated = false;
    267268    if (   m_MacAddress.au16[0] == 0
     
    291292    }
    292293
    293     /* unicast IP address */
    294     if ((m_IPv4Address.au8[0] & 0xe0) == 0xe0)
    295     {
    296         LogRel(("IP address is not unicast: %RTnaipv4\n", m_IPv4Address.u));
    297         return VERR_GENERAL_FAILURE;
    298     }
    299 
    300     /* valid netmask */
    301     int cPrefixBits;
    302     int rc = RTNetMaskToPrefixIPv4(&m_IPv4Netmask, &cPrefixBits);
    303     if (RT_FAILURE(rc) || cPrefixBits == 0)
    304     {
    305         LogRel(("IP mask is not valid: %RTnaipv4\n", m_IPv4Netmask.u));
    306         return VERR_GENERAL_FAILURE;
    307     }
    308 
    309     /* first IP is from the same network */
    310     if ((m_IPv4PoolFirst.u & m_IPv4Netmask.u) != (m_IPv4Address.u & m_IPv4Netmask.u))
    311     {
    312         LogRel(("first pool address is outside the network %RTnaipv4/%d: %RTnaipv4\n",
    313                  (m_IPv4Address.u & m_IPv4Netmask.u), cPrefixBits, m_IPv4PoolFirst.u));
    314         return VERR_GENERAL_FAILURE;
    315     }
    316 
    317     /* last IP is from the same network */
    318     if ((m_IPv4PoolLast.u & m_IPv4Netmask.u) != (m_IPv4Address.u & m_IPv4Netmask.u))
    319     {
    320         LogRel(("last pool address is outside the network %RTnaipv4/%d: %RTnaipv4\n",
    321                  (m_IPv4Address.u & m_IPv4Netmask.u), cPrefixBits, m_IPv4PoolLast.u));
    322         return VERR_GENERAL_FAILURE;
    323     }
    324 
    325     /* the pool is valid */
    326     if (RT_N2H_U32(m_IPv4PoolLast.u) < RT_N2H_U32(m_IPv4PoolFirst.u))
    327     {
    328         LogRel(("pool range is invalid: %RTnaipv4 - %RTnaipv4\n",
    329                  m_IPv4PoolFirst.u, m_IPv4PoolLast.u));
    330         return VERR_GENERAL_FAILURE;
    331     }
    332 
    333     /* our own address is not inside the pool */
    334     if (   RT_N2H_U32(m_IPv4PoolFirst.u) <= RT_N2H_U32(m_IPv4Address.u)
    335         && RT_N2H_U32(m_IPv4Address.u)   <= RT_N2H_U32(m_IPv4PoolLast.u))
    336     {
    337         LogRel(("server address inside the pool range %RTnaipv4 - %RTnaipv4: %RTnaipv4\n",
    338                  m_IPv4PoolFirst.u, m_IPv4PoolLast.u, m_IPv4Address.u));
    339         return VERR_GENERAL_FAILURE;
    340     }
    341 
    342294    if (!fMACGenerated)
    343295        LogRel(("MAC address %RTmac\n", &m_MacAddress));
    344     LogRel(("IP address %RTnaipv4/%d\n", m_IPv4Address.u, cPrefixBits));
    345     LogRel(("address pool %RTnaipv4 - %RTnaipv4\n", m_IPv4PoolFirst.u, m_IPv4PoolLast.u));
    346296
    347297    return VINF_SUCCESS;
     
    685635    }
    686636
     637    /*
     638     * Addresses and mask.
     639     */
    687640    ::getIPv4AddrAttribute(pElmServer, "IPAddress", &m_IPv4Address);
    688641    ::getIPv4AddrAttribute(pElmServer, "networkMask", &m_IPv4Netmask);
     
    690643    ::getIPv4AddrAttribute(pElmServer, "upperIP", &m_IPv4PoolLast);
    691644
     645    /* unicast IP address */
     646    if ((m_IPv4Address.au8[0] & 0xe0) == 0xe0)
     647        throw ConfigFileError("DHCP server IP address is not unicast: %RTnaipv4", m_IPv4Address.u);
     648
     649    /* valid netmask */
     650    int cPrefixBits;
     651    int rc = RTNetMaskToPrefixIPv4(&m_IPv4Netmask, &cPrefixBits);
     652    if (RT_FAILURE(rc) || cPrefixBits == 0)
     653        throw ConfigFileError("IP mask is not valid: %RTnaipv4", m_IPv4Netmask.u);
     654
     655    /* first IP is from the same network */
     656    if ((m_IPv4PoolFirst.u & m_IPv4Netmask.u) != (m_IPv4Address.u & m_IPv4Netmask.u))
     657        throw ConfigFileError("first pool address is outside the network %RTnaipv4/%d: %RTnaipv4",
     658                              (m_IPv4Address.u & m_IPv4Netmask.u), cPrefixBits, m_IPv4PoolFirst.u);
     659
     660    /* last IP is from the same network */
     661    if ((m_IPv4PoolLast.u & m_IPv4Netmask.u) != (m_IPv4Address.u & m_IPv4Netmask.u))
     662        throw ConfigFileError("last pool address is outside the network %RTnaipv4/%d: %RTnaipv4\n",
     663                              (m_IPv4Address.u & m_IPv4Netmask.u), cPrefixBits, m_IPv4PoolLast.u);
     664
     665    /* the pool is valid */
     666    if (RT_N2H_U32(m_IPv4PoolLast.u) < RT_N2H_U32(m_IPv4PoolFirst.u))
     667        throw ConfigFileError("pool range is invalid: %RTnaipv4 - %RTnaipv4", m_IPv4PoolFirst.u, m_IPv4PoolLast.u);
     668    LogRel(("IP address:   %RTnaipv4/%d\n", m_IPv4Address.u, cPrefixBits));
     669    LogRel(("Address pool: %RTnaipv4 - %RTnaipv4\n", m_IPv4PoolFirst.u, m_IPv4PoolLast.u));
     670
    692671    /*
    693672     * <DHCPServer> children
     
    699678        /* Global options: */
    700679        if (pElmChild->nameEquals("Options"))
    701             m_GlobalConfig.initFromXml(pElmChild, fStrict);
     680            m_GlobalConfig.initFromXml(pElmChild, fStrict, this);
    702681        /* Group w/ options: */
    703682        else if (pElmChild->nameEquals("Group"))
    704683        {
    705684            std::unique_ptr<GroupConfig> ptrGroup(new GroupConfig());
    706             ptrGroup->initFromXml(pElmChild, fStrict);
     685            ptrGroup->initFromXml(pElmChild, fStrict, this);
    707686            if (m_GroupConfigs.find(ptrGroup->getGroupName()) == m_GroupConfigs.end())
    708687            {
     
    721700        {
    722701            std::unique_ptr<HostConfig> ptrHost(new HostConfig());
    723             ptrHost->initFromXml(pElmChild, fStrict);
     702            ptrHost->initFromXml(pElmChild, fStrict, this);
    724703            if (m_HostConfigs.find(ptrHost->getMACAddress()) == m_HostConfigs.end())
    725704            {
     
    799778 * @param   fStrict             Set if we're in strict mode, clear if we just
    800779 *                              want to get on with it if we can.
     780 * @param   pConfig             The configuration object.
    801781 * @throws  std::bad_alloc, ConfigFileError
    802782 */
    803 void ConfigLevelBase::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict)
     783void ConfigLevelBase::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig)
    804784{
    805785    if (pElmChild->nameEquals("Option"))
     
    823803    else
    824804        throw ConfigFileError(pElmChild->getParent(), "Unexpected child '%s'", pElmChild->getName());
     805    RT_NOREF(pConfig);
    825806}
    826807
     
    834815 * @param   fStrict             Set if we're in strict mode, clear if we just
    835816 *                              want to get on with it if we can.
     817 * @param   pConfig             The configuration object.
    836818 * @throws  std::bad_alloc, ConfigFileError
    837819 */
    838 void ConfigLevelBase::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict)
     820void ConfigLevelBase::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict, Config const *pConfig)
    839821{
    840822    /*
     
    854836    const xml::ElementNode *pElmChild;
    855837    while ((pElmChild = it.forAllNodes()) != NULL)
    856         i_parseChild(pElmChild, fStrict);
     838        i_parseChild(pElmChild, fStrict, pConfig);
    857839}
    858840
     
    864846 * @param   fStrict             Set if we're in strict mode, clear if we just
    865847 *                              want to get on with it if we can.
     848 * @param   pConfig             The configuration object.
    866849 * @throws  std::bad_alloc, ConfigFileError
    867850 */
    868 void GlobalConfig::initFromXml(const xml::ElementNode *pElmOptions, bool fStrict)
    869 {
    870     ConfigLevelBase::initFromXml(pElmOptions, fStrict);
     851void GlobalConfig::initFromXml(const xml::ElementNode *pElmOptions, bool fStrict, Config const *pConfig)
     852{
     853    ConfigLevelBase::initFromXml(pElmOptions, fStrict, pConfig);
    871854}
    872855
     
    878861 * @param   fStrict             Set if we're in strict mode, clear if we just
    879862 *                              want to get on with it if we can.
     863 * @param   pConfig             The configuration object.
    880864 * @throws  std::bad_alloc, ConfigFileError
    881865 */
    882 void GroupConfig::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict)
     866void GroupConfig::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig)
    883867{
    884868    /*
     
    903887         * Not a condition, pass it on to the base class.
    904888         */
    905         ConfigLevelBase::i_parseChild(pElmChild, fStrict);
     889        ConfigLevelBase::i_parseChild(pElmChild, fStrict, pConfig);
    906890        return;
    907891    }
     
    939923    {
    940924        ConfigFileError Xcpt(pElmChild, "condition value is empty or missing (inclusive=%RTbool)", fInclusive);
    941         if (!fStrict)
    942             LogRelFunc(("%s, ignoring condition\n", Xcpt.what()));
    943         else
     925        if (fStrict)
    944926            throw Xcpt;
     927        LogRelFunc(("%s, ignoring condition\n", Xcpt.what()));
    945928    }
    946929}
     
    953936 * @param   fStrict             Set if we're in strict mode, clear if we just
    954937 *                              want to get on with it if we can.
     938 * @param   pConfig             The configuration object.
    955939 * @throws  std::bad_alloc, ConfigFileError
    956940 */
    957 void GroupConfig::initFromXml(const xml::ElementNode *pElmGroup, bool fStrict)
     941void GroupConfig::initFromXml(const xml::ElementNode *pElmGroup, bool fStrict, Config const *pConfig)
    958942{
    959943    /*
     
    970954     * Do common initialization (including children).
    971955     */
    972     ConfigLevelBase::initFromXml(pElmGroup, fStrict);
     956    ConfigLevelBase::initFromXml(pElmGroup, fStrict, pConfig);
    973957}
    974958
     
    985969 * @param   fStrict             Set if we're in strict mode, clear if we just
    986970 *                              want to get on with it if we can.
     971 * @param   pConfig             The configuration object (for netmask).
    987972 * @throws  std::bad_alloc, ConfigFileError
    988973 */
    989 void HostConfig::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict)
     974void HostConfig::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict, Config const *pConfig)
    990975{
    991976    /*
     
    1000985
    1001986    /* Fixed IP address assignment - optional: */
    1002     const char *pszFixedAddress = pElmConfig->findAttributeValue("FixedIPAddress");
     987    const char *pszFixedAddress = pElmConfig->findAttributeValue("fixedAddress");
    1003988    if (!pszFixedAddress || *RTStrStripL(pszFixedAddress) == '\0')
    1004989        m_fHaveFixedAddress = false;
    1005990    else
    1006991    {
    1007         m_fHaveFixedAddress = false;
    1008         ::getIPv4AddrAttribute(pElmConfig, "FixedIPAddress", &m_FixedAddress);
     992        ::getIPv4AddrAttribute(pElmConfig, "fixedAddress", &m_FixedAddress);
     993        if (pConfig->isInIPv4Network(m_FixedAddress))
     994            m_fHaveFixedAddress = true;
     995        else
     996        {
     997            ConfigFileError Xcpt(pElmConfig, "fixedAddress '%s' is not the DHCP network", pszFixedAddress);
     998            if (fStrict)
     999                throw Xcpt;
     1000            LogRelFunc(("%s - ignoring the fixed address assignment\n", Xcpt.what()));
     1001            m_fHaveFixedAddress = false;
     1002        }
    10091003    }
    10101004
     
    10121006     * Do common initialization.
    10131007     */
    1014     ConfigLevelBase::initFromXml(pElmConfig, fStrict);
     1008    ConfigLevelBase::initFromXml(pElmConfig, fStrict, pConfig);
     1009}
     1010
     1011
     1012/**
     1013 * Assembles a list of hosts with fixed address assignments.
     1014 *
     1015 * @returns IPRT status code.
     1016 * @param   a_rRetConfigs       Where to return the configurations.
     1017 */
     1018int Config::getFixedAddressConfigs(HostConfigVec &a_rRetConfigs) const
     1019{
     1020    for (HostConfigMap::const_iterator it = m_HostConfigs.begin(); it != m_HostConfigs.end(); ++it)
     1021    {
     1022        HostConfig const *pHostConfig = it->second;
     1023        if (pHostConfig->haveFixedAddress())
     1024            try
     1025            {
     1026                a_rRetConfigs.push_back(pHostConfig);
     1027            }
     1028            catch (std::bad_alloc &)
     1029            {
     1030                return VERR_NO_MEMORY;
     1031            }
     1032    }
     1033    return VINF_SUCCESS;
    10151034}
    10161035
  • trunk/src/VBox/NetworkServices/Dhcpd/Config.h

    r79810 r79818  
    3434
    3535
     36class Config;
     37
    3638/**
    3739 * Base configuration
     
    6264    { }
    6365
    64     virtual void        initFromXml(xml::ElementNode const *pElm, bool fStrict);
     66    virtual void        initFromXml(xml::ElementNode const *pElm, bool fStrict, Config const *pConfig);
    6567    virtual const char *getType() const RT_NOEXCEPT = 0;
    6668    virtual const char *getName() const RT_NOEXCEPT = 0;
     
    7880protected:
    7981    void            i_parseOption(const xml::ElementNode *pElmOption);
    80     virtual void    i_parseChild(const xml::ElementNode *pElmChild, bool fStrict);
     82    virtual void    i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig);
    8183};
    8284
     
    9193        : ConfigLevelBase()
    9294    { }
    93     void initFromXml(xml::ElementNode const *pElm, bool fStrict) RT_OVERRIDE;
     95    void initFromXml(xml::ElementNode const *pElm, bool fStrict, Config const *pConfig) RT_OVERRIDE;
    9496    const char *getType() const RT_NOEXCEPT RT_OVERRIDE { return "global"; }
    9597    const char *getName() const RT_NOEXCEPT RT_OVERRIDE { return "GlobalConfig"; }
     
    199201    }
    200202
    201     void initFromXml(xml::ElementNode const *pElm, bool fStrict) RT_OVERRIDE;
     203    void initFromXml(xml::ElementNode const *pElm, bool fStrict, Config const *pConfig) RT_OVERRIDE;
    202204    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass, const OptUserClassId &a_ridUserClass) const;
    203205
     
    210212
    211213protected:
    212     void                i_parseChild(const xml::ElementNode *pElmChild, bool fStrict) RT_OVERRIDE;
     214    void                i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig) RT_OVERRIDE;
    213215    /** Used to name unnamed groups. */
    214216    static uint32_t     s_uGroupNo;
     
    240242    }
    241243
    242     void initFromXml(xml::ElementNode const *pElm, bool fStrict) RT_OVERRIDE;
     244    void initFromXml(xml::ElementNode const *pElm, bool fStrict, Config const *pConfig) RT_OVERRIDE;
    243245    const char *getType() const RT_NOEXCEPT RT_OVERRIDE { return "host"; }
    244246    const char *getName() const RT_NOEXCEPT RT_OVERRIDE { return m_strName.c_str(); }
     
    246248    /** @name Accessors
    247249     * @{ */
    248     RTMAC const        &getMACAddress() const RT_NOEXCEPT       { return m_MACAddress; }
     250    RTMAC const            &getMACAddress() const RT_NOEXCEPT       { return m_MACAddress; }
     251    bool                    haveFixedAddress() const RT_NOEXCEPT    { return m_fHaveFixedAddress; }
     252    RTNETADDRIPV4 const &   getFixedAddress() const RT_NOEXCEPT     { return m_FixedAddress; }
    249253    /** @} */
    250254};
     
    257261{
    258262    /** Group configuration map. */
    259     typedef std::map<RTCString, GroupConfig * > GroupConfigMap;
     263    typedef std::map<RTCString, GroupConfig const * > GroupConfigMap;
    260264    /** Host configuration map. */
    261     typedef std::map<RTMAC,     HostConfig * > HostConfigMap;
     265    typedef std::map<RTMAC,     HostConfig const * > HostConfigMap;
    262266
    263267
     
    321325    RTNETADDRIPV4       getIPv4Address() const RT_NOEXCEPT      { return m_IPv4Address; }
    322326    RTNETADDRIPV4       getIPv4Netmask() const RT_NOEXCEPT      { return m_IPv4Netmask; }
    323 
    324327    RTNETADDRIPV4       getIPv4PoolFirst() const RT_NOEXCEPT    { return m_IPv4PoolFirst; }
    325328    RTNETADDRIPV4       getIPv4PoolLast() const RT_NOEXCEPT     { return m_IPv4PoolLast; }
    326329    /** @} */
     330
     331    /** Gets the network (IP masked by network mask). */
     332    RTNETADDRIPV4       getIPv4Network() const RT_NOEXCEPT
     333    {
     334        RTNETADDRIPV4 Network;
     335        Network.u = m_IPv4Netmask.u & m_IPv4Address.u;
     336        return Network;
     337    }
     338    /** Checks if the given IPv4 address is in the DHCP server network. */
     339    bool                isInIPv4Network(RTNETADDRIPV4 a_rAddress) const RT_NOEXCEPT
     340    {
     341        return (a_rAddress.u & getIPv4Netmask().u) == getIPv4Network().u;
     342    }
     343
     344    /** Host configuration vector. */
     345    typedef std::vector<HostConfig const *> HostConfigVec;
     346    int                 getFixedAddressConfigs(HostConfigVec &a_rRetConfigs) const;
    327347
    328348    /** Configuration vector. */
  • trunk/src/VBox/NetworkServices/Dhcpd/DHCPD.cpp

    r79800 r79818  
    267267
    268268        b->setState(Binding::ACKED);
    269         i_saveLeases();
     269        if (!b->isFixed())
     270            i_saveLeases();
    270271    }
    271272
     
    321322
    322323    b->setState(Binding::ACKED);
    323     i_saveLeases();
     324    if (!b->isFixed())
     325        i_saveLeases();
    324326
    325327    ack->setYiaddr(b->addr());
  • 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    }
  • trunk/src/VBox/NetworkServices/Dhcpd/Db.h

    r79568 r79818  
    5555    Timestamp           m_issued;
    5656    uint32_t            m_secLease;
     57    /** Set if this is a fixed assignment. */
     58    bool                m_fFixed;
    5759
    5860public:
     
    6163
    6264    explicit Binding(RTNETADDRIPV4 a_Addr)
    63         : m_addr(a_Addr), m_state(FREE), m_issued(), m_secLease()
     65        : m_addr(a_Addr), m_state(FREE), m_issued(), m_secLease(0), m_fFixed(false)
    6466    {}
    6567
    6668    Binding(RTNETADDRIPV4 a_Addr, const ClientId &a_id)
    67         : m_addr(a_Addr), m_state(FREE), m_id(a_id), m_issued(), m_secLease()
     69        : m_addr(a_Addr), m_state(FREE), m_id(a_id), m_issued(), m_secLease(0), m_fFixed(false)
    6870    {}
    6971
     72    Binding(RTNETADDRIPV4 a_Addr, const RTMAC &a_MACAddress, bool a_fFixed)
     73        : m_addr(a_Addr)
     74        , m_state(ACKED)
     75        , m_id(ClientId(a_MACAddress, OptClientId()))
     76        , m_issued(Timestamp::now())
     77        , m_secLease(UINT32_MAX - 1)
     78        , m_fFixed(a_fFixed)
     79    {}
     80
    7081
    7182    /** @name Attribute accessors
     
    7485
    7586    const ClientId &id() const RT_NOEXCEPT          { return m_id; }
     87    void            idUpdate(const ClientId &a_ridClient);
    7688
    7789    uint32_t        leaseTime() const RT_NOEXCEPT   { return m_secLease; }
     
    8698        return *this;
    8799    }
     100
     101    bool            isFixed() const RT_NOEXCEPT     { return m_fFixed; }
    88102    /** @} */
    89103
     
    152166     * @note Currently not used.  */
    153167    const Config   *m_pConfig;
    154     /** The lease database. */
     168    /** The lease database.
     169     * @note Since fixed assignments are added during initialization, they will
     170     *       always be first.  The allocateBinding() code depends on this.  */
    155171    bindings_t      m_bindings;
    156172    /** Address allocation pool. */
     
    183199
    184200private:
     201    int      i_enterFixedAddressAssignment(RTNETADDRIPV4 const &a_rAddress, RTMAC const &a_rMACAddress) RT_NOEXCEPT;
    185202    Binding *i_createBinding(const ClientId &id = ClientId());
    186203    Binding *i_createBinding(RTNETADDRIPV4 addr, const ClientId &id = ClientId());
  • trunk/src/VBox/NetworkServices/Dhcpd/DhcpMessage.cpp

    r79810 r79818  
    359359void DhcpServerMessage::addOptions(const optmap_t &optmap)
    360360{
    361     for (optmap_t::const_iterator it( optmap.begin() ); it != optmap.end(); ++it)
     361    for (optmap_t::const_iterator it = optmap.begin(); it != optmap.end(); ++it)
    362362        m_optmap << it->second;
    363363}
     
    398398         << m_optMessageType;
    399399
    400     for (optmap_t::const_iterator it ( m_optmap.begin() );
    401          it != m_optmap.end(); ++it)
     400    for (optmap_t::const_iterator it = m_optmap.begin(); it != m_optmap.end(); ++it)
    402401    {
    403402        LogRel3(("encoding option %d\n", it->first));
     
    409408
    410409    AssertCompile(RTNET_DHCP_NORMAL_SIZE == 548);
    411     if (data.size() < RTNET_DHCP_NORMAL_SIZE)      /* XXX */
     410    if (data.size() < RTNET_DHCP_NORMAL_SIZE)
    412411        data.resize(RTNET_DHCP_NORMAL_SIZE);
    413412
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