Changeset 79818 in vbox for trunk/src/VBox
- Timestamp:
- Jul 16, 2019 7:00:06 PM (5 years ago)
- Location:
- trunk/src/VBox/NetworkServices/Dhcpd
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/Dhcpd/Config.cpp
r79810 r79818 264 264 i_logInit(); 265 265 266 /** @todo the MAC address is always generated, no XML config option for it ... */ 266 267 bool fMACGenerated = false; 267 268 if ( m_MacAddress.au16[0] == 0 … … 291 292 } 292 293 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 342 294 if (!fMACGenerated) 343 295 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));346 296 347 297 return VINF_SUCCESS; … … 685 635 } 686 636 637 /* 638 * Addresses and mask. 639 */ 687 640 ::getIPv4AddrAttribute(pElmServer, "IPAddress", &m_IPv4Address); 688 641 ::getIPv4AddrAttribute(pElmServer, "networkMask", &m_IPv4Netmask); … … 690 643 ::getIPv4AddrAttribute(pElmServer, "upperIP", &m_IPv4PoolLast); 691 644 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 692 671 /* 693 672 * <DHCPServer> children … … 699 678 /* Global options: */ 700 679 if (pElmChild->nameEquals("Options")) 701 m_GlobalConfig.initFromXml(pElmChild, fStrict );680 m_GlobalConfig.initFromXml(pElmChild, fStrict, this); 702 681 /* Group w/ options: */ 703 682 else if (pElmChild->nameEquals("Group")) 704 683 { 705 684 std::unique_ptr<GroupConfig> ptrGroup(new GroupConfig()); 706 ptrGroup->initFromXml(pElmChild, fStrict );685 ptrGroup->initFromXml(pElmChild, fStrict, this); 707 686 if (m_GroupConfigs.find(ptrGroup->getGroupName()) == m_GroupConfigs.end()) 708 687 { … … 721 700 { 722 701 std::unique_ptr<HostConfig> ptrHost(new HostConfig()); 723 ptrHost->initFromXml(pElmChild, fStrict );702 ptrHost->initFromXml(pElmChild, fStrict, this); 724 703 if (m_HostConfigs.find(ptrHost->getMACAddress()) == m_HostConfigs.end()) 725 704 { … … 799 778 * @param fStrict Set if we're in strict mode, clear if we just 800 779 * want to get on with it if we can. 780 * @param pConfig The configuration object. 801 781 * @throws std::bad_alloc, ConfigFileError 802 782 */ 803 void ConfigLevelBase::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict )783 void ConfigLevelBase::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig) 804 784 { 805 785 if (pElmChild->nameEquals("Option")) … … 823 803 else 824 804 throw ConfigFileError(pElmChild->getParent(), "Unexpected child '%s'", pElmChild->getName()); 805 RT_NOREF(pConfig); 825 806 } 826 807 … … 834 815 * @param fStrict Set if we're in strict mode, clear if we just 835 816 * want to get on with it if we can. 817 * @param pConfig The configuration object. 836 818 * @throws std::bad_alloc, ConfigFileError 837 819 */ 838 void ConfigLevelBase::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict )820 void ConfigLevelBase::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict, Config const *pConfig) 839 821 { 840 822 /* … … 854 836 const xml::ElementNode *pElmChild; 855 837 while ((pElmChild = it.forAllNodes()) != NULL) 856 i_parseChild(pElmChild, fStrict );838 i_parseChild(pElmChild, fStrict, pConfig); 857 839 } 858 840 … … 864 846 * @param fStrict Set if we're in strict mode, clear if we just 865 847 * want to get on with it if we can. 848 * @param pConfig The configuration object. 866 849 * @throws std::bad_alloc, ConfigFileError 867 850 */ 868 void GlobalConfig::initFromXml(const xml::ElementNode *pElmOptions, bool fStrict )869 { 870 ConfigLevelBase::initFromXml(pElmOptions, fStrict );851 void GlobalConfig::initFromXml(const xml::ElementNode *pElmOptions, bool fStrict, Config const *pConfig) 852 { 853 ConfigLevelBase::initFromXml(pElmOptions, fStrict, pConfig); 871 854 } 872 855 … … 878 861 * @param fStrict Set if we're in strict mode, clear if we just 879 862 * want to get on with it if we can. 863 * @param pConfig The configuration object. 880 864 * @throws std::bad_alloc, ConfigFileError 881 865 */ 882 void GroupConfig::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict )866 void GroupConfig::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig) 883 867 { 884 868 /* … … 903 887 * Not a condition, pass it on to the base class. 904 888 */ 905 ConfigLevelBase::i_parseChild(pElmChild, fStrict );889 ConfigLevelBase::i_parseChild(pElmChild, fStrict, pConfig); 906 890 return; 907 891 } … … 939 923 { 940 924 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) 944 926 throw Xcpt; 927 LogRelFunc(("%s, ignoring condition\n", Xcpt.what())); 945 928 } 946 929 } … … 953 936 * @param fStrict Set if we're in strict mode, clear if we just 954 937 * want to get on with it if we can. 938 * @param pConfig The configuration object. 955 939 * @throws std::bad_alloc, ConfigFileError 956 940 */ 957 void GroupConfig::initFromXml(const xml::ElementNode *pElmGroup, bool fStrict )941 void GroupConfig::initFromXml(const xml::ElementNode *pElmGroup, bool fStrict, Config const *pConfig) 958 942 { 959 943 /* … … 970 954 * Do common initialization (including children). 971 955 */ 972 ConfigLevelBase::initFromXml(pElmGroup, fStrict );956 ConfigLevelBase::initFromXml(pElmGroup, fStrict, pConfig); 973 957 } 974 958 … … 985 969 * @param fStrict Set if we're in strict mode, clear if we just 986 970 * want to get on with it if we can. 971 * @param pConfig The configuration object (for netmask). 987 972 * @throws std::bad_alloc, ConfigFileError 988 973 */ 989 void HostConfig::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict )974 void HostConfig::initFromXml(const xml::ElementNode *pElmConfig, bool fStrict, Config const *pConfig) 990 975 { 991 976 /* … … 1000 985 1001 986 /* Fixed IP address assignment - optional: */ 1002 const char *pszFixedAddress = pElmConfig->findAttributeValue(" FixedIPAddress");987 const char *pszFixedAddress = pElmConfig->findAttributeValue("fixedAddress"); 1003 988 if (!pszFixedAddress || *RTStrStripL(pszFixedAddress) == '\0') 1004 989 m_fHaveFixedAddress = false; 1005 990 else 1006 991 { 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 } 1009 1003 } 1010 1004 … … 1012 1006 * Do common initialization. 1013 1007 */ 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 */ 1018 int 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; 1015 1034 } 1016 1035 -
trunk/src/VBox/NetworkServices/Dhcpd/Config.h
r79810 r79818 34 34 35 35 36 class Config; 37 36 38 /** 37 39 * Base configuration … … 62 64 { } 63 65 64 virtual void initFromXml(xml::ElementNode const *pElm, bool fStrict );66 virtual void initFromXml(xml::ElementNode const *pElm, bool fStrict, Config const *pConfig); 65 67 virtual const char *getType() const RT_NOEXCEPT = 0; 66 68 virtual const char *getName() const RT_NOEXCEPT = 0; … … 78 80 protected: 79 81 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); 81 83 }; 82 84 … … 91 93 : ConfigLevelBase() 92 94 { } 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; 94 96 const char *getType() const RT_NOEXCEPT RT_OVERRIDE { return "global"; } 95 97 const char *getName() const RT_NOEXCEPT RT_OVERRIDE { return "GlobalConfig"; } … … 199 201 } 200 202 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; 202 204 bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass, const OptUserClassId &a_ridUserClass) const; 203 205 … … 210 212 211 213 protected: 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; 213 215 /** Used to name unnamed groups. */ 214 216 static uint32_t s_uGroupNo; … … 240 242 } 241 243 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; 243 245 const char *getType() const RT_NOEXCEPT RT_OVERRIDE { return "host"; } 244 246 const char *getName() const RT_NOEXCEPT RT_OVERRIDE { return m_strName.c_str(); } … … 246 248 /** @name Accessors 247 249 * @{ */ 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; } 249 253 /** @} */ 250 254 }; … … 257 261 { 258 262 /** Group configuration map. */ 259 typedef std::map<RTCString, GroupConfig * > GroupConfigMap;263 typedef std::map<RTCString, GroupConfig const * > GroupConfigMap; 260 264 /** Host configuration map. */ 261 typedef std::map<RTMAC, HostConfig *> HostConfigMap;265 typedef std::map<RTMAC, HostConfig const * > HostConfigMap; 262 266 263 267 … … 321 325 RTNETADDRIPV4 getIPv4Address() const RT_NOEXCEPT { return m_IPv4Address; } 322 326 RTNETADDRIPV4 getIPv4Netmask() const RT_NOEXCEPT { return m_IPv4Netmask; } 323 324 327 RTNETADDRIPV4 getIPv4PoolFirst() const RT_NOEXCEPT { return m_IPv4PoolFirst; } 325 328 RTNETADDRIPV4 getIPv4PoolLast() const RT_NOEXCEPT { return m_IPv4PoolLast; } 326 329 /** @} */ 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; 327 347 328 348 /** Configuration vector. */ -
trunk/src/VBox/NetworkServices/Dhcpd/DHCPD.cpp
r79800 r79818 267 267 268 268 b->setState(Binding::ACKED); 269 i_saveLeases(); 269 if (!b->isFixed()) 270 i_saveLeases(); 270 271 } 271 272 … … 321 322 322 323 b->setState(Binding::ACKED); 323 i_saveLeases(); 324 if (!b->isFixed()) 325 i_saveLeases(); 324 326 325 327 ack->setYiaddr(b->addr()); -
trunk/src/VBox/NetworkServices/Dhcpd/Db.cpp
r79568 r79818 70 70 if (b->m_state == Binding::FREE) 71 71 cb += pfnOutput(pvArgOutput, RT_STR_TUPLE(" free")); 72 else if (b->m_fFixed) 73 cb += pfnOutput(pvArgOutput, RT_STR_TUPLE(" fixed")); 72 74 else 73 75 { … … 87 89 } 88 90 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 */ 101 void 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 */ 89 111 const char *Binding::stateName() const RT_NOEXCEPT 90 112 { … … 108 130 109 131 132 /** 133 * Sets the state by name (reverse of Binding::stateName()). 134 */ 110 135 Binding &Binding::setState(const char *pszStateName) RT_NOEXCEPT 111 136 { … … 139 164 bool Binding::expire(Timestamp tsDeadline) RT_NOEXCEPT 140 165 { 141 if (m_state <= Binding::EXPIRED )166 if (m_state <= Binding::EXPIRED || m_fFixed) 142 167 return false; 143 168 … … 338 363 m_pConfig = pConfig; 339 364 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 */ 396 int 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; 341 430 } 342 431 … … 442 531 /* 443 532 * 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. 444 538 */ 445 539 if (b->m_id == id) 446 540 { 447 541 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)); 448 548 return b; 449 549 } … … 552 652 Binding *Db::allocateBinding(const DhcpClientMessage &req) 553 653 { 554 /** @todo XXX: handle fixed address assignments */654 const ClientId &id(req.clientId()); 555 655 556 656 /* 557 657 * 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. 558 662 */ 559 663 OptRequestedAddress reqAddr(req); 560 664 if (reqAddr.present() && !addressBelongs(reqAddr.value())) 561 665 { 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) 563 680 { 564 681 LogRel(("DISCOVER: ignoring invalid requested address\n")); … … 572 689 * Allocate the address. 573 690 */ 574 const ClientId &id(req.clientId());575 576 691 Binding *b = i_allocateAddress(id, reqAddr.value()); 577 692 if (b != NULL) … … 668 783 { 669 784 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); 672 792 } 673 793 else … … 699 819 { 700 820 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; 703 828 } 704 829 } … … 741 866 { 742 867 const Binding *b = *it; 743 b->toXML(pElmRoot); 868 if (!b->isFixed()) 869 b->toXML(pElmRoot); 744 870 } 745 871 } -
trunk/src/VBox/NetworkServices/Dhcpd/Db.h
r79568 r79818 55 55 Timestamp m_issued; 56 56 uint32_t m_secLease; 57 /** Set if this is a fixed assignment. */ 58 bool m_fFixed; 57 59 58 60 public: … … 61 63 62 64 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) 64 66 {} 65 67 66 68 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) 68 70 {} 69 71 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 70 81 71 82 /** @name Attribute accessors … … 74 85 75 86 const ClientId &id() const RT_NOEXCEPT { return m_id; } 87 void idUpdate(const ClientId &a_ridClient); 76 88 77 89 uint32_t leaseTime() const RT_NOEXCEPT { return m_secLease; } … … 86 98 return *this; 87 99 } 100 101 bool isFixed() const RT_NOEXCEPT { return m_fFixed; } 88 102 /** @} */ 89 103 … … 152 166 * @note Currently not used. */ 153 167 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. */ 155 171 bindings_t m_bindings; 156 172 /** Address allocation pool. */ … … 183 199 184 200 private: 201 int i_enterFixedAddressAssignment(RTNETADDRIPV4 const &a_rAddress, RTMAC const &a_rMACAddress) RT_NOEXCEPT; 185 202 Binding *i_createBinding(const ClientId &id = ClientId()); 186 203 Binding *i_createBinding(RTNETADDRIPV4 addr, const ClientId &id = ClientId()); -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpMessage.cpp
r79810 r79818 359 359 void DhcpServerMessage::addOptions(const optmap_t &optmap) 360 360 { 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) 362 362 m_optmap << it->second; 363 363 } … … 398 398 << m_optMessageType; 399 399 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) 402 401 { 403 402 LogRel3(("encoding option %d\n", it->first)); … … 409 408 410 409 AssertCompile(RTNET_DHCP_NORMAL_SIZE == 548); 411 if (data.size() < RTNET_DHCP_NORMAL_SIZE) /* XXX */410 if (data.size() < RTNET_DHCP_NORMAL_SIZE) 412 411 data.resize(RTNET_DHCP_NORMAL_SIZE); 413 412
Note:
See TracChangeset
for help on using the changeset viewer.