VirtualBox

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

Last change on this file since 18863 was 18863, checked in by vboxsync, 15 years ago

Proper build fix for Solaris.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1/* $Id: VBoxNetAdpCtl.cpp 18863 2009-04-10 11:59:25Z 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.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 * 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 <sys/ioccom.h>
35#include <fcntl.h>
36
37/* @todo Error codes must be moved to some header file */
38#define ADPCTLERR_NO_CTL_DEV 3
39#define ADPCTLERR_IOCTL_FAILED 4
40
41/* @todo These are duplicates from src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdpInternal.h */
42#define VBOXNETADP_CTL_DEV_NAME "/dev/vboxnetctl"
43#define VBOXNETADP_NAME "vboxnet"
44#define VBOXNETADP_MAX_NAME_LEN 32
45#define VBOXNETADP_CTL_ADD _IOR('v', 1, VBOXNETADPREQ)
46#define VBOXNETADP_CTL_REMOVE _IOW('v', 2, VBOXNETADPREQ)
47typedef struct VBoxNetAdpReq
48{
49 char szName[VBOXNETADP_MAX_NAME_LEN];
50} VBOXNETADPREQ;
51typedef VBOXNETADPREQ *PVBOXNETADPREQ;
52
53
54#define VBOXADPCTL_IFCONFIG_PATH "/sbin/ifconfig"
55
56#ifdef RT_OS_LINUX
57#define VBOXADPCTL_DEL_CMD "del"
58#else
59#define VBOXADPCTL_DEL_CMD "delete"
60#endif
61
62static void showUsage(void)
63{
64 fprintf(stderr, "Usage: VBoxNetAdpCtl <adapter> <address> ([netmask <address>] | remove)\n");
65 fprintf(stderr, " | VBoxNetAdpCtl add\n");
66 fprintf(stderr, " | VBoxNetAdpCtl <adapter> remove\n");
67}
68
69static int executeIfconfig(const char *pcszAdapterName, const char *pcszArg1,
70 const char *pcszArg2 = NULL,
71 const char *pcszArg3 = NULL,
72 const char *pcszArg4 = NULL,
73 const char *pcszArg5 = NULL)
74{
75 const char * const argv[] =
76 {
77 VBOXADPCTL_IFCONFIG_PATH,
78 pcszAdapterName,
79 pcszArg1, /* [address family] */
80 pcszArg2, /* address */
81 pcszArg3, /* ['netmask'] */
82 pcszArg4, /* [network mask] */
83 pcszArg5, /* [network mask] */
84 NULL /* terminator */
85 };
86 int rc = EXIT_SUCCESS;
87 pid_t childPid = fork();
88 switch (childPid)
89 {
90 case -1: /* Something went wrong. */
91 perror("fork() failed");
92 rc = EXIT_FAILURE;
93 break;
94 case 0: /* Child process. */
95 if (execv(VBOXADPCTL_IFCONFIG_PATH, (char * const*)argv) == -1)
96 rc = EXIT_FAILURE;
97 break;
98 default: /* Parent process. */
99 waitpid(childPid, &rc, 0);
100 break;
101 }
102
103 return rc;
104}
105
106#define MAX_ADDRESSES 128
107#define MAX_ADDRLEN 64
108
109static bool removeAddresses(const char *pszAdapterName)
110{
111 char szCmd[1024], szBuf[1024];
112 char aszAddresses[MAX_ADDRESSES][MAX_ADDRLEN];
113
114 memset(aszAddresses, 0, sizeof(aszAddresses));
115 snprintf(szCmd, sizeof(szCmd), VBOXADPCTL_IFCONFIG_PATH " %s", pszAdapterName);
116 FILE *fp = popen(szCmd, "r");
117
118 if (!fp)
119 return false;
120
121 int cAddrs;
122 for (cAddrs = 0; cAddrs < MAX_ADDRESSES && fgets(szBuf, sizeof(szBuf), fp);)
123 {
124 int cbSkipWS = strspn(szBuf, " \t");
125#if 0 /* Don't use this! assert() breaks the mac build. Use IPRT or be a rectangular building thing. */
126 assert(cbSkipWS < 20);
127#endif
128 char *pszWord = strtok(szBuf + cbSkipWS, " ");
129 /* We are concerned with IPv6 address lines only. */
130 if (!pszWord || strcmp(pszWord, "inet6"))
131 continue;
132#ifdef RT_OS_LINUX
133 pszWord = strtok(NULL, " ");
134 /* Skip "addr:". */
135 if (!pszWord || strcmp(pszWord, "addr:"))
136 continue;
137#endif
138 pszWord = strtok(NULL, " ");
139 /* Skip link-local addresses. */
140 if (!pszWord || !strncmp(pszWord, "fe80", 4))
141 continue;
142 strncpy(aszAddresses[cAddrs++], pszWord, MAX_ADDRLEN-1);
143 }
144 pclose(fp);
145
146 for (int i = 0; i < cAddrs; i++)
147 {
148 if (executeIfconfig(pszAdapterName, "inet6", VBOXADPCTL_DEL_CMD, aszAddresses[i]) != EXIT_SUCCESS)
149 return false;
150 }
151
152 return true;
153}
154
155int doIOCtl(unsigned long uCmd, void *pData)
156{
157 int fd = open(VBOXNETADP_CTL_DEV_NAME, O_RDWR);
158 if (fd == -1)
159 {
160 perror("VBoxNetAdpCtl: failed to open " VBOXNETADP_CTL_DEV_NAME);
161 return ADPCTLERR_NO_CTL_DEV;
162 }
163
164 int rc = ioctl(fd, uCmd, pData);
165 if (rc == -1)
166 {
167 perror("VBoxNetAdpCtl: ioctl failed for " VBOXNETADP_CTL_DEV_NAME);
168 rc = ADPCTLERR_IOCTL_FAILED;
169 }
170
171 close(fd);
172
173 return rc;
174}
175
176int main(int argc, char *argv[])
177
178{
179 const char *pszAdapterName;
180 const char *pszAddress;
181 const char *pszNetworkMask = NULL;
182 const char *pszOption = NULL;
183 int rc = EXIT_SUCCESS;
184 bool fRemove = false;
185 VBOXNETADPREQ Req;
186
187 switch (argc)
188 {
189 case 5:
190 if (strcmp("netmask", argv[3]))
191 {
192 fprintf(stderr, "Invalid argument: %s\n\n", argv[3]);
193 showUsage();
194 return 1;
195 }
196 pszOption = "netmask";
197 pszNetworkMask = argv[4];
198 pszAdapterName = argv[1];
199 pszAddress = argv[2];
200 break;
201 case 4:
202 if (strcmp("remove", argv[3]))
203 {
204 fprintf(stderr, "Invalid argument: %s\n\n", argv[3]);
205 showUsage();
206 return 1;
207 }
208 fRemove = true;
209 pszAdapterName = argv[1];
210 pszAddress = argv[2];
211 break;
212 case 3:
213 pszAdapterName = argv[1];
214 pszAddress = argv[2];
215 if (strcmp("remove", pszAddress) == 0)
216 {
217 strncpy(Req.szName, pszAdapterName, sizeof(Req.szName));
218 return doIOCtl(VBOXNETADP_CTL_REMOVE, &Req);
219 }
220 break;
221 case 2:
222 if (strcmp("add", argv[1]) == 0)
223 {
224 rc = doIOCtl(VBOXNETADP_CTL_ADD, &Req);
225 if (rc == 0)
226 puts(Req.szName);
227 return rc;
228 }
229 /* Fall through */
230 default:
231 fprintf(stderr, "Invalid number of arguments.\n\n");
232 /* Fall through */
233 case 1:
234 showUsage();
235 return 1;
236 }
237
238 if (strncmp("vboxnet", pszAdapterName, 7))
239 {
240 fprintf(stderr, "Setting configuration for %s is not supported.\n", pszAdapterName);
241 return 2;
242 }
243
244 if (fRemove)
245 {
246 if (strchr(pszAddress, ':'))
247 rc = executeIfconfig(pszAdapterName, "inet6", VBOXADPCTL_DEL_CMD, pszAddress);
248 else
249 {
250#ifdef RT_OS_LINUX
251 rc = executeIfconfig(pszAdapterName, "0.0.0.0");
252#else
253 rc = executeIfconfig(pszAdapterName, "delete", pszAddress);
254#endif
255 }
256 }
257 else
258 {
259 /* We are setting/replacing address. */
260 if (strchr(pszAddress, ':'))
261 {
262 /*
263 * Before we set IPv6 address we'd like to remove
264 * all previously assigned addresses except the
265 * self-assigned one.
266 */
267 if (!removeAddresses(pszAdapterName))
268 rc = EXIT_FAILURE;
269 else
270 rc = executeIfconfig(pszAdapterName, "inet6", "add", pszAddress, pszOption, pszNetworkMask);
271 }
272 else
273 rc = executeIfconfig(pszAdapterName, pszAddress, pszOption, pszNetworkMask);
274 }
275 return rc;
276}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use