VirtualBox

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

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

doc updates.

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