VirtualBox

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

Last change on this file since 47623 was 47118, checked in by vboxsync, 12 years ago

NetworkServices: fixed parameters

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