aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-03-01 15:37:12 +0000
committerRon Yorston <rmy@pobox.com>2018-03-01 15:37:12 +0000
commit5b726f8a78c33e117c2a968739b1b4a6964905f8 (patch)
treeaf063c6bf3e99b7480c2fad2dffc2a76c09cb5e0 /networking
parent5f8dac68690e92f0be220f8f8d9f797a2aedc806 (diff)
parentcc222747ae7e264cbe9b1c8a9c253860275db8a9 (diff)
downloadbusybox-w32-5b726f8a78c33e117c2a968739b1b4a6964905f8.tar.gz
busybox-w32-5b726f8a78c33e117c2a968739b1b4a6964905f8.tar.bz2
busybox-w32-5b726f8a78c33e117c2a968739b1b4a6964905f8.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r--networking/inetd.c6
-rw-r--r--networking/ip.c58
-rw-r--r--networking/libiproute/iplink.c62
-rw-r--r--networking/ping.c105
-rw-r--r--networking/tcpudp.c9
-rw-r--r--networking/tcpudp_perhost.c22
-rw-r--r--networking/tcpudp_perhost.h8
-rw-r--r--networking/tls.c2
8 files changed, 201 insertions, 71 deletions
diff --git a/networking/inetd.c b/networking/inetd.c
index 6843845fb..ca1a97268 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -246,7 +246,11 @@
246#if ENABLE_FEATURE_INETD_RPC 246#if ENABLE_FEATURE_INETD_RPC
247# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) 247# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
248# warning "You probably need to build uClibc with UCLIBC_HAS_RPC for NFS support" 248# warning "You probably need to build uClibc with UCLIBC_HAS_RPC for NFS support"
249 /* not #error, since user may be using e.g. libtirpc instead */ 249 /* not #error, since user may be using e.g. libtirpc instead.
250 * This might work:
251 * CONFIG_EXTRA_CFLAGS="-I/usr/include/tirpc"
252 * CONFIG_EXTRA_LDLIBS="tirpc"
253 */
250# endif 254# endif
251# include <rpc/rpc.h> 255# include <rpc/rpc.h>
252# include <rpc/pmap_clnt.h> 256# include <rpc/pmap_clnt.h>
diff --git a/networking/ip.c b/networking/ip.c
index 0bc0edc57..accf90759 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -155,11 +155,61 @@
155//usage: 155//usage:
156//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 156//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
157//usage:#define iplink_trivial_usage 157//usage:#define iplink_trivial_usage
158//usage: "set IFACE [up|down] [arp on|off] | show [IFACE]" 158//usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n"
159//usage:#define iplink_full_usage "\n\n" 159//usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n"
160//usage: "iplink set IFACE [up|down] [arp on|off] [multicast on|off] [promisc on|off]\n" 160//usage: " [master IFACE | nomaster]\n"
161//usage: " [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" 161// * short help shows only "set" command, long help continues (with just one "\n")
162// * and shows all other commands:
163//usage:#define iplink_full_usage "\n"
164//usage: "iplink add [link IFACE] IFACE [address MAC] type TYPE [ARGS]\n"
165//usage: "iplink delete IFACE type TYPE [ARGS]\n"
166//usage: " TYPE ARGS := vlan VLANARGS | vrf table NUM\n"
167//usage: " VLANARGS := id VLANID [protocol 802.1q|802.1ad] [reorder_hdr on|off]\n"
168//usage: " [gvrp on|off] [mvrp on|off] [loose_binding on|off]\n"
162//usage: "iplink show [IFACE]" 169//usage: "iplink show [IFACE]"
170//upstream man ip-link:
171//=====================
172//ip link add [link DEV] [ name ] NAME
173// [ txqueuelen PACKETS ]
174// [ address LLADDR ]
175// [ broadcast LLADDR ]
176// [ mtu MTU ] [index IDX ]
177// [ numtxqueues QUEUE_COUNT ]
178// [ numrxqueues QUEUE_COUNT ]
179// type TYPE [ ARGS ]
180// ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]
181// ip link set { DEVICE | dev DEVICE | group DEVGROUP } [ { up | down } ]
182// [ arp { on | off } ]
183// [ dynamic { on | off } ]
184// [ multicast { on | off } ]
185// [ allmulticast { on | off } ]
186// [ promisc { on | off } ]
187// [ trailers { on | off } ]
188// [ txqueuelen PACKETS ]
189// [ name NEWNAME ]
190// [ address LLADDR ]
191// [ broadcast LLADDR ]
192// [ mtu MTU ]
193// [ netns { PID | NAME } ]
194// [ link-netnsid ID ]
195// [ alias NAME ]
196// [ vf NUM [ mac LLADDR ]
197// [ vlan VLANID [ qos VLAN-QOS ] ]
198// [ rate TXRATE ]
199// [ spoofchk { on | off} ]
200// [ query_rss { on | off} ]
201// [ state { auto | enable | disable} ] ]
202// [ trust { on | off} ] ]
203// [ master DEVICE ]
204// [ nomaster ]
205// [ addrgenmode { eui64 | none | stable_secret | random } ]
206// [ protodown { on | off } ]
207// ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]
208// ip link help [ TYPE ]
209//TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
210// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
211// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
212// bond_slave | ipvlan | geneve | bridge_slave | vrf }
163//usage: 213//usage:
164//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 214//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
165//usage:#define iproute_trivial_usage 215//usage:#define iproute_trivial_usage
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index f38fba055..2aa8b683b 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -128,6 +128,31 @@ static void set_mtu(char *dev, int mtu)
128} 128}
129 129
130/* Exits on error */ 130/* Exits on error */
131static void set_master(char *dev, int master)
132{
133 struct rtnl_handle rth;
134 struct {
135 struct nlmsghdr n;
136 struct ifinfomsg i;
137 char buf[1024];
138 } req;
139
140 memset(&req, 0, sizeof(req));
141
142 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
143 req.n.nlmsg_flags = NLM_F_REQUEST;
144 req.n.nlmsg_type = RTM_NEWLINK;
145 req.i.ifi_family = preferred_family;
146
147 xrtnl_open(&rth);
148 req.i.ifi_index = xll_name_to_index(dev);
149 //printf("master %i for %i\n", master, req.i.ifi_index);
150 addattr_l(&req.n, sizeof(req), IFLA_MASTER, &master, 4);
151 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
152 xfunc_die();
153}
154
155/* Exits on error */
131static int get_address(char *dev, int *htype) 156static int get_address(char *dev, int *htype)
132{ 157{
133 struct ifreq ifr; 158 struct ifreq ifr;
@@ -200,6 +225,7 @@ static int do_set(char **argv)
200 uint32_t flags = 0; 225 uint32_t flags = 0;
201 int qlen = -1; 226 int qlen = -1;
202 int mtu = -1; 227 int mtu = -1;
228 int master = -1;
203 char *newaddr = NULL; 229 char *newaddr = NULL;
204 char *newbrd = NULL; 230 char *newbrd = NULL;
205 struct ifreq ifr0, ifr1; 231 struct ifreq ifr0, ifr1;
@@ -209,9 +235,11 @@ static int do_set(char **argv)
209 static const char keywords[] ALIGN1 = 235 static const char keywords[] ALIGN1 =
210 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" 236 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0"
211 "arp\0""promisc\0""address\0" 237 "arp\0""promisc\0""address\0"
238 "master\0""nomaster\0"
212 "dev\0" /* must be last */; 239 "dev\0" /* must be last */;
213 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, 240 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast,
214 ARG_arp, ARG_promisc, ARG_addr, 241 ARG_arp, ARG_promisc, ARG_addr,
242 ARG_master, ARG_nomaster,
215 ARG_dev }; 243 ARG_dev };
216 enum { PARM_on = 0, PARM_off }; 244 enum { PARM_on = 0, PARM_off };
217 smalluint key; 245 smalluint key;
@@ -243,6 +271,11 @@ static int do_set(char **argv)
243 } else if (key == ARG_addr) { 271 } else if (key == ARG_addr) {
244 NEXT_ARG(); 272 NEXT_ARG();
245 newaddr = *argv; 273 newaddr = *argv;
274 } else if (key == ARG_master) {
275 NEXT_ARG();
276 master = xll_name_to_index(*argv);
277 } else if (key == ARG_nomaster) {
278 master = 0;
246 } else if (key >= ARG_dev) { 279 } else if (key >= ARG_dev) {
247 /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ 280 /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */
248 if (key == ARG_dev) { 281 if (key == ARG_dev) {
@@ -427,6 +460,9 @@ static int do_set(char **argv)
427 if (mtu != -1) { 460 if (mtu != -1) {
428 set_mtu(dev, mtu); 461 set_mtu(dev, mtu);
429 } 462 }
463 if (master != -1) {
464 set_master(dev, master);
465 }
430 if (mask) 466 if (mask)
431 do_chflags(dev, flags, mask); 467 do_chflags(dev, flags, mask);
432 return 0; 468 return 0;
@@ -525,6 +561,24 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
525 addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags)); 561 addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
526} 562}
527 563
564static void vrf_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
565{
566/* IFLA_VRF_TABLE is an enum, not a define -
567 * can't test "defined(IFLA_VRF_TABLE)".
568 */
569#if !defined(IFLA_VRF_MAX)
570# define IFLA_VRF_TABLE 1
571#endif
572 uint32_t table;
573
574 if (strcmp(*argv, "table") != 0)
575 invarg_1_to_2(*argv, "type vrf");
576
577 NEXT_ARG();
578 table = get_u32(*argv, "table");
579 addattr_l(n, size, IFLA_VRF_TABLE, &table, sizeof(table));
580}
581
528#ifndef NLMSG_TAIL 582#ifndef NLMSG_TAIL
529#define NLMSG_TAIL(nmsg) \ 583#define NLMSG_TAIL(nmsg) \
530 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 584 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
@@ -563,6 +617,8 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
563 if (rtm == RTM_NEWLINK) 617 if (rtm == RTM_NEWLINK)
564 req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; 618 req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
565 619
620 /* NB: update iplink_full_usage if you extend this code */
621
566 while (*argv) { 622 while (*argv) {
567 arg = index_in_substrings(keywords, *argv); 623 arg = index_in_substrings(keywords, *argv);
568 if (arg == ARG_type) { 624 if (arg == ARG_type) {
@@ -582,7 +638,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
582 } else if (arg == ARG_address) { 638 } else if (arg == ARG_address) {
583 NEXT_ARG(); 639 NEXT_ARG();
584 address_str = *argv; 640 address_str = *argv;
585 dbg("address_str:'%s'", name_str); 641 dbg("address_str:'%s'", address_str);
586 } else { 642 } else {
587 if (arg == ARG_dev) { 643 if (arg == ARG_dev) {
588 if (dev_str) 644 if (dev_str)
@@ -609,6 +665,8 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
609 665
610 if (strcmp(type_str, "vlan") == 0) 666 if (strcmp(type_str, "vlan") == 0)
611 vlan_parse_opt(argv, &req.n, sizeof(req)); 667 vlan_parse_opt(argv, &req.n, sizeof(req));
668 else if (strcmp(type_str, "vrf") == 0)
669 vrf_parse_opt(argv, &req.n, sizeof(req));
612 670
613 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; 671 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
614 } 672 }
@@ -651,6 +709,8 @@ int FAST_FUNC do_iplink(char **argv)
651{ 709{
652 static const char keywords[] ALIGN1 = 710 static const char keywords[] ALIGN1 =
653 "add\0""delete\0""set\0""show\0""lst\0""list\0"; 711 "add\0""delete\0""set\0""show\0""lst\0""list\0";
712
713 xfunc_error_retval = 2; //TODO: move up to "ip"? Is it the common rule for all "ip" tools?
654 if (*argv) { 714 if (*argv) {
655 int key = index_in_substrings(keywords, *argv); 715 int key = index_in_substrings(keywords, *argv);
656 if (key < 0) /* invalid argument */ 716 if (key < 0) /* invalid argument */
diff --git a/networking/ping.c b/networking/ping.c
index d1d59d545..8f85d3ec2 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -74,6 +74,7 @@
74//usage: ) 74//usage: )
75//usage: "\n -c CNT Send only CNT pings" 75//usage: "\n -c CNT Send only CNT pings"
76//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" 76//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
77//usage: "\n -A Ping as soon as reply is recevied"
77//usage: "\n -t TTL Set TTL" 78//usage: "\n -t TTL Set TTL"
78//usage: "\n -I IFACE/IP Source interface or IP address" 79//usage: "\n -I IFACE/IP Source interface or IP address"
79//usage: "\n -W SEC Seconds to wait for the first response (default 10)" 80//usage: "\n -W SEC Seconds to wait for the first response (default 10)"
@@ -90,6 +91,7 @@
90//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" 91//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n"
91//usage: "\n -c CNT Send only CNT pings" 92//usage: "\n -c CNT Send only CNT pings"
92//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" 93//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
94//usage: "\n -A Ping as soon as reply is recevied"
93//usage: "\n -I IFACE/IP Source interface or IP address" 95//usage: "\n -I IFACE/IP Source interface or IP address"
94//usage: "\n -q Quiet, only display output at start" 96//usage: "\n -q Quiet, only display output at start"
95//usage: "\n and when finished" 97//usage: "\n and when finished"
@@ -348,20 +350,21 @@ static int common_ping_main(sa_family_t af, char **argv)
348/* Full(er) version */ 350/* Full(er) version */
349 351
350/* -c NUM, -t NUM, -w NUM, -W NUM */ 352/* -c NUM, -t NUM, -w NUM, -W NUM */
351#define OPT_STRING "qvc:+s:t:+w:+W:+I:np:4"IF_PING6("6") 353#define OPT_STRING "qvAc:+s:t:+w:+W:+I:np:4"IF_PING6("6")
352enum { 354enum {
353 OPT_QUIET = 1 << 0, 355 OPT_QUIET = 1 << 0,
354 OPT_VERBOSE = 1 << 1, 356 OPT_VERBOSE = 1 << 1,
355 OPT_c = 1 << 2, 357 OPT_A = 1 << 2,
356 OPT_s = 1 << 3, 358 OPT_c = 1 << 3,
357 OPT_t = 1 << 4, 359 OPT_s = 1 << 4,
358 OPT_w = 1 << 5, 360 OPT_t = 1 << 5,
359 OPT_W = 1 << 6, 361 OPT_w = 1 << 6,
360 OPT_I = 1 << 7, 362 OPT_W = 1 << 7,
361 /*OPT_n = 1 << 8, - ignored */ 363 OPT_I = 1 << 8,
362 OPT_p = 1 << 9, 364 /*OPT_n = 1 << 9, - ignored */
363 OPT_IPV4 = 1 << 10, 365 OPT_p = 1 << 10,
364 OPT_IPV6 = (1 << 11) * ENABLE_PING6, 366 OPT_IPV4 = 1 << 11,
367 OPT_IPV6 = (1 << 12) * ENABLE_PING6,
365}; 368};
366 369
367 370
@@ -377,9 +380,9 @@ struct globals {
377 uint8_t pattern; 380 uint8_t pattern;
378 unsigned tmin, tmax; /* in us */ 381 unsigned tmin, tmax; /* in us */
379 unsigned long long tsum; /* in us, sum of all times */ 382 unsigned long long tsum; /* in us, sum of all times */
380 unsigned deadline; 383 unsigned cur_us; /* low word only, we don't need more */
384 unsigned deadline_us;
381 unsigned timeout; 385 unsigned timeout;
382 unsigned total_secs;
383 unsigned sizeof_rcv_packet; 386 unsigned sizeof_rcv_packet;
384 char *rcv_packet; /* [datalen + MAXIPLEN + MAXICMPLEN] */ 387 char *rcv_packet; /* [datalen + MAXIPLEN + MAXICMPLEN] */
385 void *snd_packet; /* [datalen + ipv4/ipv6_const] */ 388 void *snd_packet; /* [datalen + ipv4/ipv6_const] */
@@ -405,9 +408,7 @@ struct globals {
405#define tmin (G.tmin ) 408#define tmin (G.tmin )
406#define tmax (G.tmax ) 409#define tmax (G.tmax )
407#define tsum (G.tsum ) 410#define tsum (G.tsum )
408#define deadline (G.deadline )
409#define timeout (G.timeout ) 411#define timeout (G.timeout )
410#define total_secs (G.total_secs )
411#define hostname (G.hostname ) 412#define hostname (G.hostname )
412#define dotted (G.dotted ) 413#define dotted (G.dotted )
413#define pingaddr (G.pingaddr ) 414#define pingaddr (G.pingaddr )
@@ -455,7 +456,7 @@ static void print_stats_and_exit(int junk UNUSED_PARAM)
455 tmax / 1000, tmax % 1000); 456 tmax / 1000, tmax % 1000);
456 } 457 }
457 /* if condition is true, exit with 1 -- 'failure' */ 458 /* if condition is true, exit with 1 -- 'failure' */
458 exit(nrecv == 0 || (deadline && nrecv < pingcount)); 459 exit(nrecv == 0 || (G.deadline_us && nrecv < pingcount));
459} 460}
460 461
461static void sendping_tail(void (*sp)(int), int size_pkt) 462static void sendping_tail(void (*sp)(int), int size_pkt)
@@ -467,22 +468,23 @@ static void sendping_tail(void (*sp)(int), int size_pkt)
467 468
468 size_pkt += datalen; 469 size_pkt += datalen;
469 470
471 if (G.deadline_us) {
472 unsigned n = G.cur_us - G.deadline_us;
473 if ((int)n >= 0)
474 print_stats_and_exit(0);
475 }
476
470 /* sizeof(pingaddr) can be larger than real sa size, but I think 477 /* sizeof(pingaddr) can be larger than real sa size, but I think
471 * it doesn't matter */ 478 * it doesn't matter */
472 sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr)); 479 sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr));
473 if (sz != size_pkt) 480 if (sz != size_pkt)
474 bb_error_msg_and_die(bb_msg_write_error); 481 bb_error_msg_and_die(bb_msg_write_error);
475 482
476 if (pingcount == 0 || deadline || G.ntransmitted < pingcount) { 483 if (pingcount == 0 || G.ntransmitted < pingcount) {
477 /* Didn't send all pings yet - schedule next in 1s */ 484 /* Didn't send all pings yet - schedule next in 1s */
478 signal(SIGALRM, sp); 485 signal(SIGALRM, sp);
479 if (deadline) {
480 total_secs += PINGINTERVAL;
481 if (total_secs >= deadline)
482 signal(SIGALRM, print_stats_and_exit);
483 }
484 alarm(PINGINTERVAL); 486 alarm(PINGINTERVAL);
485 } else { /* -c NN, and all NN are sent (and no deadline) */ 487 } else { /* -c NN, and all NN are sent */
486 /* Wait for the last ping to come back. 488 /* Wait for the last ping to come back.
487 * -W timeout: wait for a response in seconds. 489 * -W timeout: wait for a response in seconds.
488 * Affects only timeout in absence of any responses, 490 * Affects only timeout in absence of any responses,
@@ -516,7 +518,7 @@ static void sendping4(int junk UNUSED_PARAM)
516 */ 518 */
517 /*if (datalen >= 4)*/ 519 /*if (datalen >= 4)*/
518 /* No hton: we'll read it back on the same machine */ 520 /* No hton: we'll read it back on the same machine */
519 *(uint32_t*)&pkt->icmp_dun = monotonic_us(); 521 *(uint32_t*)&pkt->icmp_dun = G.cur_us = monotonic_us();
520 522
521 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, datalen + ICMP_MINLEN); 523 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, datalen + ICMP_MINLEN);
522 524
@@ -535,7 +537,7 @@ static void sendping6(int junk UNUSED_PARAM)
535 pkt->icmp6_id = myid; 537 pkt->icmp6_id = myid;
536 538
537 /*if (datalen >= 4)*/ 539 /*if (datalen >= 4)*/
538 *(bb__aliased_uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); 540 *(bb__aliased_uint32_t*)(&pkt->icmp6_data8[4]) = G.cur_us = monotonic_us();
539 541
540 //TODO? pkt->icmp_cksum = inet_cksum(...); 542 //TODO? pkt->icmp_cksum = inet_cksum(...);
541 543
@@ -632,7 +634,7 @@ static void unpack_tail(int sz, uint32_t *tp,
632 puts(dupmsg); 634 puts(dupmsg);
633 fflush_all(); 635 fflush_all();
634} 636}
635static void unpack4(char *buf, int sz, struct sockaddr_in *from) 637static int unpack4(char *buf, int sz, struct sockaddr_in *from)
636{ 638{
637 struct icmp *icmppkt; 639 struct icmp *icmppkt;
638 struct iphdr *iphdr; 640 struct iphdr *iphdr;
@@ -640,7 +642,7 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from)
640 642
641 /* discard if too short */ 643 /* discard if too short */
642 if (sz < (datalen + ICMP_MINLEN)) 644 if (sz < (datalen + ICMP_MINLEN))
643 return; 645 return 0;
644 646
645 /* check IP header */ 647 /* check IP header */
646 iphdr = (struct iphdr *) buf; 648 iphdr = (struct iphdr *) buf;
@@ -648,7 +650,7 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from)
648 sz -= hlen; 650 sz -= hlen;
649 icmppkt = (struct icmp *) (buf + hlen); 651 icmppkt = (struct icmp *) (buf + hlen);
650 if (icmppkt->icmp_id != myid) 652 if (icmppkt->icmp_id != myid)
651 return; /* not our ping */ 653 return 0; /* not our ping */
652 654
653 if (icmppkt->icmp_type == ICMP_ECHOREPLY) { 655 if (icmppkt->icmp_type == ICMP_ECHOREPLY) {
654 uint16_t recv_seq = ntohs(icmppkt->icmp_seq); 656 uint16_t recv_seq = ntohs(icmppkt->icmp_seq);
@@ -659,25 +661,28 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from)
659 unpack_tail(sz, tp, 661 unpack_tail(sz, tp,
660 inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), 662 inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
661 recv_seq, iphdr->ttl); 663 recv_seq, iphdr->ttl);
662 } else if (icmppkt->icmp_type != ICMP_ECHO) { 664 return 1;
665 }
666 if (icmppkt->icmp_type != ICMP_ECHO) {
663 bb_error_msg("warning: got ICMP %d (%s)", 667 bb_error_msg("warning: got ICMP %d (%s)",
664 icmppkt->icmp_type, 668 icmppkt->icmp_type,
665 icmp_type_name(icmppkt->icmp_type)); 669 icmp_type_name(icmppkt->icmp_type));
666 } 670 }
671 return 0;
667} 672}
668#if ENABLE_PING6 673#if ENABLE_PING6
669static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit) 674static int unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit)
670{ 675{
671 struct icmp6_hdr *icmppkt; 676 struct icmp6_hdr *icmppkt;
672 char buf[INET6_ADDRSTRLEN]; 677 char buf[INET6_ADDRSTRLEN];
673 678
674 /* discard if too short */ 679 /* discard if too short */
675 if (sz < (datalen + sizeof(struct icmp6_hdr))) 680 if (sz < (datalen + sizeof(struct icmp6_hdr)))
676 return; 681 return 0;
677 682
678 icmppkt = (struct icmp6_hdr *) packet; 683 icmppkt = (struct icmp6_hdr *) packet;
679 if (icmppkt->icmp6_id != myid) 684 if (icmppkt->icmp6_id != myid)
680 return; /* not our ping */ 685 return 0; /* not our ping */
681 686
682 if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) { 687 if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) {
683 uint16_t recv_seq = ntohs(icmppkt->icmp6_seq); 688 uint16_t recv_seq = ntohs(icmppkt->icmp6_seq);
@@ -689,11 +694,14 @@ static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimi
689 inet_ntop(AF_INET6, &from->sin6_addr, 694 inet_ntop(AF_INET6, &from->sin6_addr,
690 buf, sizeof(buf)), 695 buf, sizeof(buf)),
691 recv_seq, hoplimit); 696 recv_seq, hoplimit);
692 } else if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) { 697 return 1;
698 }
699 if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) {
693 bb_error_msg("warning: got ICMP %d (%s)", 700 bb_error_msg("warning: got ICMP %d (%s)",
694 icmppkt->icmp6_type, 701 icmppkt->icmp6_type,
695 icmp6_type_name(icmppkt->icmp6_type)); 702 icmp6_type_name(icmppkt->icmp6_type));
696 } 703 }
704 return 0;
697} 705}
698#endif 706#endif
699 707
@@ -726,6 +734,7 @@ static void ping4(len_and_sockaddr *lsa)
726 signal(SIGINT, print_stats_and_exit); 734 signal(SIGINT, print_stats_and_exit);
727 735
728 /* start the ping's going ... */ 736 /* start the ping's going ... */
737 send_ping:
729 sendping4(0); 738 sendping4(0);
730 739
731 /* listen for replies */ 740 /* listen for replies */
@@ -741,9 +750,12 @@ static void ping4(len_and_sockaddr *lsa)
741 bb_perror_msg("recvfrom"); 750 bb_perror_msg("recvfrom");
742 continue; 751 continue;
743 } 752 }
744 unpack4(G.rcv_packet, c, &from); 753 c = unpack4(G.rcv_packet, c, &from);
745 if (pingcount && G.nreceived >= pingcount) 754 if (pingcount && G.nreceived >= pingcount)
746 break; 755 break;
756 if (c && (option_mask32 & OPT_A)) {
757 goto send_ping;
758 }
747 } 759 }
748} 760}
749#if ENABLE_PING6 761#if ENABLE_PING6
@@ -794,10 +806,6 @@ static void ping6(len_and_sockaddr *lsa)
794 806
795 signal(SIGINT, print_stats_and_exit); 807 signal(SIGINT, print_stats_and_exit);
796 808
797 /* start the ping's going ... */
798 sendping6(0);
799
800 /* listen for replies */
801 msg.msg_name = &from; 809 msg.msg_name = &from;
802 msg.msg_namelen = sizeof(from); 810 msg.msg_namelen = sizeof(from);
803 msg.msg_iov = &iov; 811 msg.msg_iov = &iov;
@@ -805,12 +813,18 @@ static void ping6(len_and_sockaddr *lsa)
805 msg.msg_control = control_buf; 813 msg.msg_control = control_buf;
806 iov.iov_base = G.rcv_packet; 814 iov.iov_base = G.rcv_packet;
807 iov.iov_len = G.sizeof_rcv_packet; 815 iov.iov_len = G.sizeof_rcv_packet;
816
817 /* start the ping's going ... */
818 send_ping:
819 sendping6(0);
820
821 /* listen for replies */
808 while (1) { 822 while (1) {
809 int c; 823 int c;
810 struct cmsghdr *mp; 824 struct cmsghdr *mp;
811 int hoplimit = -1; 825 int hoplimit = -1;
812 msg.msg_controllen = sizeof(control_buf);
813 826
827 msg.msg_controllen = sizeof(control_buf);
814 c = recvmsg(pingsock, &msg, 0); 828 c = recvmsg(pingsock, &msg, 0);
815 if (c < 0) { 829 if (c < 0) {
816 if (errno != EINTR) 830 if (errno != EINTR)
@@ -827,9 +841,12 @@ static void ping6(len_and_sockaddr *lsa)
827 move_from_unaligned_int(hoplimit, CMSG_DATA(mp)); 841 move_from_unaligned_int(hoplimit, CMSG_DATA(mp));
828 } 842 }
829 } 843 }
830 unpack6(G.rcv_packet, c, &from, hoplimit); 844 c = unpack6(G.rcv_packet, c, &from, hoplimit);
831 if (pingcount && G.nreceived >= pingcount) 845 if (pingcount && G.nreceived >= pingcount)
832 break; 846 break;
847 if (c && (option_mask32 & OPT_A)) {
848 goto send_ping;
849 }
833 } 850 }
834} 851}
835#endif 852#endif
@@ -875,7 +892,7 @@ static int common_ping_main(int opt, char **argv)
875 OPT_STRING 892 OPT_STRING
876 /* exactly one arg; -v and -q don't mix */ 893 /* exactly one arg; -v and -q don't mix */
877 "\0" "=1:q--v:v--q", 894 "\0" "=1:q--v:v--q",
878 &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p 895 &pingcount, &str_s, &opt_ttl, &G.deadline_us, &timeout, &str_I, &str_p
879 ); 896 );
880 if (opt & OPT_s) 897 if (opt & OPT_s)
881 datalen = xatou16(str_s); // -s 898 datalen = xatou16(str_s); // -s
@@ -889,6 +906,10 @@ static int common_ping_main(int opt, char **argv)
889 } 906 }
890 if (opt & OPT_p) 907 if (opt & OPT_p)
891 G.pattern = xstrtou_range(str_p, 16, 0, 255); 908 G.pattern = xstrtou_range(str_p, 16, 0, 255);
909 if (G.deadline_us) {
910 unsigned d = G.deadline_us < INT_MAX/1000000 ? G.deadline_us : INT_MAX/1000000;
911 G.deadline_us = 1 | ((d * 1000000) + monotonic_us());
912 }
892 913
893 myid = (uint16_t) getpid(); 914 myid = (uint16_t) getpid();
894 hostname = argv[optind]; 915 hostname = argv[optind];
@@ -911,7 +932,7 @@ static int common_ping_main(int opt, char **argv)
911 932
912 dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); 933 dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
913 ping(lsa); 934 ping(lsa);
914 print_stats_and_exit(EXIT_SUCCESS); 935 print_stats_and_exit(0);
915 /*return EXIT_SUCCESS;*/ 936 /*return EXIT_SUCCESS;*/
916} 937}
917#endif /* FEATURE_FANCY_PING */ 938#endif /* FEATURE_FANCY_PING */
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index d4c69e0f7..a90e3f80a 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -127,6 +127,7 @@ struct globals {
127 unsigned cur_per_host; 127 unsigned cur_per_host;
128 unsigned cnum; 128 unsigned cnum;
129 unsigned cmax; 129 unsigned cmax;
130 struct hcc *cc;
130 char **env_cur; 131 char **env_cur;
131 char *env_var[1]; /* actually bigger */ 132 char *env_var[1]; /* actually bigger */
132} FIX_ALIASING; 133} FIX_ALIASING;
@@ -229,7 +230,7 @@ static void sig_child_handler(int sig UNUSED_PARAM)
229 230
230 while ((pid = wait_any_nohang(&wstat)) > 0) { 231 while ((pid = wait_any_nohang(&wstat)) > 0) {
231 if (max_per_host) 232 if (max_per_host)
232 ipsvd_perhost_remove(pid); 233 ipsvd_perhost_remove(G.cc, pid);
233 if (cnum) 234 if (cnum)
234 cnum--; 235 cnum--;
235 if (verbose) 236 if (verbose)
@@ -318,7 +319,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
318 sslser = user; 319 sslser = user;
319 client = 0; 320 client = 0;
320 if ((getuid() == 0) && !(opts & OPT_u)) { 321 if ((getuid() == 0) && !(opts & OPT_u)) {
321 xfunc_exitcode = 100; 322 xfunc_error_retval = 100;
322 bb_error_msg_and_die(bb_msg_you_must_be_root); 323 bb_error_msg_and_die(bb_msg_you_must_be_root);
323 } 324 }
324 if (opts & OPT_u) 325 if (opts & OPT_u)
@@ -347,7 +348,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
347 signal(SIGPIPE, SIG_IGN); 348 signal(SIGPIPE, SIG_IGN);
348 349
349 if (max_per_host) 350 if (max_per_host)
350 ipsvd_perhost_init(cmax); 351 G.cc = ipsvd_perhost_init(cmax);
351 352
352 local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0); 353 local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0);
353 lsa = xhost2sockaddr(argv[0], local_port); 354 lsa = xhost2sockaddr(argv[0], local_port);
@@ -422,7 +423,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
422 /* Drop connection immediately if cur_per_host > max_per_host 423 /* Drop connection immediately if cur_per_host > max_per_host
423 * (minimizing load under SYN flood) */ 424 * (minimizing load under SYN flood) */
424 remote_addr = xmalloc_sockaddr2dotted_noport(&remote.u.sa); 425 remote_addr = xmalloc_sockaddr2dotted_noport(&remote.u.sa);
425 cur_per_host = ipsvd_perhost_add(remote_addr, max_per_host, &hccp); 426 cur_per_host = ipsvd_perhost_add(G.cc, remote_addr, max_per_host, &hccp);
426 if (cur_per_host > max_per_host) { 427 if (cur_per_host > max_per_host) {
427 /* ipsvd_perhost_add detected that max is exceeded 428 /* ipsvd_perhost_add detected that max is exceeded
428 * (and did not store ip in connection table) */ 429 * (and did not store ip in connection table) */
diff --git a/networking/tcpudp_perhost.c b/networking/tcpudp_perhost.c
index 105410883..2643f8d16 100644
--- a/networking/tcpudp_perhost.c
+++ b/networking/tcpudp_perhost.c
@@ -10,25 +10,21 @@
10#include "libbb.h" 10#include "libbb.h"
11#include "tcpudp_perhost.h" 11#include "tcpudp_perhost.h"
12 12
13static struct hcc *cc; 13struct hcc* FAST_FUNC ipsvd_perhost_init(unsigned c)
14static unsigned cclen;
15
16/* to be optimized */
17
18void ipsvd_perhost_init(unsigned c)
19{ 14{
20// free(cc); 15// free(cc);
21 cc = xzalloc(c * sizeof(*cc)); 16 struct hcc *cc = xzalloc((c + 1) * sizeof(*cc));
22 cclen = c; 17 cc[c].pid = -1; /* "end" marker */
18 return cc;
23} 19}
24 20
25unsigned ipsvd_perhost_add(char *ip, unsigned maxconn, struct hcc **hccpp) 21unsigned FAST_FUNC ipsvd_perhost_add(struct hcc *cc, char *ip, unsigned maxconn, struct hcc **hccpp)
26{ 22{
27 unsigned i; 23 unsigned i;
28 unsigned conn = 1; 24 unsigned conn = 1;
29 int freepos = -1; 25 int freepos = -1;
30 26
31 for (i = 0; i < cclen; ++i) { 27 for (i = 0; cc[i].pid >= 0; ++i) {
32 if (!cc[i].ip) { 28 if (!cc[i].ip) {
33 freepos = i; 29 freepos = i;
34 continue; 30 continue;
@@ -46,10 +42,10 @@ unsigned ipsvd_perhost_add(char *ip, unsigned maxconn, struct hcc **hccpp)
46 return conn; 42 return conn;
47} 43}
48 44
49void ipsvd_perhost_remove(int pid) 45void FAST_FUNC ipsvd_perhost_remove(struct hcc *cc, int pid)
50{ 46{
51 unsigned i; 47 unsigned i;
52 for (i = 0; i < cclen; ++i) { 48 for (i = 0; cc[i].pid >= 0; ++i) {
53 if (cc[i].pid == pid) { 49 if (cc[i].pid == pid) {
54 free(cc[i].ip); 50 free(cc[i].ip);
55 cc[i].ip = NULL; 51 cc[i].ip = NULL;
@@ -59,7 +55,7 @@ void ipsvd_perhost_remove(int pid)
59 } 55 }
60} 56}
61 57
62//void ipsvd_perhost_free(void) 58//void ipsvd_perhost_free(struct hcc *cc)
63//{ 59//{
64// free(cc); 60// free(cc);
65//} 61//}
diff --git a/networking/tcpudp_perhost.h b/networking/tcpudp_perhost.h
index 3e5757678..3b14d9a57 100644
--- a/networking/tcpudp_perhost.h
+++ b/networking/tcpudp_perhost.h
@@ -14,7 +14,7 @@ struct hcc {
14 int pid; 14 int pid;
15}; 15};
16 16
17void ipsvd_perhost_init(unsigned); 17struct hcc* FAST_FUNC ipsvd_perhost_init(unsigned);
18 18
19/* Returns number of already opened connects to this ips, including this one. 19/* Returns number of already opened connects to this ips, including this one.
20 * ip should be a malloc'ed ptr. 20 * ip should be a malloc'ed ptr.
@@ -22,12 +22,12 @@ void ipsvd_perhost_init(unsigned);
22 * and pointer to table entry if stored in *hccpp 22 * and pointer to table entry if stored in *hccpp
23 * (useful for storing pid later). 23 * (useful for storing pid later).
24 * Else ip is NOT inserted (you must take care of it - free() etc) */ 24 * Else ip is NOT inserted (you must take care of it - free() etc) */
25unsigned ipsvd_perhost_add(char *ip, unsigned maxconn, struct hcc **hccpp); 25unsigned FAST_FUNC ipsvd_perhost_add(struct hcc *cc, char *ip, unsigned maxconn, struct hcc **hccpp);
26 26
27/* Finds and frees element with pid */ 27/* Finds and frees element with pid */
28void ipsvd_perhost_remove(int pid); 28void FAST_FUNC ipsvd_perhost_remove(struct hcc *cc, int pid);
29 29
30//unsigned ipsvd_perhost_setpid(int pid); 30//unsigned ipsvd_perhost_setpid(int pid);
31//void ipsvd_perhost_free(void); 31//void ipsvd_perhost_free(struct hcc *cc);
32 32
33POP_SAVED_FUNCTION_VISIBILITY 33POP_SAVED_FUNCTION_VISIBILITY
diff --git a/networking/tls.c b/networking/tls.c
index da7b6058f..99722cfb4 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -806,8 +806,6 @@ static int tls_xread_record(tls_state_t *tls, const char *expected)
806 || xhdr->proto_min != TLS_MIN 806 || xhdr->proto_min != TLS_MIN
807 ) { 807 ) {
808 sz = total < target ? total : target; 808 sz = total < target ? total : target;
809 if (sz > 24)
810 sz = 24; /* don't flood */
811 bad_record_die(tls, expected, sz); 809 bad_record_die(tls, expected, sz);
812 } 810 }
813 dbg("xhdr type:%d ver:%d.%d len:%d\n", 811 dbg("xhdr type:%d ver:%d.%d len:%d\n",