VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp@ 54700

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

VBoxNetNAT, VBoxNetDHCP: use the VirtualBoxClient interface

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.3 KB
Line 
1/* $Id: VBoxNetBaseService.cpp 54700 2015-03-09 16:14:52Z vboxsync $ */
2/** @file
3 * VBoxNetDHCP - DHCP Service for connecting to IntNet.
4 */
5/** @todo r=bird: Cut&Past rules... Please fix DHCP refs! */
6
7/*
8 * Copyright (C) 2009-2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_NET_SERVICE
23
24#include <VBox/com/com.h>
25#include <VBox/com/listeners.h>
26#include <VBox/com/string.h>
27#include <VBox/com/Guid.h>
28#include <VBox/com/array.h>
29#include <VBox/com/ErrorInfo.h>
30#include <VBox/com/errorprint.h>
31#include <VBox/com/VirtualBox.h>
32#include <VBox/com/NativeEventQueue.h>
33
34#include <iprt/alloca.h>
35#include <iprt/buildconfig.h>
36#include <iprt/err.h>
37#include <iprt/net.h> /* must come before getopt.h. */
38#include <iprt/getopt.h>
39#include <iprt/initterm.h>
40#include <iprt/param.h>
41#include <iprt/path.h>
42#include <iprt/process.h>
43#include <iprt/stream.h>
44#include <iprt/string.h>
45#include <iprt/time.h>
46#include <iprt/thread.h>
47#include <iprt/mem.h>
48#include <iprt/message.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#include <vector>
57#include <string>
58
59#include <VBox/err.h>
60#include <VBox/log.h>
61
62#include "VBoxNetLib.h"
63#include "VBoxNetBaseService.h"
64
65#ifdef RT_OS_WINDOWS /* WinMain */
66# include <Windows.h>
67# include <stdlib.h>
68#endif
69
70
71/*******************************************************************************
72* Structures and Typedefs *
73*******************************************************************************/
74struct VBoxNetBaseService::Data
75{
76 Data(const std::string& aName, const std::string& aNetworkName):
77 m_Name(aName),
78 m_Network(aNetworkName),
79 m_enmTrunkType(kIntNetTrunkType_WhateverNone),
80 m_pSession(NIL_RTR0PTR),
81 m_cbSendBuf(128 * _1K),
82 m_cbRecvBuf(256 * _1K),
83 m_hIf(INTNET_HANDLE_INVALID),
84 m_pIfBuf(NULL),
85 m_cVerbosity(0),
86 m_fNeedMain(false),
87 m_EventQ(NULL),
88 m_hThrRecv(NIL_RTTHREAD),
89 fShutdown(false)
90 {
91 int rc = RTCritSectInit(&m_csThis);
92 AssertRC(rc);
93 };
94
95 std::string m_Name;
96 std::string m_Network;
97 std::string m_TrunkName;
98 INTNETTRUNKTYPE m_enmTrunkType;
99
100 RTMAC m_MacAddress;
101 RTNETADDRIPV4 m_Ipv4Address;
102 RTNETADDRIPV4 m_Ipv4Netmask;
103
104 PSUPDRVSESSION m_pSession;
105 uint32_t m_cbSendBuf;
106 uint32_t m_cbRecvBuf;
107 INTNETIFHANDLE m_hIf; /**< The handle to the network interface. */
108 PINTNETBUF m_pIfBuf; /**< Interface buffer. */
109
110 std::vector<PRTGETOPTDEF> m_vecOptionDefs;
111
112 int32_t m_cVerbosity;
113
114 /* cs for syncing */
115 RTCRITSECT m_csThis;
116
117 /* Controls whether service will connect SVC for runtime needs */
118 bool m_fNeedMain;
119 /* Event Queue */
120 com::NativeEventQueue *m_EventQ;
121
122 /** receiving thread, used only if main is used */
123 RTTHREAD m_hThrRecv;
124
125 bool fShutdown;
126 static int recvLoop(RTTHREAD, void *);
127};
128
129/*******************************************************************************
130* Global Variables *
131*******************************************************************************/
132/* Commonly used options for network configuration */
133static RTGETOPTDEF g_aGetOptDef[] =
134{
135 { "--name", 'N', RTGETOPT_REQ_STRING },
136 { "--network", 'n', RTGETOPT_REQ_STRING },
137 { "--trunk-name", 't', RTGETOPT_REQ_STRING },
138 { "--trunk-type", 'T', RTGETOPT_REQ_STRING },
139 { "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
140 { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
141 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
142 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
143 { "--need-main", 'M', RTGETOPT_REQ_BOOL },
144};
145
146
147int VBoxNetBaseService::Data::recvLoop(RTTHREAD, void *pvUser)
148{
149 VBoxNetBaseService *pThis = static_cast<VBoxNetBaseService *>(pvUser);
150
151 HRESULT hrc = com::Initialize();
152 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
153
154 pThis->doReceiveLoop();
155
156 return VINF_SUCCESS;
157}
158
159
160VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
161{
162 m = new VBoxNetBaseService::Data(aName, aNetworkName);
163
164 for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
165 m->m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
166}
167
168
169VBoxNetBaseService::~VBoxNetBaseService()
170{
171 /*
172 * Close the interface connection.
173 */
174 if (m != NULL)
175 {
176 shutdown();
177 if (m->m_hIf != INTNET_HANDLE_INVALID)
178 {
179 INTNETIFCLOSEREQ CloseReq;
180 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
181 CloseReq.Hdr.cbReq = sizeof(CloseReq);
182 CloseReq.pSession = m->m_pSession;
183 CloseReq.hIf = m->m_hIf;
184 m->m_hIf = INTNET_HANDLE_INVALID;
185 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
186 AssertRC(rc);
187 }
188
189 if (m->m_pSession != NIL_RTR0PTR)
190 {
191 SUPR3Term(false /*fForced*/);
192 m->m_pSession = NIL_RTR0PTR;
193 }
194
195 RTCritSectDelete(&m->m_csThis);
196
197 delete m;
198 m = NULL;
199 }
200}
201
202
203int VBoxNetBaseService::init()
204{
205 if (isMainNeeded())
206 {
207 HRESULT hrc = com::Initialize();
208 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
209
210 hrc = virtualboxClient.createInprocObject(CLSID_VirtualBoxClient);
211 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
212
213 hrc = virtualboxClient->COMGETTER(VirtualBox)(virtualbox.asOutParam());
214 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
215 }
216
217 return VINF_SUCCESS;
218}
219
220
221bool VBoxNetBaseService::isMainNeeded() const
222{
223 return m->m_fNeedMain;
224}
225
226
227int VBoxNetBaseService::run()
228{
229 /**
230 * If child class need Main we start receving thread which calls doReceiveLoop and enter to event polling loop
231 * and for the rest clients we do receiving on the current (main) thread.
232 */
233 if (isMainNeeded())
234 return startReceiveThreadAndEnterEventLoop();
235 else
236 {
237 doReceiveLoop();
238 return VINF_SUCCESS;
239 }
240}
241
242/**
243 * Parse the arguments.
244 *
245 * @returns 0 on success, fully bitched exit code on failure.
246 *
247 * @param argc Argument count.
248 * @param argv Argument vector.
249 */
250int VBoxNetBaseService::parseArgs(int argc, char **argv)
251{
252
253 RTGETOPTSTATE State;
254 PRTGETOPTDEF paOptionArray = getOptionsPtr();
255 int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
256 AssertRCReturn(rc, 49);
257#if 0
258 /* default initialization */
259 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
260#endif
261 Log2(("BaseService: parseArgs enter\n"));
262
263 for (;;)
264 {
265 RTGETOPTUNION Val;
266 rc = RTGetOpt(&State, &Val);
267 if (!rc)
268 break;
269 switch (rc)
270 {
271 case 'N': // --name
272 m->m_Name = Val.psz;
273 break;
274
275 case 'n': // --network
276 m->m_Network = Val.psz;
277 break;
278
279 case 't': //--trunk-name
280 m->m_TrunkName = Val.psz;
281 break;
282
283 case 'T': //--trunk-type
284 if (!strcmp(Val.psz, "none"))
285 m->m_enmTrunkType = kIntNetTrunkType_None;
286 else if (!strcmp(Val.psz, "whatever"))
287 m->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
288 else if (!strcmp(Val.psz, "netflt"))
289 m->m_enmTrunkType = kIntNetTrunkType_NetFlt;
290 else if (!strcmp(Val.psz, "netadp"))
291 m->m_enmTrunkType = kIntNetTrunkType_NetAdp;
292 else if (!strcmp(Val.psz, "srvnat"))
293 m->m_enmTrunkType = kIntNetTrunkType_SrvNat;
294 else
295 {
296 RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
297 return 1;
298 }
299 break;
300
301 case 'a': // --mac-address
302 m->m_MacAddress = Val.MacAddr;
303 break;
304
305 case 'i': // --ip-address
306 m->m_Ipv4Address = Val.IPv4Addr;
307 break;
308
309 case 'm': // --netmask
310 m->m_Ipv4Netmask = Val.IPv4Addr;
311 break;
312
313 case 'v': // --verbose
314 m->m_cVerbosity++;
315 break;
316
317 case 'V': // --version (missed)
318 RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision());
319 return 1;
320
321 case 'M': // --need-main
322 m->m_fNeedMain = true;
323 break;
324
325 case 'h': // --help (missed)
326 RTPrintf("%s Version %sr%u\n"
327 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
328 "All rights reserved.\n"
329 "\n"
330 "Usage: %s <options>\n"
331 "\n"
332 "Options:\n",
333 RTProcShortName(),
334 RTBldCfgVersion(),
335 RTBldCfgRevision(),
336 RTProcShortName());
337 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
338 RTPrintf(" -%c, %s\n", m->m_vecOptionDefs[i]->iShort, m->m_vecOptionDefs[i]->pszLong);
339 usage(); /* to print Service Specific usage */
340 return 1;
341
342 default:
343 int rc1 = parseOpt(rc, Val);
344 if (RT_FAILURE(rc1))
345 {
346 rc = RTGetOptPrintError(rc, &Val);
347 RTPrintf("Use --help for more information.\n");
348 return rc;
349 }
350 }
351 }
352
353 RTMemFree(paOptionArray);
354 return rc;
355}
356
357
358int VBoxNetBaseService::tryGoOnline(void)
359{
360 /*
361 * Open the session, load ring-0 and issue the request.
362 */
363 int rc = SUPR3Init(&m->m_pSession);
364 if (RT_FAILURE(rc))
365 {
366 m->m_pSession = NIL_RTR0PTR;
367 LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
368 return rc;
369 }
370
371 char szPath[RTPATH_MAX];
372 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
373 if (RT_FAILURE(rc))
374 {
375 LogRel(("VBoxNetBaseService: RTPathExecDir -> %Rrc\n", rc));
376 return rc;
377 }
378
379 rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
380 if (RT_FAILURE(rc))
381 {
382 LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
383 return rc;
384 }
385
386 /*
387 * Create the open request.
388 */
389 PINTNETBUF pBuf;
390 INTNETOPENREQ OpenReq;
391 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
392 OpenReq.Hdr.cbReq = sizeof(OpenReq);
393 OpenReq.pSession = m->m_pSession;
394 strncpy(OpenReq.szNetwork, m->m_Network.c_str(), sizeof(OpenReq.szNetwork));
395 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
396 strncpy(OpenReq.szTrunk, m->m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
397 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
398 OpenReq.enmTrunkType = m->m_enmTrunkType;
399 OpenReq.fFlags = 0; /** @todo check this */
400 OpenReq.cbSend = m->m_cbSendBuf;
401 OpenReq.cbRecv = m->m_cbRecvBuf;
402 OpenReq.hIf = INTNET_HANDLE_INVALID;
403
404 /*
405 * Issue the request.
406 */
407 Log2(("attempting to open/create network \"%s\"...\n", OpenReq.szNetwork));
408 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
409 if (RT_FAILURE(rc))
410 {
411 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
412 return rc;
413 }
414 m->m_hIf = OpenReq.hIf;
415 Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
416
417 /*
418 * Get the ring-3 address of the shared interface buffer.
419 */
420 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
421 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
422 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
423 GetBufferPtrsReq.pSession = m->m_pSession;
424 GetBufferPtrsReq.hIf = m->m_hIf;
425 GetBufferPtrsReq.pRing3Buf = NULL;
426 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
427 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
428 if (RT_FAILURE(rc))
429 {
430 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
431 return rc;
432 }
433 pBuf = GetBufferPtrsReq.pRing3Buf;
434 Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
435 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
436 m->m_pIfBuf = pBuf;
437
438 /*
439 * Activate the interface.
440 */
441 INTNETIFSETACTIVEREQ ActiveReq;
442 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
443 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
444 ActiveReq.pSession = m->m_pSession;
445 ActiveReq.hIf = m->m_hIf;
446 ActiveReq.fActive = true;
447 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
448 if (RT_SUCCESS(rc))
449 return 0;
450
451 /* bail out */
452 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
453
454 /* ignore this error */
455 return VINF_SUCCESS;
456}
457
458
459void VBoxNetBaseService::shutdown(void)
460{
461 syncEnter();
462 m->fShutdown = true;
463 if (m->m_hThrRecv != NIL_RTTHREAD)
464 {
465 int rc = m->m_EventQ->interruptEventQueueProcessing();
466 if (RT_SUCCESS(rc))
467 {
468 rc = RTThreadWait(m->m_hThrRecv, 60000, NULL);
469 if (RT_FAILURE(rc))
470 LogWarningFunc(("RTThreadWait(%RTthrd) -> %Rrc\n", m->m_hThrRecv, rc));
471 }
472 else
473 {
474 AssertMsgFailed(("interruptEventQueueProcessing() failed\n"));
475 RTThreadWait(m->m_hThrRecv , 0, NULL);
476 }
477 }
478 syncLeave();
479}
480
481
482int VBoxNetBaseService::syncEnter()
483{
484 return RTCritSectEnter(&m->m_csThis);
485}
486
487
488int VBoxNetBaseService::syncLeave()
489{
490 return RTCritSectLeave(&m->m_csThis);
491}
492
493
494int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
495{
496 int rc = VINF_SUCCESS;
497 INTNETIFWAITREQ WaitReq;
498 LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
499 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
500 WaitReq.Hdr.cbReq = sizeof(WaitReq);
501 WaitReq.pSession = m->m_pSession;
502 WaitReq.hIf = m->m_hIf;
503 WaitReq.cMillies = cMillis;
504
505 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
506 LogFlowFuncLeaveRC(rc);
507 return rc;
508}
509
510/* S/G API */
511int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
512{
513 PINTNETHDR pHdr = NULL;
514 uint8_t *pu8Frame = NULL;
515
516 /* Allocate frame */
517 int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
518 AssertRCReturn(rc, rc);
519
520 /* Now we fill pvFrame with S/G above */
521 int offFrame = 0;
522 for (int idxSg = 0; idxSg < cSg; ++idxSg)
523 {
524 memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
525 offFrame+=pcSg[idxSg].cb;
526 }
527
528 /* Commit */
529 IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
530
531 LogFlowFuncLeaveRC(rc);
532 return rc;
533}
534
535/**
536 * forcible ask for send packet on the "wire"
537 */
538void VBoxNetBaseService::flushWire()
539{
540 int rc = VINF_SUCCESS;
541 INTNETIFSENDREQ SendReq;
542 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
543 SendReq.Hdr.cbReq = sizeof(SendReq);
544 SendReq.pSession = m->m_pSession;
545 SendReq.hIf = m->m_hIf;
546 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
547 AssertRCReturnVoid(rc);
548 LogFlowFuncLeave();
549
550}
551
552
553int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
554 void const *pvData, size_t cbData) const
555{
556 return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
557 m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
558 uDstPort, pvData, cbData);
559
560}
561
562
563const std::string VBoxNetBaseService::getName() const
564{
565 return m->m_Name;
566}
567
568
569void VBoxNetBaseService::setName(const std::string& aName)
570{
571 m->m_Name = aName;
572}
573
574
575const std::string VBoxNetBaseService::getNetwork() const
576{
577 return m->m_Network;
578}
579
580
581void VBoxNetBaseService::setNetwork(const std::string& aNetwork)
582{
583 m->m_Network = aNetwork;
584}
585
586
587const RTMAC VBoxNetBaseService::getMacAddress() const
588{
589 return m->m_MacAddress;
590}
591
592
593void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
594{
595 m->m_MacAddress = aMac;
596}
597
598
599const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
600{
601 return m->m_Ipv4Address;
602}
603
604
605void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
606{
607 m->m_Ipv4Address = aAddress;
608}
609
610
611const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
612{
613 return m->m_Ipv4Netmask;
614}
615
616
617void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
618{
619 m->m_Ipv4Netmask = aNetmask;
620}
621
622
623uint32_t VBoxNetBaseService::getSendBufSize() const
624{
625 return m->m_cbSendBuf;
626}
627
628
629void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
630{
631 m->m_cbSendBuf = cbBuf;
632}
633
634
635uint32_t VBoxNetBaseService::getRecvBufSize() const
636{
637 return m->m_cbRecvBuf;
638}
639
640
641void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
642{
643 m->m_cbRecvBuf = cbBuf;
644}
645
646
647int32_t VBoxNetBaseService::getVerbosityLevel() const
648{
649 return m->m_cVerbosity;
650}
651
652
653void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
654{
655 m->m_cVerbosity = aVerbosity;
656}
657
658
659void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
660{
661 m->m_vecOptionDefs.push_back(optDef);
662}
663
664
665void VBoxNetBaseService::doReceiveLoop()
666{
667 int rc;
668 /* Well we're ready */
669 PINTNETRINGBUF pRingBuf = &m->m_pIfBuf->Recv;
670
671 for (;;)
672 {
673 /*
674 * Wait for a packet to become available.
675 */
676 /* 2. waiting for request for */
677 rc = waitForIntNetEvent(2000);
678 if (RT_FAILURE(rc))
679 {
680 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
681 {
682 /* do we want interrupt anyone ??? */
683 continue;
684 }
685 LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
686 AssertRCReturnVoid(rc);
687 }
688
689 /*
690 * Process the receive buffer.
691 */
692 PCINTNETHDR pHdr;
693
694 while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
695 {
696 uint8_t const u8Type = pHdr->u8Type;
697 size_t cbFrame = pHdr->cbFrame;
698 switch (u8Type)
699 {
700
701 case INTNETHDR_TYPE_FRAME:
702 {
703 void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
704 rc = processFrame(pvFrame, cbFrame);
705 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
706 {
707 /* XXX: UDP + ARP for DHCP */
708 VBOXNETUDPHDRS Hdrs;
709 size_t cb;
710 void *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
711 VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST
712 | VBOXNETUDP_MATCH_CHECKSUM
713 | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
714 &Hdrs, &cb);
715 if (pv && cb)
716 processUDP(pv, cb);
717 else
718 VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
719 }
720 }
721 break;
722 case INTNETHDR_TYPE_GSO:
723 {
724 PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
725 rc = processGSO(pGso, cbFrame);
726 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
727 break;
728 }
729 break;
730 case INTNETHDR_TYPE_PADDING:
731 break;
732 default:
733 break;
734 }
735 IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
736
737 } /* loop */
738 }
739
740}
741
742
743int VBoxNetBaseService::startReceiveThreadAndEnterEventLoop()
744{
745 AssertMsgReturn(isMainNeeded(), ("It's expected that we need Main"), VERR_INTERNAL_ERROR);
746
747 /* start receiving thread */
748 int rc = RTThreadCreate(&m->m_hThrRecv, /* thread handle*/
749 &VBoxNetBaseService::Data::recvLoop, /* routine */
750 this, /* user data */
751 128 * _1K, /* stack size */
752 RTTHREADTYPE_IO, /* type */
753 0, /* flags, @todo: waitable ?*/
754 "RECV");
755 AssertRCReturn(rc, rc);
756
757 m->m_EventQ = com::NativeEventQueue::getMainEventQueue();
758 AssertPtrReturn(m->m_EventQ, VERR_INTERNAL_ERROR);
759
760 while (!m->fShutdown)
761 {
762 rc = m->m_EventQ->processEventQueue(RT_INDEFINITE_WAIT);
763 if (rc == VERR_INTERRUPTED)
764 {
765 LogFlow(("Event queue processing ended with rc=%Rrc\n", rc));
766 break;
767 }
768 }
769
770 return VINF_SUCCESS;
771}
772
773
774void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
775{
776 if (iMinLevel <= m->m_cVerbosity)
777 {
778 va_list va;
779 va_start(va, pszFmt);
780 debugPrintV(iMinLevel, fMsg, pszFmt, va);
781 va_end(va);
782 }
783}
784
785
786/**
787 * Print debug message depending on the m_cVerbosity level.
788 *
789 * @param iMinLevel The minimum m_cVerbosity level for this message.
790 * @param fMsg Whether to dump parts for the current service message.
791 * @param pszFmt The message format string.
792 * @param va Optional arguments.
793 */
794void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
795{
796 if (iMinLevel <= m->m_cVerbosity)
797 {
798 va_list vaCopy; /* This dude is *very* special, thus the copy. */
799 va_copy(vaCopy, va);
800 RTStrmPrintf(g_pStdErr, "%s: %s: %N\n",
801 RTProcShortName(),
802 iMinLevel >= 2 ? "debug" : "info",
803 pszFmt,
804 &vaCopy);
805 va_end(vaCopy);
806 }
807
808}
809
810
811PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
812{
813 PRTGETOPTDEF pOptArray = NULL;
814 pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
815 if (!pOptArray)
816 return NULL;
817 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
818 {
819 PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
820 memcpy(&pOptArray[i], m->m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
821 }
822 return pOptArray;
823}
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