VirtualBox

source: vbox/trunk/src/apps/adpctl/VBoxNetAdpCtl.cpp@ 23045

最後變更 在這個檔案從23045是 23045,由 vboxsync 提交於 16 年 前

VBoxNetAdpCtl: refined removing of addresses

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 8.6 KB
 
1/* $Id: VBoxNetAdpCtl.cpp 23045 2009-09-15 20:56:37Z vboxsync $ */
2/** @file
3 * Apps - VBoxAdpCtl, Configuration tool for vboxnetX adapters.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <assert.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32#include <sys/wait.h>
33#include <sys/ioctl.h>
34#include <fcntl.h>
35#ifdef RT_OS_SOLARIS
36# include <sys/ioccom.h>
37#endif
38
39/* @todo Error codes must be moved to some header file */
40#define ADPCTLERR_NO_CTL_DEV 3
41#define ADPCTLERR_IOCTL_FAILED 4
42
43/* @todo These are duplicates from src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdpInternal.h */
44#define VBOXNETADP_CTL_DEV_NAME "/dev/vboxnetctl"
45#define VBOXNETADP_NAME "vboxnet"
46#define VBOXNETADP_MAX_NAME_LEN 32
47#define VBOXNETADP_CTL_ADD _IOR('v', 1, VBOXNETADPREQ)
48#define VBOXNETADP_CTL_REMOVE _IOW('v', 2, VBOXNETADPREQ)
49typedef struct VBoxNetAdpReq
50{
51 char szName[VBOXNETADP_MAX_NAME_LEN];
52} VBOXNETADPREQ;
53typedef VBOXNETADPREQ *PVBOXNETADPREQ;
54
55
56#define VBOXADPCTL_IFCONFIG_PATH "/sbin/ifconfig"
57
58#ifdef RT_OS_LINUX
59#define VBOXADPCTL_DEL_CMD "del"
60#else
61#define VBOXADPCTL_DEL_CMD "delete"
62#endif
63
64static void showUsage(void)
65{
66 fprintf(stderr, "Usage: VBoxNetAdpCtl <adapter> <address> ([netmask <address>] | remove)\n");
67 fprintf(stderr, " | VBoxNetAdpCtl add\n");
68 fprintf(stderr, " | VBoxNetAdpCtl <adapter> remove\n");
69}
70
71static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
72 const char *pcszArg2 = NULL,
73 const char *pcszArg3 = NULL,
74 const char *pcszArg4 = NULL,
75 const char *pcszArg5 = NULL)
76{
77 const char * const argv[] =
78 {
79 VBOXADPCTL_IFCONFIG_PATH,
80 pcszAdapterName,
81 pcszArg1, /* [address family] */
82 pcszArg2, /* address */
83 pcszArg3, /* ['netmask'] */
84 pcszArg4, /* [network mask] */
85 pcszArg5, /* [network mask] */
86 NULL /* terminator */
87 };
88 int rc = EXIT_SUCCESS;
89 pid_t childPid = fork();
90 switch (childPid)
91 {
92 case -1: /* Something went wrong. */
93 perror("fork() failed");
94 rc = EXIT_FAILURE;
95 break;
96 case 0: /* Child process. */
97 if (execv(VBOXADPCTL_IFCONFIG_PATH, (char * const*)argv) == -1)
98 rc = EXIT_FAILURE;
99 break;
100 default: /* Parent process. */
101 waitpid(childPid, &rc, 0);
102 break;
103 }
104
105 return rc;
106}
107
108#define MAX_ADDRESSES 128
109#define MAX_ADDRLEN 64
110
111static bool removeAddresses(char *pszAdapterName)
112{
113 char szArgv[1024], szBuf[1024];
114 char aszAddresses[MAX_ADDRESSES][MAX_ADDRLEN];
115 int rc;
116 int fds[2];
117 char * const argv[] = { pszAdapterName, NULL };
118 char * const envp[] = { (char*)"LC_ALL=C", NULL };
119
120 memset(aszAddresses, 0, sizeof(aszAddresses));
121
122 rc = pipe(fds);
123 if (rc < 0)
124 return false;
125
126 pid_t pid = fork();
127 if (pid < 0)
128 return false;
129
130 if (pid == 0)
131 {
132 close(fds[0]);
133 close(STDOUT_FILENO);
134 rc = dup2(fds[1], STDOUT_FILENO);
135 if (rc >= 0)
136 execve(VBOXADPCTL_IFCONFIG_PATH, argv, envp);
137 }
138 else
139 {
140 close(fds[1]);
141 FILE *fp = fdopen(fds[0], "r");
142 if (!fp)
143 return false;
144
145 int cAddrs;
146 for (cAddrs = 0; cAddrs < MAX_ADDRESSES && fgets(szBuf, sizeof(szBuf), fp);)
147 {
148 int cbSkipWS = strspn(szBuf, " \t");
149#if 0 /* Don't use this! assert() breaks the mac build. Use IPRT or be a rectangular building thing. */
150 assert(cbSkipWS < 20);
151#endif
152 char *pszWord = strtok(szBuf + cbSkipWS, " ");
153 /* We are concerned with IPv6 address lines only. */
154 if (!pszWord || strcmp(pszWord, "inet6"))
155 continue;
156#ifdef RT_OS_LINUX
157 pszWord = strtok(NULL, " ");
158 /* Skip "addr:". */
159 if (!pszWord || strcmp(pszWord, "addr:"))
160 continue;
161#endif
162 pszWord = strtok(NULL, " ");
163 /* Skip link-local addresses. */
164 if (!pszWord || !strncmp(pszWord, "fe80", 4))
165 continue;
166 strncpy(aszAddresses[cAddrs++], pszWord, MAX_ADDRLEN-1);
167 }
168 fclose(fp);
169
170 for (int i = 0; i < cAddrs; i++)
171 {
172 if (executeIfconfig(pszAdapterName, "inet6",
173 VBOXADPCTL_DEL_CMD, aszAddresses[i]) != EXIT_SUCCESS)
174 return false;
175 }
176 }
177
178 return true;
179}
180
181int doIOCtl(unsigned long uCmd, void *pData)
182{
183 int fd = open(VBOXNETADP_CTL_DEV_NAME, O_RDWR);
184 if (fd == -1)
185 {
186 perror("VBoxNetAdpCtl: failed to open " VBOXNETADP_CTL_DEV_NAME);
187 return ADPCTLERR_NO_CTL_DEV;
188 }
189
190 int rc = ioctl(fd, uCmd, pData);
191 if (rc == -1)
192 {
193 perror("VBoxNetAdpCtl: ioctl failed for " VBOXNETADP_CTL_DEV_NAME);
194 rc = ADPCTLERR_IOCTL_FAILED;
195 }
196
197 close(fd);
198
199 return rc;
200}
201
202int main(int argc, char *argv[])
203
204{
205 char *pszAdapterName;
206 const char *pszAddress;
207 const char *pszNetworkMask = NULL;
208 const char *pszOption = NULL;
209 int rc = EXIT_SUCCESS;
210 bool fRemove = false;
211 VBOXNETADPREQ Req;
212
213 switch (argc)
214 {
215 case 5:
216 if (strcmp("netmask", argv[3]))
217 {
218 fprintf(stderr, "Invalid argument: %s\n\n", argv[3]);
219 showUsage();
220 return 1;
221 }
222 pszOption = "netmask";
223 pszNetworkMask = argv[4];
224 pszAdapterName = argv[1];
225 pszAddress = argv[2];
226 break;
227 case 4:
228 if (strcmp("remove", argv[3]))
229 {
230 fprintf(stderr, "Invalid argument: %s\n\n", argv[3]);
231 showUsage();
232 return 1;
233 }
234 fRemove = true;
235 pszAdapterName = argv[1];
236 pszAddress = argv[2];
237 break;
238 case 3:
239 pszAdapterName = argv[1];
240 pszAddress = argv[2];
241 if (strcmp("remove", pszAddress) == 0)
242 {
243 snprintf(Req.szName, sizeof(Req.szName), "%s", pszAdapterName);
244 return doIOCtl(VBOXNETADP_CTL_REMOVE, &Req);
245 }
246 break;
247 case 2:
248 if (strcmp("add", argv[1]) == 0)
249 {
250 rc = doIOCtl(VBOXNETADP_CTL_ADD, &Req);
251 if (rc == 0)
252 puts(Req.szName);
253 return rc;
254 }
255 /* Fall through */
256 default:
257 fprintf(stderr, "Invalid number of arguments.\n\n");
258 /* Fall through */
259 case 1:
260 showUsage();
261 return 1;
262 }
263
264 if (strncmp("vboxnet", pszAdapterName, 7))
265 {
266 fprintf(stderr, "Setting configuration for %s is not supported.\n", pszAdapterName);
267 return 2;
268 }
269
270 if (fRemove)
271 {
272 if (strchr(pszAddress, ':'))
273 rc = executeIfconfig(pszAdapterName, "inet6", VBOXADPCTL_DEL_CMD, pszAddress);
274 else
275 {
276#ifdef RT_OS_LINUX
277 rc = executeIfconfig(pszAdapterName, "0.0.0.0");
278#else
279 rc = executeIfconfig(pszAdapterName, "delete", pszAddress);
280#endif
281 }
282 }
283 else
284 {
285 /* We are setting/replacing address. */
286 if (strchr(pszAddress, ':'))
287 {
288 /*
289 * Before we set IPv6 address we'd like to remove
290 * all previously assigned addresses except the
291 * self-assigned one.
292 */
293 if (!removeAddresses(pszAdapterName))
294 rc = EXIT_FAILURE;
295 else
296 rc = executeIfconfig(pszAdapterName, "inet6", "add", pszAddress, pszOption, pszNetworkMask);
297 }
298 else
299 rc = executeIfconfig(pszAdapterName, pszAddress, pszOption, pszNetworkMask);
300 }
301 return rc;
302}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette