VirtualBox

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

Last change on this file since 39557 was 39557, checked in by vboxsync, 13 years ago

NAT/service: registering port-forawarding from command line.

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