VirtualBox

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

Last change on this file since 45733 was 45114, checked in by vboxsync, 12 years ago

NAT/service:LWIP: GSO, parameters parsing.

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