Changeset 71689 in vbox
- Timestamp:
- Apr 5, 2018 3:20:32 PM (7 years ago)
- Location:
- trunk/src/VBox/NetworkServices/Dhcpd
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/Dhcpd/Config.cpp
r71353 r71689 16 16 */ 17 17 18 #include "Config.h" 19 18 20 #include <iprt/types.h> 19 21 #include <iprt/net.h> /* NB: must come before getopt.h */ … … 22 24 #include <iprt/message.h> 23 25 #include <iprt/string.h> 24 25 #include "Config.h" 26 27 28 bool Config::isSane() 29 { 30 int rc; 26 #include <iprt/uuid.h> 27 28 #include <VBox/com/com.h> 29 30 #include <iostream> 31 32 class ConfigFileError 33 : public RTCError 34 { 35 public: 36 ConfigFileError(const char *pszMessage) 37 : RTCError(pszMessage) {} 38 39 ConfigFileError(const RTCString &a_rstrMessage) 40 : RTCError(a_rstrMessage) {} 41 }; 42 43 44 Config::Config() 45 : m_strHome(), 46 m_strNetwork(), 47 m_strBaseName(), 48 m_strTrunk(), 49 m_enmTrunkType(kIntNetTrunkType_Invalid), 50 m_MacAddress(), 51 m_IPv4Address(), 52 m_IPv4Netmask(), 53 m_IPv4PoolFirst(), 54 m_IPv4PoolLast(), 55 m_GlobalOptions(), 56 m_VMMap() 57 { 58 return; 59 } 60 61 62 int Config::init() 63 { 64 int rc; 65 66 rc = homeInit(); 67 if (RT_FAILURE(rc)) 68 return rc; 69 70 return VINF_SUCCESS; 71 } 72 73 74 int Config::homeInit() 75 { 76 int rc; 77 78 /* pathname of ~/.VirtualBox or equivalent */ 79 char szHome[RTPATH_MAX]; 80 rc = com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome), false); 81 if (RT_FAILURE(rc)) 82 { 83 LogDHCP(("unable to find VirtualBox home directory: %Rrs", rc)); 84 return rc; 85 } 86 87 m_strHome.assign(szHome); 88 return VINF_SUCCESS; 89 } 90 91 92 void Config::setNetwork(const std::string &aStrNetwork) 93 { 94 AssertReturnVoid(m_strNetwork.empty()); 95 96 m_strNetwork = aStrNetwork; 97 sanitizeBaseName(); 98 } 99 100 101 /* 102 * Requires network name to be known as the log file name depends on 103 * it. Alternatively, consider passing the log file name via the 104 * command line? 105 */ 106 int Config::logInit() 107 { 108 int rc; 109 size_t cch; 110 111 if (m_strHome.empty() || m_strBaseName.empty()) 112 return VERR_GENERAL_FAILURE; 113 114 /* default log file name */ 115 char szLogFile[RTPATH_MAX]; 116 cch = RTStrPrintf(szLogFile, sizeof(szLogFile), 117 "%s%c%s-Dhcpd.log", 118 m_strHome.c_str(), RTPATH_DELIMITER, m_strBaseName.c_str()); 119 if (cch >= sizeof(szLogFile)) 120 return VERR_BUFFER_OVERFLOW; 121 122 123 /* get a writable copy of the base name */ 124 char szBaseName[RTPATH_MAX]; 125 rc = RTStrCopy(szBaseName, sizeof(szBaseName), m_strBaseName.c_str()); 126 if (RT_FAILURE(rc)) 127 return rc; 128 129 /* sanitize base name some more to be usable in an environment variable name */ 130 for (char *p = szBaseName; *p != '\0'; ++p) 131 { 132 if ( *p != '_' 133 && (*p < '0' || '9' < *p) 134 && (*p < 'a' || 'z' < *p) 135 && (*p < 'A' || 'Z' < *p)) 136 { 137 *p = '_'; 138 } 139 } 140 141 142 /* name of the environment variable to control logging */ 143 char szEnvVarBase[128]; 144 cch = RTStrPrintf(szEnvVarBase, sizeof(szEnvVarBase), 145 "VBOXDHCP_%s_RELEASE_LOG", szBaseName); 146 if (cch >= sizeof(szEnvVarBase)) 147 return VERR_BUFFER_OVERFLOW; 148 149 150 rc = com::VBoxLogRelCreate("DHCP Server", 151 szLogFile, 152 RTLOGFLAGS_PREFIX_TIME_PROG, 153 "all all.restrict -default.restrict", 154 szEnvVarBase, 155 RTLOGDEST_FILE 156 #ifdef DEBUG 157 | RTLOGDEST_STDERR 158 #endif 159 , 160 32768 /* cMaxEntriesPerGroup */, 161 0 /* cHistory */, 162 0 /* uHistoryFileTime */, 163 0 /* uHistoryFileSize */, 164 NULL /* pErrInfo */); 165 166 return rc; 167 } 168 169 170 int Config::complete() 171 { 172 int rc; 173 174 if (m_strNetwork.empty()) 175 { 176 LogDHCP(("network name is not specified\n")); 177 return false; 178 } 179 180 logInit(); 181 182 bool fMACGenerated = false; 183 if ( m_MacAddress.au16[0] == 0 184 && m_MacAddress.au16[1] == 0 185 && m_MacAddress.au16[2] == 0) 186 { 187 RTUUID Uuid; 188 RTUuidCreate(&Uuid); 189 190 m_MacAddress.au8[0] = 0x08; 191 m_MacAddress.au8[1] = 0x00; 192 m_MacAddress.au8[2] = 0x27; 193 m_MacAddress.au8[3] = Uuid.Gen.au8Node[3]; 194 m_MacAddress.au8[4] = Uuid.Gen.au8Node[4]; 195 m_MacAddress.au8[5] = Uuid.Gen.au8Node[5]; 196 197 LogDHCP(("MAC address is not specified: will use generated MAC %RTmac\n", &m_MacAddress)); 198 fMACGenerated = true; 199 } 31 200 32 201 /* unicast MAC address */ 33 202 if (m_MacAddress.au8[0] & 0x01) 34 return false; 203 { 204 LogDHCP(("MAC address is not unicast: %RTmac\n", &m_MacAddress)); 205 return VERR_GENERAL_FAILURE; 206 } 35 207 36 208 /* unicast IP address */ 37 209 if ((m_IPv4Address.au8[0] & 0xe0) == 0xe0) 38 return false; 210 { 211 LogDHCP(("IP address is not unicast: %RTnaipv4\n", m_IPv4Address.u)); 212 return VERR_GENERAL_FAILURE; 213 } 39 214 40 215 /* valid netmask */ … … 42 217 rc = RTNetMaskToPrefixIPv4(&m_IPv4Netmask, &iPrefixLengh); 43 218 if (RT_FAILURE(rc) || iPrefixLengh == 0) 44 return false; 219 { 220 LogDHCP(("IP mask is not valid: %RTnaipv4\n", m_IPv4Netmask.u)); 221 return VERR_GENERAL_FAILURE; 222 } 45 223 46 224 /* first IP is from the same network */ 47 225 if ((m_IPv4PoolFirst.u & m_IPv4Netmask.u) != (m_IPv4Address.u & m_IPv4Netmask.u)) 48 return false; 226 { 227 LogDHCP(("first pool address is outside the network %RTnaipv4/%d: %RTnaipv4\n", 228 (m_IPv4Address.u & m_IPv4Netmask.u), iPrefixLengh, 229 m_IPv4PoolFirst.u)); 230 return VERR_GENERAL_FAILURE; 231 } 49 232 50 233 /* last IP is from the same network */ 51 234 if ((m_IPv4PoolLast.u & m_IPv4Netmask.u) != (m_IPv4Address.u & m_IPv4Netmask.u)) 52 return false; 235 { 236 LogDHCP(("last pool address is outside the network %RTnaipv4/%d: %RTnaipv4\n", 237 (m_IPv4Address.u & m_IPv4Netmask.u), iPrefixLengh, 238 m_IPv4PoolLast.u)); 239 return VERR_GENERAL_FAILURE; 240 } 53 241 54 242 /* the pool is valid */ 55 243 if (RT_N2H_U32(m_IPv4PoolLast.u) < RT_N2H_U32(m_IPv4PoolFirst.u)) 56 return false; 57 58 return true; 244 { 245 LogDHCP(("pool range is invalid: %RTnaipv4 - %RTnaipv4\n", 246 m_IPv4PoolFirst.u, m_IPv4PoolLast.u)); 247 return VERR_GENERAL_FAILURE; 248 } 249 250 /* our own address is not inside the pool */ 251 if ( RT_N2H_U32(m_IPv4PoolFirst.u) <= RT_N2H_U32(m_IPv4Address.u) 252 && RT_N2H_U32(m_IPv4Address.u) <= RT_N2H_U32(m_IPv4PoolLast.u)) 253 { 254 LogDHCP(("server address inside the pool range %RTnaipv4 - %RTnaipv4: %RTnaipv4\n", 255 m_IPv4PoolFirst.u, m_IPv4PoolLast.u, m_IPv4Address.u)); 256 return VERR_GENERAL_FAILURE; 257 } 258 259 if (!fMACGenerated) 260 LogDHCP(("MAC address %RTmac\n", &m_MacAddress)); 261 LogDHCP(("IP address %RTnaipv4/%d\n", m_IPv4Address.u, iPrefixLengh)); 262 LogDHCP(("address pool %RTnaipv4 - %RTnaipv4\n", m_IPv4PoolFirst.u, m_IPv4PoolLast.u)); 263 264 return VINF_SUCCESS; 59 265 } 60 266 … … 62 268 Config *Config::hardcoded() 63 269 { 270 int rc; 271 64 272 std::unique_ptr<Config> config(new Config()); 65 66 config->m_strNetwork.assign("HostInterfaceNetworking-vboxnet0"); 67 config->sanitizeBaseName(); /* nop, but be explicit */ 68 273 rc = config->init(); 274 if (RT_FAILURE(rc)) 275 return NULL; 276 277 config->setNetwork("HostInterfaceNetworking-vboxnet0"); 69 278 config->m_strTrunk.assign("vboxnet0"); 70 279 config->m_enmTrunkType = kIntNetTrunkType_NetFlt; … … 90 299 #endif 91 300 92 AssertReturn(config->isSane(), NULL); 301 rc = config->complete(); 302 AssertRCReturn(rc, NULL); 303 93 304 return config.release(); 94 305 } … … 101 312 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR }, 102 313 { "--mac-address", 'a', RTGETOPT_REQ_MACADDR }, 314 { "--need-main", 'M', RTGETOPT_REQ_BOOL }, 103 315 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR }, 104 316 { "--network", 'n', RTGETOPT_REQ_STRING }, … … 120 332 121 333 std::unique_ptr<Config> config(new Config()); 334 rc = config->init(); 335 if (RT_FAILURE(rc)) 336 return NULL; 337 122 338 for (;;) 123 339 { … … 131 347 { 132 348 case 'a': /* --mac-address */ 349 if ( config->m_MacAddress.au16[0] != 0 350 || config->m_MacAddress.au16[1] != 0 351 || config->m_MacAddress.au16[2] != 0) 352 { 353 RTMsgError("Duplicate --mac-address option"); 354 return NULL; 355 } 133 356 config->m_MacAddress = Val.MacAddr; 134 357 break; 135 358 136 359 case 'i': /* --ip-address */ 360 if (config->m_IPv4Address.u != 0) 361 { 362 RTMsgError("Duplicate --ip-address option"); 363 return NULL; 364 } 137 365 config->m_IPv4Address = Val.IPv4Addr; 138 366 break; 139 367 140 368 case 'l': /* --lower-ip */ 369 if (config->m_IPv4PoolFirst.u != 0) 370 { 371 RTMsgError("Duplicate --lower-ip option"); 372 return NULL; 373 } 141 374 config->m_IPv4PoolFirst = Val.IPv4Addr; 142 375 break; 143 376 377 case 'M': /* --need-main */ 378 /* for backward compatibility, ignored */ 379 break; 380 144 381 case 'm': /* --netmask */ 382 if (config->m_IPv4Netmask.u != 0) 383 { 384 RTMsgError("Duplicate --netmask option"); 385 return NULL; 386 } 145 387 config->m_IPv4Netmask = Val.IPv4Addr; 146 388 break; 147 389 148 390 case 'n': /* --network */ 149 config->m_strNetwork.assign(Val.psz); 391 if (!config->m_strNetwork.empty()) 392 { 393 RTMsgError("Duplicate --network option"); 394 return NULL; 395 } 396 config->setNetwork(Val.psz); 150 397 break; 151 398 152 399 case 't': /* --trunk-name */ 400 if (!config->m_strTrunk.empty()) 401 { 402 RTMsgError("Duplicate --trunk-name option"); 403 return NULL; 404 } 153 405 config->m_strTrunk.assign(Val.psz); 154 406 break; 155 407 156 408 case 'T': /* --trunk-type */ 157 if (strcmp(Val.psz, "none") == 0) 409 if (config->m_enmTrunkType != kIntNetTrunkType_Invalid) 410 { 411 RTMsgError("Duplicate --trunk-type option"); 412 return NULL; 413 } 414 else if (strcmp(Val.psz, "none") == 0) 158 415 config->m_enmTrunkType = kIntNetTrunkType_None; 159 416 else if (strcmp(Val.psz, "whatever") == 0) … … 171 428 172 429 case 'u': /* --upper-ip */ 430 if (config->m_IPv4PoolLast.u != 0) 431 { 432 RTMsgError("Duplicate --upper-ip option"); 433 return NULL; 434 } 173 435 config->m_IPv4PoolLast = Val.IPv4Addr; 174 436 break; … … 184 446 } 185 447 186 config->sanitizeBaseName(); 187 188 if (!config->isSane()) 448 rc = config->complete(); 449 if (RT_FAILURE(rc)) 189 450 return NULL; 190 451 … … 247 508 return NULL; 248 509 249 if (!config->isSane()) 250 return NULL; 251 252 config->sanitizeBaseName(); 510 rc = config->complete(); 511 if (RT_FAILURE(rc)) 512 return NULL; 253 513 254 514 return config.release(); … … 258 518 Config *Config::read(const char *pszFileName) 259 519 { 520 int rc; 521 522 if (pszFileName == NULL || pszFileName[0] == '\0') 523 return NULL; 524 525 xml::Document doc; 526 try 527 { 528 xml::XmlFileParser parser; 529 parser.read(pszFileName, doc); 530 } 531 catch (const xml::EIPRTFailure &e) 532 { 533 LogDHCP(("%s\n", e.what())); 534 return NULL; 535 } 536 catch (const RTCError &e) 537 { 538 LogDHCP(("%s\n", e.what())); 539 return NULL; 540 } 541 catch (...) 542 { 543 LogDHCP(("Unknown exception while reading and parsing '%s'\n", 544 pszFileName)); 545 return NULL; 546 } 547 260 548 std::unique_ptr<Config> config(new Config()); 261 262 RT_NOREF(pszFileName); 549 rc = config->init(); 550 if (RT_FAILURE(rc)) 551 return NULL; 552 553 try 554 { 555 config->parseConfig(doc.getRootElement()); 556 } 557 catch (const RTCError &e) 558 { 559 LogDHCP(("%s\n", e.what())); 560 return NULL; 561 } 562 catch (...) 563 { 564 LogDHCP(("Unexpected exception\n")); 565 return NULL; 566 } 567 263 568 return config.release(); 569 } 570 571 572 void Config::parseConfig(const xml::ElementNode *root) 573 { 574 if (root == NULL) 575 throw ConfigFileError("Empty config file"); 576 577 /* 578 * XXX: NAMESPACE API IS COMPLETELY BROKEN, SO IGNORE IT FOR NOW 579 */ 580 if (!root->nameEquals("DHCPServer")) 581 { 582 const char *name = root->getName(); 583 throw ConfigFileError(RTCStringFmt("Unexpected root element \"%s\"", 584 name ? name : "(null)")); 585 } 586 587 parseServer(root); 588 589 // XXX: debug 590 for (auto it: m_GlobalOptions) { 591 std::shared_ptr<DhcpOption> opt(it.second); 592 593 octets_t data; 594 opt->encode(data); 595 596 bool space = false; 597 for (auto c: data) { 598 if (space) 599 std::cout << " "; 600 else 601 space = true; 602 std::cout << (int)c; 603 } 604 std::cout << std::endl; 605 } 606 } 607 608 609 static void getIPv4AddrAttribute(const xml::ElementNode *pNode, const char *pcszAttrName, 610 RTNETADDRIPV4 *pAddr) 611 { 612 RTCString strAddr; 613 bool fHasAttr = pNode->getAttributeValue(pcszAttrName, &strAddr); 614 if (!fHasAttr) 615 throw ConfigFileError(RTCStringFmt("%s attribute missing", 616 pcszAttrName)); 617 618 int rc = RTNetStrToIPv4Addr(strAddr.c_str(), pAddr); 619 if (RT_FAILURE(rc)) 620 throw ConfigFileError(RTCStringFmt("%s attribute invalid", 621 pcszAttrName)); 622 } 623 624 625 void Config::parseServer(const xml::ElementNode *server) 626 { 627 /* 628 * DHCPServer attributes 629 */ 630 RTCString strNetworkName; 631 bool fHasNetworkName = server->getAttributeValue("networkName", &strNetworkName); 632 if (!fHasNetworkName) 633 throw ConfigFileError("DHCPServer/@networkName missing"); 634 635 setNetwork(strNetworkName.c_str()); 636 637 getIPv4AddrAttribute(server, "IPAddress", &m_IPv4Address); 638 getIPv4AddrAttribute(server, "networkMask", &m_IPv4Netmask); 639 getIPv4AddrAttribute(server, "lowerIP", &m_IPv4PoolFirst); 640 getIPv4AddrAttribute(server, "upperIP", &m_IPv4PoolLast); 641 642 /* 643 * DHCPServer children 644 */ 645 xml::NodesLoop it(*server); 646 const xml::ElementNode *node; 647 while ((node = it.forAllNodes()) != NULL) 648 { 649 /* 650 * Global options 651 */ 652 if (node->nameEquals("Options")) 653 { 654 parseGlobalOptions(node); 655 } 656 657 /* 658 * Per-VM configuration 659 */ 660 else if (node->nameEquals("Config")) 661 { 662 parseVMConfig(node); 663 } 664 } 665 } 666 667 668 void Config::parseGlobalOptions(const xml::ElementNode *options) 669 { 670 xml::NodesLoop it(*options); 671 const xml::ElementNode *node; 672 while ((node = it.forAllNodes()) != NULL) 673 { 674 if (node->nameEquals("Option")) 675 { 676 parseOption(node, m_GlobalOptions); 677 } 678 else 679 { 680 throw ConfigFileError(RTCStringFmt("Unexpected element \"%s\"", 681 node->getName())); 682 } 683 } 684 } 685 686 687 /* 688 * VM Config entries are generated automatically from VirtualBox.xml 689 * with the MAC fetched from the VM config. The client id is nowhere 690 * in the picture there, so VM config is indexed with plain RTMAC, not 691 * ClientId (also see getOptions below). 692 */ 693 void Config::parseVMConfig(const xml::ElementNode *config) 694 { 695 RTMAC mac; 696 int rc; 697 698 RTCString strMac; 699 bool fHasMac = config->getAttributeValue("MACAddress", &strMac); 700 if (!fHasMac) 701 throw ConfigFileError(RTCStringFmt("Config missing MACAddress attribute")); 702 703 rc = parseMACAddress(mac, strMac); 704 if (RT_FAILURE(rc)) 705 { 706 throw ConfigFileError(RTCStringFmt("Malformed MACAddress attribute \"%s\"", 707 strMac.c_str())); 708 } 709 710 vmmap_t::iterator vmit( m_VMMap.find(mac) ); 711 if (vmit != m_VMMap.end()) 712 { 713 throw ConfigFileError(RTCStringFmt("Duplicate Config for MACAddress \"%s\"", 714 strMac.c_str())); 715 } 716 717 optmap_t &vmopts = m_VMMap[mac]; 718 719 xml::NodesLoop it(*config); 720 const xml::ElementNode *node; 721 while ((node = it.forAllNodes()) != NULL) 722 { 723 if (node->nameEquals("Option")) 724 { 725 parseOption(node, vmopts); 726 } 727 else 728 { 729 throw ConfigFileError(RTCStringFmt("Unexpected element \"%s\"", 730 node->getName())); 731 } 732 } 733 } 734 735 736 int Config::parseMACAddress(RTMAC &aMac, const RTCString &aStr) 737 { 738 RTMAC mac; 739 int rc; 740 741 rc = RTNetStrToMacAddr(aStr.c_str(), &mac); 742 if (RT_FAILURE(rc)) 743 return rc; 744 if (rc == VWRN_TRAILING_CHARS) 745 return VERR_INVALID_PARAMETER; 746 747 aMac = mac; 748 return VINF_SUCCESS; 749 } 750 751 752 int Config::parseClientId(OptClientId &aId, const RTCString &aStr) 753 { 754 RT_NOREF(aId, aStr); 755 return VERR_GENERAL_FAILURE; 756 } 757 758 759 /* 760 * Parse <Option/> element and add the option to the specified optmap. 761 */ 762 void Config::parseOption(const xml::ElementNode *option, optmap_t &optmap) 763 { 764 int rc; 765 766 uint8_t u8Opt; 767 RTCString strName; 768 bool fHasName = option->getAttributeValue("name", &strName); 769 if (fHasName) 770 { 771 const char *pcszName = strName.c_str(); 772 773 rc = RTStrToUInt8Full(pcszName, 10, &u8Opt); 774 if (rc != VINF_SUCCESS) /* no warnings either */ 775 throw ConfigFileError(RTCStringFmt("Bad option \"%s\"", pcszName)); 776 777 } 778 else 779 throw ConfigFileError("missing option name"); 780 781 782 uint32_t u32Enc = 0; /* XXX: DhcpOptEncoding_Legacy */ 783 RTCString strEncoding; 784 bool fHasEncoding = option->getAttributeValue("encoding", &strEncoding); 785 if (fHasEncoding) 786 { 787 const char *pcszEnc = strEncoding.c_str(); 788 789 rc = RTStrToUInt32Full(pcszEnc, 10, &u32Enc); 790 if (rc != VINF_SUCCESS) /* no warnings either */ 791 throw ConfigFileError(RTCStringFmt("Bad encoding \"%s\"", pcszEnc)); 792 793 switch (u32Enc) 794 { 795 case 0: /* XXX: DhcpOptEncoding_Legacy */ 796 case 1: /* XXX: DhcpOptEncoding_Hex */ 797 break; 798 default: 799 throw ConfigFileError(RTCStringFmt("Unknown encoding \"%s\"", pcszEnc)); 800 } 801 } 802 803 804 /* value may be omitted for OptNoValue options like rapid commit */ 805 RTCString strValue; 806 option->getAttributeValue("value", &strValue); 807 808 /* XXX: TODO: encoding, handle hex */ 809 DhcpOption *opt = DhcpOption::parse(u8Opt, u32Enc, strValue.c_str()); 810 if (opt == NULL) 811 throw ConfigFileError(RTCStringFmt("Bad option \"%s\"", strName.c_str())); 812 813 optmap << opt; 264 814 } 265 815 … … 273 823 int rc; 274 824 825 if (m_strNetwork.empty()) 826 return; 827 275 828 char szBaseName[RTPATH_MAX]; 276 829 rc = RTStrCopy(szBaseName, sizeof(szBaseName), m_strNetwork.c_str()); … … 296 849 optmap_t optmap; 297 850 298 fillDefaultOptions(optmap, reqOpts); 299 fillVendorOptions(optmap, reqOpts, vendor); 300 fillHostOptions(optmap, reqOpts, id); 851 const optmap_t *vmopts = NULL; 852 vmmap_t::const_iterator vmit( m_VMMap.find(id.mac()) ); 853 if (vmit != m_VMMap.end()) 854 vmopts = &vmit->second; 855 856 RT_NOREF(vendor); /* not yet */ 857 858 859 optmap << new OptSubnetMask(m_IPv4Netmask); 860 861 for (auto optreq: reqOpts.value()) 862 { 863 std::cout << ">>> requested option " << (int)optreq << std::endl; 864 865 if (optreq == OptSubnetMask::optcode) 866 { 867 std::cout << "... always supplied" << std::endl; 868 continue; 869 } 870 871 if (vmopts != NULL) 872 { 873 optmap_t::const_iterator it( vmopts->find(optreq) ); 874 if (it != vmopts->end()) 875 { 876 optmap << it->second; 877 std::cout << "... found in VM options" << std::endl; 878 continue; 879 } 880 } 881 882 optmap_t::const_iterator it( m_GlobalOptions.find(optreq) ); 883 if (it != m_GlobalOptions.end()) 884 { 885 optmap << it->second; 886 std::cout << "... found in global options" << std::endl; 887 continue; 888 } 889 890 // std::cout << "... not found" << std::endl; 891 } 892 893 894 /* XXX: testing ... */ 895 if (vmopts != NULL) 896 { 897 for (auto it: *vmopts) { 898 std::shared_ptr<DhcpOption> opt(it.second); 899 if (optmap.count(opt->optcode()) == 0 && opt->optcode() > 127) 900 { 901 optmap << opt; 902 std::cout << "... forcing VM option " << (int)opt->optcode() << std::endl; 903 } 904 } 905 } 906 907 for (auto it: m_GlobalOptions) { 908 std::shared_ptr<DhcpOption> opt(it.second); 909 if (optmap.count(opt->optcode()) == 0 && opt->optcode() > 127) 910 { 911 optmap << opt; 912 std::cout << "... forcing global option " << (int)opt->optcode() << std::endl; 913 } 914 } 301 915 302 916 return optmap; 303 917 } 304 305 306 void Config::fillDefaultOptions(optmap_t &optmap,307 const OptParameterRequest &reqOpts) const308 {309 RT_NOREF(reqOpts);310 311 optmap << new OptSubnetMask(m_IPv4Netmask);312 }313 314 315 void Config::fillHostOptions(optmap_t &optmap,316 const OptParameterRequest &reqOpts,317 const ClientId &id) const318 {319 /* not yet */320 RT_NOREF(optmap, reqOpts, id);321 }322 323 324 void Config::fillVendorOptions(optmap_t &optmap,325 const OptParameterRequest &reqOpts,326 const OptVendorClassId &vendor) const327 {328 if (!vendor.present())329 return;330 331 /* may be some day... */332 RT_NOREF(optmap, reqOpts);333 } -
trunk/src/VBox/NetworkServices/Dhcpd/Config.h
r71353 r71689 21 21 #include <iprt/types.h> 22 22 #include <iprt/net.h> 23 #include <iprt/cpp/xml.h> 23 24 24 25 #include <VBox/intnet.h> … … 33 34 class Config 34 35 { 35 std::string m_strHome; 36 /* XXX: TODO: also store fixed address assignments, etc? */ 37 typedef std::map<RTMAC, optmap_t> vmmap_t; 38 39 std::string m_strHome; /* path of ~/.VirtualBox or equivalent */ 36 40 37 41 std::string m_strNetwork; … … 49 53 RTNETADDRIPV4 m_IPv4PoolLast; 50 54 55 optmap_t m_GlobalOptions; 56 vmmap_t m_VMMap; 57 51 58 private: 52 bool isSane(); 59 Config(); 60 61 int init(); 62 int homeInit(); 63 int logInit(); 64 int complete(); 53 65 54 66 public: /* factory methods */ … … 58 70 59 71 public: /* accessors */ 60 void setHome(const std::string &strHome) { m_strHome =strHome; }72 const std::string &getHome() const { return m_strHome; } 61 73 62 const std::string &getHome() const { return m_strHome; }63 74 const std::string &getNetwork() const { return m_strNetwork; } 75 void setNetwork(const std::string &aStrNetwork); 76 64 77 const std::string &getBaseName() const { return m_strBaseName; } 65 78 const std::string &getTrunk() const { return m_strTrunk; } … … 80 93 private: 81 94 static Config *read(const char *pszFileName); 95 void parseConfig(const xml::ElementNode *root); 96 void parseServer(const xml::ElementNode *server); 97 void parseGlobalOptions(const xml::ElementNode *options); 98 void parseVMConfig(const xml::ElementNode *config); 99 void parseOption(const xml::ElementNode *option, optmap_t &optmap); 100 101 int parseMACAddress(RTMAC &aMac, const RTCString &aStr); 102 int parseClientId(OptClientId &aId, const RTCString &aStr); 82 103 83 104 void sanitizeBaseName(); 84 85 void fillDefaultOptions(optmap_t &optmap,86 const OptParameterRequest &reqOpts) const;87 void fillVendorOptions(optmap_t &optmap,88 const OptParameterRequest &reqOpts,89 const OptVendorClassId &vendor) const;90 void fillHostOptions(optmap_t &optmap,91 const OptParameterRequest &reqOpts,92 const ClientId &id) const;93 105 }; 94 106 -
trunk/src/VBox/NetworkServices/Dhcpd/Db.cpp
r71516 r71689 18 18 #include <iprt/err.h> 19 19 #include <iprt/stream.h> 20 21 #include <algorithm>22 #include <functional>23 20 24 21 #include "Db.h" … … 340 337 } 341 338 } 342 343 344 Binding *Db::bindingById(const ClientId &id) const345 {346 struct ClientMatch : public Binding::Match {347 const ClientId &m_id;348 ClientMatch(const ClientId &id) : m_id(id) {}349 350 bool operator()(const Binding *b)351 {352 return b->m_id == m_id;353 }354 };355 356 bindings_t::const_iterator found =357 std::find_if(m_bindings.begin(), m_bindings.end(),358 ClientMatch(id));359 360 if (found == m_bindings.end())361 return NULL;362 363 Binding *b = *found;364 return b;365 }366 367 368 Binding *Db::bindingByAddr(RTNETADDRIPV4 addr) const369 {370 struct AddrMatch : public Binding::Match {371 const RTNETADDRIPV4 m_addr;372 AddrMatch(RTNETADDRIPV4 addr) : m_addr(addr) {}373 374 bool operator()(const Binding *b)375 {376 return b->m_addr.u == m_addr.u;377 }378 };379 380 bindings_t::const_iterator found =381 std::find_if(m_bindings.begin(), m_bindings.end(),382 AddrMatch(addr));383 384 if (found == m_bindings.end())385 return NULL;386 387 Binding *b = *found;388 return b;389 }390 391 339 392 340 -
trunk/src/VBox/NetworkServices/Dhcpd/Db.h
r70836 r71689 39 39 public: 40 40 enum State { FREE, RELEASED, EXPIRED, OFFERED, ACKED }; 41 42 typedef std::unary_function<const Binding *, bool> Match;43 41 44 42 private: … … 136 134 bool addressBelongs(RTNETADDRIPV4 addr) const { return m_pool.contains(addr); } 137 135 138 Binding *bindingById(const ClientId &id) const;139 Binding *bindingByAddr(RTNETADDRIPV4 addr) const;140 141 136 Binding *allocateBinding(const DhcpClientMessage &req); 142 137 bool releaseBinding(const DhcpClientMessage &req); -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.cpp
r70836 r71689 48 48 49 49 50 int DhcpOption::encode(octets_t &dst) const 51 { 52 if (!m_fPresent) 53 return VERR_INVALID_STATE; 54 55 size_t cbOrig = dst.size(); 56 57 append(dst, m_OptCode); 58 appendLength(dst, 0); /* placeholder */ 59 60 ssize_t cbValue = encodeValue(dst); 61 if (cbValue < 0 || UINT8_MAX <= cbValue) 62 { 63 dst.resize(cbOrig); /* undo */ 64 return VERR_INVALID_PARAMETER; 65 } 66 67 dst[cbOrig+1] = cbValue; 68 return VINF_SUCCESS; 69 } 70 71 72 /* static */ 73 const octets_t *DhcpOption::findOption(const rawopts_t &aOptMap, uint8_t aOptCode) 74 { 75 rawopts_t::const_iterator it(aOptMap.find(aOptCode)); 76 if (it == aOptMap.end()) 77 return NULL; 78 79 return &it->second; 80 } 81 82 50 83 int DhcpOption::decode(const rawopts_t &map) 51 84 { … … 66 99 return decode(req.rawopts()); 67 100 } 101 102 103 int DhcpOption::parse1(uint8_t &aValue, const char *pcszValue) 104 { 105 int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &aValue); 106 107 if (rc == VERR_TRAILING_SPACES) 108 rc = VINF_SUCCESS; 109 return rc; 110 } 111 112 113 int DhcpOption::parse1(uint16_t &aValue, const char *pcszValue) 114 { 115 int rc = RTStrToUInt16Full(RTStrStripL(pcszValue), 10, &aValue); 116 117 if (rc == VERR_TRAILING_SPACES) 118 rc = VINF_SUCCESS; 119 return rc; 120 } 121 122 123 int DhcpOption::parse1(uint32_t &aValue, const char *pcszValue) 124 { 125 int rc = RTStrToUInt32Full(RTStrStripL(pcszValue), 10, &aValue); 126 127 if (rc == VERR_TRAILING_SPACES) 128 rc = VINF_SUCCESS; 129 return rc; 130 } 131 132 133 int DhcpOption::parse1(RTNETADDRIPV4 &aValue, const char *pcszValue) 134 { 135 return RTNetStrToIPv4Addr(pcszValue, &aValue); 136 } 137 138 139 int DhcpOption::parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue) 140 { 141 std::vector<RTNETADDRIPV4> l; 142 int rc; 143 144 pcszValue = RTStrStripL(pcszValue); 145 do { 146 RTNETADDRIPV4 Addr; 147 char *pszNext; 148 149 rc = RTNetStrToIPv4AddrEx(pcszValue, &Addr, &pszNext); 150 if (RT_FAILURE(rc)) 151 return VERR_INVALID_PARAMETER; 152 153 if (rc == VWRN_TRAILING_CHARS) 154 { 155 pcszValue = RTStrStripL(pszNext); 156 if (pcszValue == pszNext) /* garbage after address */ 157 return VERR_INVALID_PARAMETER; 158 } 159 160 l.push_back(Addr); 161 162 /* 163 * If we got VINF_SUCCESS or VWRN_TRAILING_SPACES then this 164 * was the last address and we are done. 165 */ 166 } while (rc == VWRN_TRAILING_CHARS); 167 168 aList.swap(l); 169 return VINF_SUCCESS; 170 } 171 172 173 /* 174 * XXX: See DHCPServer::encodeOption() 175 */ 176 int DhcpOption::parseHex(octets_t &aRawValue, const char *pcszValue) 177 { 178 octets_t data; 179 char *pszNext; 180 int rc; 181 182 if (pcszValue == NULL || *pcszValue == '\0') 183 return VERR_INVALID_PARAMETER; 184 185 while (*pcszValue != '\0') 186 { 187 if (data.size() > UINT8_MAX) 188 return VERR_INVALID_PARAMETER; 189 190 uint8_t u8Byte; 191 rc = RTStrToUInt8Ex(pcszValue, &pszNext, 16, &u8Byte); 192 if (!RT_SUCCESS(rc)) 193 return rc; 194 195 if (*pszNext == ':') 196 ++pszNext; 197 else if (*pszNext != '\0') 198 return VERR_PARSE_ERROR; 199 200 data.push_back(u8Byte); 201 pcszValue = pszNext; 202 } 203 204 aRawValue.swap(data); 205 return VINF_SUCCESS; 206 } 207 208 209 DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue) 210 { 211 switch (aEnc) 212 { 213 case 0: /* DhcpOptEncoding_Legacy */ 214 switch (aOptCode) 215 { 216 #define HANDLE(_OptClass) \ 217 case _OptClass::optcode: \ 218 return _OptClass::parse(pcszValue); 219 220 HANDLE(OptSubnetMask); 221 HANDLE(OptRouter); 222 HANDLE(OptDNS); 223 HANDLE(OptHostName); 224 HANDLE(OptDomainName); 225 HANDLE(OptRootPath); 226 HANDLE(OptLeaseTime); 227 HANDLE(OptRenewalTime); 228 HANDLE(OptRebindingTime); 229 230 #undef HANDLE 231 default: 232 return NULL; 233 } 234 break; 235 236 case 1: 237 return RawOption::parse(aOptCode, pcszValue); 238 239 default: 240 return NULL; 241 } 242 } -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.h
r70836 r71689 51 51 virtual ~DhcpOption() {} 52 52 53 protected: 54 virtual ssize_t encodeValue(octets_t &data) const = 0; 55 virtual int decodeValue(const octets_t &data, size_t cb) = 0; 53 public: 54 static DhcpOption *parse(uint8_t aOptCode, int aEnc, const char *pcszValue); 56 55 57 56 public: 58 57 uint8_t optcode() const { return m_OptCode; } 59 60 58 bool present() const { return m_fPresent; } 61 59 62 int encode(octets_t &data) const 63 { 64 if (!m_fPresent) 65 return VERR_INVALID_STATE; 66 67 size_t cbOrig = data.size(); 68 69 append(data, m_OptCode); 70 appendLength(data, 0); /* placeholder */ 71 72 ssize_t cbValue = encodeValue(data); 73 if (cbValue < 0 || UINT8_MAX <= cbValue) 74 { 75 data.resize(cbOrig); /* undo */ 76 return VERR_INVALID_PARAMETER; 77 } 78 79 data[cbOrig+1] = cbValue; 80 return VINF_SUCCESS; 81 } 82 83 int testEncodeValue(octets_t &data) const /* XXX */ 84 { 85 if (!m_fPresent) 86 return VERR_INVALID_STATE; 87 88 return encodeValue(data) >= 0 ? VINF_SUCCESS : VERR_INVALID_PARAMETER; 89 } 90 91 public: 60 public: 61 int encode(octets_t &dst) const; 62 92 63 int decode(const rawopts_t &map); 93 64 int decode(const DhcpClientMessage &req); 94 65 95 96 protected: 97 static const octets_t *findOption(const rawopts_t &aOptMap, uint8_t aOptCode) 98 { 99 rawopts_t::const_iterator it(aOptMap.find(aOptCode)); 100 if (it == aOptMap.end()) 101 return NULL; 102 103 return &it->second; 104 } 66 protected: 67 virtual ssize_t encodeValue(octets_t &dst) const = 0; 68 virtual int decodeValue(const octets_t &src, size_t cb) = 0; 69 70 protected: 71 static const octets_t *findOption(const rawopts_t &aOptMap, uint8_t aOptCode); 105 72 106 73 protected: … … 108 75 * Serialization 109 76 */ 110 static void append(octets_t &aD ata, uint8_t aValue)111 { 112 aD ata.push_back(aValue);113 } 114 115 static void append(octets_t &aD ata, uint16_t aValue)77 static void append(octets_t &aDst, uint8_t aValue) 78 { 79 aDst.push_back(aValue); 80 } 81 82 static void append(octets_t &aDst, uint16_t aValue) 116 83 { 117 84 RTUINT16U u16 = { RT_H2N_U16(aValue) }; 118 aD ata.insert(aData.end(), u16.au8, u16.au8 + sizeof(aValue));119 } 120 121 static void append(octets_t &aD ata, uint32_t aValue)85 aDst.insert(aDst.end(), u16.au8, u16.au8 + sizeof(aValue)); 86 } 87 88 static void append(octets_t &aDst, uint32_t aValue) 122 89 { 123 90 RTUINT32U u32 = { RT_H2N_U32(aValue) }; 124 aD ata.insert(aData.end(), u32.au8, u32.au8 + sizeof(aValue));125 } 126 127 static void append(octets_t &aD ata, RTNETADDRIPV4 aIPv4)128 { 129 aD ata.insert(aData.end(), aIPv4.au8, aIPv4.au8 + sizeof(aIPv4));130 } 131 132 static void append(octets_t &aD ata, const char *pszString, size_t cb)133 { 134 aD ata.insert(aData.end(), pszString, pszString + cb);135 } 136 137 static void append(octets_t &aD ata, const std::string &str)138 { 139 append(aD ata, str.c_str(), str.size());91 aDst.insert(aDst.end(), u32.au8, u32.au8 + sizeof(aValue)); 92 } 93 94 static void append(octets_t &aDst, RTNETADDRIPV4 aIPv4) 95 { 96 aDst.insert(aDst.end(), aIPv4.au8, aIPv4.au8 + sizeof(aIPv4)); 97 } 98 99 static void append(octets_t &aDst, const char *pszString, size_t cb) 100 { 101 aDst.insert(aDst.end(), pszString, pszString + cb); 102 } 103 104 static void append(octets_t &aDst, const std::string &str) 105 { 106 append(aDst, str.c_str(), str.size()); 140 107 } 141 108 142 109 /* non-overloaded name to avoid ambiguity */ 143 static void appendLength(octets_t &aD ata, size_t cb)144 { 145 append(aD ata, static_cast<uint8_t>(cb));110 static void appendLength(octets_t &aDst, size_t cb) 111 { 112 append(aDst, static_cast<uint8_t>(cb)); 146 113 } 147 114 … … 183 150 pos += cb; 184 151 } 185 }; 186 187 188 inline octets_t &operator<<(octets_t &data, const DhcpOption &option) 189 { 190 option.encode(data); 191 return data; 152 153 154 /* 155 * Parse textual representation (e.g. in config file) 156 */ 157 static int parse1(uint8_t &aValue, const char *pcszValue); 158 static int parse1(uint16_t &aValue, const char *pcszValue); 159 static int parse1(uint32_t &aValue, const char *pcszValue); 160 static int parse1(RTNETADDRIPV4 &aValue, const char *pcszValue); 161 162 static int parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue); 163 164 static int parseHex(octets_t &aRawValue, const char *pcszValue); 165 }; 166 167 168 inline octets_t &operator<<(octets_t &dst, const DhcpOption &option) 169 { 170 option.encode(dst); 171 return dst; 192 172 } 193 173 … … 202 182 */ 203 183 struct OptEnd {}; 204 inline octets_t &operator<<(octets_t &d ata, const OptEnd &end)184 inline octets_t &operator<<(octets_t &dst, const OptEnd &end) 205 185 { 206 186 RT_NOREF(end); 207 187 208 d ata.push_back(RTNET_DHCP_OPT_END);209 return d ata;188 dst.push_back(RTNET_DHCP_OPT_END); 189 return dst; 210 190 } 211 191 … … 225 205 : DhcpOption(aOptCode, fPresent) {} 226 206 227 explicitOptNoValueBase(uint8_t aOptCode, const DhcpClientMessage &req)207 OptNoValueBase(uint8_t aOptCode, const DhcpClientMessage &req) 228 208 : DhcpOption(aOptCode, false) 229 209 { … … 237 217 238 218 protected: 239 virtual ssize_t encodeValue(octets_t &d ata) const240 { 241 RT_NOREF(d ata);219 virtual ssize_t encodeValue(octets_t &dst) const 220 { 221 RT_NOREF(dst); 242 222 return 0; 243 223 } … … 249 229 } 250 230 251 virtual int decodeValue(const octets_t & data, size_t cb)252 { 253 RT_NOREF( data);231 virtual int decodeValue(const octets_t &src, size_t cb) 232 { 233 RT_NOREF(src); 254 234 255 235 if (!isLengthValid(cb)) … … 299 279 : DhcpOption(aOptCode), m_Value(aOptValue) {} 300 280 301 explicitOptValueBase(uint8_t aOptCode, const DhcpClientMessage &req)281 OptValueBase(uint8_t aOptCode, const DhcpClientMessage &req) 302 282 : DhcpOption(aOptCode, false), m_Value() 303 283 { … … 316 296 317 297 protected: 318 virtual ssize_t encodeValue(octets_t &d ata) const319 { 320 append(d ata, m_Value);298 virtual ssize_t encodeValue(octets_t &dst) const 299 { 300 append(dst, m_Value); 321 301 return sizeof(T); 322 302 } … … 328 308 } 329 309 330 virtual int decodeValue(const octets_t & data, size_t cb)310 virtual int decodeValue(const octets_t &src, size_t cb) 331 311 { 332 312 if (!isLengthValid(cb)) 333 313 return VERR_INVALID_PARAMETER; 334 314 335 octets_t::const_iterator pos( data.begin());315 octets_t::const_iterator pos(src.begin()); 336 316 extract(m_Value, pos); 337 317 … … 346 326 { 347 327 public: 328 using typename OptValueBase<T>::value_t; 329 330 public: 348 331 static const uint8_t optcode = _OptCode; 349 332 … … 356 339 explicit OptValue(const DhcpClientMessage &req) 357 340 : OptValueBase<T>(optcode, req) {} 341 342 static OptValue *parse(const char *pcszValue) 343 { 344 value_t v; 345 int rc = DhcpOption::parse1(v, pcszValue); 346 if (RT_FAILURE(rc)) 347 return NULL; 348 return new OptValue(v); 349 } 358 350 }; 359 351 … … 372 364 std::string m_String; 373 365 374 OptStringBase(uint8_t aOptCode)366 explicit OptStringBase(uint8_t aOptCode) 375 367 : DhcpOption(aOptCode, false), m_String() {} 376 368 377 explicitOptStringBase(uint8_t aOptCode, const std::string &aOptString)369 OptStringBase(uint8_t aOptCode, const std::string &aOptString) 378 370 : DhcpOption(aOptCode), m_String(aOptString) {} 379 371 380 explicitOptStringBase(uint8_t aOptCode, const DhcpClientMessage &req)372 OptStringBase(uint8_t aOptCode, const DhcpClientMessage &req) 381 373 : DhcpOption(aOptCode, false), m_String() 382 374 { … … 395 387 396 388 protected: 397 virtual ssize_t encodeValue(octets_t &d ata) const389 virtual ssize_t encodeValue(octets_t &dst) const 398 390 { 399 391 if (!isLengthValid(m_String.size())) 400 392 return -1; 401 393 402 append(d ata, m_String);394 append(dst, m_String); 403 395 return m_String.size(); 404 396 } … … 410 402 } 411 403 412 virtual int decodeValue(const octets_t & data, size_t cb)404 virtual int decodeValue(const octets_t &src, size_t cb) 413 405 { 414 406 if (!isLengthValid(cb)) 415 407 return VERR_INVALID_PARAMETER; 416 408 417 octets_t::const_iterator pos( data.begin());409 octets_t::const_iterator pos(src.begin()); 418 410 extract(m_String, pos, cb); 419 411 m_fPresent = true; … … 437 429 explicit OptString(const DhcpClientMessage &req) 438 430 : OptStringBase(optcode, req) {} 431 432 static OptString *parse(const char *pcszValue) 433 { 434 return new OptString(pcszValue); 435 } 439 436 }; 440 437 … … 463 460 : DhcpOption(aOptCode), m_List(aOptList) {} 464 461 465 explicitOptListBase(uint8_t aOptCode, const DhcpClientMessage &req)462 OptListBase(uint8_t aOptCode, const DhcpClientMessage &req) 466 463 : DhcpOption(aOptCode, false), m_List() 467 464 { … … 480 477 481 478 protected: 482 virtual ssize_t encodeValue(octets_t &d ata) const479 virtual ssize_t encodeValue(octets_t &dst) const 483 480 { 484 481 const size_t cbItem = sizeof(T); … … 490 487 break; 491 488 492 append(d ata, m_List[i]);489 append(dst, m_List[i]); 493 490 cbValue += cbItem; 494 491 } … … 503 500 } 504 501 505 virtual int decodeValue(const octets_t & data, size_t cb)502 virtual int decodeValue(const octets_t &src, size_t cb) 506 503 { 507 504 if (!isLengthValid(cb)) … … 510 507 m_List.erase(m_List.begin(), m_List.end()); 511 508 512 octets_t::const_iterator pos( data.begin());509 octets_t::const_iterator pos(src.begin()); 513 510 for (size_t i = 0; i < cb / sizeof(T); ++i) 514 511 { … … 528 525 { 529 526 public: 527 using typename OptListBase<T>::value_t; 528 529 public: 530 530 static const uint8_t optcode = _OptCode; 531 531 … … 536 536 : OptListBase<T>(optcode, aOptSingle) {} 537 537 538 OptList(const std::vector<T> &aOptList)538 explicit OptList(const std::vector<T> &aOptList) 539 539 : OptListBase<T>(optcode, aOptList) {} 540 540 541 541 explicit OptList(const DhcpClientMessage &req) 542 542 : OptListBase<T>(optcode, req) {} 543 544 static OptList *parse(const char *pcszValue) 545 { 546 value_t v; 547 int rc = DhcpOption::parseList(v, pcszValue); 548 if (RT_FAILURE(rc) || v.empty()) 549 return NULL; 550 return new OptList(v); 551 } 552 }; 553 554 555 /* 556 * Options specified by raw binary data that we don't know how to 557 * interpret. 558 */ 559 class RawOption 560 : public DhcpOption 561 { 562 protected: 563 octets_t m_Data; 564 565 public: 566 explicit RawOption(uint8_t aOptCode) 567 : DhcpOption(aOptCode, false), m_Data() {} 568 569 RawOption(uint8_t aOptCode, const octets_t &aSrc) 570 : DhcpOption(aOptCode), m_Data(aSrc) {} 571 572 public: 573 virtual RawOption *clone() const 574 { 575 return new RawOption(*this); 576 } 577 578 579 protected: 580 virtual ssize_t encodeValue(octets_t &dst) const 581 { 582 dst.insert(dst.end(), m_Data.begin(), m_Data.end()); 583 return m_Data.size(); 584 } 585 586 virtual int decodeValue(const octets_t &src, size_t cb) 587 { 588 octets_t::const_iterator beg(src.begin()); 589 octets_t data(beg, beg + cb); 590 m_Data.swap(data); 591 592 m_fPresent = true; 593 return VINF_SUCCESS; 594 } 595 596 public: 597 static RawOption *parse(uint8_t aOptCode, const char *pcszValue) 598 { 599 octets_t data; 600 int rc = DhcpOption::parseHex(data, pcszValue); 601 if (RT_FAILURE(rc)) 602 return NULL; 603 return new RawOption(aOptCode, data); 604 } 543 605 }; 544 606 -
trunk/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp
r71353 r71689 33 33 #include <VBox/intnetinline.h> 34 34 35 #include <VBox/com/com.h>36 37 35 #include "VBoxLwipCore.h" 38 36 #include "Config.h" … … 73 71 74 72 private: 73 PRTLOGGER m_pStderrReleaseLogger; 74 75 75 /* intnet plumbing */ 76 76 PSUPDRVSESSION m_pSession; … … 81 81 struct netif m_LwipNetif; 82 82 83 /* path of ~/.VirtualBox or equivalent */84 std::string m_strHome;85 86 83 Config *m_Config; 87 84 … … 98 95 99 96 private: 100 void homeInit(); 101 int logInit(const std::string &strBaseName); 97 int logInitStderr(); 102 98 103 99 /* … … 149 145 150 146 VBoxNetDhcpd::VBoxNetDhcpd() 151 : m_pSession(NIL_RTR0PTR), 147 : m_pStderrReleaseLogger(NULL), 148 m_pSession(NIL_RTR0PTR), 152 149 m_hIf(INTNET_HANDLE_INVALID), 153 150 m_pIfBuf(NULL), … … 158 155 int rc; 159 156 157 logInitStderr(); 158 160 159 rc = r3Init(); 161 160 if (RT_FAILURE(rc)) … … 170 169 ifClose(); 171 170 r3Fini(); 171 } 172 173 174 /* 175 * We don't know the name of the release log file until we parse our 176 * configuration because we use network name as basename. To get 177 * early logging to work, start with stderr-only release logger. 178 * 179 * We disable "sup" for this logger to avoid spam from SUPR3Init(). 180 */ 181 int VBoxNetDhcpd::logInitStderr() 182 { 183 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; 184 185 PRTLOGGER pLogger; 186 int rc; 187 188 uint32_t fFlags = 0; 189 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 190 fFlags |= RTLOGFLAGS_USECRLF; 191 #endif 192 193 rc = RTLogCreate(&pLogger, fFlags, 194 "all -sup all.restrict -default.restrict", 195 NULL, /* environment base */ 196 RT_ELEMENTS(s_apszGroups), s_apszGroups, 197 RTLOGDEST_STDERR, NULL); 198 if (RT_FAILURE(rc)) 199 { 200 RTPrintf("Failed to init stderr logger: %Rrs\n", rc); 201 return rc; 202 } 203 204 m_pStderrReleaseLogger = pLogger; 205 RTLogRelSetDefaultInstance(m_pStderrReleaseLogger); 206 207 return VINF_SUCCESS; 172 208 } 173 209 … … 260 296 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0'; 261 297 262 OpenReq.enmTrunkType = enmTrunkType; 298 if (enmTrunkType != kIntNetTrunkType_Invalid) 299 OpenReq.enmTrunkType = enmTrunkType; 300 else 301 OpenReq.enmTrunkType = kIntNetTrunkType_WhateverNone; 263 302 264 303 OpenReq.fFlags = 0; … … 588 627 return VERR_GENERAL_FAILURE; 589 628 590 homeInit();591 m_Config->setHome(m_strHome);592 593 logInit(m_Config->getBaseName());594 595 629 rc = m_server.init(m_Config); 596 630 … … 609 643 ifPump(); 610 644 return VINF_SUCCESS; 611 }612 613 614 void VBoxNetDhcpd::homeInit()615 {616 int rc;617 618 /* pathname of ~/.VirtualBox or equivalent */619 char szHome[RTPATH_MAX];620 rc = com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome), false);621 if (RT_FAILURE(rc))622 return;623 624 m_strHome.assign(szHome);625 }626 627 628 int VBoxNetDhcpd::logInit(const std::string &strBaseName)629 {630 int rc;631 size_t cch;632 633 /* default log file name */634 char szLogFile[RTPATH_MAX];635 cch = RTStrPrintf(szLogFile, sizeof(szLogFile),636 "%s%c%s-Dhcpd.log",637 m_strHome.c_str(), RTPATH_DELIMITER, strBaseName.c_str());638 if (cch >= sizeof(szLogFile))639 return VERR_BUFFER_OVERFLOW;640 641 642 /* get a writable copy of the base name */643 char szBaseName[RTPATH_MAX];644 rc = RTStrCopy(szBaseName, sizeof(szBaseName), strBaseName.c_str());645 if (RT_FAILURE(rc))646 return rc;647 648 /* sanitize base name some more to be usable in an environment variable name */649 for (char *p = szBaseName; *p != '\0'; ++p)650 {651 if ( *p != '_'652 && (*p < '0' || '9' < *p)653 && (*p < 'a' || 'z' < *p)654 && (*p < 'A' || 'Z' < *p))655 {656 *p = '_';657 }658 }659 660 661 /* name of the environment variable to control logging */662 char szEnvVarBase[128];663 cch = RTStrPrintf(szEnvVarBase, sizeof(szEnvVarBase),664 "VBOXDHCP_%s_RELEASE_LOG", szBaseName);665 if (cch >= sizeof(szEnvVarBase))666 return VERR_BUFFER_OVERFLOW;667 668 669 rc = com::VBoxLogRelCreate("DHCP Server",670 szLogFile,671 RTLOGFLAGS_PREFIX_TIME_PROG,672 "all all.restrict -default.restrict",673 szEnvVarBase,674 RTLOGDEST_FILE675 #ifdef DEBUG676 | RTLOGDEST_STDERR677 #endif678 ,679 32768 /* cMaxEntriesPerGroup */,680 0 /* cHistory */,681 0 /* uHistoryFileTime */,682 0 /* uHistoryFileSize */,683 NULL /* pErrInfo */);684 685 return rc;686 645 } 687 646
Note:
See TracChangeset
for help on using the changeset viewer.