aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2013-01-20 18:10:12 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2013-01-20 18:10:12 +0100
commit31dc8603eedc0140c798c9af3404a35ea190af2c (patch)
treeb8115230c65e5087d48111c3db9ebf7c90f61448
parent2f5b5beb28a3ffe9d12a19b79c453c640cee2f29 (diff)
downloadbusybox-w32-31dc8603eedc0140c798c9af3404a35ea190af2c.tar.gz
busybox-w32-31dc8603eedc0140c798c9af3404a35ea190af2c.tar.bz2
busybox-w32-31dc8603eedc0140c798c9af3404a35ea190af2c.zip
ifconfig: do not accept "ifconfig eth0 up 1.2.3.4/17" (ip with mask). Closes 5786
function old new delta ifconfig_main 1221 1237 +16 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ifconfig.c167
-rw-r--r--networking/route.c2
2 files changed, 81 insertions, 88 deletions
diff --git a/networking/ifconfig.c b/networking/ifconfig.c
index 320df3010..782374b35 100644
--- a/networking/ifconfig.c
+++ b/networking/ifconfig.c
@@ -174,10 +174,6 @@ struct in6_ifreq {
174#define ARG_ADD_DEL (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER) 174#define ARG_ADD_DEL (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
175 175
176 176
177/*
178 * Set up the tables. Warning! They must have corresponding order!
179 */
180
181struct arg1opt { 177struct arg1opt {
182 const char *name; 178 const char *name;
183 unsigned short selector; 179 unsigned short selector;
@@ -198,6 +194,10 @@ struct options {
198 194
199#define ifreq_offsetof(x) offsetof(struct ifreq, x) 195#define ifreq_offsetof(x) offsetof(struct ifreq, x)
200 196
197/*
198 * Set up the tables. Warning! They must have corresponding order!
199 */
200
201static const struct arg1opt Arg1Opt[] = { 201static const struct arg1opt Arg1Opt[] = {
202 { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) }, 202 { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) },
203 { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) }, 203 { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) },
@@ -220,11 +220,11 @@ static const struct arg1opt Arg1Opt[] = {
220 { "SIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr) }, 220 { "SIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr) },
221 { "SIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq) }, 221 { "SIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq) },
222#endif 222#endif
223 /* Last entry if for unmatched (possibly hostname) arg. */
224#if ENABLE_FEATURE_IPV6 223#if ENABLE_FEATURE_IPV6
225 { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */ 224 { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
226 { "DIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */ 225 { "DIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
227#endif 226#endif
227 /* Last entry is for unmatched (assumed to be hostname/address) arg. */
228 { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, 228 { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) },
229}; 229};
230 230
@@ -265,16 +265,49 @@ static const struct options OptArray[] = {
265 { NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING) } 265 { NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING) }
266}; 266};
267 267
268/*
269 * A couple of prototypes.
270 */
271#if ENABLE_FEATURE_IFCONFIG_HW 268#if ENABLE_FEATURE_IFCONFIG_HW
272static int in_ether(const char *bufp, struct sockaddr *sap); 269/* Input an Ethernet address and convert to binary. */
270static int in_ether(const char *bufp, struct sockaddr *sap)
271{
272 char *ptr;
273 int i, j;
274 unsigned char val;
275 unsigned char c;
276
277 sap->sa_family = ARPHRD_ETHER;
278 ptr = (char *) sap->sa_data;
279
280 i = 0;
281 do {
282 j = val = 0;
283
284 /* We might get a semicolon here - not required. */
285 if (i && (*bufp == ':')) {
286 bufp++;
287 }
288
289 do {
290 c = *bufp;
291 if (((unsigned char)(c - '0')) <= 9) {
292 c -= '0';
293 } else if ((unsigned char)((c|0x20) - 'a') <= 5) {
294 c = (unsigned char)((c|0x20) - 'a') + 10;
295 } else if (j && (c == ':' || c == 0)) {
296 break;
297 } else {
298 return -1;
299 }
300 ++bufp;
301 val <<= 4;
302 val += c;
303 } while (++j < 2);
304 *ptr++ = val;
305 } while (++i < ETH_ALEN);
306
307 return *bufp; /* Error if we don't end at end of string. */
308}
273#endif 309#endif
274 310
275/*
276 * Our main function.
277 */
278int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 311int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
279int ifconfig_main(int argc UNUSED_PARAM, char **argv) 312int ifconfig_main(int argc UNUSED_PARAM, char **argv)
280{ 313{
@@ -330,7 +363,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
330 strncpy_IFNAMSIZ(ifr.ifr_name, *argv); 363 strncpy_IFNAMSIZ(ifr.ifr_name, *argv);
331 364
332 /* Process the remaining arguments. */ 365 /* Process the remaining arguments. */
333 while (*++argv != (char *) NULL) { 366 while (*++argv != NULL) {
334 p = *argv; 367 p = *argv;
335 mask = N_MASK; 368 mask = N_MASK;
336 if (*p == '-') { /* If the arg starts with '-'... */ 369 if (*p == '-') { /* If the arg starts with '-'... */
@@ -356,9 +389,9 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
356 FOUND_ARG: 389 FOUND_ARG:
357 if (mask & ARG_MASK) { 390 if (mask & ARG_MASK) {
358 mask = op->arg_flags; 391 mask = op->arg_flags;
359 a1op = Arg1Opt + (op - OptArray);
360 if (mask & A_NETMASK & did_flags) 392 if (mask & A_NETMASK & did_flags)
361 bb_show_usage(); 393 bb_show_usage();
394 a1op = Arg1Opt + (op - OptArray);
362 if (*++argv == NULL) { 395 if (*++argv == NULL) {
363 if (mask & A_ARG_REQ) 396 if (mask & A_ARG_REQ)
364 bb_show_usage(); 397 bb_show_usage();
@@ -371,19 +404,9 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
371#if ENABLE_FEATURE_IFCONFIG_HW 404#if ENABLE_FEATURE_IFCONFIG_HW
372 if (mask & A_CAST_RESOLVE) { 405 if (mask & A_CAST_RESOLVE) {
373#endif 406#endif
374#if ENABLE_FEATURE_IPV6
375 char *prefix;
376 int prefix_len = 0;
377#endif
378 /*safe_strncpy(host, *argv, (sizeof host));*/
379 host = *argv; 407 host = *argv;
380#if ENABLE_FEATURE_IPV6 408 if (strcmp(host, "inet") == 0)
381 prefix = strchr(host, '/'); 409 continue; /* compat stuff */
382 if (prefix) {
383 prefix_len = xatou_range(prefix + 1, 0, 128);
384 *prefix = '\0';
385 }
386#endif
387 sai.sin_family = AF_INET; 410 sai.sin_family = AF_INET;
388 sai.sin_port = 0; 411 sai.sin_port = 0;
389 if (strcmp(host, "default") == 0) { 412 if (strcmp(host, "default") == 0) {
@@ -391,7 +414,8 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
391 sai.sin_addr.s_addr = INADDR_ANY; 414 sai.sin_addr.s_addr = INADDR_ANY;
392 } 415 }
393#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS 416#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
394 else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST) 417 else if ((host[0] == '+' && !host[1])
418 && (mask & A_BROADCAST)
395 && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME) 419 && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)
396 ) { 420 ) {
397 /* + is special, meaning broadcast is derived. */ 421 /* + is special, meaning broadcast is derived. */
@@ -400,23 +424,36 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
400#endif 424#endif
401 else { 425 else {
402 len_and_sockaddr *lsa; 426 len_and_sockaddr *lsa;
403 if (strcmp(host, "inet") == 0) 427#if ENABLE_FEATURE_IPV6
404 continue; /* compat stuff */ 428 char *prefix;
429 int prefix_len = 0;
430 prefix = strchr(host, '/');
431 if (prefix) {
432 prefix_len = xatou_range(prefix + 1, 0, 128);
433 *prefix = '\0';
434 }
435 resolve:
436#endif
405 lsa = xhost2sockaddr(host, 0); 437 lsa = xhost2sockaddr(host, 0);
406#if ENABLE_FEATURE_IPV6 438#if ENABLE_FEATURE_IPV6
439 if (lsa->u.sa.sa_family != AF_INET6 && prefix) {
440/* TODO: we do not support "ifconfig eth0 up 1.2.3.4/17".
441 * For now, just make it fail instead of silently ignoring "/17" part:
442 */
443 *prefix = '/';
444 goto resolve;
445 }
407 if (lsa->u.sa.sa_family == AF_INET6) { 446 if (lsa->u.sa.sa_family == AF_INET6) {
408 int sockfd6; 447 int sockfd6;
409 struct in6_ifreq ifr6; 448 struct in6_ifreq ifr6;
410 449
411 memcpy((char *) &ifr6.ifr6_addr,
412 (char *) &(lsa->u.sin6.sin6_addr),
413 sizeof(struct in6_addr));
414
415 /* Create a channel to the NET kernel. */
416 sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0); 450 sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
417 xioctl(sockfd6, SIOGIFINDEX, &ifr); 451 xioctl(sockfd6, SIOCGIFINDEX, &ifr);
418 ifr6.ifr6_ifindex = ifr.ifr_ifindex; 452 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
419 ifr6.ifr6_prefixlen = prefix_len; 453 ifr6.ifr6_prefixlen = prefix_len;
454 memcpy(&ifr6.ifr6_addr,
455 &lsa->u.sin6.sin6_addr,
456 sizeof(struct in6_addr));
420 ioctl_or_perror_and_die(sockfd6, a1op->selector, &ifr6, "SIOC%s", a1op->name); 457 ioctl_or_perror_and_die(sockfd6, a1op->selector, &ifr6, "SIOC%s", a1op->name);
421 if (ENABLE_FEATURE_CLEAN_UP) 458 if (ENABLE_FEATURE_CLEAN_UP)
422 free(lsa); 459 free(lsa);
@@ -437,18 +474,17 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
437#if ENABLE_FEATURE_IFCONFIG_HW 474#if ENABLE_FEATURE_IFCONFIG_HW
438 } else { /* A_CAST_HOST_COPY_IN_ETHER */ 475 } else { /* A_CAST_HOST_COPY_IN_ETHER */
439 /* This is the "hw" arg case. */ 476 /* This is the "hw" arg case. */
440 smalluint hw_class= index_in_substrings("ether\0" 477 smalluint hw_class = index_in_substrings("ether\0"
441 IF_FEATURE_HWIB("infiniband\0"), *argv) + 1; 478 IF_FEATURE_HWIB("infiniband\0"), *argv) + 1;
442 if (!hw_class || !*++argv) 479 if (!hw_class || !*++argv)
443 bb_show_usage(); 480 bb_show_usage();
444 /*safe_strncpy(host, *argv, sizeof(host));*/
445 host = *argv; 481 host = *argv;
446 if (hw_class == 1 ? in_ether(host, &sa) : in_ib(host, &sa)) 482 if (hw_class == 1 ? in_ether(host, &sa) : in_ib(host, &sa))
447 bb_error_msg_and_die("invalid hw-addr %s", host); 483 bb_error_msg_and_die("invalid hw-addr %s", host);
448 p = (char *) &sa; 484 p = (char *) &sa;
449 } 485 }
450#endif 486#endif
451 memcpy( (((char *)&ifr) + a1op->ifr_offset), 487 memcpy( ((char *)&ifr) + a1op->ifr_offset,
452 p, sizeof(struct sockaddr)); 488 p, sizeof(struct sockaddr));
453 } else { 489 } else {
454 /* FIXME: error check?? */ 490 /* FIXME: error check?? */
@@ -458,17 +494,17 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
458 if (mask & A_MAP_TYPE) { 494 if (mask & A_MAP_TYPE) {
459 xioctl(sockfd, SIOCGIFMAP, &ifr); 495 xioctl(sockfd, SIOCGIFMAP, &ifr);
460 if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR) 496 if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR)
461 *((unsigned char *) p) = i; 497 *(unsigned char *) p = i;
462 else if (mask & A_MAP_USHORT) 498 else if (mask & A_MAP_USHORT)
463 *((unsigned short *) p) = i; 499 *(unsigned short *) p = i;
464 else 500 else
465 *((unsigned long *) p) = i; 501 *(unsigned long *) p = i;
466 } else 502 } else
467#endif 503#endif
468 if (mask & A_CAST_CHAR_PTR) 504 if (mask & A_CAST_CHAR_PTR)
469 *((caddr_t *) p) = (caddr_t) i; 505 *(caddr_t *) p = (caddr_t) i;
470 else /* A_CAST_INT */ 506 else /* A_CAST_INT */
471 *((int *) p) = i; 507 *(int *) p = i;
472 } 508 }
473 509
474 ioctl_or_perror_and_die(sockfd, a1op->selector, &ifr, "SIOC%s", a1op->name); 510 ioctl_or_perror_and_die(sockfd, a1op->selector, &ifr, "SIOC%s", a1op->name);
@@ -494,7 +530,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
494 if (!(mask & A_SET_AFTER)) 530 if (!(mask & A_SET_AFTER))
495 continue; 531 continue;
496 mask = N_SET; 532 mask = N_SET;
497 } 533 } /* if (mask & ARG_MASK) */
498 534
499 xioctl(sockfd, SIOCGIFFLAGS, &ifr); 535 xioctl(sockfd, SIOCGIFFLAGS, &ifr);
500 selector = op->selector; 536 selector = op->selector;
@@ -509,46 +545,3 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
509 close(sockfd); 545 close(sockfd);
510 return 0; 546 return 0;
511} 547}
512
513#if ENABLE_FEATURE_IFCONFIG_HW
514/* Input an Ethernet address and convert to binary. */
515static int in_ether(const char *bufp, struct sockaddr *sap)
516{
517 char *ptr;
518 int i, j;
519 unsigned char val;
520 unsigned char c;
521
522 sap->sa_family = ARPHRD_ETHER;
523 ptr = (char *) sap->sa_data;
524
525 i = 0;
526 do {
527 j = val = 0;
528
529 /* We might get a semicolon here - not required. */
530 if (i && (*bufp == ':')) {
531 bufp++;
532 }
533
534 do {
535 c = *bufp;
536 if (((unsigned char)(c - '0')) <= 9) {
537 c -= '0';
538 } else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
539 c = (c|0x20) - ('a'-10);
540 } else if (j && (c == ':' || c == 0)) {
541 break;
542 } else {
543 return -1;
544 }
545 ++bufp;
546 val <<= 4;
547 val += c;
548 } while (++j < 2);
549 *ptr++ = val;
550 } while (++i < ETH_ALEN);
551
552 return *bufp; /* Error if we don't end at end of string. */
553}
554#endif
diff --git a/networking/route.c b/networking/route.c
index f662031e9..4235ea72c 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -435,7 +435,7 @@ static NOINLINE void INET6_setroute(int action, char **args)
435 struct ifreq ifr; 435 struct ifreq ifr;
436 memset(&ifr, 0, sizeof(ifr)); 436 memset(&ifr, 0, sizeof(ifr));
437 strncpy_IFNAMSIZ(ifr.ifr_name, devname); 437 strncpy_IFNAMSIZ(ifr.ifr_name, devname);
438 xioctl(skfd, SIOGIFINDEX, &ifr); 438 xioctl(skfd, SIOCGIFINDEX, &ifr);
439 rt.rtmsg_ifindex = ifr.ifr_ifindex; 439 rt.rtmsg_ifindex = ifr.ifr_ifindex;
440 } 440 }
441 441