VirtualBox

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

Last change on this file since 54584 was 54504, checked in by vboxsync, 10 years ago

VBoxNetDHCP: Drag kicking and screaming VBoxNetDhcp::m_DhcpServer to
NetworkManager::processParameterReqList() so that we can interrorgate
it about DHCP options configured via API (though don't do it just yet).

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