VirtualBox

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

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

iprt/log.h,SUPDrv: Replaced the 'personal' logging groups with 6 more generic logging levels (7 thru 12) and a 'Warn' level. The 'Warn' level is enabled by 'group.e' together with level 1 logging. Modified the new RTLog[Rel][Get]DefaultInstanceEx functions to only take one 32-bit parameter to minimize call setup time and size. Major support driver version bump. LogAleksey=Log7, LogBird=Log8, LogSunlover=Log9, none of the other personal macros was used. Log*Warning got renamed to Log1*Warning so as to not confuse it with the LogWarn/LogRelWarn macros.

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