diff options
author | Ron Yorston <rmy@pobox.com> | 2021-01-14 13:28:49 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-01-14 13:28:49 +0000 |
commit | 89963b524d211e1aec12b72b3725be05ee95c8cf (patch) | |
tree | 48590aef62b7ee7686b7898256f29def8d9c50b9 /networking | |
parent | 9aa5a829070392c2ac6494d0c4e674c0c2bc7dab (diff) | |
parent | 2b7c1aa92c68524559a2067609d09309d5c09adc (diff) | |
download | busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.gz busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.bz2 busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
39 files changed, 804 insertions, 670 deletions
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 7b6b89057..f1d5ca571 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c | |||
@@ -43,7 +43,7 @@ | |||
43 | //usage: "\n -v Verbose" | 43 | //usage: "\n -v Verbose" |
44 | //usage: "\n -u USER Username" | 44 | //usage: "\n -u USER Username" |
45 | //usage: "\n -p PASS Password" | 45 | //usage: "\n -p PASS Password" |
46 | //usage: "\n -P NUM Port" | 46 | //usage: "\n -P PORT" |
47 | //usage: | 47 | //usage: |
48 | //usage:#define ftpput_trivial_usage | 48 | //usage:#define ftpput_trivial_usage |
49 | //usage: "[OPTIONS] HOST [REMOTE_FILE] LOCAL_FILE" | 49 | //usage: "[OPTIONS] HOST [REMOTE_FILE] LOCAL_FILE" |
@@ -52,7 +52,7 @@ | |||
52 | //usage: "\n -v Verbose" | 52 | //usage: "\n -v Verbose" |
53 | //usage: "\n -u USER Username" | 53 | //usage: "\n -u USER Username" |
54 | //usage: "\n -p PASS Password" | 54 | //usage: "\n -p PASS Password" |
55 | //usage: "\n -P NUM Port number" | 55 | //usage: "\n -P PORT" |
56 | 56 | ||
57 | #include "libbb.h" | 57 | #include "libbb.h" |
58 | #include "common_bufsiz.h" | 58 | #include "common_bufsiz.h" |
diff --git a/networking/hostname.c b/networking/hostname.c index f96daed95..549103485 100644 --- a/networking/hostname.c +++ b/networking/hostname.c | |||
@@ -29,9 +29,9 @@ | |||
29 | //kbuild: lib-$(CONFIG_DNSDOMAINNAME) += hostname.o | 29 | //kbuild: lib-$(CONFIG_DNSDOMAINNAME) += hostname.o |
30 | 30 | ||
31 | //usage:#define hostname_trivial_usage | 31 | //usage:#define hostname_trivial_usage |
32 | //usage: "[OPTIONS] [HOSTNAME | -F FILE]" | 32 | //usage: "[-sidf] [HOSTNAME | -F FILE]" |
33 | //usage:#define hostname_full_usage "\n\n" | 33 | //usage:#define hostname_full_usage "\n\n" |
34 | //usage: "Get or set hostname or DNS domain name\n" | 34 | //usage: "Show or set hostname or DNS domain name\n" |
35 | //usage: "\n -s Short" | 35 | //usage: "\n -s Short" |
36 | //usage: "\n -i Addresses for the hostname" | 36 | //usage: "\n -i Addresses for the hostname" |
37 | //usage: "\n -d DNS domain name" | 37 | //usage: "\n -d DNS domain name" |
diff --git a/networking/httpd.c b/networking/httpd.c index daa3ca1d0..02f544593 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -305,6 +305,11 @@ | |||
305 | # include <sys/sendfile.h> | 305 | # include <sys/sendfile.h> |
306 | #endif | 306 | #endif |
307 | 307 | ||
308 | /* see sys/netinet6/in6.h */ | ||
309 | #if defined(__FreeBSD__) | ||
310 | # define s6_addr32 __u6_addr.__u6_addr32 | ||
311 | #endif | ||
312 | |||
308 | #define DEBUG 0 | 313 | #define DEBUG 0 |
309 | 314 | ||
310 | #define IOBUF_SIZE 8192 | 315 | #define IOBUF_SIZE 8192 |
@@ -1036,48 +1041,9 @@ static char *encodeString(const char *string) | |||
1036 | * Parameter: a pointer to a base64 encoded string. | 1041 | * Parameter: a pointer to a base64 encoded string. |
1037 | * Decoded data is stored in-place. | 1042 | * Decoded data is stored in-place. |
1038 | */ | 1043 | */ |
1039 | static void decodeBase64(char *Data) | 1044 | static void decodeBase64(char *data) |
1040 | { | 1045 | { |
1041 | # if ENABLE_BASE64 || ENABLE_UUDECODE | 1046 | decode_base64(data, NULL)[0] = '\0'; |
1042 | /* Call decode_base64() from uuencode.c */ | ||
1043 | char *eptr = Data; | ||
1044 | decode_base64(&eptr, Data); | ||
1045 | *eptr = '\0'; | ||
1046 | # else | ||
1047 | const unsigned char *in = (const unsigned char *)Data; | ||
1048 | /* The decoded size will be at most 3/4 the size of the encoded */ | ||
1049 | unsigned ch = 0; | ||
1050 | int i = 0; | ||
1051 | |||
1052 | while (*in) { | ||
1053 | int t = *in++; | ||
1054 | |||
1055 | if (t >= '0' && t <= '9') | ||
1056 | t = t - '0' + 52; | ||
1057 | else if (t >= 'A' && t <= 'Z') | ||
1058 | t = t - 'A'; | ||
1059 | else if (t >= 'a' && t <= 'z') | ||
1060 | t = t - 'a' + 26; | ||
1061 | else if (t == '+') | ||
1062 | t = 62; | ||
1063 | else if (t == '/') | ||
1064 | t = 63; | ||
1065 | else if (t == '=') | ||
1066 | t = 0; | ||
1067 | else | ||
1068 | continue; | ||
1069 | |||
1070 | ch = (ch << 6) | t; | ||
1071 | i++; | ||
1072 | if (i == 4) { | ||
1073 | *Data++ = (char) (ch >> 16); | ||
1074 | *Data++ = (char) (ch >> 8); | ||
1075 | *Data++ = (char) ch; | ||
1076 | i = 0; | ||
1077 | } | ||
1078 | } | ||
1079 | *Data = '\0'; | ||
1080 | # endif | ||
1081 | } | 1047 | } |
1082 | #endif | 1048 | #endif |
1083 | 1049 | ||
@@ -1945,7 +1911,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1945 | send_headers(HTTP_OK); | 1911 | send_headers(HTTP_OK); |
1946 | #if ENABLE_FEATURE_USE_SENDFILE | 1912 | #if ENABLE_FEATURE_USE_SENDFILE |
1947 | { | 1913 | { |
1948 | off_t offset = range_start; | 1914 | off_t offset = (range_start < 0) ? 0 : range_start; |
1949 | while (1) { | 1915 | while (1) { |
1950 | /* sz is rounded down to 64k */ | 1916 | /* sz is rounded down to 64k */ |
1951 | ssize_t sz = MAXINT(ssize_t) - 0xffff; | 1917 | ssize_t sz = MAXINT(ssize_t) - 0xffff; |
@@ -2590,8 +2556,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2590 | if (STRNCASECMP(iobuf, "Range:") == 0) { | 2556 | if (STRNCASECMP(iobuf, "Range:") == 0) { |
2591 | /* We know only bytes=NNN-[MMM] */ | 2557 | /* We know only bytes=NNN-[MMM] */ |
2592 | char *s = skip_whitespace(iobuf + sizeof("Range:")-1); | 2558 | char *s = skip_whitespace(iobuf + sizeof("Range:")-1); |
2593 | if (is_prefixed_with(s, "bytes=")) { | 2559 | s = is_prefixed_with(s, "bytes="); |
2594 | s += sizeof("bytes=")-1; | 2560 | if (s) { |
2595 | range_start = BB_STRTOOFF(s, &s, 10); | 2561 | range_start = BB_STRTOOFF(s, &s, 10); |
2596 | if (s[0] != '-' || range_start < 0) { | 2562 | if (s[0] != '-' || range_start < 0) { |
2597 | range_start = -1; | 2563 | range_start = -1; |
diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 3c9a2dfb3..9ee232a66 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c | |||
@@ -76,7 +76,7 @@ | |||
76 | //kbuild:lib-$(CONFIG_IFCONFIG) += ifconfig.o interface.o | 76 | //kbuild:lib-$(CONFIG_IFCONFIG) += ifconfig.o interface.o |
77 | 77 | ||
78 | //usage:#define ifconfig_trivial_usage | 78 | //usage:#define ifconfig_trivial_usage |
79 | //usage: IF_FEATURE_IFCONFIG_STATUS("[-a]") " interface [address]" | 79 | //usage: IF_FEATURE_IFCONFIG_STATUS("[-a]") " [IFACE] [ADDRESS]" |
80 | //usage:#define ifconfig_full_usage "\n\n" | 80 | //usage:#define ifconfig_full_usage "\n\n" |
81 | //usage: "Configure a network interface\n" | 81 | //usage: "Configure a network interface\n" |
82 | //usage: "\n" | 82 | //usage: "\n" |
@@ -247,7 +247,7 @@ struct options { | |||
247 | * Set up the tables. Warning! They must have corresponding order! | 247 | * Set up the tables. Warning! They must have corresponding order! |
248 | */ | 248 | */ |
249 | 249 | ||
250 | static const struct arg1opt Arg1Opt[] = { | 250 | static const struct arg1opt Arg1Opt[] ALIGN_PTR = { |
251 | { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) }, | 251 | { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) }, |
252 | { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) }, | 252 | { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) }, |
253 | { "SIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen) }, | 253 | { "SIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen) }, |
@@ -277,7 +277,7 @@ static const struct arg1opt Arg1Opt[] = { | |||
277 | { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, | 277 | { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static const struct options OptArray[] = { | 280 | static const struct options OptArray[] ALIGN_PTR = { |
281 | { "metric", N_ARG, ARG_METRIC, 0 }, | 281 | { "metric", N_ARG, ARG_METRIC, 0 }, |
282 | { "mtu", N_ARG, ARG_MTU, 0 }, | 282 | { "mtu", N_ARG, ARG_MTU, 0 }, |
283 | { "txqueuelen", N_ARG, ARG_TXQUEUELEN, 0 }, | 283 | { "txqueuelen", N_ARG, ARG_TXQUEUELEN, 0 }, |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 0d17b7d8c..18dcaff96 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -304,7 +304,7 @@ static const char api_modes[] ALIGN1 = "empwia"; | |||
304 | static const struct { | 304 | static const struct { |
305 | const char *name; | 305 | const char *name; |
306 | smallint (*func)(void); | 306 | smallint (*func)(void); |
307 | } method_table[] = { | 307 | } method_table[] ALIGN_PTR = { |
308 | { "SIOCETHTOOL" , &detect_link_ethtool }, | 308 | { "SIOCETHTOOL" , &detect_link_ethtool }, |
309 | { "SIOCGMIIPHY" , &detect_link_mii }, | 309 | { "SIOCGMIIPHY" , &detect_link_mii }, |
310 | { "SIOCDEVPRIVATE" , &detect_link_priv }, | 310 | { "SIOCDEVPRIVATE" , &detect_link_priv }, |
@@ -735,7 +735,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
735 | delay_time += G.delay_down; | 735 | delay_time += G.delay_down; |
736 | #if 0 /* if you are back in 1970... */ | 736 | #if 0 /* if you are back in 1970... */ |
737 | if (delay_time == 0) { | 737 | if (delay_time == 0) { |
738 | sleep(1); | 738 | sleep1(); |
739 | delay_time = 1; | 739 | delay_time = 1; |
740 | } | 740 | } |
741 | #endif | 741 | #endif |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 60ceb5a1f..737113dd4 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -113,30 +113,30 @@ | |||
113 | //kbuild:lib-$(CONFIG_IFDOWN) += ifupdown.o | 113 | //kbuild:lib-$(CONFIG_IFDOWN) += ifupdown.o |
114 | 114 | ||
115 | //usage:#define ifup_trivial_usage | 115 | //usage:#define ifup_trivial_usage |
116 | //usage: "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." | 116 | //usage: "[-n"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] -a | IFACE..." |
117 | //usage:#define ifup_full_usage "\n\n" | 117 | //usage:#define ifup_full_usage "\n\n" |
118 | //usage: " -a Configure all interfaces" | 118 | //usage: " -a Configure all interfaces" |
119 | //usage: "\n -i FILE Use FILE instead of /etc/network/interfaces" | 119 | //usage: "\n -i FILE Use FILE instead of /etc/network/interfaces" |
120 | //usage: "\n -n Print out what would happen, but don't do it" | 120 | //usage: "\n -n Dry run" |
121 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( | 121 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( |
122 | //usage: "\n (note: doesn't disable mappings)" | 122 | //usage: "\n (note: doesn't disable mappings)" |
123 | //usage: "\n -m Don't run any mappings" | 123 | //usage: "\n -m Don't run any mappings" |
124 | //usage: ) | 124 | //usage: ) |
125 | //usage: "\n -v Print out what would happen before doing it" | 125 | //usage: "\n -v Print out what would happen before doing it" |
126 | //usage: "\n -f Force configuration" | 126 | //usage: "\n -f Force" |
127 | //usage: | 127 | //usage: |
128 | //usage:#define ifdown_trivial_usage | 128 | //usage:#define ifdown_trivial_usage |
129 | //usage: "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." | 129 | //usage: "[-n"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] -a | IFACE..." |
130 | //usage:#define ifdown_full_usage "\n\n" | 130 | //usage:#define ifdown_full_usage "\n\n" |
131 | //usage: " -a Deconfigure all interfaces" | 131 | //usage: " -a Deconfigure all interfaces" |
132 | //usage: "\n -i FILE Use FILE for interface definitions" | 132 | //usage: "\n -i FILE Use FILE instead of /etc/network/interfaces" |
133 | //usage: "\n -n Print out what would happen, but don't do it" | 133 | //usage: "\n -n Dry run" |
134 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( | 134 | //usage: IF_FEATURE_IFUPDOWN_MAPPING( |
135 | //usage: "\n (note: doesn't disable mappings)" | 135 | //usage: "\n (note: doesn't disable mappings)" |
136 | //usage: "\n -m Don't run any mappings" | 136 | //usage: "\n -m Don't run any mappings" |
137 | //usage: ) | 137 | //usage: ) |
138 | //usage: "\n -v Print out what would happen before doing it" | 138 | //usage: "\n -v Print out what would happen before doing it" |
139 | //usage: "\n -f Force deconfiguration" | 139 | //usage: "\n -f Force" |
140 | 140 | ||
141 | #include <net/if.h> | 141 | #include <net/if.h> |
142 | #include "libbb.h" | 142 | #include "libbb.h" |
@@ -1357,15 +1357,15 @@ static FILE *open_new_state_file(void) | |||
1357 | IFSTATE_FILE_PATH".new"); | 1357 | IFSTATE_FILE_PATH".new"); |
1358 | } | 1358 | } |
1359 | /* Someone else created the .new file */ | 1359 | /* Someone else created the .new file */ |
1360 | if (cnt > 30 * 1000) { | 1360 | if (cnt > 30) { |
1361 | /* Waited for 30*30/2 = 450 milliseconds, still EEXIST. | 1361 | /* Waited for 30*30/2 = 450 milliseconds, still EEXIST. |
1362 | * Assuming a stale file, rewriting it. | 1362 | * Assuming a stale file, rewriting it. |
1363 | */ | 1363 | */ |
1364 | flags = (O_WRONLY | O_CREAT | O_TRUNC); | 1364 | flags = (O_WRONLY | O_CREAT | O_TRUNC); |
1365 | continue; | 1365 | continue; |
1366 | } | 1366 | } |
1367 | usleep(cnt); | 1367 | msleep(cnt); |
1368 | cnt += 1000; | 1368 | cnt++; |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | return xfdopen_for_write(fd); | 1371 | return xfdopen_for_write(fd); |
diff --git a/networking/inetd.c b/networking/inetd.c index 3cd2b11f0..febfb7b73 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -361,7 +361,7 @@ struct builtin { | |||
361 | void (*bi_dgram_fn)(int, servtab_t *) FAST_FUNC; | 361 | void (*bi_dgram_fn)(int, servtab_t *) FAST_FUNC; |
362 | }; | 362 | }; |
363 | 363 | ||
364 | static const struct builtin builtins[] = { | 364 | static const struct builtin builtins[] ALIGN_PTR = { |
365 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 365 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
366 | { "echo", 1, echo_stream, echo_dg }, | 366 | { "echo", 1, echo_stream, echo_dg }, |
367 | #endif | 367 | #endif |
@@ -1305,7 +1305,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) | |||
1305 | if (ready_fd_cnt < 0) { | 1305 | if (ready_fd_cnt < 0) { |
1306 | if (errno != EINTR) { | 1306 | if (errno != EINTR) { |
1307 | bb_simple_perror_msg("select"); | 1307 | bb_simple_perror_msg("select"); |
1308 | sleep(1); | 1308 | sleep1(); |
1309 | } | 1309 | } |
1310 | continue; | 1310 | continue; |
1311 | } | 1311 | } |
@@ -1406,7 +1406,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) | |||
1406 | 1406 | ||
1407 | if (pid < 0) { /* fork error */ | 1407 | if (pid < 0) { /* fork error */ |
1408 | bb_simple_perror_msg("vfork"+1); | 1408 | bb_simple_perror_msg("vfork"+1); |
1409 | sleep(1); | 1409 | sleep1(); |
1410 | restore_sigmask(&omask); | 1410 | restore_sigmask(&omask); |
1411 | maybe_close(new_udp_fd); | 1411 | maybe_close(new_udp_fd); |
1412 | maybe_close(accepted_fd); | 1412 | maybe_close(accepted_fd); |
@@ -1701,7 +1701,7 @@ static uint32_t machtime(void) | |||
1701 | { | 1701 | { |
1702 | struct timeval tv; | 1702 | struct timeval tv; |
1703 | 1703 | ||
1704 | gettimeofday(&tv, NULL); | 1704 | xgettimeofday(&tv); |
1705 | return htonl((uint32_t)(tv.tv_sec + 2208988800U)); | 1705 | return htonl((uint32_t)(tv.tv_sec + 2208988800U)); |
1706 | } | 1706 | } |
1707 | /* ARGSUSED */ | 1707 | /* ARGSUSED */ |
diff --git a/networking/interface.c b/networking/interface.c index e5e55d8d4..ea6a2c8a8 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
@@ -746,7 +746,7 @@ static const struct hwtype *const hwtypes[] = { | |||
746 | }; | 746 | }; |
747 | 747 | ||
748 | #ifdef IFF_PORTSEL | 748 | #ifdef IFF_PORTSEL |
749 | static const char *const if_port_text[] = { | 749 | static const char *const if_port_text[] ALIGN_PTR = { |
750 | /* Keep in step with <linux/netdevice.h> */ | 750 | /* Keep in step with <linux/netdevice.h> */ |
751 | "unknown", | 751 | "unknown", |
752 | "10base2", | 752 | "10base2", |
diff --git a/networking/ip.c b/networking/ip.c index 33bea5f49..85b1ba080 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -400,7 +400,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv) | |||
400 | IF_FEATURE_IP_RULE("rule\0") | 400 | IF_FEATURE_IP_RULE("rule\0") |
401 | IF_FEATURE_IP_NEIGH("neigh\0") | 401 | IF_FEATURE_IP_NEIGH("neigh\0") |
402 | ; | 402 | ; |
403 | static const ip_func_ptr_t ip_func_ptrs[] = { | 403 | static const ip_func_ptr_t ip_func_ptrs[] ALIGN_PTR = { |
404 | ip_print_help, | 404 | ip_print_help, |
405 | IF_FEATURE_IP_ADDRESS(do_ipaddr,) | 405 | IF_FEATURE_IP_ADDRESS(do_ipaddr,) |
406 | IF_FEATURE_IP_ROUTE(do_iproute,) | 406 | IF_FEATURE_IP_ROUTE(do_iproute,) |
diff --git a/networking/ipcalc.c b/networking/ipcalc.c index 09b146872..e82e35dd5 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c | |||
@@ -36,7 +36,7 @@ | |||
36 | //kbuild:lib-$(CONFIG_IPCALC) += ipcalc.o | 36 | //kbuild:lib-$(CONFIG_IPCALC) += ipcalc.o |
37 | 37 | ||
38 | //usage:#define ipcalc_trivial_usage | 38 | //usage:#define ipcalc_trivial_usage |
39 | //usage: "[OPTIONS] ADDRESS" | 39 | //usage: "[-bnm"IF_FEATURE_IPCALC_FANCY("phs")"] ADDRESS" |
40 | //usage: IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]" | 40 | //usage: IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]" |
41 | //usage:#define ipcalc_full_usage "\n\n" | 41 | //usage:#define ipcalc_full_usage "\n\n" |
42 | //usage: "Calculate and display network settings from IP address\n" | 42 | //usage: "Calculate and display network settings from IP address\n" |
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 71e8fb6a7..dfd84c000 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -21,6 +21,17 @@ | |||
21 | #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ | 21 | #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | /* for old uclibc */ | ||
25 | #ifndef IFA_F_NOPREFIXROUTE | ||
26 | # define IFA_FLAGS 8 | ||
27 | # define IFA_F_NOPREFIXROUTE 0x200 | ||
28 | enum { /* can't do this with preporcessor, IFA_MAX is an (enum - 1), not preprocessor constant */ | ||
29 | REAL_IFA_MAX = (IFA_MAX >= IFA_FLAGS) ? IFA_MAX : IFA_FLAGS, | ||
30 | }; | ||
31 | # undef IFA_MAX | ||
32 | # define IFA_MAX REAL_IFA_MAX | ||
33 | #endif | ||
34 | |||
24 | struct filter_t { | 35 | struct filter_t { |
25 | char *label; | 36 | char *label; |
26 | /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */ | 37 | /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */ |
diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c index 51f2e9bdb..3c2fad912 100644 --- a/networking/libiproute/rt_names.c +++ b/networking/libiproute/rt_names.c | |||
@@ -77,7 +77,7 @@ static rtnl_tab_t *rtnl_rtprot_tab; | |||
77 | 77 | ||
78 | static void rtnl_rtprot_initialize(void) | 78 | static void rtnl_rtprot_initialize(void) |
79 | { | 79 | { |
80 | static const char *const init_tab[] = { | 80 | static const char *const init_tab[] ALIGN_PTR = { |
81 | "none", | 81 | "none", |
82 | "redirect", | 82 | "redirect", |
83 | "kernel", | 83 | "kernel", |
diff --git a/networking/libiproute/rtm_map.c b/networking/libiproute/rtm_map.c index e94c99ab6..8b94c2f24 100644 --- a/networking/libiproute/rtm_map.c +++ b/networking/libiproute/rtm_map.c | |||
@@ -11,33 +11,55 @@ | |||
11 | #include "rt_names.h" | 11 | #include "rt_names.h" |
12 | #include "utils.h" | 12 | #include "utils.h" |
13 | 13 | ||
14 | static const char keywords[] ALIGN1 = | ||
15 | "local\0""nat\0""broadcast\0""brd\0""anycast\0" | ||
16 | "multicast\0""prohibit\0""unreachable\0""blackhole\0" | ||
17 | "xresolve\0""unicast\0""throw\0"; | ||
18 | enum { | ||
19 | ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast, | ||
20 | ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole, | ||
21 | ARG_xresolve, ARG_unicast, ARG_throw | ||
22 | }; | ||
23 | #define str_local keywords | ||
24 | #define str_nat (str_local + sizeof("local")) | ||
25 | #define str_broadcast (str_nat + sizeof("nat")) | ||
26 | #define str_brd (str_broadcast + sizeof("broadcast")) | ||
27 | #define str_anycast (str_brd + sizeof("brd")) | ||
28 | #define str_multicast (str_anycast + sizeof("anycast")) | ||
29 | #define str_prohibit (str_multicast + sizeof("multicast")) | ||
30 | #define str_unreachable (str_prohibit + sizeof("prohibit")) | ||
31 | #define str_blackhole (str_unreachable + sizeof("unreachable")) | ||
32 | #define str_xresolve (str_blackhole + sizeof("blackhole")) | ||
33 | #define str_unicast (str_xresolve + sizeof("xresolve")) | ||
34 | #define str_throw (str_unicast + sizeof("unicast")) | ||
35 | |||
14 | const char* FAST_FUNC rtnl_rtntype_n2a(int id) | 36 | const char* FAST_FUNC rtnl_rtntype_n2a(int id) |
15 | { | 37 | { |
16 | switch (id) { | 38 | switch (id) { |
17 | case RTN_UNSPEC: | 39 | case RTN_UNSPEC: |
18 | return "none"; | 40 | return "none"; |
19 | case RTN_UNICAST: | 41 | case RTN_UNICAST: |
20 | return "unicast"; | 42 | return str_unicast; |
21 | case RTN_LOCAL: | 43 | case RTN_LOCAL: |
22 | return "local"; | 44 | return str_local; |
23 | case RTN_BROADCAST: | 45 | case RTN_BROADCAST: |
24 | return "broadcast"; | 46 | return str_broadcast; |
25 | case RTN_ANYCAST: | 47 | case RTN_ANYCAST: |
26 | return "anycast"; | 48 | return str_anycast; |
27 | case RTN_MULTICAST: | 49 | case RTN_MULTICAST: |
28 | return "multicast"; | 50 | return str_multicast; |
29 | case RTN_BLACKHOLE: | 51 | case RTN_BLACKHOLE: |
30 | return "blackhole"; | 52 | return str_blackhole; |
31 | case RTN_UNREACHABLE: | 53 | case RTN_UNREACHABLE: |
32 | return "unreachable"; | 54 | return str_unreachable; |
33 | case RTN_PROHIBIT: | 55 | case RTN_PROHIBIT: |
34 | return "prohibit"; | 56 | return str_prohibit; |
35 | case RTN_THROW: | 57 | case RTN_THROW: |
36 | return "throw"; | 58 | return str_throw; |
37 | case RTN_NAT: | 59 | case RTN_NAT: |
38 | return "nat"; | 60 | return str_nat; |
39 | case RTN_XRESOLVE: | 61 | case RTN_XRESOLVE: |
40 | return "xresolve"; | 62 | return str_xresolve; |
41 | default: | 63 | default: |
42 | return itoa(id); | 64 | return itoa(id); |
43 | } | 65 | } |
@@ -45,15 +67,6 @@ const char* FAST_FUNC rtnl_rtntype_n2a(int id) | |||
45 | 67 | ||
46 | int FAST_FUNC rtnl_rtntype_a2n(int *id, char *arg) | 68 | int FAST_FUNC rtnl_rtntype_a2n(int *id, char *arg) |
47 | { | 69 | { |
48 | static const char keywords[] ALIGN1 = | ||
49 | "local\0""nat\0""broadcast\0""brd\0""anycast\0" | ||
50 | "multicast\0""prohibit\0""unreachable\0""blackhole\0" | ||
51 | "xresolve\0""unicast\0""throw\0"; | ||
52 | enum { | ||
53 | ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast, | ||
54 | ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole, | ||
55 | ARG_xresolve, ARG_unicast, ARG_throw | ||
56 | }; | ||
57 | const smalluint key = index_in_substrings(keywords, arg) + 1; | 70 | const smalluint key = index_in_substrings(keywords, arg) + 1; |
58 | char *end; | 71 | char *end; |
59 | unsigned long res; | 72 | unsigned long res; |
diff --git a/networking/nbd-client.c b/networking/nbd-client.c index 3db3b46f9..755b42ccd 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c | |||
@@ -270,7 +270,7 @@ int nbdclient_main(int argc, char **argv) | |||
270 | close(fd); | 270 | close(fd); |
271 | break; | 271 | break; |
272 | } | 272 | } |
273 | sleep(1); | 273 | sleep1(); |
274 | } | 274 | } |
275 | open(device, O_RDONLY); | 275 | open(device, O_RDONLY); |
276 | return 0; | 276 | return 0; |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 88eda6b28..25b95246f 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -196,7 +196,7 @@ enum { | |||
196 | /* Debug: squirt whatever message and sleep a bit so we can see it go by. */ | 196 | /* Debug: squirt whatever message and sleep a bit so we can see it go by. */ |
197 | /* Beware: writes to stdOUT... */ | 197 | /* Beware: writes to stdOUT... */ |
198 | #if 0 | 198 | #if 0 |
199 | #define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep(1); } while (0) | 199 | #define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep1(); } while (0) |
200 | #else | 200 | #else |
201 | #define Debug(...) do { } while (0) | 201 | #define Debug(...) do { } while (0) |
202 | #endif | 202 | #endif |
diff --git a/networking/netstat.c b/networking/netstat.c index 3ab7b0d21..807800a62 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -114,7 +114,7 @@ enum { | |||
114 | TCP_CLOSING, /* now a valid state */ | 114 | TCP_CLOSING, /* now a valid state */ |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static const char *const tcp_state[] = { | 117 | static const char *const tcp_state[] ALIGN_PTR = { |
118 | "", | 118 | "", |
119 | "ESTABLISHED", | 119 | "ESTABLISHED", |
120 | "SYN_SENT", | 120 | "SYN_SENT", |
diff --git a/networking/nslookup.c b/networking/nslookup.c index 759de5c83..c43ad46f3 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
@@ -273,7 +273,7 @@ struct query { | |||
273 | static const struct { | 273 | static const struct { |
274 | unsigned char type; | 274 | unsigned char type; |
275 | char name[7]; | 275 | char name[7]; |
276 | } qtypes[] = { | 276 | } qtypes[] ALIGN1 = { |
277 | { ns_t_soa, "SOA" }, | 277 | { ns_t_soa, "SOA" }, |
278 | { ns_t_ns, "NS" }, | 278 | { ns_t_ns, "NS" }, |
279 | { ns_t_a, "A" }, | 279 | { ns_t_a, "A" }, |
@@ -288,7 +288,7 @@ static const struct { | |||
288 | { ns_t_any, "ANY" }, | 288 | { ns_t_any, "ANY" }, |
289 | }; | 289 | }; |
290 | 290 | ||
291 | static const char *const rcodes[] = { | 291 | static const char *const rcodes[] ALIGN_PTR = { |
292 | "NOERROR", // 0 | 292 | "NOERROR", // 0 |
293 | "FORMERR", // 1 | 293 | "FORMERR", // 1 |
294 | "SERVFAIL", // 2 | 294 | "SERVFAIL", // 2 |
@@ -349,6 +349,8 @@ static int parse_reply(const unsigned char *msg, size_t len) | |||
349 | header = (HEADER *)msg; | 349 | header = (HEADER *)msg; |
350 | if (!header->aa) | 350 | if (!header->aa) |
351 | printf("Non-authoritative answer:\n"); | 351 | printf("Non-authoritative answer:\n"); |
352 | else if (option_mask32 & OPT_debug) | ||
353 | printf("Non-authoritative answer:\n" + 4); | ||
352 | 354 | ||
353 | if (ns_initparse(msg, len, &handle) != 0) { | 355 | if (ns_initparse(msg, len, &handle) != 0) { |
354 | //printf("Unable to parse reply: %s\n", strerror(errno)); | 356 | //printf("Unable to parse reply: %s\n", strerror(errno)); |
@@ -381,7 +383,7 @@ static int parse_reply(const unsigned char *msg, size_t len) | |||
381 | return -1; | 383 | return -1; |
382 | } | 384 | } |
383 | inet_ntop(AF_INET6, ns_rr_rdata(rr), astr, sizeof(astr)); | 385 | inet_ntop(AF_INET6, ns_rr_rdata(rr), astr, sizeof(astr)); |
384 | /* bind-utils-9.11.3 uses the same format for A and AAAA answers */ | 386 | /* bind-utils 9.11.3 uses the same format for A and AAAA answers */ |
385 | printf("Name:\t%s\nAddress: %s\n", ns_rr_name(rr), astr); | 387 | printf("Name:\t%s\nAddress: %s\n", ns_rr_name(rr), astr); |
386 | break; | 388 | break; |
387 | #endif | 389 | #endif |
@@ -580,7 +582,7 @@ static int send_queries(struct ns *ns) | |||
580 | printf("Address:\t%s\n\n", | 582 | printf("Address:\t%s\n\n", |
581 | auto_string(xmalloc_sockaddr2dotted(&ns->lsa->u.sa)) | 583 | auto_string(xmalloc_sockaddr2dotted(&ns->lsa->u.sa)) |
582 | ); | 584 | ); |
583 | /* In "Address", bind-utils-9.11.3 show port after a hash: "1.2.3.4#53" */ | 585 | /* In "Address", bind-utils 9.11.3 show port after a hash: "1.2.3.4#53" */ |
584 | /* Should we do the same? */ | 586 | /* Should we do the same? */ |
585 | } | 587 | } |
586 | 588 | ||
@@ -640,12 +642,26 @@ static int send_queries(struct ns *ns) | |||
640 | printf("*** Can't find %s: Parse error\n", G.query[qn].name); | 642 | printf("*** Can't find %s: Parse error\n", G.query[qn].name); |
641 | G.exitcode = EXIT_FAILURE; | 643 | G.exitcode = EXIT_FAILURE; |
642 | break; | 644 | break; |
643 | 645 | /* bind-utils 9.11.25 just says nothing in this case */ | |
644 | case 0: | 646 | //case 0: |
645 | printf("*** Can't find %s: No answer\n", G.query[qn].name); | 647 | // break; |
646 | break; | ||
647 | } | 648 | } |
648 | } | 649 | } |
650 | /* NB: in case of authoritative, empty answer (NODATA), IOW: one with | ||
651 | * ns_msg_count() == 0, bind-utils 9.11.25 shows no trace of this answer | ||
652 | * (unless -debug, where it says: | ||
653 | * ------------ | ||
654 | * QUESTIONS: | ||
655 | * host.com, type = AAAA, class = IN | ||
656 | * ANSWERS: | ||
657 | * AUTHORITY RECORDS: | ||
658 | * ADDITIONAL RECORDS: | ||
659 | * ------------ | ||
660 | * ). Due to printing of below '\n', we do show an additional empty line. | ||
661 | * This is better than not showing any indication of this reply at all, | ||
662 | * yet maintains "compatibility". I wonder whether it's better to break compat | ||
663 | * and emit something more meaningful, e.g. print "Empty answer (NODATA)"? | ||
664 | */ | ||
649 | bb_putchar('\n'); | 665 | bb_putchar('\n'); |
650 | n_replies++; | 666 | n_replies++; |
651 | if (n_replies >= G.query_count) | 667 | if (n_replies >= G.query_count) |
@@ -697,7 +713,7 @@ static void parse_resolvconf(void) | |||
697 | { | 713 | { |
698 | FILE *resolv; | 714 | FILE *resolv; |
699 | 715 | ||
700 | resolv = fopen("/etc/resolv.conf", "r"); | 716 | resolv = fopen_for_read("/etc/resolv.conf"); |
701 | if (resolv) { | 717 | if (resolv) { |
702 | char line[512]; /* "search" is defined to be up to 256 chars */ | 718 | char line[512]; /* "search" is defined to be up to 256 chars */ |
703 | 719 | ||
diff --git a/networking/ntpd.c b/networking/ntpd.c index 44e711232..1f17b08ef 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -77,7 +77,7 @@ | |||
77 | //usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...") | 77 | //usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...") |
78 | //usage:#define ntpd_full_usage "\n\n" | 78 | //usage:#define ntpd_full_usage "\n\n" |
79 | //usage: "NTP client/server\n" | 79 | //usage: "NTP client/server\n" |
80 | //usage: "\n -d Verbose (may be repeated)" | 80 | //usage: "\n -d[d] Verbose" |
81 | //usage: "\n -n Do not daemonize" | 81 | //usage: "\n -n Do not daemonize" |
82 | //usage: "\n -q Quit after clock is set" | 82 | //usage: "\n -q Quit after clock is set" |
83 | //usage: "\n -N Run at high priority" | 83 | //usage: "\n -N Run at high priority" |
@@ -113,6 +113,13 @@ | |||
113 | # define IPTOS_DSCP_AF21 0x48 | 113 | # define IPTOS_DSCP_AF21 0x48 |
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | #if defined(__FreeBSD__) | ||
117 | /* see sys/timex.h */ | ||
118 | # define adjtimex ntp_adjtime | ||
119 | # define ADJ_OFFSET MOD_OFFSET | ||
120 | # define ADJ_STATUS MOD_STATUS | ||
121 | # define ADJ_TIMECONST MOD_TIMECONST | ||
122 | #endif | ||
116 | 123 | ||
117 | /* Verbosity control (max level of -dddd options accepted). | 124 | /* Verbosity control (max level of -dddd options accepted). |
118 | * max 6 is very talkative (and bloated). 3 is non-bloated, | 125 | * max 6 is very talkative (and bloated). 3 is non-bloated, |
@@ -560,7 +567,7 @@ static double | |||
560 | gettime1900d(void) | 567 | gettime1900d(void) |
561 | { | 568 | { |
562 | struct timeval tv; | 569 | struct timeval tv; |
563 | gettimeofday(&tv, NULL); /* never fails */ | 570 | xgettimeofday(&tv); |
564 | G.cur_time = tv.tv_sec + (1.0e-6 * tv.tv_usec) + OFFSET_1900_1970; | 571 | G.cur_time = tv.tv_sec + (1.0e-6 * tv.tv_usec) + OFFSET_1900_1970; |
565 | return G.cur_time; | 572 | return G.cur_time; |
566 | } | 573 | } |
@@ -1144,11 +1151,10 @@ step_time(double offset) | |||
1144 | char buf[sizeof("yyyy-mm-dd hh:mm:ss") + /*paranoia:*/ 4]; | 1151 | char buf[sizeof("yyyy-mm-dd hh:mm:ss") + /*paranoia:*/ 4]; |
1145 | time_t tval; | 1152 | time_t tval; |
1146 | 1153 | ||
1147 | gettimeofday(&tvc, NULL); /* never fails */ | 1154 | xgettimeofday(&tvc); |
1148 | dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset; | 1155 | dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset; |
1149 | d_to_tv(dtime, &tvn); | 1156 | d_to_tv(dtime, &tvn); |
1150 | if (settimeofday(&tvn, NULL) == -1) | 1157 | xsettimeofday(&tvn); |
1151 | bb_simple_perror_msg_and_die("settimeofday"); | ||
1152 | 1158 | ||
1153 | VERB2 { | 1159 | VERB2 { |
1154 | tval = tvc.tv_sec; | 1160 | tval = tvc.tv_sec; |
@@ -2462,9 +2468,6 @@ static NOINLINE void ntp_init(char **argv) | |||
2462 | 2468 | ||
2463 | srand(getpid()); | 2469 | srand(getpid()); |
2464 | 2470 | ||
2465 | if (getuid()) | ||
2466 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
2467 | |||
2468 | /* Set some globals */ | 2471 | /* Set some globals */ |
2469 | G.discipline_jitter = G_precision_sec; | 2472 | G.discipline_jitter = G_precision_sec; |
2470 | G.stratum = MAXSTRAT; | 2473 | G.stratum = MAXSTRAT; |
diff --git a/networking/ping.c b/networking/ping.c index 5f7e5b9b5..86d8088de 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -58,16 +58,16 @@ | |||
58 | //usage:# define ping_trivial_usage | 58 | //usage:# define ping_trivial_usage |
59 | //usage: "HOST" | 59 | //usage: "HOST" |
60 | //usage:# define ping_full_usage "\n\n" | 60 | //usage:# define ping_full_usage "\n\n" |
61 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts" | 61 | //usage: "Send ICMP ECHO_REQUESTs to HOST" |
62 | //usage:# define ping6_trivial_usage | 62 | //usage:# define ping6_trivial_usage |
63 | //usage: "HOST" | 63 | //usage: "HOST" |
64 | //usage:# define ping6_full_usage "\n\n" | 64 | //usage:# define ping6_full_usage "\n\n" |
65 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts" | 65 | //usage: "Send ICMP ECHO_REQUESTs to HOST" |
66 | //usage:#else | 66 | //usage:#else |
67 | //usage:# define ping_trivial_usage | 67 | //usage:# define ping_trivial_usage |
68 | //usage: "[OPTIONS] HOST" | 68 | //usage: "[OPTIONS] HOST" |
69 | //usage:# define ping_full_usage "\n\n" | 69 | //usage:# define ping_full_usage "\n\n" |
70 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" | 70 | //usage: "Send ICMP ECHO_REQUESTs to HOST\n" |
71 | //usage: IF_PING6( | 71 | //usage: IF_PING6( |
72 | //usage: "\n -4,-6 Force IP or IPv6 name resolution" | 72 | //usage: "\n -4,-6 Force IP or IPv6 name resolution" |
73 | //usage: ) | 73 | //usage: ) |
@@ -81,22 +81,26 @@ | |||
81 | //usage: "\n (after all -c CNT packets are sent)" | 81 | //usage: "\n (after all -c CNT packets are sent)" |
82 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" | 82 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" |
83 | //usage: "\n (can exit earlier with -c CNT)" | 83 | //usage: "\n (can exit earlier with -c CNT)" |
84 | //usage: "\n -q Quiet, only display output at start" | 84 | //usage: "\n -q Quiet, only display output at start/finish" |
85 | //usage: "\n and when finished" | 85 | //usage: "\n -p HEXBYTE Payload pattern" |
86 | //usage: "\n -p HEXBYTE Pattern to use for payload" | ||
87 | //usage: | 86 | //usage: |
88 | //usage:# define ping6_trivial_usage | 87 | //usage:# define ping6_trivial_usage |
89 | //usage: "[OPTIONS] HOST" | 88 | //usage: "[OPTIONS] HOST" |
90 | //usage:# define ping6_full_usage "\n\n" | 89 | //usage:# define ping6_full_usage "\n\n" |
91 | //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" | 90 | //usage: "Send ICMP ECHO_REQUESTs to HOST\n" |
92 | //usage: "\n -c CNT Send only CNT pings" | 91 | //usage: "\n -c CNT Send only CNT pings" |
93 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" | 92 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" |
94 | //usage: "\n -i SECS Interval" | 93 | //usage: "\n -i SECS Interval" |
95 | //usage: "\n -A Ping as soon as reply is recevied" | 94 | //usage: "\n -A Ping as soon as reply is recevied" |
95 | ///////: "\n -t TTL Set TTL" | ||
96 | ///////^^^^^ -t not tested for IPv6, might be not working | ||
96 | //usage: "\n -I IFACE/IP Source interface or IP address" | 97 | //usage: "\n -I IFACE/IP Source interface or IP address" |
97 | //usage: "\n -q Quiet, only display output at start" | 98 | //usage: "\n -W SEC Seconds to wait for the first response (default 10)" |
98 | //usage: "\n and when finished" | 99 | //usage: "\n (after all -c CNT packets are sent)" |
99 | //usage: "\n -p HEXBYTE Pattern to use for payload" | 100 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" |
101 | //usage: "\n (can exit earlier with -c CNT)" | ||
102 | //usage: "\n -q Quiet, only display output at start/finish" | ||
103 | //usage: "\n -p HEXBYTE Payload pattern" | ||
100 | //usage: | 104 | //usage: |
101 | //usage:#endif | 105 | //usage:#endif |
102 | //usage: | 106 | //usage: |
@@ -118,6 +122,10 @@ | |||
118 | //usage: "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" | 122 | //usage: "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" |
119 | 123 | ||
120 | #include <net/if.h> | 124 | #include <net/if.h> |
125 | #if defined(__FreeBSD__) | ||
126 | # include <netinet/in.h> /* struct ip and friends */ | ||
127 | # include <netinet/ip.h> | ||
128 | #endif | ||
121 | #include <netinet/ip_icmp.h> | 129 | #include <netinet/ip_icmp.h> |
122 | #include "libbb.h" | 130 | #include "libbb.h" |
123 | #include "common_bufsiz.h" | 131 | #include "common_bufsiz.h" |
@@ -156,6 +164,40 @@ | |||
156 | # endif | 164 | # endif |
157 | #endif | 165 | #endif |
158 | 166 | ||
167 | #if defined(__FreeBSD__) | ||
168 | /** | ||
169 | * On BSD the IPv4 struct is called struct ip and instead of iXX | ||
170 | * the members are called ip_XX. One could change this code to use | ||
171 | * struct ip but that would require to define _BSD_SOURCE and that | ||
172 | * might have other complications. Instead make sure struct iphdr | ||
173 | * is present on FreeBSD. The below is taken from GLIBC. | ||
174 | * | ||
175 | * The GNU C Library is free software; you can redistribute it and/or | ||
176 | * modify it under the terms of the GNU Lesser General Public | ||
177 | * License as published by the Free Software Foundation; either | ||
178 | * version 2.1 of the License, or (at your option) any later version. | ||
179 | */ | ||
180 | struct iphdr { | ||
181 | # if BYTE_ORDER == LITTLE_ENDIAN | ||
182 | unsigned int ihl:4; | ||
183 | unsigned int version:4; | ||
184 | # elif BYTE_ORDER == BIG_ENDIAN | ||
185 | unsigned int version:4; | ||
186 | unsigned int ihl:4; | ||
187 | # endif | ||
188 | uint8_t tos; | ||
189 | uint16_t tot_len; | ||
190 | uint16_t id; | ||
191 | uint16_t frag_off; | ||
192 | uint8_t ttl; | ||
193 | uint8_t protocol; | ||
194 | uint16_t check; | ||
195 | uint32_t saddr; | ||
196 | uint32_t daddr; | ||
197 | /*The options start here. */ | ||
198 | }; | ||
199 | #endif | ||
200 | |||
159 | enum { | 201 | enum { |
160 | DEFDATALEN = 56, | 202 | DEFDATALEN = 56, |
161 | MAXIPLEN = 60, | 203 | MAXIPLEN = 60, |
@@ -332,6 +374,11 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
332 | 374 | ||
333 | create_icmp_socket(lsa); | 375 | create_icmp_socket(lsa); |
334 | G.myid = (uint16_t) getpid(); | 376 | G.myid = (uint16_t) getpid(); |
377 | /* we can use native-endian ident, but other Unix ping/traceroute | ||
378 | * utils use *big-endian pid*, and e.g. traceroute on our machine may be | ||
379 | * *not* from busybox, idents may collide. Follow the convention: | ||
380 | */ | ||
381 | G.myid = htons(G.myid); | ||
335 | #if ENABLE_PING6 | 382 | #if ENABLE_PING6 |
336 | if (lsa->u.sa.sa_family == AF_INET6) | 383 | if (lsa->u.sa.sa_family == AF_INET6) |
337 | ping6(lsa); | 384 | ping6(lsa); |
@@ -466,17 +513,16 @@ static void sendping_tail(void (*sp)(int), int size_pkt) | |||
466 | { | 513 | { |
467 | int sz; | 514 | int sz; |
468 | 515 | ||
469 | CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK); | ||
470 | G.ntransmitted++; | ||
471 | |||
472 | size_pkt += datalen; | ||
473 | |||
474 | if (G.deadline_us) { | 516 | if (G.deadline_us) { |
475 | unsigned n = G.cur_us - G.deadline_us; | 517 | unsigned n = G.cur_us - G.deadline_us; |
476 | if ((int)n >= 0) | 518 | if ((int)n >= 0) |
477 | print_stats_and_exit(0); | 519 | print_stats_and_exit(0); |
478 | } | 520 | } |
479 | 521 | ||
522 | CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK); | ||
523 | G.ntransmitted++; | ||
524 | size_pkt += datalen; | ||
525 | |||
480 | /* sizeof(pingaddr) can be larger than real sa size, but I think | 526 | /* sizeof(pingaddr) can be larger than real sa size, but I think |
481 | * it doesn't matter */ | 527 | * it doesn't matter */ |
482 | sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr)); | 528 | sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr)); |
@@ -927,6 +973,11 @@ static int common_ping_main(int opt, char **argv) | |||
927 | G.interval_us = interval * 1000000; | 973 | G.interval_us = interval * 1000000; |
928 | 974 | ||
929 | myid = (uint16_t) getpid(); | 975 | myid = (uint16_t) getpid(); |
976 | /* we can use native-endian ident, but other Unix ping/traceroute | ||
977 | * utils use *big-endian pid*, and e.g. traceroute on our machine may be | ||
978 | * *not* from busybox, idents may collide. Follow the convention: | ||
979 | */ | ||
980 | myid = htons(myid); | ||
930 | hostname = argv[optind]; | 981 | hostname = argv[optind]; |
931 | #if ENABLE_PING6 | 982 | #if ENABLE_PING6 |
932 | { | 983 | { |
diff --git a/networking/pscan.c b/networking/pscan.c index 2715ef2df..816178bbc 100644 --- a/networking/pscan.c +++ b/networking/pscan.c | |||
@@ -18,13 +18,13 @@ | |||
18 | //usage:#define pscan_trivial_usage | 18 | //usage:#define pscan_trivial_usage |
19 | //usage: "[-cb] [-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST" | 19 | //usage: "[-cb] [-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST" |
20 | //usage:#define pscan_full_usage "\n\n" | 20 | //usage:#define pscan_full_usage "\n\n" |
21 | //usage: "Scan a host, print all open ports\n" | 21 | //usage: "Scan HOST, print all open ports\n" |
22 | //usage: "\n -c Show closed ports too" | 22 | //usage: "\n -c Show closed ports too" |
23 | //usage: "\n -b Show blocked ports too" | 23 | //usage: "\n -b Show blocked ports too" |
24 | //usage: "\n -p Scan from this port (default 1)" | 24 | //usage: "\n -p PORT Scan from this port (default 1)" |
25 | //usage: "\n -P Scan up to this port (default 1024)" | 25 | //usage: "\n -P PORT Scan up to this port (default 1024)" |
26 | //usage: "\n -t Timeout (default 5000 ms)" | 26 | //usage: "\n -t MS Timeout (default 5000 ms)" |
27 | //usage: "\n -T Minimum rtt (default 5 ms, increase for congested hosts)" | 27 | //usage: "\n -T MS Minimum rtt (default 5 ms)" |
28 | 28 | ||
29 | #include "libbb.h" | 29 | #include "libbb.h" |
30 | 30 | ||
@@ -139,7 +139,7 @@ int pscan_main(int argc UNUSED_PARAM, char **argv) | |||
139 | * We check rtt BEFORE we usleep, otherwise | 139 | * We check rtt BEFORE we usleep, otherwise |
140 | * on localhost we'll have no writes done (!) | 140 | * on localhost we'll have no writes done (!) |
141 | * before we exceed (rather small) rtt */ | 141 | * before we exceed (rather small) rtt */ |
142 | usleep(rtt_4/8); | 142 | usleep(rtt_4 / 8); |
143 | open: | 143 | open: |
144 | diff = MONOTONIC_US() - start; | 144 | diff = MONOTONIC_US() - start; |
145 | DMSG("write to port %u @%u", port, diff - start); | 145 | DMSG("write to port %u @%u", port, diff - start); |
diff --git a/networking/route.c b/networking/route.c index 4d9aad6cc..ff5daa8a7 100644 --- a/networking/route.c +++ b/networking/route.c | |||
@@ -34,14 +34,6 @@ | |||
34 | 34 | ||
35 | //kbuild:lib-$(CONFIG_ROUTE) += route.o | 35 | //kbuild:lib-$(CONFIG_ROUTE) += route.o |
36 | 36 | ||
37 | //usage:#define route_trivial_usage | ||
38 | //usage: "[{add|del|delete}]" | ||
39 | //usage:#define route_full_usage "\n\n" | ||
40 | //usage: "Edit kernel routing tables\n" | ||
41 | //usage: "\n -n Don't resolve names" | ||
42 | //usage: "\n -e Display other/more information" | ||
43 | //usage: "\n -A inet" IF_FEATURE_IPV6("{6}") " Select address family" | ||
44 | |||
45 | #include <net/route.h> | 37 | #include <net/route.h> |
46 | #include <net/if.h> | 38 | #include <net/if.h> |
47 | 39 | ||
@@ -83,17 +75,15 @@ | |||
83 | #define RTACTION_ADD 1 | 75 | #define RTACTION_ADD 1 |
84 | #define RTACTION_DEL 2 | 76 | #define RTACTION_DEL 2 |
85 | 77 | ||
86 | /* For the various tbl_*[] arrays, the 1st byte is the offset to | 78 | /* For the various tbl_*[] arrays, the 1st byte is return value. */ |
87 | * the next entry and the 2nd byte is return value. */ | ||
88 | 79 | ||
89 | #define NET_FLAG 1 | 80 | #define NET_FLAG 1 |
90 | #define HOST_FLAG 2 | 81 | #define HOST_FLAG 2 |
91 | 82 | ||
92 | /* We remap '-' to '#' to avoid problems with getopt. */ | 83 | /* We remap '-' to '#' to avoid problems with getopt. */ |
93 | static const char tbl_hash_net_host[] ALIGN1 = | 84 | static const char tbl_hash_net_host[] ALIGN1 = |
94 | "\007\001#net\0" | 85 | "\001#net\0" |
95 | /* "\010\002#host\0" */ | 86 | "\002#host\0" |
96 | "\007\002#host" /* Since last, we can save a byte. */ | ||
97 | ; | 87 | ; |
98 | 88 | ||
99 | #define KW_TAKES_ARG 020 | 89 | #define KW_TAKES_ARG 020 |
@@ -116,29 +106,28 @@ static const char tbl_hash_net_host[] ALIGN1 = | |||
116 | static const char tbl_ipvx[] ALIGN1 = | 106 | static const char tbl_ipvx[] ALIGN1 = |
117 | /* 020 is the "takes an arg" bit */ | 107 | /* 020 is the "takes an arg" bit */ |
118 | #if HAVE_NEW_ADDRT | 108 | #if HAVE_NEW_ADDRT |
119 | "\011\020metric\0" | 109 | "\020metric\0" |
120 | #endif | 110 | #endif |
121 | "\012\021netmask\0" | 111 | "\021netmask\0" |
122 | "\005\022gw\0" | 112 | "\022gw\0" |
123 | "\012\022gateway\0" | 113 | "\022gateway\0" |
124 | "\006\023mss\0" | 114 | "\023mss\0" |
125 | "\011\024window\0" | 115 | "\024window\0" |
126 | #ifdef RTF_IRTT | 116 | #ifdef RTF_IRTT |
127 | "\007\025irtt\0" | 117 | "\025irtt\0" |
128 | #endif | 118 | #endif |
129 | "\006\026dev\0" | 119 | "\026dev\0" |
130 | "\011\026device\0" | 120 | "\026device\0" |
131 | /* 040 is the "sets a flag" bit - MUST match flags_ipvx[] values below. */ | 121 | /* 040 is the "sets a flag" bit - MUST match flags_ipvx[] values below. */ |
132 | #ifdef RTF_REJECT | 122 | #ifdef RTF_REJECT |
133 | "\011\040reject\0" | 123 | "\040reject\0" |
134 | #endif | 124 | #endif |
135 | "\006\041mod\0" | 125 | "\041mod\0" |
136 | "\006\042dyn\0" | 126 | "\042dyn\0" |
137 | /* "\014\043reinstate\0" */ | 127 | "\043reinstate\0" |
138 | "\013\043reinstate" /* Since last, we can save a byte. */ | ||
139 | ; | 128 | ; |
140 | 129 | ||
141 | static const uint16_t flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */ | 130 | static const uint16_t flags_ipvx[] ALIGN2 = { /* MUST match tbl_ipvx[] values above. */ |
142 | #ifdef RTF_REJECT | 131 | #ifdef RTF_REJECT |
143 | RTF_REJECT, | 132 | RTF_REJECT, |
144 | #endif | 133 | #endif |
@@ -151,17 +140,17 @@ static int kw_lookup(const char *kwtbl, char ***pargs) | |||
151 | { | 140 | { |
152 | if (**pargs) { | 141 | if (**pargs) { |
153 | do { | 142 | do { |
154 | if (strcmp(kwtbl+2, **pargs) == 0) { /* Found a match. */ | 143 | if (strcmp(kwtbl + 1, **pargs) == 0) { /* Found a match. */ |
155 | *pargs += 1; | 144 | *pargs += 1; |
156 | if (kwtbl[1] & KW_TAKES_ARG) { | 145 | if (kwtbl[0] & KW_TAKES_ARG) { |
157 | if (!**pargs) { /* No more args! */ | 146 | if (!**pargs) { /* No more args! */ |
158 | bb_show_usage(); | 147 | bb_show_usage(); |
159 | } | 148 | } |
160 | *pargs += 1; /* Calling routine will use args[-1]. */ | 149 | *pargs += 1; /* Calling routine will use args[-1]. */ |
161 | } | 150 | } |
162 | return kwtbl[1]; | 151 | return kwtbl[0]; |
163 | } | 152 | } |
164 | kwtbl += *kwtbl; | 153 | kwtbl += strlen(kwtbl) + 1; |
165 | } while (*kwtbl); | 154 | } while (*kwtbl); |
166 | } | 155 | } |
167 | return 0; | 156 | return 0; |
@@ -208,7 +197,7 @@ static NOINLINE void INET_setroute(int action, char **args) | |||
208 | /* Default netmask. */ | 197 | /* Default netmask. */ |
209 | netmask = "default"; | 198 | netmask = "default"; |
210 | } | 199 | } |
211 | /* Prefer hostname lookup is -host flag (xflag==1) was given. */ | 200 | /* Prefer hostname lookup if -host flag (xflag==1) was given. */ |
212 | isnet = INET_resolve(target, (struct sockaddr_in *) &rt->rt_dst, | 201 | isnet = INET_resolve(target, (struct sockaddr_in *) &rt->rt_dst, |
213 | (xflag & HOST_FLAG)); | 202 | (xflag & HOST_FLAG)); |
214 | if (isnet < 0) { | 203 | if (isnet < 0) { |
@@ -460,9 +449,9 @@ static NOINLINE void INET6_setroute(int action, char **args) | |||
460 | #endif | 449 | #endif |
461 | 450 | ||
462 | static const | 451 | static const |
463 | IF_NOT_FEATURE_IPV6(uint16_t) | 452 | IF_NOT_FEATURE_IPV6(uint16_t flagvals[] ALIGN2 = ) |
464 | IF_FEATURE_IPV6(unsigned) | 453 | IF_FEATURE_IPV6(uint32_t flagvals[] ALIGN4 = ) |
465 | flagvals[] = { /* Must agree with flagchars[]. */ | 454 | { /* Must agree with flagchars[]. */ |
466 | RTF_UP, | 455 | RTF_UP, |
467 | RTF_GATEWAY, | 456 | RTF_GATEWAY, |
468 | RTF_HOST, | 457 | RTF_HOST, |
@@ -544,7 +533,6 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt) | |||
544 | flags[0] = '!'; | 533 | flags[0] = '!'; |
545 | } | 534 | } |
546 | #endif | 535 | #endif |
547 | |||
548 | memset(&s_addr, 0, sizeof(struct sockaddr_in)); | 536 | memset(&s_addr, 0, sizeof(struct sockaddr_in)); |
549 | s_addr.sin_family = AF_INET; | 537 | s_addr.sin_family = AF_INET; |
550 | s_addr.sin_addr.s_addr = d; | 538 | s_addr.sin_addr.s_addr = d; |
@@ -634,7 +622,6 @@ static void INET6_displayroutes(void) | |||
634 | naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6, | 622 | naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6, |
635 | 0x0fff /* Apparently, upstream never resolves. */ | 623 | 0x0fff /* Apparently, upstream never resolves. */ |
636 | ); | 624 | ); |
637 | |||
638 | if (!r) { /* 1st pass */ | 625 | if (!r) { /* 1st pass */ |
639 | snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len); | 626 | snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len); |
640 | r += 40; | 627 | r += 40; |
@@ -653,18 +640,27 @@ static void INET6_displayroutes(void) | |||
653 | 640 | ||
654 | #endif | 641 | #endif |
655 | 642 | ||
643 | //usage:#define route_trivial_usage | ||
644 | ///////: "[-ne]"IF_FEATURE_IPV6(" [-A inet[6]]")" [{add|del|delete} [-net|-host] TARGET [netmask MASK] [gw GATEWAY] [metric N] [mss BYTES] [window BYTES] [irtt MSEC] [reject] [mod] [dyn] [reinstate] [[dev] IFACE]]" | ||
645 | ///////too wordy | ||
646 | //usage: "[-ne]"IF_FEATURE_IPV6(" [-A inet[6]]")" [{add|del} [-net|-host] TARGET [netmask MASK]\n" | ||
647 | //usage: " [gw GATEWAY] [metric N] [mss BYTES] [window BYTES] [reject] [IFACE]]" | ||
648 | //usage:#define route_full_usage "\n\n" | ||
649 | //usage: "Show or edit kernel routing tables\n" | ||
650 | //usage: "\n -n Don't resolve names" | ||
651 | //usage: "\n -e Display other/more information" | ||
652 | //usage: "\n -A inet" IF_FEATURE_IPV6("[6]") " Select address family" | ||
653 | |||
656 | #define ROUTE_OPT_A 0x01 | 654 | #define ROUTE_OPT_A 0x01 |
657 | #define ROUTE_OPT_n 0x02 | 655 | #define ROUTE_OPT_n 0x02 |
658 | #define ROUTE_OPT_e 0x04 | 656 | #define ROUTE_OPT_e 0x04 |
659 | #define ROUTE_OPT_INET6 0x08 /* Not an actual option. See below. */ | 657 | #define ROUTE_OPT_INET6 0x08 /* Not an actual option. See below. */ |
660 | 658 | ||
661 | /* 1st byte is offset to next entry offset. 2nd byte is return value. */ | 659 | /* 1st byte is return value, matches RTACTION_* code */ |
662 | /* 2nd byte matches RTACTION_* code */ | ||
663 | static const char tbl_verb[] ALIGN1 = | 660 | static const char tbl_verb[] ALIGN1 = |
664 | "\006\001add\0" | 661 | "\001add\0" |
665 | "\006\002del\0" | 662 | "\002del\0" |
666 | /* "\011\002delete\0" */ | 663 | "\002delete\0" |
667 | "\010\002delete" /* Since it's last, we can save a byte. */ | ||
668 | ; | 664 | ; |
669 | 665 | ||
670 | int route_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 666 | int route_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
diff --git a/networking/slattach.c b/networking/slattach.c index 51fbc1f49..6d2a252fc 100644 --- a/networking/slattach.c +++ b/networking/slattach.c | |||
@@ -76,7 +76,7 @@ static void restore_state_and_exit(int exitcode) | |||
76 | cfsetispeed(&state, B0); | 76 | cfsetispeed(&state, B0); |
77 | cfsetospeed(&state, B0); | 77 | cfsetospeed(&state, B0); |
78 | exitcode |= tcsetattr_serial_or_warn(&state); | 78 | exitcode |= tcsetattr_serial_or_warn(&state); |
79 | sleep(1); | 79 | sleep1(); |
80 | 80 | ||
81 | /* Restore line status */ | 81 | /* Restore line status */ |
82 | if (tcsetattr_serial_or_warn(&G.saved_state)) | 82 | if (tcsetattr_serial_or_warn(&G.saved_state)) |
diff --git a/networking/telnet.c b/networking/telnet.c index 9fc85050b..7a0253525 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -368,12 +368,16 @@ static void put_iac2_msb_lsb(unsigned x_y) | |||
368 | } | 368 | } |
369 | #define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y)) | 369 | #define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y)) |
370 | 370 | ||
371 | #if ENABLE_FEATURE_TELNET_WIDTH \ | ||
372 | || ENABLE_FEATURE_TELNET_TTYPE \ | ||
373 | || ENABLE_FEATURE_TELNET_AUTOLOGIN | ||
371 | static void put_iac4_msb_lsb(unsigned x_y_z_t) | 374 | static void put_iac4_msb_lsb(unsigned x_y_z_t) |
372 | { | 375 | { |
373 | put_iac2_msb_lsb(x_y_z_t >> 16); | 376 | put_iac2_msb_lsb(x_y_z_t >> 16); |
374 | put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */ | 377 | put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */ |
375 | } | 378 | } |
376 | #define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t)) | 379 | #define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t)) |
380 | #endif | ||
377 | 381 | ||
378 | static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c) | 382 | static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c) |
379 | { | 383 | { |
@@ -673,7 +677,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) | |||
673 | if (bb_got_signal) | 677 | if (bb_got_signal) |
674 | con_escape(); | 678 | con_escape(); |
675 | else | 679 | else |
676 | sleep(1); | 680 | sleep1(); |
677 | continue; | 681 | continue; |
678 | } | 682 | } |
679 | 683 | ||
diff --git a/networking/tftp.c b/networking/tftp.c index 60fdff232..4b86ed9de 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -104,7 +104,7 @@ | |||
104 | //usage: "\n -p Put file" | 104 | //usage: "\n -p Put file" |
105 | //usage: ) | 105 | //usage: ) |
106 | //usage: IF_FEATURE_TFTP_BLOCKSIZE( | 106 | //usage: IF_FEATURE_TFTP_BLOCKSIZE( |
107 | //usage: "\n -b SIZE Transfer blocks of SIZE octets" | 107 | //usage: "\n -b SIZE Transfer blocks in bytes" |
108 | //usage: ) | 108 | //usage: ) |
109 | ///////: "\n -m STR Accepted and ignored ('-m binary' compat with tftp-hpa 5.2)" | 109 | ///////: "\n -m STR Accepted and ignored ('-m binary' compat with tftp-hpa 5.2)" |
110 | //usage: | 110 | //usage: |
@@ -120,7 +120,7 @@ | |||
120 | //usage: " udpsvd -vE 0.0.0.0 69 tftpd /files/to/serve\n" | 120 | //usage: " udpsvd -vE 0.0.0.0 69 tftpd /files/to/serve\n" |
121 | //usage: "\n -r Prohibit upload" | 121 | //usage: "\n -r Prohibit upload" |
122 | //usage: "\n -c Allow file creation via upload" | 122 | //usage: "\n -c Allow file creation via upload" |
123 | //usage: "\n -u Access files as USER" | 123 | //usage: "\n -u USER Access files as USER" |
124 | //usage: "\n -l Log to syslog (inetd mode requires this)" | 124 | //usage: "\n -l Log to syslog (inetd mode requires this)" |
125 | 125 | ||
126 | #include "libbb.h" | 126 | #include "libbb.h" |
diff --git a/networking/tls.c b/networking/tls.c index c00ef5db0..869456a6a 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -1959,7 +1959,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1959 | premaster_size = sizeof(rsa_premaster); | 1959 | premaster_size = sizeof(rsa_premaster); |
1960 | } else { | 1960 | } else { |
1961 | /* ECDHE */ | 1961 | /* ECDHE */ |
1962 | static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9}; | 1962 | static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN1 = {9}; |
1963 | uint8_t privkey[CURVE25519_KEYSIZE]; //[32] | 1963 | uint8_t privkey[CURVE25519_KEYSIZE]; //[32] |
1964 | 1964 | ||
1965 | if (!(tls->flags & GOT_EC_KEY)) | 1965 | if (!(tls->flags & GOT_EC_KEY)) |
diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 5400ad9b5..feb618fb7 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c | |||
@@ -313,15 +313,15 @@ static void InvMixColumns(unsigned astate[16]) | |||
313 | d = astate[i + 3]; | 313 | d = astate[i + 3]; |
314 | x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3) | 314 | x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3) |
315 | /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3); | 315 | /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3); |
316 | astate[i + 0] = Multiply(x); | ||
316 | y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3) | 317 | y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3) |
317 | /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3); | 318 | /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3); |
319 | astate[i + 1] = Multiply(y); | ||
318 | z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3) | 320 | z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3) |
319 | /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3); | 321 | /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3); |
322 | astate[i + 2] = Multiply(z); | ||
320 | t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3) | 323 | t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3) |
321 | /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3); | 324 | /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3); |
322 | astate[i + 0] = Multiply(x); | ||
323 | astate[i + 1] = Multiply(y); | ||
324 | astate[i + 2] = Multiply(z); | ||
325 | astate[i + 3] = Multiply(t); | 325 | astate[i + 3] = Multiply(t); |
326 | } | 326 | } |
327 | } | 327 | } |
diff --git a/networking/tls_fe.c b/networking/tls_fe.c index 10971bbff..f810e112a 100644 --- a/networking/tls_fe.c +++ b/networking/tls_fe.c | |||
@@ -383,12 +383,10 @@ static void fe_inv__distinct(byte *r, const byte *x) | |||
383 | * to avoid copying temporaries. | 383 | * to avoid copying temporaries. |
384 | */ | 384 | */ |
385 | 385 | ||
386 | /* 1 1 */ | 386 | lm_copy(r, x); |
387 | fe_mul__distinct(s, x, x); | ||
388 | fe_mul__distinct(r, s, x); | ||
389 | 387 | ||
390 | /* 1 x 248 */ | 388 | /* 1, 1 x 249 */ |
391 | for (i = 0; i < 248; i++) { | 389 | for (i = 0; i < 249; i++) { |
392 | fe_mul__distinct(s, r, r); | 390 | fe_mul__distinct(s, r, r); |
393 | fe_mul__distinct(r, s, x); | 391 | fe_mul__distinct(r, s, x); |
394 | } | 392 | } |
@@ -403,13 +401,11 @@ static void fe_inv__distinct(byte *r, const byte *x) | |||
403 | /* 0 */ | 401 | /* 0 */ |
404 | fe_mul__distinct(r, s, s); | 402 | fe_mul__distinct(r, s, s); |
405 | 403 | ||
406 | /* 1 */ | 404 | /* 1, 1 */ |
407 | fe_mul__distinct(s, r, r); | 405 | for (i = 0; i < 2; i++) { |
408 | fe_mul__distinct(r, s, x); | 406 | fe_mul__distinct(s, r, r); |
409 | 407 | fe_mul__distinct(r, s, x); | |
410 | /* 1 */ | 408 | } |
411 | fe_mul__distinct(s, r, r); | ||
412 | fe_mul__distinct(r, s, x); | ||
413 | } | 409 | } |
414 | 410 | ||
415 | #if 0 //UNUSED | 411 | #if 0 //UNUSED |
@@ -435,12 +431,10 @@ static void exp2523(byte *r, const byte *x, byte *s) | |||
435 | * 111111... 01 | 431 | * 111111... 01 |
436 | */ | 432 | */ |
437 | 433 | ||
438 | /* 1 1 */ | 434 | lm_copy(s, x); |
439 | fe_mul__distinct(r, x, x); | ||
440 | fe_mul__distinct(s, r, x); | ||
441 | 435 | ||
442 | /* 1 x 248 */ | 436 | /* 1, 1 x 249 */ |
443 | for (i = 0; i < 248; i++) { | 437 | for (i = 0; i < 249; i++) { |
444 | fe_mul__distinct(r, s, s); | 438 | fe_mul__distinct(r, s, s); |
445 | fe_mul__distinct(s, r, x); | 439 | fe_mul__distinct(s, r, x); |
446 | } | 440 | } |
diff --git a/networking/traceroute.c b/networking/traceroute.c index 1c4dc3e4a..8f5cd0bf2 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -243,7 +243,7 @@ | |||
243 | //kbuild:lib-$(CONFIG_TRACEROUTE6) += traceroute.o | 243 | //kbuild:lib-$(CONFIG_TRACEROUTE6) += traceroute.o |
244 | 244 | ||
245 | //usage:#define traceroute_trivial_usage | 245 | //usage:#define traceroute_trivial_usage |
246 | //usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" | 246 | //usage: "[-"IF_TRACEROUTE6("46")IF_FEATURE_TRACEROUTE_USE_ICMP("I")"Flnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" |
247 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" | 247 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" |
248 | //usage: " [-z PAUSE_MSEC] HOST [BYTES]" | 248 | //usage: " [-z PAUSE_MSEC] HOST [BYTES]" |
249 | //usage:#define traceroute_full_usage "\n\n" | 249 | //usage:#define traceroute_full_usage "\n\n" |
@@ -271,15 +271,20 @@ | |||
271 | //usage: "\n -s IP Source address" | 271 | //usage: "\n -s IP Source address" |
272 | //usage: "\n -i IFACE Source interface" | 272 | //usage: "\n -i IFACE Source interface" |
273 | //usage: "\n -t N Type-of-service in probe packets (default 0)" | 273 | //usage: "\n -t N Type-of-service in probe packets (default 0)" |
274 | //usage: "\n -w SEC Time to wait for a response (default 3)" | 274 | //usage: "\n -w SEC Wait for a response (default 3)" |
275 | //usage: "\n -g IP Loose source route gateway (8 max)" | 275 | //usage: "\n -z MSEC Wait before each send" |
276 | //usage: | 276 | //usage: |
277 | //usage:#define traceroute6_trivial_usage | 277 | //usage:#define traceroute6_trivial_usage |
278 | //usage: "[-nrv] [-m MAXTTL] [-q PROBES] [-p PORT]\n" | 278 | //usage: "[-"IF_FEATURE_TRACEROUTE_USE_ICMP("I")"nrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" |
279 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" | 279 | //usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n" |
280 | //usage: " HOST [BYTES]" | 280 | //usage: " [-z PAUSE_MSEC] HOST [BYTES]" |
281 | //usage:#define traceroute6_full_usage "\n\n" | 281 | //usage:#define traceroute6_full_usage "\n\n" |
282 | //usage: "Trace the route to HOST\n" | 282 | //usage: "Trace the route to HOST\n" |
283 | ////NOP? "\n -F Set don't fragment bit" | ||
284 | //usage: IF_FEATURE_TRACEROUTE_USE_ICMP( | ||
285 | //usage: "\n -I Use ICMP ECHO instead of UDP datagrams" | ||
286 | //usage: ) | ||
287 | ////NOP: "\n -l Display TTL value of the returned packet" | ||
283 | //Currently disabled (TRACEROUTE_SO_DEBUG==0) | 288 | //Currently disabled (TRACEROUTE_SO_DEBUG==0) |
284 | ////usage: "\n -d Set SO_DEBUG options to socket" | 289 | ////usage: "\n -d Set SO_DEBUG options to socket" |
285 | //usage: "\n -n Print numeric addresses" | 290 | //usage: "\n -n Print numeric addresses" |
@@ -287,6 +292,7 @@ | |||
287 | //usage: IF_FEATURE_TRACEROUTE_VERBOSE( | 292 | //usage: IF_FEATURE_TRACEROUTE_VERBOSE( |
288 | //usage: "\n -v Verbose" | 293 | //usage: "\n -v Verbose" |
289 | //usage: ) | 294 | //usage: ) |
295 | //usage: "\n -f N First number of hops (default 1)" | ||
290 | //usage: "\n -m N Max number of hops" | 296 | //usage: "\n -m N Max number of hops" |
291 | //usage: "\n -q N Number of probes per hop (default 3)" | 297 | //usage: "\n -q N Number of probes per hop (default 3)" |
292 | //usage: "\n -p N Base UDP port number used in probes" | 298 | //usage: "\n -p N Base UDP port number used in probes" |
@@ -294,7 +300,8 @@ | |||
294 | //usage: "\n -s IP Source address" | 300 | //usage: "\n -s IP Source address" |
295 | //usage: "\n -i IFACE Source interface" | 301 | //usage: "\n -i IFACE Source interface" |
296 | //usage: "\n -t N Type-of-service in probe packets (default 0)" | 302 | //usage: "\n -t N Type-of-service in probe packets (default 0)" |
297 | //usage: "\n -w SEC Time wait for a response (default 3)" | 303 | //usage: "\n -w SEC Wait for a response (default 3)" |
304 | //usage: "\n -z MSEC Wait before each send" | ||
298 | 305 | ||
299 | #define TRACEROUTE_SO_DEBUG 0 | 306 | #define TRACEROUTE_SO_DEBUG 0 |
300 | 307 | ||
@@ -324,7 +331,6 @@ | |||
324 | #ifndef IPPROTO_IP | 331 | #ifndef IPPROTO_IP |
325 | # define IPPROTO_IP 0 | 332 | # define IPPROTO_IP 0 |
326 | #endif | 333 | #endif |
327 | |||
328 | /* Some operating systems, like GNU/Hurd, don't define SOL_RAW, but do have | 334 | /* Some operating systems, like GNU/Hurd, don't define SOL_RAW, but do have |
329 | * IPPROTO_RAW. Since the IPPROTO definitions are also valid to use for | 335 | * IPPROTO_RAW. Since the IPPROTO definitions are also valid to use for |
330 | * setsockopt (and take the same value as their corresponding SOL definitions, | 336 | * setsockopt (and take the same value as their corresponding SOL definitions, |
@@ -335,7 +341,7 @@ | |||
335 | 341 | ||
336 | 342 | ||
337 | #define OPT_STRING \ | 343 | #define OPT_STRING \ |
338 | "FIlnrdvxt:i:m:p:q:s:w:z:f:" \ | 344 | "FIlnrdvt:i:m:p:q:s:w:z:f:" \ |
339 | "4" IF_TRACEROUTE6("6") | 345 | "4" IF_TRACEROUTE6("6") |
340 | enum { | 346 | enum { |
341 | OPT_DONT_FRAGMNT = (1 << 0), /* F */ | 347 | OPT_DONT_FRAGMNT = (1 << 0), /* F */ |
@@ -345,20 +351,23 @@ enum { | |||
345 | OPT_BYPASS_ROUTE = (1 << 4), /* r */ | 351 | OPT_BYPASS_ROUTE = (1 << 4), /* r */ |
346 | OPT_DEBUG = (1 << 5), /* d */ | 352 | OPT_DEBUG = (1 << 5), /* d */ |
347 | OPT_VERBOSE = (1 << 6) * ENABLE_FEATURE_TRACEROUTE_VERBOSE, /* v */ | 353 | OPT_VERBOSE = (1 << 6) * ENABLE_FEATURE_TRACEROUTE_VERBOSE, /* v */ |
348 | OPT_IP_CHKSUM = (1 << 7), /* x */ | 354 | OPT_TOS = (1 << 7), /* t */ |
349 | OPT_TOS = (1 << 8), /* t */ | 355 | OPT_DEVICE = (1 << 8), /* i */ |
350 | OPT_DEVICE = (1 << 9), /* i */ | 356 | OPT_MAX_TTL = (1 << 9), /* m */ |
351 | OPT_MAX_TTL = (1 << 10), /* m */ | 357 | OPT_PORT = (1 << 10), /* p */ |
352 | OPT_PORT = (1 << 11), /* p */ | 358 | OPT_NPROBES = (1 << 11), /* q */ |
353 | OPT_NPROBES = (1 << 12), /* q */ | 359 | OPT_SOURCE = (1 << 12), /* s */ |
354 | OPT_SOURCE = (1 << 13), /* s */ | 360 | OPT_WAITTIME = (1 << 13), /* w */ |
355 | OPT_WAITTIME = (1 << 14), /* w */ | 361 | OPT_PAUSE_MS = (1 << 14), /* z */ |
356 | OPT_PAUSE_MS = (1 << 15), /* z */ | 362 | OPT_FIRST_TTL = (1 << 15), /* f */ |
357 | OPT_FIRST_TTL = (1 << 16), /* f */ | 363 | OPT_IPV4 = (1 << 16), /* 4 */ |
358 | OPT_IPV4 = (1 << 17), /* 4 */ | 364 | OPT_IPV6 = (1 << 17) * ENABLE_TRACEROUTE6, /* 6 */ |
359 | OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */ | ||
360 | }; | 365 | }; |
361 | #define verbose (option_mask32 & OPT_VERBOSE) | 366 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE |
367 | # define verbose (option_mask32 & OPT_VERBOSE) | ||
368 | #else | ||
369 | # define verbose 0 | ||
370 | #endif | ||
362 | 371 | ||
363 | enum { | 372 | enum { |
364 | SIZEOF_ICMP_HDR = 8, | 373 | SIZEOF_ICMP_HDR = 8, |
@@ -387,13 +396,26 @@ struct globals { | |||
387 | struct ip *outip; | 396 | struct ip *outip; |
388 | /* Pointer to ICMP or UDP payload (not header): */ | 397 | /* Pointer to ICMP or UDP payload (not header): */ |
389 | struct outdata_t *outdata; | 398 | struct outdata_t *outdata; |
390 | |||
391 | len_and_sockaddr *dest_lsa; | 399 | len_and_sockaddr *dest_lsa; |
400 | len_and_sockaddr *from_lsa; /* response came from this address */ | ||
401 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
402 | struct sockaddr *to; /* response came to this (local) address */ | ||
403 | #endif | ||
404 | uint32_t ident; | ||
405 | uint16_t port; /* start udp dest port # for probe packets */ | ||
406 | #if ENABLE_TRACEROUTE6 | ||
407 | smallint ipv6; | ||
408 | # define G_ipv6 G.ipv6 | ||
409 | #else | ||
410 | # define G_ipv6 0 | ||
411 | #endif | ||
392 | int packlen; /* total length of packet */ | 412 | int packlen; /* total length of packet */ |
393 | int pmtu; /* Path MTU Discovery (RFC1191) */ | 413 | int pmtu; /* Path MTU Discovery (RFC1191) */ |
394 | uint32_t ident; | 414 | int waittime; /* time to wait for response (in seconds) */ |
395 | uint16_t port; // 33434; /* start udp dest port # for probe packets */ | 415 | int first_ttl; |
396 | int waittime; // 5; /* time to wait for response (in seconds) */ | 416 | int nprobes; |
417 | int max_ttl; | ||
418 | unsigned pausemsecs; | ||
397 | unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ | 419 | unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ |
398 | }; | 420 | }; |
399 | 421 | ||
@@ -407,19 +429,39 @@ struct globals { | |||
407 | #define port (G.port ) | 429 | #define port (G.port ) |
408 | #define waittime (G.waittime ) | 430 | #define waittime (G.waittime ) |
409 | #define recv_pkt (G.recv_pkt ) | 431 | #define recv_pkt (G.recv_pkt ) |
410 | #define gwlist (G.gwlist ) | ||
411 | #define INIT_G() do { \ | 432 | #define INIT_G() do { \ |
412 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 433 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
413 | port = 33434; \ | ||
414 | waittime = 5; \ | ||
415 | } while (0) | 434 | } while (0) |
416 | 435 | ||
417 | #define outicmp ((struct icmp *)(outip + 1)) | 436 | #define outudp ((struct udphdr *)(outip + 1)) |
418 | #define outudp ((struct udphdr *)(outip + 1)) | 437 | #define outudp6 ((struct udphdr *)(((struct ip6_hdr*)outip) + 1)) |
419 | 438 | #define outicmp ((struct icmp *)(outip + 1)) | |
439 | #define outicmp6 ((struct icmp *)(((struct ip6_hdr*)outip) + 1)) | ||
440 | /* NB: for icmp echo, IPv4 and IPv6 fields are the same size and offset: | ||
441 | * struct icmp: | ||
442 | * uint8_t icmp_type; | ||
443 | * uint8_t icmp_code; | ||
444 | * uint16_t icmp_cksum; | ||
445 | * uint16_t icmp_id; | ||
446 | * uint16_t icmp_seq; | ||
447 | * struct icmp6_hdr: | ||
448 | * uint8_t icmp6_type; | ||
449 | * uint8_t icmp6_code; | ||
450 | * uint16_t icmp6_cksum; | ||
451 | * uint16_t icmp6_id; | ||
452 | * uint16_t icmp6_seq; | ||
453 | * therefore both outicmp and outicmp6 are pointers to *IPv4* icmp struct. | ||
454 | * SIZEOF_ICMP_HDR == 8 is the same for both, as well. | ||
455 | * However, values of these pointers are not the same (since IPv6 IP header is larger), | ||
456 | * and icmp_type constants are not the same: | ||
457 | * #define ICMP_ECHO 8 | ||
458 | * #define ICMP_ECHOREPLY 0 | ||
459 | * #define ICMP6_ECHO_REQUEST 128 | ||
460 | * #define ICMP6_ECHO_REPLY 129 | ||
461 | */ | ||
420 | 462 | ||
421 | static int | 463 | static int |
422 | wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) | 464 | wait_for_reply(unsigned *timestamp_us, int *left_ms) |
423 | { | 465 | { |
424 | struct pollfd pfd[1]; | 466 | struct pollfd pfd[1]; |
425 | int read_len = 0; | 467 | int read_len = 0; |
@@ -429,10 +471,19 @@ wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timest | |||
429 | if (*left_ms >= 0 && safe_poll(pfd, 1, *left_ms) > 0) { | 471 | if (*left_ms >= 0 && safe_poll(pfd, 1, *left_ms) > 0) { |
430 | unsigned t; | 472 | unsigned t; |
431 | 473 | ||
474 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
432 | read_len = recv_from_to(rcvsock, | 475 | read_len = recv_from_to(rcvsock, |
433 | recv_pkt, sizeof(recv_pkt), | 476 | recv_pkt, sizeof(recv_pkt), |
434 | /*flags:*/ MSG_DONTWAIT, | 477 | /*flags:*/ MSG_DONTWAIT, |
435 | &from_lsa->u.sa, to, from_lsa->len); | 478 | &G.from_lsa->u.sa, G.to, G.from_lsa->len); |
479 | #else | ||
480 | read_len = recvfrom(rcvsock, | ||
481 | recv_pkt, sizeof(recv_pkt), | ||
482 | /*flags:*/ MSG_DONTWAIT, | ||
483 | &G.from_lsa->u.sa, &G.from_lsa->len); | ||
484 | #endif | ||
485 | if (read_len < 0) | ||
486 | bb_simple_perror_msg_and_die("recv"); | ||
436 | t = monotonic_us(); | 487 | t = monotonic_us(); |
437 | *left_ms -= (t - *timestamp_us) / 1000; | 488 | *left_ms -= (t - *timestamp_us) / 1000; |
438 | *timestamp_us = t; | 489 | *timestamp_us = t; |
@@ -446,14 +497,16 @@ send_probe(int seq, int ttl) | |||
446 | { | 497 | { |
447 | int len, res; | 498 | int len, res; |
448 | void *out; | 499 | void *out; |
500 | struct icmp *icp; | ||
449 | 501 | ||
450 | /* Payload */ | 502 | /* Payload */ |
451 | #if ENABLE_TRACEROUTE6 | 503 | #if ENABLE_TRACEROUTE6 |
452 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 504 | if (G_ipv6) { |
453 | struct outdata6_t *pkt = (struct outdata6_t *) outdata; | 505 | struct outdata6_t *pkt = (void *) outdata; |
454 | pkt->ident6 = htonl(ident); | 506 | pkt->ident6 = ident; |
455 | pkt->seq6 = htonl(seq); | 507 | pkt->seq6 = htonl(seq); |
456 | /*gettimeofday(&pkt->tv, &tz);*/ | 508 | /*xgettimeofday(&pkt->tv);*/ |
509 | icp = outicmp6; | ||
457 | } else | 510 | } else |
458 | #endif | 511 | #endif |
459 | { | 512 | { |
@@ -461,19 +514,23 @@ send_probe(int seq, int ttl) | |||
461 | outdata->ttl = ttl; | 514 | outdata->ttl = ttl; |
462 | // UNUSED: was storing gettimeofday's result there, but never ever checked it | 515 | // UNUSED: was storing gettimeofday's result there, but never ever checked it |
463 | /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ | 516 | /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ |
464 | 517 | icp = outicmp; | |
465 | if (option_mask32 & OPT_USE_ICMP) { | 518 | } |
466 | outicmp->icmp_seq = htons(seq); | 519 | out = outdata; |
467 | 520 | if (option_mask32 & OPT_USE_ICMP) { | |
468 | /* Always calculate checksum for icmp packets */ | 521 | out = icp; |
469 | outicmp->icmp_cksum = 0; | 522 | /*icp->icmp_type = ICMP[6]_ECHO; - already set */ |
470 | outicmp->icmp_cksum = inet_cksum( | 523 | /*icp->icmp_code = 0; - already set */ |
471 | outicmp, | 524 | /*icp->icmp_id = ident; - already set */ |
472 | ((char*)outip + packlen) - (char*)outicmp | 525 | icp->icmp_seq = htons(seq); |
473 | ); | 526 | /* Always calculate checksum for icmp packets */ |
474 | if (outicmp->icmp_cksum == 0) | 527 | icp->icmp_cksum = 0; |
475 | outicmp->icmp_cksum = 0xffff; | 528 | icp->icmp_cksum = inet_cksum( |
476 | } | 529 | icp, |
530 | ((char*)outip + packlen) - (char*)icp | ||
531 | ); | ||
532 | if (icp->icmp_cksum == 0) | ||
533 | icp->icmp_cksum = 0xffff; | ||
477 | } | 534 | } |
478 | 535 | ||
479 | //BUG! verbose is (x & OPT_VERBOSE), not a counter! | 536 | //BUG! verbose is (x & OPT_VERBOSE), not a counter! |
@@ -502,9 +559,8 @@ send_probe(int seq, int ttl) | |||
502 | } | 559 | } |
503 | #endif | 560 | #endif |
504 | 561 | ||
505 | out = outdata; | ||
506 | #if ENABLE_TRACEROUTE6 | 562 | #if ENABLE_TRACEROUTE6 |
507 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 563 | if (G_ipv6) { |
508 | res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); | 564 | res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); |
509 | if (res != 0) | 565 | if (res != 0) |
510 | bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); | 566 | bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); |
@@ -516,8 +572,6 @@ send_probe(int seq, int ttl) | |||
516 | if (res != 0) | 572 | if (res != 0) |
517 | bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); | 573 | bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); |
518 | #endif | 574 | #endif |
519 | if (option_mask32 & OPT_USE_ICMP) | ||
520 | out = outicmp; | ||
521 | } | 575 | } |
522 | 576 | ||
523 | if (!(option_mask32 & OPT_USE_ICMP)) { | 577 | if (!(option_mask32 & OPT_USE_ICMP)) { |
@@ -530,13 +584,11 @@ send_probe(int seq, int ttl) | |||
530 | } | 584 | } |
531 | 585 | ||
532 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 586 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE |
533 | /* | 587 | /* Convert an ICMP "type" field to a printable string */ |
534 | * Convert an ICMP "type" field to a printable string. | ||
535 | */ | ||
536 | static const char * | 588 | static const char * |
537 | pr_type(unsigned char t) | 589 | pr_type(unsigned char t) |
538 | { | 590 | { |
539 | static const char *const ttab[] = { | 591 | static const char *const ttab[] ALIGN_PTR = { |
540 | "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", | 592 | "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", |
541 | "Source Quench", "Redirect", "ICMP 6", "ICMP 7", | 593 | "Source Quench", "Redirect", "ICMP 6", "ICMP 7", |
542 | "Echo", "Router Advert", "Router Solicit", "Time Exceeded", | 594 | "Echo", "Router Advert", "Router Solicit", "Time Exceeded", |
@@ -544,7 +596,7 @@ pr_type(unsigned char t) | |||
544 | "Info Reply", "Mask Request", "Mask Reply" | 596 | "Info Reply", "Mask Request", "Mask Reply" |
545 | }; | 597 | }; |
546 | # if ENABLE_TRACEROUTE6 | 598 | # if ENABLE_TRACEROUTE6 |
547 | static const char *const ttab6[] = { | 599 | static const char *const ttab6[] ALIGN_PTR = { |
548 | [0] = "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", | 600 | [0] = "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", |
549 | [4] = "Param Problem", | 601 | [4] = "Param Problem", |
550 | [8] = "Echo Request", "Echo Reply", "Membership Query", "Membership Report", | 602 | [8] = "Echo Request", "Echo Reply", "Membership Query", "Membership Report", |
@@ -552,7 +604,7 @@ pr_type(unsigned char t) | |||
552 | [16] = "Neighbor Advert", "Redirect", | 604 | [16] = "Neighbor Advert", "Redirect", |
553 | }; | 605 | }; |
554 | 606 | ||
555 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 607 | if (G_ipv6) { |
556 | if (t < 5) | 608 | if (t < 5) |
557 | return ttab6[t]; | 609 | return ttab6[t]; |
558 | if (t < 128 || t > ND_REDIRECT) | 610 | if (t < 128 || t > ND_REDIRECT) |
@@ -565,28 +617,54 @@ pr_type(unsigned char t) | |||
565 | 617 | ||
566 | return ttab[t]; | 618 | return ttab[t]; |
567 | } | 619 | } |
568 | #endif | 620 | static int |
621 | hexdump_if_verbose(const struct icmp *icp, int len) | ||
622 | { | ||
623 | const unsigned char *p; | ||
624 | int i; | ||
569 | 625 | ||
570 | #if !ENABLE_FEATURE_TRACEROUTE_VERBOSE | 626 | if (!verbose) |
571 | #define packet4_ok(read_len, from, seq) \ | 627 | return 0; |
572 | packet4_ok(read_len, seq) | 628 | |
629 | printf("\n%d bytes from %s to %s: icmp type %u (%s) code %u\n", | ||
630 | len, | ||
631 | auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), | ||
632 | auto_string(xmalloc_sockaddr2dotted_noport(G.to)), | ||
633 | icp->icmp_type, pr_type(icp->icmp_type), | ||
634 | icp->icmp_code | ||
635 | ); | ||
636 | p = (const void *)icp; | ||
637 | for (i = 0; i < len; i++) { | ||
638 | if (!(i & 0xf)) | ||
639 | printf("\n%04x:" + (i==0), i); | ||
640 | printf(" %02x", p[i]); | ||
641 | } | ||
642 | bb_putchar('\n'); | ||
643 | return 0; | ||
644 | } | ||
645 | #else | ||
646 | # define hexdump_if_verbose(...) 0 | ||
573 | #endif | 647 | #endif |
648 | |||
574 | static int | 649 | static int |
575 | packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | 650 | packet4_ok(int read_len, int seq) |
576 | { | 651 | { |
577 | const struct icmp *icp; | 652 | const struct icmp *icp; |
578 | unsigned char type, code; | 653 | unsigned char type, code; |
579 | int hlen; | 654 | int hlen; |
580 | const struct ip *ip; | 655 | const struct ip *ip; |
581 | 656 | ||
657 | /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket | ||
658 | * return the entire IP packet (IOW: they do not strip IP header). | ||
659 | * This differs from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) sockets!? | ||
660 | */ | ||
582 | ip = (struct ip *) recv_pkt; | 661 | ip = (struct ip *) recv_pkt; |
662 | |||
583 | hlen = ip->ip_hl << 2; | 663 | hlen = ip->ip_hl << 2; |
584 | if (read_len < hlen + ICMP_MINLEN) { | 664 | if (read_len < hlen + ICMP_MINLEN) { |
585 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
586 | if (verbose) | 665 | if (verbose) |
587 | printf("packet too short (%d bytes) from %s\n", read_len, | 666 | printf("packet too short (%d bytes) from %s\n", read_len, |
588 | inet_ntoa(from->sin_addr)); | 667 | inet_ntoa(G.from_lsa->u.sin.sin_addr)); |
589 | #endif | ||
590 | return 0; | 668 | return 0; |
591 | } | 669 | } |
592 | read_len -= hlen; | 670 | read_len -= hlen; |
@@ -598,9 +676,22 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
598 | if (code == ICMP_UNREACH_NEEDFRAG) | 676 | if (code == ICMP_UNREACH_NEEDFRAG) |
599 | pmtu = ntohs(icp->icmp_nextmtu); | 677 | pmtu = ntohs(icp->icmp_nextmtu); |
600 | 678 | ||
679 | if ((option_mask32 & OPT_USE_ICMP) | ||
680 | && type == ICMP_ECHOREPLY | ||
681 | && icp->icmp_seq == htons(seq) | ||
682 | ) { | ||
683 | if (icp->icmp_id != ident) | ||
684 | /* reply to another ping/traceroute from this box? */ | ||
685 | return 0; /* ignore, silently */ | ||
686 | /* In UDP mode, when we reach the machine, we (usually) | ||
687 | * would get "port unreachable" - in ICMP we got "echo reply". | ||
688 | * Simulate "port unreachable" for caller: | ||
689 | */ | ||
690 | return ICMP_UNREACH_PORT+1; | ||
691 | } | ||
692 | |||
601 | if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) | 693 | if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) |
602 | || type == ICMP_UNREACH | 694 | || type == ICMP_UNREACH |
603 | || type == ICMP_ECHOREPLY | ||
604 | ) { | 695 | ) { |
605 | const struct ip *hip; | 696 | const struct ip *hip; |
606 | const struct udphdr *up; | 697 | const struct udphdr *up; |
@@ -610,18 +701,10 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
610 | if (option_mask32 & OPT_USE_ICMP) { | 701 | if (option_mask32 & OPT_USE_ICMP) { |
611 | struct icmp *hicmp; | 702 | struct icmp *hicmp; |
612 | 703 | ||
613 | /* XXX */ | ||
614 | if (type == ICMP_ECHOREPLY | ||
615 | && icp->icmp_id == htons(ident) | ||
616 | && icp->icmp_seq == htons(seq) | ||
617 | ) { | ||
618 | return ICMP_UNREACH_PORT+1; | ||
619 | } | ||
620 | |||
621 | hicmp = (struct icmp *)((unsigned char *)hip + hlen); | 704 | hicmp = (struct icmp *)((unsigned char *)hip + hlen); |
622 | if (hlen + SIZEOF_ICMP_HDR <= read_len | 705 | if (hlen + SIZEOF_ICMP_HDR <= read_len |
623 | && hip->ip_p == IPPROTO_ICMP | 706 | && hip->ip_p == IPPROTO_ICMP |
624 | && hicmp->icmp_id == htons(ident) | 707 | && hicmp->icmp_id == ident |
625 | && hicmp->icmp_seq == htons(seq) | 708 | && hicmp->icmp_seq == htons(seq) |
626 | ) { | 709 | ) { |
627 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 710 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
@@ -633,51 +716,54 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) | |||
633 | // Off: since we do not form the entire IP packet, | 716 | // Off: since we do not form the entire IP packet, |
634 | // but defer it to kernel, we can't set source port, | 717 | // but defer it to kernel, we can't set source port, |
635 | // and thus can't check it here in the reply | 718 | // and thus can't check it here in the reply |
636 | /* && up->source == htons(ident) */ | 719 | /* && up->uh_sport == ident */ |
637 | && up->dest == htons(port + seq) | 720 | && up->uh_dport == htons(port + seq) |
638 | ) { | 721 | ) { |
639 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 722 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
640 | } | 723 | } |
641 | } | 724 | } |
642 | } | 725 | } |
643 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 726 | /* testcase: traceroute -vI 127.0.0.1 (sees its own echo requests) */ |
644 | if (verbose) { | 727 | return hexdump_if_verbose(icp, read_len); |
645 | int i; | ||
646 | uint32_t *lp = (uint32_t *)&icp->icmp_ip; | ||
647 | |||
648 | printf("\n%d bytes from %s to " | ||
649 | "%s: icmp type %d (%s) code %d\n", | ||
650 | read_len, inet_ntoa(from->sin_addr), | ||
651 | inet_ntoa(ip->ip_dst), | ||
652 | type, pr_type(type), icp->icmp_code); | ||
653 | for (i = 4; i < read_len; i += sizeof(*lp)) | ||
654 | printf("%2d: x%8.8x\n", i, *lp++); | ||
655 | } | ||
656 | #endif | ||
657 | return 0; | ||
658 | } | 728 | } |
659 | 729 | ||
660 | #if ENABLE_TRACEROUTE6 | 730 | #if ENABLE_TRACEROUTE6 |
661 | # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE | 731 | |
662 | #define packet_ok(read_len, from_lsa, to, seq) \ | ||
663 | packet_ok(read_len, from_lsa, seq) | ||
664 | # endif | ||
665 | static int | 732 | static int |
666 | packet_ok(int read_len, len_and_sockaddr *from_lsa, | 733 | packet6_ok(int read_len, int seq) |
667 | struct sockaddr *to, | ||
668 | int seq) | ||
669 | { | 734 | { |
670 | const struct icmp6_hdr *icp; | 735 | const struct icmp6_hdr *icp; |
671 | unsigned char type, code; | 736 | unsigned char type, code; |
672 | 737 | ||
673 | if (from_lsa->u.sa.sa_family == AF_INET) | 738 | /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket |
674 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | 739 | * return only ICMP packet (IOW: they strip IPv6 header). |
675 | 740 | * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? | |
741 | */ | ||
742 | if (read_len < ICMP_MINLEN) { | ||
743 | if (verbose) | ||
744 | printf("packet too short (%d bytes) from %s\n", read_len, | ||
745 | auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa))); | ||
746 | return 0; | ||
747 | } | ||
676 | icp = (struct icmp6_hdr *) recv_pkt; | 748 | icp = (struct icmp6_hdr *) recv_pkt; |
677 | 749 | ||
678 | type = icp->icmp6_type; | 750 | type = icp->icmp6_type; |
679 | code = icp->icmp6_code; | 751 | code = icp->icmp6_code; |
680 | 752 | ||
753 | if ((option_mask32 & OPT_USE_ICMP) | ||
754 | && type == ICMP6_ECHO_REPLY | ||
755 | && icp->icmp6_seq == htons(seq) | ||
756 | ) { | ||
757 | if (icp->icmp6_id != ident) | ||
758 | /* reply to another ping/traceroute from this box? */ | ||
759 | return 0; /* ignore, silently */ | ||
760 | /* In UDP mode, when we reach the machine, we (usually) | ||
761 | * would get "port unreachable" - in ICMP we got "echo reply". | ||
762 | * Simulate "port unreachable" for caller: | ||
763 | */ | ||
764 | return (ICMP6_DST_UNREACH_NOPORT << 8) + 1; | ||
765 | } | ||
766 | |||
681 | if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) | 767 | if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) |
682 | || type == ICMP6_DST_UNREACH | 768 | || type == ICMP6_DST_UNREACH |
683 | ) { | 769 | ) { |
@@ -698,106 +784,75 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, | |||
698 | 784 | ||
699 | pkt = (struct outdata6_t *) (up + 1); | 785 | pkt = (struct outdata6_t *) (up + 1); |
700 | 786 | ||
701 | if (ntohl(pkt->ident6) == ident | 787 | if (pkt->ident6 == ident |
702 | && ntohl(pkt->seq6) == seq | 788 | && ntohl(pkt->seq6) == seq |
703 | ) { | 789 | ) { |
704 | return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); | 790 | return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); |
705 | } | 791 | } |
706 | } | 792 | } |
707 | } | 793 | } |
708 | 794 | /* cast is safe since the beginning of icmp4 and icmp6 layouts match */ | |
709 | # if ENABLE_FEATURE_TRACEROUTE_VERBOSE | 795 | return hexdump_if_verbose((const struct icmp *)icp, read_len); |
710 | if (verbose) { | ||
711 | # ifndef MAXHOSTNAMELEN | ||
712 | # define MAXHOSTNAMELEN 80 | ||
713 | # endif | ||
714 | unsigned char *p; | ||
715 | char pa1[MAXHOSTNAMELEN]; | ||
716 | char pa2[MAXHOSTNAMELEN]; | ||
717 | int i; | ||
718 | |||
719 | p = (unsigned char *) (icp + 1); | ||
720 | |||
721 | printf("\n%d bytes from %s to " | ||
722 | "%s: icmp type %d (%s) code %d\n", | ||
723 | read_len, | ||
724 | inet_ntop(AF_INET6, &from_lsa->u.sin6.sin6_addr, pa1, sizeof(pa1)), | ||
725 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa2, sizeof(pa2)), | ||
726 | type, pr_type(type), icp->icmp6_code); | ||
727 | |||
728 | read_len -= sizeof(struct icmp6_hdr); | ||
729 | for (i = 0; i < read_len; i++) { | ||
730 | if (i % 16 == 0) | ||
731 | printf("%04x:", i); | ||
732 | if (i % 4 == 0) | ||
733 | bb_putchar(' '); | ||
734 | printf("%02x", p[i]); | ||
735 | if ((i % 16 == 15) && (i + 1 < read_len)) | ||
736 | bb_putchar('\n'); | ||
737 | } | ||
738 | bb_putchar('\n'); | ||
739 | } | ||
740 | # endif | ||
741 | |||
742 | return 0; | ||
743 | } | 796 | } |
744 | #else /* !ENABLE_TRACEROUTE6 */ | 797 | |
745 | static ALWAYS_INLINE int | 798 | static int |
746 | packet_ok(int read_len, | 799 | packet_ok(int read_len, int seq) |
747 | len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), | ||
748 | struct sockaddr *to UNUSED_PARAM, | ||
749 | int seq) | ||
750 | { | 800 | { |
751 | return packet4_ok(read_len, &from_lsa->u.sin, seq); | 801 | if (!G_ipv6) |
802 | return packet4_ok(read_len, seq); | ||
803 | return packet6_ok(read_len, seq); | ||
752 | } | 804 | } |
805 | |||
806 | #else /* !ENABLE_TRACEROUTE6 */ | ||
807 | |||
808 | # define packet_ok(read_len, seq) packet4_ok(read_len, seq) | ||
809 | |||
753 | #endif | 810 | #endif |
754 | 811 | ||
755 | /* | ||
756 | * Construct an Internet address representation. | ||
757 | * If the -n flag has been supplied, give | ||
758 | * numeric value, otherwise try for symbolic name. | ||
759 | */ | ||
760 | static void | 812 | static void |
761 | print_inetname(const struct sockaddr *from) | 813 | #if !ENABLE_FEATURE_TRACEROUTE_VERBOSE |
814 | print(void) | ||
815 | # define print(len) print() | ||
816 | #else | ||
817 | print(int read_len) | ||
818 | #endif | ||
762 | { | 819 | { |
763 | char *ina = xmalloc_sockaddr2dotted_noport(from); | 820 | char *ina = auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)); |
764 | 821 | ||
765 | if (option_mask32 & OPT_ADDR_NUM) { | 822 | if (option_mask32 & OPT_ADDR_NUM) { |
766 | printf(" %s", ina); | 823 | printf(" %s", ina); |
767 | } else { | 824 | } else { |
768 | char *n = NULL; | 825 | char *n = NULL; |
769 | 826 | if (G_ipv6 | |
770 | if (from->sa_family != AF_INET | 827 | || G.from_lsa->u.sin.sin_addr.s_addr != INADDR_ANY |
771 | || ((struct sockaddr_in*)from)->sin_addr.s_addr != INADDR_ANY | ||
772 | ) { | 828 | ) { |
773 | /* Try to reverse resolve if it is not 0.0.0.0 */ | 829 | /* Reverse resolve if IPV6 or not 0.0.0.0 */ |
774 | n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); | 830 | n = auto_string(xmalloc_sockaddr2host_noport(&G.from_lsa->u.sa)); |
775 | } | 831 | } |
776 | printf(" %s (%s)", (n ? n : ina), ina); | 832 | printf(" %s (%s)", (n ? n : ina), ina); |
777 | free(n); | ||
778 | } | 833 | } |
779 | free(ina); | ||
780 | } | ||
781 | |||
782 | static void | ||
783 | print(int read_len, const struct sockaddr *from, const struct sockaddr *to) | ||
784 | { | ||
785 | print_inetname(from); | ||
786 | 834 | ||
835 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
787 | if (verbose) { | 836 | if (verbose) { |
788 | char *ina = xmalloc_sockaddr2dotted_noport(to); | 837 | # if ENABLE_TRACEROUTE6 |
789 | #if ENABLE_TRACEROUTE6 | 838 | /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket |
790 | if (to->sa_family == AF_INET6) { | 839 | * return the entire IP packet (IOW: they do not strip IP header). |
791 | read_len -= sizeof(struct ip6_hdr); | 840 | * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 |
841 | * header and return only ICMP6 packet. Weird. | ||
842 | */ | ||
843 | if (G_ipv6) { | ||
844 | /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ | ||
792 | } else | 845 | } else |
793 | #endif | 846 | # endif |
794 | { | 847 | { |
795 | struct ip *ip4packet = (struct ip*)recv_pkt; | 848 | struct ip *ip4packet = (struct ip*)recv_pkt; |
796 | read_len -= ip4packet->ip_hl << 2; | 849 | read_len -= ip4packet->ip_hl << 2; |
797 | } | 850 | } |
798 | printf(" %d bytes to %s", read_len, ina); | 851 | printf(" %d bytes to %s", read_len, |
799 | free(ina); | 852 | auto_string(xmalloc_sockaddr2dotted_noport(G.to)) |
853 | ); | ||
800 | } | 854 | } |
855 | #endif | ||
801 | } | 856 | } |
802 | 857 | ||
803 | static void | 858 | static void |
@@ -807,22 +862,12 @@ print_delta_ms(unsigned t1p, unsigned t2p) | |||
807 | printf(" %u.%03u ms", tt / 1000, tt % 1000); | 862 | printf(" %u.%03u ms", tt / 1000, tt % 1000); |
808 | } | 863 | } |
809 | 864 | ||
810 | /* | 865 | /* Keeping init code in a separate (not inlined!) function |
811 | * Usage: [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl] | 866 | * for stack use reduction and better register allocation in main loop. |
812 | * [-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos] | ||
813 | * [-w waittime] [-z pausemsecs] host [packetlen]" | ||
814 | */ | 867 | */ |
815 | static int | 868 | static NOINLINE void |
816 | common_traceroute_main(int op, char **argv) | 869 | traceroute_init(int op, char **argv) |
817 | { | 870 | { |
818 | int minpacket; | ||
819 | #ifdef IP_TOS | ||
820 | int tos = 0; | ||
821 | #endif | ||
822 | int max_ttl = 30; | ||
823 | int nprobes = 3; | ||
824 | int first_ttl = 1; | ||
825 | unsigned pausemsecs = 0; | ||
826 | char *source; | 871 | char *source; |
827 | char *device; | 872 | char *device; |
828 | char *tos_str; | 873 | char *tos_str; |
@@ -838,13 +883,16 @@ common_traceroute_main(int op, char **argv) | |||
838 | #else | 883 | #else |
839 | enum { af = AF_INET }; | 884 | enum { af = AF_INET }; |
840 | #endif | 885 | #endif |
841 | int ttl; | 886 | |
842 | int seq; | 887 | /* Ensure the socket fds won't be 0, 1 or 2 */ |
843 | len_and_sockaddr *from_lsa; | 888 | bb_sanitize_stdio(); |
844 | struct sockaddr *lastaddr; | ||
845 | struct sockaddr *to; | ||
846 | 889 | ||
847 | INIT_G(); | 890 | INIT_G(); |
891 | port = 33434; | ||
892 | waittime = 5; | ||
893 | G.first_ttl = 1; | ||
894 | G.nprobes = 3; | ||
895 | G.max_ttl = 30; | ||
848 | 896 | ||
849 | op |= getopt32(argv, "^" | 897 | op |= getopt32(argv, "^" |
850 | OPT_STRING | 898 | OPT_STRING |
@@ -854,43 +902,29 @@ common_traceroute_main(int op, char **argv) | |||
854 | ); | 902 | ); |
855 | argv += optind; | 903 | argv += optind; |
856 | 904 | ||
857 | #if 0 /* IGNORED */ | ||
858 | if (op & OPT_IP_CHKSUM) | ||
859 | bb_error_msg("warning: ip checksums disabled"); | ||
860 | #endif | ||
861 | #ifdef IP_TOS | ||
862 | if (op & OPT_TOS) | ||
863 | tos = xatou_range(tos_str, 0, 255); | ||
864 | #endif | ||
865 | if (op & OPT_MAX_TTL) | 905 | if (op & OPT_MAX_TTL) |
866 | max_ttl = xatou_range(max_ttl_str, 1, 255); | 906 | G.max_ttl = xatou_range(max_ttl_str, 1, 255); |
867 | if (op & OPT_PORT) | 907 | if (op & OPT_PORT) |
868 | port = xatou16(port_str); | 908 | port = xatou16(port_str); |
869 | if (op & OPT_NPROBES) | 909 | if (op & OPT_NPROBES) |
870 | nprobes = xatou_range(nprobes_str, 1, INT_MAX); | 910 | G.nprobes = xatou_range(nprobes_str, 1, INT_MAX); |
871 | if (op & OPT_SOURCE) { | ||
872 | /* | ||
873 | * set the ip source address of the outbound | ||
874 | * probe (e.g., on a multi-homed host). | ||
875 | */ | ||
876 | if (getuid() != 0) | ||
877 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
878 | } | ||
879 | if (op & OPT_WAITTIME) | 911 | if (op & OPT_WAITTIME) |
880 | waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); | 912 | waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); |
881 | if (op & OPT_PAUSE_MS) | 913 | if (op & OPT_PAUSE_MS) |
882 | pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); | 914 | G.pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); |
883 | if (op & OPT_FIRST_TTL) | 915 | if (op & OPT_FIRST_TTL) |
884 | first_ttl = xatou_range(first_ttl_str, 1, max_ttl); | 916 | G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl); |
885 | 917 | ||
886 | /* Process destination and optional packet size */ | 918 | /* Process destination and optional packet size */ |
887 | minpacket = sizeof(struct ip) | 919 | packlen = sizeof(struct ip) |
888 | + SIZEOF_ICMP_HDR | ||
889 | + sizeof(struct outdata_t); | ||
890 | if (!(op & OPT_USE_ICMP)) | ||
891 | minpacket = sizeof(struct ip) | ||
892 | + sizeof(struct udphdr) | 920 | + sizeof(struct udphdr) |
893 | + sizeof(struct outdata_t); | 921 | + sizeof(struct outdata_t); |
922 | if (op & OPT_USE_ICMP) { | ||
923 | packlen = sizeof(struct ip) | ||
924 | + SIZEOF_ICMP_HDR | ||
925 | + sizeof(struct outdata_t); | ||
926 | port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL! */ | ||
927 | } | ||
894 | #if ENABLE_TRACEROUTE6 | 928 | #if ENABLE_TRACEROUTE6 |
895 | af = AF_UNSPEC; | 929 | af = AF_UNSPEC; |
896 | if (op & OPT_IPV4) | 930 | if (op & OPT_IPV4) |
@@ -899,49 +933,73 @@ common_traceroute_main(int op, char **argv) | |||
899 | af = AF_INET6; | 933 | af = AF_INET6; |
900 | dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); | 934 | dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); |
901 | af = dest_lsa->u.sa.sa_family; | 935 | af = dest_lsa->u.sa.sa_family; |
902 | if (af == AF_INET6) | 936 | //TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX) |
903 | minpacket = sizeof(struct ip6_hdr) | 937 | if (af == AF_INET6) { |
904 | + sizeof(struct udphdr) | 938 | G_ipv6 = 1; |
905 | + sizeof(struct outdata6_t); | 939 | packlen = sizeof(struct ip6_hdr) |
940 | + sizeof(struct udphdr) | ||
941 | + sizeof(struct outdata6_t); | ||
942 | if (op & OPT_USE_ICMP) | ||
943 | packlen = sizeof(struct ip6_hdr) | ||
944 | + SIZEOF_ICMP_HDR | ||
945 | + sizeof(struct outdata6_t); | ||
946 | } | ||
906 | #else | 947 | #else |
907 | dest_lsa = xhost2sockaddr(argv[0], port); | 948 | /* accept only IPv4 addresses */ |
949 | dest_lsa = xhost_and_af2sockaddr(argv[0], port, AF_INET); | ||
950 | #endif | ||
951 | G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); | ||
952 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
953 | G.to = xzalloc(dest_lsa->len); | ||
908 | #endif | 954 | #endif |
909 | packlen = minpacket; | ||
910 | if (argv[1]) | 955 | if (argv[1]) |
911 | packlen = xatoul_range(argv[1], minpacket, 32 * 1024); | 956 | packlen = xatoul_range(argv[1], packlen, 32 * 1024); |
912 | |||
913 | /* Ensure the socket fds won't be 0, 1 or 2 */ | ||
914 | bb_sanitize_stdio(); | ||
915 | 957 | ||
958 | if (af == AF_INET) { | ||
959 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); | ||
960 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
961 | /* want recvmsg to report target local address (for -v) */ | ||
962 | setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO); | ||
963 | #endif | ||
964 | } | ||
916 | #if ENABLE_TRACEROUTE6 | 965 | #if ENABLE_TRACEROUTE6 |
917 | if (af == AF_INET6) { | 966 | else { |
918 | xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); | 967 | xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); |
968 | # if ENABLE_FEATURE_TRACEROUTE_VERBOSE | ||
969 | /* want recvmsg to report target local address (for -v) */ | ||
919 | setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); | 970 | setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); |
920 | } else | 971 | # endif |
921 | #endif | ||
922 | { | ||
923 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); | ||
924 | } | 972 | } |
925 | 973 | #endif | |
926 | #if TRACEROUTE_SO_DEBUG | 974 | #if TRACEROUTE_SO_DEBUG |
927 | if (op & OPT_DEBUG) | 975 | if (op & OPT_DEBUG) |
928 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG); | 976 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG); |
929 | #endif | 977 | #endif |
930 | if (op & OPT_BYPASS_ROUTE) | ||
931 | setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); | ||
932 | 978 | ||
979 | { | ||
980 | int snd; | ||
981 | if (af == AF_INET) { | ||
982 | if (op & OPT_USE_ICMP) | ||
983 | snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
984 | else | ||
985 | snd = xsocket(AF_INET, SOCK_DGRAM, 0); | ||
986 | } | ||
933 | #if ENABLE_TRACEROUTE6 | 987 | #if ENABLE_TRACEROUTE6 |
934 | if (af == AF_INET6) { | 988 | # if defined(__FreeBSD__) |
935 | if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) | 989 | # define SOL_V6_OPTION SOL_IPV6 |
936 | bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); | 990 | # else |
937 | xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock); | 991 | # define SOL_V6_OPTION SOL_RAW |
938 | } else | 992 | # endif |
993 | else { | ||
994 | if (setsockopt_int(rcvsock, SOL_V6_OPTION, IPV6_CHECKSUM, 2) != 0) | ||
995 | bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); | ||
996 | if (op & OPT_USE_ICMP) | ||
997 | snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); | ||
998 | else | ||
999 | snd = xsocket(AF_INET6, SOCK_DGRAM, 0); | ||
1000 | } | ||
939 | #endif | 1001 | #endif |
940 | { | 1002 | xmove_fd(snd, sndsock); |
941 | if (op & OPT_USE_ICMP) | ||
942 | xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); | ||
943 | else | ||
944 | xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); | ||
945 | } | 1003 | } |
946 | 1004 | ||
947 | #ifdef SO_SNDBUF | 1005 | #ifdef SO_SNDBUF |
@@ -950,8 +1008,10 @@ common_traceroute_main(int op, char **argv) | |||
950 | } | 1008 | } |
951 | #endif | 1009 | #endif |
952 | #ifdef IP_TOS | 1010 | #ifdef IP_TOS |
953 | if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) { | 1011 | if (op & OPT_TOS) { |
954 | bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos); | 1012 | int tos = xatou_range(tos_str, 0, 255); |
1013 | if (setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) | ||
1014 | bb_perror_msg_and_die("setsockopt(%s,%d)", "TOS", tos); | ||
955 | } | 1015 | } |
956 | #endif | 1016 | #endif |
957 | #ifdef IP_DONTFRAG | 1017 | #ifdef IP_DONTFRAG |
@@ -968,23 +1028,30 @@ common_traceroute_main(int op, char **argv) | |||
968 | outip = xzalloc(packlen); | 1028 | outip = xzalloc(packlen); |
969 | 1029 | ||
970 | ident = getpid(); | 1030 | ident = getpid(); |
971 | 1031 | /* we can use native-endian ident, but other Unix ping/traceroute | |
972 | if (!ENABLE_TRACEROUTE6 || af == AF_INET) { | 1032 | * utils use *big-endian pid*, and e.g. ping on our machine may be |
1033 | * *not* from busybox, idents may collide. Follow the convention: | ||
1034 | */ | ||
1035 | ident = htons(ident); | ||
1036 | |||
1037 | outdata = (void*)(outudp + 1); | ||
1038 | if (af == AF_INET) { | ||
973 | if (op & OPT_USE_ICMP) { | 1039 | if (op & OPT_USE_ICMP) { |
974 | ident |= 0x8000; | ||
975 | outicmp->icmp_type = ICMP_ECHO; | 1040 | outicmp->icmp_type = ICMP_ECHO; |
976 | outicmp->icmp_id = htons(ident); | 1041 | /*outicmp->icmp_code = 0; - set by xzalloc */ |
977 | outdata = (struct outdata_t *)((char *)outicmp + SIZEOF_ICMP_HDR); | 1042 | outicmp->icmp_id = ident; |
978 | } else { | 1043 | outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); |
979 | outdata = (struct outdata_t *)(outudp + 1); | ||
980 | } | 1044 | } |
981 | } | 1045 | } |
982 | #if ENABLE_TRACEROUTE6 | 1046 | #if ENABLE_TRACEROUTE6 |
983 | if (af == AF_INET6) { | 1047 | else { |
984 | outdata = (void*)((char*)outip | 1048 | outdata = (void*)(outudp6 + 1); |
985 | + sizeof(struct ip6_hdr) | 1049 | if (op & OPT_USE_ICMP) { |
986 | + sizeof(struct udphdr) | 1050 | outicmp6->icmp_type = ICMP6_ECHO_REQUEST; |
987 | ); | 1051 | /*outicmp->icmp_code = 0; - set by xzalloc */ |
1052 | outicmp6->icmp_id = ident; | ||
1053 | outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); | ||
1054 | } | ||
988 | } | 1055 | } |
989 | #endif | 1056 | #endif |
990 | 1057 | ||
@@ -998,6 +1065,8 @@ common_traceroute_main(int op, char **argv) | |||
998 | #else | 1065 | #else |
999 | len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); | 1066 | len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); |
1000 | #endif | 1067 | #endif |
1068 | if (getuid() != 0) | ||
1069 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | ||
1001 | /* Ping4 does this (why?) */ | 1070 | /* Ping4 does this (why?) */ |
1002 | if (af == AF_INET) | 1071 | if (af == AF_INET) |
1003 | if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, | 1072 | if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, |
@@ -1006,36 +1075,24 @@ common_traceroute_main(int op, char **argv) | |||
1006 | //TODO: we can query source port we bound to, | 1075 | //TODO: we can query source port we bound to, |
1007 | // and check it in replies... if we care enough | 1076 | // and check it in replies... if we care enough |
1008 | xbind(sndsock, &source_lsa->u.sa, source_lsa->len); | 1077 | xbind(sndsock, &source_lsa->u.sa, source_lsa->len); |
1009 | free(source_lsa); | 1078 | if (ENABLE_FEATURE_CLEAN_UP) |
1010 | } | 1079 | free(source_lsa); |
1011 | #if ENABLE_TRACEROUTE6 | 1080 | } else { |
1012 | else if (af == AF_INET6) { | ||
1013 | //TODO: why we don't do it for IPv4? | ||
1014 | len_and_sockaddr *source_lsa; | 1081 | len_and_sockaddr *source_lsa; |
1015 | 1082 | ||
1016 | int probe_fd = xsocket(af, SOCK_DGRAM, 0); | ||
1017 | if (op & OPT_DEVICE) | ||
1018 | setsockopt_bindtodevice(probe_fd, device); | ||
1019 | set_nport(&dest_lsa->u.sa, htons(1025)); | ||
1020 | /* dummy connect. makes kernel pick source IP (and port) */ | ||
1021 | xconnect(probe_fd, &dest_lsa->u.sa, dest_lsa->len); | ||
1022 | set_nport(&dest_lsa->u.sa, htons(port)); | 1083 | set_nport(&dest_lsa->u.sa, htons(port)); |
1023 | 1084 | /* Connect makes kernel pick source IP (and port if UDP) */ | |
1024 | /* read IP and port */ | 1085 | xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len); |
1025 | source_lsa = get_sock_lsa(probe_fd); | 1086 | /* Read IP and port */ |
1087 | source_lsa = get_sock_lsa(sndsock); | ||
1026 | if (source_lsa == NULL) | 1088 | if (source_lsa == NULL) |
1027 | bb_simple_error_msg_and_die("can't get probe addr"); | 1089 | bb_simple_perror_msg_and_die("getsockname"); |
1028 | 1090 | /* bind our recv ICMP socket to this IP (but not port, ICMP has no ports) */ | |
1029 | close(probe_fd); | 1091 | //set_nport(&source_lsa->u.sa, 0); - paranoia, seems to work without this for both ipv4 and ipv6 |
1030 | |||
1031 | /* bind our sockets to this IP (but not port) */ | ||
1032 | set_nport(&source_lsa->u.sa, 0); | ||
1033 | xbind(sndsock, &source_lsa->u.sa, source_lsa->len); | ||
1034 | xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); | 1092 | xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); |
1035 | 1093 | if (ENABLE_FEATURE_CLEAN_UP) | |
1036 | free(source_lsa); | 1094 | free(source_lsa); |
1037 | } | 1095 | } |
1038 | #endif | ||
1039 | 1096 | ||
1040 | /* Revert to non-privileged user after opening sockets */ | 1097 | /* Revert to non-privileged user after opening sockets */ |
1041 | xsetgid(getgid()); | 1098 | xsetgid(getgid()); |
@@ -1043,169 +1100,177 @@ common_traceroute_main(int op, char **argv) | |||
1043 | 1100 | ||
1044 | dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa); | 1101 | dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa); |
1045 | printf("traceroute to %s (%s)", argv[0], dest_str); | 1102 | printf("traceroute to %s (%s)", argv[0], dest_str); |
1046 | if (ENABLE_FEATURE_CLEAN_UP) { | 1103 | if (ENABLE_FEATURE_CLEAN_UP) |
1047 | free(dest_str); | 1104 | free(dest_str); |
1048 | } | ||
1049 | 1105 | ||
1050 | if (op & OPT_SOURCE) | 1106 | if (op & OPT_SOURCE) |
1051 | printf(" from %s", source); | 1107 | printf(" from %s", source); |
1052 | printf(", %d hops max, %d byte packets\n", max_ttl, packlen); | 1108 | printf(", %d hops max, %d byte packets\n", G.max_ttl, packlen); |
1109 | } | ||
1110 | |||
1111 | static int | ||
1112 | common_traceroute_main(int op, char **argv) | ||
1113 | { | ||
1114 | int ttl; | ||
1115 | int seq; | ||
1116 | struct sockaddr *lastaddr; | ||
1117 | |||
1118 | traceroute_init(op, argv); | ||
1053 | 1119 | ||
1054 | from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); | ||
1055 | lastaddr = xzalloc(dest_lsa->len); | 1120 | lastaddr = xzalloc(dest_lsa->len); |
1056 | to = xzalloc(dest_lsa->len); | ||
1057 | seq = 0; | 1121 | seq = 0; |
1058 | for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { | 1122 | for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) { |
1059 | int probe; | 1123 | int probe; |
1060 | int unreachable = 0; /* counter */ | 1124 | int unreachable = 0; /* counter */ |
1061 | int gotlastaddr = 0; /* flags */ | ||
1062 | int got_there = 0; | 1125 | int got_there = 0; |
1063 | 1126 | ||
1064 | printf("%2d", ttl); | 1127 | printf("%2d", ttl); |
1065 | for (probe = 0; probe < nprobes; ++probe) { | 1128 | for (probe = 0; probe < G.nprobes; ++probe) { |
1066 | int read_len; | ||
1067 | unsigned t1; | 1129 | unsigned t1; |
1068 | unsigned t2; | 1130 | unsigned t2; |
1069 | int left_ms; | 1131 | int left_ms; |
1070 | struct ip *ip; | 1132 | int read_len; |
1133 | int icmp_code; | ||
1071 | 1134 | ||
1072 | fflush_all(); | 1135 | fflush_all(); |
1073 | if (probe != 0 && pausemsecs > 0) | 1136 | if (probe != 0) |
1074 | usleep(pausemsecs * 1000); | 1137 | msleep(G.pausemsecs); |
1075 | 1138 | ||
1076 | send_probe(++seq, ttl); | 1139 | send_probe(++seq, ttl); |
1077 | t2 = t1 = monotonic_us(); | ||
1078 | 1140 | ||
1141 | t2 = t1 = monotonic_us(); | ||
1079 | left_ms = waittime * 1000; | 1142 | left_ms = waittime * 1000; |
1080 | while ((read_len = wait_for_reply(from_lsa, to, &t2, &left_ms)) != 0) { | 1143 | for (;;) { |
1081 | int icmp_code; | 1144 | /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with |
1082 | 1145 | * "where it came from" and "what local address it arrived to" | |
1083 | /* Recv'ed a packet, or read error */ | 1146 | * addresses. Sets t2 = monotonic_us(), updates left_ms. |
1084 | /* t2 = monotonic_us() - set by wait_for_reply */ | 1147 | */ |
1085 | 1148 | read_len = wait_for_reply(&t2, &left_ms); | |
1086 | if (read_len < 0) | 1149 | |
1087 | continue; | 1150 | if (read_len == 0) { /* there was no packet at all? */ |
1088 | icmp_code = packet_ok(read_len, from_lsa, to, seq); | 1151 | printf(" *"); |
1089 | /* Skip short packet */ | 1152 | goto next_probe; |
1090 | if (icmp_code == 0) | ||
1091 | continue; | ||
1092 | |||
1093 | if (!gotlastaddr | ||
1094 | || (memcmp(lastaddr, &from_lsa->u.sa, from_lsa->len) != 0) | ||
1095 | ) { | ||
1096 | print(read_len, &from_lsa->u.sa, to); | ||
1097 | memcpy(lastaddr, &from_lsa->u.sa, from_lsa->len); | ||
1098 | gotlastaddr = 1; | ||
1099 | } | 1153 | } |
1154 | icmp_code = packet_ok(read_len, seq); | ||
1155 | if (icmp_code != 0) | ||
1156 | break; /* got a good response */ | ||
1157 | /* unrecognized type/code or too short, back to recv */ | ||
1158 | } | ||
1100 | 1159 | ||
1101 | print_delta_ms(t1, t2); | 1160 | if (probe == 0 |
1102 | ip = (struct ip *)recv_pkt; | 1161 | || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0) |
1162 | ) { | ||
1163 | print(read_len); | ||
1164 | memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len); | ||
1165 | } | ||
1166 | print_delta_ms(t1, t2); | ||
1167 | if (!G_ipv6) { | ||
1168 | if (op & OPT_TTL_FLAG) { | ||
1169 | struct ip *ip = (struct ip *)recv_pkt; | ||
1170 | printf(" (%d)", ip->ip_ttl); | ||
1171 | } | ||
1172 | } | ||
1103 | 1173 | ||
1104 | if (from_lsa->u.sa.sa_family == AF_INET) | 1174 | /* Got a "time exceeded in transit" icmp message? */ |
1105 | if (op & OPT_TTL_FLAG) | 1175 | if (icmp_code == -1) |
1106 | printf(" (%d)", ip->ip_ttl); | 1176 | continue; |
1107 | 1177 | ||
1108 | /* time exceeded in transit */ | 1178 | icmp_code--; |
1109 | if (icmp_code == -1) | 1179 | switch (icmp_code) { |
1110 | break; | ||
1111 | icmp_code--; | ||
1112 | switch (icmp_code) { | ||
1113 | #if ENABLE_TRACEROUTE6 | 1180 | #if ENABLE_TRACEROUTE6 |
1114 | case ICMP6_DST_UNREACH_NOPORT << 8: | 1181 | case ICMP6_DST_UNREACH_NOPORT << 8: |
1115 | got_there = 1; | 1182 | got_there = 1; |
1116 | break; | 1183 | break; |
1117 | #endif | 1184 | #endif |
1118 | case ICMP_UNREACH_PORT: | 1185 | case ICMP_UNREACH_PORT: { |
1119 | if (ip->ip_ttl <= 1) | 1186 | struct ip *ip = (struct ip *)recv_pkt; |
1120 | printf(" !"); | 1187 | if (ip->ip_ttl <= 1) |
1121 | got_there = 1; | 1188 | printf(" !"); |
1122 | break; | 1189 | got_there = 1; |
1123 | 1190 | break; | |
1124 | case ICMP_UNREACH_NET: | 1191 | } |
1192 | case ICMP_UNREACH_NET: | ||
1125 | #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) | 1193 | #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) |
1126 | case ICMP6_DST_UNREACH_NOROUTE << 8: | 1194 | case ICMP6_DST_UNREACH_NOROUTE << 8: |
1127 | #endif | 1195 | #endif |
1128 | printf(" !N"); | 1196 | printf(" !N"); |
1129 | ++unreachable; | 1197 | ++unreachable; |
1130 | break; | 1198 | break; |
1131 | case ICMP_UNREACH_HOST: | 1199 | case ICMP_UNREACH_HOST: |
1132 | #if ENABLE_TRACEROUTE6 | 1200 | #if ENABLE_TRACEROUTE6 |
1133 | case ICMP6_DST_UNREACH_ADDR << 8: | 1201 | case ICMP6_DST_UNREACH_ADDR << 8: |
1134 | #endif | 1202 | #endif |
1135 | printf(" !H"); | 1203 | printf(" !H"); |
1136 | ++unreachable; | 1204 | ++unreachable; |
1137 | break; | 1205 | break; |
1138 | case ICMP_UNREACH_PROTOCOL: | 1206 | case ICMP_UNREACH_PROTOCOL: |
1139 | printf(" !P"); | 1207 | printf(" !P"); |
1140 | got_there = 1; | 1208 | got_there = 1; |
1141 | break; | 1209 | break; |
1142 | case ICMP_UNREACH_NEEDFRAG: | 1210 | case ICMP_UNREACH_NEEDFRAG: |
1143 | printf(" !F-%d", pmtu); | 1211 | printf(" !F-%d", pmtu); |
1144 | ++unreachable; | 1212 | ++unreachable; |
1145 | break; | 1213 | break; |
1146 | case ICMP_UNREACH_SRCFAIL: | 1214 | case ICMP_UNREACH_SRCFAIL: |
1147 | #if ENABLE_TRACEROUTE6 | 1215 | #if ENABLE_TRACEROUTE6 |
1148 | case ICMP6_DST_UNREACH_ADMIN << 8: | 1216 | case ICMP6_DST_UNREACH_ADMIN << 8: |
1149 | #endif | 1217 | #endif |
1150 | printf(" !S"); | 1218 | printf(" !S"); |
1151 | ++unreachable; | 1219 | ++unreachable; |
1152 | break; | ||
1153 | case ICMP_UNREACH_FILTER_PROHIB: | ||
1154 | case ICMP_UNREACH_NET_PROHIB: /* misuse */ | ||
1155 | printf(" !A"); | ||
1156 | ++unreachable; | ||
1157 | break; | ||
1158 | case ICMP_UNREACH_HOST_PROHIB: | ||
1159 | printf(" !C"); | ||
1160 | ++unreachable; | ||
1161 | break; | ||
1162 | case ICMP_UNREACH_HOST_PRECEDENCE: | ||
1163 | printf(" !V"); | ||
1164 | ++unreachable; | ||
1165 | break; | ||
1166 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: | ||
1167 | printf(" !C"); | ||
1168 | ++unreachable; | ||
1169 | break; | ||
1170 | case ICMP_UNREACH_NET_UNKNOWN: | ||
1171 | case ICMP_UNREACH_HOST_UNKNOWN: | ||
1172 | printf(" !U"); | ||
1173 | ++unreachable; | ||
1174 | break; | ||
1175 | case ICMP_UNREACH_ISOLATED: | ||
1176 | printf(" !I"); | ||
1177 | ++unreachable; | ||
1178 | break; | ||
1179 | case ICMP_UNREACH_TOSNET: | ||
1180 | case ICMP_UNREACH_TOSHOST: | ||
1181 | printf(" !T"); | ||
1182 | ++unreachable; | ||
1183 | break; | ||
1184 | default: | ||
1185 | printf(" !<%d>", icmp_code); | ||
1186 | ++unreachable; | ||
1187 | break; | ||
1188 | } | ||
1189 | break; | 1220 | break; |
1190 | } /* while (wait and read a packet) */ | 1221 | case ICMP_UNREACH_FILTER_PROHIB: |
1191 | 1222 | case ICMP_UNREACH_NET_PROHIB: /* misuse */ | |
1192 | /* there was no packet at all? */ | 1223 | printf(" !A"); |
1193 | if (read_len == 0) | 1224 | ++unreachable; |
1194 | printf(" *"); | 1225 | break; |
1226 | case ICMP_UNREACH_HOST_PROHIB: | ||
1227 | printf(" !C"); | ||
1228 | ++unreachable; | ||
1229 | break; | ||
1230 | case ICMP_UNREACH_HOST_PRECEDENCE: | ||
1231 | printf(" !V"); | ||
1232 | ++unreachable; | ||
1233 | break; | ||
1234 | case ICMP_UNREACH_PRECEDENCE_CUTOFF: | ||
1235 | printf(" !C"); | ||
1236 | ++unreachable; | ||
1237 | break; | ||
1238 | case ICMP_UNREACH_NET_UNKNOWN: | ||
1239 | case ICMP_UNREACH_HOST_UNKNOWN: | ||
1240 | printf(" !U"); | ||
1241 | ++unreachable; | ||
1242 | break; | ||
1243 | case ICMP_UNREACH_ISOLATED: | ||
1244 | printf(" !I"); | ||
1245 | ++unreachable; | ||
1246 | break; | ||
1247 | case ICMP_UNREACH_TOSNET: | ||
1248 | case ICMP_UNREACH_TOSHOST: | ||
1249 | printf(" !T"); | ||
1250 | ++unreachable; | ||
1251 | break; | ||
1252 | default: | ||
1253 | printf(" !<%d>", icmp_code); | ||
1254 | ++unreachable; | ||
1255 | break; | ||
1256 | } | ||
1257 | next_probe: ; | ||
1195 | } /* for (nprobes) */ | 1258 | } /* for (nprobes) */ |
1196 | 1259 | ||
1197 | bb_putchar('\n'); | 1260 | bb_putchar('\n'); |
1198 | if (got_there | 1261 | if (got_there |
1199 | || (unreachable > 0 && unreachable >= nprobes - 1) | 1262 | || (unreachable > 0 && unreachable >= G.nprobes - 1) |
1200 | ) { | 1263 | ) { |
1201 | break; | 1264 | break; |
1202 | } | 1265 | } |
1203 | } | 1266 | } |
1204 | 1267 | ||
1205 | if (ENABLE_FEATURE_CLEAN_UP) { | 1268 | if (ENABLE_FEATURE_CLEAN_UP) { |
1206 | free(to); | 1269 | #if ENABLE_FEATURE_TRACEROUTE_VERBOSE |
1270 | free(G.to); | ||
1271 | #endif | ||
1207 | free(lastaddr); | 1272 | free(lastaddr); |
1208 | free(from_lsa); | 1273 | free(G.from_lsa); |
1209 | } | 1274 | } |
1210 | 1275 | ||
1211 | return 0; | 1276 | return 0; |
diff --git a/networking/tunctl.c b/networking/tunctl.c index 0f010e196..97e6917aa 100644 --- a/networking/tunctl.c +++ b/networking/tunctl.c | |||
@@ -28,16 +28,16 @@ | |||
28 | //kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o | 28 | //kbuild:lib-$(CONFIG_TUNCTL) += tunctl.o |
29 | 29 | ||
30 | //usage:#define tunctl_trivial_usage | 30 | //usage:#define tunctl_trivial_usage |
31 | //usage: "[-f device] ([-t name] | -d name)" IF_FEATURE_TUNCTL_UG(" [-u owner] [-g group] [-b]") | 31 | //usage: "[-f DEVICE] [-t NAME | -d NAME]" IF_FEATURE_TUNCTL_UG(" [-u USER] [-g GRP] [-b]") |
32 | //usage:#define tunctl_full_usage "\n\n" | 32 | //usage:#define tunctl_full_usage "\n\n" |
33 | //usage: "Create or delete tun interfaces\n" | 33 | //usage: "Create or delete TUN/TAP interfaces\n" |
34 | //usage: "\n -f name tun device (/dev/net/tun)" | 34 | //usage: "\n -f DEV TUN device (default /dev/net/tun)" |
35 | //usage: "\n -t name Create iface 'name'" | 35 | //usage: "\n -t NAME Create iface (default: tapN)" |
36 | //usage: "\n -d name Delete iface 'name'" | 36 | //usage: "\n -d NAME Delete iface" |
37 | //usage: IF_FEATURE_TUNCTL_UG( | 37 | //usage: IF_FEATURE_TUNCTL_UG( |
38 | //usage: "\n -u owner Set iface owner" | 38 | //usage: "\n -u USER Set iface owner" |
39 | //usage: "\n -g group Set iface group" | 39 | //usage: "\n -g GRP Set iface group" |
40 | //usage: "\n -b Brief output" | 40 | //usage: "\n -b Brief output" |
41 | //usage: ) | 41 | //usage: ) |
42 | //usage: | 42 | //usage: |
43 | //usage:#define tunctl_example_usage | 43 | //usage:#define tunctl_example_usage |
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 7d04bb246..8c8c11c26 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src | |||
@@ -104,6 +104,14 @@ INSERT | |||
104 | comment "Common options for DHCP applets" | 104 | comment "Common options for DHCP applets" |
105 | depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY | 105 | depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY |
106 | 106 | ||
107 | config UDHCPC_DEFAULT_INTERFACE | ||
108 | string "Default interface name" | ||
109 | default "eth0" | ||
110 | depends on UDHCPC || UDHCPC6 | ||
111 | help | ||
112 | The interface that will be used if no other interface is | ||
113 | specified on the commandline. | ||
114 | |||
107 | config FEATURE_UDHCP_PORT | 115 | config FEATURE_UDHCP_PORT |
108 | bool "Enable '-P port' option for udhcpd and udhcpc" | 116 | bool "Enable '-P port' option for udhcpd and udhcpc" |
109 | default n | 117 | default n |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 3cbd2d3c8..cc0abd269 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -343,7 +343,8 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
343 | 343 | ||
344 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 344 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, |
345 | uint32_t source_nip, int source_port, | 345 | uint32_t source_nip, int source_port, |
346 | uint32_t dest_nip, int dest_port) FAST_FUNC; | 346 | uint32_t dest_nip, int dest_port, |
347 | const char *ifname) FAST_FUNC; | ||
347 | 348 | ||
348 | void udhcp_sp_setup(void) FAST_FUNC; | 349 | void udhcp_sp_setup(void) FAST_FUNC; |
349 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 350 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 688f5d6c7..9dfde7709 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h | |||
@@ -159,18 +159,16 @@ int FAST_FUNC d6_recv_kernel_packet( | |||
159 | struct d6_packet *packet, int fd | 159 | struct d6_packet *packet, int fd |
160 | ); | 160 | ); |
161 | 161 | ||
162 | int FAST_FUNC d6_send_raw_packet( | 162 | int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( |
163 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 163 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
164 | struct in6_addr *src_ipv6, int source_port, | 164 | struct in6_addr *src_ipv6, int source_port, |
165 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp, | 165 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp |
166 | int ifindex | ||
167 | ); | 166 | ); |
168 | 167 | ||
169 | int FAST_FUNC d6_send_kernel_packet( | 168 | int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( |
170 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 169 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
171 | struct in6_addr *src_ipv6, int source_port, | 170 | struct in6_addr *src_ipv6, int source_port, |
172 | struct in6_addr *dst_ipv6, int dest_port, | 171 | struct in6_addr *dst_ipv6, int dest_port |
173 | int ifindex | ||
174 | ); | 172 | ); |
175 | 173 | ||
176 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | 174 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index ac8af91d3..fbdaa99bd 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -558,11 +558,10 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * | |||
558 | 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, | 558 | 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, |
559 | }; | 559 | }; |
560 | 560 | ||
561 | return d6_send_raw_packet( | 561 | return d6_send_raw_packet_from_client_data_ifindex( |
562 | packet, (end - (uint8_t*) packet), | 562 | packet, (end - (uint8_t*) packet), |
563 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, | 563 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, |
564 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR, | 564 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR |
565 | client_data.ifindex | ||
566 | ); | 565 | ); |
567 | } | 566 | } |
568 | 567 | ||
@@ -864,11 +863,10 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st | |||
864 | 863 | ||
865 | bb_info_msg("sending %s", "renew"); | 864 | bb_info_msg("sending %s", "renew"); |
866 | if (server_ipv6) | 865 | if (server_ipv6) |
867 | return d6_send_kernel_packet( | 866 | return d6_send_kernel_packet_from_client_data_ifindex( |
868 | &packet, (opt_ptr - (uint8_t*) &packet), | 867 | &packet, (opt_ptr - (uint8_t*) &packet), |
869 | our_cur_ipv6, CLIENT_PORT6, | 868 | our_cur_ipv6, CLIENT_PORT6, |
870 | server_ipv6, SERVER_PORT6, | 869 | server_ipv6, SERVER_PORT6 |
871 | client_data.ifindex | ||
872 | ); | 870 | ); |
873 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); | 871 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); |
874 | } | 872 | } |
@@ -893,11 +891,10 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | |||
893 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 891 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
894 | 892 | ||
895 | bb_info_msg("sending %s", "release"); | 893 | bb_info_msg("sending %s", "release"); |
896 | return d6_send_kernel_packet( | 894 | return d6_send_kernel_packet_from_client_data_ifindex( |
897 | &packet, (opt_ptr - (uint8_t*) &packet), | 895 | &packet, (opt_ptr - (uint8_t*) &packet), |
898 | our_cur_ipv6, CLIENT_PORT6, | 896 | our_cur_ipv6, CLIENT_PORT6, |
899 | server_ipv6, SERVER_PORT6, | 897 | server_ipv6, SERVER_PORT6 |
900 | client_data.ifindex | ||
901 | ); | 898 | ); |
902 | } | 899 | } |
903 | 900 | ||
@@ -1164,9 +1161,9 @@ static void client_background(void) | |||
1164 | //usage:#endif | 1161 | //usage:#endif |
1165 | //usage:#define udhcpc6_trivial_usage | 1162 | //usage:#define udhcpc6_trivial_usage |
1166 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"odR] [-i IFACE] [-r IPv6] [-s PROG] [-p PIDFILE]\n" | 1163 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"odR] [-i IFACE] [-r IPv6] [-s PROG] [-p PIDFILE]\n" |
1167 | //usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") | 1164 | //usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P PORT]") |
1168 | //usage:#define udhcpc6_full_usage "\n" | 1165 | //usage:#define udhcpc6_full_usage "\n" |
1169 | //usage: "\n -i IFACE Interface to use (default eth0)" | 1166 | //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" |
1170 | //usage: "\n -p FILE Create pidfile" | 1167 | //usage: "\n -p FILE Create pidfile" |
1171 | //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" | 1168 | //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" |
1172 | //usage: "\n -B Request broadcast replies" | 1169 | //usage: "\n -B Request broadcast replies" |
@@ -1182,7 +1179,7 @@ static void client_background(void) | |||
1182 | //usage: "\n -R Release IP on exit" | 1179 | //usage: "\n -R Release IP on exit" |
1183 | //usage: "\n -S Log to syslog too" | 1180 | //usage: "\n -S Log to syslog too" |
1184 | //usage: IF_FEATURE_UDHCP_PORT( | 1181 | //usage: IF_FEATURE_UDHCP_PORT( |
1185 | //usage: "\n -P N Use port N (default 546)" | 1182 | //usage: "\n -P PORT Use PORT (default 546)" |
1186 | //usage: ) | 1183 | //usage: ) |
1187 | ////usage: IF_FEATURE_UDHCPC_ARPING( | 1184 | ////usage: IF_FEATURE_UDHCPC_ARPING( |
1188 | ////usage: "\n -a Use arping to validate offered address" | 1185 | ////usage: "\n -a Use arping to validate offered address" |
@@ -1234,7 +1231,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1234 | /* Default options */ | 1231 | /* Default options */ |
1235 | IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) | 1232 | IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) |
1236 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) | 1233 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) |
1237 | client_data.interface = "eth0"; | 1234 | client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; |
1238 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; | 1235 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
1239 | client_data.sockfd = -1; | 1236 | client_data.sockfd = -1; |
1240 | 1237 | ||
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index 167a813e3..172f8e1ab 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | #include "common.h" | 7 | #include "common.h" |
8 | #include "d6_common.h" | 8 | #include "d6_common.h" |
9 | #include "dhcpc.h" | ||
9 | #include "dhcpd.h" | 10 | #include "dhcpd.h" |
10 | #include <netinet/in.h> | 11 | #include <netinet/in.h> |
11 | #include <netinet/if_ether.h> | 12 | #include <netinet/if_ether.h> |
@@ -50,11 +51,10 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 | |||
50 | } | 51 | } |
51 | 52 | ||
52 | /* Construct a ipv6+udp header for a packet, send packet */ | 53 | /* Construct a ipv6+udp header for a packet, send packet */ |
53 | int FAST_FUNC d6_send_raw_packet( | 54 | int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( |
54 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 55 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
55 | struct in6_addr *src_ipv6, int source_port, | 56 | struct in6_addr *src_ipv6, int source_port, |
56 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp, | 57 | struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp) |
57 | int ifindex) | ||
58 | { | 58 | { |
59 | struct sockaddr_ll dest_sll; | 59 | struct sockaddr_ll dest_sll; |
60 | struct ip6_udp_d6_packet packet; | 60 | struct ip6_udp_d6_packet packet; |
@@ -74,7 +74,7 @@ int FAST_FUNC d6_send_raw_packet( | |||
74 | 74 | ||
75 | dest_sll.sll_family = AF_PACKET; | 75 | dest_sll.sll_family = AF_PACKET; |
76 | dest_sll.sll_protocol = htons(ETH_P_IPV6); | 76 | dest_sll.sll_protocol = htons(ETH_P_IPV6); |
77 | dest_sll.sll_ifindex = ifindex; | 77 | dest_sll.sll_ifindex = client_data.ifindex; |
78 | /*dest_sll.sll_hatype = ARPHRD_???;*/ | 78 | /*dest_sll.sll_hatype = ARPHRD_???;*/ |
79 | /*dest_sll.sll_pkttype = PACKET_???;*/ | 79 | /*dest_sll.sll_pkttype = PACKET_???;*/ |
80 | dest_sll.sll_halen = 6; | 80 | dest_sll.sll_halen = 6; |
@@ -103,8 +103,8 @@ int FAST_FUNC d6_send_raw_packet( | |||
103 | */ | 103 | */ |
104 | packet.ip6.ip6_hlim = IPPROTO_UDP; | 104 | packet.ip6.ip6_hlim = IPPROTO_UDP; |
105 | packet.udp.check = inet_cksum( | 105 | packet.udp.check = inet_cksum( |
106 | (uint8_t *)&packet + 4, | 106 | (uint8_t *)&packet + 4, |
107 | offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size | 107 | offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size |
108 | ); | 108 | ); |
109 | /* fix 'hop limit' and 'next header' after UDP checksumming */ | 109 | /* fix 'hop limit' and 'next header' after UDP checksumming */ |
110 | packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */ | 110 | packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */ |
@@ -126,11 +126,10 @@ int FAST_FUNC d6_send_raw_packet( | |||
126 | } | 126 | } |
127 | 127 | ||
128 | /* Let the kernel do all the work for packet generation */ | 128 | /* Let the kernel do all the work for packet generation */ |
129 | int FAST_FUNC d6_send_kernel_packet( | 129 | int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( |
130 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, | 130 | struct d6_packet *d6_pkt, unsigned d6_pkt_size, |
131 | struct in6_addr *src_ipv6, int source_port, | 131 | struct in6_addr *src_ipv6, int source_port, |
132 | struct in6_addr *dst_ipv6, int dest_port, | 132 | struct in6_addr *dst_ipv6, int dest_port) |
133 | int ifindex) | ||
134 | { | 133 | { |
135 | struct sockaddr_in6 sa; | 134 | struct sockaddr_in6 sa; |
136 | int fd; | 135 | int fd; |
@@ -157,7 +156,7 @@ int FAST_FUNC d6_send_kernel_packet( | |||
157 | sa.sin6_family = AF_INET6; | 156 | sa.sin6_family = AF_INET6; |
158 | sa.sin6_port = htons(dest_port); | 157 | sa.sin6_port = htons(dest_port); |
159 | sa.sin6_addr = *dst_ipv6; /* struct copy */ | 158 | sa.sin6_addr = *dst_ipv6; /* struct copy */ |
160 | sa.sin6_scope_id = ifindex; | 159 | sa.sin6_scope_id = client_data.ifindex; |
161 | if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { | 160 | if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { |
162 | msg = "connect"; | 161 | msg = "connect"; |
163 | goto ret_close; | 162 | goto ret_close; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 66aa38c20..922c71ebd 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -702,7 +702,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t | |||
702 | if (server) | 702 | if (server) |
703 | return udhcp_send_kernel_packet(packet, | 703 | return udhcp_send_kernel_packet(packet, |
704 | ciaddr, CLIENT_PORT, | 704 | ciaddr, CLIENT_PORT, |
705 | server, SERVER_PORT); | 705 | server, SERVER_PORT, |
706 | client_data.interface); | ||
706 | return raw_bcast_from_client_data_ifindex(packet, ciaddr); | 707 | return raw_bcast_from_client_data_ifindex(packet, ciaddr); |
707 | } | 708 | } |
708 | 709 | ||
@@ -1195,7 +1196,7 @@ static void client_background(void) | |||
1195 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" | 1196 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" |
1196 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." | 1197 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." |
1197 | //usage:#define udhcpc_full_usage "\n" | 1198 | //usage:#define udhcpc_full_usage "\n" |
1198 | //usage: "\n -i IFACE Interface to use (default eth0)" | 1199 | //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" |
1199 | //usage: IF_FEATURE_UDHCP_PORT( | 1200 | //usage: IF_FEATURE_UDHCP_PORT( |
1200 | //usage: "\n -P PORT Use PORT (default 68)" | 1201 | //usage: "\n -P PORT Use PORT (default 68)" |
1201 | //usage: ) | 1202 | //usage: ) |
@@ -1264,7 +1265,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1264 | /* Default options */ | 1265 | /* Default options */ |
1265 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) | 1266 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) |
1266 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) | 1267 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) |
1267 | client_data.interface = "eth0"; | 1268 | client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; |
1268 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; | 1269 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
1269 | client_data.sockfd = -1; | 1270 | client_data.sockfd = -1; |
1270 | str_V = "udhcp "BB_VER; | 1271 | str_V = "udhcp "BB_VER; |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index acfdaa8c3..cd32cb437 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -27,7 +27,7 @@ | |||
27 | //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o | 27 | //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o |
28 | 28 | ||
29 | //usage:#define udhcpd_trivial_usage | 29 | //usage:#define udhcpd_trivial_usage |
30 | //usage: "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]" | 30 | //usage: "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P PORT]") " [CONFFILE]" |
31 | //usage:#define udhcpd_full_usage "\n\n" | 31 | //usage:#define udhcpd_full_usage "\n\n" |
32 | //usage: "DHCP server\n" | 32 | //usage: "DHCP server\n" |
33 | //usage: "\n -f Run in foreground" | 33 | //usage: "\n -f Run in foreground" |
@@ -35,7 +35,7 @@ | |||
35 | //usage: "\n -I ADDR Local address" | 35 | //usage: "\n -I ADDR Local address" |
36 | //usage: "\n -a MSEC Timeout for ARP ping (default 2000)" | 36 | //usage: "\n -a MSEC Timeout for ARP ping (default 2000)" |
37 | //usage: IF_FEATURE_UDHCP_PORT( | 37 | //usage: IF_FEATURE_UDHCP_PORT( |
38 | //usage: "\n -P N Use port N (default 67)" | 38 | //usage: "\n -P PORT Use PORT (default 67)" |
39 | //usage: ) | 39 | //usage: ) |
40 | //usage: "\nSignals:" | 40 | //usage: "\nSignals:" |
41 | //usage: "\n USR1 Update lease file" | 41 | //usage: "\n USR1 Update lease file" |
@@ -398,7 +398,7 @@ struct config_keyword { | |||
398 | 398 | ||
399 | #define OFS(field) offsetof(struct server_data_t, field) | 399 | #define OFS(field) offsetof(struct server_data_t, field) |
400 | 400 | ||
401 | static const struct config_keyword keywords[] = { | 401 | static const struct config_keyword keywords[] ALIGN_PTR = { |
402 | /* keyword handler variable address default */ | 402 | /* keyword handler variable address default */ |
403 | {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, | 403 | {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, |
404 | {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, | 404 | {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, |
@@ -612,7 +612,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) | |||
612 | 612 | ||
613 | udhcp_send_kernel_packet(dhcp_pkt, | 613 | udhcp_send_kernel_packet(dhcp_pkt, |
614 | server_data.server_nip, SERVER_PORT, | 614 | server_data.server_nip, SERVER_PORT, |
615 | dhcp_pkt->gateway_nip, SERVER_PORT); | 615 | dhcp_pkt->gateway_nip, SERVER_PORT, |
616 | server_data.interface); | ||
616 | } | 617 | } |
617 | 618 | ||
618 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) | 619 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) |
diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c index 70d2d1434..1e9405205 100644 --- a/networking/udhcp/dumpleases.c +++ b/networking/udhcp/dumpleases.c | |||
@@ -10,18 +10,10 @@ | |||
10 | //usage: "[-r|-a] [-d] [-f LEASEFILE]" | 10 | //usage: "[-r|-a] [-d] [-f LEASEFILE]" |
11 | //usage:#define dumpleases_full_usage "\n\n" | 11 | //usage:#define dumpleases_full_usage "\n\n" |
12 | //usage: "Display DHCP leases granted by udhcpd\n" | 12 | //usage: "Display DHCP leases granted by udhcpd\n" |
13 | //usage: IF_LONG_OPTS( | ||
14 | //usage: "\n -f,--file FILE Lease file" | ||
15 | //usage: "\n -r,--remaining Show remaining time" | ||
16 | //usage: "\n -a,--absolute Show expiration time" | ||
17 | //usage: "\n -d,--decimal Show time in seconds" | ||
18 | //usage: ) | ||
19 | //usage: IF_NOT_LONG_OPTS( | ||
20 | //usage: "\n -f FILE Lease file" | 13 | //usage: "\n -f FILE Lease file" |
21 | //usage: "\n -r Show remaining time" | 14 | //usage: "\n -r Show remaining time" |
22 | //usage: "\n -a Show expiration time" | 15 | //usage: "\n -a Show expiration time" |
23 | //usage: "\n -d Show time in seconds" | 16 | //usage: "\n -d Show time in seconds" |
24 | //usage: ) | ||
25 | 17 | ||
26 | #include "common.h" | 18 | #include "common.h" |
27 | #include "dhcpd.h" | 19 | #include "dhcpd.h" |
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 51374646d..4d8e005d4 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c | |||
@@ -189,7 +189,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
189 | /* Let the kernel do all the work for packet generation */ | 189 | /* Let the kernel do all the work for packet generation */ |
190 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 190 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, |
191 | uint32_t source_nip, int source_port, | 191 | uint32_t source_nip, int source_port, |
192 | uint32_t dest_nip, int dest_port) | 192 | uint32_t dest_nip, int dest_port, |
193 | const char *ifname) | ||
193 | { | 194 | { |
194 | struct sockaddr_in sa; | 195 | struct sockaddr_in sa; |
195 | unsigned padding; | 196 | unsigned padding; |
@@ -204,6 +205,21 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |||
204 | } | 205 | } |
205 | setsockopt_reuseaddr(fd); | 206 | setsockopt_reuseaddr(fd); |
206 | 207 | ||
208 | /* If interface carrier goes down, unless we | ||
209 | * bind socket to a particular netdev, the packet | ||
210 | * can go out through another interface, eg. via | ||
211 | * default route despite being bound to a specific | ||
212 | * source IP. As such, bind to device hard and fail | ||
213 | * otherwise. Sending renewal packets on foreign | ||
214 | * interfaces makes no sense. | ||
215 | */ | ||
216 | if (ifname) { | ||
217 | if (setsockopt_bindtodevice(fd, ifname) < 0) { | ||
218 | msg = "bindtodevice"; | ||
219 | goto ret_close; | ||
220 | } | ||
221 | } | ||
222 | |||
207 | memset(&sa, 0, sizeof(sa)); | 223 | memset(&sa, 0, sizeof(sa)); |
208 | sa.sin_family = AF_INET; | 224 | sa.sin_family = AF_INET; |
209 | sa.sin_port = htons(source_port); | 225 | sa.sin_port = htons(source_port); |
diff --git a/networking/wget.c b/networking/wget.c index 8a967fe20..270eab141 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -128,19 +128,14 @@ | |||
128 | 128 | ||
129 | //usage:#define wget_trivial_usage | 129 | //usage:#define wget_trivial_usage |
130 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( | 130 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( |
131 | //usage: "[-c|--continue] [--spider] [-q|--quiet] [-O|--output-document FILE]\n" | 131 | //usage: "[-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header 'HEADER: VALUE'] [-Y on/off]\n" |
132 | //usage: " [-o|--output-file FILE] [--header 'header: value'] [-Y|--proxy on/off]\n" | ||
133 | //usage: IF_FEATURE_WGET_OPENSSL( | ||
134 | //usage: " [--no-check-certificate]\n" | ||
135 | //usage: ) | ||
136 | /* Since we ignore these opts, we don't show them in --help */ | 132 | /* Since we ignore these opts, we don't show them in --help */ |
137 | /* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ | 133 | /* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ |
138 | /* //usage: " [-nv] [-nc] [-nH] [-np]" */ | 134 | /* //usage: " [-nv] [-nc] [-nH] [-np]" */ |
139 | //usage: " [-P DIR] [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." | 135 | //usage: " "IF_FEATURE_WGET_OPENSSL("[--no-check-certificate] ")"[-P DIR] [-U AGENT]"IF_FEATURE_WGET_TIMEOUT(" [-T SEC]")" URL..." |
140 | //usage: ) | 136 | //usage: ) |
141 | //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( | 137 | //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( |
142 | //usage: "[-cq] [-O FILE] [-o FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]" | 138 | //usage: "[-cqS] [-O FILE] [-o LOGFILE] [-Y on/off] [-P DIR] [-U AGENT]"IF_FEATURE_WGET_TIMEOUT(" [-T SEC]")" URL..." |
143 | //usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." | ||
144 | //usage: ) | 139 | //usage: ) |
145 | //usage:#define wget_full_usage "\n\n" | 140 | //usage:#define wget_full_usage "\n\n" |
146 | //usage: "Retrieve files via HTTP or FTP\n" | 141 | //usage: "Retrieve files via HTTP or FTP\n" |
@@ -158,7 +153,7 @@ | |||
158 | //usage: "\n -T SEC Network read timeout is SEC seconds" | 153 | //usage: "\n -T SEC Network read timeout is SEC seconds" |
159 | //usage: ) | 154 | //usage: ) |
160 | //usage: "\n -O FILE Save to FILE ('-' for stdout)" | 155 | //usage: "\n -O FILE Save to FILE ('-' for stdout)" |
161 | //usage: "\n -o FILE Log messages to FILE" | 156 | //usage: "\n -o LOGFILE Log messages to FILE" |
162 | //usage: "\n -U STR Use STR for User-Agent header" | 157 | //usage: "\n -U STR Use STR for User-Agent header" |
163 | //usage: "\n -Y on/off Use proxy" | 158 | //usage: "\n -Y on/off Use proxy" |
164 | 159 | ||
@@ -287,6 +282,8 @@ enum { | |||
287 | WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 282 | WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
288 | WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 283 | WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
289 | WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 284 | WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
285 | /* hijack this bit for other than opts purposes: */ | ||
286 | WGET_NO_FTRUNCATE = (1 << 31) | ||
290 | }; | 287 | }; |
291 | 288 | ||
292 | enum { | 289 | enum { |
@@ -1085,8 +1082,13 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
1085 | */ | 1082 | */ |
1086 | { | 1083 | { |
1087 | off_t pos = lseek(G.output_fd, 0, SEEK_CUR); | 1084 | off_t pos = lseek(G.output_fd, 0, SEEK_CUR); |
1088 | if (pos != (off_t)-1) | 1085 | if (pos != (off_t)-1) { |
1089 | ftruncate(G.output_fd, pos); | 1086 | /* do not truncate if -O- is in use, a user complained about |
1087 | * "wget -qO- 'http://example.com/empty' >>FILE" truncating FILE. | ||
1088 | */ | ||
1089 | if (!(option_mask32 & WGET_NO_FTRUNCATE)) | ||
1090 | ftruncate(G.output_fd, pos); | ||
1091 | } | ||
1090 | } | 1092 | } |
1091 | 1093 | ||
1092 | if (!(option_mask32 & WGET_OPT_QUIET)) { | 1094 | if (!(option_mask32 & WGET_OPT_QUIET)) { |
@@ -1599,7 +1601,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") | |||
1599 | if (G.fname_out) { /* -O FILE ? */ | 1601 | if (G.fname_out) { /* -O FILE ? */ |
1600 | if (LONE_DASH(G.fname_out)) { /* -O - ? */ | 1602 | if (LONE_DASH(G.fname_out)) { /* -O - ? */ |
1601 | G.output_fd = 1; | 1603 | G.output_fd = 1; |
1602 | option_mask32 &= ~WGET_OPT_CONTINUE; | 1604 | option_mask32 = (option_mask32 & (~WGET_OPT_CONTINUE)) | WGET_NO_FTRUNCATE; |
1603 | } | 1605 | } |
1604 | /* compat with wget: -O FILE can overwrite */ | 1606 | /* compat with wget: -O FILE can overwrite */ |
1605 | G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; | 1607 | G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; |