aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2015-10-13 14:45:51 +0100
committerRon Yorston <rmy@pobox.com>2015-10-13 14:45:51 +0100
commit8e509f11bceeec419abc718300bef7422d1fee4c (patch)
treefdfbc752ad94102e3613a5d7254f14a93eaf7f56 /networking
parent420f5edfe7676fe6e7cddbbf15c04649d096e422 (diff)
parent4d0c1ea4784c9844f8468d97ca5c26d3c70f9921 (diff)
downloadbusybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.tar.gz
busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.tar.bz2
busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r--networking/Config.src49
-rw-r--r--networking/Kbuild.src1
-rw-r--r--networking/arping.c29
-rw-r--r--networking/brctl.c56
-rw-r--r--networking/ftpd.c25
-rw-r--r--networking/ftpgetput.c7
-rw-r--r--networking/httpd.c10
-rw-r--r--networking/ifenslave.c8
-rw-r--r--networking/ifplugd.c16
-rw-r--r--networking/ifupdown.c4
-rw-r--r--networking/interface.c24
-rw-r--r--networking/isrv.c4
-rw-r--r--networking/libiproute/ipaddress.c14
-rw-r--r--networking/libiproute/iproute.c3
-rw-r--r--networking/libiproute/iprule.c11
-rw-r--r--networking/libiproute/iptunnel.c3
-rw-r--r--networking/libiproute/ll_map.c14
-rw-r--r--networking/libiproute/ll_map.h2
-rw-r--r--networking/libiproute/rt_names.c93
-rw-r--r--networking/libiproute/rt_names.h11
-rw-r--r--networking/libiproute/rtm_map.c6
-rw-r--r--networking/libiproute/rtm_map.h2
-rw-r--r--networking/nbd-client.c2
-rw-r--r--networking/nc_bloaty.c4
-rw-r--r--networking/ntpd.c6
-rw-r--r--networking/ping.c24
-rwxr-xr-xnetworking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.822
-rw-r--r--networking/ssl_helper-wolfssl/README20
-rw-r--r--networking/ssl_helper-wolfssl/ssl_helper.c480
-rwxr-xr-xnetworking/ssl_helper-wolfssl/ssl_helper.sh12
-rw-r--r--networking/tc.c7
-rw-r--r--networking/telnet.c2
-rw-r--r--networking/telnetd.c2
-rw-r--r--networking/tftp.c7
-rw-r--r--networking/traceroute.c115
-rw-r--r--networking/udhcp/dhcpc.c18
-rw-r--r--networking/wget.c159
-rw-r--r--networking/zcip.c363
38 files changed, 1132 insertions, 503 deletions
diff --git a/networking/Config.src b/networking/Config.src
index da36e8627..43ccbf385 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -533,6 +533,13 @@ config FEATURE_IP_ROUTE
533 help 533 help
534 Add support for routing table management to "ip". 534 Add support for routing table management to "ip".
535 535
536config FEATURE_IP_ROUTE_DIR
537 string "ip route configuration directory"
538 default "/etc/iproute2"
539 depends on FEATURE_IP_ROUTE
540 help
541 Location of the "ip" applet routing configuration.
542
536config FEATURE_IP_TUNNEL 543config FEATURE_IP_TUNNEL
537 bool "ip tunnel" 544 bool "ip tunnel"
538 default y 545 default y
@@ -947,48 +954,6 @@ config VCONFIG
947 help 954 help
948 Creates, removes, and configures VLAN interfaces 955 Creates, removes, and configures VLAN interfaces
949 956
950config WGET
951 bool "wget"
952 default y
953 help
954 wget is a utility for non-interactive download of files from HTTP
955 and FTP servers.
956
957config FEATURE_WGET_STATUSBAR
958 bool "Enable a nifty process meter (+2k)"
959 default y
960 depends on WGET
961 help
962 Enable the transfer progress bar for wget transfers.
963
964config FEATURE_WGET_AUTHENTICATION
965 bool "Enable HTTP authentication"
966 default y
967 depends on WGET
968 help
969 Support authenticated HTTP transfers.
970
971config FEATURE_WGET_LONG_OPTIONS
972 bool "Enable long options"
973 default y
974 depends on WGET && LONG_OPTS
975 help
976 Support long options for the wget applet.
977
978config FEATURE_WGET_TIMEOUT
979 bool "Enable timeout option -T SEC"
980 default y
981 depends on WGET
982 help
983 Supports network read and connect timeouts for wget,
984 so that wget will give up and timeout, through the -T
985 command line option.
986
987 Currently only connect and network data read timeout are
988 supported (i.e., timeout is not applied to the DNS query). When
989 FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
990 will work in addition to -T.
991
992config ZCIP 957config ZCIP
993 bool "zcip" 958 bool "zcip"
994 default y 959 default y
diff --git a/networking/Kbuild.src b/networking/Kbuild.src
index 944f27be1..79f54824b 100644
--- a/networking/Kbuild.src
+++ b/networking/Kbuild.src
@@ -41,7 +41,6 @@ lib-$(CONFIG_TFTPD) += tftp.o
41lib-$(CONFIG_TRACEROUTE) += traceroute.o 41lib-$(CONFIG_TRACEROUTE) += traceroute.o
42lib-$(CONFIG_TUNCTL) += tunctl.o 42lib-$(CONFIG_TUNCTL) += tunctl.o
43lib-$(CONFIG_VCONFIG) += vconfig.o 43lib-$(CONFIG_VCONFIG) += vconfig.o
44lib-$(CONFIG_WGET) += wget.o
45lib-$(CONFIG_ZCIP) += zcip.o 44lib-$(CONFIG_ZCIP) += zcip.o
46 45
47lib-$(CONFIG_TCPSVD) += tcpudp.o tcpudp_perhost.o 46lib-$(CONFIG_TCPSVD) += tcpudp.o tcpudp_perhost.o
diff --git a/networking/arping.c b/networking/arping.c
index dbfd75ef5..ef205e5e6 100644
--- a/networking/arping.c
+++ b/networking/arping.c
@@ -13,11 +13,11 @@
13//usage: "\n -f Quit on first ARP reply" 13//usage: "\n -f Quit on first ARP reply"
14//usage: "\n -q Quiet" 14//usage: "\n -q Quiet"
15//usage: "\n -b Keep broadcasting, don't go unicast" 15//usage: "\n -b Keep broadcasting, don't go unicast"
16//usage: "\n -D Duplicated address detection mode" 16//usage: "\n -D Exit with 1 if DST_IP replies"
17//usage: "\n -U Unsolicited ARP mode, update your neighbors" 17//usage: "\n -U Unsolicited ARP mode, update your neighbors"
18//usage: "\n -A ARP answer mode, update your neighbors" 18//usage: "\n -A ARP answer mode, update your neighbors"
19//usage: "\n -c N Stop after sending N ARP requests" 19//usage: "\n -c N Stop after sending N ARP requests"
20//usage: "\n -w TIMEOUT Time to wait for ARP reply, seconds" 20//usage: "\n -w TIMEOUT Seconds to wait for ARP reply"
21//usage: "\n -I IFACE Interface to use (default eth0)" 21//usage: "\n -I IFACE Interface to use (default eth0)"
22//usage: "\n -s SRC_IP Sender IP address" 22//usage: "\n -s SRC_IP Sender IP address"
23//usage: "\n DST_IP Target IP address" 23//usage: "\n DST_IP Target IP address"
@@ -162,7 +162,7 @@ static void catcher(void)
162 alarm(1); 162 alarm(1);
163} 163}
164 164
165static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) 165static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
166{ 166{
167 struct arphdr *ah = (struct arphdr *) buf; 167 struct arphdr *ah = (struct arphdr *) buf;
168 unsigned char *p = (unsigned char *) (ah + 1); 168 unsigned char *p = (unsigned char *) (ah + 1);
@@ -181,33 +181,33 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
181 if (FROM->sll_pkttype != PACKET_HOST 181 if (FROM->sll_pkttype != PACKET_HOST
182 && FROM->sll_pkttype != PACKET_BROADCAST 182 && FROM->sll_pkttype != PACKET_BROADCAST
183 && FROM->sll_pkttype != PACKET_MULTICAST) 183 && FROM->sll_pkttype != PACKET_MULTICAST)
184 return false; 184 return;
185 185
186 /* Only these types are recognized */ 186 /* Only these types are recognized */
187 if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY)) 187 if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
188 return false; 188 return;
189 189
190 /* ARPHRD check and this darned FDDI hack here :-( */ 190 /* ARPHRD check and this darned FDDI hack here :-( */
191 if (ah->ar_hrd != htons(FROM->sll_hatype) 191 if (ah->ar_hrd != htons(FROM->sll_hatype)
192 && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER))) 192 && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
193 return false; 193 return;
194 194
195 /* Protocol must be IP. */ 195 /* Protocol must be IP. */
196 if (ah->ar_pro != htons(ETH_P_IP) 196 if (ah->ar_pro != htons(ETH_P_IP)
197 || (ah->ar_pln != 4) 197 || (ah->ar_pln != 4)
198 || (ah->ar_hln != me.sll_halen) 198 || (ah->ar_hln != me.sll_halen)
199 || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln)))) 199 || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))))
200 return false; 200 return;
201 201
202 move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln); 202 move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln);
203 move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln); 203 move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln);
204 204
205 if (dst.s_addr != src_ip.s_addr) 205 if (dst.s_addr != src_ip.s_addr)
206 return false; 206 return;
207 if (!(option_mask32 & DAD)) { 207 if (!(option_mask32 & DAD)) {
208 if ((src.s_addr != dst_ip.s_addr) 208 if ((src.s_addr != dst_ip.s_addr)
209 || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln))) 209 || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
210 return false; 210 return;
211 } else { 211 } else {
212 /* DAD packet was: 212 /* DAD packet was:
213 src_ip = 0 (or some src) 213 src_ip = 0 (or some src)
@@ -224,7 +224,7 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
224 */ 224 */
225 if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0) 225 if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0)
226 || (src.s_addr && src.s_addr != dst_ip.s_addr)) 226 || (src.s_addr && src.s_addr != dst_ip.s_addr))
227 return false; 227 return;
228 } 228 }
229 if (!(option_mask32 & QUIET)) { 229 if (!(option_mask32 & QUIET)) {
230 int s_printed = 0; 230 int s_printed = 0;
@@ -249,7 +249,7 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
249 unsigned diff = MONOTONIC_US() - last; 249 unsigned diff = MONOTONIC_US() - last;
250 printf(" %u.%03ums\n", diff / 1000, diff % 1000); 250 printf(" %u.%03ums\n", diff / 1000, diff % 1000);
251 } else { 251 } else {
252 printf(" UNSOLICITED?\n"); 252 puts(" UNSOLICITED?");
253 } 253 }
254 fflush_all(); 254 fflush_all();
255 } 255 }
@@ -264,7 +264,6 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
264 memcpy(he.sll_addr, p, me.sll_halen); 264 memcpy(he.sll_addr, p, me.sll_halen);
265 option_mask32 |= UNICASTING; 265 option_mask32 |= UNICASTING;
266 } 266 }
267 return true;
268} 267}
269 268
270int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 269int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -358,8 +357,8 @@ int arping_main(int argc UNUSED_PARAM, char **argv)
358 saddr.sin_port = htons(1025); 357 saddr.sin_port = htons(1025);
359 saddr.sin_addr = dst; 358 saddr.sin_addr = dst;
360 359
361 if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) 360 if (setsockopt_SOL_SOCKET_1(probe_fd, SO_DONTROUTE) != 0)
362 bb_perror_msg("setsockopt(SO_DONTROUTE)"); 361 bb_perror_msg("setsockopt(%s)", "SO_DONTROUTE");
363 xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 362 xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
364 getsockname(probe_fd, (struct sockaddr *) &saddr, &alen); 363 getsockname(probe_fd, (struct sockaddr *) &saddr, &alen);
365 //never happens: 364 //never happens:
diff --git a/networking/brctl.c b/networking/brctl.c
index 207b069aa..c01a86998 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -64,7 +64,57 @@
64#define BRCTL_USE_INTERNAL 1 64#define BRCTL_USE_INTERNAL 1
65 65
66#if ENABLE_FEATURE_BRCTL_FANCY 66#if ENABLE_FEATURE_BRCTL_FANCY
67# include <linux/if_bridge.h> 67/* #include <linux/if_bridge.h>
68 * breaks on musl: we already included netinet/in.h in libbb.h,
69 * if we include <linux/if_bridge.h> here, we get this:
70 * In file included from /usr/include/linux/if_bridge.h:18,
71 * from networking/brctl.c:67:
72 * /usr/include/linux/in6.h:32: error: redefinition of 'struct in6_addr'
73 * /usr/include/linux/in6.h:49: error: redefinition of 'struct sockaddr_in6'
74 * /usr/include/linux/in6.h:59: error: redefinition of 'struct ipv6_mreq'
75 */
76/* From <linux/if_bridge.h> */
77#define BRCTL_GET_VERSION 0
78#define BRCTL_GET_BRIDGES 1
79#define BRCTL_ADD_BRIDGE 2
80#define BRCTL_DEL_BRIDGE 3
81#define BRCTL_ADD_IF 4
82#define BRCTL_DEL_IF 5
83#define BRCTL_GET_BRIDGE_INFO 6
84#define BRCTL_GET_PORT_LIST 7
85#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8
86#define BRCTL_SET_BRIDGE_HELLO_TIME 9
87#define BRCTL_SET_BRIDGE_MAX_AGE 10
88#define BRCTL_SET_AGEING_TIME 11
89#define BRCTL_SET_GC_INTERVAL 12
90#define BRCTL_GET_PORT_INFO 13
91#define BRCTL_SET_BRIDGE_STP_STATE 14
92#define BRCTL_SET_BRIDGE_PRIORITY 15
93#define BRCTL_SET_PORT_PRIORITY 16
94#define BRCTL_SET_PATH_COST 17
95#define BRCTL_GET_FDB_ENTRIES 18
96struct __bridge_info {
97 uint64_t designated_root;
98 uint64_t bridge_id;
99 uint32_t root_path_cost;
100 uint32_t max_age;
101 uint32_t hello_time;
102 uint32_t forward_delay;
103 uint32_t bridge_max_age;
104 uint32_t bridge_hello_time;
105 uint32_t bridge_forward_delay;
106 uint8_t topology_change;
107 uint8_t topology_change_detected;
108 uint8_t root_port;
109 uint8_t stp_enabled;
110 uint32_t ageing_time;
111 uint32_t gc_interval;
112 uint32_t hello_timer_value;
113 uint32_t tcn_timer_value;
114 uint32_t topology_change_timer_value;
115 uint32_t gc_timer_value;
116};
117/* end <linux/if_bridge.h> */
68 118
69/* FIXME: These 4 funcs are not really clean and could be improved */ 119/* FIXME: These 4 funcs are not really clean and could be improved */
70static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv, 120static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv,
@@ -167,7 +217,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
167 arm_ioctl(args, BRCTL_GET_BRIDGES, 217 arm_ioctl(args, BRCTL_GET_BRIDGES,
168 (unsigned long) bridx, MAX_PORTS); 218 (unsigned long) bridx, MAX_PORTS);
169 num = xioctl(fd, SIOCGIFBR, args); 219 num = xioctl(fd, SIOCGIFBR, args);
170 printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n"); 220 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
171 for (i = 0; i < num; i++) { 221 for (i = 0; i < num; i++) {
172 char ifname[IFNAMSIZ]; 222 char ifname[IFNAMSIZ];
173 int j, tabs; 223 int j, tabs;
@@ -186,7 +236,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
186 /* print bridge id */ 236 /* print bridge id */
187 x = (unsigned char *) &bi.bridge_id; 237 x = (unsigned char *) &bi.bridge_id;
188 for (j = 0; j < 8; j++) { 238 for (j = 0; j < 8; j++) {
189 printf("%.2x", x[j]); 239 printf("%02x", x[j]);
190 if (j == 1) 240 if (j == 1)
191 bb_putchar('.'); 241 bb_putchar('.');
192 } 242 }
diff --git a/networking/ftpd.c b/networking/ftpd.c
index 2351d6dd3..8345ae67c 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -377,7 +377,7 @@ ftpdataio_get_pasv_fd(void)
377 return remote_fd; 377 return remote_fd;
378 } 378 }
379 379
380 setsockopt(remote_fd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); 380 setsockopt_keepalive(remote_fd);
381 return remote_fd; 381 return remote_fd;
382} 382}
383 383
@@ -1186,11 +1186,11 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1186 , SIG_IGN); 1186 , SIG_IGN);
1187 1187
1188 /* Set up options on the command socket (do we need these all? why?) */ 1188 /* Set up options on the command socket (do we need these all? why?) */
1189 setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); 1189 setsockopt_1(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY);
1190 setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); 1190 setsockopt_keepalive(STDIN_FILENO);
1191 /* Telnet protocol over command link may send "urgent" data, 1191 /* Telnet protocol over command link may send "urgent" data,
1192 * we prefer it to be received in the "normal" data stream: */ 1192 * we prefer it to be received in the "normal" data stream: */
1193 setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &const_int_1, sizeof(const_int_1)); 1193 setsockopt_1(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE);
1194 1194
1195 WRITE_OK(FTP_GREET); 1195 WRITE_OK(FTP_GREET);
1196 signal(SIGALRM, timeout_handler); 1196 signal(SIGALRM, timeout_handler);
@@ -1223,11 +1223,26 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1223#endif 1223#endif
1224 argv += optind; 1224 argv += optind;
1225 if (argv[0]) { 1225 if (argv[0]) {
1226 const char *basedir = argv[0];
1226#if !BB_MMU 1227#if !BB_MMU
1227 G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY); 1228 G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
1228 close_on_exec_on(G.root_fd); 1229 close_on_exec_on(G.root_fd);
1229#endif 1230#endif
1230 xchroot(argv[0]); 1231 if (chroot(basedir) == 0)
1232 basedir = "/";
1233#if !BB_MMU
1234 else {
1235 close(G.root_fd);
1236 G.root_fd = -1;
1237 }
1238#endif
1239 /*
1240 * If chroot failed, assume that we aren't root,
1241 * and at least chdir to the specified DIR
1242 * (older versions were dying with error message).
1243 * If chroot worked, move current dir to new "/":
1244 */
1245 xchdir(basedir);
1231 } 1246 }
1232 1247
1233#if ENABLE_FEATURE_FTP_AUTHENTICATION 1248#if ENABLE_FEATURE_FTP_AUTHENTICATION
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c
index 0670b2141..607e82713 100644
--- a/networking/ftpgetput.c
+++ b/networking/ftpgetput.c
@@ -62,9 +62,6 @@ struct globals {
62} FIX_ALIASING; 62} FIX_ALIASING;
63#define G (*(struct globals*)&bb_common_bufsiz1) 63#define G (*(struct globals*)&bb_common_bufsiz1)
64enum { BUFSZ = COMMON_BUFSIZE - offsetof(struct globals, buf) }; 64enum { BUFSZ = COMMON_BUFSIZE - offsetof(struct globals, buf) };
65struct BUG_G_too_big {
66 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
67};
68#define user (G.user ) 65#define user (G.user )
69#define password (G.password ) 66#define password (G.password )
70#define lsa (G.lsa ) 67#define lsa (G.lsa )
@@ -72,7 +69,9 @@ struct BUG_G_too_big {
72#define verbose_flag (G.verbose_flag ) 69#define verbose_flag (G.verbose_flag )
73#define do_continue (G.do_continue ) 70#define do_continue (G.do_continue )
74#define buf (G.buf ) 71#define buf (G.buf )
75#define INIT_G() do { } while (0) 72#define INIT_G() do { \
73 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
74} while (0)
76 75
77 76
78static void ftp_die(const char *msg) NORETURN; 77static void ftp_die(const char *msg) NORETURN;
diff --git a/networking/httpd.c b/networking/httpd.c
index 7a9065fcc..00169c36d 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1222,12 +1222,12 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1222 out_cnt += count; 1222 out_cnt += count;
1223 count = 0; 1223 count = 0;
1224 /* "Status" header format is: "Status: 302 Redirected\r\n" */ 1224 /* "Status" header format is: "Status: 302 Redirected\r\n" */
1225 if (out_cnt >= 8 && memcmp(rbuf, "Status: ", 8) == 0) { 1225 if (out_cnt >= 7 && memcmp(rbuf, "Status:", 7) == 0) {
1226 /* send "HTTP/1.0 " */ 1226 /* send "HTTP/1.0 " */
1227 if (full_write(STDOUT_FILENO, HTTP_200, 9) != 9) 1227 if (full_write(STDOUT_FILENO, HTTP_200, 9) != 9)
1228 break; 1228 break;
1229 rbuf += 8; /* skip "Status: " */ 1229 rbuf += 7; /* skip "Status:" */
1230 count = out_cnt - 8; 1230 count = out_cnt - 7;
1231 out_cnt = -1; /* buffering off */ 1231 out_cnt = -1; /* buffering off */
1232 } else if (out_cnt >= 4) { 1232 } else if (out_cnt >= 4) {
1233 /* Did CGI add "HTTP"? */ 1233 /* Did CGI add "HTTP"? */
@@ -2352,7 +2352,7 @@ static void mini_httpd(int server_socket)
2352 continue; 2352 continue;
2353 2353
2354 /* set the KEEPALIVE option to cull dead connections */ 2354 /* set the KEEPALIVE option to cull dead connections */
2355 setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); 2355 setsockopt_keepalive(n);
2356 2356
2357 if (fork() == 0) { 2357 if (fork() == 0) {
2358 /* child */ 2358 /* child */
@@ -2395,7 +2395,7 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv)
2395 continue; 2395 continue;
2396 2396
2397 /* set the KEEPALIVE option to cull dead connections */ 2397 /* set the KEEPALIVE option to cull dead connections */
2398 setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); 2398 setsockopt_keepalive(n);
2399 2399
2400 if (vfork() == 0) { 2400 if (vfork() == 0) {
2401 /* child */ 2401 /* child */
diff --git a/networking/ifenslave.c b/networking/ifenslave.c
index c3be8180b..6b234adee 100644
--- a/networking/ifenslave.c
+++ b/networking/ifenslave.c
@@ -577,8 +577,8 @@ int ifenslave_main(int argc UNUSED_PARAM, char **argv)
577 /* Can't work with this slave, */ 577 /* Can't work with this slave, */
578 /* remember the error and skip it */ 578 /* remember the error and skip it */
579 bb_perror_msg( 579 bb_perror_msg(
580 "skipping %s: can't get flags", 580 "skipping %s: can't get %s",
581 slave_ifname); 581 slave_ifname, "flags");
582 res = rv; 582 res = rv;
583 continue; 583 continue;
584 } 584 }
@@ -595,8 +595,8 @@ int ifenslave_main(int argc UNUSED_PARAM, char **argv)
595 /* Can't work with this slave, */ 595 /* Can't work with this slave, */
596 /* remember the error and skip it */ 596 /* remember the error and skip it */
597 bb_perror_msg( 597 bb_perror_msg(
598 "skipping %s: can't get settings", 598 "skipping %s: can't get %s",
599 slave_ifname); 599 slave_ifname, "settings");
600 res = rv; 600 res = rv;
601 continue; 601 continue;
602 } 602 }
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index fef7a5ac9..f0defb5c8 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -38,7 +38,17 @@
38#include <linux/mii.h> 38#include <linux/mii.h>
39#include <linux/ethtool.h> 39#include <linux/ethtool.h>
40#ifdef HAVE_NET_ETHERNET_H 40#ifdef HAVE_NET_ETHERNET_H
41# include <net/ethernet.h> 41/* musl breakage:
42 * In file included from /usr/include/net/ethernet.h:10,
43 * from networking/ifplugd.c:41:
44 * /usr/include/netinet/if_ether.h:96: error: redefinition of 'struct ethhdr'
45 *
46 * Build succeeds without it on musl. Commented it out.
47 * If on your system you need it, consider removing <linux/ethtool.h>
48 * and copy-pasting its definitions here (<linux/ethtool.h> is what pulls in
49 * conflicting definition of struct ethhdr on musl).
50 */
51/* # include <net/ethernet.h> */
42#endif 52#endif
43#include <linux/netlink.h> 53#include <linux/netlink.h>
44#include <linux/rtnetlink.h> 54#include <linux/rtnetlink.h>
@@ -48,6 +58,10 @@
48#define __user 58#define __user
49#include <linux/wireless.h> 59#include <linux/wireless.h>
50 60
61#ifndef ETH_ALEN
62# define ETH_ALEN 6
63#endif
64
51/* 65/*
52From initial port to busybox, removed most of the redundancy by 66From initial port to busybox, removed most of the redundancy by
53converting implementation of a polymorphic interface to the strict 67converting implementation of a polymorphic interface to the strict
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 606fc049f..7c45e8927 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -395,7 +395,7 @@ static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec)
395 result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec); 395 result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec);
396 result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); 396 result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
397 /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */ 397 /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */
398 result += execute("[[ip route add ::/0 via %gateway%]][[ prio %metric%]]", ifd, exec); 398 result += execute("[[ip route add ::/0 via %gateway%]][[ metric %metric%]]", ifd, exec);
399# else 399# else
400 result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec); 400 result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
401 result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec); 401 result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
@@ -482,7 +482,7 @@ static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec)
482 result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] " 482 result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] "
483 "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec); 483 "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec);
484 result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); 484 result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
485 result += execute("[[ip route add default via %gateway% dev %iface%[[ prio %metric%]]]]", ifd, exec); 485 result += execute("[[ip route add default via %gateway% dev %iface%[[ metric %metric%]]]]", ifd, exec);
486 return ((result == 3) ? 3 : 0); 486 return ((result == 3) ? 3 : 0);
487# else 487# else
488 /* ifconfig said to set iface up before it processes hw %hwaddress%, 488 /* ifconfig said to set iface up before it processes hw %hwaddress%,
diff --git a/networking/interface.c b/networking/interface.c
index b0572d04e..24bd13c57 100644
--- a/networking/interface.c
+++ b/networking/interface.c
@@ -89,13 +89,9 @@ struct in6_ifreq {
89/* Display an Internet socket address. */ 89/* Display an Internet socket address. */
90static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric) 90static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric)
91{ 91{
92 static char *buff; /* defaults to NULL */
93
94 if (sap->sa_family == 0xFFFF || sap->sa_family == 0) 92 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
95 return "[NONE SET]"; 93 return "[NONE SET]";
96 free(buff); 94 return auto_string(INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00));
97 buff = INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00);
98 return buff;
99} 95}
100 96
101#ifdef UNUSED_AND_BUGGY 97#ifdef UNUSED_AND_BUGGY
@@ -171,13 +167,9 @@ static const struct aftype inet_aftype = {
171/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */ 167/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
172static const char* FAST_FUNC INET6_sprint(struct sockaddr *sap, int numeric) 168static const char* FAST_FUNC INET6_sprint(struct sockaddr *sap, int numeric)
173{ 169{
174 static char *buff;
175
176 if (sap->sa_family == 0xFFFF || sap->sa_family == 0) 170 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
177 return "[NONE SET]"; 171 return "[NONE SET]";
178 free(buff); 172 return auto_string(INET6_rresolve((struct sockaddr_in6 *) sap, numeric));
179 buff = INET6_rresolve((struct sockaddr_in6 *) sap, numeric);
180 return buff;
181} 173}
182 174
183#ifdef UNUSED 175#ifdef UNUSED
@@ -223,13 +215,11 @@ static const struct aftype inet6_aftype = {
223/* Display an UNSPEC address. */ 215/* Display an UNSPEC address. */
224static char* FAST_FUNC UNSPEC_print(unsigned char *ptr) 216static char* FAST_FUNC UNSPEC_print(unsigned char *ptr)
225{ 217{
226 static char *buff; 218 char *buff;
227
228 char *pos; 219 char *pos;
229 unsigned int i; 220 unsigned int i;
230 221
231 if (!buff) 222 buff = auto_string(xmalloc(sizeof(struct sockaddr) * 3 + 1));
232 buff = xmalloc(sizeof(struct sockaddr) * 3 + 1);
233 pos = buff; 223 pos = buff;
234 for (i = 0; i < sizeof(struct sockaddr); i++) { 224 for (i = 0; i < sizeof(struct sockaddr); i++) {
235 /* careful -- not every libc's sprintf returns # bytes written */ 225 /* careful -- not every libc's sprintf returns # bytes written */
@@ -712,14 +702,12 @@ static const struct hwtype loop_hwtype = {
712/* Display an Ethernet address in readable format. */ 702/* Display an Ethernet address in readable format. */
713static char* FAST_FUNC ether_print(unsigned char *ptr) 703static char* FAST_FUNC ether_print(unsigned char *ptr)
714{ 704{
715 static char *buff; 705 char *buff;
716
717 free(buff);
718 buff = xasprintf("%02X:%02X:%02X:%02X:%02X:%02X", 706 buff = xasprintf("%02X:%02X:%02X:%02X:%02X:%02X",
719 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377), 707 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
720 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377) 708 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
721 ); 709 );
722 return buff; 710 return auto_string(buff);
723} 711}
724 712
725static const struct hwtype ether_hwtype = { 713static const struct hwtype ether_hwtype = {
diff --git a/networking/isrv.c b/networking/isrv.c
index 1c6491edd..3673db715 100644
--- a/networking/isrv.c
+++ b/networking/isrv.c
@@ -194,7 +194,6 @@ static void handle_accept(isrv_state_t *state, int fd)
194 remove_peer(state, n); /* unsuccesful peer start */ 194 remove_peer(state, n); /* unsuccesful peer start */
195} 195}
196 196
197void BUG_sizeof_fd_set_is_strange(void);
198static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **)) 197static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **))
199{ 198{
200 enum { LONG_CNT = sizeof(fd_set) / sizeof(long) }; 199 enum { LONG_CNT = sizeof(fd_set) / sizeof(long) };
@@ -203,8 +202,7 @@ static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void *
203 /* need to know value at _the beginning_ of this routine */ 202 /* need to know value at _the beginning_ of this routine */
204 int fd_cnt = FD_COUNT; 203 int fd_cnt = FD_COUNT;
205 204
206 if (LONG_CNT * sizeof(long) != sizeof(fd_set)) 205 BUILD_BUG_ON(LONG_CNT * sizeof(long) != sizeof(fd_set));
207 BUG_sizeof_fd_set_is_strange();
208 206
209 fds_pos = 0; 207 fds_pos = 0;
210 while (1) { 208 while (1) {
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index a6d5129e7..8845cab91 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -137,12 +137,11 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n)
137 { 137 {
138 unsigned m_flag = 0; 138 unsigned m_flag = 0;
139 if (tb[IFLA_LINK]) { 139 if (tb[IFLA_LINK]) {
140 SPRINT_BUF(b1);
141 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); 140 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
142 if (iflink == 0) 141 if (iflink == 0)
143 printf("@NONE: "); 142 printf("@NONE: ");
144 else { 143 else {
145 printf("@%s: ", ll_idx_n2a(iflink, b1)); 144 printf("@%s: ", ll_index_to_name(iflink));
146 m_flag = ll_index_to_flags(iflink); 145 m_flag = ll_index_to_flags(iflink);
147 m_flag = !(m_flag & IFF_UP); 146 m_flag = !(m_flag & IFF_UP);
148 } 147 }
@@ -158,8 +157,7 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n)
158 printf("qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC])); 157 printf("qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
159#ifdef IFLA_MASTER 158#ifdef IFLA_MASTER
160 if (tb[IFLA_MASTER]) { 159 if (tb[IFLA_MASTER]) {
161 SPRINT_BUF(b1); 160 printf("master %s ", ll_index_to_name(*(int*)RTA_DATA(tb[IFLA_MASTER])));
162 printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
163 } 161 }
164#endif 162#endif
165/* IFLA_OPERSTATE was added to kernel with the same commit as IFF_DORMANT */ 163/* IFLA_OPERSTATE was added to kernel with the same commit as IFF_DORMANT */
@@ -218,7 +216,6 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
218 int len = n->nlmsg_len; 216 int len = n->nlmsg_len;
219 struct rtattr * rta_tb[IFA_MAX+1]; 217 struct rtattr * rta_tb[IFA_MAX+1];
220 char abuf[256]; 218 char abuf[256];
221 SPRINT_BUF(b1);
222 219
223 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) 220 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
224 return 0; 221 return 0;
@@ -250,7 +247,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
250 if (rta_tb[IFA_LABEL]) 247 if (rta_tb[IFA_LABEL])
251 label = RTA_DATA(rta_tb[IFA_LABEL]); 248 label = RTA_DATA(rta_tb[IFA_LABEL]);
252 else 249 else
253 label = ll_idx_n2a(ifa->ifa_index, b1); 250 label = ll_index_to_name(ifa->ifa_index);
254 if (fnmatch(G_filter.label, label, 0) != 0) 251 if (fnmatch(G_filter.label, label, 0) != 0)
255 return 0; 252 return 0;
256 } 253 }
@@ -325,7 +322,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
325 abuf, sizeof(abuf)) 322 abuf, sizeof(abuf))
326 ); 323 );
327 } 324 }
328 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1)); 325 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope));
329 if (ifa->ifa_flags & IFA_F_SECONDARY) { 326 if (ifa->ifa_flags & IFA_F_SECONDARY) {
330 ifa->ifa_flags &= ~IFA_F_SECONDARY; 327 ifa->ifa_flags &= ~IFA_F_SECONDARY;
331 printf("secondary "); 328 printf("secondary ");
@@ -556,12 +553,11 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush)
556 continue; 553 continue;
557 } 554 }
558 if (G_filter.label) { 555 if (G_filter.label) {
559 SPRINT_BUF(b1);
560 const char *label; 556 const char *label;
561 if (tb[IFA_LABEL]) 557 if (tb[IFA_LABEL])
562 label = RTA_DATA(tb[IFA_LABEL]); 558 label = RTA_DATA(tb[IFA_LABEL]);
563 else 559 else
564 label = ll_idx_n2a(ifa->ifa_index, b1); 560 label = ll_index_to_name(ifa->ifa_index);
565 if (fnmatch(G_filter.label, label, 0) != 0) 561 if (fnmatch(G_filter.label, label, 0) != 0)
566 continue; 562 continue;
567 } 563 }
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index 170c67b30..6ecd5f719 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -87,7 +87,6 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
87 inet_prefix dst; 87 inet_prefix dst;
88 inet_prefix src; 88 inet_prefix src;
89 int host_len = -1; 89 int host_len = -1;
90 SPRINT_BUF(b1);
91 90
92 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) { 91 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
93 fprintf(stderr, "Not a route: %08x %08x %08x\n", 92 fprintf(stderr, "Not a route: %08x %08x %08x\n",
@@ -236,7 +235,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
236 printf("Deleted "); 235 printf("Deleted ");
237 } 236 }
238 if (r->rtm_type != RTN_UNICAST /* && !G_filter.type - always 0 */) { 237 if (r->rtm_type != RTN_UNICAST /* && !G_filter.type - always 0 */) {
239 printf("%s ", rtnl_rtntype_n2a(r->rtm_type, b1)); 238 printf("%s ", rtnl_rtntype_n2a(r->rtm_type));
240 } 239 }
241 240
242 if (tb[RTA_DST]) { 241 if (tb[RTA_DST]) {
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c
index 8dbe6bd92..774a3e220 100644
--- a/networking/libiproute/iprule.c
+++ b/networking/libiproute/iprule.c
@@ -45,7 +45,6 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
45 int host_len = -1; 45 int host_len = -1;
46 struct rtattr * tb[RTA_MAX+1]; 46 struct rtattr * tb[RTA_MAX+1];
47 char abuf[256]; 47 char abuf[256];
48 SPRINT_BUF(b1);
49 48
50 if (n->nlmsg_type != RTM_NEWRULE) 49 if (n->nlmsg_type != RTM_NEWRULE)
51 return 0; 50 return 0;
@@ -110,7 +109,7 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
110 } 109 }
111 110
112 if (r->rtm_tos) { 111 if (r->rtm_tos) {
113 printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1)); 112 printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos));
114 } 113 }
115 if (tb[RTA_PROTOINFO]) { 114 if (tb[RTA_PROTOINFO]) {
116 printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO])); 115 printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO]));
@@ -121,7 +120,7 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
121 } 120 }
122 121
123 if (r->rtm_table) 122 if (r->rtm_table)
124 printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1)); 123 printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
125 124
126 if (tb[RTA_FLOW]) { 125 if (tb[RTA_FLOW]) {
127 uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]); 126 uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]);
@@ -129,10 +128,10 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
129 to &= 0xFFFF; 128 to &= 0xFFFF;
130 if (from) { 129 if (from) {
131 printf("realms %s/", 130 printf("realms %s/",
132 rtnl_rtrealm_n2a(from, b1)); 131 rtnl_rtrealm_n2a(from));
133 } 132 }
134 printf("%s ", 133 printf("%s ",
135 rtnl_rtrealm_n2a(to, b1)); 134 rtnl_rtrealm_n2a(to));
136 } 135 }
137 136
138 if (r->rtm_type == RTN_NAT) { 137 if (r->rtm_type == RTN_NAT) {
@@ -145,7 +144,7 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
145 } else 144 } else
146 printf("masquerade"); 145 printf("masquerade");
147 } else if (r->rtm_type != RTN_UNICAST) 146 } else if (r->rtm_type != RTN_UNICAST)
148 fputs(rtnl_rtntype_n2a(r->rtm_type, b1), stdout); 147 fputs(rtnl_rtntype_n2a(r->rtm_type), stdout);
149 148
150 bb_putchar('\n'); 149 bb_putchar('\n');
151 /*fflush_all();*/ 150 /*fflush_all();*/
diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c
index b54c3c53f..a65d5e579 100644
--- a/networking/libiproute/iptunnel.c
+++ b/networking/libiproute/iptunnel.c
@@ -432,13 +432,12 @@ static void print_tunnel(struct ip_tunnel_parm *p)
432 else 432 else
433 printf(" ttl inherit "); 433 printf(" ttl inherit ");
434 if (p->iph.tos) { 434 if (p->iph.tos) {
435 SPRINT_BUF(b1);
436 printf(" tos"); 435 printf(" tos");
437 if (p->iph.tos & 1) 436 if (p->iph.tos & 1)
438 printf(" inherit"); 437 printf(" inherit");
439 if (p->iph.tos & ~1) 438 if (p->iph.tos & ~1)
440 printf("%c%s ", p->iph.tos & 1 ? '/' : ' ', 439 printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
441 rtnl_dsfield_n2a(p->iph.tos & ~1, b1)); 440 rtnl_dsfield_n2a(p->iph.tos & ~1));
442 } 441 }
443 if (!(p->iph.frag_off & htons(IP_DF))) 442 if (!(p->iph.frag_off & htons(IP_DF)))
444 printf(" nopmtudisc"); 443 printf(" nopmtudisc");
diff --git a/networking/libiproute/ll_map.c b/networking/libiproute/ll_map.c
index 27cd90f34..e2b85fc7b 100644
--- a/networking/libiproute/ll_map.c
+++ b/networking/libiproute/ll_map.c
@@ -86,7 +86,8 @@ int FAST_FUNC ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM,
86 return 0; 86 return 0;
87} 87}
88 88
89const char FAST_FUNC *ll_idx_n2a(int idx, char *buf) 89static
90const char FAST_FUNC *ll_idx_n2a(int idx/*, char *buf*/)
90{ 91{
91 struct idxmap *im; 92 struct idxmap *im;
92 93
@@ -95,16 +96,15 @@ const char FAST_FUNC *ll_idx_n2a(int idx, char *buf)
95 im = find_by_index(idx); 96 im = find_by_index(idx);
96 if (im) 97 if (im)
97 return im->name; 98 return im->name;
98 snprintf(buf, 16, "if%d", idx); 99 //snprintf(buf, 16, "if%d", idx);
99 return buf; 100 //return buf;
101 return auto_string(xasprintf("if%d", idx));
100} 102}
101 103
102
103const char FAST_FUNC *ll_index_to_name(int idx) 104const char FAST_FUNC *ll_index_to_name(int idx)
104{ 105{
105 static char nbuf[16]; 106 //static char nbuf[16];
106 107 return ll_idx_n2a(idx/*, nbuf*/);
107 return ll_idx_n2a(idx, nbuf);
108} 108}
109 109
110#ifdef UNUSED 110#ifdef UNUSED
diff --git a/networking/libiproute/ll_map.h b/networking/libiproute/ll_map.h
index c5d383422..7ea383c81 100644
--- a/networking/libiproute/ll_map.h
+++ b/networking/libiproute/ll_map.h
@@ -7,8 +7,8 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
7int ll_remember_index(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) FAST_FUNC; 7int ll_remember_index(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) FAST_FUNC;
8int ll_init_map(struct rtnl_handle *rth) FAST_FUNC; 8int ll_init_map(struct rtnl_handle *rth) FAST_FUNC;
9int xll_name_to_index(const char *name) FAST_FUNC; 9int xll_name_to_index(const char *name) FAST_FUNC;
10//static: const char *ll_idx_n2a(int idx, char *buf) FAST_FUNC;
10const char *ll_index_to_name(int idx) FAST_FUNC; 11const char *ll_index_to_name(int idx) FAST_FUNC;
11const char *ll_idx_n2a(int idx, char *buf) FAST_FUNC;
12/* int ll_index_to_type(int idx); */ 12/* int ll_index_to_type(int idx); */
13unsigned ll_index_to_flags(int idx) FAST_FUNC; 13unsigned ll_index_to_flags(int idx) FAST_FUNC;
14 14
diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c
index c474ab903..51f2e9bdb 100644
--- a/networking/libiproute/rt_names.c
+++ b/networking/libiproute/rt_names.c
@@ -10,20 +10,32 @@
10#include "libbb.h" 10#include "libbb.h"
11#include "rt_names.h" 11#include "rt_names.h"
12 12
13#define CONFDIR CONFIG_FEATURE_IP_ROUTE_DIR
14
13typedef struct rtnl_tab_t { 15typedef struct rtnl_tab_t {
14 const char *cached_str; 16 const char *cached_str;
15 unsigned cached_result; 17 unsigned cached_result;
16 const char *tab[256]; 18 /* upstream version switched to a hash table and removed
19 * id < 256 limit. For now bbox bumps this array size from 256
20 * to 1024. If you plan to change this to a hash table,
21 * consider merging several hash tables we have (for example,
22 * awk has resizable one!
23 */
24#define RT_TABLE_MAX 1023
25 const char *tab[RT_TABLE_MAX+1];
17} rtnl_tab_t; 26} rtnl_tab_t;
18 27
19static void rtnl_tab_initialize(const char *file, const char **tab) 28static void rtnl_tab_initialize(const char *file, const char **tab)
20{ 29{
21 char *token[2]; 30 char *token[2];
22 parser_t *parser = config_open2(file, fopen_for_read); 31 char fullname[sizeof(CONFDIR"/rt_dsfield") + 8];
32 parser_t *parser;
23 33
34 sprintf(fullname, CONFDIR"/rt_%s", file);
35 parser = config_open2(fullname, fopen_for_read);
24 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) { 36 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
25 unsigned id = bb_strtou(token[0], NULL, 0); 37 unsigned id = bb_strtou(token[0], NULL, 0);
26 if (id > 256) { 38 if (id > RT_TABLE_MAX) {
27 bb_error_msg("database %s is corrupted at line %d", 39 bb_error_msg("database %s is corrupted at line %d",
28 file, parser->lineno); 40 file, parser->lineno);
29 break; 41 break;
@@ -42,7 +54,7 @@ static int rtnl_a2n(rtnl_tab_t *tab, uint32_t *id, const char *arg, int base)
42 return 0; 54 return 0;
43 } 55 }
44 56
45 for (i = 0; i < 256; i++) { 57 for (i = 0; i <= RT_TABLE_MAX; i++) {
46 if (tab->tab[i] 58 if (tab->tab[i]
47 && strcmp(tab->tab[i], arg) == 0 59 && strcmp(tab->tab[i], arg) == 0
48 ) { 60 ) {
@@ -54,7 +66,7 @@ static int rtnl_a2n(rtnl_tab_t *tab, uint32_t *id, const char *arg, int base)
54 } 66 }
55 67
56 i = bb_strtou(arg, NULL, base); 68 i = bb_strtou(arg, NULL, base);
57 if (i > 255) 69 if (i > RT_TABLE_MAX)
58 return -1; 70 return -1;
59 *id = i; 71 *id = i;
60 return 0; 72 return 0;
@@ -85,24 +97,23 @@ static void rtnl_rtprot_initialize(void)
85 return; 97 return;
86 rtnl_rtprot_tab = xzalloc(sizeof(*rtnl_rtprot_tab)); 98 rtnl_rtprot_tab = xzalloc(sizeof(*rtnl_rtprot_tab));
87 memcpy(rtnl_rtprot_tab->tab, init_tab, sizeof(init_tab)); 99 memcpy(rtnl_rtprot_tab->tab, init_tab, sizeof(init_tab));
88 rtnl_tab_initialize("/etc/iproute2/rt_protos", rtnl_rtprot_tab->tab); 100 rtnl_tab_initialize("protos", rtnl_rtprot_tab->tab);
89} 101}
90 102
91const char* FAST_FUNC rtnl_rtprot_n2a(int id, char *buf) 103#if 0 /* UNUSED */
104const char* FAST_FUNC rtnl_rtprot_n2a(int id)
92{ 105{
93 if (id < 0 || id >= 256) { 106 if (id < 0 || id > RT_TABLE_MAX) {
94 sprintf(buf, "%d", id); 107 return itoa(id);
95 return buf;
96 } 108 }
97 109
98 rtnl_rtprot_initialize(); 110 rtnl_rtprot_initialize();
99 111
100 if (rtnl_rtprot_tab->tab[id]) 112 if (rtnl_rtprot_tab->tab[id])
101 return rtnl_rtprot_tab->tab[id]; 113 return rtnl_rtprot_tab->tab[id];
102 /* buf is SPRINT_BSIZE big */ 114 return itoa(id);
103 sprintf(buf, "%d", id);
104 return buf;
105} 115}
116#endif
106 117
107int FAST_FUNC rtnl_rtprot_a2n(uint32_t *id, char *arg) 118int FAST_FUNC rtnl_rtprot_a2n(uint32_t *id, char *arg)
108{ 119{
@@ -123,23 +134,20 @@ static void rtnl_rtscope_initialize(void)
123 rtnl_rtscope_tab->tab[254] = "host"; 134 rtnl_rtscope_tab->tab[254] = "host";
124 rtnl_rtscope_tab->tab[253] = "link"; 135 rtnl_rtscope_tab->tab[253] = "link";
125 rtnl_rtscope_tab->tab[200] = "site"; 136 rtnl_rtscope_tab->tab[200] = "site";
126 rtnl_tab_initialize("/etc/iproute2/rt_scopes", rtnl_rtscope_tab->tab); 137 rtnl_tab_initialize("scopes", rtnl_rtscope_tab->tab);
127} 138}
128 139
129const char* FAST_FUNC rtnl_rtscope_n2a(int id, char *buf) 140const char* FAST_FUNC rtnl_rtscope_n2a(int id)
130{ 141{
131 if (id < 0 || id >= 256) { 142 if (id < 0 || id > RT_TABLE_MAX) {
132 sprintf(buf, "%d", id); 143 return itoa(id);
133 return buf;
134 } 144 }
135 145
136 rtnl_rtscope_initialize(); 146 rtnl_rtscope_initialize();
137 147
138 if (rtnl_rtscope_tab->tab[id]) 148 if (rtnl_rtscope_tab->tab[id])
139 return rtnl_rtscope_tab->tab[id]; 149 return rtnl_rtscope_tab->tab[id];
140 /* buf is SPRINT_BSIZE big */ 150 return itoa(id);
141 sprintf(buf, "%d", id);
142 return buf;
143} 151}
144 152
145int FAST_FUNC rtnl_rtscope_a2n(uint32_t *id, char *arg) 153int FAST_FUNC rtnl_rtscope_a2n(uint32_t *id, char *arg)
@@ -156,7 +164,7 @@ static void rtnl_rtrealm_initialize(void)
156 if (rtnl_rtrealm_tab) return; 164 if (rtnl_rtrealm_tab) return;
157 rtnl_rtrealm_tab = xzalloc(sizeof(*rtnl_rtrealm_tab)); 165 rtnl_rtrealm_tab = xzalloc(sizeof(*rtnl_rtrealm_tab));
158 rtnl_rtrealm_tab->tab[0] = "unknown"; 166 rtnl_rtrealm_tab->tab[0] = "unknown";
159 rtnl_tab_initialize("/etc/iproute2/rt_realms", rtnl_rtrealm_tab->tab); 167 rtnl_tab_initialize("realms", rtnl_rtrealm_tab->tab);
160} 168}
161 169
162int FAST_FUNC rtnl_rtrealm_a2n(uint32_t *id, char *arg) 170int FAST_FUNC rtnl_rtrealm_a2n(uint32_t *id, char *arg)
@@ -166,20 +174,17 @@ int FAST_FUNC rtnl_rtrealm_a2n(uint32_t *id, char *arg)
166} 174}
167 175
168#if ENABLE_FEATURE_IP_RULE 176#if ENABLE_FEATURE_IP_RULE
169const char* FAST_FUNC rtnl_rtrealm_n2a(int id, char *buf) 177const char* FAST_FUNC rtnl_rtrealm_n2a(int id)
170{ 178{
171 if (id < 0 || id >= 256) { 179 if (id < 0 || id > RT_TABLE_MAX) {
172 sprintf(buf, "%d", id); 180 return itoa(id);
173 return buf;
174 } 181 }
175 182
176 rtnl_rtrealm_initialize(); 183 rtnl_rtrealm_initialize();
177 184
178 if (rtnl_rtrealm_tab->tab[id]) 185 if (rtnl_rtrealm_tab->tab[id])
179 return rtnl_rtrealm_tab->tab[id]; 186 return rtnl_rtrealm_tab->tab[id];
180 /* buf is SPRINT_BSIZE big */ 187 return itoa(id);
181 sprintf(buf, "%d", id);
182 return buf;
183} 188}
184#endif 189#endif
185 190
@@ -191,23 +196,20 @@ static void rtnl_rtdsfield_initialize(void)
191 if (rtnl_rtdsfield_tab) return; 196 if (rtnl_rtdsfield_tab) return;
192 rtnl_rtdsfield_tab = xzalloc(sizeof(*rtnl_rtdsfield_tab)); 197 rtnl_rtdsfield_tab = xzalloc(sizeof(*rtnl_rtdsfield_tab));
193 rtnl_rtdsfield_tab->tab[0] = "0"; 198 rtnl_rtdsfield_tab->tab[0] = "0";
194 rtnl_tab_initialize("/etc/iproute2/rt_dsfield", rtnl_rtdsfield_tab->tab); 199 rtnl_tab_initialize("dsfield", rtnl_rtdsfield_tab->tab);
195} 200}
196 201
197const char* FAST_FUNC rtnl_dsfield_n2a(int id, char *buf) 202const char* FAST_FUNC rtnl_dsfield_n2a(int id)
198{ 203{
199 if (id < 0 || id >= 256) { 204 if (id < 0 || id > RT_TABLE_MAX) {
200 sprintf(buf, "%d", id); 205 return itoa(id);
201 return buf;
202 } 206 }
203 207
204 rtnl_rtdsfield_initialize(); 208 rtnl_rtdsfield_initialize();
205 209
206 if (rtnl_rtdsfield_tab->tab[id]) 210 if (rtnl_rtdsfield_tab->tab[id])
207 return rtnl_rtdsfield_tab->tab[id]; 211 return rtnl_rtdsfield_tab->tab[id];
208 /* buf is SPRINT_BSIZE big */ 212 return itoa(id);
209 sprintf(buf, "0x%02x", id);
210 return buf;
211} 213}
212 214
213int FAST_FUNC rtnl_dsfield_a2n(uint32_t *id, char *arg) 215int FAST_FUNC rtnl_dsfield_a2n(uint32_t *id, char *arg)
@@ -222,29 +224,28 @@ static rtnl_tab_t *rtnl_rttable_tab;
222 224
223static void rtnl_rttable_initialize(void) 225static void rtnl_rttable_initialize(void)
224{ 226{
225 if (rtnl_rtdsfield_tab) return; 227 if (rtnl_rttable_tab)
228 return;
229
226 rtnl_rttable_tab = xzalloc(sizeof(*rtnl_rttable_tab)); 230 rtnl_rttable_tab = xzalloc(sizeof(*rtnl_rttable_tab));
227 rtnl_rttable_tab->tab[0] = "unspec"; 231 rtnl_rttable_tab->tab[0] = "unspec";
228 rtnl_rttable_tab->tab[255] = "local"; 232 rtnl_rttable_tab->tab[255] = "local";
229 rtnl_rttable_tab->tab[254] = "main"; 233 rtnl_rttable_tab->tab[254] = "main";
230 rtnl_rttable_tab->tab[253] = "default"; 234 rtnl_rttable_tab->tab[253] = "default";
231 rtnl_tab_initialize("/etc/iproute2/rt_tables", rtnl_rttable_tab->tab); 235 rtnl_tab_initialize("tables", rtnl_rttable_tab->tab);
232} 236}
233 237
234const char* FAST_FUNC rtnl_rttable_n2a(int id, char *buf) 238const char* FAST_FUNC rtnl_rttable_n2a(int id)
235{ 239{
236 if (id < 0 || id >= 256) { 240 if (id < 0 || id > RT_TABLE_MAX) {
237 sprintf(buf, "%d", id); 241 return itoa(id);
238 return buf;
239 } 242 }
240 243
241 rtnl_rttable_initialize(); 244 rtnl_rttable_initialize();
242 245
243 if (rtnl_rttable_tab->tab[id]) 246 if (rtnl_rttable_tab->tab[id])
244 return rtnl_rttable_tab->tab[id]; 247 return rtnl_rttable_tab->tab[id];
245 /* buf is SPRINT_BSIZE big */ 248 return itoa(id);
246 sprintf(buf, "%d", id);
247 return buf;
248} 249}
249 250
250int FAST_FUNC rtnl_rttable_a2n(uint32_t *id, char *arg) 251int FAST_FUNC rtnl_rttable_a2n(uint32_t *id, char *arg)
diff --git a/networking/libiproute/rt_names.h b/networking/libiproute/rt_names.h
index e73aa851c..29932d6a4 100644
--- a/networking/libiproute/rt_names.h
+++ b/networking/libiproute/rt_names.h
@@ -4,12 +4,11 @@
4 4
5PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 5PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
6 6
7/* buf is SPRINT_BSIZE big */ 7extern const char* rtnl_rtprot_n2a(int id) FAST_FUNC;
8extern const char* rtnl_rtprot_n2a(int id, char *buf) FAST_FUNC; 8extern const char* rtnl_rtscope_n2a(int id) FAST_FUNC;
9extern const char* rtnl_rtscope_n2a(int id, char *buf) FAST_FUNC; 9extern const char* rtnl_rtrealm_n2a(int id) FAST_FUNC;
10extern const char* rtnl_rtrealm_n2a(int id, char *buf) FAST_FUNC; 10extern const char* rtnl_dsfield_n2a(int id) FAST_FUNC;
11extern const char* rtnl_dsfield_n2a(int id, char *buf) FAST_FUNC; 11extern const char* rtnl_rttable_n2a(int id) FAST_FUNC;
12extern const char* rtnl_rttable_n2a(int id, char *buf) FAST_FUNC;
13extern int rtnl_rtprot_a2n(uint32_t *id, char *arg) FAST_FUNC; 12extern int rtnl_rtprot_a2n(uint32_t *id, char *arg) FAST_FUNC;
14extern int rtnl_rtscope_a2n(uint32_t *id, char *arg) FAST_FUNC; 13extern int rtnl_rtscope_a2n(uint32_t *id, char *arg) FAST_FUNC;
15extern int rtnl_rtrealm_a2n(uint32_t *id, char *arg) FAST_FUNC; 14extern int rtnl_rtrealm_a2n(uint32_t *id, char *arg) FAST_FUNC;
diff --git a/networking/libiproute/rtm_map.c b/networking/libiproute/rtm_map.c
index 3bab53baf..c763da049 100644
--- a/networking/libiproute/rtm_map.c
+++ b/networking/libiproute/rtm_map.c
@@ -12,7 +12,7 @@
12#include "rt_names.h" 12#include "rt_names.h"
13#include "utils.h" 13#include "utils.h"
14 14
15const char* FAST_FUNC rtnl_rtntype_n2a(int id, char *buf) 15const char* FAST_FUNC rtnl_rtntype_n2a(int id)
16{ 16{
17 switch (id) { 17 switch (id) {
18 case RTN_UNSPEC: 18 case RTN_UNSPEC:
@@ -40,9 +40,7 @@ const char* FAST_FUNC rtnl_rtntype_n2a(int id, char *buf)
40 case RTN_XRESOLVE: 40 case RTN_XRESOLVE:
41 return "xresolve"; 41 return "xresolve";
42 default: 42 default:
43 /* buf is SPRINT_BSIZE big */ 43 return itoa(id);
44 sprintf(buf, "%d", id);
45 return buf;
46 } 44 }
47} 45}
48 46
diff --git a/networking/libiproute/rtm_map.h b/networking/libiproute/rtm_map.h
index 4377bd590..63b665169 100644
--- a/networking/libiproute/rtm_map.h
+++ b/networking/libiproute/rtm_map.h
@@ -4,7 +4,7 @@
4 4
5PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 5PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
6 6
7const char *rtnl_rtntype_n2a(int id, char *buf) FAST_FUNC; 7const char *rtnl_rtntype_n2a(int id) FAST_FUNC;
8int rtnl_rtntype_a2n(int *id, char *arg) FAST_FUNC; 8int rtnl_rtntype_a2n(int *id, char *arg) FAST_FUNC;
9 9
10int get_rt_realms(uint32_t *realms, char *arg) FAST_FUNC; 10int get_rt_realms(uint32_t *realms, char *arg) FAST_FUNC;
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index cadda5261..a601430b6 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -83,7 +83,7 @@ int nbdclient_main(int argc, char **argv)
83 83
84 // Find and connect to server 84 // Find and connect to server
85 sock = create_and_connect_stream_or_die(host, xatou16(port)); 85 sock = create_and_connect_stream_or_die(host, xatou16(port));
86 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); 86 setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY);
87 87
88 // Log on to the server 88 // Log on to the server
89 xread(sock, &nbd_header, 8+8+8+4 + 124); 89 xread(sock, &nbd_header, 8+8+8+4 + 124);
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index b28d05f51..471ae1a12 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -863,8 +863,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
863 xbind(netfd, &ouraddr->u.sa, ouraddr->len); 863 xbind(netfd, &ouraddr->u.sa, ouraddr->len);
864 } 864 }
865#if 0 865#if 0
866 setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf); 866 setsockopt_SOL_SOCKET_int(netfd, SO_RCVBUF, o_rcvbuf);
867 setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); 867 setsockopt_SOL_SOCKET_int(netfd, SO_SNDBUF, o_sndbuf);
868#endif 868#endif
869 869
870#ifdef BLOAT 870#ifdef BLOAT
diff --git a/networking/ntpd.c b/networking/ntpd.c
index b5120a70d..9732c9b1a 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -405,8 +405,6 @@ struct globals {
405}; 405};
406#define G (*ptr_to_globals) 406#define G (*ptr_to_globals)
407 407
408static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
409
410 408
411#define VERB1 if (MAX_VERBOSE && G.verbose) 409#define VERB1 if (MAX_VERBOSE && G.verbose)
412#define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2) 410#define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2)
@@ -837,7 +835,7 @@ send_query_to_peer(peer_t *p)
837#if ENABLE_FEATURE_IPV6 835#if ENABLE_FEATURE_IPV6
838 if (family == AF_INET) 836 if (family == AF_INET)
839#endif 837#endif
840 setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); 838 setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
841 free(local_lsa); 839 free(local_lsa);
842 } 840 }
843 841
@@ -2186,7 +2184,7 @@ static NOINLINE void ntp_init(char **argv)
2186 xfunc_die(); 2184 xfunc_die();
2187 } 2185 }
2188 socket_want_pktinfo(G_listen_fd); 2186 socket_want_pktinfo(G_listen_fd);
2189 setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); 2187 setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
2190 } 2188 }
2191#endif 2189#endif
2192 if (!(opts & OPT_n)) { 2190 if (!(opts & OPT_n)) {
diff --git a/networking/ping.c b/networking/ping.c
index c475395e7..0eb1ae799 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -247,7 +247,7 @@ static void ping6(len_and_sockaddr *lsa)
247 pkt->icmp6_type = ICMP6_ECHO_REQUEST; 247 pkt->icmp6_type = ICMP6_ECHO_REQUEST;
248 248
249 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); 249 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
250 setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt)); 250 setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
251 251
252 xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); 252 xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len);
253 253
@@ -396,10 +396,8 @@ struct globals {
396#define dotted (G.dotted ) 396#define dotted (G.dotted )
397#define pingaddr (G.pingaddr ) 397#define pingaddr (G.pingaddr )
398#define rcvd_tbl (G.rcvd_tbl ) 398#define rcvd_tbl (G.rcvd_tbl )
399void BUG_ping_globals_too_big(void);
400#define INIT_G() do { \ 399#define INIT_G() do { \
401 if (sizeof(G) > COMMON_BUFSIZE) \ 400 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
402 BUG_ping_globals_too_big(); \
403 datalen = DEFDATALEN; \ 401 datalen = DEFDATALEN; \
404 timeout = MAXWAIT; \ 402 timeout = MAXWAIT; \
405 tmin = UINT_MAX; \ 403 tmin = UINT_MAX; \
@@ -700,12 +698,12 @@ static void ping4(len_and_sockaddr *lsa)
700 /* set recv buf (needed if we can get lots of responses: flood ping, 698 /* set recv buf (needed if we can get lots of responses: flood ping,
701 * broadcast ping etc) */ 699 * broadcast ping etc) */
702 sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ 700 sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
703 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); 701 setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt);
704 702
705 if (opt_ttl != 0) { 703 if (opt_ttl != 0) {
706 setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl)); 704 setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl);
707 /* above doesnt affect packets sent to bcast IP, so... */ 705 /* above doesnt affect packets sent to bcast IP, so... */
708 setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl)); 706 setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl);
709 } 707 }
710 708
711 signal(SIGINT, print_stats_and_exit); 709 signal(SIGINT, print_stats_and_exit);
@@ -732,7 +730,6 @@ static void ping4(len_and_sockaddr *lsa)
732 } 730 }
733} 731}
734#if ENABLE_PING6 732#if ENABLE_PING6
735extern int BUG_bad_offsetof_icmp6_cksum(void);
736static void ping6(len_and_sockaddr *lsa) 733static void ping6(len_and_sockaddr *lsa)
737{ 734{
738 int sockopt; 735 int sockopt;
@@ -756,7 +753,7 @@ static void ping6(len_and_sockaddr *lsa)
756 } 753 }
757 if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 754 if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
758 sizeof(filt)) < 0) 755 sizeof(filt)) < 0)
759 bb_error_msg_and_die("setsockopt(ICMP6_FILTER)"); 756 bb_error_msg_and_die("setsockopt(%s)", "ICMP6_FILTER");
760 } 757 }
761#endif /*ICMP6_FILTER*/ 758#endif /*ICMP6_FILTER*/
762 759
@@ -766,15 +763,14 @@ static void ping6(len_and_sockaddr *lsa)
766 /* set recv buf (needed if we can get lots of responses: flood ping, 763 /* set recv buf (needed if we can get lots of responses: flood ping,
767 * broadcast ping etc) */ 764 * broadcast ping etc) */
768 sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ 765 sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
769 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); 766 setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt);
770 767
771 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); 768 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
772 if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2) 769 BUILD_BUG_ON(offsetof(struct icmp6_hdr, icmp6_cksum) != 2);
773 BUG_bad_offsetof_icmp6_cksum(); 770 setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
774 setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
775 771
776 /* request ttl info to be returned in ancillary data */ 772 /* request ttl info to be returned in ancillary data */
777 setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1)); 773 setsockopt_1(pingsock, SOL_IPV6, IPV6_HOPLIMIT);
778 774
779 if (if_index) 775 if (if_index)
780 pingaddr.sin6.sin6_scope_id = if_index; 776 pingaddr.sin6.sin6_scope_id = if_index;
diff --git a/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 b/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8
new file mode 100755
index 000000000..50b6102d9
--- /dev/null
+++ b/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8
@@ -0,0 +1,22 @@
1#!/bin/sh
2
3# How to configure & build a static wolfssl-3.6.8 library
4# suitable for static build of ssl_helper.
5
6export CC="i686-gcc"
7export CFLAGS="\
8-Os \
9-static \
10-fomit-frame-pointer \
11-falign-functions=1 -falign-labels=1 -falign-loops=1 -falign-jumps=1 \
12-ffunction-sections -fdata-sections \
13"
14
15./configure \
16 --host=i686 \
17 --enable-static \
18 --enable-singlethreaded \
19 --disable-shared \
20|| exit $?
21
22make
diff --git a/networking/ssl_helper-wolfssl/README b/networking/ssl_helper-wolfssl/README
new file mode 100644
index 000000000..58a381c20
--- /dev/null
+++ b/networking/ssl_helper-wolfssl/README
@@ -0,0 +1,20 @@
1A small SSL helper for busybox wget.
2
3Precompiled static binary may be found in
4http://busybox.net/downloads/binaries/
5
6Build instructions:
7
8* Unpack wolfssl-3.6.8.zip
9* Build it:
10 ./configure --enable-static --disable-shared && make
11* Drop this directory into wolfssl-3.6.8/ssl_helper
12* Run ssl_helper.sh to compile and link the helper
13
14Usage: "ssl_helper -d FILE_DESCRIPTOR" where FILE_DESCRIPTOR is open to the peer.
15
16In bash, you can do it this way:
17$ ssl_helper -d3 3<>/dev/tcp/HOST/PORT
18
19Stdin will be SSL-encrypted and sent to FILE_DESCRIPTOR.
20Data from FILE_DESCRIPTOR will be decrypted and sent to stdout.
diff --git a/networking/ssl_helper-wolfssl/ssl_helper.c b/networking/ssl_helper-wolfssl/ssl_helper.c
new file mode 100644
index 000000000..38b7b56c6
--- /dev/null
+++ b/networking/ssl_helper-wolfssl/ssl_helper.c
@@ -0,0 +1,480 @@
1/*
2 * Adapted from:
3 *
4 * client.c
5 *
6 * Copyright (C) 2006-2015 wolfSSL Inc.
7 *
8 * This file is part of wolfSSL. (formerly known as CyaSSL)
9 *
10 * wolfSSL is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * wolfSSL is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24#include <stdlib.h>
25#include <unistd.h>
26#include <stdarg.h>
27#include <string.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <time.h>
32#include <poll.h>
33#include <sys/socket.h>
34
35#include <wolfssl/wolfcrypt/types.h>
36#include <wolfssl/ssl.h>
37
38#if 0
39# define dbg(...) say(__VA_ARGS__)
40#else
41# define dbg(...) ((void)0)
42#endif
43
44static ssize_t safe_write(int fd, const void *buf, size_t count)
45{
46 ssize_t n;
47
48 do {
49 n = write(fd, buf, count);
50 } while (n < 0 && errno == EINTR);
51
52 return n;
53}
54
55static ssize_t full_write(int fd, const void *buf, size_t len)
56{
57 ssize_t cc;
58 ssize_t total;
59
60 total = 0;
61
62 while (len) {
63 cc = safe_write(fd, buf, len);
64
65 if (cc < 0) {
66 if (total) {
67 /* we already wrote some! */
68 /* user can do another write to know the error code */
69 return total;
70 }
71 return cc; /* write() returns -1 on failure. */
72 }
73
74 total += cc;
75 buf = ((const char *)buf) + cc;
76 len -= cc;
77 }
78
79 return total;
80}
81
82static void say(const char *s, ...)
83{
84 char buf[256];
85 va_list p;
86 int sz;
87
88 va_start(p, s);
89 sz = vsnprintf(buf, sizeof(buf), s, p);
90 full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
91 va_end(p);
92}
93
94static void die(const char *s, ...)
95{
96 char buf[256];
97 va_list p;
98 int sz;
99
100 va_start(p, s);
101 sz = vsnprintf(buf, sizeof(buf), s, p);
102 full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
103 exit(1);
104 va_end(p);
105}
106
107static void err_sys(const char *msg)
108{
109 die("%s\n", msg);
110}
111
112/* ==== */
113
114#if 0
115static void showPeer(WOLFSSL* ssl)
116{
117 WOLFSSL_CIPHER* cipher;
118 WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
119 if (peer)
120 ShowX509(peer, "peer's cert info:");
121 else
122 say("peer has no cert!\n");
123 say("SSL version is %s\n", wolfSSL_get_version(ssl));
124
125 cipher = wolfSSL_get_current_cipher(ssl);
126 say("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher));
127
128 {
129 WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl);
130 int count = wolfSSL_get_chain_count(chain);
131 int i;
132
133 for (i = 0; i < count; i++) {
134 int length;
135 unsigned char buffer[3072];
136 WOLFSSL_X509* chainX509;
137
138 wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length);
139 buffer[length] = 0;
140 say("cert %d has length %d data = \n%s\n", i, length, buffer);
141
142 chainX509 = wolfSSL_get_chain_X509(chain, i);
143 if (chainX509)
144 ShowX509(chainX509, "session cert info:");
145 else
146 say("get_chain_X509 failed\n");
147 wolfSSL_FreeX509(chainX509);
148 }
149 }
150}
151#endif
152
153WOLFSSL *prepare(int sockfd)
154{
155 WOLFSSL_METHOD* method;
156 WOLFSSL_CTX* ctx;
157 WOLFSSL* ssl;
158
159 wolfSSL_Init();
160
161 method = wolfTLSv1_1_client_method();
162 if (method == NULL)
163 err_sys("out of memory");
164 ctx = wolfSSL_CTX_new(method);
165 if (ctx == NULL)
166 err_sys("out of memory");
167// if (cipherList)
168// if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
169// err_sys("client can't set cipher list 1");
170
171// if (fewerPackets)
172// wolfSSL_CTX_set_group_messages(ctx);
173
174//#ifndef NO_DH
175// wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
176//#endif
177
178// if (usePsk) {
179// wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
180// if (cipherList == NULL) {
181// const char *defaultCipherList;
182//#if defined(HAVE_AESGCM) && !defined(NO_DH)
183// defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
184//#elif defined(HAVE_NULL_CIPHER)
185// defaultCipherList = "PSK-NULL-SHA256";
186//#else
187// defaultCipherList = "PSK-AES128-CBC-SHA256";
188//#endif
189// if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) != SSL_SUCCESS)
190// err_sys("client can't set cipher list 2");
191// }
192// useClientCert = 0;
193// }
194
195// if (useAnon) {
196// if (cipherList == NULL) {
197// wolfSSL_CTX_allow_anon_cipher(ctx);
198// if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS)
199// err_sys("client can't set cipher list 4");
200// }
201// useClientCert = 0;
202// }
203
204//#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
205// wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
206//#endif
207
208// if (useOcsp) {
209// if (ocspUrl != NULL) {
210// wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
211// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE
212// | WOLFSSL_OCSP_URL_OVERRIDE);
213// }
214// else
215// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
216// }
217//
218//#ifdef USER_CA_CB
219// wolfSSL_CTX_SetCACb(ctx, CaCb);
220//#endif
221//
222//#ifdef VERIFY_CALLBACK
223// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
224//#endif
225//#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
226// if (useClientCert) {
227// if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS)
228// err_sys("can't load client cert file, check file and run from"
229// " wolfSSL home dir");
230// if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS)
231// err_sys("can't load client private key file, check file and run "
232// "from wolfSSL home dir");
233// }
234//
235// if (!usePsk && !useAnon) {
236// if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS)
237// err_sys("can't load ca file, Please run from wolfSSL home dir");
238//#ifdef HAVE_ECC
239// /* load ecc verify too, echoserver uses it by default w/ ecc */
240// if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS)
241// err_sys("can't load ecc ca file, Please run from wolfSSL home dir");
242//#endif
243// }
244//#endif /* !NO_FILESYSTEM && !NO_CERTS */
245
246//#if !defined(NO_CERTS)
247// if (!usePsk && !useAnon && doPeerCheck == 0)
248// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
249// if (!usePsk && !useAnon && overrideDateErrors == 1)
250// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb);
251//#endif
252
253 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
254
255//#ifdef HAVE_SNI
256// if (sniHostName)
257// if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS)
258// err_sys("UseSNI failed");
259//#endif
260
261//#ifdef HAVE_MAX_FRAGMENT
262// if (maxFragment)
263// if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS)
264// err_sys("UseMaxFragment failed");
265//#endif
266//#ifdef HAVE_TRUNCATED_HMAC
267// if (truncatedHMAC)
268// if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
269// err_sys("UseTruncatedHMAC failed");
270//#endif
271//#ifdef HAVE_SESSION_TICKET
272// if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
273// err_sys("UseSessionTicket failed");
274//#endif
275
276//#if defined(WOLFSSL_MDK_ARM)
277// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
278//#endif
279
280 ssl = wolfSSL_new(ctx);
281 if (ssl == NULL)
282 err_sys("out of memory");
283
284//#ifdef HAVE_SESSION_TICKET
285// wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session");
286//#endif
287
288// if (doDTLS) {
289// SOCKADDR_IN_T addr;
290// build_addr(&addr, host, port, 1);
291// wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
292// tcp_socket(&sockfd, 1);
293// } wlse {
294// tcp_connect(&sockfd, host, port, 0);
295// }
296
297//#ifdef HAVE_POLY1305
298// /* use old poly to connect with google server */
299// if (!XSTRNCMP(domain, "www.google.com", 14)) {
300// if (wolfSSL_use_old_poly(ssl, 1) != 0)
301// err_sys("unable to set to old poly");
302// }
303//#endif
304
305 wolfSSL_set_fd(ssl, sockfd);
306
307//#ifdef HAVE_CRL
308// if (disableCRL == 0) {
309// if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS)
310// err_sys("can't enable crl check");
311// if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS)
312// err_sys("can't load crl, check crlfile and date validity");
313// if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
314// err_sys("can't set crl callback");
315// }
316//#endif
317//#ifdef HAVE_SECURE_RENEGOTIATION
318// if (scr) {
319// if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
320// err_sys("can't enable secure renegotiation");
321// }
322//#endif
323//#ifdef ATOMIC_USER
324// if (atomicUser)
325// SetupAtomicUser(ctx, ssl);
326//#endif
327//#ifdef HAVE_PK_CALLBACKS
328// if (pkCallbacks)
329// SetupPkCallbacks(ctx, ssl);
330//#endif
331// if (matchName && doPeerCheck)
332// wolfSSL_check_domain_name(ssl, domain);
333
334 if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
335// /* see note at top of README */
336// int err = wolfSSL_get_error(ssl, 0);
337// char buffer[WOLFSSL_MAX_ERROR_SZ];
338// say("err = %d, %s\n", err,
339// wolfSSL_ERR_error_string(err, buffer));
340 err_sys("SSL_connect failed");
341 }
342// showPeer(ssl);
343
344//#ifdef HAVE_SECURE_RENEGOTIATION
345// if (scr && forceScr) {
346// if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) {
347// int err = wolfSSL_get_error(ssl, 0);
348// char buffer[WOLFSSL_MAX_ERROR_SZ];
349// say("err = %d, %s\n", err,
350// wolfSSL_ERR_error_string(err, buffer));
351// err_sys("wolfSSL_Rehandshake failed");
352// }
353// }
354//#endif
355
356 return ssl;
357}
358
359static struct pollfd pfd[2] = {
360 { -1, POLLIN|POLLERR|POLLHUP, 0 },
361 { -1, POLLIN|POLLERR|POLLHUP, 0 },
362};
363#define STDIN pfd[0]
364#define NETWORK pfd[1]
365#define STDIN_READY() (pfd[0].revents & (POLLIN|POLLERR|POLLHUP))
366#define NETWORK_READY() (pfd[1].revents & (POLLIN|POLLERR|POLLHUP))
367
368static void wait_for_input(void)
369{
370 if (STDIN.fd == NETWORK.fd) /* means both are -1 */
371 exit(0);
372 dbg("polling\n");
373 STDIN.revents = NETWORK.revents = 0;
374 while (poll(pfd, 2, -1) < 0 && errno == EINTR)
375 continue;
376}
377
378static void do_io_until_eof_and_exit(WOLFSSL *ssl, int fd)
379{
380 int len;
381 char ibuf[4 * 1024];
382
383 NETWORK.fd = fd;
384 STDIN.fd = 0;
385
386 len = 0; /* only to suppress compiler warning */
387 for (;;) {
388 wait_for_input();
389
390 if (STDIN_READY()) {
391 dbg("reading stdin\n");
392 len = read(STDIN_FILENO, ibuf, sizeof(ibuf));
393 if (len < 0)
394 die("read error on stdin\n");
395 if (len == 0) {
396 dbg("read len = 0, stdin not polled anymore\n");
397 STDIN.fd = -1;
398 } else {
399 int n = wolfSSL_write(ssl, ibuf, len);
400 if (n != len)
401 die("SSL_write(%d) failed (returned %d)\n", len, n);
402 }
403 }
404
405 if (NETWORK_READY()) {
406 dbg("%s%s%s\n",
407 (pfd[1].revents & POLLIN) ? "POLLIN" : "",
408 (pfd[1].revents & POLLERR) ? "|POLLERR" : "",
409 (pfd[1].revents & POLLHUP) ? "|POLLHUP" : ""
410 );
411/* We are using blocking socket here.
412 * (Nonblocking socket would complicate writing to it).
413 * Therefore, SSL_read _can block_ here.
414 * This is not what wget expects (it wants to see short reads).
415 * Therefore, we use smallish buffer here, to approximate that.
416 */
417 len = wolfSSL_read(ssl, ibuf,
418 sizeof(ibuf) < 1024 ? sizeof(ibuf) : 1024
419 );
420 if (len < 0)
421 die("SSL_read error on network (%d)\n", len);
422 if (len > 0) {
423 int n;
424 n = full_write(STDOUT_FILENO, ibuf, len);
425 if (n != len)
426 die("write(%d) to stdout returned %d\n", len, n);
427 continue;
428 }
429/* Blocking reads are easier wtr EOF detection (no EAGAIN error to check for) */
430 dbg("read len = 0, network not polled anymore\n");
431 NETWORK.fd = -1;
432 /* saw EOF on network, and we processed
433 * and wrote out all ssl data. Signal it:
434 */
435 close(STDOUT_FILENO);
436 }
437 }
438}
439
440int main(int argc, char **argv)
441{
442 WOLFSSL *ssl;
443 int fd;
444 char *fd_str;
445
446 if (!argv[1])
447 die("Syntax error\n");
448 if (argv[1][0] != '-')
449 die("Syntax error\n");
450 if (argv[1][1] != 'd')
451 die("Syntax error\n");
452 fd_str = argv[1] + 2;
453 if (!fd_str[0])
454 fd_str = argv[2];
455 if (!fd_str || fd_str[0] < '0' || fd_str[0] > '9')
456 die("Syntax error\n");
457
458 fd = atoi(fd_str);
459 if (fd < 3)
460 die("Syntax error\n");
461
462 ssl = prepare(fd);
463 do_io_until_eof_and_exit(ssl, fd);
464 /* does not return */
465
466// if (doDTLS == 0) { /* don't send alert after "break" command */
467// ret = wolfSSL_shutdown(ssl);
468// if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
469// wolfSSL_shutdown(ssl); /* bidirectional shutdown */
470// }
471//#ifdef ATOMIC_USER
472// if (atomicUser)
473// FreeAtomicUser(ssl);
474//#endif
475// wolfSSL_free(ssl);
476// CloseSocket(sockfd);
477// wolfSSL_CTX_free(ctx);
478
479 return 0;
480}
diff --git a/networking/ssl_helper-wolfssl/ssl_helper.sh b/networking/ssl_helper-wolfssl/ssl_helper.sh
new file mode 100755
index 000000000..184ffe67e
--- /dev/null
+++ b/networking/ssl_helper-wolfssl/ssl_helper.sh
@@ -0,0 +1,12 @@
1#!/bin/sh
2
3# I use this to build static uclibc based binary using Aboriginal Linux toolchain:
4PREFIX="i686-"
5STATIC="-static"
6# Standard build:
7#PREFIX=""
8#STATIC=""
9
10${PREFIX}gcc -Os -Wall -I.. -c ssl_helper.c -o ssl_helper.o
11${PREFIX}gcc $STATIC --start-group ssl_helper.o -lm ../src/.libs/libwolfssl.a --end-group -o ssl_helper
12${PREFIX}-strip ssl_helper
diff --git a/networking/tc.c b/networking/tc.c
index 76e2e8359..6d1fef993 100644
--- a/networking/tc.c
+++ b/networking/tc.c
@@ -64,15 +64,14 @@ struct globals {
64 uint32_t filter_proto; 64 uint32_t filter_proto;
65} FIX_ALIASING; 65} FIX_ALIASING;
66#define G (*(struct globals*)&bb_common_bufsiz1) 66#define G (*(struct globals*)&bb_common_bufsiz1)
67struct BUG_G_too_big {
68 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
69};
70#define filter_ifindex (G.filter_ifindex) 67#define filter_ifindex (G.filter_ifindex)
71#define filter_qdisc (G.filter_qdisc) 68#define filter_qdisc (G.filter_qdisc)
72#define filter_parent (G.filter_parent) 69#define filter_parent (G.filter_parent)
73#define filter_prio (G.filter_prio) 70#define filter_prio (G.filter_prio)
74#define filter_proto (G.filter_proto) 71#define filter_proto (G.filter_proto)
75#define INIT_G() do { } while (0) 72#define INIT_G() do { \
73 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
74} while (0)
76 75
77/* Allocates a buffer containing the name of a class id. 76/* Allocates a buffer containing the name of a class id.
78 * The caller must free the returned memory. */ 77 * The caller must free the returned memory. */
diff --git a/networking/telnet.c b/networking/telnet.c
index a25579773..3bb6fb1ba 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -623,7 +623,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv)
623 623
624 xmove_fd(create_and_connect_stream_or_die(host, port), netfd); 624 xmove_fd(create_and_connect_stream_or_die(host, port), netfd);
625 625
626 setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); 626 setsockopt_keepalive(netfd);
627 627
628 signal(SIGINT, record_signo); 628 signal(SIGINT, record_signo);
629 629
diff --git a/networking/telnetd.c b/networking/telnetd.c
index 6aee95871..25d05fe7a 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -265,7 +265,7 @@ make_new_session(
265 close_on_exec_on(fd); 265 close_on_exec_on(fd);
266 266
267 /* SO_KEEPALIVE by popular demand */ 267 /* SO_KEEPALIVE by popular demand */
268 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); 268 setsockopt_keepalive(sock);
269#if ENABLE_FEATURE_TELNETD_STANDALONE 269#if ENABLE_FEATURE_TELNETD_STANDALONE
270 ts->sockfd_read = sock; 270 ts->sockfd_read = sock;
271 ndelay_on(sock); 271 ndelay_on(sock);
diff --git a/networking/tftp.c b/networking/tftp.c
index 8ecd7bb6f..ad9308e52 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -129,10 +129,9 @@ struct globals {
129#endif 129#endif
130} FIX_ALIASING; 130} FIX_ALIASING;
131#define G (*(struct globals*)&bb_common_bufsiz1) 131#define G (*(struct globals*)&bb_common_bufsiz1)
132struct BUG_G_too_big { 132#define INIT_G() do { \
133 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; 133 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
134}; 134} while (0)
135#define INIT_G() do { } while (0)
136 135
137#define G_error_pkt_reason (G.error_pkt[3]) 136#define G_error_pkt_reason (G.error_pkt[3])
138#define G_error_pkt_str ((char*)(G.error_pkt + 4)) 137#define G_error_pkt_str ((char*)(G.error_pkt + 4))
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 12ba614e8..642110c54 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -211,60 +211,62 @@
211 */ 211 */
212 212
213//usage:#define traceroute_trivial_usage 213//usage:#define traceroute_trivial_usage
214//usage: "[-"IF_TRACEROUTE6("46")"FIldnrv] [-f 1ST_TTL] [-m MAXTTL] [-p PORT] [-q PROBES]\n" 214//usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
215//usage: " [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-g GATEWAY] [-i IFACE]\n" 215//usage: " [-t TOS] [-w WAIT_SEC]"
216//usage: IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(" [-g GATEWAY]")" [-s SRC_IP] [-i IFACE]\n"
216//usage: " [-z PAUSE_MSEC] HOST [BYTES]" 217//usage: " [-z PAUSE_MSEC] HOST [BYTES]"
217//usage:#define traceroute_full_usage "\n\n" 218//usage:#define traceroute_full_usage "\n\n"
218//usage: "Trace the route to HOST\n" 219//usage: "Trace the route to HOST\n"
219//usage: IF_TRACEROUTE6( 220//usage: IF_TRACEROUTE6(
220//usage: "\n -4,-6 Force IP or IPv6 name resolution" 221//usage: "\n -4,-6 Force IP or IPv6 name resolution"
221//usage: ) 222//usage: )
222//usage: "\n -F Set the don't fragment bit" 223//usage: "\n -F Set don't fragment bit"
224//usage: IF_FEATURE_TRACEROUTE_USE_ICMP(
223//usage: "\n -I Use ICMP ECHO instead of UDP datagrams" 225//usage: "\n -I Use ICMP ECHO instead of UDP datagrams"
224//usage: "\n -l Display the TTL value of the returned packet" 226//usage: )
225//usage: "\n -d Set SO_DEBUG options to socket" 227//usage: "\n -l Display TTL value of the returned packet"
228//Currently disabled (TRACEROUTE_SO_DEBUG==0)
229////usage: "\n -d Set SO_DEBUG options to socket"
226//usage: "\n -n Print numeric addresses" 230//usage: "\n -n Print numeric addresses"
227//usage: "\n -r Bypass routing tables, send directly to HOST" 231//usage: "\n -r Bypass routing tables, send directly to HOST"
232//usage: IF_FEATURE_TRACEROUTE_VERBOSE(
228//usage: "\n -v Verbose" 233//usage: "\n -v Verbose"
229//usage: "\n -m Max time-to-live (max number of hops)" 234//usage: )
230//usage: "\n -p Base UDP port number used in probes" 235//usage: "\n -f N First number of hops (default 1)"
236//usage: "\n -m N Max number of hops"
237//usage: "\n -q N Number of probes per hop (default 3)"
238//usage: "\n -p N Base UDP port number used in probes"
231//usage: "\n (default 33434)" 239//usage: "\n (default 33434)"
232//usage: "\n -q Number of probes per TTL (default 3)" 240//usage: "\n -s IP Source address"
233//usage: "\n -s IP address to use as the source address" 241//usage: "\n -i IFACE Source interface"
234//usage: "\n -t Type-of-service in probe packets (default 0)" 242//usage: "\n -t N Type-of-service in probe packets (default 0)"
235//usage: "\n -w Time in seconds to wait for a response (default 3)" 243//usage: "\n -w SEC Time to wait for a response (default 3)"
236//usage: "\n -g Loose source route gateway (8 max)" 244//usage: "\n -g IP Loose source route gateway (8 max)"
237//usage: 245//usage:
238//usage:#define traceroute6_trivial_usage 246//usage:#define traceroute6_trivial_usage
239//usage: "[-dnrv] [-m MAXTTL] [-p PORT] [-q PROBES]\n" 247//usage: "[-nrv] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
240//usage: " [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-i IFACE]\n" 248//usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n"
241//usage: " HOST [BYTES]" 249//usage: " HOST [BYTES]"
242//usage:#define traceroute6_full_usage "\n\n" 250//usage:#define traceroute6_full_usage "\n\n"
243//usage: "Trace the route to HOST\n" 251//usage: "Trace the route to HOST\n"
244//usage: "\n -d Set SO_DEBUG options to socket" 252//Currently disabled (TRACEROUTE_SO_DEBUG==0)
253////usage: "\n -d Set SO_DEBUG options to socket"
245//usage: "\n -n Print numeric addresses" 254//usage: "\n -n Print numeric addresses"
246//usage: "\n -r Bypass routing tables, send directly to HOST" 255//usage: "\n -r Bypass routing tables, send directly to HOST"
256//usage: IF_FEATURE_TRACEROUTE_VERBOSE(
247//usage: "\n -v Verbose" 257//usage: "\n -v Verbose"
248//usage: "\n -m Max time-to-live (max number of hops)" 258//usage: )
249//usage: "\n -p Base UDP port number used in probes" 259//usage: "\n -m N Max number of hops"
250//usage: "\n (default is 33434)" 260//usage: "\n -q N Number of probes per hop (default 3)"
251//usage: "\n -q Number of probes per TTL (default 3)" 261//usage: "\n -p N Base UDP port number used in probes"
252//usage: "\n -s IP address to use as the source address" 262//usage: "\n (default 33434)"
253//usage: "\n -t Type-of-service in probe packets (default 0)" 263//usage: "\n -s IP Source address"
254//usage: "\n -w Time in seconds to wait for a response (default 3)" 264//usage: "\n -i IFACE Source interface"
265//usage: "\n -t N Type-of-service in probe packets (default 0)"
266//usage: "\n -w SEC Time wait for a response (default 3)"
255 267
256#define TRACEROUTE_SO_DEBUG 0 268#define TRACEROUTE_SO_DEBUG 0
257 269
258/* TODO: undefs were uncommented - ??! we have config system for that! */
259/* probably ok to remove altogether */
260//#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
261//#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
262//#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
263//#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
264//#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
265//#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
266
267
268#include <net/if.h> 270#include <net/if.h>
269#include <arpa/inet.h> 271#include <arpa/inet.h>
270#include <netinet/in.h> 272#include <netinet/in.h>
@@ -471,18 +473,18 @@ send_probe(int seq, int ttl)
471 473
472#if ENABLE_TRACEROUTE6 474#if ENABLE_TRACEROUTE6
473 if (dest_lsa->u.sa.sa_family == AF_INET6) { 475 if (dest_lsa->u.sa.sa_family == AF_INET6) {
474 res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); 476 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
475 if (res < 0) 477 if (res != 0)
476 bb_perror_msg_and_die("setsockopt UNICAST_HOPS %d", ttl); 478 bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl);
477 out = outip; 479 out = outip;
478 len = packlen; 480 len = packlen;
479 } else 481 } else
480#endif 482#endif
481 { 483 {
482#if defined IP_TTL 484#if defined IP_TTL
483 res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); 485 res = setsockopt_int(sndsock, IPPROTO_IP, IP_TTL, ttl);
484 if (res < 0) 486 if (res != 0)
485 bb_perror_msg_and_die("setsockopt ttl %d", ttl); 487 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
486#endif 488#endif
487 out = outicmp; 489 out = outicmp;
488 len = packlen - sizeof(*outip); 490 len = packlen - sizeof(*outip);
@@ -900,13 +902,10 @@ common_traceroute_main(int op, char **argv)
900 if (af == AF_INET6) { 902 if (af == AF_INET6) {
901 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); 903 xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
902# ifdef IPV6_RECVPKTINFO 904# ifdef IPV6_RECVPKTINFO
903 setsockopt(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO, 905 setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
904 &const_int_1, sizeof(const_int_1)); 906 setsockopt_1(rcvsock, SOL_IPV6, IPV6_2292PKTINFO);
905 setsockopt(rcvsock, SOL_IPV6, IPV6_2292PKTINFO,
906 &const_int_1, sizeof(const_int_1));
907# else 907# else
908 setsockopt(rcvsock, SOL_IPV6, IPV6_PKTINFO, 908 setsockopt_1(rcvsock, SOL_IPV6, IPV6_PKTINFO);
909 &const_int_1, sizeof(const_int_1));
910# endif 909# endif
911 } else 910 } else
912#endif 911#endif
@@ -916,18 +915,15 @@ common_traceroute_main(int op, char **argv)
916 915
917#if TRACEROUTE_SO_DEBUG 916#if TRACEROUTE_SO_DEBUG
918 if (op & OPT_DEBUG) 917 if (op & OPT_DEBUG)
919 setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 918 setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG);
920 &const_int_1, sizeof(const_int_1));
921#endif 919#endif
922 if (op & OPT_BYPASS_ROUTE) 920 if (op & OPT_BYPASS_ROUTE)
923 setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 921 setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE);
924 &const_int_1, sizeof(const_int_1));
925 922
926#if ENABLE_TRACEROUTE6 923#if ENABLE_TRACEROUTE6
927 if (af == AF_INET6) { 924 if (af == AF_INET6) {
928 static const int two = 2; 925 if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
929 if (setsockopt(rcvsock, SOL_RAW, IPV6_CHECKSUM, &two, sizeof(two)) < 0) 926 bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
930 bb_perror_msg_and_die("setsockopt RAW_CHECKSUM");
931 xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock); 927 xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock);
932 } else 928 } else
933#endif 929#endif
@@ -964,28 +960,25 @@ common_traceroute_main(int op, char **argv)
964 } 960 }
965 961
966#ifdef SO_SNDBUF 962#ifdef SO_SNDBUF
967 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) { 963 if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
968 bb_perror_msg_and_die("SO_SNDBUF"); 964 bb_perror_msg_and_die("setsockopt(%s)", "SO_SNDBUF");
969 } 965 }
970#endif 966#endif
971#ifdef IP_TOS 967#ifdef IP_TOS
972 if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { 968 if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) {
973 bb_perror_msg_and_die("setsockopt tos %d", tos); 969 bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos);
974 } 970 }
975#endif 971#endif
976#ifdef IP_DONTFRAG 972#ifdef IP_DONTFRAG
977 if (op & OPT_DONT_FRAGMNT) 973 if (op & OPT_DONT_FRAGMNT)
978 setsockopt(sndsock, IPPROTO_IP, IP_DONTFRAG, 974 setsockopt_1(sndsock, IPPROTO_IP, IP_DONTFRAG);
979 &const_int_1, sizeof(const_int_1));
980#endif 975#endif
981#if TRACEROUTE_SO_DEBUG 976#if TRACEROUTE_SO_DEBUG
982 if (op & OPT_DEBUG) 977 if (op & OPT_DEBUG)
983 setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 978 setsockopt_SOL_SOCKET_1(sndsock, SO_DEBUG);
984 &const_int_1, sizeof(const_int_1));
985#endif 979#endif
986 if (op & OPT_BYPASS_ROUTE) 980 if (op & OPT_BYPASS_ROUTE)
987 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 981 setsockopt_SOL_SOCKET_1(sndsock, SO_DONTROUTE);
988 &const_int_1, sizeof(const_int_1));
989 982
990 outip = xzalloc(packlen); 983 outip = xzalloc(packlen);
991 984
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 811a1a1ee..915f65935 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -29,6 +29,20 @@
29#include <linux/filter.h> 29#include <linux/filter.h>
30#include <linux/if_packet.h> 30#include <linux/if_packet.h>
31 31
32#ifndef PACKET_AUXDATA
33# define PACKET_AUXDATA 8
34struct tpacket_auxdata {
35 uint32_t tp_status;
36 uint32_t tp_len;
37 uint32_t tp_snaplen;
38 uint16_t tp_mac;
39 uint16_t tp_net;
40 uint16_t tp_vlan_tci;
41 uint16_t tp_padding;
42};
43#endif
44
45
32/* "struct client_config_t client_config" is in bb_common_bufsiz1 */ 46/* "struct client_config_t client_config" is in bb_common_bufsiz1 */
33 47
34 48
@@ -1043,9 +1057,7 @@ static int udhcp_raw_socket(int ifindex)
1043 } 1057 }
1044#endif 1058#endif
1045 1059
1046 if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, 1060 if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) {
1047 &const_int_1, sizeof(int)) < 0
1048 ) {
1049 if (errno != ENOPROTOOPT) 1061 if (errno != ENOPROTOOPT)
1050 log1("Can't set PACKET_AUXDATA on raw socket"); 1062 log1("Can't set PACKET_AUXDATA on raw socket");
1051 } 1063 }
diff --git a/networking/wget.c b/networking/wget.c
index e09bd2368..0082ced39 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -9,6 +9,94 @@
9 * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. 9 * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2.
10 */ 10 */
11 11
12//config:config WGET
13//config: bool "wget"
14//config: default y
15//config: help
16//config: wget is a utility for non-interactive download of files from HTTP
17//config: and FTP servers.
18//config:
19//config:config FEATURE_WGET_STATUSBAR
20//config: bool "Enable a nifty process meter (+2k)"
21//config: default y
22//config: depends on WGET
23//config: help
24//config: Enable the transfer progress bar for wget transfers.
25//config:
26//config:config FEATURE_WGET_AUTHENTICATION
27//config: bool "Enable HTTP authentication"
28//config: default y
29//config: depends on WGET
30//config: help
31//config: Support authenticated HTTP transfers.
32//config:
33//config:config FEATURE_WGET_LONG_OPTIONS
34//config: bool "Enable long options"
35//config: default y
36//config: depends on WGET && LONG_OPTS
37//config: help
38//config: Support long options for the wget applet.
39//config:
40//config:config FEATURE_WGET_TIMEOUT
41//config: bool "Enable timeout option -T SEC"
42//config: default y
43//config: depends on WGET
44//config: help
45//config: Supports network read and connect timeouts for wget,
46//config: so that wget will give up and timeout, through the -T
47//config: command line option.
48//config:
49//config: Currently only connect and network data read timeout are
50//config: supported (i.e., timeout is not applied to the DNS query). When
51//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
52//config: will work in addition to -T.
53//config:
54//config:config FEATURE_WGET_OPENSSL
55//config: bool "Try to connect to HTTPS using openssl"
56//config: default y
57//config: depends on WGET
58//config: help
59//config: Choose how wget establishes SSL connection for https:// URLs.
60//config:
61//config: Busybox itself contains no SSL code. wget will spawn
62//config: a helper program to talk over HTTPS.
63//config:
64//config: OpenSSL has a simple SSL client for debug purposes.
65//config: If you select "openssl" helper, wget will effectively call
66//config: "openssl s_client -quiet -connect IP:443 2>/dev/null"
67//config: and pipe its data through it.
68//config: Note inconvenient API: host resolution is done twice,
69//config: and there is no guarantee openssl's idea of IPv6 address
70//config: format is the same as ours.
71//config: Another problem is that s_client prints debug information
72//config: to stderr, and it needs to be suppressed. This means
73//config: all error messages get suppressed too.
74//config: openssl is also a big binary, often dynamically linked
75//config: against ~15 libraries.
76//config:
77//config:config FEATURE_WGET_SSL_HELPER
78//config: bool "Try to connect to HTTPS using ssl_helper"
79//config: default y
80//config: depends on WGET
81//config: help
82//config: Choose how wget establishes SSL connection for https:// URLs.
83//config:
84//config: Busybox itself contains no SSL code. wget will spawn
85//config: a helper program to talk over HTTPS.
86//config:
87//config: ssl_helper is a tool which can be built statically
88//config: from busybox sources against a small embedded SSL library.
89//config: Please see networking/ssl_helper/README.
90//config: It does not require double host resolution and emits
91//config: error messages to stderr.
92//config:
93//config: Precompiled static binary may be available at
94//config: http://busybox.net/downloads/binaries/
95
96//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
97
98//kbuild:lib-$(CONFIG_WGET) += wget.o
99
12//usage:#define wget_trivial_usage 100//usage:#define wget_trivial_usage
13//usage: IF_FEATURE_WGET_LONG_OPTIONS( 101//usage: IF_FEATURE_WGET_LONG_OPTIONS(
14//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" 102//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n"
@@ -59,7 +147,9 @@ struct host_info {
59}; 147};
60static const char P_FTP[] = "ftp"; 148static const char P_FTP[] = "ftp";
61static const char P_HTTP[] = "http"; 149static const char P_HTTP[] = "http";
150#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
62static const char P_HTTPS[] = "https"; 151static const char P_HTTPS[] = "https";
152#endif
63 153
64#if ENABLE_FEATURE_WGET_LONG_OPTIONS 154#if ENABLE_FEATURE_WGET_LONG_OPTIONS
65/* User-specified headers prevent using our corresponding built-in headers. */ 155/* User-specified headers prevent using our corresponding built-in headers. */
@@ -328,7 +418,7 @@ static void parse_url(const char *src_url, struct host_info *h)
328 if (strcmp(url, P_FTP) == 0) { 418 if (strcmp(url, P_FTP) == 0) {
329 h->port = bb_lookup_port(P_FTP, "tcp", 21); 419 h->port = bb_lookup_port(P_FTP, "tcp", 21);
330 } else 420 } else
331#if !ENABLE_PLATFORM_MINGW32 421#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
332 if (strcmp(url, P_HTTPS) == 0) { 422 if (strcmp(url, P_HTTPS) == 0) {
333 h->port = bb_lookup_port(P_HTTPS, "tcp", 443); 423 h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
334 h->protocol = P_HTTPS; 424 h->protocol = P_HTTPS;
@@ -528,12 +618,13 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
528 return sfp; 618 return sfp;
529} 619}
530 620
531#if !ENABLE_PLATFORM_MINGW32 621#if ENABLE_FEATURE_WGET_OPENSSL
532static int spawn_https_helper(const char *host, unsigned port) 622static int spawn_https_helper_openssl(const char *host, unsigned port)
533{ 623{
534 char *allocated = NULL; 624 char *allocated = NULL;
535 int sp[2]; 625 int sp[2];
536 int pid; 626 int pid;
627 IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;)
537 628
538 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 629 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
539 /* Kernel can have AF_UNIX support disabled */ 630 /* Kernel can have AF_UNIX support disabled */
@@ -542,7 +633,8 @@ static int spawn_https_helper(const char *host, unsigned port)
542 if (!strchr(host, ':')) 633 if (!strchr(host, ':'))
543 host = allocated = xasprintf("%s:%u", host, port); 634 host = allocated = xasprintf("%s:%u", host, port);
544 635
545 pid = BB_MMU ? xfork() : xvfork(); 636 fflush_all();
637 pid = xvfork();
546 if (pid == 0) { 638 if (pid == 0) {
547 /* Child */ 639 /* Child */
548 char *argv[6]; 640 char *argv[6];
@@ -551,10 +643,6 @@ static int spawn_https_helper(const char *host, unsigned port)
551 xmove_fd(sp[1], 0); 643 xmove_fd(sp[1], 0);
552 xdup2(0, 1); 644 xdup2(0, 1);
553 /* 645 /*
554 * TODO: develop a tiny ssl/tls helper (using matrixssl?),
555 * try to exec it here before falling back to big fat openssl.
556 */
557 /*
558 * openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null 646 * openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null
559 * It prints some debug stuff on stderr, don't know how to suppress it. 647 * It prints some debug stuff on stderr, don't know how to suppress it.
560 * Work around by dev-nulling stderr. We lose all error messages :( 648 * Work around by dev-nulling stderr. We lose all error messages :(
@@ -569,22 +657,31 @@ static int spawn_https_helper(const char *host, unsigned port)
569 argv[5] = NULL; 657 argv[5] = NULL;
570 BB_EXECVP(argv[0], argv); 658 BB_EXECVP(argv[0], argv);
571 xmove_fd(3, 2); 659 xmove_fd(3, 2);
660# if ENABLE_FEATURE_WGET_SSL_HELPER
661 child_failed = 1;
662 xfunc_die();
663# else
572 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 664 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
665# endif
573 /* notreached */ 666 /* notreached */
574 } 667 }
575 668
576 /* Parent */ 669 /* Parent */
577 free(allocated); 670 free(allocated);
578 close(sp[1]); 671 close(sp[1]);
672# if ENABLE_FEATURE_WGET_SSL_HELPER
673 if (child_failed) {
674 close(sp[0]);
675 return -1;
676 }
677# endif
579 return sp[0]; 678 return sp[0];
580} 679}
581#endif 680#endif
582 681
583/* See networking/ssl_helper/README */ 682/* See networking/ssl_helper/README how to build one */
584#define SSL_HELPER 0 683#if ENABLE_FEATURE_WGET_SSL_HELPER
585 684static void spawn_https_helper_small(int network_fd)
586#if SSL_HELPER
587static void spawn_https_helper1(int network_fd)
588{ 685{
589 int sp[2]; 686 int sp[2];
590 int pid; 687 int pid;
@@ -861,21 +958,37 @@ static void download_one_url(const char *url)
861 int status; 958 int status;
862 959
863 /* Open socket to http(s) server */ 960 /* Open socket to http(s) server */
864#if !ENABLE_PLATFORM_MINGW32 961#if ENABLE_FEATURE_WGET_OPENSSL
962 /* openssl (and maybe ssl_helper) support is configured */
865 if (target.protocol == P_HTTPS) { 963 if (target.protocol == P_HTTPS) {
866/* openssl-based helper 964 /* openssl-based helper
867 * Inconvenient API since we can't give it an open fd 965 * Inconvenient API since we can't give it an open fd
868 */ 966 */
869 int fd = spawn_https_helper(server.host, server.port); 967 int fd = spawn_https_helper_openssl(server.host, server.port);
968# if ENABLE_FEATURE_WGET_SSL_HELPER
969 if (fd < 0) { /* no openssl? try ssl_helper */
970 sfp = open_socket(lsa);
971 spawn_https_helper_small(fileno(sfp));
972 goto socket_opened;
973 }
974# else
975 /* We don't check for exec("openssl") failure in this case */
976# endif
870 sfp = fdopen(fd, "r+"); 977 sfp = fdopen(fd, "r+");
871 if (!sfp) 978 if (!sfp)
872 bb_perror_msg_and_die(bb_msg_memory_exhausted); 979 bb_perror_msg_and_die(bb_msg_memory_exhausted);
873 } else 980 goto socket_opened;
874#endif 981 }
875 sfp = open_socket(lsa); 982 sfp = open_socket(lsa);
876#if SSL_HELPER 983 socket_opened:
984#elif ENABLE_FEATURE_WGET_SSL_HELPER
985 /* Only ssl_helper support is configured */
986 sfp = open_socket(lsa);
877 if (target.protocol == P_HTTPS) 987 if (target.protocol == P_HTTPS)
878 spawn_https_helper1(fileno(sfp)); 988 spawn_https_helper_small(fileno(sfp));
989#else
990 /* ssl (https) support is not configured */
991 sfp = open_socket(lsa);
879#endif 992#endif
880 /* Send HTTP request */ 993 /* Send HTTP request */
881 if (use_proxy) { 994 if (use_proxy) {
diff --git a/networking/zcip.c b/networking/zcip.c
index 69644b230..d15c67d55 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -56,9 +56,6 @@ struct arp_packet {
56} PACKED; 56} PACKED;
57 57
58enum { 58enum {
59 /* 169.254.0.0 */
60 LINKLOCAL_ADDR = 0xa9fe0000,
61
62 /* 0-1 seconds before sending 1st probe */ 59 /* 0-1 seconds before sending 1st probe */
63 PROBE_WAIT = 1, 60 PROBE_WAIT = 1,
64 /* 1-2 seconds between probes */ 61 /* 1-2 seconds between probes */
@@ -70,7 +67,7 @@ enum {
70 /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */ 67 /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */
71 CONFLICT_MULTIPLIER = 2, 68 CONFLICT_MULTIPLIER = 2,
72 /* if we monitor and see a conflict, how long is defend state? */ 69 /* if we monitor and see a conflict, how long is defend state? */
73 DEFEND_INTERVAL = 10 70 DEFEND_INTERVAL = 10,
74}; 71};
75 72
76/* States during the configuration process. */ 73/* States during the configuration process. */
@@ -90,7 +87,7 @@ enum {
90 87
91struct globals { 88struct globals {
92 struct sockaddr iface_sockaddr; 89 struct sockaddr iface_sockaddr;
93 struct ether_addr eth_addr; 90 struct ether_addr our_ethaddr;
94 uint32_t localnet_ip; 91 uint32_t localnet_ip;
95} FIX_ALIASING; 92} FIX_ALIASING;
96#define G (*(struct globals*)&bb_common_bufsiz1) 93#define G (*(struct globals*)&bb_common_bufsiz1)
@@ -121,14 +118,14 @@ static const char *nip_to_a(uint32_t nip)
121/** 118/**
122 * Broadcast an ARP packet. 119 * Broadcast an ARP packet.
123 */ 120 */
124static void arp( 121static void send_arp_request(
125 /* int op, - always ARPOP_REQUEST */ 122 /* int op, - always ARPOP_REQUEST */
126 /* const struct ether_addr *source_eth, - always &G.eth_addr */ 123 /* const struct ether_addr *source_eth, - always &G.our_ethaddr */
127 uint32_t source_nip, 124 uint32_t source_nip,
128 const struct ether_addr *target_eth, uint32_t target_nip) 125 const struct ether_addr *target_eth, uint32_t target_nip)
129{ 126{
130 enum { op = ARPOP_REQUEST }; 127 enum { op = ARPOP_REQUEST };
131#define source_eth (&G.eth_addr) 128#define source_eth (&G.our_ethaddr)
132 129
133 struct arp_packet p; 130 struct arp_packet p;
134 memset(&p, 0, sizeof(p)); 131 memset(&p, 0, sizeof(p));
@@ -196,7 +193,7 @@ static int run(char *argv[3], const char *param, uint32_t nip)
196 */ 193 */
197static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs) 194static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
198{ 195{
199 return rand() % (secs * 1000); 196 return (unsigned)rand() % (secs * 1000);
200} 197}
201 198
202/** 199/**
@@ -205,37 +202,34 @@ static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
205int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 202int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
206int zcip_main(int argc UNUSED_PARAM, char **argv) 203int zcip_main(int argc UNUSED_PARAM, char **argv)
207{ 204{
208 int state;
209 char *r_opt; 205 char *r_opt;
210 const char *l_opt = "169.254.0.0"; 206 const char *l_opt = "169.254.0.0";
207 int state;
208 int nsent;
211 unsigned opts; 209 unsigned opts;
212 210
213 // ugly trick, but I want these zeroed in one go 211 // Ugly trick, but I want these zeroed in one go
214 struct { 212 struct {
215 const struct ether_addr null_addr; 213 const struct ether_addr null_ethaddr;
216 struct ifreq ifr; 214 struct ifreq ifr;
217 uint32_t chosen_nip; 215 uint32_t chosen_nip;
218 int timeout_ms; /* must be signed */ 216 int conflicts;
219 unsigned conflicts; 217 int timeout_ms; // must be signed
220 unsigned nprobes;
221 unsigned nclaims;
222 int verbose; 218 int verbose;
223 } L; 219 } L;
224#define null_addr (L.null_addr ) 220#define null_ethaddr (L.null_ethaddr)
225#define chosen_nip (L.chosen_nip) 221#define ifr (L.ifr )
226#define ifr (L.ifr ) 222#define chosen_nip (L.chosen_nip )
227#define timeout_ms (L.timeout_ms) 223#define conflicts (L.conflicts )
228#define conflicts (L.conflicts ) 224#define timeout_ms (L.timeout_ms )
229#define nprobes (L.nprobes ) 225#define verbose (L.verbose )
230#define nclaims (L.nclaims )
231#define verbose (L.verbose )
232 226
233 memset(&L, 0, sizeof(L)); 227 memset(&L, 0, sizeof(L));
234 INIT_G(); 228 INIT_G();
235 229
236#define FOREGROUND (opts & 1) 230#define FOREGROUND (opts & 1)
237#define QUIT (opts & 2) 231#define QUIT (opts & 2)
238 // parse commandline: prog [options] ifname script 232 // Parse commandline: prog [options] ifname script
239 // exactly 2 args; -v accumulates and implies -f 233 // exactly 2 args; -v accumulates and implies -f
240 opt_complementary = "=2:vv:vf"; 234 opt_complementary = "=2:vv:vf";
241 opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose); 235 opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose);
@@ -244,7 +238,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
244 if (!FOREGROUND) 238 if (!FOREGROUND)
245 bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv); 239 bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv);
246#endif 240#endif
247 // open an ARP socket 241 // Open an ARP socket
248 // (need to do it before openlog to prevent openlog from taking 242 // (need to do it before openlog to prevent openlog from taking
249 // fd 3 (sock_fd==3)) 243 // fd 3 (sock_fd==3))
250 xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd); 244 xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd);
@@ -284,26 +278,26 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
284 278
285 xsetenv("interface", argv_intf); 279 xsetenv("interface", argv_intf);
286 280
287 // initialize the interface (modprobe, ifup, etc) 281 // Initialize the interface (modprobe, ifup, etc)
288 if (run(argv, "init", 0)) 282 if (run(argv, "init", 0))
289 return EXIT_FAILURE; 283 return EXIT_FAILURE;
290 284
291 // initialize G.iface_sockaddr 285 // Initialize G.iface_sockaddr
292 // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; } 286 // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; }
293 //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr)); 287 //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr));
294 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! 288 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
295 safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data)); 289 safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data));
296 290
297 // bind to the interface's ARP socket 291 // Bind to the interface's ARP socket
298 xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr)); 292 xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr));
299 293
300 // get the interface's ethernet address 294 // Get the interface's ethernet address
301 //memset(&ifr, 0, sizeof(ifr)); 295 //memset(&ifr, 0, sizeof(ifr));
302 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf); 296 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
303 xioctl(sock_fd, SIOCGIFHWADDR, &ifr); 297 xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
304 memcpy(&G.eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 298 memcpy(&G.our_ethaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
305 299
306 // start with some stable ip address, either a function of 300 // Start with some stable ip address, either a function of
307 // the hardware address or else the last address we used. 301 // the hardware address or else the last address we used.
308 // we are taking low-order four bytes, as top-order ones 302 // we are taking low-order four bytes, as top-order ones
309 // aren't random enough. 303 // aren't random enough.
@@ -311,17 +305,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
311 // depending on when we detect conflicts. 305 // depending on when we detect conflicts.
312 { 306 {
313 uint32_t t; 307 uint32_t t;
314 move_from_unaligned32(t, ((char *)&G.eth_addr + 2)); 308 move_from_unaligned32(t, ((char *)&G.our_ethaddr + 2));
315 srand(t); 309 srand(t);
316 } 310 }
317 if (chosen_nip == 0)
318 chosen_nip = pick_nip();
319
320 // FIXME cases to handle: 311 // FIXME cases to handle:
321 // - zcip already running! 312 // - zcip already running!
322 // - link already has local address... just defend/update 313 // - link already has local address... just defend/update
323 314
324 // daemonize now; don't delay system startup 315 // Daemonize now; don't delay system startup
325 if (!FOREGROUND) { 316 if (!FOREGROUND) {
326#if BB_MMU 317#if BB_MMU
327 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); 318 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
@@ -329,14 +320,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
329 bb_info_msg("start, interface %s", argv_intf); 320 bb_info_msg("start, interface %s", argv_intf);
330 } 321 }
331 322
332 // run the dynamic address negotiation protocol, 323 // Run the dynamic address negotiation protocol,
333 // restarting after address conflicts: 324 // restarting after address conflicts:
334 // - start with some address we want to try 325 // - start with some address we want to try
335 // - short random delay 326 // - short random delay
336 // - arp probes to see if another host uses it 327 // - arp probes to see if another host uses it
337 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 tell 0.0.0.0 328 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 tell 0.0.0.0
338 // - arp announcements that we're claiming it 329 // - arp announcements that we're claiming it
339 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171 330 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171
340 // - use it 331 // - use it
341 // - defend it, within limits 332 // - defend it, within limits
342 // exit if: 333 // exit if:
@@ -344,215 +335,191 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
344 // run "<script> config", then exit with exitcode 0 335 // run "<script> config", then exit with exitcode 0
345 // - poll error (when does this happen?) 336 // - poll error (when does this happen?)
346 // - read error (when does this happen?) 337 // - read error (when does this happen?)
347 // - sendto error (in arp()) (when does this happen?) 338 // - sendto error (in send_arp_request()) (when does this happen?)
348 // - revents & POLLERR (link down). run "<script> deconfig" first 339 // - revents & POLLERR (link down). run "<script> deconfig" first
340 if (chosen_nip == 0) {
341 new_nip_and_PROBE:
342 chosen_nip = pick_nip();
343 }
344 nsent = 0;
349 state = PROBE; 345 state = PROBE;
350 while (1) { 346 while (1) {
351 struct pollfd fds[1]; 347 struct pollfd fds[1];
352 unsigned deadline_us; 348 unsigned deadline_us;
353 struct arp_packet p; 349 struct arp_packet p;
354 int source_ip_conflict; 350 int ip_conflict;
355 int target_ip_conflict; 351 int n;
356 352
357 fds[0].fd = sock_fd; 353 fds[0].fd = sock_fd;
358 fds[0].events = POLLIN; 354 fds[0].events = POLLIN;
359 fds[0].revents = 0; 355 fds[0].revents = 0;
360 356
361 // poll, being ready to adjust current timeout 357 // Poll, being ready to adjust current timeout
362 if (!timeout_ms) { 358 if (!timeout_ms) {
363 timeout_ms = random_delay_ms(PROBE_WAIT); 359 timeout_ms = random_delay_ms(PROBE_WAIT);
364 // FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to 360 // FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to
365 // make the kernel filter out all packets except 361 // make the kernel filter out all packets except
366 // ones we'd care about. 362 // ones we'd care about.
367 } 363 }
368 // set deadline_us to the point in time when we timeout 364 // Set deadline_us to the point in time when we timeout
369 deadline_us = MONOTONIC_US() + timeout_ms * 1000; 365 deadline_us = MONOTONIC_US() + timeout_ms * 1000;
370 366
371 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", 367 VDBG("...wait %d %s nsent=%u\n",
372 timeout_ms, argv_intf, nprobes, nclaims); 368 timeout_ms, argv_intf, nsent);
373
374 switch (safe_poll(fds, 1, timeout_ms)) {
375 369
376 default: 370 n = safe_poll(fds, 1, timeout_ms);
371 if (n < 0) {
377 //bb_perror_msg("poll"); - done in safe_poll 372 //bb_perror_msg("poll"); - done in safe_poll
378 return EXIT_FAILURE; 373 return EXIT_FAILURE;
379 374 }
380 // timeout 375 if (n == 0) { // timed out?
381 case 0: 376 VDBG("state:%d\n", state);
382 VDBG("state = %d\n", state);
383 switch (state) { 377 switch (state) {
384 case PROBE: 378 case PROBE:
385 // timeouts in the PROBE state mean no conflicting ARP packets 379 // No conflicting ARP packets were seen:
386 // have been received, so we can progress through the states 380 // we can progress through the states
387 if (nprobes < PROBE_NUM) { 381 if (nsent < PROBE_NUM) {
388 nprobes++; 382 nsent++;
389 VDBG("probe/%u %s@%s\n", 383 VDBG("probe/%u %s@%s\n",
390 nprobes, argv_intf, nip_to_a(chosen_nip)); 384 nsent, argv_intf, nip_to_a(chosen_nip));
391 timeout_ms = PROBE_MIN * 1000; 385 timeout_ms = PROBE_MIN * 1000;
392 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); 386 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
393 arp(/* ARPOP_REQUEST, */ 387 send_arp_request(0, &null_ethaddr, chosen_nip);
394 /* &G.eth_addr, */ 0, 388 continue;
395 &null_addr, chosen_nip);
396 break;
397 } 389 }
398 // Switch to announce state. 390 // Switch to announce state
399 nclaims = 0; 391 nsent = 0;
400 state = ANNOUNCE; 392 state = ANNOUNCE;
401 goto send_announce; 393 goto send_announce;
402 case ANNOUNCE: 394 case ANNOUNCE:
403 // timeouts in the ANNOUNCE state mean no conflicting ARP packets 395 // No conflicting ARP packets were seen:
404 // have been received, so we can progress through the states 396 // we can progress through the states
405 if (nclaims < ANNOUNCE_NUM) { 397 if (nsent < ANNOUNCE_NUM) {
406 send_announce: 398 send_announce:
407 nclaims++; 399 nsent++;
408 VDBG("announce/%u %s@%s\n", 400 VDBG("announce/%u %s@%s\n",
409 nclaims, argv_intf, nip_to_a(chosen_nip)); 401 nsent, argv_intf, nip_to_a(chosen_nip));
410 timeout_ms = ANNOUNCE_INTERVAL * 1000; 402 timeout_ms = ANNOUNCE_INTERVAL * 1000;
411 arp(/* ARPOP_REQUEST, */ 403 send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
412 /* &G.eth_addr, */ chosen_nip, 404 continue;
413 &G.eth_addr, chosen_nip);
414 break;
415 } 405 }
416 // Switch to monitor state. 406 // Switch to monitor state
417 // FIXME update filters 407 // FIXME update filters
418 run(argv, "config", chosen_nip); 408 run(argv, "config", chosen_nip);
419 // NOTE: all other exit paths should deconfig... 409 // NOTE: all other exit paths should deconfig...
420 if (QUIT) 410 if (QUIT)
421 return EXIT_SUCCESS; 411 return EXIT_SUCCESS;
422 conflicts = 0; 412 // fall through: switch to MONITOR
423 timeout_ms = -1; // Never timeout in the monitor state. 413 default:
424 state = MONITOR; 414 // case DEFEND:
425 break; 415 // case MONITOR: (shouldn't happen, MONITOR timeout is infinite)
426 case DEFEND: 416 // Defend period ended with no ARP replies - we won
427 // Defend period ended with no ARP replies - we won. 417 timeout_ms = -1; // never timeout in monitor state
428 conflicts = 0;
429 timeout_ms = -1;
430 state = MONITOR; 418 state = MONITOR;
431 break;
432 } // switch (state)
433 break; // case 0 (timeout)
434
435 // packets arriving, or link went down
436 case 1:
437 // We need to adjust the timeout in case we didn't receive
438 // a conflicting packet.
439 if (timeout_ms > 0) {
440 unsigned diff = deadline_us - MONOTONIC_US();
441 if ((int)(diff) < 0) {
442 // Current time is greater than the expected timeout time.
443 diff = 0;
444 }
445 VDBG("adjusting timeout\n");
446 timeout_ms = (diff / 1000) | 1; /* never 0 */
447 }
448
449 if ((fds[0].revents & POLLIN) == 0) {
450 if (fds[0].revents & POLLERR) {
451 // FIXME: links routinely go down;
452 // this shouldn't necessarily exit.
453 bb_error_msg("iface %s is down", argv_intf);
454 if (state >= MONITOR) {
455 /* only if we are in MONITOR or DEFEND */
456 run(argv, "deconfig", chosen_nip);
457 }
458 return EXIT_FAILURE;
459 }
460 continue; 419 continue;
461 } 420 }
421 }
462 422
463 // read ARP packet 423 // Packet arrived, or link went down.
464 if (safe_read(sock_fd, &p, sizeof(p)) < 0) { 424 // We need to adjust the timeout in case we didn't receive
465 bb_perror_msg_and_die(bb_msg_read_error); 425 // a conflicting packet.
426 if (timeout_ms > 0) {
427 unsigned diff = deadline_us - MONOTONIC_US();
428 if ((int)(diff) < 0) {
429 // Current time is greater than the expected timeout time.
430 diff = 0;
466 } 431 }
432 VDBG("adjusting timeout\n");
433 timeout_ms = (diff / 1000) | 1; // never 0
434 }
467 435
468 if (p.eth.ether_type != htons(ETHERTYPE_ARP)) 436 if ((fds[0].revents & POLLIN) == 0) {
469 continue; 437 if (fds[0].revents & POLLERR) {
470 if (p.arp.arp_op != htons(ARPOP_REQUEST) 438 // FIXME: links routinely go down;
471 && p.arp.arp_op != htons(ARPOP_REPLY) 439 // this shouldn't necessarily exit.
472 ) { 440 bb_error_msg("iface %s is down", argv_intf);
473 continue; 441 if (state >= MONITOR) {
442 // Only if we are in MONITOR or DEFEND
443 run(argv, "deconfig", chosen_nip);
444 }
445 return EXIT_FAILURE;
474 } 446 }
447 continue;
448 }
449
450 // Read ARP packet
451 if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
452 bb_perror_msg_and_die(bb_msg_read_error);
453 }
454
455 if (p.eth.ether_type != htons(ETHERTYPE_ARP))
456 continue;
457 if (p.arp.arp_op != htons(ARPOP_REQUEST)
458 && p.arp.arp_op != htons(ARPOP_REPLY)
459 ) {
460 continue;
461 }
475#ifdef DEBUG 462#ifdef DEBUG
476 { 463 {
477 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; 464 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
478 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha; 465 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
479 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; 466 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
480 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; 467 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
481 VDBG("%s recv arp type=%d, op=%d,\n", 468 VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa));
482 argv_intf, ntohs(p.eth.ether_type), 469 VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa));
483 ntohs(p.arp.arp_op)); 470 }
484 VDBG("\tsource=%s %s\n",
485 ether_ntoa(sha),
486 inet_ntoa(*spa));
487 VDBG("\ttarget=%s %s\n",
488 ether_ntoa(tha),
489 inet_ntoa(*tpa));
490 }
491#endif 471#endif
492 source_ip_conflict = 0; 472 ip_conflict = 0;
493 target_ip_conflict = 0; 473 if (memcmp(&p.arp.arp_sha, &G.our_ethaddr, ETH_ALEN) != 0) {
494 474 if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) {
495 if (memcmp(&p.arp.arp_sha, &G.eth_addr, ETH_ALEN) != 0) { 475 // A probe or reply with source_ip == chosen ip
496 if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) { 476 ip_conflict = 1;
497 /* A probe or reply with source_ip == chosen ip */
498 source_ip_conflict = 1;
499 }
500 if (p.arp.arp_op == htons(ARPOP_REQUEST)
501 && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
502 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
503 ) {
504 /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
505 * another host trying to claim this ip!
506 */
507 target_ip_conflict = 1;
508 }
509 } 477 }
478 if (p.arp.arp_op == htons(ARPOP_REQUEST)
479 && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
480 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
481 ) {
482 // A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
483 // another host trying to claim this ip!
484 ip_conflict |= 2;
485 }
486 }
487 VDBG("state:%d ip_conflict:%d\n", state, ip_conflict);
488 if (!ip_conflict)
489 continue;
490
491 // Either src or target IP conflict exists
492 if (state <= ANNOUNCE) {
493 // PROBE or ANNOUNCE
494 conflicts++;
495 timeout_ms = PROBE_MIN * 1000
496 + CONFLICT_MULTIPLIER * random_delay_ms(conflicts);
497 goto new_nip_and_PROBE;
498 }
510 499
511 VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", 500 // MONITOR or DEFEND: only src IP conflict is a problem
512 state, source_ip_conflict, target_ip_conflict); 501 if (ip_conflict & 1) {
513 switch (state) { 502 if (state == MONITOR) {
514 case PROBE: 503 // Src IP conflict, defend with a single ARP probe
515 case ANNOUNCE: 504 VDBG("monitor conflict - defending\n");
516 // When probing or announcing, check for source IP conflicts 505 timeout_ms = DEFEND_INTERVAL * 1000;
517 // and other hosts doing ARP probes (target IP conflicts). 506 state = DEFEND;
518 if (source_ip_conflict || target_ip_conflict) { 507 send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
519 conflicts++; 508 continue;
520 timeout_ms = PROBE_MIN * 1000 509 }
521 + CONFLICT_MULTIPLIER * random_delay_ms(conflicts); 510 // state == DEFEND
522 chosen_nip = pick_nip(); 511 // Another src IP conflict, start over
523 nprobes = 0; 512 VDBG("defend conflict - starting over\n");
524 nclaims = 0; 513 run(argv, "deconfig", chosen_nip);
525 state = PROBE; 514 conflicts = 0;
526 } 515 timeout_ms = 0;
527 break; 516 goto new_nip_and_PROBE;
528 case MONITOR: 517 }
529 // If a conflict, we try to defend with a single ARP probe. 518 // Note: if we only have a target IP conflict here (ip_conflict & 2),
530 if (source_ip_conflict) { 519 // IOW: if we just saw this sort of ARP packet:
531 VDBG("monitor conflict -- defending\n"); 520 // aa:bb:cc:dd:ee:ff > xx:xx:xx:xx:xx:xx arp who-has <chosen_nip> tell 0.0.0.0
532 timeout_ms = DEFEND_INTERVAL * 1000; 521 // we expect _kernel_ to respond to that, because <chosen_nip>
533 state = DEFEND; 522 // is (expected to be) configured on this iface.
534 arp(/* ARPOP_REQUEST, */
535 /* &G.eth_addr, */ chosen_nip,
536 &G.eth_addr, chosen_nip);
537 }
538 break;
539 case DEFEND:
540 // Well, we tried. Start over (on conflict).
541 if (source_ip_conflict) {
542 VDBG("defend conflict -- starting over\n");
543 run(argv, "deconfig", chosen_nip);
544
545 // restart the whole protocol
546 timeout_ms = 0;
547 chosen_nip = pick_nip();
548 nprobes = 0;
549 nclaims = 0;
550 state = PROBE;
551 }
552 break;
553 } // switch state
554 break; // case 1 (packets arriving)
555 } // switch poll
556 } // while (1) 523 } // while (1)
557#undef argv_intf 524#undef argv_intf
558} 525}