diff options
author | Ron Yorston <rmy@pobox.com> | 2018-03-15 08:49:48 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-03-15 08:49:48 +0000 |
commit | 6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba (patch) | |
tree | bb7620a3217f5adf6fb5f3358b2b89a97331b5e8 /networking | |
parent | f3d24e08a385a68c4bacb284bd8a8e3da7f0f4b3 (diff) | |
parent | bbe47d9b9aee3824845f1ce08c9caeb262c15059 (diff) | |
download | busybox-w32-6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba.tar.gz busybox-w32-6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba.tar.bz2 busybox-w32-6fe4ad9a6c96624c2b75c0d51b035bc1a71d9eba.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r-- | networking/httpd.c | 6 | ||||
-rw-r--r-- | networking/ifconfig.c | 8 | ||||
-rw-r--r-- | networking/interface.c | 235 | ||||
-rw-r--r-- | networking/ip.c | 2 | ||||
-rw-r--r-- | networking/libiproute/ipaddress.c | 5 | ||||
-rw-r--r-- | networking/ntpd.c | 100 | ||||
-rw-r--r-- | networking/tcpudp.c | 11 | ||||
-rw-r--r-- | networking/udhcp/common.h | 2 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 9 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 9 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 49 | ||||
-rw-r--r-- | networking/udhcp/signalpipe.c | 11 | ||||
-rw-r--r-- | networking/wget.c | 8 |
13 files changed, 252 insertions, 203 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 74196a4f1..9439e206c 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -1046,6 +1046,7 @@ static void send_headers(int responseNum) | |||
1046 | /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ | 1046 | /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ |
1047 | char date_str[40]; /* using a bit larger buffer to paranoia reasons */ | 1047 | char date_str[40]; /* using a bit larger buffer to paranoia reasons */ |
1048 | 1048 | ||
1049 | struct tm tm; | ||
1049 | const char *responseString = ""; | 1050 | const char *responseString = ""; |
1050 | const char *infoString = NULL; | 1051 | const char *infoString = NULL; |
1051 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 1052 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
@@ -1074,7 +1075,8 @@ static void send_headers(int responseNum) | |||
1074 | * always fit into those kbytes. | 1075 | * always fit into those kbytes. |
1075 | */ | 1076 | */ |
1076 | 1077 | ||
1077 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&timer)); | 1078 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm)); |
1079 | /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ | ||
1078 | len = sprintf(iobuf, | 1080 | len = sprintf(iobuf, |
1079 | "HTTP/1.0 %d %s\r\n" | 1081 | "HTTP/1.0 %d %s\r\n" |
1080 | "Content-type: %s\r\n" | 1082 | "Content-type: %s\r\n" |
@@ -1128,7 +1130,7 @@ static void send_headers(int responseNum) | |||
1128 | #endif | 1130 | #endif |
1129 | 1131 | ||
1130 | if (file_size != -1) { /* file */ | 1132 | if (file_size != -1) { /* file */ |
1131 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&last_mod)); | 1133 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&last_mod, &tm)); |
1132 | #if ENABLE_FEATURE_HTTPD_RANGES | 1134 | #if ENABLE_FEATURE_HTTPD_RANGES |
1133 | if (responseNum == HTTP_PARTIAL_CONTENT) { | 1135 | if (responseNum == HTTP_PARTIAL_CONTENT) { |
1134 | len += sprintf(iobuf + len, | 1136 | len += sprintf(iobuf + len, |
diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 61d91788a..5c47abc16 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c | |||
@@ -338,6 +338,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv) | |||
338 | char *p; | 338 | char *p; |
339 | /*char host[128];*/ | 339 | /*char host[128];*/ |
340 | const char *host = NULL; /* make gcc happy */ | 340 | const char *host = NULL; /* make gcc happy */ |
341 | IF_FEATURE_IFCONFIG_STATUS(char *show_all_param;) | ||
341 | 342 | ||
342 | did_flags = 0; | 343 | did_flags = 0; |
343 | #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS | 344 | #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS |
@@ -349,15 +350,16 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv) | |||
349 | ++argv; | 350 | ++argv; |
350 | 351 | ||
351 | #if ENABLE_FEATURE_IFCONFIG_STATUS | 352 | #if ENABLE_FEATURE_IFCONFIG_STATUS |
352 | if (argv[0] && (argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2])) { | 353 | show_all_param = NULL; |
353 | interface_opt_a = 1; | 354 | if (argv[0] && argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2]) { |
354 | ++argv; | 355 | ++argv; |
356 | show_all_param = IFNAME_SHOW_DOWNED_TOO; | ||
355 | } | 357 | } |
356 | #endif | 358 | #endif |
357 | 359 | ||
358 | if (!argv[0] || !argv[1]) { /* one or no args */ | 360 | if (!argv[0] || !argv[1]) { /* one or no args */ |
359 | #if ENABLE_FEATURE_IFCONFIG_STATUS | 361 | #if ENABLE_FEATURE_IFCONFIG_STATUS |
360 | return display_interfaces(argv[0] /* can be NULL */); | 362 | return display_interfaces(argv[0] ? argv[0] : show_all_param); |
361 | #else | 363 | #else |
362 | bb_error_msg_and_die("no support for status display"); | 364 | bb_error_msg_and_die("no support for status display"); |
363 | #endif | 365 | #endif |
diff --git a/networking/interface.c b/networking/interface.c index 89427f2f4..e5e55d8d4 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
@@ -318,31 +318,37 @@ struct interface { | |||
318 | char name[IFNAMSIZ]; /* interface name */ | 318 | char name[IFNAMSIZ]; /* interface name */ |
319 | short type; /* if type */ | 319 | short type; /* if type */ |
320 | short flags; /* various flags */ | 320 | short flags; /* various flags */ |
321 | int tx_queue_len; /* transmit queue length */ | ||
322 | |||
323 | /* these should be contiguous, zeroed in one go in if_fetch(): */ | ||
324 | #define FIRST_TO_ZERO metric | ||
321 | int metric; /* routing metric */ | 325 | int metric; /* routing metric */ |
322 | int mtu; /* MTU value */ | 326 | int mtu; /* MTU value */ |
323 | int tx_queue_len; /* transmit queue length */ | ||
324 | struct ifmap map; /* hardware setup */ | 327 | struct ifmap map; /* hardware setup */ |
325 | struct sockaddr addr; /* IP address */ | 328 | struct sockaddr addr; /* IP address */ |
326 | struct sockaddr dstaddr; /* P-P IP address */ | 329 | struct sockaddr dstaddr; /* P-P IP address */ |
327 | struct sockaddr broadaddr; /* IP broadcast address */ | 330 | struct sockaddr broadaddr; /* IP broadcast address */ |
328 | struct sockaddr netmask; /* IP network mask */ | 331 | struct sockaddr netmask; /* IP network mask */ |
329 | int has_ip; | ||
330 | char hwaddr[32]; /* HW address */ | 332 | char hwaddr[32]; /* HW address */ |
331 | int statistics_valid; | 333 | #define LAST_TO_ZERO hwaddr |
334 | |||
335 | smallint has_ip; | ||
336 | smallint statistics_valid; | ||
332 | struct user_net_device_stats stats; /* statistics */ | 337 | struct user_net_device_stats stats; /* statistics */ |
338 | #if 0 /* UNUSED */ | ||
333 | int keepalive; /* keepalive value for SLIP */ | 339 | int keepalive; /* keepalive value for SLIP */ |
334 | int outfill; /* outfill value for SLIP */ | 340 | int outfill; /* outfill value for SLIP */ |
341 | #endif | ||
335 | }; | 342 | }; |
336 | 343 | ||
337 | 344 | struct iface_list { | |
338 | smallint interface_opt_a; /* show all interfaces */ | 345 | struct interface *int_list, *int_last; |
339 | 346 | }; | |
340 | static struct interface *int_list, *int_last; | ||
341 | 347 | ||
342 | 348 | ||
343 | #if 0 | 349 | #if 0 |
344 | /* like strcmp(), but knows about numbers */ | 350 | /* like strcmp(), but knows about numbers */ |
345 | except that the freshly added calls to xatoul() brf on ethernet aliases with | 351 | except that the freshly added calls to xatoul() barf on ethernet aliases with |
346 | uClibc with e.g.: ife->name='lo' name='eth0:1' | 352 | uClibc with e.g.: ife->name='lo' name='eth0:1' |
347 | static int nstrcmp(const char *a, const char *b) | 353 | static int nstrcmp(const char *a, const char *b) |
348 | { | 354 | { |
@@ -368,11 +374,11 @@ static int nstrcmp(const char *a, const char *b) | |||
368 | } | 374 | } |
369 | #endif | 375 | #endif |
370 | 376 | ||
371 | static struct interface *add_interface(char *name) | 377 | static struct interface *add_interface(struct iface_list *ilist, char *name) |
372 | { | 378 | { |
373 | struct interface *ife, **nextp, *new; | 379 | struct interface *ife, **nextp, *new; |
374 | 380 | ||
375 | for (ife = int_last; ife; ife = ife->prev) { | 381 | for (ife = ilist->int_last; ife; ife = ife->prev) { |
376 | int n = /*n*/strcmp(ife->name, name); | 382 | int n = /*n*/strcmp(ife->name, name); |
377 | 383 | ||
378 | if (n == 0) | 384 | if (n == 0) |
@@ -383,43 +389,43 @@ static struct interface *add_interface(char *name) | |||
383 | 389 | ||
384 | new = xzalloc(sizeof(*new)); | 390 | new = xzalloc(sizeof(*new)); |
385 | strncpy_IFNAMSIZ(new->name, name); | 391 | strncpy_IFNAMSIZ(new->name, name); |
386 | nextp = ife ? &ife->next : &int_list; | 392 | |
393 | nextp = ife ? &ife->next : &ilist->int_list; | ||
387 | new->prev = ife; | 394 | new->prev = ife; |
388 | new->next = *nextp; | 395 | new->next = *nextp; |
389 | if (new->next) | 396 | if (new->next) |
390 | new->next->prev = new; | 397 | new->next->prev = new; |
391 | else | 398 | else |
392 | int_last = new; | 399 | ilist->int_last = new; |
393 | *nextp = new; | 400 | *nextp = new; |
394 | return new; | 401 | return new; |
395 | } | 402 | } |
396 | 403 | ||
397 | static char *get_name(char *name, char *p) | 404 | static char *get_name(char name[IFNAMSIZ], char *p) |
398 | { | 405 | { |
399 | /* Extract <name> from nul-terminated p where p matches | 406 | /* Extract NAME from nul-terminated p of the form "<whitespace>NAME:" |
400 | * <name>: after leading whitespace. | 407 | * If match is not made, set NAME to "" and return unchanged p. |
401 | * If match is not made, set name empty and return unchanged p | ||
402 | */ | 408 | */ |
403 | char *nameend; | 409 | char *nameend; |
404 | char *namestart = skip_whitespace(p); | 410 | char *namestart; |
405 | 411 | ||
406 | nameend = namestart; | 412 | nameend = namestart = skip_whitespace(p); |
407 | while (*nameend && *nameend != ':' && !isspace(*nameend)) | 413 | |
408 | nameend++; | 414 | for (;;) { |
409 | if (*nameend == ':') { | 415 | if ((nameend - namestart) >= IFNAMSIZ) |
410 | if ((nameend - namestart) < IFNAMSIZ) { | 416 | break; /* interface name too large - return "" */ |
417 | if (*nameend == ':') { | ||
411 | memcpy(name, namestart, nameend - namestart); | 418 | memcpy(name, namestart, nameend - namestart); |
412 | name[nameend - namestart] = '\0'; | 419 | name[nameend - namestart] = '\0'; |
413 | p = nameend; | 420 | return nameend + 1; |
414 | } else { | ||
415 | /* Interface name too large */ | ||
416 | name[0] = '\0'; | ||
417 | } | 421 | } |
418 | } else { | 422 | nameend++; |
419 | /* trailing ':' not found - return empty */ | 423 | /* isspace, NUL, any control char? */ |
420 | name[0] = '\0'; | 424 | if ((unsigned char)*nameend <= (unsigned char)' ') |
425 | break; /* trailing ':' not found - return "" */ | ||
421 | } | 426 | } |
422 | return p + 1; | 427 | name[0] = '\0'; |
428 | return p; | ||
423 | } | 429 | } |
424 | 430 | ||
425 | /* If scanf supports size qualifiers for %n conversions, then we can | 431 | /* If scanf supports size qualifiers for %n conversions, then we can |
@@ -435,7 +441,10 @@ static char *get_name(char *name, char *p) | |||
435 | /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ | 441 | /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ |
436 | /* }; */ | 442 | /* }; */ |
437 | 443 | ||
438 | /* Lie about the size of the int pointed to for %n. */ | 444 | /* We use %n for unavailable data in older versions of /proc/net/dev formats. |
445 | * This results in bogus stores to ife->FOO members corresponding to | ||
446 | * %n specifiers (even the size of integers may not match). | ||
447 | */ | ||
439 | #if INT_MAX == LONG_MAX | 448 | #if INT_MAX == LONG_MAX |
440 | static const char *const ss_fmt[] = { | 449 | static const char *const ss_fmt[] = { |
441 | "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", | 450 | "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", |
@@ -448,7 +457,6 @@ static const char *const ss_fmt[] = { | |||
448 | "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", | 457 | "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", |
449 | "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" | 458 | "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" |
450 | }; | 459 | }; |
451 | |||
452 | #endif | 460 | #endif |
453 | 461 | ||
454 | static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | 462 | static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) |
@@ -456,22 +464,22 @@ static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | |||
456 | memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); | 464 | memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); |
457 | 465 | ||
458 | sscanf(bp, ss_fmt[procnetdev_vsn], | 466 | sscanf(bp, ss_fmt[procnetdev_vsn], |
459 | &ife->stats.rx_bytes, /* missing for 0 */ | 467 | &ife->stats.rx_bytes, /* missing for v0 */ |
460 | &ife->stats.rx_packets, | 468 | &ife->stats.rx_packets, |
461 | &ife->stats.rx_errors, | 469 | &ife->stats.rx_errors, |
462 | &ife->stats.rx_dropped, | 470 | &ife->stats.rx_dropped, |
463 | &ife->stats.rx_fifo_errors, | 471 | &ife->stats.rx_fifo_errors, |
464 | &ife->stats.rx_frame_errors, | 472 | &ife->stats.rx_frame_errors, |
465 | &ife->stats.rx_compressed, /* missing for <= 1 */ | 473 | &ife->stats.rx_compressed, /* missing for v0, v1 */ |
466 | &ife->stats.rx_multicast, /* missing for <= 1 */ | 474 | &ife->stats.rx_multicast, /* missing for v0, v1 */ |
467 | &ife->stats.tx_bytes, /* missing for 0 */ | 475 | &ife->stats.tx_bytes, /* missing for v0 */ |
468 | &ife->stats.tx_packets, | 476 | &ife->stats.tx_packets, |
469 | &ife->stats.tx_errors, | 477 | &ife->stats.tx_errors, |
470 | &ife->stats.tx_dropped, | 478 | &ife->stats.tx_dropped, |
471 | &ife->stats.tx_fifo_errors, | 479 | &ife->stats.tx_fifo_errors, |
472 | &ife->stats.collisions, | 480 | &ife->stats.collisions, |
473 | &ife->stats.tx_carrier_errors, | 481 | &ife->stats.tx_carrier_errors, |
474 | &ife->stats.tx_compressed /* missing for <= 1 */ | 482 | &ife->stats.tx_compressed /* missing for v0, v1 */ |
475 | ); | 483 | ); |
476 | 484 | ||
477 | if (procnetdev_vsn <= 1) { | 485 | if (procnetdev_vsn <= 1) { |
@@ -494,31 +502,25 @@ static int procnetdev_version(char *buf) | |||
494 | return 0; | 502 | return 0; |
495 | } | 503 | } |
496 | 504 | ||
497 | static int if_readconf(void) | 505 | static void if_readconf(struct iface_list *ilist) |
498 | { | 506 | { |
499 | int numreqs = 30; | 507 | int numreqs = 30; |
500 | struct ifconf ifc; | 508 | struct ifconf ifc; |
501 | struct ifreq *ifr; | 509 | struct ifreq *ifr; |
502 | int n, err = -1; | 510 | int n; |
503 | int skfd; | 511 | int skfd; |
504 | 512 | ||
505 | ifc.ifc_buf = NULL; | 513 | ifc.ifc_buf = NULL; |
506 | 514 | ||
507 | /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets | 515 | /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets |
508 | (as of 2.1.128) */ | 516 | (as of 2.1.128) */ |
509 | skfd = socket(AF_INET, SOCK_DGRAM, 0); | 517 | skfd = xsocket(AF_INET, SOCK_DGRAM, 0); |
510 | if (skfd < 0) { | ||
511 | bb_perror_msg("error: no inet socket available"); | ||
512 | return -1; | ||
513 | } | ||
514 | 518 | ||
515 | for (;;) { | 519 | for (;;) { |
516 | ifc.ifc_len = sizeof(struct ifreq) * numreqs; | 520 | ifc.ifc_len = sizeof(struct ifreq) * numreqs; |
517 | ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); | 521 | ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); |
518 | 522 | ||
519 | if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) { | 523 | xioctl(skfd, SIOCGIFCONF, &ifc); |
520 | goto out; | ||
521 | } | ||
522 | if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { | 524 | if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { |
523 | /* assume it overflowed and try again */ | 525 | /* assume it overflowed and try again */ |
524 | numreqs += 10; | 526 | numreqs += 10; |
@@ -529,67 +531,54 @@ static int if_readconf(void) | |||
529 | 531 | ||
530 | ifr = ifc.ifc_req; | 532 | ifr = ifc.ifc_req; |
531 | for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { | 533 | for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { |
532 | add_interface(ifr->ifr_name); | 534 | add_interface(ilist, ifr->ifr_name); |
533 | ifr++; | 535 | ifr++; |
534 | } | 536 | } |
535 | err = 0; | ||
536 | 537 | ||
537 | out: | ||
538 | close(skfd); | 538 | close(skfd); |
539 | free(ifc.ifc_buf); | 539 | free(ifc.ifc_buf); |
540 | return err; | ||
541 | } | 540 | } |
542 | 541 | ||
543 | static int if_readlist_proc(char *target) | 542 | static int if_readlist_proc(struct iface_list *ilist, char *ifname) |
544 | { | 543 | { |
545 | static smallint proc_read; | ||
546 | |||
547 | FILE *fh; | 544 | FILE *fh; |
548 | char buf[512]; | 545 | char buf[512]; |
549 | struct interface *ife; | 546 | struct interface *ife; |
550 | int err, procnetdev_vsn; | 547 | int procnetdev_vsn; |
551 | 548 | int ret; | |
552 | if (proc_read) | ||
553 | return 0; | ||
554 | if (!target) | ||
555 | proc_read = 1; | ||
556 | 549 | ||
557 | fh = fopen_or_warn(_PATH_PROCNET_DEV, "r"); | 550 | fh = fopen_or_warn(_PATH_PROCNET_DEV, "r"); |
558 | if (!fh) { | 551 | if (!fh) { |
559 | return if_readconf(); | 552 | return 0; /* "not found" */ |
560 | } | 553 | } |
561 | fgets(buf, sizeof buf, fh); /* eat line */ | 554 | fgets(buf, sizeof buf, fh); /* eat line */ |
562 | fgets(buf, sizeof buf, fh); | 555 | fgets(buf, sizeof buf, fh); |
563 | 556 | ||
564 | procnetdev_vsn = procnetdev_version(buf); | 557 | procnetdev_vsn = procnetdev_version(buf); |
565 | 558 | ||
566 | err = 0; | 559 | ret = 0; |
567 | while (fgets(buf, sizeof buf, fh)) { | 560 | while (fgets(buf, sizeof buf, fh)) { |
568 | char *s, name[128]; | 561 | char *s, name[IFNAMSIZ]; |
569 | 562 | ||
570 | s = get_name(name, buf); | 563 | s = get_name(name, buf); |
571 | ife = add_interface(name); | 564 | ife = add_interface(ilist, name); |
572 | get_dev_fields(s, ife, procnetdev_vsn); | 565 | get_dev_fields(s, ife, procnetdev_vsn); |
573 | ife->statistics_valid = 1; | 566 | ife->statistics_valid = 1; |
574 | if (target && strcmp(target, name) == 0) | 567 | if (ifname && strcmp(ifname, name) == 0) { |
568 | ret = 1; /* found */ | ||
575 | break; | 569 | break; |
576 | } | 570 | } |
577 | if (ferror(fh)) { | ||
578 | bb_perror_msg(_PATH_PROCNET_DEV); | ||
579 | err = -1; | ||
580 | proc_read = 0; | ||
581 | } | 571 | } |
582 | fclose(fh); | 572 | fclose(fh); |
583 | return err; | 573 | return ret; |
584 | } | 574 | } |
585 | 575 | ||
586 | static int if_readlist(void) | 576 | static void if_readlist(struct iface_list *ilist, char *ifname) |
587 | { | 577 | { |
588 | int err = if_readlist_proc(NULL); | 578 | int found = if_readlist_proc(ilist, ifname); |
589 | /* Needed in order to get ethN:M aliases */ | 579 | /* Needed in order to get ethN:M aliases */ |
590 | if (!err) | 580 | if (!found) |
591 | err = if_readconf(); | 581 | if_readconf(ilist); |
592 | return err; | ||
593 | } | 582 | } |
594 | 583 | ||
595 | /* Fetch the interface configuration from the kernel. */ | 584 | /* Fetch the interface configuration from the kernel. */ |
@@ -608,24 +597,29 @@ static int if_fetch(struct interface *ife) | |||
608 | } | 597 | } |
609 | ife->flags = ifr.ifr_flags; | 598 | ife->flags = ifr.ifr_flags; |
610 | 599 | ||
600 | /* set up default values if ioctl's would fail */ | ||
601 | ife->tx_queue_len = -1; /* unknown value */ | ||
602 | memset(&ife->FIRST_TO_ZERO, 0, | ||
603 | offsetof(struct interface, LAST_TO_ZERO) | ||
604 | - offsetof(struct interface, FIRST_TO_ZERO) | ||
605 | + sizeof(ife->LAST_TO_ZERO) | ||
606 | ); | ||
607 | |||
611 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 608 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
612 | memset(ife->hwaddr, 0, 32); | ||
613 | if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) | 609 | if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) |
614 | memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); | 610 | memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); |
615 | 611 | ||
612 | //er.... why this _isnt_ inside if()? | ||
616 | ife->type = ifr.ifr_hwaddr.sa_family; | 613 | ife->type = ifr.ifr_hwaddr.sa_family; |
617 | 614 | ||
618 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 615 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
619 | ife->metric = 0; | ||
620 | if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) | 616 | if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) |
621 | ife->metric = ifr.ifr_metric; | 617 | ife->metric = ifr.ifr_metric; |
622 | 618 | ||
623 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 619 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
624 | ife->mtu = 0; | ||
625 | if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) | 620 | if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) |
626 | ife->mtu = ifr.ifr_mtu; | 621 | ife->mtu = ifr.ifr_mtu; |
627 | 622 | ||
628 | memset(&ife->map, 0, sizeof(struct ifmap)); | ||
629 | #ifdef SIOCGIFMAP | 623 | #ifdef SIOCGIFMAP |
630 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 624 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
631 | if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) | 625 | if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) |
@@ -634,31 +628,24 @@ static int if_fetch(struct interface *ife) | |||
634 | 628 | ||
635 | #ifdef HAVE_TXQUEUELEN | 629 | #ifdef HAVE_TXQUEUELEN |
636 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 630 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
637 | ife->tx_queue_len = -1; /* unknown value */ | ||
638 | if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) | 631 | if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) |
639 | ife->tx_queue_len = ifr.ifr_qlen; | 632 | ife->tx_queue_len = ifr.ifr_qlen; |
640 | #else | ||
641 | ife->tx_queue_len = -1; /* unknown value */ | ||
642 | #endif | 633 | #endif |
643 | 634 | ||
644 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 635 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
645 | ifr.ifr_addr.sa_family = AF_INET; | 636 | ifr.ifr_addr.sa_family = AF_INET; |
646 | memset(&ife->addr, 0, sizeof(struct sockaddr)); | ||
647 | if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { | 637 | if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { |
648 | ife->has_ip = 1; | 638 | ife->has_ip = 1; |
649 | ife->addr = ifr.ifr_addr; | 639 | ife->addr = ifr.ifr_addr; |
650 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 640 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
651 | memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); | ||
652 | if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) | 641 | if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) |
653 | ife->dstaddr = ifr.ifr_dstaddr; | 642 | ife->dstaddr = ifr.ifr_dstaddr; |
654 | 643 | ||
655 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 644 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
656 | memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); | ||
657 | if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) | 645 | if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) |
658 | ife->broadaddr = ifr.ifr_broadaddr; | 646 | ife->broadaddr = ifr.ifr_broadaddr; |
659 | 647 | ||
660 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | 648 | strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
661 | memset(&ife->netmask, 0, sizeof(struct sockaddr)); | ||
662 | if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) | 649 | if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) |
663 | ife->netmask = ifr.ifr_netmask; | 650 | ife->netmask = ifr.ifr_netmask; |
664 | } | 651 | } |
@@ -1020,10 +1007,12 @@ static void ife_print(struct interface *ptr) | |||
1020 | 1007 | ||
1021 | /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ | 1008 | /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ |
1022 | printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); | 1009 | printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); |
1010 | #if 0 | ||
1023 | #ifdef SIOCSKEEPALIVE | 1011 | #ifdef SIOCSKEEPALIVE |
1024 | if (ptr->outfill || ptr->keepalive) | 1012 | if (ptr->outfill || ptr->keepalive) |
1025 | printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); | 1013 | printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); |
1026 | #endif | 1014 | #endif |
1015 | #endif | ||
1027 | bb_putchar('\n'); | 1016 | bb_putchar('\n'); |
1028 | 1017 | ||
1029 | /* If needed, display the interface statistics. */ | 1018 | /* If needed, display the interface statistics. */ |
@@ -1077,67 +1066,44 @@ static void ife_print(struct interface *ptr) | |||
1077 | bb_putchar('\n'); | 1066 | bb_putchar('\n'); |
1078 | } | 1067 | } |
1079 | 1068 | ||
1080 | static int do_if_print(struct interface *ife) /*, int *opt_a)*/ | 1069 | static int do_if_print(struct interface *ife, int show_downed_too) |
1081 | { | 1070 | { |
1082 | int res; | 1071 | int res; |
1083 | 1072 | ||
1084 | res = do_if_fetch(ife); | 1073 | res = do_if_fetch(ife); |
1085 | if (res >= 0) { | 1074 | if (res >= 0) { |
1086 | if ((ife->flags & IFF_UP) || interface_opt_a) | 1075 | if ((ife->flags & IFF_UP) || show_downed_too) |
1087 | ife_print(ife); | 1076 | ife_print(ife); |
1088 | } | 1077 | } |
1089 | return res; | 1078 | return res; |
1090 | } | 1079 | } |
1091 | 1080 | ||
1092 | static struct interface *lookup_interface(char *name) | 1081 | int FAST_FUNC display_interfaces(char *ifname) |
1093 | { | ||
1094 | struct interface *ife = NULL; | ||
1095 | |||
1096 | if (if_readlist_proc(name) < 0) | ||
1097 | return NULL; | ||
1098 | ife = add_interface(name); | ||
1099 | return ife; | ||
1100 | } | ||
1101 | |||
1102 | #ifdef UNUSED | ||
1103 | static int for_all_interfaces(int (*doit) (struct interface *, void *), | ||
1104 | void *cookie) | ||
1105 | { | 1082 | { |
1106 | struct interface *ife; | 1083 | struct interface *ife; |
1084 | int res; | ||
1085 | struct iface_list ilist; | ||
1107 | 1086 | ||
1108 | if (!int_list && (if_readlist() < 0)) | 1087 | ilist.int_list = NULL; |
1109 | return -1; | 1088 | ilist.int_last = NULL; |
1110 | for (ife = int_list; ife; ife = ife->next) { | 1089 | if_readlist(&ilist, ifname != IFNAME_SHOW_DOWNED_TOO ? ifname : NULL); |
1111 | int err = doit(ife, cookie); | ||
1112 | if (err) | ||
1113 | return err; | ||
1114 | } | ||
1115 | return 0; | ||
1116 | } | ||
1117 | #endif | ||
1118 | 1090 | ||
1119 | /* for ipv4 add/del modes */ | 1091 | if (!ifname || ifname == IFNAME_SHOW_DOWNED_TOO) { |
1120 | static int if_print(char *ifname) | 1092 | for (ife = ilist.int_list; ife; ife = ife->next) { |
1121 | { | ||
1122 | struct interface *ife; | ||
1123 | int res; | ||
1124 | 1093 | ||
1125 | if (!ifname) { | 1094 | BUILD_BUG_ON((int)(intptr_t)IFNAME_SHOW_DOWNED_TOO != 1); |
1126 | /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ | 1095 | |
1127 | if (!int_list && (if_readlist() < 0)) | 1096 | res = do_if_print(ife, (int)(intptr_t)ifname); |
1128 | return -1; | 1097 | if (res < 0) |
1129 | for (ife = int_list; ife; ife = ife->next) { | 1098 | goto ret; |
1130 | int err = do_if_print(ife); /*, &interface_opt_a);*/ | ||
1131 | if (err) | ||
1132 | return err; | ||
1133 | } | 1099 | } |
1134 | return 0; | 1100 | return 0; |
1135 | } | 1101 | } |
1136 | ife = lookup_interface(ifname); | 1102 | |
1137 | res = do_if_fetch(ife); | 1103 | ife = add_interface(&ilist, ifname); |
1138 | if (res >= 0) | 1104 | res = do_if_print(ife, /*show_downed_too:*/ 1); |
1139 | ife_print(ife); | 1105 | ret: |
1140 | return res; | 1106 | return (res < 0); /* status < 0 == 1 -- error */ |
1141 | } | 1107 | } |
1142 | 1108 | ||
1143 | #if ENABLE_FEATURE_HWIB | 1109 | #if ENABLE_FEATURE_HWIB |
@@ -1153,12 +1119,3 @@ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) | |||
1153 | return 0; | 1119 | return 0; |
1154 | } | 1120 | } |
1155 | #endif | 1121 | #endif |
1156 | |||
1157 | int FAST_FUNC display_interfaces(char *ifname) | ||
1158 | { | ||
1159 | int status; | ||
1160 | |||
1161 | status = if_print(ifname); | ||
1162 | |||
1163 | return (status < 0); /* status < 0 == 1 -- error */ | ||
1164 | } | ||
diff --git a/networking/ip.c b/networking/ip.c index accf90759..9ecb99abb 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -157,7 +157,7 @@ | |||
157 | //usage:#define iplink_trivial_usage | 157 | //usage:#define iplink_trivial_usage |
158 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" | 158 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" |
159 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" | 159 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" |
160 | //usage: " [master IFACE | nomaster]\n" | 160 | //usage: " [master IFACE | nomaster]" |
161 | // * short help shows only "set" command, long help continues (with just one "\n") | 161 | // * short help shows only "set" command, long help continues (with just one "\n") |
162 | // * and shows all other commands: | 162 | // * and shows all other commands: |
163 | //usage:#define iplink_full_usage "\n" | 163 | //usage:#define iplink_full_usage "\n" |
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index d7f888176..9ec665b69 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -570,7 +570,10 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) | |||
570 | } | 570 | } |
571 | 571 | ||
572 | for (l = linfo; l; l = l->next) { | 572 | for (l = linfo; l; l = l->next) { |
573 | if (no_link || print_linkinfo(&l->h) == 0) { | 573 | if (no_link |
574 | || (oneline || print_linkinfo(&l->h) == 0) | ||
575 | /* ^^^^^^^^^ "ip -oneline a" does not print link info */ | ||
576 | ) { | ||
574 | struct ifinfomsg *ifi = NLMSG_DATA(&l->h); | 577 | struct ifinfomsg *ifi = NLMSG_DATA(&l->h); |
575 | if (G_filter.family != AF_PACKET) | 578 | if (G_filter.family != AF_PACKET) |
576 | print_selected_addrinfo(ifi->ifi_index, ainfo); | 579 | print_selected_addrinfo(ifi->ifi_index, ainfo); |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 17e5c7da6..8205ab271 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -165,8 +165,12 @@ | |||
165 | * Using exact power of 2 (1/8) results in smaller code | 165 | * Using exact power of 2 (1/8) results in smaller code |
166 | */ | 166 | */ |
167 | #define SLEW_THRESHOLD 0.125 | 167 | #define SLEW_THRESHOLD 0.125 |
168 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: man adjtimex about tmx.offset: | ||
169 | // "Since Linux 2.6.26, the supplied value is clamped to the range (-0.5s, +0.5s)" | ||
170 | // - can use this larger value instead? | ||
171 | |||
168 | /* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ | 172 | /* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ |
169 | #define WATCH_THRESHOLD 128 | 173 | //UNUSED: #define WATCH_THRESHOLD 128 |
170 | /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ | 174 | /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ |
171 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ | 175 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ |
172 | 176 | ||
@@ -419,6 +423,7 @@ struct globals { | |||
419 | uint8_t discipline_state; // doc calls it c.state | 423 | uint8_t discipline_state; // doc calls it c.state |
420 | uint8_t poll_exp; // s.poll | 424 | uint8_t poll_exp; // s.poll |
421 | int polladj_count; // c.count | 425 | int polladj_count; // c.count |
426 | int FREQHOLD_cnt; | ||
422 | long kernel_freq_drift; | 427 | long kernel_freq_drift; |
423 | peer_t *last_update_peer; | 428 | peer_t *last_update_peer; |
424 | double last_update_offset; // c.last | 429 | double last_update_offset; // c.last |
@@ -1034,6 +1039,7 @@ step_time(double offset) | |||
1034 | tval = tvn.tv_sec; | 1039 | tval = tvn.tv_sec; |
1035 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); | 1040 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); |
1036 | bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); | 1041 | bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); |
1042 | //maybe? G.FREQHOLD_cnt = 0; | ||
1037 | 1043 | ||
1038 | /* Correct various fields which contain time-relative values: */ | 1044 | /* Correct various fields which contain time-relative values: */ |
1039 | 1045 | ||
@@ -1709,39 +1715,96 @@ update_local_clock(peer_t *p) | |||
1709 | tmx.freq = G.discipline_freq_drift * 65536e6; | 1715 | tmx.freq = G.discipline_freq_drift * 65536e6; |
1710 | #endif | 1716 | #endif |
1711 | tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; | 1717 | tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; |
1712 | tmx.constant = (int)G.poll_exp - 4; | 1718 | |
1713 | /* EXPERIMENTAL. | ||
1714 | * The below if statement should be unnecessary, but... | ||
1715 | * It looks like Linux kernel's PLL is far too gentle in changing | ||
1716 | * tmx.freq in response to clock offset. Offset keeps growing | ||
1717 | * and eventually we fall back to smaller poll intervals. | ||
1718 | * We can make correction more aggressive (about x2) by supplying | ||
1719 | * PLL time constant which is one less than the real one. | ||
1720 | * To be on a safe side, let's do it only if offset is significantly | ||
1721 | * larger than jitter. | ||
1722 | */ | ||
1723 | if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE) | ||
1724 | tmx.constant--; | ||
1725 | tmx.offset = (long)(offset * 1000000); /* usec */ | 1719 | tmx.offset = (long)(offset * 1000000); /* usec */ |
1726 | if (SLEW_THRESHOLD < STEP_THRESHOLD) { | 1720 | if (SLEW_THRESHOLD < STEP_THRESHOLD) { |
1727 | if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { | 1721 | if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) { |
1728 | tmx.offset = (long)(SLEW_THRESHOLD * 1000000); | 1722 | tmx.offset = (long)(SLEW_THRESHOLD * 1000000); |
1729 | tmx.constant--; | ||
1730 | } | 1723 | } |
1731 | if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { | 1724 | if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) { |
1732 | tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); | 1725 | tmx.offset = -(long)(SLEW_THRESHOLD * 1000000); |
1733 | tmx.constant--; | ||
1734 | } | 1726 | } |
1735 | } | 1727 | } |
1736 | if (tmx.constant < 0) | ||
1737 | tmx.constant = 0; | ||
1738 | 1728 | ||
1739 | tmx.status = STA_PLL; | 1729 | tmx.status = STA_PLL; |
1730 | if (G.FREQHOLD_cnt != 0) { | ||
1731 | /* man adjtimex on STA_FREQHOLD: | ||
1732 | * "Normally adjustments made via ADJ_OFFSET result in dampened | ||
1733 | * frequency adjustments also being made. | ||
1734 | * This flag prevents the small frequency adjustment from being | ||
1735 | * made when correcting for an ADJ_OFFSET value." | ||
1736 | * | ||
1737 | * Use this flag for a few first adjustments at the beginning | ||
1738 | * of ntpd execution, otherwise even relatively small initial | ||
1739 | * offset tend to cause largish changes to in-kernel tmx.freq. | ||
1740 | * If ntpd was restarted due to e.g. switch to another network, | ||
1741 | * this destroys already well-established tmx.freq value. | ||
1742 | */ | ||
1743 | if (G.FREQHOLD_cnt < 0) { | ||
1744 | /* Initialize it */ | ||
1745 | // Example: a laptop whose clock runs slower when hibernated, | ||
1746 | // after wake up it still has good tmx.freq, but accumulated ~0.5 sec offset: | ||
1747 | // Run with code where initial G.FREQHOLD_cnt was always 8: | ||
1748 | //15:17:52.947 no valid datapoints, no peer selected | ||
1749 | //15:17:56.515 update from:<IP> offset:+0.485133 delay:0.157762 jitter:0.209310 clock drift:-1.393ppm tc:4 | ||
1750 | //15:17:57.719 update from:<IP> offset:+0.483825 delay:0.158070 jitter:0.181159 clock drift:-1.393ppm tc:4 | ||
1751 | //15:17:59.925 update from:<IP> offset:+0.479504 delay:0.158147 jitter:0.156657 clock drift:-1.393ppm tc:4 | ||
1752 | //15:18:33.322 update from:<IP> offset:+0.428119 delay:0.158317 jitter:0.138071 clock drift:-1.393ppm tc:4 | ||
1753 | //15:19:06.718 update from:<IP> offset:+0.376932 delay:0.158276 jitter:0.122075 clock drift:-1.393ppm tc:4 | ||
1754 | //15:19:39.114 update from:<IP> offset:+0.327022 delay:0.158384 jitter:0.108538 clock drift:-1.393ppm tc:4 | ||
1755 | //15:20:12.715 update from:<IP> offset:+0.275596 delay:0.158297 jitter:0.097292 clock drift:-1.393ppm tc:4 | ||
1756 | //15:20:45.111 update from:<IP> offset:+0.225715 delay:0.158271 jitter:0.087841 clock drift:-1.393ppm tc:4 | ||
1757 | // If allwed to continue, it would start increasing tmx.freq now. | ||
1758 | // Instead, it was ^Ced, and started anew: | ||
1759 | //15:21:15.043 no valid datapoints, no peer selected | ||
1760 | //15:21:17.408 update from:<IP> offset:+0.175910 delay:0.158314 jitter:0.076683 clock drift:-1.393ppm tc:4 | ||
1761 | //15:21:19.774 update from:<IP> offset:+0.171784 delay:0.158401 jitter:0.066436 clock drift:-1.393ppm tc:4 | ||
1762 | //15:21:22.140 update from:<IP> offset:+0.171660 delay:0.158592 jitter:0.057536 clock drift:-1.393ppm tc:4 | ||
1763 | //15:21:22.140 update from:<IP> offset:+0.167126 delay:0.158507 jitter:0.049792 clock drift:-1.393ppm tc:4 | ||
1764 | //15:21:55.696 update from:<IP> offset:+0.115223 delay:0.158277 jitter:0.050240 clock drift:-1.393ppm tc:4 | ||
1765 | //15:22:29.093 update from:<IP> offset:+0.068051 delay:0.158243 jitter:0.049405 clock drift:-1.393ppm tc:5 | ||
1766 | //15:23:02.490 update from:<IP> offset:+0.051632 delay:0.158215 jitter:0.043545 clock drift:-1.393ppm tc:5 | ||
1767 | //15:23:34.726 update from:<IP> offset:+0.039984 delay:0.158157 jitter:0.038106 clock drift:-1.393ppm tc:5 | ||
1768 | // STA_FREQHOLD no longer set, started increasing tmx.freq now: | ||
1769 | //15:24:06.961 update from:<IP> offset:+0.030968 delay:0.158190 jitter:0.033306 clock drift:+2.387ppm tc:5 | ||
1770 | //15:24:40.357 update from:<IP> offset:+0.023648 delay:0.158211 jitter:0.029072 clock drift:+5.454ppm tc:5 | ||
1771 | //15:25:13.774 update from:<IP> offset:+0.018068 delay:0.157660 jitter:0.025288 clock drift:+7.728ppm tc:5 | ||
1772 | //15:26:19.173 update from:<IP> offset:+0.010057 delay:0.157969 jitter:0.022255 clock drift:+8.361ppm tc:6 | ||
1773 | //15:27:26.602 update from:<IP> offset:+0.006737 delay:0.158103 jitter:0.019316 clock drift:+8.792ppm tc:6 | ||
1774 | //15:28:33.030 update from:<IP> offset:+0.004513 delay:0.158294 jitter:0.016765 clock drift:+9.080ppm tc:6 | ||
1775 | //15:29:40.617 update from:<IP> offset:+0.002787 delay:0.157745 jitter:0.014543 clock drift:+9.258ppm tc:6 | ||
1776 | //15:30:47.045 update from:<IP> offset:+0.001324 delay:0.157709 jitter:0.012594 clock drift:+9.342ppm tc:6 | ||
1777 | //15:31:53.473 update from:<IP> offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 | ||
1778 | //15:32:58.902 update from:<IP> offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 | ||
1779 | /* | ||
1780 | * This expression would choose 15 in the above example. | ||
1781 | */ | ||
1782 | G.FREQHOLD_cnt = 8 + ((unsigned)(abs(tmx.offset)) >> 16); | ||
1783 | } | ||
1784 | G.FREQHOLD_cnt--; | ||
1785 | tmx.status |= STA_FREQHOLD; | ||
1786 | } | ||
1740 | if (G.ntp_status & LI_PLUSSEC) | 1787 | if (G.ntp_status & LI_PLUSSEC) |
1741 | tmx.status |= STA_INS; | 1788 | tmx.status |= STA_INS; |
1742 | if (G.ntp_status & LI_MINUSSEC) | 1789 | if (G.ntp_status & LI_MINUSSEC) |
1743 | tmx.status |= STA_DEL; | 1790 | tmx.status |= STA_DEL; |
1744 | 1791 | ||
1792 | tmx.constant = (int)G.poll_exp - 4; | ||
1793 | /* EXPERIMENTAL. | ||
1794 | * The below if statement should be unnecessary, but... | ||
1795 | * It looks like Linux kernel's PLL is far too gentle in changing | ||
1796 | * tmx.freq in response to clock offset. Offset keeps growing | ||
1797 | * and eventually we fall back to smaller poll intervals. | ||
1798 | * We can make correction more aggressive (about x2) by supplying | ||
1799 | * PLL time constant which is one less than the real one. | ||
1800 | * To be on a safe side, let's do it only if offset is significantly | ||
1801 | * larger than jitter. | ||
1802 | */ | ||
1803 | if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE) | ||
1804 | tmx.constant--; | ||
1805 | if (tmx.constant < 0) | ||
1806 | tmx.constant = 0; | ||
1807 | |||
1745 | //tmx.esterror = (uint32_t)(clock_jitter * 1e6); | 1808 | //tmx.esterror = (uint32_t)(clock_jitter * 1e6); |
1746 | //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); | 1809 | //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); |
1747 | rc = adjtimex(&tmx); | 1810 | rc = adjtimex(&tmx); |
@@ -2227,6 +2290,7 @@ static NOINLINE void ntp_init(char **argv) | |||
2227 | if (BURSTPOLL != 0) | 2290 | if (BURSTPOLL != 0) |
2228 | G.poll_exp = BURSTPOLL; /* speeds up initial sync */ | 2291 | G.poll_exp = BURSTPOLL; /* speeds up initial sync */ |
2229 | G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */ | 2292 | G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */ |
2293 | G.FREQHOLD_cnt = -1; | ||
2230 | 2294 | ||
2231 | /* Parse options */ | 2295 | /* Parse options */ |
2232 | peers = NULL; | 2296 | peers = NULL; |
diff --git a/networking/tcpudp.c b/networking/tcpudp.c index a90e3f80a..c914221ae 100644 --- a/networking/tcpudp.c +++ b/networking/tcpudp.c | |||
@@ -270,17 +270,22 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv) | |||
270 | 270 | ||
271 | tcp = (applet_name[0] == 't'); | 271 | tcp = (applet_name[0] == 't'); |
272 | 272 | ||
273 | /* "+": stop on first non-option */ | ||
273 | #ifdef SSLSVD | 274 | #ifdef SSLSVD |
274 | opts = getopt32(argv, "^+" | 275 | opts = getopt32(argv, "^+" |
275 | "c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:" /* -c NUM, -b NUM */ | 276 | "c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:" /* -c NUM, -b NUM */ |
277 | "\0" | ||
276 | /* 3+ args, -i at most once, -p implies -h, -v is a counter */ | 278 | /* 3+ args, -i at most once, -p implies -h, -v is a counter */ |
277 | "\0" "-3:i--i:ph:vv", | 279 | "-3:i--i:ph:vv", |
278 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, | 280 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
279 | &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose | 281 | &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose |
280 | ); | 282 | ); |
281 | #else | 283 | #else |
282 | /* "+": stop on first non-option */ | 284 | opts = getopt32(argv, "^+" |
283 | opts = getopt32(argv, "+c:+C:i:x:u:l:Eb:hpt:v", | 285 | "c:+C:i:x:u:l:Eb:+hpt:v" /* -c NUM, -b NUM */ |
286 | "\0" | ||
287 | /* 3+ args, -i at most once, -p implies -h, -v is a counter */ | ||
288 | "-3:i--i:ph:vv", | ||
284 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, | 289 | &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, |
285 | &backlog, &str_t, &verbose | 290 | &backlog, &str_t, &verbose |
286 | ); | 291 | ); |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 04939e707..13059f106 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -314,7 +314,7 @@ int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |||
314 | 314 | ||
315 | void udhcp_sp_setup(void) FAST_FUNC; | 315 | void udhcp_sp_setup(void) FAST_FUNC; |
316 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 316 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
317 | int udhcp_sp_read(struct pollfd *pfds) FAST_FUNC; | 317 | int udhcp_sp_read(void) FAST_FUNC; |
318 | 318 | ||
319 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; | 319 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; |
320 | 320 | ||
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 35c99e89c..289df66ee 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -1375,13 +1375,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1375 | /* yah, I know, *you* say it would never happen */ | 1375 | /* yah, I know, *you* say it would never happen */ |
1376 | timeout = INT_MAX; | 1376 | timeout = INT_MAX; |
1377 | continue; /* back to main loop */ | 1377 | continue; /* back to main loop */ |
1378 | } /* if select timed out */ | 1378 | } /* if poll timed out */ |
1379 | 1379 | ||
1380 | /* select() didn't timeout, something happened */ | 1380 | /* poll() didn't timeout, something happened */ |
1381 | 1381 | ||
1382 | /* Is it a signal? */ | 1382 | /* Is it a signal? */ |
1383 | /* note: udhcp_sp_read checks poll result before reading */ | 1383 | switch (udhcp_sp_read()) { |
1384 | switch (udhcp_sp_read(pfds)) { | ||
1385 | case SIGUSR1: | 1384 | case SIGUSR1: |
1386 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1385 | client_config.first_secs = 0; /* make secs field count from 0 */ |
1387 | already_waited_sec = 0; | 1386 | already_waited_sec = 0; |
@@ -1416,7 +1415,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1416 | } | 1415 | } |
1417 | 1416 | ||
1418 | /* Is it a packet? */ | 1417 | /* Is it a packet? */ |
1419 | if (listen_mode == LISTEN_NONE || !pfds[1].revents) | 1418 | if (!pfds[1].revents) |
1420 | continue; /* no */ | 1419 | continue; /* no */ |
1421 | 1420 | ||
1422 | { | 1421 | { |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 35694fbe3..90b07bf4b 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -1574,13 +1574,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1574 | /* yah, I know, *you* say it would never happen */ | 1574 | /* yah, I know, *you* say it would never happen */ |
1575 | timeout = INT_MAX; | 1575 | timeout = INT_MAX; |
1576 | continue; /* back to main loop */ | 1576 | continue; /* back to main loop */ |
1577 | } /* if select timed out */ | 1577 | } /* if poll timed out */ |
1578 | 1578 | ||
1579 | /* select() didn't timeout, something happened */ | 1579 | /* poll() didn't timeout, something happened */ |
1580 | 1580 | ||
1581 | /* Is it a signal? */ | 1581 | /* Is it a signal? */ |
1582 | /* note: udhcp_sp_read checks poll result before reading */ | 1582 | switch (udhcp_sp_read()) { |
1583 | switch (udhcp_sp_read(pfds)) { | ||
1584 | case SIGUSR1: | 1583 | case SIGUSR1: |
1585 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1584 | client_config.first_secs = 0; /* make secs field count from 0 */ |
1586 | already_waited_sec = 0; | 1585 | already_waited_sec = 0; |
@@ -1615,7 +1614,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1615 | } | 1614 | } |
1616 | 1615 | ||
1617 | /* Is it a packet? */ | 1616 | /* Is it a packet? */ |
1618 | if (listen_mode == LISTEN_NONE || !pfds[1].revents) | 1617 | if (!pfds[1].revents) |
1619 | continue; /* no */ | 1618 | continue; /* no */ |
1620 | 1619 | ||
1621 | { | 1620 | { |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 093239536..19f94a2d7 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -853,6 +853,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
853 | /* Would rather not do read_config before daemonization - | 853 | /* Would rather not do read_config before daemonization - |
854 | * otherwise NOMMU machines will parse config twice */ | 854 | * otherwise NOMMU machines will parse config twice */ |
855 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); | 855 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); |
856 | /* prevent poll timeout overflow */ | ||
857 | if (server_config.auto_time > INT_MAX / 1000) | ||
858 | server_config.auto_time = INT_MAX / 1000; | ||
856 | 859 | ||
857 | /* Make sure fd 0,1,2 are open */ | 860 | /* Make sure fd 0,1,2 are open */ |
858 | bb_sanitize_stdio(); | 861 | bb_sanitize_stdio(); |
@@ -914,21 +917,31 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
914 | } | 917 | } |
915 | 918 | ||
916 | udhcp_sp_fd_set(pfds, server_socket); | 919 | udhcp_sp_fd_set(pfds, server_socket); |
917 | tv = timeout_end - monotonic_sec(); | 920 | |
918 | retval = 0; | 921 | new_tv: |
919 | if (!server_config.auto_time || tv > 0) { | 922 | tv = -1; |
920 | retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); | 923 | if (server_config.auto_time) { |
921 | } | 924 | tv = timeout_end - monotonic_sec(); |
922 | if (retval == 0) { | 925 | if (tv <= 0) { |
923 | write_leases(); | 926 | write_leases: |
924 | goto continue_with_autotime; | 927 | write_leases(); |
928 | goto continue_with_autotime; | ||
929 | } | ||
930 | tv *= 1000; | ||
925 | } | 931 | } |
926 | if (retval < 0 && errno != EINTR) { | 932 | |
927 | log1("error on select"); | 933 | /* Block here waiting for either signal or packet */ |
928 | continue; | 934 | retval = poll(pfds, 2, tv); |
935 | if (retval <= 0) { | ||
936 | if (retval == 0) | ||
937 | goto write_leases; | ||
938 | if (errno == EINTR) | ||
939 | goto new_tv; | ||
940 | /* < 0 and not EINTR: should not happen */ | ||
941 | bb_perror_msg_and_die("poll"); | ||
929 | } | 942 | } |
930 | 943 | ||
931 | switch (udhcp_sp_read(pfds)) { | 944 | if (pfds[0].revents) switch (udhcp_sp_read()) { |
932 | case SIGUSR1: | 945 | case SIGUSR1: |
933 | bb_error_msg("received %s", "SIGUSR1"); | 946 | bb_error_msg("received %s", "SIGUSR1"); |
934 | write_leases(); | 947 | write_leases(); |
@@ -938,12 +951,16 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
938 | bb_error_msg("received %s", "SIGTERM"); | 951 | bb_error_msg("received %s", "SIGTERM"); |
939 | write_leases(); | 952 | write_leases(); |
940 | goto ret0; | 953 | goto ret0; |
941 | case 0: /* no signal: read a packet */ | ||
942 | break; | ||
943 | default: /* signal or error (probably EINTR): back to select */ | ||
944 | continue; | ||
945 | } | 954 | } |
946 | 955 | ||
956 | /* Is it a packet? */ | ||
957 | if (!pfds[1].revents) | ||
958 | continue; /* no */ | ||
959 | |||
960 | /* Note: we do not block here, we block on poll() instead. | ||
961 | * Blocking here would prevent SIGTERM from working: | ||
962 | * socket read inside this call is restarted on caught signals. | ||
963 | */ | ||
947 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); | 964 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); |
948 | if (bytes < 0) { | 965 | if (bytes < 0) { |
949 | /* bytes can also be -2 ("bad packet data") */ | 966 | /* bytes can also be -2 ("bad packet data") */ |
diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c index b101b4ce4..2ff78f0f2 100644 --- a/networking/udhcp/signalpipe.c +++ b/networking/udhcp/signalpipe.c | |||
@@ -40,6 +40,7 @@ void FAST_FUNC udhcp_sp_setup(void) | |||
40 | xpiped_pair(signal_pipe); | 40 | xpiped_pair(signal_pipe); |
41 | close_on_exec_on(signal_pipe.rd); | 41 | close_on_exec_on(signal_pipe.rd); |
42 | close_on_exec_on(signal_pipe.wr); | 42 | close_on_exec_on(signal_pipe.wr); |
43 | ndelay_on(signal_pipe.rd); | ||
43 | ndelay_on(signal_pipe.wr); | 44 | ndelay_on(signal_pipe.wr); |
44 | bb_signals(0 | 45 | bb_signals(0 |
45 | + (1 << SIGUSR1) | 46 | + (1 << SIGUSR1) |
@@ -61,20 +62,20 @@ void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd) | |||
61 | pfds[1].fd = extra_fd; | 62 | pfds[1].fd = extra_fd; |
62 | pfds[1].events = POLLIN; | 63 | pfds[1].events = POLLIN; |
63 | } | 64 | } |
65 | /* this simplifies "is extra_fd ready?" tests elsewhere: */ | ||
66 | pfds[1].revents = 0; | ||
64 | } | 67 | } |
65 | 68 | ||
66 | /* Read a signal from the signal pipe. Returns 0 if there is | 69 | /* Read a signal from the signal pipe. Returns 0 if there is |
67 | * no signal, -1 on error (and sets errno appropriately), and | 70 | * no signal, -1 on error (and sets errno appropriately), and |
68 | * your signal on success */ | 71 | * your signal on success */ |
69 | int FAST_FUNC udhcp_sp_read(struct pollfd pfds[2]) | 72 | int FAST_FUNC udhcp_sp_read(void) |
70 | { | 73 | { |
71 | unsigned char sig; | 74 | unsigned char sig; |
72 | 75 | ||
73 | if (!pfds[0].revents) | 76 | /* Can't block here, fd is in nonblocking mode */ |
74 | return 0; | ||
75 | |||
76 | if (safe_read(signal_pipe.rd, &sig, 1) != 1) | 77 | if (safe_read(signal_pipe.rd, &sig, 1) != 1) |
77 | return -1; | 78 | return 0; |
78 | 79 | ||
79 | return sig; | 80 | return sig; |
80 | } | 81 | } |
diff --git a/networking/wget.c b/networking/wget.c index b9225fac0..150bc8e12 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -1017,7 +1017,6 @@ static void download_one_url(const char *url) | |||
1017 | len_and_sockaddr *lsa; | 1017 | len_and_sockaddr *lsa; |
1018 | FILE *sfp; /* socket to web/ftp server */ | 1018 | FILE *sfp; /* socket to web/ftp server */ |
1019 | FILE *dfp; /* socket to ftp server (data) */ | 1019 | FILE *dfp; /* socket to ftp server (data) */ |
1020 | char *proxy = NULL; | ||
1021 | char *fname_out_alloc; | 1020 | char *fname_out_alloc; |
1022 | char *redirected_path = NULL; | 1021 | char *redirected_path = NULL; |
1023 | struct host_info server; | 1022 | struct host_info server; |
@@ -1033,13 +1032,14 @@ static void download_one_url(const char *url) | |||
1033 | /* Use the proxy if necessary */ | 1032 | /* Use the proxy if necessary */ |
1034 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); | 1033 | use_proxy = (strcmp(G.proxy_flag, "off") != 0); |
1035 | if (use_proxy) { | 1034 | if (use_proxy) { |
1036 | proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); | 1035 | char *proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); |
1037 | //FIXME: what if protocol is https? Ok to use http_proxy? | 1036 | //FIXME: what if protocol is https? Ok to use http_proxy? |
1038 | use_proxy = (proxy && proxy[0]); | 1037 | use_proxy = (proxy && proxy[0]); |
1039 | if (use_proxy) | 1038 | if (use_proxy) |
1040 | parse_url(proxy, &server); | 1039 | parse_url(proxy, &server); |
1041 | } | 1040 | } |
1042 | if (!use_proxy) { | 1041 | if (!use_proxy) { |
1042 | server.protocol = target.protocol; | ||
1043 | server.port = target.port; | 1043 | server.port = target.port; |
1044 | if (ENABLE_FEATURE_IPV6) { | 1044 | if (ENABLE_FEATURE_IPV6) { |
1045 | //free(server.allocated); - can't be non-NULL | 1045 | //free(server.allocated); - can't be non-NULL |
@@ -1104,7 +1104,7 @@ static void download_one_url(const char *url) | |||
1104 | /* Open socket to http(s) server */ | 1104 | /* Open socket to http(s) server */ |
1105 | #if ENABLE_FEATURE_WGET_OPENSSL | 1105 | #if ENABLE_FEATURE_WGET_OPENSSL |
1106 | /* openssl (and maybe internal TLS) support is configured */ | 1106 | /* openssl (and maybe internal TLS) support is configured */ |
1107 | if (target.protocol == P_HTTPS) { | 1107 | if (server.protocol == P_HTTPS) { |
1108 | /* openssl-based helper | 1108 | /* openssl-based helper |
1109 | * Inconvenient API since we can't give it an open fd | 1109 | * Inconvenient API since we can't give it an open fd |
1110 | */ | 1110 | */ |
@@ -1128,7 +1128,7 @@ static void download_one_url(const char *url) | |||
1128 | #elif ENABLE_FEATURE_WGET_HTTPS | 1128 | #elif ENABLE_FEATURE_WGET_HTTPS |
1129 | /* Only internal TLS support is configured */ | 1129 | /* Only internal TLS support is configured */ |
1130 | sfp = open_socket(lsa); | 1130 | sfp = open_socket(lsa); |
1131 | if (target.protocol == P_HTTPS) | 1131 | if (server.protocol == P_HTTPS) |
1132 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); | 1132 | spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); |
1133 | #else | 1133 | #else |
1134 | /* ssl (https) support is not configured */ | 1134 | /* ssl (https) support is not configured */ |