Changeset 49563 in vbox for trunk/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp
- Timestamp:
- Nov 20, 2013 7:13:46 AM (11 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp
r49561 r49563 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxNetDHCP - DHCP Service for connecting to IntNet.3 * NetworkManagerDhcp - Network Manager part handling Dhcp. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 20 09-2011Oracle Corporation7 * Copyright (C) 2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 */ 17 17 18 /** @page pg_net_dhcp VBoxNetDHCP19 *20 * Write a few words...21 *22 */23 24 18 /******************************************************************************* 25 19 * Header Files * 26 20 *******************************************************************************/ 27 #include <VBox/com/com.h> 28 #include <VBox/com/listeners.h> 29 #include <VBox/com/string.h> 30 #include <VBox/com/Guid.h> 31 #include <VBox/com/array.h> 32 #include <VBox/com/ErrorInfo.h> 33 #include <VBox/com/errorprint.h> 34 #include <VBox/com/EventQueue.h> 35 #include <VBox/com/VirtualBox.h> 36 37 #include <iprt/alloca.h> 38 #include <iprt/buildconfig.h> 39 #include <iprt/err.h> 40 #include <iprt/net.h> /* must come before getopt */ 41 #include <iprt/getopt.h> 42 #include <iprt/initterm.h> 43 #include <iprt/message.h> 21 #include <iprt/asm.h> 22 #include <iprt/cdefs.h> 23 #include <iprt/net.h> 44 24 #include <iprt/param.h> 45 25 #include <iprt/path.h> … … 48 28 #include <iprt/string.h> 49 29 50 #include <VBox/sup.h>51 #include <VBox/intnet.h>52 #include <VBox/intnetinline.h>53 #include <VBox/vmm/vmm.h>54 #include <VBox/version.h>55 56 57 #include "../NetLib/VBoxNetLib.h"58 30 #include "../NetLib/shared_ptr.h" 59 31 … … 63 35 #include <map> 64 36 65 #include "../NetLib/VBoxNetBaseService.h" 66 67 #ifdef RT_OS_WINDOWS /* WinMain */ 68 # include <Windows.h> 69 # include <stdlib.h> 70 # ifdef INET_ADDRSTRLEN 71 /* On Windows INET_ADDRSTRLEN defined as 22 Ws2ipdef.h, because it include port number */ 72 # undef INET_ADDRSTRLEN 73 # endif 74 # define INET_ADDRSTRLEN 16 75 #else 76 # include <netinet/in.h> 77 #endif 78 79 37 #include <VBox/sup.h> 38 #include <VBox/intnet.h> 80 39 #include "Config.h" 81 /******************************************************************************* 82 * Structures and Typedefs * 83 *******************************************************************************/ 84 /** 85 * DHCP server instance. 86 */ 87 class VBoxNetDhcp: public VBoxNetBaseService 88 { 89 public: 90 VBoxNetDhcp(); 91 virtual ~VBoxNetDhcp(); 92 93 int init(); 94 int run(void); 95 void usage(void) { /* XXX: document options */ }; 96 int parseOpt(int rc, const RTGETOPTUNION& getOptVal); 97 98 protected: 99 bool handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb); 100 bool handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb); 101 bool handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb); 102 bool handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb); 103 bool handleDhcpReqRelease(PCRTNETBOOTP pDhcpMsg, size_t cb); 104 105 void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const; 106 static const char *debugDhcpName(uint8_t uMsgType); 107 108 private: 109 int initNoMain(); 110 int initWithMain(); 111 112 protected: 113 /** @name The DHCP server specific configuration data members. 114 * @{ */ 115 /* 116 * XXX: what was the plan? SQL3 or plain text file? 117 * How it will coexists with managment from VBoxManagement, who should manage db 118 * in that case (VBoxManage, VBoxSVC ???) 119 */ 120 std::string m_LeaseDBName; 121 122 /** @} */ 123 124 /* corresponding dhcp server description in Main */ 125 ComPtr<IDHCPServer> m_DhcpServer; 126 127 ComPtr<INATNetwork> m_NATNetwork; 128 129 /* 130 * We will ignore cmd line parameters IFF there will be some DHCP specific arguments 131 * otherwise all paramters will come from Main. 132 */ 133 bool m_fIgnoreCmdLineParameters; 134 135 /* 136 * -b -n 10.0.1.2 -m 255.255.255.0 -> to the list processing in 137 */ 138 typedef struct 139 { 140 char Key; 141 std::string strValue; 142 } CMDLNPRM; 143 std::list<CMDLNPRM> CmdParameterll; 144 typedef std::list<CMDLNPRM>::iterator CmdParameterIterator; 145 146 /** @name Debug stuff 147 * @{ */ 148 int32_t m_cVerbosity; 149 uint8_t m_uCurMsgType; 150 size_t m_cbCurMsg; 151 PCRTNETBOOTP m_pCurMsg; 152 VBOXNETUDPHDRS m_CurHdrs; 153 /** @} */ 154 }; 155 156 /******************************************************************************* 157 * Global Variables * 158 *******************************************************************************/ 159 /** Pointer to the DHCP server. */ 160 static VBoxNetDhcp *g_pDhcp; 161 162 /* DHCP server specific options */ 163 static RTGETOPTDEF g_aOptionDefs[] = 164 { 165 { "--lease-db", 'D', RTGETOPT_REQ_STRING }, 166 { "--begin-config", 'b', RTGETOPT_REQ_NOTHING }, 167 { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR }, 168 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR }, 169 { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR }, 170 }; 171 172 /** 173 * Construct a DHCP server with a default configuration. 174 */ 175 VBoxNetDhcp::VBoxNetDhcp() 176 { 177 m_Name = "VBoxNetDhcp"; 178 m_Network = "VBoxNetDhcp"; 179 m_TrunkName = ""; 180 m_enmTrunkType = kIntNetTrunkType_WhateverNone; 181 m_MacAddress.au8[0] = 0x08; 182 m_MacAddress.au8[1] = 0x00; 183 m_MacAddress.au8[2] = 0x27; 184 m_MacAddress.au8[3] = 0x40; 185 m_MacAddress.au8[4] = 0x41; 186 m_MacAddress.au8[5] = 0x42; 187 m_Ipv4Address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 5))); 188 189 m_pSession = NIL_RTR0PTR; 190 m_cbSendBuf = 8192; 191 m_cbRecvBuf = 51200; /** @todo tune to 64 KB with help from SrvIntR0 */ 192 m_hIf = INTNET_HANDLE_INVALID; 193 m_pIfBuf = NULL; 194 195 m_cVerbosity = 0; 196 m_uCurMsgType = UINT8_MAX; 197 m_cbCurMsg = 0; 198 m_pCurMsg = NULL; 199 memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs)); 200 201 m_fIgnoreCmdLineParameters = true; 202 203 for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i) 204 m_vecOptionDefs.push_back(&g_aOptionDefs[i]); 205 206 #if 0 /* enable to hack the code without a mile long argument list. */ 207 VBoxNetDhcpCfg *pDefCfg = new VBoxNetDhcpCfg(); 208 pDefCfg->m_LowerAddr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2,100))); 209 pDefCfg->m_UpperAddr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2,250))); 210 pDefCfg->m_SubnetMask.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(255,255,255, 0))); 211 RTNETADDRIPV4 Addr; 212 Addr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 1))); 213 pDefCfg->m_Routers.push_back(Addr); 214 Addr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 2))); 215 pDefCfg->m_DNSes.push_back(Addr); 216 pDefCfg->m_DomainName = "vboxnetdhcp.org"; 217 # if 0 218 pDefCfg->m_cSecLease = 60*60; /* 1 hour */ 219 # else 220 pDefCfg->m_cSecLease = 30; /* sec */ 221 # endif 222 pDefCfg->m_TftpServer = "10.0.2.3"; //?? 223 this->addConfig(pDefCfg); 224 #endif 225 } 226 227 228 /** 229 * Destruct a DHCP server. 230 */ 231 VBoxNetDhcp::~VBoxNetDhcp() 232 { 233 } 234 235 236 237 238 /** 239 * Parse the DHCP specific arguments. 240 * 241 * This callback caled for each paramenter so 242 * .... 243 * we nee post analisys of the parameters, at least 244 * for -b, -g, -l, -u, -m 245 */ 246 int VBoxNetDhcp::parseOpt(int rc, const RTGETOPTUNION& Val) 247 { 248 CMDLNPRM prm; 249 250 /* Ok, we've entered here, thus we can't ignore cmd line parameters anymore */ 251 m_fIgnoreCmdLineParameters = false; 252 253 prm.Key = rc; 254 255 switch (rc) 256 { 257 case 'l': 258 case 'u': 259 case 'g': 260 { 261 char buf[17]; 262 RTStrPrintf(buf, 17, "%RTnaipv4", Val.IPv4Addr.u); 263 prm.strValue = buf; 264 CmdParameterll.push_back(prm); 265 } 266 break; 267 268 case 'b': // ignore 269 case 'D': // ignore 270 break; 271 272 default: 273 rc = RTGetOptPrintError(rc, &Val); 274 RTPrintf("Use --help for more information.\n"); 275 return rc; 276 } 277 278 return VINF_SUCCESS; 279 } 280 281 int VBoxNetDhcp::init() 282 { 283 int rc = this->VBoxNetBaseService::init(); 284 AssertRCReturn(rc, rc); 285 286 NetworkManager *netManager = NetworkManager::getNetworkManager(); 287 288 netManager->setOurAddress(m_Ipv4Address); 289 netManager->setOurNetmask(m_Ipv4Netmask); 290 netManager->setOurMac(m_MacAddress); 291 292 if (isMainNeeded()) 293 rc = initWithMain(); 294 else 295 rc = initNoMain(); 296 297 AssertRCReturn(rc, rc); 298 299 return VINF_SUCCESS; 300 } 301 302 /** 303 * Runs the DHCP server. 304 * 305 * @returns exit code + error message to stderr on failure, won't return on 306 * success (you must kill this process). 307 */ 308 int VBoxNetDhcp::run(void) 309 { 310 311 /* XXX: shortcut should be hidden from network manager */ 312 NetworkManager *netManager = NetworkManager::getNetworkManager(); 313 netManager->setSession(m_pSession); 314 netManager->setInterface(m_hIf); 315 netManager->setRingBuffer(m_pIfBuf); 316 317 /* 318 * The loop. 319 */ 320 PINTNETRINGBUF pRingBuf = &m_pIfBuf->Recv; 321 for (;;) 322 { 323 /* 324 * Wait for a packet to become available. 325 */ 326 INTNETIFWAITREQ WaitReq; 327 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; 328 WaitReq.Hdr.cbReq = sizeof(WaitReq); 329 WaitReq.pSession = m_pSession; 330 WaitReq.hIf = m_hIf; 331 WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */ /** @todo fix interruptability in SrvIntNet! */ 332 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr); 333 if (RT_FAILURE(rc)) 334 { 335 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED) 336 continue; 337 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc); 338 return 1; 339 } 340 341 /* 342 * Process the receive buffer. 343 */ 344 while (IntNetRingHasMoreToRead(pRingBuf)) 345 { 346 size_t cb; 347 void *pv = VBoxNetUDPMatch(m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m_MacAddress, 348 VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST | VBOXNETUDP_MATCH_CHECKSUM 349 | (m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0), 350 &m_CurHdrs, &cb); 351 if (pv && cb) 352 { 353 PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv; 354 m_pCurMsg = pDhcpMsg; 355 m_cbCurMsg = cb; 356 357 uint8_t uMsgType; 358 if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cb, &uMsgType)) 359 { 360 m_uCurMsgType = uMsgType; 361 handleDhcpMsg(uMsgType, pDhcpMsg, cb); 362 m_uCurMsgType = UINT8_MAX; 363 } 364 else 365 debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */ 366 367 m_pCurMsg = NULL; 368 m_cbCurMsg = 0; 369 } 370 else if (VBoxNetArpHandleIt(m_pSession, m_hIf, m_pIfBuf, &m_MacAddress, m_Ipv4Address)) 371 { 372 /* nothing */ 373 } 374 375 /* Advance to the next frame. */ 376 IntNetRingSkipFrame(pRingBuf); 377 } 378 } 379 380 return 0; 381 } 382 383 384 /** 385 * Handles a DHCP message. 386 * 387 * @returns true if handled, false if not. 388 * @param uMsgType The message type. 389 * @param pDhcpMsg The DHCP message. 390 * @param cb The size of the DHCP message. 391 */ 392 bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb) 393 { 394 if (pDhcpMsg->bp_op == RTNETBOOTP_OP_REQUEST) 395 { 396 switch (uMsgType) 397 { 398 case RTNET_DHCP_MT_DISCOVER: 399 return handleDhcpReqDiscover(pDhcpMsg, cb); 400 401 case RTNET_DHCP_MT_REQUEST: 402 return handleDhcpReqRequest(pDhcpMsg, cb); 403 404 case RTNET_DHCP_MT_DECLINE: 405 return handleDhcpReqDecline(pDhcpMsg, cb); 406 407 case RTNET_DHCP_MT_RELEASE: 408 return handleDhcpReqRelease(pDhcpMsg, cb); 409 410 case RTNET_DHCP_MT_INFORM: 411 debugPrint(0, true, "Should we handle this?"); 412 break; 413 414 default: 415 debugPrint(0, true, "Unexpected."); 416 break; 417 } 418 } 419 return false; 420 } 421 40 #include "ClientDataInt.h" 422 41 423 42 /** … … 429 48 * @param cb The message size. 430 49 */ 431 bool VBoxNetDhcp::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb)50 bool NetworkManager::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb) 432 51 { 433 52 RawOption opt; … … 444 63 445 64 /* 3. Send of offer */ 446 NetworkManager *networkManager = NetworkManager::getNetworkManager();447 65 448 66 lease.bindingPhase(true); 449 67 lease.phaseStart(RTTimeMilliTS()); 450 68 lease.setExpiration(300); /* 3 min. */ 451 networkManager->offer4Client(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);69 offer4Client(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt); 452 70 453 71 return VINF_SUCCESS; … … 463 81 * @param cb The message size. 464 82 */ 465 bool VBoxNetDhcp::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)83 bool NetworkManager::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb) 466 84 { 467 85 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager(); 468 NetworkManager *networkManager = NetworkManager::getNetworkManager();469 86 470 87 /* 1. find client */ … … 480 97 /* send client to INIT state */ 481 98 Client c(client); 482 n etworkManager->nak(client, pDhcpMsg->bp_xid);99 nak(client, pDhcpMsg->bp_xid); 483 100 confManager->expireLease4Client(c); 484 101 return true; … … 496 113 AssertRCReturn(rc, false); 497 114 498 networkManager->ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);115 ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt); 499 116 } 500 117 } 501 118 else 502 119 { 503 n etworkManager->nak(client, pDhcpMsg->bp_xid);120 nak(client, pDhcpMsg->bp_xid); 504 121 } 505 122 return true; … … 515 132 * @param cb The message size. 516 133 */ 517 bool VBoxNetDhcp::handleDhcpReqDecline(PCRTNETBOOTP, size_t)134 bool NetworkManager::handleDhcpReqDecline(PCRTNETBOOTP, size_t) 518 135 { 519 136 /** @todo Probably need to match the server IP here to work correctly with … … 527 144 528 145 /** @todo this is not required in the initial implementation, do it later. */ 529 debugPrint(1, true, "DECLINE is not implemented");530 146 return true; 531 147 } … … 540 156 * @param cb The message size. 541 157 */ 542 bool VBoxNetDhcp::handleDhcpReqRelease(PCRTNETBOOTP, size_t)158 bool NetworkManager::handleDhcpReqRelease(PCRTNETBOOTP, size_t) 543 159 { 544 160 /** @todo Probably need to match the server IP here to work correctly with … … 564 180 565 181 /** @todo this is not required in the initial implementation, do it later. */ 566 debugPrint(1, true, "RELEASE is not implemented");567 182 return true; 568 183 } 569 184 570 571 /**572 * Print debug message depending on the m_cVerbosity level.573 *574 * @param iMinLevel The minimum m_cVerbosity level for this message.575 * @param fMsg Whether to dump parts for the current DHCP message.576 * @param pszFmt The message format string.577 * @param va Optional arguments.578 */579 void VBoxNetDhcp::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const580 {581 if (iMinLevel <= m_cVerbosity)582 {583 va_list vaCopy; /* This dude is *very* special, thus the copy. */584 va_copy(vaCopy, va);585 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);586 va_end(vaCopy);587 588 if ( fMsg589 && m_cVerbosity >= 2590 && m_pCurMsg)591 {592 /* XXX: export this to debugPrinfDhcpMsg or variant and other method export593 * to base class594 */595 const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";596 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d xid=%#x\n",597 pszMsg,598 &m_pCurMsg->bp_chaddr,599 m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],600 m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],601 m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3],602 m_pCurMsg->bp_xid);603 }604 }605 }606 607 608 /**609 * Gets the name of given DHCP message type.610 *611 * @returns Readonly name.612 * @param uMsgType The message number.613 */614 /* static */ const char *VBoxNetDhcp::debugDhcpName(uint8_t uMsgType)615 {616 switch (uMsgType)617 {618 case 0: return "MT_00";619 case RTNET_DHCP_MT_DISCOVER: return "DISCOVER";620 case RTNET_DHCP_MT_OFFER: return "OFFER";621 case RTNET_DHCP_MT_REQUEST: return "REQUEST";622 case RTNET_DHCP_MT_DECLINE: return "DECLINE";623 case RTNET_DHCP_MT_ACK: return "ACK";624 case RTNET_DHCP_MT_NAC: return "NAC";625 case RTNET_DHCP_MT_RELEASE: return "RELEASE";626 case RTNET_DHCP_MT_INFORM: return "INFORM";627 case 9: return "MT_09";628 case 10: return "MT_0a";629 case 11: return "MT_0b";630 case 12: return "MT_0c";631 case 13: return "MT_0d";632 case 14: return "MT_0e";633 case 15: return "MT_0f";634 case 16: return "MT_10";635 case 17: return "MT_11";636 case 18: return "MT_12";637 case 19: return "MT_13";638 case UINT8_MAX: return "MT_ff";639 default: return "UNKNOWN";640 }641 }642 643 644 int VBoxNetDhcp::initNoMain()645 {646 CmdParameterIterator it;647 648 RTNETADDRIPV4 networkId;649 networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u;650 RTNETADDRIPV4 netmask = m_Ipv4Netmask;651 652 RTNETADDRIPV4 UpperAddress;653 RTNETADDRIPV4 LowerAddress = networkId;654 UpperAddress.u = RT_H2N_U32(RT_N2H_U32(LowerAddress.u) | RT_N2H_U32(netmask.u));655 656 for (it = CmdParameterll.begin(); it != CmdParameterll.end(); ++it)657 {658 switch(it->Key)659 {660 case 'l':661 RTNetStrToIPv4Addr(it->strValue.c_str(), &LowerAddress);662 break;663 664 case 'u':665 RTNetStrToIPv4Addr(it->strValue.c_str(), &UpperAddress);666 break;667 case 'b':668 break;669 670 }671 }672 673 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();674 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);675 confManager->addNetwork(unconst(g_RootConfig),676 networkId,677 m_Ipv4Netmask,678 LowerAddress,679 UpperAddress);680 681 return VINF_SUCCESS;682 }683 684 685 int VBoxNetDhcp::initWithMain()686 {687 /* ok, here we should initiate instance of dhcp server688 * and listener for Dhcp configuration events689 */690 AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);691 692 HRESULT hrc = virtualbox->FindDHCPServerByNetworkName(com::Bstr(m_Network.c_str()).raw(),693 m_DhcpServer.asOutParam());694 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);695 696 hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_Network.c_str()).raw(),697 m_NATNetwork.asOutParam());698 699 BOOL fNeedDhcpServer = false;700 if (FAILED(m_NATNetwork->COMGETTER(NeedDhcpServer)(&fNeedDhcpServer)))701 return VERR_INTERNAL_ERROR;702 703 if (!fNeedDhcpServer)704 return VERR_CANCELLED;705 706 RTNETADDRIPV4 gateway;707 com::Bstr strGateway;708 709 hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());710 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);711 RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);712 713 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();714 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);715 confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);716 717 unsigned int i;718 unsigned int count_strs;719 com::SafeArray<BSTR> strs;720 std::map<RTNETADDRIPV4, uint32_t> MapIp4Addr2Off;721 722 hrc = m_NATNetwork->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));723 if ( SUCCEEDED(hrc)724 && (count_strs = strs.size()))725 {726 for (i = 0; i < count_strs; ++i)727 {728 char szAddr[17];729 RTNETADDRIPV4 ip4addr;730 char *pszTerm;731 uint32_t u32Off;732 com::Utf8Str strLo2Off(strs[i]);733 const char *pszLo2Off = strLo2Off.c_str();734 735 RT_ZERO(szAddr);736 737 pszTerm = RTStrStr(pszLo2Off, "=");738 739 if ( pszTerm740 && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN)741 {742 memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));743 int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);744 if (RT_SUCCESS(rc))745 {746 u32Off = RTStrToUInt32(pszTerm + 1);747 if (u32Off != 0)748 MapIp4Addr2Off.insert(749 std::map<RTNETADDRIPV4,uint32_t>::value_type(ip4addr, u32Off));750 }751 }752 }753 }754 755 strs.setNull();756 ComPtr<IHost> host;757 if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))758 {759 if (SUCCEEDED(host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs))))760 {761 RTNETADDRIPV4 addr;762 763 confManager->flushAddressList(RTNET_DHCP_OPT_DNS);764 int rc;765 for (i = 0; i < strs.size(); ++i)766 {767 rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);768 if (RT_SUCCESS(rc))769 {770 if (addr.au8[0] == 127)771 {772 if (MapIp4Addr2Off[addr] != 0)773 {774 addr.u = RT_H2N_U32(RT_N2H_U32(m_Ipv4Address.u & m_Ipv4Netmask.u)775 + MapIp4Addr2Off[addr]);776 }777 else778 continue;779 }780 781 confManager->addToAddressList(RTNET_DHCP_OPT_DNS, addr);782 }783 }784 }785 786 strs.setNull();787 #if 0788 if (SUCCEEDED(host->COMGETTER(SearchStrings)(ComSafeArrayAsOutParam(strs))))789 {790 /* XXX: todo. */;791 }792 strs.setNull();793 #endif794 com::Bstr domain;795 if (SUCCEEDED(host->COMGETTER(DomainName)(domain.asOutParam())))796 confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, std::string(com::Utf8Str(domain).c_str()));797 }798 799 com::Bstr strUpperIp, strLowerIp;800 801 RTNETADDRIPV4 LowerAddress;802 RTNETADDRIPV4 UpperAddress;803 804 hrc = m_DhcpServer->COMGETTER(UpperIP)(strUpperIp.asOutParam());805 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);806 RTNetStrToIPv4Addr(com::Utf8Str(strUpperIp).c_str(), &UpperAddress);807 808 809 hrc = m_DhcpServer->COMGETTER(LowerIP)(strLowerIp.asOutParam());810 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);811 RTNetStrToIPv4Addr(com::Utf8Str(strLowerIp).c_str(), &LowerAddress);812 813 RTNETADDRIPV4 networkId;814 networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u;815 std::string name = std::string("default");816 817 confManager->addNetwork(unconst(g_RootConfig),818 networkId,819 m_Ipv4Netmask,820 LowerAddress,821 UpperAddress);822 823 com::Bstr bstr;824 hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());825 std::string strXmlLeaseFile(com::Utf8StrFmt("%ls%c%s.leases",826 bstr.raw(), RTPATH_DELIMITER, m_Network.c_str()).c_str());827 confManager->loadFromFile(strXmlLeaseFile);828 829 return VINF_SUCCESS;830 }831 832 /**833 * Entry point.834 */835 extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv)836 {837 /*838 * Instantiate the DHCP server and hand it the options.839 */840 841 VBoxNetDhcp *pDhcp = new VBoxNetDhcp();842 if (!pDhcp)843 {844 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxNetDhcp failed!\n");845 return 1;846 }847 int rc = pDhcp->parseArgs(argc - 1, argv + 1);848 if (rc)849 return rc;850 851 pDhcp->init();852 853 /*854 * Try connect the server to the network.855 */856 rc = pDhcp->tryGoOnline();857 if (RT_FAILURE(rc))858 {859 delete pDhcp;860 return 1;861 }862 863 /*864 * Process requests.865 */866 g_pDhcp = pDhcp;867 rc = pDhcp->run();868 g_pDhcp = NULL;869 delete pDhcp;870 871 return 0;872 }873 874 875 #ifndef VBOX_WITH_HARDENING876 877 int main(int argc, char **argv)878 {879 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);880 if (RT_FAILURE(rc))881 return RTMsgInitFailure(rc);882 883 return TrustedMain(argc, argv);884 }885 886 # ifdef RT_OS_WINDOWS887 888 static LRESULT CALLBACK WindowProc(HWND hwnd,889 UINT uMsg,890 WPARAM wParam,891 LPARAM lParam892 )893 {894 if(uMsg == WM_DESTROY)895 {896 PostQuitMessage(0);897 return 0;898 }899 return DefWindowProc (hwnd, uMsg, wParam, lParam);900 }901 902 static LPCWSTR g_WndClassName = L"VBoxNetDHCPClass";903 904 static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)905 {906 HWND hwnd = 0;907 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);908 bool bExit = false;909 910 /* Register the Window Class. */911 WNDCLASS wc;912 wc.style = 0;913 wc.lpfnWndProc = WindowProc;914 wc.cbClsExtra = 0;915 wc.cbWndExtra = sizeof(void *);916 wc.hInstance = hInstance;917 wc.hIcon = NULL;918 wc.hCursor = NULL;919 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);920 wc.lpszMenuName = NULL;921 wc.lpszClassName = g_WndClassName;922 923 ATOM atomWindowClass = RegisterClass(&wc);924 925 if (atomWindowClass != 0)926 {927 /* Create the window. */928 hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,929 g_WndClassName, g_WndClassName,930 WS_POPUPWINDOW,931 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);932 933 if (hwnd)934 {935 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,936 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);937 938 MSG msg;939 while (GetMessage(&msg, NULL, 0, 0))940 {941 TranslateMessage(&msg);942 DispatchMessage(&msg);943 }944 945 DestroyWindow (hwnd);946 947 bExit = true;948 }949 950 UnregisterClass (g_WndClassName, hInstance);951 }952 953 if(bExit)954 {955 /* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */956 exit(0);957 }958 959 return 0;960 }961 962 963 /** (We don't want a console usually.) */964 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)965 {966 NOREF(hInstance); NOREF(hPrevInstance); NOREF(lpCmdLine); NOREF(nCmdShow);967 968 HANDLE hThread = CreateThread(969 NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */970 0, /*__in SIZE_T dwStackSize, */971 MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/972 NULL, /*__in_opt LPVOID lpParameter,*/973 0, /*__in DWORD dwCreationFlags,*/974 NULL /*__out_opt LPDWORD lpThreadId*/975 );976 977 if(hThread != NULL)978 CloseHandle(hThread);979 980 return main(__argc, __argv);981 }982 # endif /* RT_OS_WINDOWS */983 984 #endif /* !VBOX_WITH_HARDENING */985
Note:
See TracChangeset
for help on using the changeset viewer.