VirtualBox

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

Last change on this file since 52560 was 50213, checked in by vboxsync, 11 years ago

spaces

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.6 KB
Line 
1/* $Id: VBoxNetBaseService.cpp 50213 2014-01-24 08:23:12Z 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.virtualbox.org. 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 = virtualbox.createLocalObject(CLSID_VirtualBox);
211 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
212 }
213
214 return VINF_SUCCESS;
215}
216
217
218bool VBoxNetBaseService::isMainNeeded() const
219{
220 return m->m_fNeedMain;
221}
222
223
224int VBoxNetBaseService::run()
225{
226 /**
227 * If child class need Main we start receving thread which calls doReceiveLoop and enter to event polling loop
228 * and for the rest clients we do receiving on the current (main) thread.
229 */
230 if (isMainNeeded())
231 return startReceiveThreadAndEnterEventLoop();
232 else
233 {
234 doReceiveLoop();
235 return VINF_SUCCESS;
236 }
237}
238
239/**
240 * Parse the arguments.
241 *
242 * @returns 0 on success, fully bitched exit code on failure.
243 *
244 * @param argc Argument count.
245 * @param argv Argument vector.
246 */
247int VBoxNetBaseService::parseArgs(int argc, char **argv)
248{
249
250 RTGETOPTSTATE State;
251 PRTGETOPTDEF paOptionArray = getOptionsPtr();
252 int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
253 AssertRCReturn(rc, 49);
254#if 0
255 /* default initialization */
256 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
257#endif
258 Log2(("BaseService: parseArgs enter\n"));
259
260 for (;;)
261 {
262 RTGETOPTUNION Val;
263 rc = RTGetOpt(&State, &Val);
264 if (!rc)
265 break;
266 switch (rc)
267 {
268 case 'N': // --name
269 m->m_Name = Val.psz;
270 break;
271
272 case 'n': // --network
273 m->m_Network = Val.psz;
274 break;
275
276 case 't': //--trunk-name
277 m->m_TrunkName = Val.psz;
278 break;
279
280 case 'T': //--trunk-type
281 if (!strcmp(Val.psz, "none"))
282 m->m_enmTrunkType = kIntNetTrunkType_None;
283 else if (!strcmp(Val.psz, "whatever"))
284 m->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
285 else if (!strcmp(Val.psz, "netflt"))
286 m->m_enmTrunkType = kIntNetTrunkType_NetFlt;
287 else if (!strcmp(Val.psz, "netadp"))
288 m->m_enmTrunkType = kIntNetTrunkType_NetAdp;
289 else if (!strcmp(Val.psz, "srvnat"))
290 m->m_enmTrunkType = kIntNetTrunkType_SrvNat;
291 else
292 {
293 RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
294 return 1;
295 }
296 break;
297
298 case 'a': // --mac-address
299 m->m_MacAddress = Val.MacAddr;
300 break;
301
302 case 'i': // --ip-address
303 m->m_Ipv4Address = Val.IPv4Addr;
304 break;
305
306 case 'm': // --netmask
307 m->m_Ipv4Netmask = Val.IPv4Addr;
308 break;
309
310 case 'v': // --verbose
311 m->m_cVerbosity++;
312 break;
313
314 case 'V': // --version (missed)
315 RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision());
316 return 1;
317
318 case 'M': // --need-main
319 m->m_fNeedMain = true;
320 break;
321
322 case 'h': // --help (missed)
323 RTPrintf("%s Version %sr%u\n"
324 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
325 "All rights reserved.\n"
326 "\n"
327 "Usage: %s <options>\n"
328 "\n"
329 "Options:\n",
330 RTProcShortName(),
331 RTBldCfgVersion(),
332 RTBldCfgRevision(),
333 RTProcShortName());
334 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
335 RTPrintf(" -%c, %s\n", m->m_vecOptionDefs[i]->iShort, m->m_vecOptionDefs[i]->pszLong);
336 usage(); /* to print Service Specific usage */
337 return 1;
338
339 default:
340 int rc1 = parseOpt(rc, Val);
341 if (RT_FAILURE(rc1))
342 {
343 rc = RTGetOptPrintError(rc, &Val);
344 RTPrintf("Use --help for more information.\n");
345 return rc;
346 }
347 }
348 }
349
350 RTMemFree(paOptionArray);
351 return rc;
352}
353
354
355int VBoxNetBaseService::tryGoOnline(void)
356{
357 /*
358 * Open the session, load ring-0 and issue the request.
359 */
360 int rc = SUPR3Init(&m->m_pSession);
361 if (RT_FAILURE(rc))
362 {
363 m->m_pSession = NIL_RTR0PTR;
364 LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
365 return rc;
366 }
367
368 char szPath[RTPATH_MAX];
369 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
370 if (RT_FAILURE(rc))
371 {
372 LogRel(("VBoxNetBaseService: RTPathExecDir -> %Rrc\n", rc));
373 return rc;
374 }
375
376 rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
377 if (RT_FAILURE(rc))
378 {
379 LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
380 return rc;
381 }
382
383 /*
384 * Create the open request.
385 */
386 PINTNETBUF pBuf;
387 INTNETOPENREQ OpenReq;
388 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
389 OpenReq.Hdr.cbReq = sizeof(OpenReq);
390 OpenReq.pSession = m->m_pSession;
391 strncpy(OpenReq.szNetwork, m->m_Network.c_str(), sizeof(OpenReq.szNetwork));
392 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
393 strncpy(OpenReq.szTrunk, m->m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
394 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
395 OpenReq.enmTrunkType = m->m_enmTrunkType;
396 OpenReq.fFlags = 0; /** @todo check this */
397 OpenReq.cbSend = m->m_cbSendBuf;
398 OpenReq.cbRecv = m->m_cbRecvBuf;
399 OpenReq.hIf = INTNET_HANDLE_INVALID;
400
401 /*
402 * Issue the request.
403 */
404 Log2(("attempting to open/create network \"%s\"...\n", OpenReq.szNetwork));
405 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
406 if (RT_FAILURE(rc))
407 {
408 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
409 return rc;
410 }
411 m->m_hIf = OpenReq.hIf;
412 Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
413
414 /*
415 * Get the ring-3 address of the shared interface buffer.
416 */
417 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
418 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
419 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
420 GetBufferPtrsReq.pSession = m->m_pSession;
421 GetBufferPtrsReq.hIf = m->m_hIf;
422 GetBufferPtrsReq.pRing3Buf = NULL;
423 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
424 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
425 if (RT_FAILURE(rc))
426 {
427 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
428 return rc;
429 }
430 pBuf = GetBufferPtrsReq.pRing3Buf;
431 Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
432 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
433 m->m_pIfBuf = pBuf;
434
435 /*
436 * Activate the interface.
437 */
438 INTNETIFSETACTIVEREQ ActiveReq;
439 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
440 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
441 ActiveReq.pSession = m->m_pSession;
442 ActiveReq.hIf = m->m_hIf;
443 ActiveReq.fActive = true;
444 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
445 if (RT_SUCCESS(rc))
446 return 0;
447
448 /* bail out */
449 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
450
451 /* ignore this error */
452 return VINF_SUCCESS;
453}
454
455
456void VBoxNetBaseService::shutdown(void)
457{
458 syncEnter();
459 m->fShutdown = true;
460 syncLeave();
461}
462
463
464int VBoxNetBaseService::syncEnter()
465{
466 return RTCritSectEnter(&m->m_csThis);
467}
468
469
470int VBoxNetBaseService::syncLeave()
471{
472 return RTCritSectLeave(&m->m_csThis);
473}
474
475
476int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
477{
478 int rc = VINF_SUCCESS;
479 INTNETIFWAITREQ WaitReq;
480 LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
481 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
482 WaitReq.Hdr.cbReq = sizeof(WaitReq);
483 WaitReq.pSession = m->m_pSession;
484 WaitReq.hIf = m->m_hIf;
485 WaitReq.cMillies = cMillis;
486
487 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
488 LogFlowFuncLeaveRC(rc);
489 return rc;
490}
491
492/* S/G API */
493int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
494{
495 PINTNETHDR pHdr = NULL;
496 uint8_t *pu8Frame = NULL;
497
498 /* Allocate frame */
499 int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
500 AssertRCReturn(rc, rc);
501
502 /* Now we fill pvFrame with S/G above */
503 int offFrame = 0;
504 for (int idxSg = 0; idxSg < cSg; ++idxSg)
505 {
506 memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
507 offFrame+=pcSg[idxSg].cb;
508 }
509
510 /* Commit */
511 IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
512
513 LogFlowFuncLeaveRC(rc);
514 return rc;
515}
516
517/**
518 * forcible ask for send packet on the "wire"
519 */
520void VBoxNetBaseService::flushWire()
521{
522 int rc = VINF_SUCCESS;
523 INTNETIFSENDREQ SendReq;
524 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
525 SendReq.Hdr.cbReq = sizeof(SendReq);
526 SendReq.pSession = m->m_pSession;
527 SendReq.hIf = m->m_hIf;
528 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
529 AssertRCReturnVoid(rc);
530 LogFlowFuncLeave();
531
532}
533
534
535int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
536 void const *pvData, size_t cbData) const
537{
538 return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
539 m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
540 uDstPort, pvData, cbData);
541
542}
543
544
545const std::string VBoxNetBaseService::getName() const
546{
547 return m->m_Name;
548}
549
550
551void VBoxNetBaseService::setName(const std::string& aName)
552{
553 m->m_Name = aName;
554}
555
556
557const std::string VBoxNetBaseService::getNetwork() const
558{
559 return m->m_Network;
560}
561
562
563void VBoxNetBaseService::setNetwork(const std::string& aNetwork)
564{
565 m->m_Network = aNetwork;
566}
567
568
569const RTMAC VBoxNetBaseService::getMacAddress() const
570{
571 return m->m_MacAddress;
572}
573
574
575void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
576{
577 m->m_MacAddress = aMac;
578}
579
580
581const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
582{
583 return m->m_Ipv4Address;
584}
585
586
587void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
588{
589 m->m_Ipv4Address = aAddress;
590}
591
592
593const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
594{
595 return m->m_Ipv4Netmask;
596}
597
598
599void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
600{
601 m->m_Ipv4Netmask = aNetmask;
602}
603
604
605uint32_t VBoxNetBaseService::getSendBufSize() const
606{
607 return m->m_cbSendBuf;
608}
609
610
611void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
612{
613 m->m_cbSendBuf = cbBuf;
614}
615
616
617uint32_t VBoxNetBaseService::getRecvBufSize() const
618{
619 return m->m_cbRecvBuf;
620}
621
622
623void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
624{
625 m->m_cbRecvBuf = cbBuf;
626}
627
628
629int32_t VBoxNetBaseService::getVerbosityLevel() const
630{
631 return m->m_cVerbosity;
632}
633
634
635void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
636{
637 m->m_cVerbosity = aVerbosity;
638}
639
640
641void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
642{
643 m->m_vecOptionDefs.push_back(optDef);
644}
645
646
647void VBoxNetBaseService::doReceiveLoop()
648{
649 int rc;
650 /* Well we're ready */
651 PINTNETRINGBUF pRingBuf = &m->m_pIfBuf->Recv;
652
653 for (;;)
654 {
655 /*
656 * Wait for a packet to become available.
657 */
658 /* 2. waiting for request for */
659 rc = waitForIntNetEvent(2000);
660 if (RT_FAILURE(rc))
661 {
662 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
663 {
664 /* do we want interrupt anyone ??? */
665 continue;
666 }
667 LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
668 AssertRCReturnVoid(rc);
669 }
670
671 /*
672 * Process the receive buffer.
673 */
674 PCINTNETHDR pHdr;
675
676 while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
677 {
678 uint8_t const u8Type = pHdr->u8Type;
679 size_t cbFrame = pHdr->cbFrame;
680 switch (u8Type)
681 {
682
683 case INTNETHDR_TYPE_FRAME:
684 {
685 void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
686 rc = processFrame(pvFrame, cbFrame);
687 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
688 {
689 /* XXX: UDP + ARP for DHCP */
690 VBOXNETUDPHDRS Hdrs;
691 size_t cb;
692 void *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
693 VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST
694 | VBOXNETUDP_MATCH_CHECKSUM
695 | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
696 &Hdrs, &cb);
697 if (pv && cb)
698 processUDP(pv, cb);
699 else
700 VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
701 }
702 }
703 break;
704 case INTNETHDR_TYPE_GSO:
705 {
706 PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
707 rc = processGSO(pGso, cbFrame);
708 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
709 break;
710 }
711 break;
712 case INTNETHDR_TYPE_PADDING:
713 break;
714 default:
715 break;
716 }
717 IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
718
719 } /* loop */
720 }
721
722}
723
724
725int VBoxNetBaseService::startReceiveThreadAndEnterEventLoop()
726{
727 AssertMsgReturn(isMainNeeded(), ("It's expected that we need Main"), VERR_INTERNAL_ERROR);
728
729 /* start receiving thread */
730 int rc = RTThreadCreate(&m->m_hThrRecv, /* thread handle*/
731 &VBoxNetBaseService::Data::recvLoop, /* routine */
732 this, /* user data */
733 128 * _1K, /* stack size */
734 RTTHREADTYPE_IO, /* type */
735 0, /* flags, @todo: waitable ?*/
736 "RECV");
737 AssertRCReturn(rc,rc);
738
739 m->m_EventQ = com::NativeEventQueue::getMainEventQueue();
740 AssertPtrReturn(m->m_EventQ, VERR_INTERNAL_ERROR);
741
742 while(true)
743 {
744 m->m_EventQ->processEventQueue(0);
745
746 if (m->fShutdown)
747 break;
748
749 m->m_EventQ->processEventQueue(500);
750 }
751
752 return VINF_SUCCESS;
753}
754
755
756void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
757{
758 if (iMinLevel <= m->m_cVerbosity)
759 {
760 va_list va;
761 va_start(va, pszFmt);
762 debugPrintV(iMinLevel, fMsg, pszFmt, va);
763 va_end(va);
764 }
765}
766
767
768/**
769 * Print debug message depending on the m_cVerbosity level.
770 *
771 * @param iMinLevel The minimum m_cVerbosity level for this message.
772 * @param fMsg Whether to dump parts for the current service message.
773 * @param pszFmt The message format string.
774 * @param va Optional arguments.
775 */
776void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
777{
778 if (iMinLevel <= m->m_cVerbosity)
779 {
780 va_list vaCopy; /* This dude is *very* special, thus the copy. */
781 va_copy(vaCopy, va);
782 RTStrmPrintf(g_pStdErr, "%s: %s: %N\n",
783 RTProcShortName(),
784 iMinLevel >= 2 ? "debug" : "info",
785 pszFmt,
786 &vaCopy);
787 va_end(vaCopy);
788 }
789
790}
791
792
793PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
794{
795 PRTGETOPTDEF pOptArray = NULL;
796 pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
797 if (!pOptArray)
798 return NULL;
799 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
800 {
801 PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
802 memcpy(&pOptArray[i], m->m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
803 }
804 return pOptArray;
805}
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