aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-01-14 13:28:49 +0000
committerRon Yorston <rmy@pobox.com>2021-01-14 13:28:49 +0000
commit89963b524d211e1aec12b72b3725be05ee95c8cf (patch)
tree48590aef62b7ee7686b7898256f29def8d9c50b9 /networking
parent9aa5a829070392c2ac6494d0c4e674c0c2bc7dab (diff)
parent2b7c1aa92c68524559a2067609d09309d5c09adc (diff)
downloadbusybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.gz
busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.bz2
busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r--networking/ftpgetput.c4
-rw-r--r--networking/hostname.c4
-rw-r--r--networking/httpd.c54
-rw-r--r--networking/ifconfig.c6
-rw-r--r--networking/ifplugd.c4
-rw-r--r--networking/ifupdown.c20
-rw-r--r--networking/inetd.c8
-rw-r--r--networking/interface.c2
-rw-r--r--networking/ip.c2
-rw-r--r--networking/ipcalc.c2
-rw-r--r--networking/libiproute/ipaddress.c11
-rw-r--r--networking/libiproute/rt_names.c2
-rw-r--r--networking/libiproute/rtm_map.c53
-rw-r--r--networking/nbd-client.c2
-rw-r--r--networking/nc_bloaty.c2
-rw-r--r--networking/netstat.c2
-rw-r--r--networking/nslookup.c34
-rw-r--r--networking/ntpd.c19
-rw-r--r--networking/ping.c81
-rw-r--r--networking/pscan.c12
-rw-r--r--networking/route.c84
-rw-r--r--networking/slattach.c2
-rw-r--r--networking/telnet.c6
-rw-r--r--networking/tftp.c4
-rw-r--r--networking/tls.c2
-rw-r--r--networking/tls_aes.c6
-rw-r--r--networking/tls_fe.c28
-rw-r--r--networking/traceroute.c871
-rw-r--r--networking/tunctl.c16
-rw-r--r--networking/udhcp/Config.src8
-rw-r--r--networking/udhcp/common.h3
-rw-r--r--networking/udhcp/d6_common.h10
-rw-r--r--networking/udhcp/d6_dhcpc.c23
-rw-r--r--networking/udhcp/d6_packet.c19
-rw-r--r--networking/udhcp/dhcpc.c7
-rw-r--r--networking/udhcp/dhcpd.c9
-rw-r--r--networking/udhcp/dumpleases.c8
-rw-r--r--networking/udhcp/packet.c18
-rw-r--r--networking/wget.c26
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 */
1039static void decodeBase64(char *Data) 1044static 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
250static const struct arg1opt Arg1Opt[] = { 250static 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
280static const struct options OptArray[] = { 280static 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";
304static const struct { 304static 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
364static const struct builtin builtins[] = { 364static 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
749static const char *const if_port_text[] = { 749static 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
28enum { /* 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
24struct filter_t { 35struct 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
78static void rtnl_rtprot_initialize(void) 78static 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
14static 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";
18enum {
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
14const char* FAST_FUNC rtnl_rtntype_n2a(int id) 36const 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
46int FAST_FUNC rtnl_rtntype_a2n(int *id, char *arg) 68int 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
117static const char *const tcp_state[] = { 117static 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 {
273static const struct { 273static 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
291static const char *const rcodes[] = { 291static 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
560gettime1900d(void) 567gettime1900d(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 */
180struct 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
159enum { 201enum {
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. */
93static const char tbl_hash_net_host[] ALIGN1 = 84static 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 =
116static const char tbl_ipvx[] ALIGN1 = 106static 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
141static const uint16_t flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */ 130static 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
462static const 451static const
463IF_NOT_FEATURE_IPV6(uint16_t) 452IF_NOT_FEATURE_IPV6(uint16_t flagvals[] ALIGN2 = )
464IF_FEATURE_IPV6(unsigned) 453IF_FEATURE_IPV6(uint32_t flagvals[] ALIGN4 = )
465flagvals[] = { /* 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 */
663static const char tbl_verb[] ALIGN1 = 660static 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
670int route_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 666int 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
371static void put_iac4_msb_lsb(unsigned x_y_z_t) 374static 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
378static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c) 382static 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")
340enum { 346enum {
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
363enum { 372enum {
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
421static int 463static int
422wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) 464wait_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 */
536static const char * 588static const char *
537pr_type(unsigned char t) 589pr_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 620static int
621hexdump_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
574static int 649static int
575packet4_ok(int read_len, const struct sockaddr_in *from, int seq) 650packet4_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
665static int 732static int
666packet_ok(int read_len, len_and_sockaddr *from_lsa, 733packet6_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
745static ALWAYS_INLINE int 798static int
746packet_ok(int read_len, 799packet_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 */
760static void 812static void
761print_inetname(const struct sockaddr *from) 813#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
814print(void)
815# define print(len) print()
816#else
817print(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
782static void
783print(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
803static void 858static 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 */
815static int 868static NOINLINE void
816common_traceroute_main(int op, char **argv) 869traceroute_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
1111static int
1112common_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
104comment "Common options for DHCP applets" 104comment "Common options for DHCP applets"
105 depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY 105 depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY
106 106
107config 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
107config FEATURE_UDHCP_PORT 115config 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
344int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, 344int 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
348void udhcp_sp_setup(void) FAST_FUNC; 349void udhcp_sp_setup(void) FAST_FUNC;
349void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; 350void 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
162int FAST_FUNC d6_send_raw_packet( 162int 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
169int FAST_FUNC d6_send_kernel_packet( 168int 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 */
53int FAST_FUNC d6_send_raw_packet( 54int 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 */
129int FAST_FUNC d6_send_kernel_packet( 129int 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
401static const struct config_keyword keywords[] = { 401static 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
618static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) 619static 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 */
190int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, 190int 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
292enum { 289enum {
@@ -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;