VirtualBox

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

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

NetworkServices: warnings

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

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