VirtualBox

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

Last change on this file since 63267 was 63267, checked in by vboxsync, 8 years ago

NetworkServices: warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.5 KB
Line 
1/* $Id: VBoxNetBaseService.cpp 63267 2016-08-10 13:34:15Z vboxsync $ */
2/** @file
3 * VBoxNetBaseService - common services for VBoxNetDHCP and VBoxNetNAT.
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
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 <iprt/win/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& aServiceName, const std::string& aNetworkName):
77 m_ServiceName(aServiceName),
78 m_NetworkName(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_ServiceName;
96 std::string m_NetworkName;
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 DECLCALLBACK(int) recvLoop(RTTHREAD, void *);
127};
128
129
130/*********************************************************************************************************************************
131* Global Variables *
132*********************************************************************************************************************************/
133/* Commonly used options for network configuration */
134static RTGETOPTDEF g_aGetOptDef[] =
135{
136 { "--name", 'N', RTGETOPT_REQ_STRING },
137 { "--network", 'n', RTGETOPT_REQ_STRING },
138 { "--trunk-name", 't', RTGETOPT_REQ_STRING },
139 { "--trunk-type", 'T', RTGETOPT_REQ_STRING },
140 { "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
141 { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
142 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
143 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
144 { "--need-main", 'M', RTGETOPT_REQ_BOOL },
145};
146
147
148DECLCALLBACK(int) VBoxNetBaseService::Data::recvLoop(RTTHREAD, void *pvUser)
149{
150 VBoxNetBaseService *pThis = static_cast<VBoxNetBaseService *>(pvUser);
151
152 HRESULT hrc = com::Initialize();
153 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
154
155 pThis->doReceiveLoop();
156
157 return VINF_SUCCESS;
158}
159
160
161VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
162{
163 m = new VBoxNetBaseService::Data(aName, aNetworkName);
164
165 for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
166 m->m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
167}
168
169
170VBoxNetBaseService::~VBoxNetBaseService()
171{
172 /*
173 * Close the interface connection.
174 */
175 if (m)
176 {
177 shutdown();
178 if (m->m_hIf != INTNET_HANDLE_INVALID)
179 {
180 INTNETIFCLOSEREQ CloseReq;
181 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
182 CloseReq.Hdr.cbReq = sizeof(CloseReq);
183 CloseReq.pSession = m->m_pSession;
184 CloseReq.hIf = m->m_hIf;
185 m->m_hIf = INTNET_HANDLE_INVALID;
186 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
187 AssertRC(rc);
188 }
189
190 if (m->m_pSession != NIL_RTR0PTR)
191 {
192 SUPR3Term(false /*fForced*/);
193 m->m_pSession = NIL_RTR0PTR;
194 }
195
196 RTCritSectDelete(&m->m_csThis);
197
198 delete m;
199 m = NULL;
200 }
201}
202
203
204int VBoxNetBaseService::init()
205{
206 if (isMainNeeded())
207 {
208 HRESULT hrc = com::Initialize();
209 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
210
211 hrc = virtualboxClient.createInprocObject(CLSID_VirtualBoxClient);
212 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
213
214 hrc = virtualboxClient->COMGETTER(VirtualBox)(virtualbox.asOutParam());
215 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
216 }
217
218 return VINF_SUCCESS;
219}
220
221
222bool VBoxNetBaseService::isMainNeeded() const
223{
224 return m->m_fNeedMain;
225}
226
227
228int VBoxNetBaseService::run()
229{
230 /**
231 * If the child class needs Main we start the receving thread which calls
232 * doReceiveLoop and enter to event polling loop. For other clients we do
233 * receiving on the current (main) thread.
234 */
235 if (isMainNeeded())
236 return startReceiveThreadAndEnterEventLoop();
237
238 doReceiveLoop();
239 return VINF_SUCCESS;
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_ServiceName = Val.psz;
273 break;
274
275 case 'n': // --network
276 m->m_NetworkName = 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 {
344 int rc1 = parseOpt(rc, Val);
345 if (RT_FAILURE(rc1))
346 {
347 rc = RTGetOptPrintError(rc, &Val);
348 RTPrintf("Use --help for more information.\n");
349 return rc;
350 }
351 break;
352 }
353 }
354 }
355
356 RTMemFree(paOptionArray);
357 return rc;
358}
359
360
361int VBoxNetBaseService::tryGoOnline(void)
362{
363 /*
364 * Open the session, load ring-0 and issue the request.
365 */
366 int rc = SUPR3Init(&m->m_pSession);
367 if (RT_FAILURE(rc))
368 {
369 m->m_pSession = NIL_RTR0PTR;
370 LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
371 return rc;
372 }
373
374 char szPath[RTPATH_MAX];
375 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
376 if (RT_FAILURE(rc))
377 {
378 LogRel(("VBoxNetBaseService: RTPathExecDir -> %Rrc\n", rc));
379 return rc;
380 }
381
382 rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
383 if (RT_FAILURE(rc))
384 {
385 LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
386 return rc;
387 }
388
389 /*
390 * Create the open request.
391 */
392 PINTNETBUF pBuf;
393 INTNETOPENREQ OpenReq;
394 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
395 OpenReq.Hdr.cbReq = sizeof(OpenReq);
396 OpenReq.pSession = m->m_pSession;
397 RTStrCopy(OpenReq.szNetwork, sizeof(OpenReq.szNetwork), m->m_NetworkName.c_str());
398 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
399 RTStrCopy(OpenReq.szTrunk, sizeof(OpenReq.szTrunk), m->m_TrunkName.c_str());
400 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
401 OpenReq.enmTrunkType = m->m_enmTrunkType;
402 OpenReq.fFlags = 0; /** @todo check this */
403 OpenReq.cbSend = m->m_cbSendBuf;
404 OpenReq.cbRecv = m->m_cbRecvBuf;
405 OpenReq.hIf = INTNET_HANDLE_INVALID;
406
407 /*
408 * Issue the request.
409 */
410 Log2(("attempting to open/create network \"%s\"...\n", OpenReq.szNetwork));
411 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
412 if (RT_FAILURE(rc))
413 {
414 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
415 return rc;
416 }
417 m->m_hIf = OpenReq.hIf;
418 Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
419
420 /*
421 * Get the ring-3 address of the shared interface buffer.
422 */
423 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
424 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
425 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
426 GetBufferPtrsReq.pSession = m->m_pSession;
427 GetBufferPtrsReq.hIf = m->m_hIf;
428 GetBufferPtrsReq.pRing3Buf = NULL;
429 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
430 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
431 if (RT_FAILURE(rc))
432 {
433 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
434 return rc;
435 }
436 pBuf = GetBufferPtrsReq.pRing3Buf;
437 Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
438 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
439 m->m_pIfBuf = pBuf;
440
441 /*
442 * Activate the interface.
443 */
444 INTNETIFSETACTIVEREQ ActiveReq;
445 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
446 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
447 ActiveReq.pSession = m->m_pSession;
448 ActiveReq.hIf = m->m_hIf;
449 ActiveReq.fActive = true;
450 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
451 if (RT_SUCCESS(rc))
452 return 0;
453
454 /* bail out */
455 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
456
457 /* ignore this error */
458 return VINF_SUCCESS;
459}
460
461
462void VBoxNetBaseService::shutdown(void)
463{
464 syncEnter();
465 if (!m->fShutdown)
466 {
467 m->fShutdown = true;
468 if (m->m_hThrRecv != NIL_RTTHREAD)
469 {
470 int rc = abortWait();
471 AssertRC(rc == VINF_SUCCESS || rc == VERR_SEM_DESTROYED);
472 rc = m->m_EventQ->interruptEventQueueProcessing();
473 if (RT_SUCCESS(rc))
474 {
475 rc = RTThreadWait(m->m_hThrRecv, 60000, NULL);
476 if (RT_FAILURE(rc))
477 Log1WarningFunc(("RTThreadWait(%RTthrd) -> %Rrc\n", m->m_hThrRecv, rc));
478 }
479 else
480 {
481 AssertMsgFailed(("interruptEventQueueProcessing() failed\n"));
482 RTThreadWait(m->m_hThrRecv , 0, NULL);
483 }
484 }
485 }
486 syncLeave();
487}
488
489
490int VBoxNetBaseService::syncEnter()
491{
492 return RTCritSectEnter(&m->m_csThis);
493}
494
495
496int VBoxNetBaseService::syncLeave()
497{
498 return RTCritSectLeave(&m->m_csThis);
499}
500
501
502int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
503{
504 INTNETIFWAITREQ WaitReq;
505 LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
506 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
507 WaitReq.Hdr.cbReq = sizeof(WaitReq);
508 WaitReq.pSession = m->m_pSession;
509 WaitReq.hIf = m->m_hIf;
510 WaitReq.cMillies = cMillis;
511
512 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
513 LogFlowFuncLeaveRC(rc);
514 return rc;
515}
516
517
518int VBoxNetBaseService::abortWait()
519{
520 INTNETIFABORTWAITREQ AbortReq;
521 LogFlowFunc(("ENTER:\n"));
522 AbortReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
523 AbortReq.Hdr.cbReq = sizeof(AbortReq);
524 AbortReq.pSession = m->m_pSession;
525 AbortReq.hIf = m->m_hIf;
526 AbortReq.fNoMoreWaits = true;
527
528 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_ABORT_WAIT, 0, &AbortReq.Hdr);
529 LogFlowFuncLeaveRC(rc);
530 return rc;
531}
532
533
534/* S/G API */
535int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG paSegs, size_t cSegs, size_t cbFrame)
536{
537 /* Allocate frame */
538 PINTNETHDR pHdr = NULL;
539 uint8_t *pbFrame = NULL;
540 int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, (uint32_t)cbFrame, &pHdr, (void **)&pbFrame);
541 AssertRCReturn(rc, rc);
542
543 /* Now we fill pvFrame with S/G above */
544 size_t offFrame = 0;
545 for (size_t idxSeg = 0; idxSeg < cSegs; ++idxSeg)
546 {
547 memcpy(&pbFrame[offFrame], paSegs[idxSeg].pv, paSegs[idxSeg].cb);
548 offFrame += paSegs[idxSeg].cb;
549 }
550
551 /* Commit */
552 IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
553
554 LogFlowFuncLeaveRC(rc);
555 return rc;
556}
557
558/**
559 * forcible ask for send packet on the "wire"
560 */
561void VBoxNetBaseService::flushWire()
562{
563 INTNETIFSENDREQ SendReq;
564 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
565 SendReq.Hdr.cbReq = sizeof(SendReq);
566 SendReq.pSession = m->m_pSession;
567 SendReq.hIf = m->m_hIf;
568 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
569 AssertRCReturnVoid(rc);
570 LogFlowFuncLeave();
571}
572
573
574int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
575 void const *pvData, size_t cbData) const
576{
577 return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
578 m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
579 uDstPort, pvData, cbData);
580
581}
582
583
584const std::string VBoxNetBaseService::getServiceName() const
585{
586 return m->m_ServiceName;
587}
588
589
590void VBoxNetBaseService::setServiceName(const std::string& aName)
591{
592 m->m_ServiceName = aName;
593}
594
595
596const std::string VBoxNetBaseService::getNetworkName() const
597{
598 return m->m_NetworkName;
599}
600
601
602void VBoxNetBaseService::setNetworkName(const std::string& aName)
603{
604 m->m_NetworkName = aName;
605}
606
607
608const RTMAC VBoxNetBaseService::getMacAddress() const
609{
610 return m->m_MacAddress;
611}
612
613
614void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
615{
616 m->m_MacAddress = aMac;
617}
618
619
620const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
621{
622 return m->m_Ipv4Address;
623}
624
625
626void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
627{
628 m->m_Ipv4Address = aAddress;
629}
630
631
632const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
633{
634 return m->m_Ipv4Netmask;
635}
636
637
638void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
639{
640 m->m_Ipv4Netmask = aNetmask;
641}
642
643
644uint32_t VBoxNetBaseService::getSendBufSize() const
645{
646 return m->m_cbSendBuf;
647}
648
649
650void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
651{
652 m->m_cbSendBuf = cbBuf;
653}
654
655
656uint32_t VBoxNetBaseService::getRecvBufSize() const
657{
658 return m->m_cbRecvBuf;
659}
660
661
662void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
663{
664 m->m_cbRecvBuf = cbBuf;
665}
666
667
668int32_t VBoxNetBaseService::getVerbosityLevel() const
669{
670 return m->m_cVerbosity;
671}
672
673
674void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
675{
676 m->m_cVerbosity = aVerbosity;
677}
678
679
680void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
681{
682 m->m_vecOptionDefs.push_back(optDef);
683}
684
685
686void VBoxNetBaseService::doReceiveLoop()
687{
688 int rc;
689 /* Well we're ready */
690 PINTNETRINGBUF pRingBuf = &m->m_pIfBuf->Recv;
691
692 for (;;)
693 {
694 /*
695 * Wait for a packet to become available.
696 */
697 rc = waitForIntNetEvent(2000);
698 if (rc == VERR_SEM_DESTROYED)
699 break;
700
701 if (RT_FAILURE(rc))
702 {
703 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
704 {
705 /* do we want interrupt anyone ??? */
706 continue;
707 }
708 LogRel(("VBoxNetBaseService: waitForIntNetEvent returned %Rrc\n", rc));
709 AssertRCReturnVoid(rc);
710 }
711
712 /*
713 * Process the receive buffer.
714 */
715 PCINTNETHDR pHdr;
716 while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
717 {
718 uint8_t const u8Type = pHdr->u8Type;
719 size_t cbFrame = pHdr->cbFrame;
720 switch (u8Type)
721 {
722 case INTNETHDR_TYPE_FRAME:
723 {
724 void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
725 rc = processFrame(pvFrame, cbFrame);
726 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
727 {
728 /* XXX: UDP + ARP for DHCP */
729 VBOXNETUDPHDRS Hdrs;
730 size_t cb;
731 void *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
732 VBOXNETUDP_MATCH_UNICAST
733 | VBOXNETUDP_MATCH_BROADCAST
734 | VBOXNETUDP_MATCH_CHECKSUM
735 | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
736 &Hdrs, &cb);
737 if (pv && cb)
738 processUDP(pv, cb);
739 else
740 VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
741 }
742 break;
743 }
744 case INTNETHDR_TYPE_GSO:
745 {
746 PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
747 rc = processGSO(pGso, cbFrame);
748 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
749 break;
750 break;
751 }
752
753 case INTNETHDR_TYPE_PADDING:
754 break;
755
756 default:
757 break;
758 }
759 IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
760 } /* loop */
761 }
762}
763
764
765int VBoxNetBaseService::startReceiveThreadAndEnterEventLoop()
766{
767 AssertMsgReturn(isMainNeeded(), ("It's expected that we need Main"), VERR_INTERNAL_ERROR);
768
769 /* start receiving thread */
770 int rc = RTThreadCreate(&m->m_hThrRecv, /* thread handle*/
771 &VBoxNetBaseService::Data::recvLoop, /* routine */
772 this, /* user data */
773 128 * _1K, /* stack size */
774 RTTHREADTYPE_IO, /* type */
775 RTTHREADFLAGS_WAITABLE, /* flags */
776 "RECV");
777 AssertRCReturn(rc, rc);
778
779 m->m_EventQ = com::NativeEventQueue::getMainEventQueue();
780 AssertPtrReturn(m->m_EventQ, VERR_INTERNAL_ERROR);
781
782 while (!m->fShutdown)
783 {
784 rc = m->m_EventQ->processEventQueue(RT_INDEFINITE_WAIT);
785 if (rc == VERR_INTERRUPTED)
786 {
787 LogFlow(("Event queue processing ended with rc=%Rrc\n", rc));
788 break;
789 }
790 }
791
792 return VINF_SUCCESS;
793}
794
795
796void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
797{
798 if (iMinLevel <= m->m_cVerbosity)
799 {
800 va_list va;
801 va_start(va, pszFmt);
802 debugPrintV(iMinLevel, fMsg, pszFmt, va);
803 va_end(va);
804 }
805}
806
807
808/**
809 * Print debug message depending on the m_cVerbosity level.
810 *
811 * @param iMinLevel The minimum m_cVerbosity level for this message.
812 * @param fMsg Whether to dump parts for the current service message.
813 * @param pszFmt The message format string.
814 * @param va Optional arguments.
815 */
816void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
817{
818 RT_NOREF(fMsg);
819 if (iMinLevel <= m->m_cVerbosity)
820 {
821 va_list vaCopy; /* This dude is *very* special, thus the copy. */
822 va_copy(vaCopy, va);
823 RTStrmPrintf(g_pStdErr, "%s: %s: %N\n",
824 RTProcShortName(),
825 iMinLevel >= 2 ? "debug" : "info",
826 pszFmt,
827 &vaCopy);
828 va_end(vaCopy);
829 }
830}
831
832
833PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
834{
835 PRTGETOPTDEF pOptArray = NULL;
836 pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
837 if (!pOptArray)
838 return NULL;
839 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
840 {
841 PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
842 memcpy(&pOptArray[i], pOpt, sizeof(*pOpt));
843 }
844 return pOptArray;
845}
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