VirtualBox

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

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

NetworkServices: changed the manner network services verify their dependecy on Main.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1/* $Id: VBoxNetBaseService.cpp 49558 2013-11-20 02:43:14Z 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/EventQueue.h>
32#include <VBox/com/VirtualBox.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/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*******************************************************************************/
73
74/*******************************************************************************
75* Global Variables *
76*******************************************************************************/
77/* Commonly used options for network configuration */
78static RTGETOPTDEF g_aGetOptDef[] =
79{
80 { "--name", 'N', RTGETOPT_REQ_STRING },
81 { "--network", 'n', RTGETOPT_REQ_STRING },
82 { "--trunk-name", 't', RTGETOPT_REQ_STRING },
83 { "--trunk-type", 'T', RTGETOPT_REQ_STRING },
84 { "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
85 { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
86 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
87 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
88 { "--need-main", 'M', RTGETOPT_REQ_BOOL },
89};
90
91
92VBoxNetBaseService::VBoxNetBaseService()
93{
94 int rc = RTCritSectInit(&m_csThis);
95 AssertRC(rc);
96 /* numbers from DrvIntNet */
97 m_cbSendBuf = 128 * _1K;
98 m_cbRecvBuf = 256 * _1K;
99 m_hIf = INTNET_HANDLE_INVALID;
100 m_pIfBuf = NULL;
101
102 m_cVerbosity = 0;
103 m_Name = "VBoxNetNAT";
104 m_Network = "intnet";
105 m_fNeedMain = false;
106
107 for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
108 m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
109}
110
111
112VBoxNetBaseService::~VBoxNetBaseService()
113{
114 /*
115 * Close the interface connection.
116 */
117 if (m_hIf != INTNET_HANDLE_INVALID)
118 {
119 INTNETIFCLOSEREQ CloseReq;
120 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
121 CloseReq.Hdr.cbReq = sizeof(CloseReq);
122 CloseReq.pSession = m_pSession;
123 CloseReq.hIf = m_hIf;
124 m_hIf = INTNET_HANDLE_INVALID;
125 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
126 AssertRC(rc);
127 }
128
129 if (m_pSession)
130 {
131 SUPR3Term(false /*fForced*/);
132 m_pSession = NIL_RTR0PTR;
133 }
134 RTCritSectDelete(&m_csThis);
135}
136
137
138int VBoxNetBaseService::init()
139{
140 if (isMainNeeded())
141 {
142 HRESULT hrc = com::Initialize();
143 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
144
145 hrc = virtualbox.createLocalObject(CLSID_VirtualBox);
146 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
147 }
148
149 return VINF_SUCCESS;
150}
151
152
153/**
154 * Parse the arguments.
155 *
156 * @returns 0 on success, fully bitched exit code on failure.
157 *
158 * @param argc Argument count.
159 * @param argv Argument vector.
160 */
161int VBoxNetBaseService::parseArgs(int argc, char **argv)
162{
163
164 RTGETOPTSTATE State;
165 PRTGETOPTDEF paOptionArray = getOptionsPtr();
166 int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
167 AssertRCReturn(rc, 49);
168#if 0
169 /* default initialization */
170 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
171#endif
172 Log2(("BaseService: parseArgs enter\n"));
173
174 for (;;)
175 {
176 RTGETOPTUNION Val;
177 rc = RTGetOpt(&State, &Val);
178 if (!rc)
179 break;
180 switch (rc)
181 {
182 case 'N': // --name
183 m_Name = Val.psz;
184 break;
185
186 case 'n': // --network
187 m_Network = Val.psz;
188 break;
189
190 case 't': //--trunk-name
191 m_TrunkName = Val.psz;
192 break;
193
194 case 'T': //--trunk-type
195 if (!strcmp(Val.psz, "none"))
196 m_enmTrunkType = kIntNetTrunkType_None;
197 else if (!strcmp(Val.psz, "whatever"))
198 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
199 else if (!strcmp(Val.psz, "netflt"))
200 m_enmTrunkType = kIntNetTrunkType_NetFlt;
201 else if (!strcmp(Val.psz, "netadp"))
202 m_enmTrunkType = kIntNetTrunkType_NetAdp;
203 else if (!strcmp(Val.psz, "srvnat"))
204 m_enmTrunkType = kIntNetTrunkType_SrvNat;
205 else
206 {
207 RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
208 return 1;
209 }
210 break;
211
212 case 'a': // --mac-address
213 m_MacAddress = Val.MacAddr;
214 break;
215
216 case 'i': // --ip-address
217 m_Ipv4Address = Val.IPv4Addr;
218 break;
219
220 case 'm': // --netmask
221 m_Ipv4Netmask = Val.IPv4Addr;
222 break;
223
224 case 'v': // --verbose
225 m_cVerbosity++;
226 break;
227
228 case 'V': // --version (missed)
229 RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision());
230 return 1;
231
232 case 'M': // --need-main
233 m_fNeedMain = true;
234 break;
235
236 case 'h': // --help (missed)
237 RTPrintf("%s Version %sr%u\n"
238 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
239 "All rights reserved.\n"
240 "\n"
241 "Usage: %s <options>\n"
242 "\n"
243 "Options:\n",
244 RTProcShortName(),
245 RTBldCfgVersion(),
246 RTBldCfgRevision(),
247 RTProcShortName());
248 for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++)
249 RTPrintf(" -%c, %s\n", m_vecOptionDefs[i]->iShort, m_vecOptionDefs[i]->pszLong);
250 usage(); /* to print Service Specific usage */
251 return 1;
252
253 default:
254 int rc1 = parseOpt(rc, Val);
255 if (RT_FAILURE(rc1))
256 {
257 rc = RTGetOptPrintError(rc, &Val);
258 RTPrintf("Use --help for more information.\n");
259 return rc;
260 }
261 }
262 }
263
264 RTMemFree(paOptionArray);
265 return rc;
266}
267
268
269int VBoxNetBaseService::tryGoOnline(void)
270{
271 /*
272 * Open the session, load ring-0 and issue the request.
273 */
274 int rc = SUPR3Init(&m_pSession);
275 if (RT_FAILURE(rc))
276 {
277 m_pSession = NIL_RTR0PTR;
278 LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
279 return rc;
280 }
281
282 char szPath[RTPATH_MAX];
283 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
284 if (RT_FAILURE(rc))
285 {
286 LogRel(("VBoxNetBaseService: RTPathExecDir -> %Rrc\n", rc));
287 return rc;
288 }
289
290 rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
291 if (RT_FAILURE(rc))
292 {
293 LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
294 return rc;
295 }
296
297 /*
298 * Create the open request.
299 */
300 PINTNETBUF pBuf;
301 INTNETOPENREQ OpenReq;
302 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
303 OpenReq.Hdr.cbReq = sizeof(OpenReq);
304 OpenReq.pSession = m_pSession;
305 strncpy(OpenReq.szNetwork, m_Network.c_str(), sizeof(OpenReq.szNetwork));
306 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
307 strncpy(OpenReq.szTrunk, m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
308 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
309 OpenReq.enmTrunkType = m_enmTrunkType;
310 OpenReq.fFlags = 0; /** @todo check this */
311 OpenReq.cbSend = m_cbSendBuf;
312 OpenReq.cbRecv = m_cbRecvBuf;
313 OpenReq.hIf = INTNET_HANDLE_INVALID;
314
315 /*
316 * Issue the request.
317 */
318 Log2(("attempting to open/create network \"%s\"...\n", OpenReq.szNetwork));
319 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
320 if (RT_FAILURE(rc))
321 {
322 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
323 return rc;
324 }
325 m_hIf = OpenReq.hIf;
326 Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m_hIf));
327
328 /*
329 * Get the ring-3 address of the shared interface buffer.
330 */
331 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
332 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
333 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
334 GetBufferPtrsReq.pSession = m_pSession;
335 GetBufferPtrsReq.hIf = m_hIf;
336 GetBufferPtrsReq.pRing3Buf = NULL;
337 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
338 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
339 if (RT_FAILURE(rc))
340 {
341 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
342 return rc;
343 }
344 pBuf = GetBufferPtrsReq.pRing3Buf;
345 Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
346 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
347 m_pIfBuf = pBuf;
348
349 /*
350 * Activate the interface.
351 */
352 INTNETIFSETACTIVEREQ ActiveReq;
353 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
354 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
355 ActiveReq.pSession = m_pSession;
356 ActiveReq.hIf = m_hIf;
357 ActiveReq.fActive = true;
358 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
359 if (RT_SUCCESS(rc))
360 return 0;
361
362 /* bail out */
363 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
364
365 /* ignore this error */
366 return VINF_SUCCESS;
367}
368
369
370void VBoxNetBaseService::shutdown(void)
371{
372}
373
374
375int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
376{
377 int rc = VINF_SUCCESS;
378 INTNETIFWAITREQ WaitReq;
379 LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
380 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
381 WaitReq.Hdr.cbReq = sizeof(WaitReq);
382 WaitReq.pSession = m_pSession;
383 WaitReq.hIf = m_hIf;
384 WaitReq.cMillies = cMillis;
385
386 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
387 LogFlowFuncLeaveRC(rc);
388 return rc;
389}
390
391/* S/G API */
392int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
393{
394 int rc = VINF_SUCCESS;
395 PINTNETHDR pHdr = NULL;
396 uint8_t *pu8Frame = NULL;
397 int offFrame = 0;
398 int idxSg = 0;
399 /* Allocate frame */
400 rc = IntNetRingAllocateFrame(&m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
401 AssertRCReturn(rc, rc);
402 /* Now we fill pvFrame with S/G above */
403 for (idxSg = 0; idxSg < cSg; ++idxSg)
404 {
405 memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
406 offFrame+=pcSg[idxSg].cb;
407 }
408 /* Commit */
409 IntNetRingCommitFrame(&m_pIfBuf->Send, pHdr);
410
411 LogFlowFuncLeaveRC(rc);
412 return rc;
413}
414/**
415 * forcible ask for send packet on the "wire"
416 */
417void VBoxNetBaseService::flushWire()
418{
419 int rc = VINF_SUCCESS;
420 INTNETIFSENDREQ SendReq;
421 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
422 SendReq.Hdr.cbReq = sizeof(SendReq);
423 SendReq.pSession = m_pSession;
424 SendReq.hIf = m_hIf;
425 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
426 AssertRCReturnVoid(rc);
427 LogFlowFuncLeave();
428
429}
430
431
432/**
433 * Print debug message depending on the m_cVerbosity level.
434 *
435 * @param iMinLevel The minimum m_cVerbosity level for this message.
436 * @param fMsg Whether to dump parts for the current service message.
437 * @param pszFmt The message format string.
438 * @param va Optional arguments.
439 */
440void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
441{
442 if (iMinLevel <= m_cVerbosity)
443 {
444 va_list vaCopy; /* This dude is *very* special, thus the copy. */
445 va_copy(vaCopy, va);
446 RTStrmPrintf(g_pStdErr, "%s: %s: %N\n",
447 RTProcShortName(),
448 iMinLevel >= 2 ? "debug" : "info",
449 pszFmt,
450 &vaCopy);
451 va_end(vaCopy);
452 }
453
454}
455
456
457PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
458{
459 PRTGETOPTDEF pOptArray = NULL;
460 pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m_vecOptionDefs.size());
461 if (!pOptArray)
462 return NULL;
463 for (unsigned int i = 0; i < m_vecOptionDefs.size(); ++i)
464 {
465 PRTGETOPTDEF pOpt = m_vecOptionDefs[i];
466 memcpy(&pOptArray[i], m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
467 }
468 return pOptArray;
469}
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