VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/generic/NetIf-generic.cpp@ 43507

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

Main/Metrics: Alternative way to get link speed for old kernels (#6345)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: NetIf-generic.cpp 43507 2012-10-02 13:22:31Z vboxsync $ */
2/** @file
3 * VirtualBox Main - Generic NetIf implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/err.h>
19#include <VBox/log.h>
20#include <iprt/process.h>
21#include <iprt/env.h>
22#include <iprt/path.h>
23#include <iprt/param.h>
24
25#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN)
26# include <cstdio>
27#endif
28
29#include "HostNetworkInterfaceImpl.h"
30#include "ProgressImpl.h"
31#include "VirtualBoxImpl.h"
32#include "netif.h"
33
34#define VBOXNETADPCTL_NAME "VBoxNetAdpCtl"
35
36static int NetIfAdpCtl(const char * pcszIfName, const char *pszAddr, const char *pszOption, const char *pszMask)
37{
38 const char *args[] = { NULL, pcszIfName, pszAddr, pszOption, pszMask, NULL };
39
40 char szAdpCtl[RTPATH_MAX];
41 int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME));
42 if (RT_FAILURE(rc))
43 {
44 LogRel(("NetIfAdpCtl: failed to get program path, rc=%Rrc.\n", rc));
45 return rc;
46 }
47 strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME);
48 args[0] = szAdpCtl;
49 if (!RTPathExists(szAdpCtl))
50 {
51 LogRel(("NetIfAdpCtl: path %s does not exist. Failed to run " VBOXNETADPCTL_NAME " helper.\n",
52 szAdpCtl));
53 return VERR_FILE_NOT_FOUND;
54 }
55
56 RTPROCESS pid;
57 rc = RTProcCreate(szAdpCtl, args, RTENV_DEFAULT, 0, &pid);
58 if (RT_SUCCESS(rc))
59 {
60 RTPROCSTATUS Status;
61 rc = RTProcWait(pid, 0, &Status);
62 if ( RT_SUCCESS(rc)
63 && Status.iStatus == 0
64 && Status.enmReason == RTPROCEXITREASON_NORMAL)
65 return VINF_SUCCESS;
66 }
67 else
68 LogRel(("NetIfAdpCtl: failed to create process for %.\n",
69 szAdpCtl));
70 return rc;
71}
72
73static int NetIfAdpCtl(HostNetworkInterface * pIf, const char *pszAddr, const char *pszOption, const char *pszMask)
74{
75 Bstr interfaceName;
76 pIf->COMGETTER(Name)(interfaceName.asOutParam());
77 Utf8Str strName(interfaceName);
78 return NetIfAdpCtl(strName.c_str(), pszAddr, pszOption, pszMask);
79}
80
81int NetIfAdpCtlOut(const char * pcszName, const char * pcszCmd, char *pszBuffer, size_t cBufSize)
82{
83 char szAdpCtl[RTPATH_MAX];
84 int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " ") - strlen(pcszCmd));
85 if (RT_FAILURE(rc))
86 {
87 LogRel(("NetIfAdpCtlStream: Failed to get program path, rc=%Rrc\n", rc));
88 return VERR_INVALID_PARAMETER;
89 }
90 strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME " ");
91 if (pcszName && strlen(pcszName) <= RTPATH_MAX - strlen(szAdpCtl) - 1 - strlen(pcszCmd))
92 {
93 strcat(szAdpCtl, pcszName);
94 strcat(szAdpCtl, " ");
95 strcat(szAdpCtl, pcszCmd);
96 }
97 else
98 {
99 LogRel(("NetIfAdpCtlStream: Command line is too long: %s%s %s\n", szAdpCtl, pcszName, pcszCmd));
100 return VERR_INVALID_PARAMETER;
101 }
102 if (strlen(szAdpCtl) < RTPATH_MAX - sizeof(" 2>&1"))
103 strcat(szAdpCtl, " 2>&1");
104 FILE *fp = popen(szAdpCtl, "r");
105 if (fp)
106 {
107 if (fgets(pszBuffer, cBufSize, fp))
108 {
109 if (!strncmp(VBOXNETADPCTL_NAME ":", pszBuffer, sizeof(VBOXNETADPCTL_NAME)))
110 {
111 LogRel(("NetIfAdpCtlStream: %s", pszBuffer));
112 rc = VERR_INTERNAL_ERROR;
113 }
114 }
115 else
116 {
117 LogRel(("NetIfAdpCtlStream: No output from " VBOXNETADPCTL_NAME));
118 rc = VERR_INTERNAL_ERROR;
119 }
120 pclose(fp);
121 }
122 return rc;
123}
124
125int NetIfEnableStaticIpConfig(VirtualBox * /* vBox */, HostNetworkInterface * pIf, ULONG aOldIp, ULONG aNewIp, ULONG aMask)
126{
127 const char *pszOption, *pszMask;
128 char szAddress[16]; /* 4*3 + 3*1 + 1 */
129 char szNetMask[16]; /* 4*3 + 3*1 + 1 */
130 uint8_t *pu8Addr = (uint8_t *)&aNewIp;
131 uint8_t *pu8Mask = (uint8_t *)&aMask;
132 if (aNewIp == 0)
133 {
134 pu8Addr = (uint8_t *)&aOldIp;
135 pszOption = "remove";
136 pszMask = NULL;
137 }
138 else
139 {
140 pszOption = "netmask";
141 pszMask = szNetMask;
142 RTStrPrintf(szNetMask, sizeof(szNetMask), "%d.%d.%d.%d",
143 pu8Mask[0], pu8Mask[1], pu8Mask[2], pu8Mask[3]);
144 }
145 RTStrPrintf(szAddress, sizeof(szAddress), "%d.%d.%d.%d",
146 pu8Addr[0], pu8Addr[1], pu8Addr[2], pu8Addr[3]);
147 return NetIfAdpCtl(pIf, szAddress, pszOption, pszMask);
148}
149
150int NetIfEnableStaticIpConfigV6(VirtualBox * /* vBox */, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address, IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
151{
152 char szAddress[5*8 + 1 + 5 + 1];
153 if (Bstr(aIPV6Address).length())
154 {
155 RTStrPrintf(szAddress, sizeof(szAddress), "%ls/%d",
156 aIPV6Address, aIPV6MaskPrefixLength);
157 return NetIfAdpCtl(pIf, szAddress, NULL, NULL);
158 }
159 else
160 {
161 RTStrPrintf(szAddress, sizeof(szAddress), "%ls",
162 aOldIPV6Address);
163 return NetIfAdpCtl(pIf, szAddress, "remove", NULL);
164 }
165}
166
167int NetIfEnableDynamicIpConfig(VirtualBox * /* vBox */, HostNetworkInterface * /* pIf */)
168{
169 return VERR_NOT_IMPLEMENTED;
170}
171
172
173int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox,
174 IHostNetworkInterface **aHostNetworkInterface,
175 IProgress **aProgress,
176 const char *pcszName)
177{
178#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
179 /* create a progress object */
180 ComObjPtr<Progress> progress;
181 progress.createObject();
182
183 ComPtr<IHost> host;
184 HRESULT hrc = pVBox->COMGETTER(Host)(host.asOutParam());
185 if (SUCCEEDED(hrc))
186 {
187 hrc = progress->init(pVBox, host,
188 Bstr("Creating host only network interface").raw(),
189 FALSE /* aCancelable */);
190 if (SUCCEEDED(hrc))
191 {
192 progress.queryInterfaceTo(aProgress);
193
194 char szAdpCtl[RTPATH_MAX];
195 int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " add"));
196 if (RT_FAILURE(rc))
197 {
198 progress->notifyComplete(E_FAIL,
199 COM_IIDOF(IHostNetworkInterface),
200 HostNetworkInterface::getStaticComponentName(),
201 "Failed to get program path, rc=%Rrc\n", rc);
202 return rc;
203 }
204 strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME " ");
205 if (pcszName && strlen(pcszName) <= RTPATH_MAX - strlen(szAdpCtl) - sizeof(" add"))
206 {
207 strcat(szAdpCtl, pcszName);
208 strcat(szAdpCtl, " add");
209 }
210 else
211 strcat(szAdpCtl, "add");
212 if (strlen(szAdpCtl) < RTPATH_MAX - sizeof(" 2>&1"))
213 strcat(szAdpCtl, " 2>&1");
214 FILE *fp = popen(szAdpCtl, "r");
215
216 if (fp)
217 {
218 char szBuf[128]; /* We are not interested in long error messages. */
219 if (fgets(szBuf, sizeof(szBuf), fp))
220 {
221 if (!strncmp(VBOXNETADPCTL_NAME ":", szBuf, sizeof(VBOXNETADPCTL_NAME)))
222 {
223 progress->notifyComplete(E_FAIL,
224 COM_IIDOF(IHostNetworkInterface),
225 HostNetworkInterface::getStaticComponentName(),
226 "%s", szBuf);
227 pclose(fp);
228 return E_FAIL;
229 }
230 char *pLast = szBuf + strlen(szBuf) - 1;
231 if (pLast >= szBuf && *pLast == '\n')
232 *pLast = 0;
233
234 size_t cbNameLen = strlen(szBuf) + 1;
235 PNETIFINFO pInfo = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen]));
236 if (!pInfo)
237 rc = VERR_NO_MEMORY;
238 else
239 {
240 strcpy(pInfo->szShortName, szBuf);
241 strcpy(pInfo->szName, szBuf);
242 rc = NetIfGetConfigByName(pInfo);
243 if (RT_FAILURE(rc))
244 {
245 progress->notifyComplete(E_FAIL,
246 COM_IIDOF(IHostNetworkInterface),
247 HostNetworkInterface::getStaticComponentName(),
248 "Failed to get config info for %s (as reported by '" VBOXNETADPCTL_NAME " add')\n", szBuf);
249 }
250 else
251 {
252 Bstr IfName(szBuf);
253 /* create a new uninitialized host interface object */
254 ComObjPtr<HostNetworkInterface> iface;
255 iface.createObject();
256 iface->init(IfName, HostNetworkInterfaceType_HostOnly, pInfo);
257 iface->setVirtualBox(pVBox);
258 iface.queryInterfaceTo(aHostNetworkInterface);
259 }
260 RTMemFree(pInfo);
261 }
262 if ((rc = pclose(fp)) != 0)
263 {
264 progress->notifyComplete(E_FAIL,
265 COM_IIDOF(IHostNetworkInterface),
266 HostNetworkInterface::getStaticComponentName(),
267 "Failed to execute '"VBOXNETADPCTL_NAME " add' (exit status: %d)", rc);
268 rc = VERR_INTERNAL_ERROR;
269 }
270 }
271 else
272 {
273 /* Failed to add an interface */
274 rc = VERR_PERMISSION_DENIED;
275 progress->notifyComplete(E_FAIL,
276 COM_IIDOF(IHostNetworkInterface),
277 HostNetworkInterface::getStaticComponentName(),
278 "Failed to execute '"VBOXNETADPCTL_NAME " add' (exit status: %d). Check permissions!", rc);
279 pclose(fp);
280 }
281 }
282 if (RT_SUCCESS(rc))
283 progress->notifyComplete(rc);
284 else
285 hrc = E_FAIL;
286 }
287 }
288
289 return hrc;
290
291#else
292 NOREF(pVBox);
293 NOREF(aHostNetworkInterface);
294 NOREF(aProgress);
295 NOREF(pcszName);
296 return VERR_NOT_IMPLEMENTED;
297#endif
298}
299
300int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVBox, IN_GUID aId,
301 IProgress **aProgress)
302{
303#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
304 /* create a progress object */
305 ComObjPtr<Progress> progress;
306 progress.createObject();
307 ComPtr<IHost> host;
308 int rc = VINF_SUCCESS;
309 HRESULT hr = pVBox->COMGETTER(Host)(host.asOutParam());
310 if(SUCCEEDED(hr))
311 {
312 Bstr ifname;
313 ComPtr<IHostNetworkInterface> iface;
314 if (FAILED(host->FindHostNetworkInterfaceById(Guid(aId).toUtf16().raw(), iface.asOutParam())))
315 return VERR_INVALID_PARAMETER;
316 iface->COMGETTER(Name)(ifname.asOutParam());
317 if (ifname.isEmpty())
318 return VERR_INTERNAL_ERROR;
319
320 rc = progress->init(pVBox, host,
321 Bstr("Removing host network interface").raw(),
322 FALSE /* aCancelable */);
323 if(SUCCEEDED(rc))
324 {
325 progress.queryInterfaceTo(aProgress);
326 rc = NetIfAdpCtl(Utf8Str(ifname).c_str(), "remove", NULL, NULL);
327 if (RT_FAILURE(rc))
328 progress->notifyComplete(E_FAIL,
329 COM_IIDOF(IHostNetworkInterface),
330 HostNetworkInterface::getStaticComponentName(),
331 "Failed to execute '"VBOXNETADPCTL_NAME "' (exit status: %d)", rc);
332 else
333 progress->notifyComplete(S_OK);
334 }
335 }
336 else
337 {
338 progress->notifyComplete(hr);
339 rc = VERR_INTERNAL_ERROR;
340 }
341 return rc;
342#else
343 NOREF(pVBox);
344 NOREF(aId);
345 NOREF(aProgress);
346 return VERR_NOT_IMPLEMENTED;
347#endif
348}
349
350int NetIfGetConfig(HostNetworkInterface * /* pIf */, NETIFINFO *)
351{
352 return VERR_NOT_IMPLEMENTED;
353}
354
355int NetIfDhcpRediscover(VirtualBox * /* pVbox */, HostNetworkInterface * /* pIf */)
356{
357 return VERR_NOT_IMPLEMENTED;
358}
359
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