diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-01-20 18:10:12 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-01-20 18:10:12 +0100 |
commit | 31dc8603eedc0140c798c9af3404a35ea190af2c (patch) | |
tree | b8115230c65e5087d48111c3db9ebf7c90f61448 | |
parent | 2f5b5beb28a3ffe9d12a19b79c453c640cee2f29 (diff) | |
download | busybox-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.c | 167 | ||||
-rw-r--r-- | networking/route.c | 2 |
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 | |||
181 | struct arg1opt { | 177 | struct 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 | |||
201 | static const struct arg1opt Arg1Opt[] = { | 201 | static 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 |
272 | static int in_ether(const char *bufp, struct sockaddr *sap); | 269 | /* Input an Ethernet address and convert to binary. */ |
270 | static 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 | */ | ||
278 | int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 311 | int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
279 | int ifconfig_main(int argc UNUSED_PARAM, char **argv) | 312 | int 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. */ | ||
515 | static 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 | ||