Changeset 79865 in vbox for trunk/src/VBox/NetworkServices/Dhcpd
- Timestamp:
- Jul 18, 2019 8:31:15 PM (6 years ago)
- Location:
- trunk/src/VBox/NetworkServices/Dhcpd
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/Dhcpd/Config.cpp
r79825 r79865 773 773 774 774 /** 775 * Internal worker for parsing \<ForcedOption\> and \<SupressedOption\> elements 776 * found under /DHCPServer/Options/, /DHCPServer/Group/ and /DHCPServer/Config/. 777 * 778 * @param pElmOption The element. 779 * @param fForced Whether it's a ForcedOption (true) or 780 * SuppressedOption element. 781 * @throws std::bad_alloc, ConfigFileError 782 */ 783 void ConfigLevelBase::i_parseForcedOrSuppressedOption(const xml::ElementNode *pElmOption, bool fForced) 784 { 785 /* Only a name attribute: */ 786 const char *pszName; 787 if (!pElmOption->getAttributeValue("name", &pszName)) 788 throw ConfigFileError(pElmOption, "missing option name"); 789 790 uint8_t u8Opt; 791 int rc = RTStrToUInt8Full(pszName, 10, &u8Opt); 792 if (rc != VINF_SUCCESS) /* no warnings either */ 793 throw ConfigFileError(pElmOption, "Bad option name '%s': %Rrc", pszName, rc); 794 795 if (fForced) 796 m_vecForcedOptions.push_back(u8Opt); 797 else 798 m_vecSuppressedOptions.push_back(u8Opt); 799 } 800 801 802 /** 775 803 * Final children parser, handling only \<Option\> and barfing at anything else. 776 804 * 777 805 * @param pElmChild The child element to handle. 778 806 * @param fStrict Set if we're in strict mode, clear if we just 779 * want to get on with it if we can. 807 * want to get on with it if we can. That said, 808 * the caller will catch ConfigFileError exceptions 809 * and ignore them if @a fStrict is @c false. 780 810 * @param pConfig The configuration object. 781 811 * @throws std::bad_alloc, ConfigFileError … … 783 813 void ConfigLevelBase::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig) 784 814 { 815 /* 816 * Options. 817 */ 785 818 if (pElmChild->nameEquals("Option")) 786 819 { 787 try788 {789 i_parseOption(pElmChild);790 } 791 catch (ConfigFileError &rXcpt)792 {793 if (fStrict)794 throw rXcpt;795 LogRelFunc(("Ignoring option: %s\n", rXcpt.what()));796 }797 }798 else if (!fStrict)799 {800 ConfigFileError Dummy(pElmChild->getParent(), "Unexpected child '%s'", pElmChild->getName()); 801 LogRelFunc(("%s\n", Dummy.what()));802 }803 else804 805 RT_NOREF( pConfig);820 i_parseOption(pElmChild); 821 return; 822 } 823 824 /* 825 * Forced and supressed options. 826 */ 827 bool const fForced = pElmChild->nameEquals("ForcedOption"); 828 if (fForced || pElmChild->nameEquals("SuppressedOption")) 829 { 830 i_parseForcedOrSuppressedOption(pElmChild, fForced); 831 return; 832 } 833 834 /* 835 * What's this? 836 */ 837 throw ConfigFileError(pElmChild->getParent(), "Unexpected child '%s'", pElmChild->getName()); 838 RT_NOREF(fStrict, pConfig); 806 839 } 807 840 … … 845 878 const xml::ElementNode *pElmChild; 846 879 while ((pElmChild = it.forAllNodes()) != NULL) 847 i_parseChild(pElmChild, fStrict, pConfig); 880 { 881 try 882 { 883 i_parseChild(pElmChild, fStrict, pConfig); 884 } 885 catch (ConfigFileError &rXcpt) 886 { 887 if (fStrict) 888 throw rXcpt; 889 LogRelFunc(("Ignoring: %s\n", rXcpt.what())); 890 } 891 } 848 892 } 849 893 … … 1117 1161 { 1118 1162 /* 1163 * The client typcially requests a list of options. The list is subject to 1164 * forced and supressed lists on each configuration level in a_rConfig. To 1165 * efficiently manage it without resorting to maps, the current code 1166 * assembles a C-style array of options on the stack that should be returned 1167 * to the client. 1168 */ 1169 uint8_t abOptions[256]; 1170 size_t cOptions = 0; 1171 size_t iFirstForced = 255; 1172 #define IS_OPTION_PRESENT(a_bOption) (memchr(abOptions, (a_bOption), cOptions) != NULL) 1173 #define APPEND_NOT_PRESENT_OPTION(a_bOption) do { \ 1174 AssertLogRelMsgBreak(cOptions < sizeof(abOptions), \ 1175 ("a_bOption=%#x abOptions=%.*Rhxs\n", (a_bOption), sizeof(abOptions), &abOptions[0])); \ 1176 abOptions[cOptions++] = (a_bOption); \ 1177 } while (0) 1178 1179 const OptParameterRequest::value_t &reqValue = a_rReqOpts.value(); 1180 if (reqValue.size() != 0) 1181 { 1182 /* Copy the requested list and append any forced options from the configs: */ 1183 for (octets_t::const_iterator itOptReq = reqValue.begin(); itOptReq != reqValue.end(); ++itOptReq) 1184 if (!IS_OPTION_PRESENT(*itOptReq)) 1185 APPEND_NOT_PRESENT_OPTION(*itOptReq); 1186 iFirstForced = cOptions; 1187 for (Config::ConfigVec::const_iterator itCfg = a_rConfigs.begin(); itCfg != a_rConfigs.end(); ++itCfg) 1188 { 1189 octets_t const &rForced = (*itCfg)->getForcedOptions(); 1190 for (octets_t::const_iterator itOpt = rForced.begin(); itOpt != rForced.end(); ++itOpt) 1191 if (!IS_OPTION_PRESENT(*itOpt)) 1192 { 1193 LogRel3((">>> Forcing option %d (%s)\n", *itOpt, DhcpOption::name(*itOpt))); 1194 APPEND_NOT_PRESENT_OPTION(*itOpt); 1195 } 1196 } 1197 } 1198 else 1199 { 1200 /* No options requests, feed the client all available options: */ 1201 for (Config::ConfigVec::const_iterator itCfg = a_rConfigs.begin(); itCfg != a_rConfigs.end(); ++itCfg) 1202 { 1203 optmap_t const &rOptions = (*itCfg)->getOptions(); 1204 for (optmap_t::const_iterator itOpt = rOptions.begin(); itOpt != rOptions.end(); ++itOpt) 1205 if (!IS_OPTION_PRESENT(itOpt->first)) 1206 APPEND_NOT_PRESENT_OPTION(itOpt->first); 1207 1208 } 1209 } 1210 1211 /* 1119 1212 * Always supply the subnet: 1120 1213 */ 1121 1214 a_rRetOpts << new OptSubnetMask(m_IPv4Netmask); 1122 1215 1123 /** @todo If a_rReqOpts is not present, provide the sum of all options in 1124 * a_rConfigs like ics says it does. */ 1125 /** @todo Look thru a_rConfigs for forced options, maybe we do it by using 1126 * DHCP option 55, and merging these into a_rReqOpts. */ 1127 /** @todo Have a way to mute options, i.e. break out of the inner search 1128 * loop below. Maybe using 'Suppress' encoding? */ 1129 1130 /* 1131 * Try provide the requested options: 1132 */ 1133 const OptParameterRequest::value_t &reqValue = a_rReqOpts.value(); 1134 for (octets_t::const_iterator itOptReq = reqValue.begin(); itOptReq != reqValue.end(); ++itOptReq) 1135 { 1136 uint8_t bOptReq = *itOptReq; 1137 LogRel2((">>> requested option %d (%#x)\n", bOptReq, bOptReq)); 1216 /* 1217 * Try provide the options we've decided to return. 1218 */ 1219 for (size_t iOpt = 0; iOpt < cOptions; iOpt++) 1220 { 1221 uint8_t const bOptReq = abOptions[iOpt]; 1222 if (iOpt < iFirstForced) 1223 LogRel2((">>> requested option %d (%s)\n", bOptReq, DhcpOption::name(bOptReq))); 1224 else 1225 LogRel2((">>> forced option %d (%s)\n", bOptReq, DhcpOption::name(bOptReq))); 1138 1226 1139 1227 if (bOptReq != OptSubnetMask::optcode) … … 1142 1230 for (size_t i = 0; i < a_rConfigs.size(); i++) 1143 1231 { 1144 optmap_t::const_iterator itFound; 1145 if (a_rConfigs[i]->findOption(bOptReq, itFound)) /* crap interface */ 1232 if (!a_rConfigs[i]->isOptionSuppressed(bOptReq)) 1146 1233 { 1147 LogRel2(("... found in %s (type %s)\n", a_rConfigs[i]->getName(), a_rConfigs[i]->getType())); 1148 a_rRetOpts << itFound->second; 1234 optmap_t::const_iterator itFound; 1235 if (a_rConfigs[i]->findOption(bOptReq, itFound)) /* crap interface */ 1236 { 1237 LogRel2(("... found in %s (type %s)\n", a_rConfigs[i]->getName(), a_rConfigs[i]->getType())); 1238 a_rRetOpts << itFound->second; 1239 fFound = true; 1240 break; 1241 } 1242 } 1243 else 1244 { 1245 LogRel2(("... suppressed by %s (type %s)\n", a_rConfigs[i]->getName(), a_rConfigs[i]->getType())); 1149 1246 fFound = true; 1150 1247 break; … … 1158 1255 } 1159 1256 1257 #undef IS_OPTION_PRESENT 1258 #undef APPEND_NOT_PRESENT_OPTION 1160 1259 return a_rRetOpts; 1161 1260 } -
trunk/src/VBox/NetworkServices/Dhcpd/Config.h
r79824 r79865 54 54 uint32_t m_secMaxLeaseTime; 55 55 56 /** Options forced unsolicited upon the client. */ 57 octets_t m_vecForcedOptions; 58 /** Options (typcially from higher up) that should be hidden from the client. */ 59 octets_t m_vecSuppressedOptions; 60 56 61 public: 57 62 ConfigLevelBase() … … 60 65 , m_secDefaultLeaseTime(0) 61 66 , m_secMaxLeaseTime(0) 67 , m_vecForcedOptions() 68 , m_vecSuppressedOptions() 62 69 { } 63 70 … … 79 86 } 80 87 88 /** Checks if @a bOpt is suppressed or not. */ 89 bool isOptionSuppressed(uint8_t bOpt) const RT_NOEXCEPT 90 { 91 return m_vecSuppressedOptions.size() > 0 92 && memchr(&m_vecSuppressedOptions.front(), bOpt, m_vecSuppressedOptions.size()) != NULL; 93 } 94 81 95 /** @name Accessors 82 96 * @{ */ 83 uint32_t getMinLeaseTime() const RT_NOEXCEPT { return m_secMinLeaseTime; } 84 uint32_t getDefaultLeaseTime() const RT_NOEXCEPT { return m_secDefaultLeaseTime; } 85 uint32_t getMaxLeaseTime() const RT_NOEXCEPT { return m_secMaxLeaseTime; } 97 uint32_t getMinLeaseTime() const RT_NOEXCEPT { return m_secMinLeaseTime; } 98 uint32_t getDefaultLeaseTime() const RT_NOEXCEPT { return m_secDefaultLeaseTime; } 99 uint32_t getMaxLeaseTime() const RT_NOEXCEPT { return m_secMaxLeaseTime; } 100 octets_t const &getForcedOptions() const RT_NOEXCEPT { return m_vecForcedOptions; } 101 octets_t const &getSuppressedOptions() const RT_NOEXCEPT { return m_vecSuppressedOptions; } 102 optmap_t const &getOptions() const RT_NOEXCEPT { return m_Options; } 86 103 /** @} */ 87 104 88 105 protected: 89 106 void i_parseOption(const xml::ElementNode *pElmOption); 107 void i_parseForcedOrSuppressedOption(const xml::ElementNode *pElmOption, bool fForced); 90 108 virtual void i_parseChild(const xml::ElementNode *pElmChild, bool fStrict, Config const *pConfig); 91 109 }; -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpMessage.cpp
r79818 r79865 400 400 for (optmap_t::const_iterator it = m_optmap.begin(); it != m_optmap.end(); ++it) 401 401 { 402 LogRel3(("encoding option %d \n", it->first));402 LogRel3(("encoding option %d (%s)\n", it->first, DhcpOption::name(it->first))); 403 403 DhcpOption &opt = *it->second; 404 404 data << opt; -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.cpp
r79845 r79865 285 285 286 286 287 DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc /*= NULL*/)287 /*static*/ DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc /*= NULL*/) 288 288 { 289 289 int rcIgn; … … 402 402 } 403 403 } 404 405 406 /** 407 * Gets the option name (simply "unknown" if not known) for logging purposes. 408 */ 409 /*static*/ const char *DhcpOption::name(uint8_t aOptCode) 410 { 411 switch (aOptCode) 412 { 413 #define HANDLE(a_OptClass) \ 414 case a_OptClass::optcode: \ 415 return &#a_OptClass[3] 416 417 HANDLE(OptSubnetMask); // 1 418 HANDLE(OptTimeOffset); // 2 419 HANDLE(OptRouters); // 3 420 HANDLE(OptTimeServers); // 4 421 HANDLE(OptNameServers); // 5 422 HANDLE(OptDNSes); // 6 423 HANDLE(OptLogServers); // 7 424 HANDLE(OptCookieServers); // 8 425 HANDLE(OptLPRServers); // 9 426 HANDLE(OptImpressServers); // 10 427 HANDLE(OptResourceLocationServers); // 11 428 HANDLE(OptHostName); // 12 429 HANDLE(OptBootFileSize); // 13 430 HANDLE(OptMeritDumpFile); // 14 431 HANDLE(OptDomainName); // 15 432 HANDLE(OptSwapServer); // 16 433 HANDLE(OptRootPath); // 17 434 HANDLE(OptExtensionPath); // 18 435 HANDLE(OptIPForwarding); // 19 436 HANDLE(OptNonLocalSourceRouting); // 20 437 HANDLE(OptPolicyFilter); // 21 438 HANDLE(OptMaxDgramReassemblySize); // 22 439 HANDLE(OptDefaultIPTTL); // 23 440 HANDLE(OptPathMTUAgingTimeout); // 24 441 HANDLE(OptPathMTUPlateauTable); // 25 442 HANDLE(OptInterfaceMTU); // 26 443 HANDLE(OptAllSubnetsAreLocal); // 27 444 HANDLE(OptBroadcastAddress); // 28 445 HANDLE(OptPerformMaskDiscovery); // 29 446 HANDLE(OptMaskSupplier); // 30 447 HANDLE(OptPerformRouterDiscovery); // 31 448 HANDLE(OptRouterSolicitationAddress); // 32 449 HANDLE(OptStaticRoute); // 33 450 HANDLE(OptTrailerEncapsulation); // 34 451 HANDLE(OptARPCacheTimeout); // 35 452 HANDLE(OptEthernetEncapsulation); // 36 453 HANDLE(OptTCPDefaultTTL); // 37 454 HANDLE(OptTCPKeepaliveInterval); // 38 455 HANDLE(OptTCPKeepaliveGarbage); // 39 456 HANDLE(OptNISDomain); // 40 457 HANDLE(OptNISServers); // 41 458 HANDLE(OptNTPServers); // 42 459 HANDLE(OptVendorSpecificInfo); // 43 460 HANDLE(OptNetBIOSNameServers); // 44 461 HANDLE(OptNetBIOSDatagramServers); // 45 462 HANDLE(OptNetBIOSNodeType); // 46 463 HANDLE(OptNetBIOSScope); // 47 464 HANDLE(OptXWindowsFontServers); // 48 465 HANDLE(OptXWindowsDisplayManager); // 49 466 HANDLE(OptRequestedAddress); // 50 467 HANDLE(OptLeaseTime); // 51 468 //HANDLE(OptOptionOverload); // 52 469 HANDLE(OptMessageType); // 53 470 HANDLE(OptServerId); // 54 471 HANDLE(OptParameterRequest); // 55 472 HANDLE(OptMessage); // 56 473 HANDLE(OptMaxDHCPMessageSize); // 57 474 HANDLE(OptRenewalTime); // 58 475 HANDLE(OptRebindingTime); // 59 476 HANDLE(OptVendorClassId); // 60 477 HANDLE(OptClientId); // 61 478 HANDLE(OptNetWareIPDomainName); // 62 479 HANDLE(OptNetWareIPInformation); // 63 480 HANDLE(OptNISPlusDomain); // 64 481 HANDLE(OptNISPlusServers); // 65 482 HANDLE(OptTFTPServerName); // 66 483 HANDLE(OptBootfileName); // 67 484 HANDLE(OptMobileIPHomeAgents); // 68 485 HANDLE(OptSMTPServers); // 69 486 HANDLE(OptPOP3Servers); // 70 487 HANDLE(OptNNTPServers); // 71 488 HANDLE(OptWWWServers); // 72 489 HANDLE(OptFingerServers); // 73 490 HANDLE(OptIRCServers); // 74 491 HANDLE(OptStreetTalkServers); // 75 492 HANDLE(OptSTDAServers); // 76 493 HANDLE(OptUserClassId); // 77 494 HANDLE(OptSLPDirectoryAgent); // 78 - Only DHCPOptionEncoding_hex 495 HANDLE(OptSLPServiceScope); // 79 - Only DHCPOptionEncoding_hex 496 HANDLE(OptRapidCommit); // 80 497 498 HANDLE(OptDomainSearch); // 119 - Only DHCPOptionEncoding_hex 499 500 #undef HANDLE 501 default: 502 return "unknown"; 503 } 504 } 505 -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.h
r79845 r79865 62 62 public: 63 63 static DhcpOption *parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc = NULL); 64 static const char *name(uint8_t bOptcode); 64 65 65 66 public:
Note:
See TracChangeset
for help on using the changeset viewer.