VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp@ 60422

Last change on this file since 60422 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.8 KB
Line 
1/* $Id: VBoxNetDHCP.cpp 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * VBoxNetDHCP - DHCP Service for connecting to IntNet.
4 */
5
6/*
7 * Copyright (C) 2009-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @page pg_net_dhcp VBoxNetDHCP
19 *
20 * Write a few words...
21 *
22 */
23
24
25/*********************************************************************************************************************************
26* Header Files *
27*********************************************************************************************************************************/
28#include <VBox/com/com.h>
29#include <VBox/com/listeners.h>
30#include <VBox/com/string.h>
31#include <VBox/com/Guid.h>
32#include <VBox/com/array.h>
33#include <VBox/com/ErrorInfo.h>
34#include <VBox/com/errorprint.h>
35#include <VBox/com/EventQueue.h>
36#include <VBox/com/VirtualBox.h>
37
38#include <iprt/alloca.h>
39#include <iprt/buildconfig.h>
40#include <iprt/err.h>
41#include <iprt/net.h> /* must come before getopt */
42#include <iprt/getopt.h>
43#include <iprt/initterm.h>
44#include <iprt/message.h>
45#include <iprt/param.h>
46#include <iprt/path.h>
47#include <iprt/stream.h>
48#include <iprt/time.h>
49#include <iprt/string.h>
50
51#include <VBox/sup.h>
52#include <VBox/intnet.h>
53#include <VBox/intnetinline.h>
54#include <VBox/vmm/vmm.h>
55#include <VBox/version.h>
56
57
58#include "../NetLib/VBoxNetLib.h"
59#include "../NetLib/shared_ptr.h"
60
61#include <vector>
62#include <list>
63#include <string>
64#include <map>
65
66#include "../NetLib/VBoxNetBaseService.h"
67#include "../NetLib/utils.h"
68
69#ifdef RT_OS_WINDOWS /* WinMain */
70# include <Windows.h>
71# include <stdlib.h>
72# ifdef INET_ADDRSTRLEN
73/* On Windows INET_ADDRSTRLEN defined as 22 Ws2ipdef.h, because it include port number */
74# undef INET_ADDRSTRLEN
75# endif
76# define INET_ADDRSTRLEN 16
77#else
78# include <netinet/in.h>
79#endif
80
81
82#include "Config.h"
83
84
85/*********************************************************************************************************************************
86* Structures and Typedefs *
87*********************************************************************************************************************************/
88/**
89 * DHCP server instance.
90 */
91class VBoxNetDhcp: public VBoxNetBaseService, public NATNetworkEventAdapter
92{
93public:
94 VBoxNetDhcp();
95 virtual ~VBoxNetDhcp();
96
97 int init();
98 void done();
99 void usage(void) { /* XXX: document options */ };
100 int parseOpt(int rc, const RTGETOPTUNION& getOptVal);
101 int processFrame(void *, size_t) {return VERR_IGNORED; };
102 int processGSO(PCPDMNETWORKGSO, size_t) {return VERR_IGNORED; };
103 int processUDP(void *, size_t);
104
105protected:
106 bool handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb);
107
108 void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
109 static const char *debugDhcpName(uint8_t uMsgType);
110
111private:
112 int initNoMain();
113 int initWithMain();
114 HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);
115 int fetchAndUpdateDnsInfo();
116
117protected:
118 /** @name The DHCP server specific configuration data members.
119 * @{ */
120 /*
121 * XXX: what was the plan? SQL3 or plain text file?
122 * How it will coexists with managment from VBoxManagement, who should manage db
123 * in that case (VBoxManage, VBoxSVC ???)
124 */
125 std::string m_LeaseDBName;
126
127 /** @} */
128
129 /* corresponding dhcp server description in Main */
130 ComPtr<IDHCPServer> m_DhcpServer;
131
132 ComPtr<INATNetwork> m_NATNetwork;
133
134 /** Listener for Host DNS changes */
135 ComNatListenerPtr m_VBoxListener;
136 ComNatListenerPtr m_VBoxClientListener;
137
138 NetworkManager *m_NetworkManager;
139
140 /*
141 * We will ignore cmd line parameters IFF there will be some DHCP specific arguments
142 * otherwise all paramters will come from Main.
143 */
144 bool m_fIgnoreCmdLineParameters;
145
146 /*
147 * -b -n 10.0.1.2 -m 255.255.255.0 -> to the list processing in
148 */
149 typedef struct
150 {
151 char Key;
152 std::string strValue;
153 } CMDLNPRM;
154 std::list<CMDLNPRM> CmdParameterll;
155 typedef std::list<CMDLNPRM>::iterator CmdParameterIterator;
156
157 /** @name Debug stuff
158 * @{ */
159 int32_t m_cVerbosity;
160 uint8_t m_uCurMsgType;
161 size_t m_cbCurMsg;
162 PCRTNETBOOTP m_pCurMsg;
163 VBOXNETUDPHDRS m_CurHdrs;
164 /** @} */
165};
166
167
168static inline int configGetBoundryAddress(const ComDhcpServerPtr& dhcp, bool fUpperBoundry, RTNETADDRIPV4& boundryAddress)
169{
170 boundryAddress.u = INADDR_ANY;
171
172 HRESULT hrc;
173 com::Bstr strAddress;
174 if (fUpperBoundry)
175 hrc = dhcp->COMGETTER(UpperIP)(strAddress.asOutParam());
176 else
177 hrc = dhcp->COMGETTER(LowerIP)(strAddress.asOutParam());
178 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
179
180 return RTNetStrToIPv4Addr(com::Utf8Str(strAddress).c_str(), &boundryAddress);
181}
182
183
184/*********************************************************************************************************************************
185* Global Variables *
186*********************************************************************************************************************************/
187/** Pointer to the DHCP server. */
188static VBoxNetDhcp *g_pDhcp;
189
190/* DHCP server specific options */
191static RTGETOPTDEF g_aOptionDefs[] =
192{
193 { "--lease-db", 'D', RTGETOPT_REQ_STRING },
194 { "--begin-config", 'b', RTGETOPT_REQ_NOTHING },
195 { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR },
196 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR },
197 { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR },
198};
199
200/**
201 * Construct a DHCP server with a default configuration.
202 */
203VBoxNetDhcp::VBoxNetDhcp()
204 : VBoxNetBaseService("VBoxNetDhcp", "VBoxNetDhcp"),
205 m_NetworkManager(NULL)
206{
207 /* m_enmTrunkType = kIntNetTrunkType_WhateverNone; */
208 RTMAC mac;
209 mac.au8[0] = 0x08;
210 mac.au8[1] = 0x00;
211 mac.au8[2] = 0x27;
212 mac.au8[3] = 0x40;
213 mac.au8[4] = 0x41;
214 mac.au8[5] = 0x42;
215 setMacAddress(mac);
216
217 RTNETADDRIPV4 address;
218 address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 5)));
219 setIpv4Address(address);
220
221 setSendBufSize(8 * _1K);
222 setRecvBufSize(50 * _1K);
223
224 m_uCurMsgType = UINT8_MAX;
225 m_cbCurMsg = 0;
226 m_pCurMsg = NULL;
227 RT_ZERO(m_CurHdrs);
228
229 m_fIgnoreCmdLineParameters = true;
230
231 for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i)
232 addCommandLineOption(&g_aOptionDefs[i]);
233}
234
235
236/**
237 * Destruct a DHCP server.
238 */
239VBoxNetDhcp::~VBoxNetDhcp()
240{
241}
242
243
244
245
246/**
247 * Parse the DHCP specific arguments.
248 *
249 * This callback caled for each paramenter so
250 * ....
251 * we nee post analisys of the parameters, at least
252 * for -b, -g, -l, -u, -m
253 */
254int VBoxNetDhcp::parseOpt(int rc, const RTGETOPTUNION& Val)
255{
256 CMDLNPRM prm;
257
258 /* Ok, we've entered here, thus we can't ignore cmd line parameters anymore */
259 m_fIgnoreCmdLineParameters = false;
260
261 prm.Key = rc;
262
263 switch (rc)
264 {
265 case 'l':
266 case 'u':
267 case 'g':
268 {
269 char buf[17];
270 RTStrPrintf(buf, 17, "%RTnaipv4", Val.IPv4Addr.u);
271 prm.strValue = buf;
272 CmdParameterll.push_back(prm);
273 }
274 break;
275
276 case 'b': // ignore
277 case 'D': // ignore
278 break;
279
280 default:
281 rc = RTGetOptPrintError(rc, &Val);
282 RTPrintf("Use --help for more information.\n");
283 return rc;
284 }
285
286 return VINF_SUCCESS;
287}
288
289int VBoxNetDhcp::init()
290{
291 int rc = this->VBoxNetBaseService::init();
292 AssertRCReturn(rc, rc);
293
294 if (isMainNeeded())
295 rc = initWithMain();
296 else
297 rc = initNoMain();
298 AssertRCReturn(rc, rc);
299
300 m_NetworkManager = NetworkManager::getNetworkManager(m_DhcpServer);
301 AssertPtrReturn(m_NetworkManager, VERR_INTERNAL_ERROR);
302
303 m_NetworkManager->setOurAddress(getIpv4Address());
304 m_NetworkManager->setOurNetmask(getIpv4Netmask());
305 m_NetworkManager->setOurMac(getMacAddress());
306 m_NetworkManager->setService(this);
307
308 return VINF_SUCCESS;
309}
310
311void VBoxNetDhcp::done()
312{
313 destroyNatListener(m_VBoxListener, virtualbox);
314 destroyClientListener(m_VBoxClientListener, virtualboxClient);
315}
316
317int VBoxNetDhcp::processUDP(void *pv, size_t cbPv)
318{
319 PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
320 m_pCurMsg = pDhcpMsg;
321 m_cbCurMsg = cbPv;
322
323 uint8_t uMsgType;
324 if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cbPv, &uMsgType))
325 {
326 m_uCurMsgType = uMsgType;
327 {
328 /* To avoid fight with event processing thread */
329 VBoxNetALock(this);
330 handleDhcpMsg(uMsgType, pDhcpMsg, cbPv);
331 }
332 m_uCurMsgType = UINT8_MAX;
333 }
334 else
335 debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
336
337 m_pCurMsg = NULL;
338 m_cbCurMsg = 0;
339
340 return VINF_SUCCESS;
341}
342
343
344/**
345 * Handles a DHCP message.
346 *
347 * @returns true if handled, false if not.
348 * @param uMsgType The message type.
349 * @param pDhcpMsg The DHCP message.
350 * @param cb The size of the DHCP message.
351 */
352bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb)
353{
354 if (pDhcpMsg->bp_op == RTNETBOOTP_OP_REQUEST)
355 {
356 AssertPtrReturn(m_NetworkManager, false);
357
358 switch (uMsgType)
359 {
360 case RTNET_DHCP_MT_DISCOVER:
361 return m_NetworkManager->handleDhcpReqDiscover(pDhcpMsg, cb);
362
363 case RTNET_DHCP_MT_REQUEST:
364 return m_NetworkManager->handleDhcpReqRequest(pDhcpMsg, cb);
365
366 case RTNET_DHCP_MT_DECLINE:
367 return m_NetworkManager->handleDhcpReqDecline(pDhcpMsg, cb);
368
369 case RTNET_DHCP_MT_RELEASE:
370 return m_NetworkManager->handleDhcpReqRelease(pDhcpMsg, cb);
371
372 case RTNET_DHCP_MT_INFORM:
373 debugPrint(0, true, "Should we handle this?");
374 break;
375
376 default:
377 debugPrint(0, true, "Unexpected.");
378 break;
379 }
380 }
381 return false;
382}
383
384/**
385 * Print debug message depending on the m_cVerbosity level.
386 *
387 * @param iMinLevel The minimum m_cVerbosity level for this message.
388 * @param fMsg Whether to dump parts for the current DHCP message.
389 * @param pszFmt The message format string.
390 * @param va Optional arguments.
391 */
392void VBoxNetDhcp::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
393{
394 if (iMinLevel <= m_cVerbosity)
395 {
396 va_list vaCopy; /* This dude is *very* special, thus the copy. */
397 va_copy(vaCopy, va);
398 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);
399 va_end(vaCopy);
400
401 if ( fMsg
402 && m_cVerbosity >= 2
403 && m_pCurMsg)
404 {
405 /* XXX: export this to debugPrinfDhcpMsg or variant and other method export
406 * to base class
407 */
408 const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
409 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",
410 pszMsg,
411 &m_pCurMsg->bp_chaddr,
412 m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],
413 m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],
414 m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3],
415 m_pCurMsg->bp_xid);
416 }
417 }
418}
419
420
421/**
422 * Gets the name of given DHCP message type.
423 *
424 * @returns Readonly name.
425 * @param uMsgType The message number.
426 */
427/* static */ const char *VBoxNetDhcp::debugDhcpName(uint8_t uMsgType)
428{
429 switch (uMsgType)
430 {
431 case 0: return "MT_00";
432 case RTNET_DHCP_MT_DISCOVER: return "DISCOVER";
433 case RTNET_DHCP_MT_OFFER: return "OFFER";
434 case RTNET_DHCP_MT_REQUEST: return "REQUEST";
435 case RTNET_DHCP_MT_DECLINE: return "DECLINE";
436 case RTNET_DHCP_MT_ACK: return "ACK";
437 case RTNET_DHCP_MT_NAC: return "NAC";
438 case RTNET_DHCP_MT_RELEASE: return "RELEASE";
439 case RTNET_DHCP_MT_INFORM: return "INFORM";
440 case 9: return "MT_09";
441 case 10: return "MT_0a";
442 case 11: return "MT_0b";
443 case 12: return "MT_0c";
444 case 13: return "MT_0d";
445 case 14: return "MT_0e";
446 case 15: return "MT_0f";
447 case 16: return "MT_10";
448 case 17: return "MT_11";
449 case 18: return "MT_12";
450 case 19: return "MT_13";
451 case UINT8_MAX: return "MT_ff";
452 default: return "UNKNOWN";
453 }
454}
455
456
457int VBoxNetDhcp::initNoMain()
458{
459 CmdParameterIterator it;
460
461 RTNETADDRIPV4 address = getIpv4Address();
462 RTNETADDRIPV4 netmask = getIpv4Netmask();
463 RTNETADDRIPV4 networkId;
464 networkId.u = address.u & netmask.u;
465
466 RTNETADDRIPV4 UpperAddress;
467 RTNETADDRIPV4 LowerAddress = networkId;
468 UpperAddress.u = RT_H2N_U32(RT_N2H_U32(LowerAddress.u) | RT_N2H_U32(netmask.u));
469
470 for (it = CmdParameterll.begin(); it != CmdParameterll.end(); ++it)
471 {
472 switch(it->Key)
473 {
474 case 'l':
475 RTNetStrToIPv4Addr(it->strValue.c_str(), &LowerAddress);
476 break;
477
478 case 'u':
479 RTNetStrToIPv4Addr(it->strValue.c_str(), &UpperAddress);
480 break;
481 case 'b':
482 break;
483
484 }
485 }
486
487 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
488 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
489 confManager->addNetwork(unconst(g_RootConfig),
490 networkId,
491 netmask,
492 LowerAddress,
493 UpperAddress);
494
495 return VINF_SUCCESS;
496}
497
498
499int VBoxNetDhcp::initWithMain()
500{
501 /* ok, here we should initiate instance of dhcp server
502 * and listener for Dhcp configuration events
503 */
504 AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
505 std::string networkName = getNetworkName();
506
507 int rc = findDhcpServer(virtualbox, networkName, m_DhcpServer);
508 AssertRCReturn(rc, rc);
509
510 rc = findNatNetwork(virtualbox, networkName, m_NATNetwork);
511 AssertRCReturn(rc, rc);
512
513 BOOL fNeedDhcpServer = isDhcpRequired(m_NATNetwork);
514 if (!fNeedDhcpServer)
515 return VERR_CANCELLED;
516
517 RTNETADDRIPV4 gateway;
518 com::Bstr strGateway;
519 HRESULT hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
520 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
521 RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);
522
523 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
524 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
525 confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);
526
527 rc = fetchAndUpdateDnsInfo();
528 AssertMsgRCReturn(rc, ("Wasn't able to fetch Dns info"), rc);
529
530 {
531 ComEventTypeArray eventTypes;
532 eventTypes.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
533 eventTypes.push_back(VBoxEventType_OnNATNetworkStartStop);
534 rc = createNatListener(m_VBoxListener, virtualbox, this, eventTypes);
535 AssertRCReturn(rc, rc);
536 }
537
538 {
539 ComEventTypeArray eventTypes;
540 eventTypes.push_back(VBoxEventType_OnVBoxSVCAvailabilityChanged);
541 rc = createClientListener(m_VBoxClientListener, virtualboxClient, this, eventTypes);
542 AssertRCReturn(rc, rc);
543 }
544
545 RTNETADDRIPV4 LowerAddress;
546 rc = configGetBoundryAddress(m_DhcpServer, false, LowerAddress);
547 AssertMsgRCReturn(rc, ("can't get lower boundrary adderss'"),rc);
548
549 RTNETADDRIPV4 UpperAddress;
550 rc = configGetBoundryAddress(m_DhcpServer, true, UpperAddress);
551 AssertMsgRCReturn(rc, ("can't get upper boundrary adderss'"),rc);
552
553 RTNETADDRIPV4 address = getIpv4Address();
554 RTNETADDRIPV4 netmask = getIpv4Netmask();
555 RTNETADDRIPV4 networkId = networkid(address, netmask);
556 std::string name = std::string("default");
557
558 confManager->addNetwork(unconst(g_RootConfig),
559 networkId,
560 netmask,
561 LowerAddress,
562 UpperAddress);
563
564 com::Bstr bstr;
565 hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
566 com::Utf8StrFmt strXmlLeaseFile("%ls%c%s.leases",
567 bstr.raw(), RTPATH_DELIMITER, networkName.c_str());
568 confManager->loadFromFile(strXmlLeaseFile);
569
570 return VINF_SUCCESS;
571}
572
573
574int VBoxNetDhcp::fetchAndUpdateDnsInfo()
575{
576 ComHostPtr host;
577 if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))
578 {
579 AddressToOffsetMapping mapIp4Addr2Off;
580 int rc = localMappings(m_NATNetwork, mapIp4Addr2Off);
581 /* XXX: here could be several cases: 1. COM error, 2. not found (empty) 3. ? */
582 AssertMsgRCReturn(rc, ("Can't fetch local mappings"), rc);
583
584 RTNETADDRIPV4 address = getIpv4Address();
585 RTNETADDRIPV4 netmask = getIpv4Netmask();
586
587 AddressList nameservers;
588 rc = hostDnsServers(host, networkid(address, netmask), mapIp4Addr2Off, nameservers);
589 AssertMsgRCReturn(rc, ("Debug me!!!"), rc);
590 /* XXX: Search strings */
591
592 std::string domain;
593 rc = hostDnsDomain(host, domain);
594 AssertMsgRCReturn(rc, ("Debug me!!"), rc);
595
596 {
597 VBoxNetALock(this);
598 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
599 confManager->flushAddressList(RTNET_DHCP_OPT_DNS);
600
601 for (AddressList::iterator it = nameservers.begin(); it != nameservers.end(); ++it)
602 confManager->addToAddressList(RTNET_DHCP_OPT_DNS, *it);
603
604 confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, domain);
605 }
606 }
607
608 return VINF_SUCCESS;
609}
610
611HRESULT VBoxNetDhcp::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
612{
613 switch(aEventType)
614 {
615 case VBoxEventType_OnHostNameResolutionConfigurationChange:
616 fetchAndUpdateDnsInfo();
617 break;
618
619 case VBoxEventType_OnNATNetworkStartStop:
620 {
621 ComPtr <INATNetworkStartStopEvent> pStartStopEvent = pEvent;
622
623 com::Bstr networkName;
624 HRESULT hrc = pStartStopEvent->COMGETTER(NetworkName)(networkName.asOutParam());
625 AssertComRCReturn(hrc, hrc);
626 if (networkName.compare(getNetworkName().c_str()))
627 break; /* change not for our network */
628
629 BOOL fStart = TRUE;
630 hrc = pStartStopEvent->COMGETTER(StartEvent)(&fStart);
631 AssertComRCReturn(hrc, hrc);
632 if (!fStart)
633 shutdown();
634 break;
635 }
636
637 case VBoxEventType_OnVBoxSVCAvailabilityChanged:
638 {
639 shutdown();
640 break;
641 }
642 }
643
644 return S_OK;
645}
646
647/**
648 * Entry point.
649 */
650extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv)
651{
652 /*
653 * Instantiate the DHCP server and hand it the options.
654 */
655
656 VBoxNetDhcp *pDhcp = new VBoxNetDhcp();
657 if (!pDhcp)
658 {
659 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxNetDhcp failed!\n");
660 return 1;
661 }
662 int rc = pDhcp->parseArgs(argc - 1, argv + 1);
663 if (rc)
664 return rc;
665
666 pDhcp->init();
667
668 /*
669 * Try connect the server to the network.
670 */
671 rc = pDhcp->tryGoOnline();
672 if (RT_FAILURE(rc))
673 {
674 delete pDhcp;
675 return 1;
676 }
677
678 /*
679 * Process requests.
680 */
681 g_pDhcp = pDhcp;
682 rc = pDhcp->run();
683 pDhcp->done();
684
685 g_pDhcp = NULL;
686 delete pDhcp;
687
688 return 0;
689}
690
691
692#ifndef VBOX_WITH_HARDENING
693
694int main(int argc, char **argv)
695{
696 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
697 if (RT_FAILURE(rc))
698 return RTMsgInitFailure(rc);
699
700 return TrustedMain(argc, argv);
701}
702
703# ifdef RT_OS_WINDOWS
704
705static LRESULT CALLBACK WindowProc(HWND hwnd,
706 UINT uMsg,
707 WPARAM wParam,
708 LPARAM lParam
709)
710{
711 if(uMsg == WM_DESTROY)
712 {
713 PostQuitMessage(0);
714 return 0;
715 }
716 return DefWindowProc (hwnd, uMsg, wParam, lParam);
717}
718
719static LPCWSTR g_WndClassName = L"VBoxNetDHCPClass";
720
721static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)
722{
723 HWND hwnd = 0;
724 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
725 bool bExit = false;
726
727 /* Register the Window Class. */
728 WNDCLASS wc;
729 wc.style = 0;
730 wc.lpfnWndProc = WindowProc;
731 wc.cbClsExtra = 0;
732 wc.cbWndExtra = sizeof(void *);
733 wc.hInstance = hInstance;
734 wc.hIcon = NULL;
735 wc.hCursor = NULL;
736 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
737 wc.lpszMenuName = NULL;
738 wc.lpszClassName = g_WndClassName;
739
740 ATOM atomWindowClass = RegisterClass(&wc);
741
742 if (atomWindowClass != 0)
743 {
744 /* Create the window. */
745 hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
746 g_WndClassName, g_WndClassName,
747 WS_POPUPWINDOW,
748 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
749
750 if (hwnd)
751 {
752 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,
753 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
754
755 MSG msg;
756 while (GetMessage(&msg, NULL, 0, 0))
757 {
758 TranslateMessage(&msg);
759 DispatchMessage(&msg);
760 }
761
762 DestroyWindow (hwnd);
763
764 bExit = true;
765 }
766
767 UnregisterClass (g_WndClassName, hInstance);
768 }
769
770 if(bExit)
771 {
772 /* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */
773 exit(0);
774 }
775
776 return 0;
777}
778
779
780/** (We don't want a console usually.) */
781int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
782{
783 NOREF(hInstance); NOREF(hPrevInstance); NOREF(lpCmdLine); NOREF(nCmdShow);
784
785 HANDLE hThread = CreateThread(
786 NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */
787 0, /*__in SIZE_T dwStackSize, */
788 MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/
789 NULL, /*__in_opt LPVOID lpParameter,*/
790 0, /*__in DWORD dwCreationFlags,*/
791 NULL /*__out_opt LPDWORD lpThreadId*/
792 );
793
794 if(hThread != NULL)
795 CloseHandle(hThread);
796
797 return main(__argc, __argv);
798}
799# endif /* RT_OS_WINDOWS */
800
801#endif /* !VBOX_WITH_HARDENING */
802
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette