aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-10-19 17:01:55 +0100
committerRon Yorston <rmy@pobox.com>2016-10-19 17:01:55 +0100
commit075814c60a316cfd088c88f26f75ab21b5850b98 (patch)
treef6e33ac693630827deb309faa5fa4931588db57d /networking
parent977d65c1bbc57f5cdd0c8bfd67c8b5bb1cd390dd (diff)
parentf37e1155aabde6bd95d267a8aec347cedccb8bc3 (diff)
downloadbusybox-w32-075814c60a316cfd088c88f26f75ab21b5850b98.tar.gz
busybox-w32-075814c60a316cfd088c88f26f75ab21b5850b98.tar.bz2
busybox-w32-075814c60a316cfd088c88f26f75ab21b5850b98.zip
Merge branch busybox (up to "ash: comment out free(p) just before...")
Diffstat (limited to 'networking')
-rw-r--r--networking/Config.src12
-rw-r--r--networking/ifplugd.c8
-rw-r--r--networking/ifupdown.c14
-rw-r--r--networking/libiproute/iproute.c3
-rw-r--r--networking/libiproute/iprule.c8
-rw-r--r--networking/libiproute/libnetlink.c66
-rw-r--r--networking/ntpd.c7
-rw-r--r--networking/route.c4
-rwxr-xr-xnetworking/ssl_helper-wolfssl/00cfg-wolfssl-3.9.839
-rw-r--r--networking/ssl_helper-wolfssl/README7
-rwxr-xr-xnetworking/ssl_helper-wolfssl/ssl_helper.sh2
-rw-r--r--networking/traceroute.c124
-rw-r--r--networking/udhcp/Kbuild.src2
-rw-r--r--networking/udhcp/arpping.c1
-rw-r--r--networking/udhcp/d6_dhcpc.c9
-rw-r--r--networking/udhcp/dhcpc.c13
-rw-r--r--networking/udhcp/dhcpd.c502
-rw-r--r--networking/udhcp/dhcpd.h33
-rw-r--r--networking/udhcp/files.c234
-rw-r--r--networking/udhcp/leases.c211
-rw-r--r--networking/udhcp/static_leases.c77
-rw-r--r--networking/wget.c130
22 files changed, 766 insertions, 740 deletions
diff --git a/networking/Config.src b/networking/Config.src
index 27c604a31..eb0536a7c 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -912,17 +912,9 @@ config FEATURE_TRACEROUTE_VERBOSE
912 Add some verbosity to traceroute. This includes among other things 912 Add some verbosity to traceroute. This includes among other things
913 hostnames and ICMP response types. 913 hostnames and ICMP response types.
914 914
915config FEATURE_TRACEROUTE_SOURCE_ROUTE
916 bool "Enable loose source route"
917 default n
918 depends on TRACEROUTE
919 help
920 Add option to specify a loose source route gateway
921 (8 maximum).
922
923config FEATURE_TRACEROUTE_USE_ICMP 915config FEATURE_TRACEROUTE_USE_ICMP
924 bool "Use ICMP instead of UDP" 916 bool "Enable -I option (use ICMP instead of UDP)"
925 default n 917 default y
926 depends on TRACEROUTE 918 depends on TRACEROUTE
927 help 919 help
928 Add option -I to use ICMP ECHO instead of UDP datagrams. 920 Add option -I to use ICMP ECHO instead of UDP datagrams.
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 28c49e218..029cba147 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -358,8 +358,12 @@ static void up_iface(void)
358 ifrequest.ifr_flags |= IFF_UP; 358 ifrequest.ifr_flags |= IFF_UP;
359 /* Let user know we mess up with interface */ 359 /* Let user know we mess up with interface */
360 bb_error_msg("upping interface"); 360 bb_error_msg("upping interface");
361 if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) 361 if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) {
362 xfunc_die(); 362 if (errno != ENODEV)
363 xfunc_die();
364 G.iface_exists = 0;
365 return;
366 }
363 } 367 }
364 368
365#if 0 /* why do we mess with IP addr? It's not our business */ 369#if 0 /* why do we mess with IP addr? It's not our business */
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 25b04c9d7..b0bc0d70f 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -21,7 +21,7 @@
21//usage: "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." 21//usage: "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..."
22//usage:#define ifup_full_usage "\n\n" 22//usage:#define ifup_full_usage "\n\n"
23//usage: " -a De/configure all interfaces automatically" 23//usage: " -a De/configure all interfaces automatically"
24//usage: "\n -i FILE Use FILE for interface definitions" 24//usage: "\n -i FILE Use FILE instead of /etc/network/interfaces"
25//usage: "\n -n Print out what would happen, but don't do it" 25//usage: "\n -n Print out what would happen, but don't do it"
26//usage: IF_FEATURE_IFUPDOWN_MAPPING( 26//usage: IF_FEATURE_IFUPDOWN_MAPPING(
27//usage: "\n (note: doesn't disable mappings)" 27//usage: "\n (note: doesn't disable mappings)"
@@ -492,7 +492,7 @@ static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec)
492 result = execute("ifconfig %iface%[[ hw %hwaddress%]][[ media %media%]][[ mtu %mtu%]] up", 492 result = execute("ifconfig %iface%[[ hw %hwaddress%]][[ media %media%]][[ mtu %mtu%]] up",
493 ifd, exec); 493 ifd, exec);
494 result += execute("ifconfig %iface% %address% netmask %netmask%" 494 result += execute("ifconfig %iface% %address% netmask %netmask%"
495 "[[ broadcast %broadcast%]][[ pointopoint %pointopoint%]] ", 495 "[[ broadcast %broadcast%]][[ pointopoint %pointopoint%]]",
496 ifd, exec); 496 ifd, exec);
497 result += execute("[[route add default gw %gateway%[[ metric %metric%]] %iface%]]", ifd, exec); 497 result += execute("[[route add default gw %gateway%[[ metric %metric%]] %iface%]]", ifd, exec);
498 return ((result == 3) ? 3 : 0); 498 return ((result == 3) ? 3 : 0);
@@ -503,7 +503,10 @@ static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec)
503{ 503{
504 int result; 504 int result;
505# if ENABLE_FEATURE_IFUPDOWN_IP 505# if ENABLE_FEATURE_IFUPDOWN_IP
506 result = execute("ip addr flush dev %iface%", ifd, exec); 506 /* Optional "label LBL" is necessary if interface is an alias (eth0:0),
507 * otherwise "ip addr flush dev eth0:0" flushes all addresses on eth0.
508 */
509 result = execute("ip addr flush dev %iface%[[ label %label%]]", ifd, exec);
507 result += execute("ip link set %iface% down", ifd, exec); 510 result += execute("ip link set %iface% down", ifd, exec);
508# else 511# else
509 /* result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec); */ 512 /* result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec); */
@@ -1066,6 +1069,11 @@ static int execute_all(struct interface_defn_t *ifd, const char *opt)
1066 } 1069 }
1067 } 1070 }
1068 1071
1072 /* Tested on Debian Squeeze: "standard" ifup runs this without
1073 * checking that directory exists. If it doesn't, run-parts
1074 * complains, and this message _is_ annoyingly visible.
1075 * Don't "fix" this (unless newer Debian does).
1076 */
1069 buf = xasprintf("run-parts /etc/network/if-%s.d", opt); 1077 buf = xasprintf("run-parts /etc/network/if-%s.d", opt);
1070 /* heh, we don't bother free'ing it */ 1078 /* heh, we don't bother free'ing it */
1071 return doit(buf); 1079 return doit(buf);
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index e674e9a0d..48dc6e3d9 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -362,10 +362,9 @@ IF_FEATURE_IP_RULE(ARG_table,)
362 req.r.rtm_scope = RT_SCOPE_NOWHERE; 362 req.r.rtm_scope = RT_SCOPE_NOWHERE;
363 363
364 if (cmd != RTM_DELROUTE) { 364 if (cmd != RTM_DELROUTE) {
365 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
365 if (RTPROT_BOOT != 0) 366 if (RTPROT_BOOT != 0)
366 req.r.rtm_protocol = RTPROT_BOOT; 367 req.r.rtm_protocol = RTPROT_BOOT;
367 if (RT_SCOPE_UNIVERSE != 0)
368 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
369 if (RTN_UNICAST != 0) 368 if (RTN_UNICAST != 0)
370 req.r.rtm_type = RTN_UNICAST; 369 req.r.rtm_type = RTN_UNICAST;
371 } 370 }
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c
index dba64346f..c486834b0 100644
--- a/networking/libiproute/iprule.c
+++ b/networking/libiproute/iprule.c
@@ -197,9 +197,11 @@ static int iprule_modify(int cmd, char **argv)
197 req.n.nlmsg_flags = NLM_F_REQUEST; 197 req.n.nlmsg_flags = NLM_F_REQUEST;
198 req.r.rtm_family = preferred_family; 198 req.r.rtm_family = preferred_family;
199 req.r.rtm_protocol = RTPROT_BOOT; 199 req.r.rtm_protocol = RTPROT_BOOT;
200 req.r.rtm_scope = RT_SCOPE_UNIVERSE; 200 if (RT_SCOPE_UNIVERSE != 0)
201 req.r.rtm_table = 0; 201 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
202 req.r.rtm_type = RTN_UNSPEC; 202 /*req.r.rtm_table = 0; - already is */
203 if (RTN_UNSPEC != 0)
204 req.r.rtm_type = RTN_UNSPEC;
203 205
204 if (cmd == RTM_NEWRULE) { 206 if (cmd == RTM_NEWRULE) {
205 req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; 207 req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c
index cbb5daf95..7e0ff1b6c 100644
--- a/networking/libiproute/libnetlink.c
+++ b/networking/libiproute/libnetlink.c
@@ -68,30 +68,32 @@ int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len)
68 68
69int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 69int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
70{ 70{
71 struct nlmsghdr nlh; 71 struct {
72 struct sockaddr_nl nladdr; 72 struct nlmsghdr nlh;
73 struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } }; 73 struct msghdr msg;
74 /* Use designated initializers, struct layout is non-portable */ 74 struct sockaddr_nl nladdr;
75 struct msghdr msg = { 75 } s;
76 .msg_name = (void*)&nladdr, 76 struct iovec iov[2] = { { &s.nlh, sizeof(s.nlh) }, { req, len } };
77 .msg_namelen = sizeof(nladdr), 77
78 .msg_iov = iov, 78 memset(&s, 0, sizeof(s));
79 .msg_iovlen = 2, 79
80 .msg_control = NULL, 80 s.msg.msg_name = (void*)&s.nladdr;
81 .msg_controllen = 0, 81 s.msg.msg_namelen = sizeof(s.nladdr);
82 .msg_flags = 0 82 s.msg.msg_iov = iov;
83 }; 83 s.msg.msg_iovlen = 2;
84 84 /*s.msg.msg_control = NULL; - already is */
85 memset(&nladdr, 0, sizeof(nladdr)); 85 /*s.msg.msg_controllen = 0; - already is */
86 nladdr.nl_family = AF_NETLINK; 86 /*s.msg.msg_flags = 0; - already is */
87 87
88 nlh.nlmsg_len = NLMSG_LENGTH(len); 88 s.nladdr.nl_family = AF_NETLINK;
89 nlh.nlmsg_type = type; 89
90 nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; 90 s.nlh.nlmsg_len = NLMSG_LENGTH(len);
91 nlh.nlmsg_pid = 0; 91 s.nlh.nlmsg_type = type;
92 nlh.nlmsg_seq = rth->dump = ++rth->seq; 92 s.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
93 93 /*s.nlh.nlmsg_pid = 0; - already is */
94 return sendmsg(rth->fd, &msg, 0); 94 s.nlh.nlmsg_seq = rth->dump = ++rth->seq;
95
96 return sendmsg(rth->fd, &s.msg, 0);
95} 97}
96 98
97static int rtnl_dump_filter(struct rtnl_handle *rth, 99static int rtnl_dump_filter(struct rtnl_handle *rth,
@@ -338,14 +340,14 @@ int FAST_FUNC addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data)
338 int len = RTA_LENGTH(4); 340 int len = RTA_LENGTH(4);
339 struct rtattr *rta; 341 struct rtattr *rta;
340 342
341 if ((int)(NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) { 343 if ((int)(NLMSG_ALIGN(n->nlmsg_len + len)) > maxlen) {
342 return -1; 344 return -1;
343 } 345 }
344 rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); 346 rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
345 rta->rta_type = type; 347 rta->rta_type = type;
346 rta->rta_len = len; 348 rta->rta_len = len;
347 move_to_unaligned32(RTA_DATA(rta), data); 349 move_to_unaligned32(RTA_DATA(rta), data);
348 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 350 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len + len);
349 return 0; 351 return 0;
350} 352}
351 353
@@ -354,14 +356,14 @@ int FAST_FUNC addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, in
354 int len = RTA_LENGTH(alen); 356 int len = RTA_LENGTH(alen);
355 struct rtattr *rta; 357 struct rtattr *rta;
356 358
357 if ((int)(NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) { 359 if ((int)(NLMSG_ALIGN(n->nlmsg_len + len)) > maxlen) {
358 return -1; 360 return -1;
359 } 361 }
360 rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); 362 rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
361 rta->rta_type = type; 363 rta->rta_type = type;
362 rta->rta_len = len; 364 rta->rta_len = len;
363 memcpy(RTA_DATA(rta), data, alen); 365 memcpy(RTA_DATA(rta), data, alen);
364 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; 366 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len + len);
365 return 0; 367 return 0;
366} 368}
367 369
@@ -370,14 +372,14 @@ int FAST_FUNC rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t d
370 int len = RTA_LENGTH(4); 372 int len = RTA_LENGTH(4);
371 struct rtattr *subrta; 373 struct rtattr *subrta;
372 374
373 if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 375 if (RTA_ALIGN(rta->rta_len + len) > maxlen) {
374 return -1; 376 return -1;
375 } 377 }
376 subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 378 subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
377 subrta->rta_type = type; 379 subrta->rta_type = type;
378 subrta->rta_len = len; 380 subrta->rta_len = len;
379 move_to_unaligned32(RTA_DATA(subrta), data); 381 move_to_unaligned32(RTA_DATA(subrta), data);
380 rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 382 rta->rta_len = NLMSG_ALIGN(rta->rta_len + len);
381 return 0; 383 return 0;
382} 384}
383 385
@@ -386,14 +388,14 @@ int FAST_FUNC rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data
386 struct rtattr *subrta; 388 struct rtattr *subrta;
387 int len = RTA_LENGTH(alen); 389 int len = RTA_LENGTH(alen);
388 390
389 if (RTA_ALIGN(rta->rta_len) + len > maxlen) { 391 if (RTA_ALIGN(rta->rta_len + len) > maxlen) {
390 return -1; 392 return -1;
391 } 393 }
392 subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); 394 subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
393 subrta->rta_type = type; 395 subrta->rta_type = type;
394 subrta->rta_len = len; 396 subrta->rta_len = len;
395 memcpy(RTA_DATA(subrta), data, alen); 397 memcpy(RTA_DATA(subrta), data, alen);
396 rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; 398 rta->rta_len = NLMSG_ALIGN(rta->rta_len + len);
397 return 0; 399 return 0;
398} 400}
399 401
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 130cef0af..8ca62cf1b 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -2051,6 +2051,13 @@ recv_and_process_client_pkt(void /*int fd*/)
2051 goto bail; 2051 goto bail;
2052 } 2052 }
2053 2053
2054 /* Respond only to client and symmetric active packets */
2055 if ((msg.m_status & MODE_MASK) != MODE_CLIENT
2056 && (msg.m_status & MODE_MASK) != MODE_SYM_ACT
2057 ) {
2058 goto bail;
2059 }
2060
2054 query_status = msg.m_status; 2061 query_status = msg.m_status;
2055 query_xmttime = msg.m_xmttime; 2062 query_xmttime = msg.m_xmttime;
2056 2063
diff --git a/networking/route.c b/networking/route.c
index 65c2fb7c8..102a6ec67 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -295,7 +295,7 @@ static NOINLINE void INET_setroute(int action, char **args)
295#endif 295#endif
296 296
297 /* Device is special in that it can be the last arg specified 297 /* Device is special in that it can be the last arg specified
298 * and doesn't requre the dev/device keyword in that case. */ 298 * and doesn't require the dev/device keyword in that case. */
299 if (!rt->rt_dev && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) { 299 if (!rt->rt_dev && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
300 /* Don't use args_m1 here since args may have changed! */ 300 /* Don't use args_m1 here since args may have changed! */
301 rt->rt_dev = args[-1]; 301 rt->rt_dev = args[-1];
@@ -416,7 +416,7 @@ static NOINLINE void INET6_setroute(int action, char **args)
416 } 416 }
417 417
418 /* Device is special in that it can be the last arg specified 418 /* Device is special in that it can be the last arg specified
419 * and doesn't requre the dev/device keyword in that case. */ 419 * and doesn't require the dev/device keyword in that case. */
420 if (!devname && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) { 420 if (!devname && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
421 /* Don't use args_m1 here since args may have changed! */ 421 /* Don't use args_m1 here since args may have changed! */
422 devname = args[-1]; 422 devname = args[-1];
diff --git a/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.9.8 b/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.9.8
new file mode 100755
index 000000000..208a7087d
--- /dev/null
+++ b/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.9.8
@@ -0,0 +1,39 @@
1#!/bin/sh
2
3# How to configure & build a static wolfssl 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{
16
17./configure \
18 --host="i686" \
19 --enable-static \
20 --enable-singlethreaded \
21 --disable-shared \
22\
23 C_EXTRA_FLAGS="-DWOLFSSL_STATIC_RSA" \
24|| exit $?
25
26# The second group of options was added when "vanilla" config did not work.
27# A good tool to debug problems is to try wolfssl's client tool, e.g.:
28# examples/client/client -h www.google.com -p 443 -d -x
29#
30# configure has many other options, see ./configure --help
31# --enable-ecc \
32# --enable-sni \
33#
34# Also consult "wolfSSL - Embedded SSL Library Product Support Forums"
35# for recent report of users having problems connecting.
36
37make
38
39} 2>&1 | tee "$0.log"
diff --git a/networking/ssl_helper-wolfssl/README b/networking/ssl_helper-wolfssl/README
index 58a381c20..ff46f4bdf 100644
--- a/networking/ssl_helper-wolfssl/README
+++ b/networking/ssl_helper-wolfssl/README
@@ -11,6 +11,13 @@ Build instructions:
11* Drop this directory into wolfssl-3.6.8/ssl_helper 11* Drop this directory into wolfssl-3.6.8/ssl_helper
12* Run ssl_helper.sh to compile and link the helper 12* Run ssl_helper.sh to compile and link the helper
13 13
14* Unpack wolfssl-3.9.8.tar.gz from https://github.com/wolfSSL/wolfssl/releases
15* Create configure:
16 ./autogen.sh
17* Build it: see 00cfg-wolfssl-3.9.8 shell script
18* Drop this directory into wolfssl-x.y.z/ssl_helper
19* Run ssl_helper.sh to compile and link the helper
20
14Usage: "ssl_helper -d FILE_DESCRIPTOR" where FILE_DESCRIPTOR is open to the peer. 21Usage: "ssl_helper -d FILE_DESCRIPTOR" where FILE_DESCRIPTOR is open to the peer.
15 22
16In bash, you can do it this way: 23In bash, you can do it this way:
diff --git a/networking/ssl_helper-wolfssl/ssl_helper.sh b/networking/ssl_helper-wolfssl/ssl_helper.sh
index 184ffe67e..c6cbf353f 100755
--- a/networking/ssl_helper-wolfssl/ssl_helper.sh
+++ b/networking/ssl_helper-wolfssl/ssl_helper.sh
@@ -9,4 +9,4 @@ STATIC="-static"
9 9
10${PREFIX}gcc -Os -Wall -I.. -c ssl_helper.c -o ssl_helper.o 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 11${PREFIX}gcc $STATIC --start-group ssl_helper.o -lm ../src/.libs/libwolfssl.a --end-group -o ssl_helper
12${PREFIX}-strip ssl_helper 12${PREFIX}strip ssl_helper
diff --git a/networking/traceroute.c b/networking/traceroute.c
index e43a36dc7..b9a9ca4bb 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -212,8 +212,7 @@
212 212
213//usage:#define traceroute_trivial_usage 213//usage:#define traceroute_trivial_usage
214//usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n" 214//usage: "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
215//usage: " [-t TOS] [-w WAIT_SEC]" 215//usage: " [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n"
216//usage: IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(" [-g GATEWAY]")" [-s SRC_IP] [-i IFACE]\n"
217//usage: " [-z PAUSE_MSEC] HOST [BYTES]" 216//usage: " [-z PAUSE_MSEC] HOST [BYTES]"
218//usage:#define traceroute_full_usage "\n\n" 217//usage:#define traceroute_full_usage "\n\n"
219//usage: "Trace the route to HOST\n" 218//usage: "Trace the route to HOST\n"
@@ -294,7 +293,6 @@
294 293
295#define OPT_STRING \ 294#define OPT_STRING \
296 "FIlnrdvxt:i:m:p:q:s:w:z:f:" \ 295 "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
297 IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:*") \
298 "4" IF_TRACEROUTE6("6") 296 "4" IF_TRACEROUTE6("6")
299enum { 297enum {
300 OPT_DONT_FRAGMNT = (1 << 0), /* F */ 298 OPT_DONT_FRAGMNT = (1 << 0), /* F */
@@ -314,9 +312,8 @@ enum {
314 OPT_WAITTIME = (1 << 14), /* w */ 312 OPT_WAITTIME = (1 << 14), /* w */
315 OPT_PAUSE_MS = (1 << 15), /* z */ 313 OPT_PAUSE_MS = (1 << 15), /* z */
316 OPT_FIRST_TTL = (1 << 16), /* f */ 314 OPT_FIRST_TTL = (1 << 16), /* f */
317 OPT_SOURCE_ROUTE = (1 << 17) * ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE, /* g */ 315 OPT_IPV4 = (1 << 17), /* 4 */
318 OPT_IPV4 = (1 << (17+ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE)), /* 4 */ 316 OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */
319 OPT_IPV6 = (1 << (18+ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE)) * ENABLE_TRACEROUTE6, /* 6 */
320}; 317};
321#define verbose (option_mask32 & OPT_VERBOSE) 318#define verbose (option_mask32 & OPT_VERBOSE)
322 319
@@ -343,26 +340,18 @@ struct outdata6_t {
343#endif 340#endif
344 341
345struct globals { 342struct globals {
343 /* Pointer to entire malloced IP packet, "packlen" bytes long: */
346 struct ip *outip; 344 struct ip *outip;
345 /* Pointer to ICMP or UDP payload (not header): */
347 struct outdata_t *outdata; 346 struct outdata_t *outdata;
347
348 len_and_sockaddr *dest_lsa; 348 len_and_sockaddr *dest_lsa;
349 int packlen; /* total length of packet */ 349 int packlen; /* total length of packet */
350 int pmtu; /* Path MTU Discovery (RFC1191) */ 350 int pmtu; /* Path MTU Discovery (RFC1191) */
351 uint32_t ident; 351 uint32_t ident;
352 uint16_t port; // 32768 + 666; /* start udp dest port # for probe packets */ 352 uint16_t port; // 33434; /* start udp dest port # for probe packets */
353 int waittime; // 5; /* time to wait for response (in seconds) */ 353 int waittime; // 5; /* time to wait for response (in seconds) */
354#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
355 int optlen; /* length of ip options */
356#else
357#define optlen 0
358#endif
359 unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ 354 unsigned char recv_pkt[512]; /* last inbound (icmp) packet */
360#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
361 /* Maximum number of gateways (include room for one noop) */
362#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t)))
363 /* loose source route gateway list (including room for final destination) */
364 uint32_t gwlist[NGATEWAYS + 1];
365#endif
366}; 355};
367 356
368#define G (*ptr_to_globals) 357#define G (*ptr_to_globals)
@@ -374,14 +363,11 @@ struct globals {
374#define ident (G.ident ) 363#define ident (G.ident )
375#define port (G.port ) 364#define port (G.port )
376#define waittime (G.waittime ) 365#define waittime (G.waittime )
377#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
378# define optlen (G.optlen )
379#endif
380#define recv_pkt (G.recv_pkt ) 366#define recv_pkt (G.recv_pkt )
381#define gwlist (G.gwlist ) 367#define gwlist (G.gwlist )
382#define INIT_G() do { \ 368#define INIT_G() do { \
383 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 369 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
384 port = 32768 + 666; \ 370 port = 33434; \
385 waittime = 5; \ 371 waittime = 5; \
386} while (0) 372} while (0)
387 373
@@ -421,7 +407,7 @@ send_probe(int seq, int ttl)
421 /* Payload */ 407 /* Payload */
422#if ENABLE_TRACEROUTE6 408#if ENABLE_TRACEROUTE6
423 if (dest_lsa->u.sa.sa_family == AF_INET6) { 409 if (dest_lsa->u.sa.sa_family == AF_INET6) {
424 struct outdata6_t *pkt = (struct outdata6_t *) outip; 410 struct outdata6_t *pkt = (struct outdata6_t *) outdata;
425 pkt->ident6 = htonl(ident); 411 pkt->ident6 = htonl(ident);
426 pkt->seq6 = htonl(seq); 412 pkt->seq6 = htonl(seq);
427 /*gettimeofday(&pkt->tv, &tz);*/ 413 /*gettimeofday(&pkt->tv, &tz);*/
@@ -438,8 +424,10 @@ send_probe(int seq, int ttl)
438 424
439 /* Always calculate checksum for icmp packets */ 425 /* Always calculate checksum for icmp packets */
440 outicmp->icmp_cksum = 0; 426 outicmp->icmp_cksum = 0;
441 outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp, 427 outicmp->icmp_cksum = inet_cksum(
442 packlen - (sizeof(*outip) + optlen)); 428 (uint16_t *)outicmp,
429 ((char*)outip + packlen) - (char*)outicmp
430 );
443 if (outicmp->icmp_cksum == 0) 431 if (outicmp->icmp_cksum == 0)
444 outicmp->icmp_cksum = 0xffff; 432 outicmp->icmp_cksum = 0xffff;
445 } 433 }
@@ -471,13 +459,12 @@ send_probe(int seq, int ttl)
471 } 459 }
472#endif 460#endif
473 461
462 out = outdata;
474#if ENABLE_TRACEROUTE6 463#if ENABLE_TRACEROUTE6
475 if (dest_lsa->u.sa.sa_family == AF_INET6) { 464 if (dest_lsa->u.sa.sa_family == AF_INET6) {
476 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); 465 res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
477 if (res != 0) 466 if (res != 0)
478 bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); 467 bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl);
479 out = outip;
480 len = packlen;
481 } else 468 } else
482#endif 469#endif
483 { 470 {
@@ -486,15 +473,14 @@ send_probe(int seq, int ttl)
486 if (res != 0) 473 if (res != 0)
487 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); 474 bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
488#endif 475#endif
489 out = outicmp; 476 if (option_mask32 & OPT_USE_ICMP)
490 len = packlen - sizeof(*outip); 477 out = outicmp;
491 if (!(option_mask32 & OPT_USE_ICMP)) {
492 out = outdata;
493 len -= sizeof(*outudp);
494 set_nport(&dest_lsa->u.sa, htons(port + seq));
495 }
496 } 478 }
497 479
480 if (!(option_mask32 & OPT_USE_ICMP)) {
481 set_nport(&dest_lsa->u.sa, htons(port + seq));
482 }
483 len = ((char*)outip + packlen) - (char*)out;
498 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len); 484 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
499 if (res != len) 485 if (res != len)
500 bb_error_msg("sent %d octets, ret=%d", len, res); 486 bb_error_msg("sent %d octets, ret=%d", len, res);
@@ -801,10 +787,6 @@ common_traceroute_main(int op, char **argv)
801 char *pausemsecs_str; 787 char *pausemsecs_str;
802 char *first_ttl_str; 788 char *first_ttl_str;
803 char *dest_str; 789 char *dest_str;
804#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
805 llist_t *source_route_list = NULL;
806 int lsrr = 0;
807#endif
808#if ENABLE_TRACEROUTE6 790#if ENABLE_TRACEROUTE6
809 sa_family_t af; 791 sa_family_t af;
810#else 792#else
@@ -823,9 +805,6 @@ common_traceroute_main(int op, char **argv)
823 op |= getopt32(argv, OPT_STRING 805 op |= getopt32(argv, OPT_STRING
824 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str 806 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
825 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str 807 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
826#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
827 , &source_route_list
828#endif
829 ); 808 );
830 argv += optind; 809 argv += optind;
831 810
@@ -858,26 +837,14 @@ common_traceroute_main(int op, char **argv)
858 if (op & OPT_FIRST_TTL) 837 if (op & OPT_FIRST_TTL)
859 first_ttl = xatou_range(first_ttl_str, 1, max_ttl); 838 first_ttl = xatou_range(first_ttl_str, 1, max_ttl);
860 839
861#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
862 if (source_route_list) {
863 while (source_route_list) {
864 len_and_sockaddr *lsa;
865
866 if (lsrr >= NGATEWAYS)
867 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS);
868 lsa = xhost_and_af2sockaddr(llist_pop(&source_route_list), 0, AF_INET);
869 gwlist[lsrr] = lsa->u.sin.sin_addr.s_addr;
870 free(lsa);
871 ++lsrr;
872 }
873 optlen = (lsrr + 1) * sizeof(gwlist[0]);
874 }
875#endif
876
877 /* Process destination and optional packet size */ 840 /* Process destination and optional packet size */
878 minpacket = sizeof(*outip) + SIZEOF_ICMP_HDR + sizeof(*outdata) + optlen; 841 minpacket = sizeof(struct ip)
842 + SIZEOF_ICMP_HDR
843 + sizeof(struct outdata_t);
879 if (!(op & OPT_USE_ICMP)) 844 if (!(op & OPT_USE_ICMP))
880 minpacket += sizeof(*outudp) - SIZEOF_ICMP_HDR; 845 minpacket = sizeof(struct ip)
846 + sizeof(struct udphdr)
847 + sizeof(struct outdata_t);
881#if ENABLE_TRACEROUTE6 848#if ENABLE_TRACEROUTE6
882 af = AF_UNSPEC; 849 af = AF_UNSPEC;
883 if (op & OPT_IPV4) 850 if (op & OPT_IPV4)
@@ -887,7 +854,9 @@ common_traceroute_main(int op, char **argv)
887 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); 854 dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
888 af = dest_lsa->u.sa.sa_family; 855 af = dest_lsa->u.sa.sa_family;
889 if (af == AF_INET6) 856 if (af == AF_INET6)
890 minpacket = sizeof(struct outdata6_t); 857 minpacket = sizeof(struct ip6_hdr)
858 + sizeof(struct udphdr)
859 + sizeof(struct outdata6_t);
891#else 860#else
892 dest_lsa = xhost2sockaddr(argv[0], port); 861 dest_lsa = xhost2sockaddr(argv[0], port);
893#endif 862#endif
@@ -932,31 +901,6 @@ common_traceroute_main(int op, char **argv)
932 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); 901 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock);
933 else 902 else
934 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); 903 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
935#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE && defined IP_OPTIONS
936 if (lsrr > 0) {
937 unsigned char optlist[MAX_IPOPTLEN];
938 unsigned size;
939
940 /* final hop */
941 gwlist[lsrr] = dest_lsa->u.sin.sin_addr.s_addr;
942 ++lsrr;
943
944 /* force 4 byte alignment */
945 optlist[0] = IPOPT_NOP;
946 /* loose source route option */
947 optlist[1] = IPOPT_LSRR;
948 size = lsrr * sizeof(gwlist[0]);
949 optlist[2] = size + 3;
950 /* pointer to LSRR addresses */
951 optlist[3] = IPOPT_MINOFF;
952 memcpy(optlist + 4, gwlist, size);
953
954 if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
955 (char *)optlist, size + sizeof(gwlist[0])) < 0) {
956 bb_perror_msg_and_die("IP_OPTIONS");
957 }
958 }
959#endif
960 } 904 }
961 905
962#ifdef SO_SNDBUF 906#ifdef SO_SNDBUF
@@ -984,7 +928,7 @@ common_traceroute_main(int op, char **argv)
984 928
985 ident = getpid(); 929 ident = getpid();
986 930
987 if (af == AF_INET) { 931 if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
988 if (op & OPT_USE_ICMP) { 932 if (op & OPT_USE_ICMP) {
989 ident |= 0x8000; 933 ident |= 0x8000;
990 outicmp->icmp_type = ICMP_ECHO; 934 outicmp->icmp_type = ICMP_ECHO;
@@ -994,6 +938,14 @@ common_traceroute_main(int op, char **argv)
994 outdata = (struct outdata_t *)(outudp + 1); 938 outdata = (struct outdata_t *)(outudp + 1);
995 } 939 }
996 } 940 }
941#if ENABLE_TRACEROUTE6
942 if (af == AF_INET6) {
943 outdata = (void*)((char*)outip
944 + sizeof(struct ip6_hdr)
945 + sizeof(struct udphdr)
946 );
947 }
948#endif
997 949
998 if (op & OPT_DEVICE) /* hmm, do we need error check? */ 950 if (op & OPT_DEVICE) /* hmm, do we need error check? */
999 setsockopt_bindtodevice(sndsock, device); 951 setsockopt_bindtodevice(sndsock, device);
diff --git a/networking/udhcp/Kbuild.src b/networking/udhcp/Kbuild.src
index b8767baea..5ea77df06 100644
--- a/networking/udhcp/Kbuild.src
+++ b/networking/udhcp/Kbuild.src
@@ -13,7 +13,7 @@ lib-$(CONFIG_UDHCPC) += common.o packet.o signalpipe.o socket.o
13lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o 13lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o
14 14
15lib-$(CONFIG_UDHCPC) += dhcpc.o 15lib-$(CONFIG_UDHCPC) += dhcpc.o
16lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o 16lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o
17lib-$(CONFIG_DUMPLEASES) += dumpleases.o 17lib-$(CONFIG_DUMPLEASES) += dumpleases.o
18lib-$(CONFIG_DHCPRELAY) += dhcprelay.o 18lib-$(CONFIG_DHCPRELAY) += dhcprelay.o
19 19
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c
index c98027316..215d023ce 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -9,7 +9,6 @@
9#include <net/if_arp.h> 9#include <net/if_arp.h>
10 10
11#include "common.h" 11#include "common.h"
12#include "dhcpd.h"
13 12
14struct arpMsg { 13struct arpMsg {
15 /* Ethernet header */ 14 /* Ethernet header */
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 6ff040d9e..ddf3412a0 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -800,10 +800,15 @@ static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *ou
800 ) { 800 ) {
801 bb_error_msg("unicasting a release"); 801 bb_error_msg("unicasting a release");
802 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */ 802 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */
803 d6_run_script(NULL, "deconfig");
804 } 803 }
805 bb_error_msg("entering released state"); 804 bb_error_msg("entering released state");
806 805/*
806 * We can be here on: SIGUSR2,
807 * or on exit (SIGTERM) and -R "release on quit" is specified.
808 * Users requested to be notified in all cases, even if not in one
809 * of the states above.
810 */
811 d6_run_script(NULL, "deconfig");
807 change_listen_mode(LISTEN_NONE); 812 change_listen_mode(LISTEN_NONE);
808 state = RELEASED; 813 state = RELEASED;
809} 814}
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 8a16e987d..bef73277a 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1129,9 +1129,15 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
1129 bb_error_msg("unicasting a release of %s to %s", 1129 bb_error_msg("unicasting a release of %s to %s",
1130 inet_ntoa(temp_addr), buffer); 1130 inet_ntoa(temp_addr), buffer);
1131 send_release(server_addr, requested_ip); /* unicast */ 1131 send_release(server_addr, requested_ip); /* unicast */
1132 udhcp_run_script(NULL, "deconfig");
1133 } 1132 }
1134 bb_error_msg("entering released state"); 1133 bb_error_msg("entering released state");
1134/*
1135 * We can be here on: SIGUSR2,
1136 * or on exit (SIGTERM) and -R "release on quit" is specified.
1137 * Users requested to be notified in all cases, even if not in one
1138 * of the states above.
1139 */
1140 udhcp_run_script(NULL, "deconfig");
1135 1141
1136 change_listen_mode(LISTEN_NONE); 1142 change_listen_mode(LISTEN_NONE);
1137 state = RELEASED; 1143 state = RELEASED;
@@ -1813,9 +1819,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1813 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1819 temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1814 if (!temp) { 1820 if (!temp) {
1815 non_matching_svid: 1821 non_matching_svid:
1816 log1("%s with wrong server ID, ignoring packet", 1822 log1("received DHCP NAK with wrong"
1817 "Received DHCP NAK" 1823 " server ID, ignoring packet");
1818 );
1819 continue; 1824 continue;
1820 } 1825 }
1821 move_from_unaligned32(svid, temp); 1826 move_from_unaligned32(svid, temp);
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index e93a9f1da..56116d01f 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -33,11 +33,507 @@
33//usage: "\n -P N Use port N (default 67)" 33//usage: "\n -P N Use port N (default 67)"
34//usage: ) 34//usage: )
35 35
36#include <netinet/ether.h>
36#include <syslog.h> 37#include <syslog.h>
37#include "common.h" 38#include "common.h"
38#include "dhcpc.h" 39#include "dhcpc.h"
39#include "dhcpd.h" 40#include "dhcpd.h"
40 41
42/* globals */
43struct dyn_lease *g_leases;
44/* struct server_config_t server_config is in bb_common_bufsiz1 */
45
46/* Takes the address of the pointer to the static_leases linked list,
47 * address to a 6 byte mac address,
48 * 4 byte IP address */
49static void add_static_lease(struct static_lease **st_lease_pp,
50 uint8_t *mac,
51 uint32_t nip)
52{
53 struct static_lease *st_lease;
54
55 /* Find the tail of the list */
56 while ((st_lease = *st_lease_pp) != NULL) {
57 st_lease_pp = &st_lease->next;
58 }
59
60 /* Add new node */
61 *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease));
62 memcpy(st_lease->mac, mac, 6);
63 st_lease->nip = nip;
64 /*st_lease->next = NULL;*/
65}
66
67/* Find static lease IP by mac */
68static uint32_t get_static_nip_by_mac(struct static_lease *st_lease, void *mac)
69{
70 while (st_lease) {
71 if (memcmp(st_lease->mac, mac, 6) == 0)
72 return st_lease->nip;
73 st_lease = st_lease->next;
74 }
75
76 return 0;
77}
78
79static int is_nip_reserved(struct static_lease *st_lease, uint32_t nip)
80{
81 while (st_lease) {
82 if (st_lease->nip == nip)
83 return 1;
84 st_lease = st_lease->next;
85 }
86
87 return 0;
88}
89
90#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
91/* Print out static leases just to check what's going on */
92/* Takes the address of the pointer to the static_leases linked list */
93static void log_static_leases(struct static_lease **st_lease_pp)
94{
95 struct static_lease *cur;
96
97 if (dhcp_verbose < 2)
98 return;
99
100 cur = *st_lease_pp;
101 while (cur) {
102 bb_error_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
103 cur->mac[0], cur->mac[1], cur->mac[2],
104 cur->mac[3], cur->mac[4], cur->mac[5],
105 cur->nip
106 );
107 cur = cur->next;
108 }
109}
110#else
111# define log_static_leases(st_lease_pp) ((void)0)
112#endif
113
114/* Find the oldest expired lease, NULL if there are no expired leases */
115static struct dyn_lease *oldest_expired_lease(void)
116{
117 struct dyn_lease *oldest_lease = NULL;
118 leasetime_t oldest_time = time(NULL);
119 unsigned i;
120
121 /* Unexpired leases have g_leases[i].expires >= current time
122 * and therefore can't ever match */
123 for (i = 0; i < server_config.max_leases; i++) {
124 if (g_leases[i].expires == 0 /* empty entry */
125 || g_leases[i].expires < oldest_time
126 ) {
127 oldest_time = g_leases[i].expires;
128 oldest_lease = &g_leases[i];
129 }
130 }
131 return oldest_lease;
132}
133
134/* Clear out all leases with matching nonzero chaddr OR yiaddr.
135 * If chaddr == NULL, this is a conflict lease.
136 */
137static void clear_leases(const uint8_t *chaddr, uint32_t yiaddr)
138{
139 unsigned i;
140
141 for (i = 0; i < server_config.max_leases; i++) {
142 if ((chaddr && memcmp(g_leases[i].lease_mac, chaddr, 6) == 0)
143 || (yiaddr && g_leases[i].lease_nip == yiaddr)
144 ) {
145 memset(&g_leases[i], 0, sizeof(g_leases[i]));
146 }
147 }
148}
149
150/* Add a lease into the table, clearing out any old ones.
151 * If chaddr == NULL, this is a conflict lease.
152 */
153static struct dyn_lease *add_lease(
154 const uint8_t *chaddr, uint32_t yiaddr,
155 leasetime_t leasetime,
156 const char *hostname, int hostname_len)
157{
158 struct dyn_lease *oldest;
159
160 /* clean out any old ones */
161 clear_leases(chaddr, yiaddr);
162
163 oldest = oldest_expired_lease();
164
165 if (oldest) {
166 memset(oldest, 0, sizeof(*oldest));
167 if (hostname) {
168 char *p;
169
170 hostname_len++; /* include NUL */
171 if (hostname_len > sizeof(oldest->hostname))
172 hostname_len = sizeof(oldest->hostname);
173 p = safe_strncpy(oldest->hostname, hostname, hostname_len);
174 /*
175 * Sanitization (s/bad_char/./g).
176 * The intent is not to allow only "DNS-valid" hostnames,
177 * but merely make dumpleases output safe for shells to use.
178 * We accept "0-9A-Za-z._-", all other chars turn to dots.
179 */
180 while (*p) {
181 if (!isalnum(*p) && *p != '-' && *p != '_')
182 *p = '.';
183 p++;
184 }
185 }
186 if (chaddr)
187 memcpy(oldest->lease_mac, chaddr, 6);
188 oldest->lease_nip = yiaddr;
189 oldest->expires = time(NULL) + leasetime;
190 }
191
192 return oldest;
193}
194
195/* True if a lease has expired */
196static int is_expired_lease(struct dyn_lease *lease)
197{
198 return (lease->expires < (leasetime_t) time(NULL));
199}
200
201/* Find the first lease that matches MAC, NULL if no match */
202static struct dyn_lease *find_lease_by_mac(const uint8_t *mac)
203{
204 unsigned i;
205
206 for (i = 0; i < server_config.max_leases; i++)
207 if (memcmp(g_leases[i].lease_mac, mac, 6) == 0)
208 return &g_leases[i];
209
210 return NULL;
211}
212
213/* Find the first lease that matches IP, NULL is no match */
214static struct dyn_lease *find_lease_by_nip(uint32_t nip)
215{
216 unsigned i;
217
218 for (i = 0; i < server_config.max_leases; i++)
219 if (g_leases[i].lease_nip == nip)
220 return &g_leases[i];
221
222 return NULL;
223}
224
225/* Check if the IP is taken; if it is, add it to the lease table */
226static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms)
227{
228 struct in_addr temp;
229 int r;
230
231 r = arpping(nip, safe_mac,
232 server_config.server_nip,
233 server_config.server_mac,
234 server_config.interface,
235 arpping_ms);
236 if (r)
237 return r;
238
239 temp.s_addr = nip;
240 bb_error_msg("%s belongs to someone, reserving it for %u seconds",
241 inet_ntoa(temp), (unsigned)server_config.conflict_time);
242 add_lease(NULL, nip, server_config.conflict_time, NULL, 0);
243 return 0;
244}
245
246/* Find a new usable (we think) address */
247static uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms)
248{
249 uint32_t addr;
250 struct dyn_lease *oldest_lease = NULL;
251
252#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
253 uint32_t stop;
254 unsigned i, hash;
255
256 /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
257 * dispersal even with similarly-valued "strings".
258 */
259 hash = 0;
260 for (i = 0; i < 6; i++)
261 hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash;
262
263 /* pick a seed based on hwaddr then iterate until we find a free address. */
264 addr = server_config.start_ip
265 + (hash % (1 + server_config.end_ip - server_config.start_ip));
266 stop = addr;
267#else
268 addr = server_config.start_ip;
269#define stop (server_config.end_ip + 1)
270#endif
271 do {
272 uint32_t nip;
273 struct dyn_lease *lease;
274
275 /* ie, 192.168.55.0 */
276 if ((addr & 0xff) == 0)
277 goto next_addr;
278 /* ie, 192.168.55.255 */
279 if ((addr & 0xff) == 0xff)
280 goto next_addr;
281 nip = htonl(addr);
282 /* skip our own address */
283 if (nip == server_config.server_nip)
284 goto next_addr;
285 /* is this a static lease addr? */
286 if (is_nip_reserved(server_config.static_leases, nip))
287 goto next_addr;
288
289 lease = find_lease_by_nip(nip);
290 if (!lease) {
291//TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
292 if (nobody_responds_to_arp(nip, safe_mac, arpping_ms))
293 return nip;
294 } else {
295 if (!oldest_lease || lease->expires < oldest_lease->expires)
296 oldest_lease = lease;
297 }
298
299 next_addr:
300 addr++;
301#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
302 if (addr > server_config.end_ip)
303 addr = server_config.start_ip;
304#endif
305 } while (addr != stop);
306
307 if (oldest_lease
308 && is_expired_lease(oldest_lease)
309 && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms)
310 ) {
311 return oldest_lease->lease_nip;
312 }
313
314 return 0;
315}
316
317/* On these functions, make sure your datatype matches */
318static int FAST_FUNC read_str(const char *line, void *arg)
319{
320 char **dest = arg;
321
322 free(*dest);
323 *dest = xstrdup(line);
324 return 1;
325}
326
327static int FAST_FUNC read_u32(const char *line, void *arg)
328{
329 *(uint32_t*)arg = bb_strtou32(line, NULL, 10);
330 return errno == 0;
331}
332
333static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
334{
335 char *line;
336 char *mac_string;
337 char *ip_string;
338 struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */
339 uint32_t nip;
340
341 /* Read mac */
342 line = (char *) const_line;
343 mac_string = strtok_r(line, " \t", &line);
344 if (!mac_string || !ether_aton_r(mac_string, &mac_bytes))
345 return 0;
346
347 /* Read ip */
348 ip_string = strtok_r(NULL, " \t", &line);
349 if (!ip_string || !udhcp_str2nip(ip_string, &nip))
350 return 0;
351
352 add_static_lease(arg, (uint8_t*) &mac_bytes, nip);
353
354 log_static_leases(arg);
355
356 return 1;
357}
358
359struct config_keyword {
360 const char *keyword;
361 int (*handler)(const char *line, void *var) FAST_FUNC;
362 unsigned ofs;
363 const char *def;
364};
365
366#define OFS(field) offsetof(struct server_config_t, field)
367
368static const struct config_keyword keywords[] = {
369 /* keyword handler variable address default */
370 {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
371 {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
372 {"interface" , read_str , OFS(interface ), "eth0"},
373 /* Avoid "max_leases value not sane" warning by setting default
374 * to default_end_ip - default_start_ip + 1: */
375 {"max_leases" , read_u32 , OFS(max_leases ), "235"},
376 {"auto_time" , read_u32 , OFS(auto_time ), "7200"},
377 {"decline_time" , read_u32 , OFS(decline_time ), "3600"},
378 {"conflict_time", read_u32 , OFS(conflict_time), "3600"},
379 {"offer_time" , read_u32 , OFS(offer_time ), "60"},
380 {"min_lease" , read_u32 , OFS(min_lease_sec), "60"},
381 {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE},
382 {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"},
383 {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
384 /* keywords with no defaults must be last! */
385 {"option" , udhcp_str2optset, OFS(options ), ""},
386 {"opt" , udhcp_str2optset, OFS(options ), ""},
387 {"notify_file" , read_str , OFS(notify_file ), NULL},
388 {"sname" , read_str , OFS(sname ), NULL},
389 {"boot_file" , read_str , OFS(boot_file ), NULL},
390 {"static_lease" , read_staticlease, OFS(static_leases), ""},
391};
392enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
393
394static NOINLINE void read_config(const char *file)
395{
396 parser_t *parser;
397 const struct config_keyword *k;
398 unsigned i;
399 char *token[2];
400
401 for (i = 0; i < KWS_WITH_DEFAULTS; i++)
402 keywords[i].handler(keywords[i].def, (char*)&server_config + keywords[i].ofs);
403
404 parser = config_open(file);
405 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
406 for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
407 if (strcasecmp(token[0], k->keyword) == 0) {
408 if (!k->handler(token[1], (char*)&server_config + k->ofs)) {
409 bb_error_msg("can't parse line %u in %s",
410 parser->lineno, file);
411 /* reset back to the default value */
412 k->handler(k->def, (char*)&server_config + k->ofs);
413 }
414 break;
415 }
416 }
417 }
418 config_close(parser);
419
420 server_config.start_ip = ntohl(server_config.start_ip);
421 server_config.end_ip = ntohl(server_config.end_ip);
422}
423
424static void write_leases(void)
425{
426 int fd;
427 unsigned i;
428 leasetime_t curr;
429 int64_t written_at;
430
431 fd = open_or_warn(server_config.lease_file, O_WRONLY|O_CREAT|O_TRUNC);
432 if (fd < 0)
433 return;
434
435 curr = written_at = time(NULL);
436
437 written_at = SWAP_BE64(written_at);
438 full_write(fd, &written_at, sizeof(written_at));
439
440 for (i = 0; i < server_config.max_leases; i++) {
441 leasetime_t tmp_time;
442
443 if (g_leases[i].lease_nip == 0)
444 continue;
445
446 /* Screw with the time in the struct, for easier writing */
447 tmp_time = g_leases[i].expires;
448
449 g_leases[i].expires -= curr;
450 if ((signed_leasetime_t) g_leases[i].expires < 0)
451 g_leases[i].expires = 0;
452 g_leases[i].expires = htonl(g_leases[i].expires);
453
454 /* No error check. If the file gets truncated,
455 * we lose some leases on restart. Oh well. */
456 full_write(fd, &g_leases[i], sizeof(g_leases[i]));
457
458 /* Then restore it when done */
459 g_leases[i].expires = tmp_time;
460 }
461 close(fd);
462
463 if (server_config.notify_file) {
464 char *argv[3];
465 argv[0] = server_config.notify_file;
466 argv[1] = server_config.lease_file;
467 argv[2] = NULL;
468 spawn_and_wait(argv);
469 }
470}
471
472static NOINLINE void read_leases(const char *file)
473{
474 struct dyn_lease lease;
475 int64_t written_at, time_passed;
476 int fd;
477#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
478 unsigned i = 0;
479#endif
480
481 fd = open_or_warn(file, O_RDONLY);
482 if (fd < 0)
483 return;
484
485 if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
486 goto ret;
487 written_at = SWAP_BE64(written_at);
488
489 time_passed = time(NULL) - written_at;
490 /* Strange written_at, or lease file from old version of udhcpd
491 * which had no "written_at" field? */
492 if ((uint64_t)time_passed > 12 * 60 * 60)
493 goto ret;
494
495 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
496 uint32_t y = ntohl(lease.lease_nip);
497 if (y >= server_config.start_ip && y <= server_config.end_ip) {
498 signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
499 uint32_t static_nip;
500
501 if (expires <= 0)
502 /* We keep expired leases: add_lease() will add
503 * a lease with 0 seconds remaining.
504 * Fewer IP address changes this way for mass reboot scenario.
505 */
506 expires = 0;
507
508 /* Check if there is a different static lease for this IP or MAC */
509 static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
510 if (static_nip) {
511 /* NB: we do not add lease even if static_nip == lease.lease_nip.
512 */
513 continue;
514 }
515 if (is_nip_reserved(server_config.static_leases, lease.lease_nip))
516 continue;
517
518 /* NB: add_lease takes "relative time", IOW,
519 * lease duration, not lease deadline. */
520 if (add_lease(lease.lease_mac, lease.lease_nip,
521 expires,
522 lease.hostname, sizeof(lease.hostname)
523 ) == 0
524 ) {
525 bb_error_msg("too many leases while loading %s", file);
526 break;
527 }
528#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
529 i++;
530#endif
531 }
532 }
533 log1("read %d leases", i);
534 ret:
535 close(fd);
536}
41 537
42/* Send a packet to a specific mac address and ip address by creating our own ip packet */ 538/* Send a packet to a specific mac address and ip address by creating our own ip packet */
43static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast) 539static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
@@ -290,12 +786,6 @@ static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
290 send_packet(&packet, /*force_bcast:*/ 0); 786 send_packet(&packet, /*force_bcast:*/ 0);
291} 787}
292 788
293
294/* globals */
295struct dyn_lease *g_leases;
296/* struct server_config_t server_config is in bb_common_bufsiz1 */
297
298
299int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 789int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
300int udhcpd_main(int argc UNUSED_PARAM, char **argv) 790int udhcpd_main(int argc UNUSED_PARAM, char **argv)
301{ 791{
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h
index 9dd5bef9e..b8f96b029 100644
--- a/networking/udhcp/dhcpd.h
+++ b/networking/udhcp/dhcpd.h
@@ -90,39 +90,6 @@ struct dyn_lease {
90 /* total size is a multiply of 4 */ 90 /* total size is a multiply of 4 */
91} PACKED; 91} PACKED;
92 92
93extern struct dyn_lease *g_leases;
94
95struct dyn_lease *add_lease(
96 const uint8_t *chaddr, uint32_t yiaddr,
97 leasetime_t leasetime,
98 const char *hostname, int hostname_len
99 ) FAST_FUNC;
100int is_expired_lease(struct dyn_lease *lease) FAST_FUNC;
101struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC;
102struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC;
103uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) FAST_FUNC;
104
105
106/* Config file parser will pass static lease info to this function
107 * which will add it to a data structure that can be searched later */
108void add_static_lease(struct static_lease **st_lease_pp, uint8_t *mac, uint32_t nip) FAST_FUNC;
109/* Find static lease IP by mac */
110uint32_t get_static_nip_by_mac(struct static_lease *st_lease, void *arg) FAST_FUNC;
111/* Check to see if an IP is reserved as a static IP */
112int is_nip_reserved(struct static_lease *st_lease, uint32_t nip) FAST_FUNC;
113/* Print out static leases just to check what's going on (debug code) */
114#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
115void log_static_leases(struct static_lease **st_lease_pp) FAST_FUNC;
116#else
117# define log_static_leases(st_lease_pp) ((void)0)
118#endif
119
120
121void read_config(const char *file) FAST_FUNC;
122void write_leases(void) FAST_FUNC;
123void read_leases(const char *file) FAST_FUNC;
124
125
126POP_SAVED_FUNCTION_VISIBILITY 93POP_SAVED_FUNCTION_VISIBILITY
127 94
128#endif 95#endif
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
deleted file mode 100644
index b22425352..000000000
--- a/networking/udhcp/files.c
+++ /dev/null
@@ -1,234 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * DHCP server config and lease file manipulation
4 *
5 * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9#include <netinet/ether.h>
10
11#include "common.h"
12#include "dhcpd.h"
13
14/* on these functions, make sure your datatype matches */
15static int FAST_FUNC read_str(const char *line, void *arg)
16{
17 char **dest = arg;
18
19 free(*dest);
20 *dest = xstrdup(line);
21 return 1;
22}
23
24static int FAST_FUNC read_u32(const char *line, void *arg)
25{
26 *(uint32_t*)arg = bb_strtou32(line, NULL, 10);
27 return errno == 0;
28}
29
30static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
31{
32 char *line;
33 char *mac_string;
34 char *ip_string;
35 struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */
36 uint32_t nip;
37
38 /* Read mac */
39 line = (char *) const_line;
40 mac_string = strtok_r(line, " \t", &line);
41 if (!mac_string || !ether_aton_r(mac_string, &mac_bytes))
42 return 0;
43
44 /* Read ip */
45 ip_string = strtok_r(NULL, " \t", &line);
46 if (!ip_string || !udhcp_str2nip(ip_string, &nip))
47 return 0;
48
49 add_static_lease(arg, (uint8_t*) &mac_bytes, nip);
50
51 log_static_leases(arg);
52
53 return 1;
54}
55
56
57struct config_keyword {
58 const char *keyword;
59 int (*handler)(const char *line, void *var) FAST_FUNC;
60 unsigned ofs;
61 const char *def;
62};
63
64#define OFS(field) offsetof(struct server_config_t, field)
65
66static const struct config_keyword keywords[] = {
67 /* keyword handler variable address default */
68 {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
69 {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
70 {"interface" , read_str , OFS(interface ), "eth0"},
71 /* Avoid "max_leases value not sane" warning by setting default
72 * to default_end_ip - default_start_ip + 1: */
73 {"max_leases" , read_u32 , OFS(max_leases ), "235"},
74 {"auto_time" , read_u32 , OFS(auto_time ), "7200"},
75 {"decline_time" , read_u32 , OFS(decline_time ), "3600"},
76 {"conflict_time", read_u32 , OFS(conflict_time), "3600"},
77 {"offer_time" , read_u32 , OFS(offer_time ), "60"},
78 {"min_lease" , read_u32 , OFS(min_lease_sec), "60"},
79 {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE},
80 {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"},
81 {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
82 /* keywords with no defaults must be last! */
83 {"option" , udhcp_str2optset, OFS(options ), ""},
84 {"opt" , udhcp_str2optset, OFS(options ), ""},
85 {"notify_file" , read_str , OFS(notify_file ), NULL},
86 {"sname" , read_str , OFS(sname ), NULL},
87 {"boot_file" , read_str , OFS(boot_file ), NULL},
88 {"static_lease" , read_staticlease, OFS(static_leases), ""},
89};
90enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
91
92void FAST_FUNC read_config(const char *file)
93{
94 parser_t *parser;
95 const struct config_keyword *k;
96 unsigned i;
97 char *token[2];
98
99 for (i = 0; i < KWS_WITH_DEFAULTS; i++)
100 keywords[i].handler(keywords[i].def, (char*)&server_config + keywords[i].ofs);
101
102 parser = config_open(file);
103 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
104 for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
105 if (strcasecmp(token[0], k->keyword) == 0) {
106 if (!k->handler(token[1], (char*)&server_config + k->ofs)) {
107 bb_error_msg("can't parse line %u in %s",
108 parser->lineno, file);
109 /* reset back to the default value */
110 k->handler(k->def, (char*)&server_config + k->ofs);
111 }
112 break;
113 }
114 }
115 }
116 config_close(parser);
117
118 server_config.start_ip = ntohl(server_config.start_ip);
119 server_config.end_ip = ntohl(server_config.end_ip);
120}
121
122void FAST_FUNC write_leases(void)
123{
124 int fd;
125 unsigned i;
126 leasetime_t curr;
127 int64_t written_at;
128
129 fd = open_or_warn(server_config.lease_file, O_WRONLY|O_CREAT|O_TRUNC);
130 if (fd < 0)
131 return;
132
133 curr = written_at = time(NULL);
134
135 written_at = SWAP_BE64(written_at);
136 full_write(fd, &written_at, sizeof(written_at));
137
138 for (i = 0; i < server_config.max_leases; i++) {
139 leasetime_t tmp_time;
140
141 if (g_leases[i].lease_nip == 0)
142 continue;
143
144 /* Screw with the time in the struct, for easier writing */
145 tmp_time = g_leases[i].expires;
146
147 g_leases[i].expires -= curr;
148 if ((signed_leasetime_t) g_leases[i].expires < 0)
149 g_leases[i].expires = 0;
150 g_leases[i].expires = htonl(g_leases[i].expires);
151
152 /* No error check. If the file gets truncated,
153 * we lose some leases on restart. Oh well. */
154 full_write(fd, &g_leases[i], sizeof(g_leases[i]));
155
156 /* Then restore it when done */
157 g_leases[i].expires = tmp_time;
158 }
159 close(fd);
160
161 if (server_config.notify_file) {
162 char *argv[3];
163 argv[0] = server_config.notify_file;
164 argv[1] = server_config.lease_file;
165 argv[2] = NULL;
166 spawn_and_wait(argv);
167 }
168}
169
170void FAST_FUNC read_leases(const char *file)
171{
172 struct dyn_lease lease;
173 int64_t written_at, time_passed;
174 int fd;
175#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
176 unsigned i = 0;
177#endif
178
179 fd = open_or_warn(file, O_RDONLY);
180 if (fd < 0)
181 return;
182
183 if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
184 goto ret;
185 written_at = SWAP_BE64(written_at);
186
187 time_passed = time(NULL) - written_at;
188 /* Strange written_at, or lease file from old version of udhcpd
189 * which had no "written_at" field? */
190 if ((uint64_t)time_passed > 12 * 60 * 60)
191 goto ret;
192
193 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
194 uint32_t y = ntohl(lease.lease_nip);
195 if (y >= server_config.start_ip && y <= server_config.end_ip) {
196 signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
197 uint32_t static_nip;
198
199 if (expires <= 0)
200 /* We keep expired leases: add_lease() will add
201 * a lease with 0 seconds remaining.
202 * Fewer IP address changes this way for mass reboot scenario.
203 */
204 expires = 0;
205
206 /* Check if there is a different static lease for this IP or MAC */
207 static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
208 if (static_nip) {
209 /* NB: we do not add lease even if static_nip == lease.lease_nip.
210 */
211 continue;
212 }
213 if (is_nip_reserved(server_config.static_leases, lease.lease_nip))
214 continue;
215
216 /* NB: add_lease takes "relative time", IOW,
217 * lease duration, not lease deadline. */
218 if (add_lease(lease.lease_mac, lease.lease_nip,
219 expires,
220 lease.hostname, sizeof(lease.hostname)
221 ) == 0
222 ) {
223 bb_error_msg("too many leases while loading %s", file);
224 break;
225 }
226#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
227 i++;
228#endif
229 }
230 }
231 log1("read %d leases", i);
232 ret:
233 close(fd);
234}
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
deleted file mode 100644
index 6642e396d..000000000
--- a/networking/udhcp/leases.c
+++ /dev/null
@@ -1,211 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Russ Dill <Russ.Dill@asu.edu> July 2001
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7#include "common.h"
8#include "dhcpd.h"
9
10/* Find the oldest expired lease, NULL if there are no expired leases */
11static struct dyn_lease *oldest_expired_lease(void)
12{
13 struct dyn_lease *oldest_lease = NULL;
14 leasetime_t oldest_time = time(NULL);
15 unsigned i;
16
17 /* Unexpired leases have g_leases[i].expires >= current time
18 * and therefore can't ever match */
19 for (i = 0; i < server_config.max_leases; i++) {
20 if (g_leases[i].expires == 0 /* empty entry */
21 || g_leases[i].expires < oldest_time
22 ) {
23 oldest_time = g_leases[i].expires;
24 oldest_lease = &g_leases[i];
25 }
26 }
27 return oldest_lease;
28}
29
30/* Clear out all leases with matching nonzero chaddr OR yiaddr.
31 * If chaddr == NULL, this is a conflict lease.
32 */
33static void clear_leases(const uint8_t *chaddr, uint32_t yiaddr)
34{
35 unsigned i;
36
37 for (i = 0; i < server_config.max_leases; i++) {
38 if ((chaddr && memcmp(g_leases[i].lease_mac, chaddr, 6) == 0)
39 || (yiaddr && g_leases[i].lease_nip == yiaddr)
40 ) {
41 memset(&g_leases[i], 0, sizeof(g_leases[i]));
42 }
43 }
44}
45
46/* Add a lease into the table, clearing out any old ones.
47 * If chaddr == NULL, this is a conflict lease.
48 */
49struct dyn_lease* FAST_FUNC add_lease(
50 const uint8_t *chaddr, uint32_t yiaddr,
51 leasetime_t leasetime,
52 const char *hostname, int hostname_len)
53{
54 struct dyn_lease *oldest;
55
56 /* clean out any old ones */
57 clear_leases(chaddr, yiaddr);
58
59 oldest = oldest_expired_lease();
60
61 if (oldest) {
62 memset(oldest, 0, sizeof(*oldest));
63 if (hostname) {
64 char *p;
65
66 hostname_len++; /* include NUL */
67 if (hostname_len > sizeof(oldest->hostname))
68 hostname_len = sizeof(oldest->hostname);
69 p = safe_strncpy(oldest->hostname, hostname, hostname_len);
70 /*
71 * Sanitization (s/bad_char/./g).
72 * The intent is not to allow only "DNS-valid" hostnames,
73 * but merely make dumpleases output safe for shells to use.
74 * We accept "0-9A-Za-z._-", all other chars turn to dots.
75 */
76 while (*p) {
77 if (!isalnum(*p) && *p != '-' && *p != '_')
78 *p = '.';
79 p++;
80 }
81 }
82 if (chaddr)
83 memcpy(oldest->lease_mac, chaddr, 6);
84 oldest->lease_nip = yiaddr;
85 oldest->expires = time(NULL) + leasetime;
86 }
87
88 return oldest;
89}
90
91/* True if a lease has expired */
92int FAST_FUNC is_expired_lease(struct dyn_lease *lease)
93{
94 return (lease->expires < (leasetime_t) time(NULL));
95}
96
97/* Find the first lease that matches MAC, NULL if no match */
98struct dyn_lease* FAST_FUNC find_lease_by_mac(const uint8_t *mac)
99{
100 unsigned i;
101
102 for (i = 0; i < server_config.max_leases; i++)
103 if (memcmp(g_leases[i].lease_mac, mac, 6) == 0)
104 return &g_leases[i];
105
106 return NULL;
107}
108
109/* Find the first lease that matches IP, NULL is no match */
110struct dyn_lease* FAST_FUNC find_lease_by_nip(uint32_t nip)
111{
112 unsigned i;
113
114 for (i = 0; i < server_config.max_leases; i++)
115 if (g_leases[i].lease_nip == nip)
116 return &g_leases[i];
117
118 return NULL;
119}
120
121/* Check if the IP is taken; if it is, add it to the lease table */
122static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms)
123{
124 struct in_addr temp;
125 int r;
126
127 r = arpping(nip, safe_mac,
128 server_config.server_nip,
129 server_config.server_mac,
130 server_config.interface,
131 arpping_ms);
132 if (r)
133 return r;
134
135 temp.s_addr = nip;
136 bb_error_msg("%s belongs to someone, reserving it for %u seconds",
137 inet_ntoa(temp), (unsigned)server_config.conflict_time);
138 add_lease(NULL, nip, server_config.conflict_time, NULL, 0);
139 return 0;
140}
141
142/* Find a new usable (we think) address */
143uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms)
144{
145 uint32_t addr;
146 struct dyn_lease *oldest_lease = NULL;
147
148#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
149 uint32_t stop;
150 unsigned i, hash;
151
152 /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
153 * dispersal even with similarly-valued "strings".
154 */
155 hash = 0;
156 for (i = 0; i < 6; i++)
157 hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash;
158
159 /* pick a seed based on hwaddr then iterate until we find a free address. */
160 addr = server_config.start_ip
161 + (hash % (1 + server_config.end_ip - server_config.start_ip));
162 stop = addr;
163#else
164 addr = server_config.start_ip;
165#define stop (server_config.end_ip + 1)
166#endif
167 do {
168 uint32_t nip;
169 struct dyn_lease *lease;
170
171 /* ie, 192.168.55.0 */
172 if ((addr & 0xff) == 0)
173 goto next_addr;
174 /* ie, 192.168.55.255 */
175 if ((addr & 0xff) == 0xff)
176 goto next_addr;
177 nip = htonl(addr);
178 /* skip our own address */
179 if (nip == server_config.server_nip)
180 goto next_addr;
181 /* is this a static lease addr? */
182 if (is_nip_reserved(server_config.static_leases, nip))
183 goto next_addr;
184
185 lease = find_lease_by_nip(nip);
186 if (!lease) {
187//TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
188 if (nobody_responds_to_arp(nip, safe_mac, arpping_ms))
189 return nip;
190 } else {
191 if (!oldest_lease || lease->expires < oldest_lease->expires)
192 oldest_lease = lease;
193 }
194
195 next_addr:
196 addr++;
197#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
198 if (addr > server_config.end_ip)
199 addr = server_config.start_ip;
200#endif
201 } while (addr != stop);
202
203 if (oldest_lease
204 && is_expired_lease(oldest_lease)
205 && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms)
206 ) {
207 return oldest_lease->lease_nip;
208 }
209
210 return 0;
211}
diff --git a/networking/udhcp/static_leases.c b/networking/udhcp/static_leases.c
deleted file mode 100644
index b7f9e5c59..000000000
--- a/networking/udhcp/static_leases.c
+++ /dev/null
@@ -1,77 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Storing and retrieving data for static leases
4 *
5 * Wade Berrier <wberrier@myrealbox.com> September 2004
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9#include "common.h"
10#include "dhcpd.h"
11
12/* Takes the address of the pointer to the static_leases linked list,
13 * address to a 6 byte mac address,
14 * 4 byte IP address */
15void FAST_FUNC add_static_lease(struct static_lease **st_lease_pp,
16 uint8_t *mac,
17 uint32_t nip)
18{
19 struct static_lease *st_lease;
20
21 /* Find the tail of the list */
22 while ((st_lease = *st_lease_pp) != NULL) {
23 st_lease_pp = &st_lease->next;
24 }
25
26 /* Add new node */
27 *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease));
28 memcpy(st_lease->mac, mac, 6);
29 st_lease->nip = nip;
30 /*st_lease->next = NULL;*/
31}
32
33/* Find static lease IP by mac */
34uint32_t FAST_FUNC get_static_nip_by_mac(struct static_lease *st_lease, void *mac)
35{
36 while (st_lease) {
37 if (memcmp(st_lease->mac, mac, 6) == 0)
38 return st_lease->nip;
39 st_lease = st_lease->next;
40 }
41
42 return 0;
43}
44
45/* Check to see if an IP is reserved as a static IP */
46int FAST_FUNC is_nip_reserved(struct static_lease *st_lease, uint32_t nip)
47{
48 while (st_lease) {
49 if (st_lease->nip == nip)
50 return 1;
51 st_lease = st_lease->next;
52 }
53
54 return 0;
55}
56
57#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
58/* Print out static leases just to check what's going on */
59/* Takes the address of the pointer to the static_leases linked list */
60void FAST_FUNC log_static_leases(struct static_lease **st_lease_pp)
61{
62 struct static_lease *cur;
63
64 if (dhcp_verbose < 2)
65 return;
66
67 cur = *st_lease_pp;
68 while (cur) {
69 bb_error_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
70 cur->mac[0], cur->mac[1], cur->mac[2],
71 cur->mac[3], cur->mac[4], cur->mac[5],
72 cur->nip
73 );
74 cur = cur->next;
75 }
76}
77#endif
diff --git a/networking/wget.c b/networking/wget.c
index c886dd391..460b4b833 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -62,9 +62,10 @@
62//config: a helper program to talk over HTTPS. 62//config: a helper program to talk over HTTPS.
63//config: 63//config:
64//config: OpenSSL has a simple SSL client for debug purposes. 64//config: OpenSSL has a simple SSL client for debug purposes.
65//config: If you select "openssl" helper, wget will effectively call 65//config: If you select "openssl" helper, wget will effectively run:
66//config: "openssl s_client -quiet -connect IP:443 2>/dev/null" 66//config: "openssl s_client -quiet -connect hostname:443
67//config: and pipe its data through it. 67//config: -servername hostname 2>/dev/null" and pipe its data
68//config: through it. -servername is not used if hostname is numeric.
68//config: Note inconvenient API: host resolution is done twice, 69//config: Note inconvenient API: host resolution is done twice,
69//config: and there is no guarantee openssl's idea of IPv6 address 70//config: and there is no guarantee openssl's idea of IPv6 address
70//config: format is the same as ours. 71//config: format is the same as ours.
@@ -99,7 +100,7 @@
99 100
100//usage:#define wget_trivial_usage 101//usage:#define wget_trivial_usage
101//usage: IF_FEATURE_WGET_LONG_OPTIONS( 102//usage: IF_FEATURE_WGET_LONG_OPTIONS(
102//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" 103//usage: "[-c|--continue] [--spider] [-q|--quiet] [-O|--output-document FILE]\n"
103//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" 104//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
104/* Since we ignore these opts, we don't show them in --help */ 105/* Since we ignore these opts, we don't show them in --help */
105/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ 106/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
@@ -107,21 +108,23 @@
107//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 108//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
108//usage: ) 109//usage: )
109//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( 110//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
110//usage: "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" 111//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]"
111//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 112//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
112//usage: ) 113//usage: )
113//usage:#define wget_full_usage "\n\n" 114//usage:#define wget_full_usage "\n\n"
114//usage: "Retrieve files via HTTP or FTP\n" 115//usage: "Retrieve files via HTTP or FTP\n"
115//usage: "\n -s Spider mode - only check file existence" 116//usage: IF_FEATURE_WGET_LONG_OPTIONS(
116//usage: "\n -c Continue retrieval of aborted transfer" 117//usage: "\n --spider Spider mode - only check file existence"
117//usage: "\n -q Quiet" 118//usage: )
118//usage: "\n -P DIR Save to DIR (default .)" 119//usage: "\n -c Continue retrieval of aborted transfer"
120//usage: "\n -q Quiet"
121//usage: "\n -P DIR Save to DIR (default .)"
119//usage: IF_FEATURE_WGET_TIMEOUT( 122//usage: IF_FEATURE_WGET_TIMEOUT(
120//usage: "\n -T SEC Network read timeout is SEC seconds" 123//usage: "\n -T SEC Network read timeout is SEC seconds"
121//usage: ) 124//usage: )
122//usage: "\n -O FILE Save to FILE ('-' for stdout)" 125//usage: "\n -O FILE Save to FILE ('-' for stdout)"
123//usage: "\n -U STR Use STR for User-Agent header" 126//usage: "\n -U STR Use STR for User-Agent header"
124//usage: "\n -Y Use proxy ('on' or 'off')" 127//usage: "\n -Y on/off Use proxy"
125 128
126#include "libbb.h" 129#include "libbb.h"
127 130
@@ -228,17 +231,17 @@ struct globals {
228/* Must match option string! */ 231/* Must match option string! */
229enum { 232enum {
230 WGET_OPT_CONTINUE = (1 << 0), 233 WGET_OPT_CONTINUE = (1 << 0),
231 WGET_OPT_SPIDER = (1 << 1), 234 WGET_OPT_QUIET = (1 << 1),
232 WGET_OPT_QUIET = (1 << 2), 235 WGET_OPT_OUTNAME = (1 << 2),
233 WGET_OPT_OUTNAME = (1 << 3), 236 WGET_OPT_PREFIX = (1 << 3),
234 WGET_OPT_PREFIX = (1 << 4), 237 WGET_OPT_PROXY = (1 << 4),
235 WGET_OPT_PROXY = (1 << 5), 238 WGET_OPT_USER_AGENT = (1 << 5),
236 WGET_OPT_USER_AGENT = (1 << 6), 239 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 6),
237 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7), 240 WGET_OPT_RETRIES = (1 << 7),
238 WGET_OPT_RETRIES = (1 << 8), 241 WGET_OPT_nsomething = (1 << 8),
239 WGET_OPT_PASSIVE = (1 << 9), 242 WGET_OPT_HEADER = (1 << 9) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
240 WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 243 WGET_OPT_POST_DATA = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
241 WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 244 WGET_OPT_SPIDER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
242}; 245};
243 246
244enum { 247enum {
@@ -349,6 +352,30 @@ static void set_alarm(void)
349# define clear_alarm() ((void)0) 352# define clear_alarm() ((void)0)
350#endif 353#endif
351 354
355#if ENABLE_FEATURE_WGET_OPENSSL
356/*
357 * is_ip_address() attempts to verify whether or not a string
358 * contains an IPv4 or IPv6 address (vs. an FQDN). The result
359 * of inet_pton() can be used to determine this.
360 *
361 * TODO add proper error checking when inet_pton() returns -1
362 * (some form of system error has occurred, and errno is set)
363 */
364static int is_ip_address(const char *string)
365{
366 struct sockaddr_in sa;
367
368 int result = inet_pton(AF_INET, string, &(sa.sin_addr));
369# if ENABLE_FEATURE_IPV6
370 if (result == 0) {
371 struct sockaddr_in6 sa6;
372 result = inet_pton(AF_INET6, string, &(sa6.sin6_addr));
373 }
374# endif
375 return (result == 1);
376}
377#endif
378
352static FILE *open_socket(len_and_sockaddr *lsa) 379static FILE *open_socket(len_and_sockaddr *lsa)
353{ 380{
354 int fd; 381 int fd;
@@ -635,6 +662,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
635static int spawn_https_helper_openssl(const char *host, unsigned port) 662static int spawn_https_helper_openssl(const char *host, unsigned port)
636{ 663{
637 char *allocated = NULL; 664 char *allocated = NULL;
665 char *servername;
638 int sp[2]; 666 int sp[2];
639 int pid; 667 int pid;
640 IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) 668 IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;)
@@ -645,12 +673,14 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
645 673
646 if (!strchr(host, ':')) 674 if (!strchr(host, ':'))
647 host = allocated = xasprintf("%s:%u", host, port); 675 host = allocated = xasprintf("%s:%u", host, port);
676 servername = xstrdup(host);
677 strrchr(servername, ':')[0] = '\0';
648 678
649 fflush_all(); 679 fflush_all();
650 pid = xvfork(); 680 pid = xvfork();
651 if (pid == 0) { 681 if (pid == 0) {
652 /* Child */ 682 /* Child */
653 char *argv[6]; 683 char *argv[8];
654 684
655 close(sp[0]); 685 close(sp[0]);
656 xmove_fd(sp[1], 0); 686 xmove_fd(sp[1], 0);
@@ -662,12 +692,22 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
662 */ 692 */
663 xmove_fd(2, 3); 693 xmove_fd(2, 3);
664 xopen("/dev/null", O_RDWR); 694 xopen("/dev/null", O_RDWR);
695 memset(&argv, 0, sizeof(argv));
665 argv[0] = (char*)"openssl"; 696 argv[0] = (char*)"openssl";
666 argv[1] = (char*)"s_client"; 697 argv[1] = (char*)"s_client";
667 argv[2] = (char*)"-quiet"; 698 argv[2] = (char*)"-quiet";
668 argv[3] = (char*)"-connect"; 699 argv[3] = (char*)"-connect";
669 argv[4] = (char*)host; 700 argv[4] = (char*)host;
670 argv[5] = NULL; 701 /*
702 * Per RFC 6066 Section 3, the only permitted values in the
703 * TLS server_name (SNI) field are FQDNs (DNS hostnames).
704 * IPv4 and IPv6 addresses, port numbers are not allowed.
705 */
706 if (!is_ip_address(servername)) {
707 argv[5] = (char*)"-servername";
708 argv[6] = (char*)servername;
709 }
710
671 BB_EXECVP(argv[0], argv); 711 BB_EXECVP(argv[0], argv);
672 xmove_fd(3, 2); 712 xmove_fd(3, 2);
673# if ENABLE_FEATURE_WGET_SSL_HELPER 713# if ENABLE_FEATURE_WGET_SSL_HELPER
@@ -680,6 +720,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
680 } 720 }
681 721
682 /* Parent */ 722 /* Parent */
723 free(servername);
683 free(allocated); 724 free(allocated);
684 close(sp[1]); 725 close(sp[1]);
685# if ENABLE_FEATURE_WGET_SSL_HELPER 726# if ENABLE_FEATURE_WGET_SSL_HELPER
@@ -1058,6 +1099,12 @@ static void download_one_url(const char *url)
1058 } 1099 }
1059 1100
1060 fflush(sfp); 1101 fflush(sfp);
1102 /* If we use SSL helper, keeping our end of the socket open for writing
1103 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF)
1104 * even after child closes its copy of the fd.
1105 * This helps:
1106 */
1107 shutdown(fileno(sfp), SHUT_WR);
1061 1108
1062 /* 1109 /*
1063 * Retrieve HTTP response line and check for "200" status code. 1110 * Retrieve HTTP response line and check for "200" status code.
@@ -1077,7 +1124,21 @@ static void download_one_url(const char *url)
1077 while (gethdr(sfp) != NULL) 1124 while (gethdr(sfp) != NULL)
1078 /* eat all remaining headers */; 1125 /* eat all remaining headers */;
1079 goto read_response; 1126 goto read_response;
1127
1128 /* Success responses */
1080 case 200: 1129 case 200:
1130 /* fall through */
1131 case 201: /* 201 Created */
1132/* "The request has been fulfilled and resulted in a new resource being created" */
1133 /* Standard wget is reported to treat this as success */
1134 /* fall through */
1135 case 202: /* 202 Accepted */
1136/* "The request has been accepted for processing, but the processing has not been completed" */
1137 /* Treat as success: fall through */
1138 case 203: /* 203 Non-Authoritative Information */
1139/* "Use of this response code is not required and is only appropriate when the response would otherwise be 200 (OK)" */
1140 /* fall through */
1141 case 204: /* 204 No Content */
1081/* 1142/*
1082Response 204 doesn't say "null file", it says "metadata 1143Response 204 doesn't say "null file", it says "metadata
1083has changed but data didn't": 1144has changed but data didn't":
@@ -1102,7 +1163,6 @@ is always terminated by the first empty line after the header fields."
1102However, in real world it was observed that some web servers 1163However, in real world it was observed that some web servers
1103(e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero. 1164(e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero.
1104*/ 1165*/
1105 case 204:
1106 if (G.beg_range != 0) { 1166 if (G.beg_range != 0) {
1107 /* "Range:..." was not honored by the server. 1167 /* "Range:..." was not honored by the server.
1108 * Restart download from the beginning. 1168 * Restart download from the beginning.
@@ -1110,11 +1170,14 @@ However, in real world it was observed that some web servers
1110 reset_beg_range_to_zero(); 1170 reset_beg_range_to_zero();
1111 } 1171 }
1112 break; 1172 break;
1173 /* 205 Reset Content ?? what to do on this ?? */
1174
1113 case 300: /* redirection */ 1175 case 300: /* redirection */
1114 case 301: 1176 case 301:
1115 case 302: 1177 case 302:
1116 case 303: 1178 case 303:
1117 break; 1179 break;
1180
1118 case 206: /* Partial Content */ 1181 case 206: /* Partial Content */
1119 if (G.beg_range != 0) 1182 if (G.beg_range != 0)
1120 /* "Range:..." worked. Good. */ 1183 /* "Range:..." worked. Good. */
@@ -1231,8 +1294,6 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1231 static const char wget_longopts[] ALIGN1 = 1294 static const char wget_longopts[] ALIGN1 =
1232 /* name, has_arg, val */ 1295 /* name, has_arg, val */
1233 "continue\0" No_argument "c" 1296 "continue\0" No_argument "c"
1234//FIXME: -s isn't --spider, it's --save-headers!
1235 "spider\0" No_argument "s"
1236 "quiet\0" No_argument "q" 1297 "quiet\0" No_argument "q"
1237 "output-document\0" Required_argument "O" 1298 "output-document\0" Required_argument "O"
1238 "directory-prefix\0" Required_argument "P" 1299 "directory-prefix\0" Required_argument "P"
@@ -1244,6 +1305,7 @@ IF_FEATURE_WGET_TIMEOUT(
1244IF_DESKTOP( "tries\0" Required_argument "t") 1305IF_DESKTOP( "tries\0" Required_argument "t")
1245 "header\0" Required_argument "\xff" 1306 "header\0" Required_argument "\xff"
1246 "post-data\0" Required_argument "\xfe" 1307 "post-data\0" Required_argument "\xfe"
1308 "spider\0" No_argument "\xfd"
1247 /* Ignored (we always use PASV): */ 1309 /* Ignored (we always use PASV): */
1248IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") 1310IF_DESKTOP( "passive-ftp\0" No_argument "\xf0")
1249 /* Ignored (we don't do ssl) */ 1311 /* Ignored (we don't do ssl) */
@@ -1275,7 +1337,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1275#endif 1337#endif
1276 opt_complementary = "-1" /* at least one URL */ 1338 opt_complementary = "-1" /* at least one URL */
1277 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */ 1339 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
1278 getopt32(argv, "csqO:P:Y:U:T:+" 1340 getopt32(argv, "cqO:P:Y:U:T:+"
1279 /*ignored:*/ "t:" 1341 /*ignored:*/ "t:"
1280 /*ignored:*/ "n::" 1342 /*ignored:*/ "n::"
1281 /* wget has exactly four -n<letter> opts, all of which we can ignore: 1343 /* wget has exactly four -n<letter> opts, all of which we can ignore:
@@ -1294,6 +1356,14 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1294 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist) 1356 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
1295 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data) 1357 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
1296 ); 1358 );
1359#if 0 /* option bits debug */
1360 if (option_mask32 & WGET_OPT_RETRIES) bb_error_msg("-t NUM");
1361 if (option_mask32 & WGET_OPT_nsomething) bb_error_msg("-nsomething");
1362 if (option_mask32 & WGET_OPT_HEADER) bb_error_msg("--header");
1363 if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data");
1364 if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider");
1365 exit(0);
1366#endif
1297 argv += optind; 1367 argv += optind;
1298 1368
1299#if ENABLE_FEATURE_WGET_LONG_OPTIONS 1369#if ENABLE_FEATURE_WGET_LONG_OPTIONS