VirtualBox

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

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

Network-service for lwip-driven proxy.
additionally enables SrvNat trunk type for Nat services.
Note: all changes disabled by default.

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