aboutsummaryrefslogtreecommitdiff
path: root/ifconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'ifconfig.c')
-rw-r--r--ifconfig.c437
1 files changed, 196 insertions, 241 deletions
diff --git a/ifconfig.c b/ifconfig.c
index a3e2c0fdb..2a50a9605 100644
--- a/ifconfig.c
+++ b/ifconfig.c
@@ -15,16 +15,19 @@
15 * Foundation; either version 2 of the License, or (at 15 * Foundation; either version 2 of the License, or (at
16 * your option) any later version. 16 * your option) any later version.
17 * 17 *
18 * $Id: ifconfig.c,v 1.3 2001/02/20 06:14:07 andersen Exp $ 18 * $Id: ifconfig.c,v 1.4 2001/03/06 00:48:59 andersen Exp $
19 *
20 * Majorly hacked up by Larry Doolittle <ldoolitt@recycle.lbl.gov>
19 * 21 *
20 */ 22 */
21 23
24#include "busybox.h"
25#include <sys/types.h>
22#include <stdio.h> 26#include <stdio.h>
23#include <stdlib.h> 27#include <stdlib.h>
24#include <errno.h> 28#include <errno.h>
25#include <string.h> // strcmp and friends 29#include <string.h> // strcmp and friends
26#include <ctype.h> // isdigit and friends 30#include <ctype.h> // isdigit and friends
27#include <sys/types.h>
28#include <sys/socket.h> 31#include <sys/socket.h>
29#include <sys/ioctl.h> 32#include <sys/ioctl.h>
30#include <netinet/in.h> 33#include <netinet/in.h>
@@ -32,10 +35,50 @@
32#include <net/if.h> 35#include <net/if.h>
33#include <net/if_arp.h> 36#include <net/if_arp.h>
34#include <linux/if_ether.h> 37#include <linux/if_ether.h>
35#include "busybox.h"
36 38
37static int sockfd; /* socket fd we use to manipulate stuff with */ 39static int sockfd; /* socket fd we use to manipulate stuff with */
38 40
41#define TESTME 0
42#if TESTME
43#define ioctl test_ioctl
44char *saddr_to_a(struct sockaddr *s)
45{
46 if (s->sa_family == ARPHRD_ETHER) {
47 static char hw[18];
48 sprintf(hw, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
49 s->sa_data[0], s->sa_data[1], s->sa_data[2],
50 s->sa_data[3], s->sa_data[4], s->sa_data[5]);
51 return hw;
52 } else if (s->sa_family == AF_INET) {
53 struct sockaddr_in *ss = (struct sockaddr_in *) s;
54 return inet_ntoa(ss->sin_addr);
55 } else {
56 return NULL;
57 }
58}
59
60int test_ioctl(int __fd, unsigned long int __request, void *param)
61{
62 struct ifreq *i=(struct ifreq *)param;
63 printf("ioctl fd=%d, request=%ld\n", __fd, __request);
64
65 switch(__request) {
66 case SIOCGIFFLAGS: printf(" SIOCGIFFLAGS\n"); i->ifr_flags = 0; break;
67 case SIOCSIFFLAGS: printf(" SIOCSIFFLAGS, %x\n", i->ifr_flags); break;
68 case SIOCSIFMETRIC: printf(" SIOCSIFMETRIC, %d\n", i->ifr_metric); break;
69 case SIOCSIFMTU: printf(" SIOCSIFMTU, %d\n", i->ifr_mtu); break;
70 case SIOCSIFBRDADDR: printf(" SIOCSIFBRDADDR, %s\n", saddr_to_a(&(i->ifr_broadaddr))); break;
71 case SIOCSIFDSTADDR: printf(" SIOCSIFDSTADDR, %s\n", saddr_to_a(&(i->ifr_dstaddr ))); break;
72 case SIOCSIFNETMASK: printf(" SIOCSIFNETMASK, %s\n", saddr_to_a(&(i->ifr_netmask ))); break;
73 case SIOCSIFADDR: printf(" SIOCSIFADDR, %s\n", saddr_to_a(&(i->ifr_addr ))); break;
74 case SIOCSIFHWADDR: printf(" SIOCSIFHWADDR, %s\n", saddr_to_a(&(i->ifr_hwaddr ))); break; /* broken */
75 default:
76 }
77 return 0;
78}
79#endif
80
81
39/* print usage and exit */ 82/* print usage and exit */
40 83
41#define _(x) x 84#define _(x) x
@@ -49,7 +92,7 @@ set_flag(char *ifname, short flag)
49 strcpy(ifr.ifr_name, ifname); 92 strcpy(ifr.ifr_name, ifname);
50 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 93 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
51 perror("SIOCGIFFLAGS"); 94 perror("SIOCGIFFLAGS");
52 return (-1); 95 return -1;
53 } 96 }
54 strcpy(ifr.ifr_name, ifname); 97 strcpy(ifr.ifr_name, ifname);
55 ifr.ifr_flags |= flag; 98 ifr.ifr_flags |= flag;
@@ -57,7 +100,7 @@ set_flag(char *ifname, short flag)
57 perror("SIOCSIFFLAGS"); 100 perror("SIOCSIFFLAGS");
58 return -1; 101 return -1;
59 } 102 }
60 return (0); 103 return 0;
61} 104}
62 105
63 106
@@ -78,9 +121,62 @@ clr_flag(char *ifname, short flag)
78 perror("SIOCSIFFLAGS"); 121 perror("SIOCSIFFLAGS");
79 return -1; 122 return -1;
80 } 123 }
81 return (0); 124 return 0;
82} 125}
83 126
127/* which element in struct ifreq to frob */
128enum frob {
129 L_METRIC,
130 L_MTU,
131 L_DATA,
132 L_BROAD,
133 L_DEST,
134 L_MASK,
135 L_HWAD,
136};
137
138
139struct flag_map {
140 char *name;
141 enum frob frob;
142 int flag;
143 int sflag;
144 int action;
145};
146
147/* action:
148 * 2 set
149 * 4 clear
150 * 6 set/clear
151 * 8 clear/set
152 * 10 numeric
153 * 12 address
154 * 14 address/clear
155 */
156const static struct flag_map flag_table[] = {
157 {"arp", 0, IFF_NOARP, 0, 6},
158 {"trailers", 0, IFF_NOTRAILERS, 0, 6},
159 {"promisc", 0, IFF_PROMISC, 0, 8},
160 {"multicast", 0, IFF_MULTICAST, 0, 8},
161 {"allmulti", 0, IFF_ALLMULTI, 0, 8},
162 {"up", 0, (IFF_UP | IFF_RUNNING), 0, 2},
163 {"down", 0, IFF_UP, 0, 4},
164 {"metric", L_METRIC, 0, SIOCSIFMETRIC, 10},
165 {"mtu", L_MTU, 0, SIOCSIFMTU, 10},
166#ifdef SIOCSKEEPALIVE
167 {"keepalive", L_DATA, 0, SIOCSKEEPALIVE, 10},
168#endif
169#ifdef SIOCSOUTFILL
170 {"outfill", L_DATA, 0, SIOCSOUTFILL, 10},
171#endif
172 {"broadcast", L_BROAD, IFF_BROADCAST, SIOCSIFBRDADDR, 14},
173 {"dstaddr", L_DEST, 0, SIOCSIFDSTADDR, 12},
174 {"netmask", L_MASK, 0, SIOCSIFNETMASK, 12},
175 {"pointopoint", L_DEST, IFF_POINTOPOINT, SIOCSIFDSTADDR, 14},
176 {"hw", L_HWAD, 0, SIOCSIFHWADDR, 14},
177};
178
179
84/* resolve XXX.YYY.ZZZ.QQQ -> binary */ 180/* resolve XXX.YYY.ZZZ.QQQ -> binary */
85 181
86static int 182static int
@@ -90,15 +186,16 @@ INET_resolve(char *name, struct sockaddr_in *sin)
90 sin->sin_port = 0; 186 sin->sin_port = 0;
91 187
92 /* Default is special, meaning 0.0.0.0. */ 188 /* Default is special, meaning 0.0.0.0. */
93 if (!strcmp(name, "default")) { 189 if (strcmp(name, "default")==0) {
94 sin->sin_addr.s_addr = INADDR_ANY; 190 sin->sin_addr.s_addr = INADDR_ANY;
95 return (1); 191 return 1;
96 } 192 }
97 /* Look to see if it's a dotted quad. */ 193 /* Look to see if it's a dotted quad. */
98 if (inet_aton(name, &sin->sin_addr)) { 194 if (inet_aton(name, &sin->sin_addr)) {
99 return 0; 195 return 0;
100 } 196 }
101 /* guess not.. */ 197 /* guess not.. */
198 errno = EINVAL;
102 return -1; 199 return -1;
103} 200}
104 201
@@ -127,12 +224,12 @@ in_ether(char *bufp, struct sockaddr *sap)
127 val = c - 'A' + 10; 224 val = c - 'A' + 10;
128 else { 225 else {
129#ifdef DEBUG 226#ifdef DEBUG
130 fprintf(stderr, 227 error_msg(
131 _("in_ether(%s): invalid ether address!\n"), 228 _("in_ether(%s): invalid ether address!"),
132 orig); 229 orig);
133#endif 230#endif
134 errno = EINVAL; 231 errno = EINVAL;
135 return (-1); 232 return -1;
136 } 233 }
137 val <<= 4; 234 val <<= 4;
138 c = *bufp; 235 c = *bufp;
@@ -146,22 +243,19 @@ in_ether(char *bufp, struct sockaddr *sap)
146 val >>= 4; 243 val >>= 4;
147 else { 244 else {
148#ifdef DEBUG 245#ifdef DEBUG
149 fprintf(stderr, 246 error_msg(
150 _("in_ether(%s): invalid ether address!\n"), 247 _("in_ether(%s): invalid ether address!"),
151 orig); 248 orig);
152#endif 249#endif
153 errno = EINVAL; 250 errno = EINVAL;
154 return (-1); 251 return -1;
155 } 252 }
156 if (c != 0) 253 if (c != 0)
157 bufp++; 254 bufp++;
158 *ptr++ = (unsigned char) (val & 0377); 255 *ptr++ = (unsigned char) (val & 0377);
159 i++; 256 i++;
160 257
161 /* We might get a semicolon here - not required. */ 258 /* optional colon already handled, don't swallow a second */
162 if (*bufp == ':')
163 bufp++;
164
165 } 259 }
166 260
167 if(i != ETH_ALEN) { 261 if(i != ETH_ALEN) {
@@ -171,25 +265,37 @@ in_ether(char *bufp, struct sockaddr *sap)
171 265
172 return 0; 266 return 0;
173} 267}
268
269#ifdef BB_FEATURE_IFCONFIG_STATUS
270extern int display_interfaces(void);
271#else
272int display_interfaces(void)
273{
274 show_usage();
275}
276#endif
174 277
175int ifconfig_main(int argc, char **argv) 278int ifconfig_main(int argc, char **argv)
176{ 279{
177 struct ifreq ifr; 280 struct ifreq ifr;
178 struct sockaddr_in sa; 281 struct sockaddr_in sa;
179 struct sockaddr sa2; 282 char **spp, *cmd;
180 char **spp;
181 int goterr = 0; 283 int goterr = 0;
182 int r, didnetmask = 0; 284 int r;
285 /* int didnetmask = 0; special case input error detection no longer implemented */
183 char host[128]; 286 char host[128];
287 const struct flag_map *ft;
288 int i, sense;
289 int a, ecode;
290 struct sockaddr *d;
184 291
185 if(argc < 2) { 292 if(argc < 2) {
186 show_usage(); 293 return(display_interfaces());
187 } 294 }
188 295
189 /* Create a channel to the NET kernel. */ 296 /* Create a channel to the NET kernel. */
190 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 297 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
191 perror("socket"); 298 perror_msg_and_die("socket");
192 exit(1);
193 } 299 }
194 300
195 /* skip argv[0] */ 301 /* skip argv[0] */
@@ -205,235 +311,84 @@ int ifconfig_main(int argc, char **argv)
205 311
206 /* Process the remaining arguments. */ 312 /* Process the remaining arguments. */
207 while (*spp != (char *) NULL) { 313 while (*spp != (char *) NULL) {
208 if (!strcmp(*spp, "arp")) { 314 cmd = *spp;
209 goterr |= clr_flag(ifr.ifr_name, IFF_NOARP); 315 sense=0;
210 spp++; 316 if (*cmd=='-') {
211 continue; 317 sense=1;
212 } 318 cmd++;
213 if (!strcmp(*spp, "-arp")) {
214 goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
215 spp++;
216 continue;
217 }
218
219 if (!strcmp(*spp, "trailers")) {
220 goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
221 spp++;
222 continue;
223 }
224 if (!strcmp(*spp, "-trailers")) {
225 goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
226 spp++;
227 continue;
228 }
229 if (!strcmp(*spp, "promisc")) {
230 goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
231 spp++;
232 continue;
233 }
234 if (!strcmp(*spp, "-promisc")) {
235 goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
236 spp++;
237 continue;
238 }
239 if (!strcmp(*spp, "multicast")) {
240 goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
241 spp++;
242 continue;
243 }
244 if (!strcmp(*spp, "-multicast")) {
245 goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
246 spp++;
247 continue;
248 }
249 if (!strcmp(*spp, "allmulti")) {
250 goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
251 spp++;
252 continue;
253 }
254 if (!strcmp(*spp, "-allmulti")) {
255 goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
256 spp++;
257 continue;
258 }
259 if (!strcmp(*spp, "up")) {
260 goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
261 spp++;
262 continue;
263 }
264 if (!strcmp(*spp, "down")) {
265 goterr |= clr_flag(ifr.ifr_name, IFF_UP);
266 spp++;
267 continue;
268 }
269
270 if (!strcmp(*spp, "metric")) {
271 if (*++spp == NULL)
272 show_usage();
273 ifr.ifr_metric = atoi(*spp);
274 if (ioctl(sockfd, SIOCSIFMETRIC, &ifr) < 0) {
275 fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
276 goterr++;
277 }
278 spp++;
279 continue;
280 }
281 if (!strcmp(*spp, "mtu")) {
282 if (*++spp == NULL)
283 show_usage();
284 ifr.ifr_mtu = atoi(*spp);
285 if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
286 fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
287 goterr++;
288 }
289 spp++;
290 continue;
291 } 319 }
292#ifdef SIOCSKEEPALIVE 320 ft = NULL;
293 if (!strcmp(*spp, "keepalive")) { 321 for (i=0; i<(sizeof(flag_table)/sizeof(struct flag_map)); i++) {
294 if (*++spp == NULL) 322 if (strcmp(cmd, flag_table[i].name)==0) {
295 show_usage(); 323 ft=flag_table+i;
296 ifr.ifr_data = (caddr_t) atoi(*spp); 324 spp++;
297 if (ioctl(sockfd, SIOCSKEEPALIVE, &ifr) < 0) { 325 break;
298 fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno));
299 goterr++;
300 }
301 spp++;
302 continue;
303 }
304#endif
305
306#ifdef SIOCSOUTFILL
307 if (!strcmp(*spp, "outfill")) {
308 if (*++spp == NULL)
309 show_usage();
310 ifr.ifr_data = (caddr_t) atoi(*spp);
311 if (ioctl(sockfd, SIOCSOUTFILL, &ifr) < 0) {
312 fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno));
313 goterr++;
314 } 326 }
315 spp++;
316 continue;
317 } 327 }
318#endif 328 if (ft) {
329 switch (ft->action+sense) {
330 case 4:
331 case 7:
332 case 8:
333 case 15:
334 goterr |= clr_flag(ifr.ifr_name, ft->flag);
335 break;
336 case 2:
337 case 6:
338 case 9:
339 goterr |= set_flag(ifr.ifr_name, ft->flag);
340 break;
341 case 10:
342 if (*spp == NULL)
343 show_usage();
344 a = atoi(*spp++);
345 switch (ft->frob) {
346 case L_METRIC: ifr.ifr_metric = a; break;
347 case L_MTU: ifr.ifr_mtu = a; break;
348 case L_DATA: ifr.ifr_data = (caddr_t) a; break;
349 default: error_msg_and_die("bugaboo");
350 }
319 351
320 if (!strcmp(*spp, "-broadcast")) { 352 if (ioctl(sockfd, ft->sflag, &ifr) < 0) {
321 goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST); 353 perror(ft->name); /* imperfect */
322 spp++;
323 continue;
324 }
325 if (!strcmp(*spp, "broadcast")) {
326 if (*++spp != NULL) {
327 safe_strncpy(host, *spp, (sizeof host));
328 if (INET_resolve(host, &sa) < 0) {
329 goterr++; 354 goterr++;
330 spp++;
331 continue;
332 } 355 }
333 memcpy((char *) &ifr.ifr_broadaddr, 356 break;
334 (char *) &sa, 357 case 12:
335 sizeof(struct sockaddr)); 358 case 14:
336 if (ioctl(sockfd, SIOCSIFBRDADDR, &ifr) < 0) { 359 if (ft->action+sense==10 && *spp == NULL) {
337 perror("SIOCSIFBRDADDR"); 360 show_usage();
338 goterr++; 361 break;
339 } 362 }
340 spp++; 363 if (*spp != NULL) {
341 } 364 safe_strncpy(host, *spp, (sizeof host));
342 goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
343 continue;
344 }
345 if (!strcmp(*spp, "dstaddr")) {
346 if (*++spp == NULL)
347 show_usage();
348 safe_strncpy(host, *spp, (sizeof host));
349 if (INET_resolve(host, &sa) < 0) {
350 goterr++;
351 spp++;
352 continue;
353 }
354 memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
355 sizeof(struct sockaddr));
356 if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
357 fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
358 strerror(errno));
359 goterr++;
360 }
361 spp++;
362 continue;
363 }
364 if (!strcmp(*spp, "netmask")) {
365 if (*++spp == NULL || didnetmask)
366 show_usage();
367 safe_strncpy(host, *spp, (sizeof host));
368 if (INET_resolve(host, &sa) < 0) {
369 goterr++;
370 spp++;
371 continue;
372 }
373 didnetmask++;
374 memcpy((char *) &ifr.ifr_netmask, (char *) &sa,
375 sizeof(struct sockaddr));
376 if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
377 perror("SIOCSIFNETMASK");
378 goterr++;
379 }
380 spp++;
381 continue;
382 }
383
384 if (!strcmp(*spp, "-pointopoint")) {
385 goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
386 spp++;
387 continue;
388 }
389 if (!strcmp(*spp, "pointopoint")) {
390 if (*(spp + 1) != NULL) {
391 spp++;
392 safe_strncpy(host, *spp, (sizeof host));
393 if (INET_resolve(host, &sa)) {
394 goterr++;
395 spp++; 365 spp++;
396 continue; 366 if (ft->frob == L_HWAD) {
367 ecode = in_ether(host, &ifr.ifr_hwaddr);
368 } else {
369 switch (ft->frob) {
370 case L_BROAD: d = &ifr.ifr_broadaddr; break;
371 case L_DEST: d = &ifr.ifr_dstaddr; break;
372 case L_MASK: d = &ifr.ifr_netmask; break;
373 default: error_msg_and_die("bugaboo");
374 }
375 ecode = INET_resolve(host, (struct sockaddr_in *) d);
376 }
377 if (ecode < 0 || ioctl(sockfd, ft->sflag, &ifr) < 0) {
378 perror(ft->name); /* imperfect */
379 goterr++;
380 }
397 } 381 }
398 memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa, 382 if (ft->flag != 0) {
399 sizeof(struct sockaddr)); 383 goterr |= set_flag(ifr.ifr_name, ft->flag);
400 if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
401 perror("SIOCSIFDSTADDR");
402 goterr++;
403 } 384 }
404 } 385 break;
405 goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT); 386 default:
406 spp++;
407 continue;
408 };
409
410 if (!strcmp(*spp, "hw")) {
411 if (*++spp == NULL || strcmp("ether", *spp)) {
412 show_usage(); 387 show_usage();
413 } 388 } /* end of switch */
414
415 if (*++spp == NULL) {
416 /* silently ignore it if no address */
417 continue;
418 }
419
420 safe_strncpy(host, *spp, (sizeof host));
421 if (in_ether(host, &sa2) < 0) {
422 fprintf(stderr, "invalid hw-addr %s\n", host);
423 goterr++;
424 spp++;
425 continue;
426 }
427 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa2,
428 sizeof(struct sockaddr));
429 if (ioctl(sockfd, SIOCSIFHWADDR, &ifr) < 0) {
430 perror("SIOCSIFHWADDR");
431 goterr++;
432 }
433 spp++;
434 continue; 389 continue;
435 } 390 }
436 391
437 /* If the next argument is a valid hostname, assume OK. */ 392 /* If the next argument is a valid hostname, assume OK. */
438 safe_strncpy(host, *spp, (sizeof host)); 393 safe_strncpy(host, *spp, (sizeof host));
439 394
@@ -471,6 +426,6 @@ int ifconfig_main(int argc, char **argv)
471 426
472 } /* end of while-loop */ 427 } /* end of while-loop */
473 428
474 exit(0); 429 return goterr;
475} 430}
476 431