VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/VBoxNetNAT.cpp@ 28138

Last change on this file since 28138 was 28025, checked in by vboxsync, 15 years ago

intnet, VBoxNet*, network device & drivers: GSO preps.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.0 KB
Line 
1/* $Id: VBoxNetNAT.cpp 28025 2010-04-07 06:37:43Z vboxsync $ */
2/** @file
3 * VBoxNetNAT - NAT Service for connecting to IntNet.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/** @page pg_net_nat VBoxNetNAT
23 *
24 * Write a few words...
25 *
26 */
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/net.h>
32#include <iprt/initterm.h>
33#include <iprt/alloca.h>
34#include <iprt/err.h>
35#include <iprt/time.h>
36#include <iprt/timer.h>
37#include <iprt/thread.h>
38#include <iprt/stream.h>
39#include <iprt/path.h>
40#include <iprt/param.h>
41#include <iprt/getopt.h>
42#include <iprt/string.h>
43#include <iprt/mem.h>
44#include <iprt/req.h>
45#include <iprt/file.h>
46#include <iprt/semaphore.h>
47#define LOG_GROUP LOG_GROUP_NAT_SERVICE
48#include <VBox/log.h>
49
50#include <VBox/sup.h>
51#include <VBox/intnet.h>
52#include <VBox/intnetinline.h>
53#include <VBox/vmm.h>
54#include <VBox/version.h>
55
56#include <vector>
57#include <string>
58
59#include "../NetLib/VBoxNetLib.h"
60#include "../NetLib/VBoxNetBaseService.h"
61#include <libslirp.h>
62
63#ifdef RT_OS_WINDOWS /* WinMain */
64# include <Windows.h>
65# include <stdlib.h>
66#else
67# include <errno.h>
68#endif
69
70
71
72/*******************************************************************************
73* Structures and Typedefs *
74*******************************************************************************/
75
76class VBoxNetNAT : public VBoxNetBaseService
77{
78public:
79 VBoxNetNAT();
80 virtual ~VBoxNetNAT();
81 void usage(void);
82 void run(void);
83 void init(void);
84
85public:
86 PNATState m_pNATState;
87 RTNETADDRIPV4 m_Ipv4Netmask;
88 bool m_fPassDomain;
89 RTTHREAD m_ThrNAT;
90 RTTHREAD m_ThrSndNAT;
91 RTTHREAD m_ThrUrgSndNAT;
92#ifdef RT_OS_WINDOWS
93 HANDLE m_hWakeupEvent;
94#else
95 RTFILE m_PipeWrite;
96 RTFILE m_PipeRead;
97#endif
98 /** Queue for NAT-thread-external events. */
99 /** event to wakeup the guest receive thread */
100 RTSEMEVENT m_EventSend;
101 /** event to wakeup the guest urgent receive thread */
102 RTSEMEVENT m_EventUrgSend;
103
104 PRTREQQUEUE m_pReqQueue;
105 PRTREQQUEUE m_pSendQueue;
106 PRTREQQUEUE m_pUrgSendQueue;
107 volatile uint32_t cUrgPkt;
108 volatile uint32_t cPkt;
109
110 PRTTIMER pTmrSlow;
111 PRTTIMER pTmrFast;
112 bool fIsRunning;
113};
114
115
116
117/*******************************************************************************
118* Global Variables *
119*******************************************************************************/
120/** Pointer to the NAT server. */
121class VBoxNetNAT *g_pNAT;
122static DECLCALLBACK(int) AsyncIoThread(RTTHREAD pThread, void *pvUser);
123static DECLCALLBACK(int) natSndThread(RTTHREAD pThread, void *pvUser);
124static DECLCALLBACK(int) natUrgSndThread(RTTHREAD pThread, void *pvUser);
125static void SendWorker(struct mbuf *m, size_t cb);
126static void IntNetSendWorker(bool urg, const void *pvFrame, size_t cbFrame, struct mbuf *m);
127static void natNotifyNATThread();
128
129void slirp_arm_fast_timer(void *pvUser)
130{
131 RTTimerStart(g_pNAT->pTmrFast, 2);
132}
133
134void slirp_arm_slow_timer(void *pvUser)
135{
136 RTTimerStart(g_pNAT->pTmrSlow, 500);
137}
138
139static DECLCALLBACK(void) natSlowTimer(PRTTIMER ppTimer, void *pvUser, uint64_t iTick)
140{
141 natNotifyNATThread();
142}
143
144static DECLCALLBACK(void) natFastTimer(PRTTIMER ppTimer, void *pvUser, uint64_t iTick)
145{
146 natNotifyNATThread();
147}
148
149static void natNotifyNATThread()
150{
151 int rc;
152#ifndef RT_OS_WINDOWS
153 /* kick select() */
154 rc = RTFileWrite(g_pNAT->m_PipeWrite, "", 1, NULL);
155#else
156 /* kick WSAWaitForMultipleEvents */
157 rc = WSASetEvent(g_pNAT->hWakeupEvent);
158#endif
159 AssertRC(rc);
160}
161
162VBoxNetNAT::VBoxNetNAT()
163{
164#if defined(RT_OS_WINDOWS)
165 /*@todo check if we can remove this*/
166 VBoxNetBaseService();
167#endif
168 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
169 m_TrunkName = "";
170 m_MacAddress.au8[0] = 0x08;
171 m_MacAddress.au8[1] = 0x00;
172 m_MacAddress.au8[2] = 0x27;
173 m_MacAddress.au8[3] = 0x40;
174 m_MacAddress.au8[4] = 0x41;
175 m_MacAddress.au8[5] = 0x42;
176 m_Ipv4Address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 1)));
177 m_Ipv4Netmask.u = 0xffff0000;
178 cPkt = 0;
179 cUrgPkt = 0;
180}
181
182VBoxNetNAT::~VBoxNetNAT() { }
183void VBoxNetNAT::init()
184{
185 int rc;
186
187 /*
188 * Initialize slirp.
189 */
190 rc = slirp_init(&m_pNATState, m_Ipv4Address.u, m_Ipv4Netmask.u, m_fPassDomain, false, this);
191 AssertReleaseRC(rc);
192
193 slirp_set_ethaddr_and_activate_port_forwarding(m_pNATState, &m_MacAddress.au8[0], INADDR_ANY);
194#ifndef RT_OS_WINDOWS
195 /*
196 * Create the control pipe.
197 */
198 int fds[2];
199 if (pipe(&fds[0]) != 0) /** @todo RTPipeCreate() or something... */
200 {
201 rc = RTErrConvertFromErrno(errno);
202 AssertReleaseRC(rc);
203 return;
204 }
205 m_PipeRead = fds[0];
206 m_PipeWrite = fds[1];
207#else
208 m_hWakeupEvent = CreateEvent(NULL, FALSE, FALSE, NULL); /* auto-reset event */
209 slirp_register_external_event(m_pNATState, m_hWakeupEvent, VBOX_WAKEUP_EVENT_INDEX);
210#endif
211 rc = RTReqCreateQueue(&m_pReqQueue);
212 AssertReleaseRC(rc);
213
214 rc = RTReqCreateQueue(&m_pSendQueue);
215 AssertReleaseRC(rc);
216
217 rc = RTReqCreateQueue(&m_pUrgSendQueue);
218 AssertReleaseRC(rc);
219
220 rc = RTThreadCreate(&m_ThrNAT, AsyncIoThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "NAT");
221 rc = RTThreadCreate(&m_ThrSndNAT, natSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "SndNAT");
222 rc = RTThreadCreate(&m_ThrUrgSndNAT, natUrgSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "UrgSndNAT");
223 rc = RTTimerCreate(&pTmrSlow, 0 /* one-shot */, natSlowTimer, this);
224 rc = RTTimerCreate(&pTmrFast, 0 /* one-shot */ , natFastTimer, this);
225 rc = RTSemEventCreate(&m_EventSend);
226 rc = RTSemEventCreate(&m_EventUrgSend);
227 AssertReleaseRC(rc);
228}
229
230/* Mandatory functions */
231void VBoxNetNAT::run()
232{
233
234 /*
235 * The loop.
236 */
237 fIsRunning = true;
238 PINTNETRINGBUF pRingBuf = &m_pIfBuf->Recv;
239 //RTThreadSetType(RTThreadSelf(), RTTHREADTYPE_IO);
240 for (;;)
241 {
242 /*
243 * Wait for a packet to become available.
244 */
245 INTNETIFWAITREQ WaitReq;
246 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
247 WaitReq.Hdr.cbReq = sizeof(WaitReq);
248 WaitReq.pSession = m_pSession;
249 WaitReq.hIf = m_hIf;
250 WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */ /** @todo fix interruptability in SrvIntNet! */
251#if 0
252 RTReqProcess(m_pSendQueue, 0);
253 RTReqProcess(m_pUrgSendQueue, 0);
254#endif
255 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
256 if (RT_FAILURE(rc))
257 {
258 if (rc == VERR_TIMEOUT)
259 continue;
260 LogRel(("VBoxNetNAT: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc));
261 return;
262 }
263
264 /*
265 * Process the receive buffer.
266 */
267 PCINTNETHDR pHdr;
268 while ((pHdr = INTNETRingGetNextFrameToRead(pRingBuf)) != NULL)
269 {
270 uint16_t const u16Type = pHdr->u16Type;
271 if (RT_LIKELY( u16Type == INTNETHDR_TYPE_FRAME
272 || u16Type == INTNETHDR_TYPE_GSO))
273 {
274 size_t cbFrame = pHdr->cbFrame;
275 size_t cbIgnored;
276 void *pvSlirpFrame;
277 struct mbuf *m;
278 if (u16Type == INTNETHDR_TYPE_FRAME)
279 {
280 m = slirp_ext_m_get(g_pNAT->m_pNATState, cbFrame, &pvSlirpFrame, &cbIgnored);
281 if (!m)
282 {
283 LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame));
284 break;
285 }
286 memcpy(pvSlirpFrame, INTNETHdrGetFramePtr(pHdr, m_pIfBuf), cbFrame);
287 INTNETRingSkipFrame(&m_pIfBuf->Recv);
288
289 /* don't wait, we may have to wakeup the NAT thread first */
290 rc = RTReqCallEx(m_pReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
291 (PFNRT)SendWorker, 2, m, cbFrame);
292 AssertReleaseRC(rc);
293 }
294 else
295 {
296 /** @todo pass these unmodified. */
297 PCPDMNETWORKGSO pGso = INTNETHdrGetGsoContext(pHdr, m_pIfBuf);
298 if (!PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(*pGso)))
299 {
300 INTNETRingSkipFrame(&m_pIfBuf->Recv);
301 STAM_REL_COUNTER_INC(&m_pIfBuf->cStatBadFrames);
302 continue;
303 }
304
305 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame - sizeof(*pGso));
306 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
307 {
308 uint32_t cbSegFrame;
309 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)(pGso + 1), cbFrame, abHdrScratch,
310 &cbSegFrame);
311 m = slirp_ext_m_get(g_pNAT->m_pNATState, cbFrame, &pvSlirpFrame, &cbIgnored);
312 if (!m)
313 {
314 LogRel(("NAT: Can't allocate send buffer cbSegFrame=%u seg=%u/%u\n", cbSegFrame, iSeg, cSegs));
315 break;
316 }
317 memcpy(pvSlirpFrame, pvSegFrame, cbFrame);
318
319 rc = RTReqCallEx(m_pReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
320 (PFNRT)SendWorker, 2, m, cbSubFrame);
321 AssertReleaseRC(rc);
322 }
323 INTNETRingSkipFrame(&m_pIfBuf->Recv);
324 }
325
326#ifndef RT_OS_WINDOWS
327 /* kick select() */
328 rc = RTFileWrite(m_PipeWrite, "", 1, NULL);
329 AssertRC(rc);
330#else
331 /* kick WSAWaitForMultipleEvents */
332 rc = WSASetEvent(m_hWakeupEvent);
333 AssertRelease(rc == TRUE);
334#endif
335 }
336 else if (u16Type == INTNETHDR_TYPE_PADDING)
337 INTNETRingSkipFrame(&m_pIfBuf->Recv);
338 else
339 {
340 INTNETRingSkipFrame(&m_pIfBuf->Recv);
341 STAM_REL_COUNTER_INC(&m_pIfBuf->cStatBadFrames);
342 }
343 }
344
345 }
346 fIsRunning = false;
347}
348
349void VBoxNetNAT::usage()
350{
351}
352
353/**
354 * Entry point.
355 */
356extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
357{
358 Log2(("NAT: main\n"));
359 g_pNAT = new VBoxNetNAT();
360 Log2(("NAT: parsing command line\n"));
361 g_pNAT->parseArgs(argc - 1, argv + 1);
362 Log2(("NAT: initialization\n"));
363 g_pNAT->init();
364 Log2(("NAT: try go online\n"));
365 g_pNAT->tryGoOnline();
366 Log2(("NAT: main loop\n"));
367 g_pNAT->run();
368 delete g_pNAT;
369 return 0;
370}
371
372/** slirp's hooks */
373extern "C" int slirp_can_output(void * pvUser)
374{
375 return 1;
376}
377
378extern "C" void slirp_urg_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
379{
380 int rc = RTReqCallEx(g_pNAT->m_pUrgSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
381 (PFNRT)IntNetSendWorker, 4, (uintptr_t)1, (uintptr_t)pu8Buf, (uintptr_t)cb, (uintptr_t)m);
382 ASMAtomicIncU32(&g_pNAT->cUrgPkt);
383 RTSemEventSignal(g_pNAT->m_EventUrgSend);
384 AssertReleaseRC(rc);
385}
386extern "C" void slirp_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
387{
388 AssertRelease(g_pNAT == pvUser);
389 int rc = RTReqCallEx(g_pNAT->m_pSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
390 (PFNRT)IntNetSendWorker, 4, (uintptr_t)0, (uintptr_t)pu8Buf, (uintptr_t)cb, (uintptr_t)m);
391 ASMAtomicIncU32(&g_pNAT->cPkt);
392 RTSemEventSignal(g_pNAT->m_EventSend);
393 AssertReleaseRC(rc);
394}
395
396/**
397 * Worker function for drvNATSend().
398 * @thread "NAT" thread.
399 */
400static void SendWorker(struct mbuf *m, size_t cb)
401{
402 slirp_input(g_pNAT->m_pNATState, m, cb);
403}
404
405static void IntNetSendWorker(bool urg, const void *pvFrame, size_t cbFrame, struct mbuf *m)
406{
407 Log2(("VBoxNetNAT: going to send some bytes ... \n"));
408 VBoxNetNAT *pThis = g_pNAT;
409 INTNETIFSENDREQ SendReq;
410 int rc;
411
412 if (!urg)
413 {
414 while (ASMAtomicReadU32(&g_pNAT->cUrgPkt) != 0
415 || ASMAtomicReadU32(&g_pNAT->cPkt) == 0)
416 rc = RTSemEventWait(g_pNAT->m_EventSend, RT_INDEFINITE_WAIT);
417 }
418 else
419 {
420 while (ASMAtomicReadU32(&g_pNAT->cUrgPkt) == 0)
421 rc = RTSemEventWait(g_pNAT->m_EventUrgSend, RT_INDEFINITE_WAIT);
422 }
423 rc = INTNETRingWriteFrame(&pThis->m_pIfBuf->Send, pvFrame, cbFrame);
424 if (RT_FAILURE(rc))
425 {
426 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
427 SendReq.Hdr.cbReq = sizeof(SendReq);
428 SendReq.pSession = pThis->m_pSession;
429 SendReq.hIf = pThis->m_hIf;
430 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
431
432 rc = INTNETRingWriteFrame(&pThis->m_pIfBuf->Send, pvFrame, cbFrame);
433
434 }
435 if (RT_SUCCESS(rc))
436 {
437 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
438 SendReq.Hdr.cbReq = sizeof(SendReq);
439 SendReq.pSession = pThis->m_pSession;
440 SendReq.hIf = pThis->m_hIf;
441 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
442 }
443 if (RT_FAILURE(rc))
444 Log2(("VBoxNetNAT: Failed to send packet; rc=%Rrc\n", rc));
445
446 if (!urg)
447 {
448 ASMAtomicDecU32(&g_pNAT->cPkt);
449 }
450 else {
451 if (ASMAtomicDecU32(&g_pNAT->cUrgPkt) == 0)
452 RTSemEventSignal(g_pNAT->m_EventSend);
453 }
454 natNotifyNATThread();
455 slirp_ext_m_free(pThis->m_pNATState, m);
456#ifdef VBOX_WITH_SLIRP_BSD_MBUF
457 RTMemFree((void *)pvFrame);
458#endif
459}
460
461static DECLCALLBACK(int) AsyncIoThread(RTTHREAD pThread, void *pvUser)
462{
463 VBoxNetNAT *pThis = (VBoxNetNAT *)pvUser;
464 int nFDs = -1;
465 unsigned int ms;
466#ifdef RT_OS_WINDOWS
467 DWORD event;
468 HANDLE *phEvents;
469 unsigned int cBreak = 0;
470#else /* RT_OS_WINDOWS */
471 struct pollfd *polls = NULL;
472 unsigned int cPollNegRet = 0;
473#endif /* !RT_OS_WINDOWS */
474
475 LogFlow(("drvNATAsyncIoThread: pThis=%p\n", pThis));
476
477
478#ifdef RT_OS_WINDOWS
479 phEvents = slirp_get_events(pThis->m_pNATState);
480#endif /* RT_OS_WINDOWS */
481
482 /*
483 * Polling loop.
484 */
485 for(;;)
486 {
487 nFDs = -1;
488
489 /*
490 * To prevent concurent execution of sending/receving threads
491 */
492#ifndef RT_OS_WINDOWS
493 nFDs = slirp_get_nsock(pThis->m_pNATState);
494 polls = NULL;
495 /* allocation for all sockets + Management pipe */
496 polls = (struct pollfd *)RTMemAlloc((1 + nFDs) * sizeof(struct pollfd) + sizeof(uint32_t));
497 if (polls == NULL)
498 return VERR_NO_MEMORY;
499
500 /* don't pass the managemant pipe */
501 slirp_select_fill(pThis->m_pNATState, &nFDs, &polls[1]);
502 ms = slirp_get_timeout_ms(pThis->m_pNATState);
503
504 polls[0].fd = pThis->m_PipeRead;
505 /* POLLRDBAND usually doesn't used on Linux but seems used on Solaris */
506 polls[0].events = POLLRDNORM|POLLPRI|POLLRDBAND;
507 polls[0].revents = 0;
508
509 int cChangedFDs = poll(polls, nFDs + 1, -1);
510 if (cChangedFDs < 0)
511 {
512 if (errno == EINTR)
513 {
514 Log2(("NAT: signal was caught while sleep on poll\n"));
515 /* No error, just process all outstanding requests but don't wait */
516 cChangedFDs = 0;
517 }
518 else if (cPollNegRet++ > 128)
519 {
520 LogRel(("NAT:Poll returns (%s) suppressed %d\n", strerror(errno), cPollNegRet));
521 cPollNegRet = 0;
522 }
523 }
524
525 if (cChangedFDs >= 0)
526 {
527 slirp_select_poll(pThis->m_pNATState, &polls[1], nFDs);
528 if (polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND))
529 {
530 /* drain the pipe */
531 char ch[1];
532 size_t cbRead;
533 int counter = 0;
534 /*
535 * drvNATSend decoupled so we don't know how many times
536 * device's thread sends before we've entered multiplex,
537 * so to avoid false alarm drain pipe here to the very end
538 *
539 * @todo: Probably we should counter drvNATSend to count how
540 * deep pipe has been filed before drain.
541 *
542 * XXX:Make it reading exactly we need to drain the pipe.
543 */
544 RTFileRead(pThis->m_PipeRead, &ch, 1, &cbRead);
545 }
546 }
547 /* process _all_ outstanding requests but don't wait */
548 RTReqProcess(pThis->m_pReqQueue, 0);
549 RTMemFree(polls);
550#else /* RT_OS_WINDOWS */
551 slirp_select_fill(pThis->m_pNATState, &nFDs);
552 event = WSAWaitForMultipleEvents(nFDs, phEvents, FALSE, WSA_INFINITE, FALSE);
553 if ( (event < WSA_WAIT_EVENT_0 || event > WSA_WAIT_EVENT_0 + nFDs - 1)
554 && event != WSA_WAIT_TIMEOUT)
555 {
556 int error = WSAGetLastError();
557 LogRel(("NAT: WSAWaitForMultipleEvents returned %d (error %d)\n", event, error));
558 RTAssertReleasePanic();
559 }
560
561 if (event == WSA_WAIT_TIMEOUT)
562 {
563 /* only check for slow/fast timers */
564 slirp_select_poll(pThis->m_pNATState, /* fTimeout=*/true, /*fIcmp=*/false);
565 continue;
566 }
567
568 /* poll the sockets in any case */
569 slirp_select_poll(pThis->m_pNATState, /* fTimeout=*/false, /* fIcmp=*/(event == WSA_WAIT_EVENT_0));
570 /* process _all_ outstanding requests but don't wait */
571 RTReqProcess(pThis->m_pReqQueue, 0);
572#endif /* RT_OS_WINDOWS */
573 }
574
575 return VINF_SUCCESS;
576}
577
578static DECLCALLBACK(int) natSndThread(RTTHREAD pThread, void *pvUser)
579{
580 while (g_pNAT->fIsRunning)
581 RTReqProcess(g_pNAT->m_pSendQueue, 0);
582 return VINF_SUCCESS;
583}
584static DECLCALLBACK(int) natUrgSndThread(RTTHREAD pThread, void *pvUser)
585{
586 while (g_pNAT->fIsRunning)
587 RTReqProcess(g_pNAT->m_pUrgSendQueue, 0);
588 return VINF_SUCCESS;
589}
590
591#ifndef VBOX_WITH_HARDENING
592
593int main(int argc, char **argv, char **envp)
594{
595 int rc = RTR3InitAndSUPLib();
596 if (RT_FAILURE(rc))
597 {
598 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: RTR3InitAndSupLib failed, rc=%Rrc\n", rc);
599 return 1;
600 }
601
602 return TrustedMain(argc, argv, envp);
603}
604
605# if defined(RT_OS_WINDOWS)
606
607static LRESULT CALLBACK WindowProc(HWND hwnd,
608 UINT uMsg,
609 WPARAM wParam,
610 LPARAM lParam
611)
612{
613 if(uMsg == WM_DESTROY)
614 {
615 PostQuitMessage(0);
616 return 0;
617 }
618 return DefWindowProc (hwnd, uMsg, wParam, lParam);
619}
620
621static LPCSTR g_WndClassName = "VBoxNetNatClass";
622
623static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)
624{
625 HWND hwnd = 0;
626 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
627 bool bExit = false;
628
629 /* Register the Window Class. */
630 WNDCLASS wc;
631 wc.style = 0;
632 wc.lpfnWndProc = WindowProc;
633 wc.cbClsExtra = 0;
634 wc.cbWndExtra = sizeof(void *);
635 wc.hInstance = hInstance;
636 wc.hIcon = NULL;
637 wc.hCursor = NULL;
638 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
639 wc.lpszMenuName = NULL;
640 wc.lpszClassName = g_WndClassName;
641
642 ATOM atomWindowClass = RegisterClass(&wc);
643
644 if (atomWindowClass != 0)
645 {
646 /* Create the window. */
647 hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
648 g_WndClassName, g_WndClassName,
649 WS_POPUPWINDOW,
650 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
651
652 if (hwnd)
653 {
654 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,
655 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
656
657 MSG msg;
658 while (GetMessage(&msg, NULL, 0, 0))
659 {
660 TranslateMessage(&msg);
661 DispatchMessage(&msg);
662 }
663
664 DestroyWindow (hwnd);
665
666 bExit = true;
667 }
668
669 UnregisterClass (g_WndClassName, hInstance);
670 }
671
672 if(bExit)
673 {
674 /* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */
675 exit(0);
676 }
677
678 return 0;
679}
680
681
682
683/** (We don't want a console usually.) */
684int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
685{
686#if 0
687 NOREF(hInstance); NOREF(hPrevInstance); NOREF(lpCmdLine); NOREF(nCmdShow);
688
689 HANDLE hThread = CreateThread(
690 NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */
691 0, /*__in SIZE_T dwStackSize, */
692 MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/
693 NULL, /*__in_opt LPVOID lpParameter,*/
694 0, /*__in DWORD dwCreationFlags,*/
695 NULL /*__out_opt LPDWORD lpThreadId*/
696 );
697
698 if(hThread != NULL)
699 CloseHandle(hThread);
700
701#endif
702 return main(__argc, __argv, environ);
703}
704# endif /* RT_OS_WINDOWS */
705
706#endif /* !VBOX_WITH_HARDENING */
707
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