diff options
author | Ron Yorston <rmy@pobox.com> | 2020-01-08 12:30:49 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-01-08 12:30:49 +0000 |
commit | a9271a8e97e6e7be5285330d5f19352decabf807 (patch) | |
tree | bf3c4464c369a15a46454792dac167505f74769f /networking | |
parent | b0b7ab792bc1f45963f4b84b94faaf05054e1613 (diff) | |
parent | 9ec836c033fc6e55e80f3309b3e05acdf09bb297 (diff) | |
download | busybox-w32-a9271a8e97e6e7be5285330d5f19352decabf807.tar.gz busybox-w32-a9271a8e97e6e7be5285330d5f19352decabf807.tar.bz2 busybox-w32-a9271a8e97e6e7be5285330d5f19352decabf807.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r-- | networking/brctl.c | 614 | ||||
-rw-r--r-- | networking/netstat.c | 2 | ||||
-rw-r--r-- | networking/nslookup.c | 28 | ||||
-rw-r--r-- | networking/ntpd.c | 10 | ||||
-rw-r--r-- | networking/route.c | 1 | ||||
-rw-r--r-- | networking/tc.c | 2 | ||||
-rw-r--r-- | networking/telnet.c | 14 | ||||
-rw-r--r-- | networking/tls_aesgcm.c | 2 | ||||
-rw-r--r-- | networking/traceroute.c | 10 | ||||
-rw-r--r-- | networking/udhcp/common.c | 2 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 99 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 4 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.h | 4 | ||||
-rw-r--r-- | networking/wget.c | 2 | ||||
-rw-r--r-- | networking/whois.c | 4 |
15 files changed, 596 insertions, 202 deletions
diff --git a/networking/brctl.c b/networking/brctl.c index 586ca9b0c..25640246d 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -53,7 +53,9 @@ | |||
53 | //usage: "\n addif BRIDGE IFACE Add IFACE to BRIDGE" | 53 | //usage: "\n addif BRIDGE IFACE Add IFACE to BRIDGE" |
54 | //usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE" | 54 | //usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE" |
55 | //usage: IF_FEATURE_BRCTL_FANCY( | 55 | //usage: IF_FEATURE_BRCTL_FANCY( |
56 | //usage: "\n stp BRIDGE 1/yes/on|0/no/off STP on/off" | 56 | //usage: "\n showmacs BRIDGE List MAC addresses" |
57 | //usage: "\n showstp BRIDGE Show STP info" | ||
58 | //usage: "\n stp BRIDGE 1/yes/on|0/no/off Set STP on/off" | ||
57 | //usage: "\n setageing BRIDGE SECONDS Set ageing time" | 59 | //usage: "\n setageing BRIDGE SECONDS Set ageing time" |
58 | //usage: "\n setfd BRIDGE SECONDS Set bridge forward delay" | 60 | //usage: "\n setfd BRIDGE SECONDS Set bridge forward delay" |
59 | //usage: "\n sethello BRIDGE SECONDS Set hello time" | 61 | //usage: "\n sethello BRIDGE SECONDS Set hello time" |
@@ -63,9 +65,7 @@ | |||
63 | //usage: "\n setpathcost BRIDGE IFACE COST Set path cost" | 65 | //usage: "\n setpathcost BRIDGE IFACE COST Set path cost" |
64 | //usage: ) | 66 | //usage: ) |
65 | // Not yet implemented: | 67 | // Not yet implemented: |
66 | // hairpin BRIDGE IFACE on|off Hairpin on/off | 68 | // hairpin BRIDGE IFACE on|off Set hairpin on/off |
67 | // showmacs BRIDGE List mac addrs | ||
68 | // showstp BRIDGE Show stp info | ||
69 | 69 | ||
70 | #include "libbb.h" | 70 | #include "libbb.h" |
71 | #include "common_bufsiz.h" | 71 | #include "common_bufsiz.h" |
@@ -129,7 +129,7 @@ static int show_bridge(const char *name, int need_hdr) | |||
129 | *bridge name bridge id STP enabled interfaces | 129 | *bridge name bridge id STP enabled interfaces |
130 | *br0 8000.000000000000 no eth0 | 130 | *br0 8000.000000000000 no eth0 |
131 | */ | 131 | */ |
132 | char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32]; | 132 | char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 8]; |
133 | int tabs; | 133 | int tabs; |
134 | DIR *ifaces; | 134 | DIR *ifaces; |
135 | struct dirent *ent; | 135 | struct dirent *ent; |
@@ -146,8 +146,7 @@ static int show_bridge(const char *name, int need_hdr) | |||
146 | 146 | ||
147 | if (need_hdr) | 147 | if (need_hdr) |
148 | puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); | 148 | puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); |
149 | printf("%s\t\t", name); | 149 | printf("%s\t\t%s\t", name, filedata); |
150 | printf("%s\t", filedata); | ||
151 | 150 | ||
152 | strcpy(sfx, "stp_state"); | 151 | strcpy(sfx, "stp_state"); |
153 | read_file(pathbuf); | 152 | read_file(pathbuf); |
@@ -158,7 +157,8 @@ static int show_bridge(const char *name, int need_hdr) | |||
158 | strcpy(filedata, "yes"); | 157 | strcpy(filedata, "yes"); |
159 | fputs(filedata, stdout); | 158 | fputs(filedata, stdout); |
160 | 159 | ||
161 | strcpy(sfx - (sizeof("bridge/")-1), "brif"); | 160 | /* sfx points past "BR/bridge/", turn it into "BR/brif": */ |
161 | sfx[-4] = 'f'; sfx[-3] = '\0'; | ||
162 | tabs = 0; | 162 | tabs = 0; |
163 | ifaces = opendir(pathbuf); | 163 | ifaces = opendir(pathbuf); |
164 | if (ifaces) { | 164 | if (ifaces) { |
@@ -194,7 +194,299 @@ static void write_uint(const char *name, const char *leaf, unsigned val) | |||
194 | n = sprintf(filedata, "%u\n", val); | 194 | n = sprintf(filedata, "%u\n", val); |
195 | if (write(fd, filedata, n) < 0) | 195 | if (write(fd, filedata, n) < 0) |
196 | bb_simple_perror_msg_and_die(name); | 196 | bb_simple_perror_msg_and_die(name); |
197 | close(fd); | 197 | /* So far all callers exit very soon after calling us. |
198 | * Do not bother closing fd (unless debugging): | ||
199 | */ | ||
200 | if (ENABLE_FEATURE_CLEAN_UP) | ||
201 | close(fd); | ||
202 | } | ||
203 | |||
204 | struct fdb_entry { | ||
205 | uint8_t mac_addr[6]; | ||
206 | uint8_t port_no; | ||
207 | uint8_t is_local; | ||
208 | uint32_t ageing_timer_value; | ||
209 | uint8_t port_hi; | ||
210 | uint8_t pad0; | ||
211 | uint16_t unused; | ||
212 | }; | ||
213 | |||
214 | static int compare_fdbs(const void *_f0, const void *_f1) | ||
215 | { | ||
216 | const struct fdb_entry *f0 = _f0; | ||
217 | const struct fdb_entry *f1 = _f1; | ||
218 | |||
219 | return memcmp(f0->mac_addr, f1->mac_addr, 6); | ||
220 | } | ||
221 | |||
222 | static size_t read_bridge_forward_db(const char *name, struct fdb_entry **_fdb) | ||
223 | { | ||
224 | char pathbuf[IFNAMSIZ + sizeof("/brforward") + 8]; | ||
225 | struct fdb_entry *fdb; | ||
226 | size_t nentries; | ||
227 | int fd; | ||
228 | ssize_t cc; | ||
229 | |||
230 | #if IFNAMSIZ == 16 | ||
231 | sprintf(pathbuf, "%.16s/brforward", name); | ||
232 | #else | ||
233 | sprintf(pathbuf, "%.*s/brforward", (int)IFNAMSIZ, name); | ||
234 | #endif | ||
235 | fd = open(pathbuf, O_RDONLY); | ||
236 | if (fd < 0) | ||
237 | bb_error_msg_and_die("bridge %s does not exist", name); | ||
238 | |||
239 | fdb = NULL; | ||
240 | nentries = 0; | ||
241 | for (;;) { | ||
242 | fdb = xrealloc_vector(fdb, 4, nentries); | ||
243 | cc = full_read(fd, &fdb[nentries], sizeof(*fdb)); | ||
244 | if (cc == 0) { | ||
245 | break; | ||
246 | } | ||
247 | if (cc != sizeof(*fdb)) { | ||
248 | bb_perror_msg_and_die("can't read bridge %s forward db", name); | ||
249 | } | ||
250 | ++nentries; | ||
251 | } | ||
252 | |||
253 | if (ENABLE_FEATURE_CLEAN_UP) | ||
254 | close(fd); | ||
255 | |||
256 | qsort(fdb, nentries, sizeof(*fdb), compare_fdbs); | ||
257 | |||
258 | *_fdb = fdb; | ||
259 | return nentries; | ||
260 | } | ||
261 | |||
262 | static void show_bridge_macs(const char *name) | ||
263 | { | ||
264 | struct fdb_entry *fdb; | ||
265 | size_t nentries; | ||
266 | size_t i; | ||
267 | |||
268 | nentries = read_bridge_forward_db(name, &fdb); | ||
269 | |||
270 | printf("port no\tmac addr\t\tis local?\tageing timer\n"); | ||
271 | for (i = 0; i < nentries; ++i) { | ||
272 | const struct fdb_entry *f = &fdb[i]; | ||
273 | unsigned tv_sec = f->ageing_timer_value / 100; | ||
274 | unsigned tv_csec = f->ageing_timer_value % 100; | ||
275 | printf("%3u\t" | ||
276 | "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t" | ||
277 | "%s\t\t" | ||
278 | "%4u.%.2u\n", | ||
279 | f->port_no, | ||
280 | f->mac_addr[0], f->mac_addr[1], f->mac_addr[2], | ||
281 | f->mac_addr[3], f->mac_addr[4], f->mac_addr[5], | ||
282 | (f->is_local ? "yes" : "no"), | ||
283 | tv_sec, tv_csec | ||
284 | ); | ||
285 | } | ||
286 | |||
287 | if (ENABLE_FEATURE_CLEAN_UP) | ||
288 | free(fdb); | ||
289 | } | ||
290 | |||
291 | static void show_bridge_timer(const char *msg) | ||
292 | { | ||
293 | unsigned long long centisec = xstrtoull(filedata, 0); | ||
294 | unsigned tv_sec = centisec / 100; | ||
295 | unsigned tv_csec = centisec % 100; | ||
296 | printf("%s%4u.%.2u", msg, tv_sec, tv_csec); | ||
297 | } | ||
298 | |||
299 | static const char *show_bridge_state(unsigned state) | ||
300 | { | ||
301 | /* See linux/if_bridge.h, BR_STATE_ constants */ | ||
302 | static const char state_names[] ALIGN1 = | ||
303 | "disabled\0" //BR_STATE_DISABLED 0 | ||
304 | "listening\0" //BR_STATE_LISTENING 1 | ||
305 | "learning\0" //BR_STATE_LEARNING 2 | ||
306 | "forwarding\0" //BR_STATE_FORWARDING 3 | ||
307 | "blocking" //BR_STATE_BLOCKING 4 | ||
308 | ; | ||
309 | if (state < 5) | ||
310 | return nth_string(state_names, state); | ||
311 | return utoa(state); | ||
312 | } | ||
313 | |||
314 | static void printf_xstrtou(const char *fmt) | ||
315 | { | ||
316 | printf(fmt, xstrtou(filedata, 0)); | ||
317 | } | ||
318 | |||
319 | static void show_bridge_port(const char *name) | ||
320 | { | ||
321 | char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 8]; | ||
322 | char *sfx; | ||
323 | |||
324 | #if IFNAMSIZ == 16 | ||
325 | sfx = pathbuf + sprintf(pathbuf, "%.16s/brport/", name); | ||
326 | #else | ||
327 | sfx = pathbuf + sprintf(pathbuf, "%.*s/brport/", (int)IFNAMSIZ, name); | ||
328 | #endif | ||
329 | |||
330 | strcpy(sfx, "port_no"); | ||
331 | read_file(pathbuf); | ||
332 | printf("%s (%u)\n", name, xstrtou(filedata, 0)); | ||
333 | |||
334 | strcpy(sfx + 5, "id"); // "port_id" | ||
335 | read_file(pathbuf); | ||
336 | printf_xstrtou(" port id\t\t%.4x"); | ||
337 | |||
338 | strcpy(sfx, "state"); | ||
339 | read_file(pathbuf); | ||
340 | printf("\t\t\tstate\t\t%15s\n", show_bridge_state(xstrtou(filedata, 0))); | ||
341 | |||
342 | strcpy(sfx, "designated_root"); | ||
343 | read_file(pathbuf); | ||
344 | printf(" designated root\t%s", filedata); | ||
345 | |||
346 | strcpy(sfx, "path_cost"); | ||
347 | read_file(pathbuf); | ||
348 | printf_xstrtou("\tpath cost\t\t%4u\n"); | ||
349 | |||
350 | strcpy(sfx, "designated_bridge"); | ||
351 | read_file(pathbuf); | ||
352 | printf(" designated bridge\t%s", filedata); | ||
353 | |||
354 | strcpy(sfx, "message_age_timer"); | ||
355 | read_file(pathbuf); | ||
356 | show_bridge_timer("\tmessage age timer\t"); | ||
357 | |||
358 | strcpy(sfx, "designated_port"); | ||
359 | read_file(pathbuf); | ||
360 | printf_xstrtou("\n designated port\t%.4x"); | ||
361 | |||
362 | strcpy(sfx, "forward_delay_timer"); | ||
363 | read_file(pathbuf); | ||
364 | show_bridge_timer("\t\t\tforward delay timer\t"); | ||
365 | |||
366 | strcpy(sfx, "designated_cost"); | ||
367 | read_file(pathbuf); | ||
368 | printf_xstrtou("\n designated cost\t%4u"); | ||
369 | |||
370 | strcpy(sfx, "hold_timer"); | ||
371 | read_file(pathbuf); | ||
372 | show_bridge_timer("\t\t\thold timer\t\t"); | ||
373 | |||
374 | printf("\n flags\t\t\t"); | ||
375 | |||
376 | strcpy(sfx, "config_pending"); | ||
377 | read_file(pathbuf); | ||
378 | if (!LONE_CHAR(filedata, '0')) | ||
379 | printf("CONFIG_PENDING "); | ||
380 | |||
381 | strcpy(sfx, "change_ack"); | ||
382 | read_file(pathbuf); | ||
383 | if (!LONE_CHAR(filedata, '0')) | ||
384 | printf("TOPOLOGY_CHANGE_ACK "); | ||
385 | |||
386 | strcpy(sfx, "hairpin_mode"); | ||
387 | read_file(pathbuf); | ||
388 | if (!LONE_CHAR(filedata, '0')) | ||
389 | printf_xstrtou("\n hairpin mode\t\t%4u"); | ||
390 | |||
391 | printf("\n\n"); | ||
392 | } | ||
393 | |||
394 | static void show_bridge_stp(const char *name) | ||
395 | { | ||
396 | char pathbuf[IFNAMSIZ + sizeof("/bridge/topology_change_timer") + 8]; | ||
397 | char *sfx; | ||
398 | |||
399 | #if IFNAMSIZ == 16 | ||
400 | sfx = pathbuf + sprintf(pathbuf, "%.16s/bridge/", name); | ||
401 | #else | ||
402 | sfx = pathbuf + sprintf(pathbuf, "%.*s/bridge/", (int)IFNAMSIZ, name); | ||
403 | #endif | ||
404 | |||
405 | strcpy(sfx, "bridge_id"); | ||
406 | if (read_file(pathbuf) < 0) | ||
407 | bb_error_msg_and_die("bridge %s does not exist", name); | ||
408 | |||
409 | printf("%s\n" | ||
410 | " bridge id\t\t%s", name, filedata); | ||
411 | |||
412 | strcpy(sfx, "root_id"); | ||
413 | read_file(pathbuf); | ||
414 | printf("\n designated root\t%s", filedata); | ||
415 | |||
416 | strcpy(sfx + 5, "port"); // "root_port" | ||
417 | read_file(pathbuf); | ||
418 | printf_xstrtou("\n root port\t\t%4u\t\t\t"); | ||
419 | |||
420 | strcpy(sfx + 6, "ath_cost"); // "root_path_cost" | ||
421 | read_file(pathbuf); | ||
422 | printf_xstrtou("path cost\t\t%4u\n"); | ||
423 | |||
424 | strcpy(sfx, "max_age"); | ||
425 | read_file(pathbuf); | ||
426 | show_bridge_timer(" max age\t\t"); | ||
427 | show_bridge_timer("\t\t\tbridge max age\t\t"); | ||
428 | |||
429 | strcpy(sfx, "hello_time"); | ||
430 | read_file(pathbuf); | ||
431 | show_bridge_timer("\n hello time\t\t"); | ||
432 | show_bridge_timer("\t\t\tbridge hello time\t"); | ||
433 | |||
434 | strcpy(sfx, "forward_delay"); | ||
435 | read_file(pathbuf); | ||
436 | show_bridge_timer("\n forward delay\t\t"); | ||
437 | show_bridge_timer("\t\t\tbridge forward delay\t"); | ||
438 | |||
439 | strcpy(sfx, "ageing_time"); | ||
440 | read_file(pathbuf); | ||
441 | show_bridge_timer("\n ageing time\t\t"); | ||
442 | |||
443 | strcpy(sfx, "hello_timer"); | ||
444 | read_file(pathbuf); | ||
445 | show_bridge_timer("\n hello timer\t\t"); | ||
446 | |||
447 | strcpy(sfx, "tcn_timer"); | ||
448 | read_file(pathbuf); | ||
449 | show_bridge_timer("\t\t\ttcn timer\t\t"); | ||
450 | |||
451 | strcpy(sfx, "topology_change_timer"); | ||
452 | read_file(pathbuf); | ||
453 | show_bridge_timer("\n topology change timer\t"); | ||
454 | |||
455 | strcpy(sfx, "gc_timer"); | ||
456 | read_file(pathbuf); | ||
457 | show_bridge_timer("\t\t\tgc timer\t\t"); | ||
458 | |||
459 | printf("\n flags\t\t\t"); | ||
460 | |||
461 | strcpy(sfx, "topology_change"); | ||
462 | read_file(pathbuf); | ||
463 | if (!LONE_CHAR(filedata, '0')) | ||
464 | printf("TOPOLOGY_CHANGE "); | ||
465 | |||
466 | strcpy(sfx, "topology_change_detected"); | ||
467 | read_file(pathbuf); | ||
468 | if (!LONE_CHAR(filedata, '0')) | ||
469 | printf("TOPOLOGY_CHANGE_DETECTED "); | ||
470 | printf("\n\n\n"); | ||
471 | |||
472 | /* Show bridge ports */ | ||
473 | { | ||
474 | DIR *ifaces; | ||
475 | |||
476 | /* sfx points past "BR/bridge/", turn it into "BR/brif": */ | ||
477 | sfx[-4] = 'f'; sfx[-3] = '\0'; | ||
478 | ifaces = opendir(pathbuf); | ||
479 | if (ifaces) { | ||
480 | struct dirent *ent; | ||
481 | while ((ent = readdir(ifaces)) != NULL) { | ||
482 | if (DOT_OR_DOTDOT(ent->d_name)) | ||
483 | continue; /* . or .. */ | ||
484 | show_bridge_port(ent->d_name); | ||
485 | } | ||
486 | if (ENABLE_FEATURE_CLEAN_UP) | ||
487 | closedir(ifaces); | ||
488 | } | ||
489 | } | ||
198 | } | 490 | } |
199 | #endif | 491 | #endif |
200 | 492 | ||
@@ -205,20 +497,26 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
205 | "addbr\0" "delbr\0" "addif\0" "delif\0" | 497 | "addbr\0" "delbr\0" "addif\0" "delif\0" |
206 | IF_FEATURE_BRCTL_FANCY( | 498 | IF_FEATURE_BRCTL_FANCY( |
207 | "stp\0" | 499 | "stp\0" |
500 | "showstp\0" | ||
208 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" | 501 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" |
209 | "setpathcost\0" "setportprio\0" | 502 | "setpathcost\0" "setportprio\0" |
210 | "setbridgeprio\0" | 503 | "setbridgeprio\0" |
504 | "showmacs\0" | ||
211 | ) | 505 | ) |
212 | IF_FEATURE_BRCTL_SHOW("show\0"); | 506 | IF_FEATURE_BRCTL_SHOW("show\0"); |
213 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif | 507 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif |
214 | IF_FEATURE_BRCTL_FANCY(, | 508 | IF_FEATURE_BRCTL_FANCY(, |
215 | ARG_stp, | 509 | ARG_stp, |
510 | ARG_showstp, | ||
216 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, | 511 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, |
217 | ARG_setpathcost, ARG_setportprio, | 512 | ARG_setpathcost, ARG_setportprio, |
218 | ARG_setbridgeprio | 513 | ARG_setbridgeprio, |
514 | ARG_showmacs | ||
219 | ) | 515 | ) |
220 | IF_FEATURE_BRCTL_SHOW(, ARG_show) | 516 | IF_FEATURE_BRCTL_SHOW(, ARG_show) |
221 | }; | 517 | }; |
518 | int key; | ||
519 | char *br; | ||
222 | 520 | ||
223 | argv++; | 521 | argv++; |
224 | if (!*argv) { | 522 | if (!*argv) { |
@@ -228,185 +526,157 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
228 | 526 | ||
229 | xchdir("/sys/class/net"); | 527 | xchdir("/sys/class/net"); |
230 | 528 | ||
231 | // while (*argv) | 529 | key = index_in_strings(keywords, *argv); |
232 | { | 530 | if (key == -1) /* no match found in keywords array, bail out. */ |
233 | smallint key; | 531 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); |
234 | char *br; | 532 | argv++; |
235 | |||
236 | key = index_in_strings(keywords, *argv); | ||
237 | if (key == -1) /* no match found in keywords array, bail out. */ | ||
238 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); | ||
239 | argv++; | ||
240 | 533 | ||
241 | #if ENABLE_FEATURE_BRCTL_SHOW | 534 | #if ENABLE_FEATURE_BRCTL_SHOW |
242 | if (key == ARG_show) { /* show [BR]... */ | 535 | if (key == ARG_show) { /* show [BR]... */ |
243 | DIR *net; | 536 | DIR *net; |
244 | struct dirent *ent; | 537 | struct dirent *ent; |
245 | int need_hdr = 1; | 538 | int need_hdr = 1; |
246 | int exitcode = EXIT_SUCCESS; | 539 | int exitcode = EXIT_SUCCESS; |
247 | 540 | ||
248 | if (*argv) { | 541 | if (*argv) { |
249 | /* "show BR1 BR2 BR3" */ | 542 | /* "show BR1 BR2 BR3" */ |
250 | do { | 543 | do { |
251 | if (show_bridge(*argv, need_hdr) >= 0) { | 544 | if (show_bridge(*argv, need_hdr) >= 0) { |
252 | need_hdr = 0; | 545 | need_hdr = 0; |
253 | } else { | 546 | } else { |
254 | bb_error_msg("bridge %s does not exist", *argv); | 547 | bb_error_msg("bridge %s does not exist", *argv); |
255 | //TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 | 548 | //TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 |
256 | //says this instead: "device eth0 is not a bridge" | 549 | //says this instead: "device eth0 is not a bridge" |
257 | exitcode = EXIT_FAILURE; | 550 | exitcode = EXIT_FAILURE; |
258 | } | 551 | } |
259 | } while (*++argv != NULL); | 552 | } while (*++argv != NULL); |
260 | return exitcode; | ||
261 | } | ||
262 | |||
263 | /* "show" (if no ifaces, shows nothing, not even header) */ | ||
264 | net = xopendir("."); | ||
265 | while ((ent = readdir(net)) != NULL) { | ||
266 | if (DOT_OR_DOTDOT(ent->d_name)) | ||
267 | continue; /* . or .. */ | ||
268 | if (show_bridge(ent->d_name, need_hdr) >= 0) | ||
269 | need_hdr = 0; | ||
270 | } | ||
271 | if (ENABLE_FEATURE_CLEAN_UP) | ||
272 | closedir(net); | ||
273 | return exitcode; | 553 | return exitcode; |
274 | } | 554 | } |
555 | |||
556 | /* "show" (if no ifaces, shows nothing, not even header) */ | ||
557 | net = xopendir("."); | ||
558 | while ((ent = readdir(net)) != NULL) { | ||
559 | if (DOT_OR_DOTDOT(ent->d_name)) | ||
560 | continue; /* . or .. */ | ||
561 | if (show_bridge(ent->d_name, need_hdr) >= 0) | ||
562 | need_hdr = 0; | ||
563 | } | ||
564 | if (ENABLE_FEATURE_CLEAN_UP) | ||
565 | closedir(net); | ||
566 | return exitcode; | ||
567 | } | ||
275 | #endif | 568 | #endif |
276 | 569 | ||
277 | if (!*argv) /* all but 'show' need at least one argument */ | 570 | if (!*argv) /* All of the below need at least one argument */ |
278 | bb_show_usage(); | 571 | bb_show_usage(); |
279 | 572 | ||
280 | br = *argv++; | 573 | br = *argv++; |
281 | 574 | ||
282 | if (key == ARG_addbr || key == ARG_delbr) { | 575 | if (key == ARG_addbr || key == ARG_delbr) { |
283 | /* addbr or delbr */ | 576 | /* brctl from bridge-utils 1.6 still uses ioctl |
284 | /* brctl from bridge-utils 1.6 still uses ioctl | 577 | * for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses |
285 | * for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses | 578 | */ |
286 | */ | 579 | int fd = xsocket(AF_INET, SOCK_STREAM, 0); |
287 | int fd = xsocket(AF_INET, SOCK_STREAM, 0); | 580 | ioctl_or_perror_and_die(fd, |
288 | ioctl_or_perror_and_die(fd, | 581 | key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, |
289 | key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, | 582 | br, "bridge %s", br |
290 | br, "bridge %s", br | 583 | ); |
291 | ); | 584 | //close(fd); |
292 | //close(fd); | 585 | //goto done; |
293 | //goto done; | 586 | /* bridge-utils 1.6 simply ignores trailing args: |
294 | /* bridge-utils 1.6 simply ignores trailing args: | 587 | * "brctl addbr BR1 ARGS" ignores ARGS |
295 | * "brctl addbr BR1 ARGS" ignores ARGS | 588 | */ |
296 | */ | 589 | if (ENABLE_FEATURE_CLEAN_UP) |
297 | if (ENABLE_FEATURE_CLEAN_UP) | 590 | close(fd); |
298 | close(fd); | 591 | return EXIT_SUCCESS; |
299 | return EXIT_SUCCESS; | 592 | } |
300 | } | ||
301 | 593 | ||
302 | if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ | 594 | if (key == ARG_showmacs) { |
303 | bb_show_usage(); | 595 | show_bridge_macs(br); |
596 | return EXIT_SUCCESS; | ||
597 | } | ||
598 | if (key == ARG_showstp) { | ||
599 | show_bridge_stp(br); | ||
600 | return EXIT_SUCCESS; | ||
601 | } | ||
304 | 602 | ||
305 | #if ENABLE_FEATURE_BRCTL_FANCY | 603 | if (!*argv) /* All of the below need at least two arguments */ |
306 | if (key == ARG_stp) { /* stp */ | 604 | bb_show_usage(); |
307 | static const char no_yes[] ALIGN1 = | ||
308 | "0\0" "off\0" "n\0" "no\0" /* 0 .. 3 */ | ||
309 | "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */ | ||
310 | int onoff = index_in_strings(no_yes, *argv); | ||
311 | if (onoff < 0) | ||
312 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); | ||
313 | onoff = (unsigned)onoff / 4; | ||
314 | write_uint(br, "bridge/stp_state", onoff); | ||
315 | //goto done_next_argv; | ||
316 | return EXIT_SUCCESS; | ||
317 | } | ||
318 | 605 | ||
319 | if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ | 606 | #if ENABLE_FEATURE_BRCTL_FANCY |
320 | /* setageing BR N: "N*100\n" to /sys/class/net/BR/bridge/ageing_time | 607 | if (key == ARG_stp) { |
321 | * setfd BR N: "N*100\n" to /sys/class/net/BR/bridge/forward_delay | 608 | static const char no_yes[] ALIGN1 = |
322 | * sethello BR N: "N*100\n" to /sys/class/net/BR/bridge/hello_time | 609 | "0\0" "off\0" "n\0" "no\0" /* 0 .. 3 */ |
323 | * setmaxage BR N: "N*100\n" to /sys/class/net/BR/bridge/max_age | 610 | "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */ |
324 | */ | 611 | int onoff = index_in_strings(no_yes, *argv); |
325 | write_uint(br, | 612 | if (onoff < 0) |
326 | nth_string( | 613 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); |
327 | "bridge/ageing_time" "\0" /* ARG_setageing */ | 614 | onoff = (unsigned)onoff / 4; |
328 | "bridge/forward_delay""\0" /* ARG_setfd */ | 615 | write_uint(br, "bridge/stp_state", onoff); |
329 | "bridge/hello_time" "\0" /* ARG_sethello */ | 616 | return EXIT_SUCCESS; |
330 | "bridge/max_age", /* ARG_setmaxage */ | 617 | } |
331 | key - ARG_setageing | ||
332 | ), | ||
333 | str_to_jiffies(*argv) | ||
334 | ); | ||
335 | //goto done_next_argv; | ||
336 | return EXIT_SUCCESS; | ||
337 | } | ||
338 | 618 | ||
339 | if (key == ARG_setbridgeprio) { | 619 | if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ |
340 | write_uint(br, "bridge/priority", xatoi_positive(*argv)); | 620 | /* setageing BR N: "N*100\n" to /sys/class/net/BR/bridge/ageing_time |
341 | //goto done_next_argv; | 621 | * setfd BR N: "N*100\n" to /sys/class/net/BR/bridge/forward_delay |
342 | return EXIT_SUCCESS; | 622 | * sethello BR N: "N*100\n" to /sys/class/net/BR/bridge/hello_time |
343 | } | 623 | * setmaxage BR N: "N*100\n" to /sys/class/net/BR/bridge/max_age |
624 | */ | ||
625 | write_uint(br, | ||
626 | nth_string( | ||
627 | "bridge/ageing_time" "\0" /* ARG_setageing */ | ||
628 | "bridge/forward_delay""\0" /* ARG_setfd */ | ||
629 | "bridge/hello_time" "\0" /* ARG_sethello */ | ||
630 | "bridge/max_age", /* ARG_setmaxage */ | ||
631 | key - ARG_setageing | ||
632 | ), | ||
633 | str_to_jiffies(*argv) | ||
634 | ); | ||
635 | return EXIT_SUCCESS; | ||
636 | } | ||
344 | 637 | ||
345 | if (key == ARG_setpathcost | 638 | if (key == ARG_setbridgeprio) { |
346 | || key == ARG_setportprio | 639 | write_uint(br, "bridge/priority", xatoi_positive(*argv)); |
347 | ) { | 640 | return EXIT_SUCCESS; |
348 | if (!argv[1]) | 641 | } |
349 | bb_show_usage(); | ||
350 | /* BR is not used (and ignored!) for these commands: | ||
351 | * "setpathcost BR PORT N" writes "N\n" to | ||
352 | * /sys/class/net/PORT/brport/path_cost | ||
353 | * "setportprio BR PORT N" writes "N\n" to | ||
354 | * /sys/class/net/PORT/brport/priority | ||
355 | */ | ||
356 | write_uint(argv[0], | ||
357 | nth_string( | ||
358 | "brport/path_cost" "\0" /* ARG_setpathcost */ | ||
359 | "brport/priority", /* ARG_setportprio */ | ||
360 | key - ARG_setpathcost | ||
361 | ), | ||
362 | xatoi_positive(argv[1]) | ||
363 | ); | ||
364 | //argv++; | ||
365 | //goto done_next_argv; | ||
366 | return EXIT_SUCCESS; | ||
367 | } | ||
368 | 642 | ||
369 | /* TODO: "showmacs BR" | 643 | if (key == ARG_setpathcost |
370 | * port no\tmac addr\t\tis local?\tageing timer | 644 | || key == ARG_setportprio |
371 | * <sp><sp>1\txx:xx:xx:xx:xx:xx\tno\t\t<sp><sp><sp>1.31 | 645 | ) { |
372 | * port no mac addr is local? ageing timer | 646 | if (!argv[1]) |
373 | * 1 xx:xx:xx:xx:xx:xx no 1.31 | 647 | bb_show_usage(); |
374 | * Read fixed-sized records from /sys/class/net/BR/brforward: | 648 | /* BR is not used (and ignored!) for these commands: |
375 | * struct __fdb_entry { | 649 | * "setpathcost BR PORT N" writes "N\n" to |
376 | * uint8_t mac_addr[ETH_ALEN]; | 650 | * /sys/class/net/PORT/brport/path_cost |
377 | * uint8_t port_no; //lsb | 651 | * "setportprio BR PORT N" writes "N\n" to |
378 | * uint8_t is_local; | 652 | * /sys/class/net/PORT/brport/priority |
379 | * uint32_t ageing_timer_value; | 653 | */ |
380 | * uint8_t port_hi; | 654 | write_uint(argv[0], |
381 | * uint8_t pad0; | 655 | nth_string( |
382 | * uint16_t unused; | 656 | "brport/path_cost" "\0" /* ARG_setpathcost */ |
383 | * }; | 657 | "brport/priority", /* ARG_setportprio */ |
384 | */ | 658 | key - ARG_setpathcost |
659 | ), | ||
660 | xatoi_positive(argv[1]) | ||
661 | ); | ||
662 | return EXIT_SUCCESS; | ||
663 | } | ||
385 | #endif | 664 | #endif |
386 | /* always true: if (key == ARG_addif || key == ARG_delif) */ { | 665 | /* always true: if (key == ARG_addif || key == ARG_delif) */ { |
387 | /* addif or delif */ | 666 | struct ifreq ifr; |
388 | struct ifreq ifr; | 667 | int fd = xsocket(AF_INET, SOCK_STREAM, 0); |
389 | int fd = xsocket(AF_INET, SOCK_STREAM, 0); | 668 | |
390 | 669 | strncpy_IFNAMSIZ(ifr.ifr_name, br); | |
391 | strncpy_IFNAMSIZ(ifr.ifr_name, br); | 670 | ifr.ifr_ifindex = if_nametoindex(*argv); |
392 | ifr.ifr_ifindex = if_nametoindex(*argv); | 671 | if (ifr.ifr_ifindex == 0) { |
393 | if (ifr.ifr_ifindex == 0) { | 672 | bb_perror_msg_and_die("iface %s", *argv); |
394 | bb_perror_msg_and_die("iface %s", *argv); | ||
395 | } | ||
396 | ioctl_or_perror_and_die(fd, | ||
397 | key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, | ||
398 | &ifr, "bridge %s", br | ||
399 | ); | ||
400 | //close(fd); | ||
401 | //goto done_next_argv; | ||
402 | if (ENABLE_FEATURE_CLEAN_UP) | ||
403 | close(fd); | ||
404 | return EXIT_SUCCESS; | ||
405 | } | 673 | } |
406 | 674 | ioctl_or_perror_and_die(fd, | |
407 | // done_next_argv: | 675 | key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, |
408 | // argv++; | 676 | &ifr, "bridge %s", br |
409 | // done: | 677 | ); |
678 | if (ENABLE_FEATURE_CLEAN_UP) | ||
679 | close(fd); | ||
410 | } | 680 | } |
411 | 681 | ||
412 | return EXIT_SUCCESS; | 682 | return EXIT_SUCCESS; |
diff --git a/networking/netstat.c b/networking/netstat.c index 29b891cdc..c7934423b 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -172,7 +172,7 @@ struct prg_node { | |||
172 | #define PRG_HASH_SIZE 211 | 172 | #define PRG_HASH_SIZE 211 |
173 | 173 | ||
174 | struct globals { | 174 | struct globals { |
175 | smallint flags; | 175 | smalluint flags; |
176 | #if ENABLE_FEATURE_NETSTAT_PRG | 176 | #if ENABLE_FEATURE_NETSTAT_PRG |
177 | smallint prg_cache_loaded; | 177 | smallint prg_cache_loaded; |
178 | struct prg_node *prg_hash[PRG_HASH_SIZE]; | 178 | struct prg_node *prg_hash[PRG_HASH_SIZE]; |
diff --git a/networking/nslookup.c b/networking/nslookup.c index 8adde14b8..c43e60558 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
@@ -283,6 +283,7 @@ static const struct { | |||
283 | { ns_t_cname, "CNAME" }, | 283 | { ns_t_cname, "CNAME" }, |
284 | { ns_t_mx, "MX" }, | 284 | { ns_t_mx, "MX" }, |
285 | { ns_t_txt, "TXT" }, | 285 | { ns_t_txt, "TXT" }, |
286 | { ns_t_srv, "SRV" }, | ||
286 | { ns_t_ptr, "PTR" }, | 287 | { ns_t_ptr, "PTR" }, |
287 | { ns_t_any, "ANY" }, | 288 | { ns_t_any, "ANY" }, |
288 | }; | 289 | }; |
@@ -435,6 +436,25 @@ static int parse_reply(const unsigned char *msg, size_t len) | |||
435 | } | 436 | } |
436 | break; | 437 | break; |
437 | 438 | ||
439 | case ns_t_srv: | ||
440 | if (rdlen < 6) { | ||
441 | //printf("SRV record too short\n"); | ||
442 | return -1; | ||
443 | } | ||
444 | |||
445 | cp = ns_rr_rdata(rr); | ||
446 | n = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), | ||
447 | cp + 6, dname, sizeof(dname)); | ||
448 | |||
449 | if (n < 0) { | ||
450 | //printf("Unable to uncompress domain: %s\n", strerror(errno)); | ||
451 | return -1; | ||
452 | } | ||
453 | |||
454 | printf("%s\tservice = %u %u %u %s\n", ns_rr_name(rr), | ||
455 | ns_get16(cp), ns_get16(cp + 2), ns_get16(cp + 4), dname); | ||
456 | break; | ||
457 | |||
438 | case ns_t_soa: | 458 | case ns_t_soa: |
439 | if (rdlen < 20) { | 459 | if (rdlen < 20) { |
440 | dbg("SOA record too short:%d\n", rdlen); | 460 | dbg("SOA record too short:%d\n", rdlen); |
@@ -615,9 +635,15 @@ static int send_queries(struct ns *ns) | |||
615 | G.query[qn].name, rcodes[rcode]); | 635 | G.query[qn].name, rcodes[rcode]); |
616 | G.exitcode = EXIT_FAILURE; | 636 | G.exitcode = EXIT_FAILURE; |
617 | } else { | 637 | } else { |
618 | if (parse_reply(reply, recvlen) < 0) { | 638 | switch (parse_reply(reply, recvlen)) { |
639 | case -1: | ||
619 | printf("*** Can't find %s: Parse error\n", G.query[qn].name); | 640 | printf("*** Can't find %s: Parse error\n", G.query[qn].name); |
620 | G.exitcode = EXIT_FAILURE; | 641 | G.exitcode = EXIT_FAILURE; |
642 | break; | ||
643 | |||
644 | case 0: | ||
645 | printf("*** Can't find %s: No answer\n", G.query[qn].name); | ||
646 | break; | ||
621 | } | 647 | } |
622 | } | 648 | } |
623 | bb_putchar('\n'); | 649 | bb_putchar('\n'); |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 48dc1c379..0f12409f9 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -164,7 +164,7 @@ | |||
164 | */ | 164 | */ |
165 | 165 | ||
166 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ | 166 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ |
167 | #define MIN_FREQHOLD 12 /* adjust offset, but not freq in this many first adjustments */ | 167 | #define MIN_FREQHOLD 10 /* adjust offset, but not freq in this many first adjustments */ |
168 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this factor */ | 168 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this factor */ |
169 | 169 | ||
170 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ | 170 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ |
@@ -504,12 +504,14 @@ static ALWAYS_INLINE double MAXD(double a, double b) | |||
504 | return a; | 504 | return a; |
505 | return b; | 505 | return b; |
506 | } | 506 | } |
507 | #if !USING_KERNEL_PLL_LOOP | ||
507 | static ALWAYS_INLINE double MIND(double a, double b) | 508 | static ALWAYS_INLINE double MIND(double a, double b) |
508 | { | 509 | { |
509 | if (a < b) | 510 | if (a < b) |
510 | return a; | 511 | return a; |
511 | return b; | 512 | return b; |
512 | } | 513 | } |
514 | #endif | ||
513 | static NOINLINE double my_SQRT(double X) | 515 | static NOINLINE double my_SQRT(double X) |
514 | { | 516 | { |
515 | union { | 517 | union { |
@@ -1874,9 +1876,11 @@ update_local_clock(peer_t *p) | |||
1874 | //15:31:53.473 update from:<IP> offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 | 1876 | //15:31:53.473 update from:<IP> offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 |
1875 | //15:32:58.902 update from:<IP> offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 | 1877 | //15:32:58.902 update from:<IP> offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 |
1876 | /* | 1878 | /* |
1877 | * This expression would choose MIN_FREQHOLD + 8 in the above example. | 1879 | * This expression would choose MIN_FREQHOLD + 14 in the above example |
1880 | * (off_032 is +1 for each 0.032768 seconds of offset). | ||
1878 | */ | 1881 | */ |
1879 | G.FREQHOLD_cnt = 1 + MIN_FREQHOLD + ((unsigned)(abs(tmx.offset)) >> 16); | 1882 | unsigned off_032 = abs((int)(tmx.offset >> 15)); |
1883 | G.FREQHOLD_cnt = 1 + MIN_FREQHOLD + off_032; | ||
1880 | } | 1884 | } |
1881 | G.FREQHOLD_cnt--; | 1885 | G.FREQHOLD_cnt--; |
1882 | tmx.status |= STA_FREQHOLD; | 1886 | tmx.status |= STA_FREQHOLD; |
diff --git a/networking/route.c b/networking/route.c index a5d8d7cb9..e785b1da6 100644 --- a/networking/route.c +++ b/networking/route.c | |||
@@ -628,6 +628,7 @@ static void INET6_displayroutes(void) | |||
628 | 628 | ||
629 | r = 0; | 629 | r = 0; |
630 | while (1) { | 630 | while (1) { |
631 | memset(&snaddr6, 0, sizeof(snaddr6)); | ||
631 | inet_pton(AF_INET6, addr6x + r, | 632 | inet_pton(AF_INET6, addr6x + r, |
632 | (struct sockaddr *) &snaddr6.sin6_addr); | 633 | (struct sockaddr *) &snaddr6.sin6_addr); |
633 | snaddr6.sin6_family = AF_INET6; | 634 | snaddr6.sin6_family = AF_INET6; |
diff --git a/networking/tc.c b/networking/tc.c index 2e1078d31..510684443 100644 --- a/networking/tc.c +++ b/networking/tc.c | |||
@@ -215,8 +215,6 @@ static int prio_print_opt(struct rtattr *opt) | |||
215 | if (opt == NULL) | 215 | if (opt == NULL) |
216 | return 0; | 216 | return 0; |
217 | parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); | 217 | parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); |
218 | if (tb == NULL) | ||
219 | return 0; | ||
220 | printf("bands %u priomap ", qopt->bands); | 218 | printf("bands %u priomap ", qopt->bands); |
221 | for (i=0; i<=TC_PRIO_MAX; i++) | 219 | for (i=0; i<=TC_PRIO_MAX; i++) |
222 | printf(" %d", qopt->priomap[i]); | 220 | printf(" %d", qopt->priomap[i]); |
diff --git a/networking/telnet.c b/networking/telnet.c index fa1628723..9fc85050b 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -238,6 +238,18 @@ static void handle_net_output(int len) | |||
238 | *dst = '\r'; /* Enter -> CR LF */ | 238 | *dst = '\r'; /* Enter -> CR LF */ |
239 | *++dst = '\n'; | 239 | *++dst = '\n'; |
240 | } | 240 | } |
241 | #if 0 | ||
242 | /* putty's "special commands" mode does this: */ | ||
243 | /* Korenix 3005 switch needs at least the backspace tweak */ | ||
244 | if (c == 0x08 || c == 0x7f) { /* ctrl+h || backspace */ | ||
245 | *dst = IAC; | ||
246 | *++dst = EC; | ||
247 | } | ||
248 | if (c == 0x03) { /* ctrl+c */ | ||
249 | *dst = IAC; | ||
250 | *++dst = IP; | ||
251 | } | ||
252 | #endif | ||
241 | dst++; | 253 | dst++; |
242 | } | 254 | } |
243 | if (dst - outbuf != 0) | 255 | if (dst - outbuf != 0) |
@@ -248,7 +260,7 @@ static void handle_net_input(int len) | |||
248 | { | 260 | { |
249 | byte c; | 261 | byte c; |
250 | int i; | 262 | int i; |
251 | int cstart = cstart; /* for compiler */ | 263 | int cstart = 0; |
252 | 264 | ||
253 | i = 0; | 265 | i = 0; |
254 | //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf); | 266 | //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf); |
diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index a4663cd79..5ddcdd2ad 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c | |||
@@ -13,6 +13,7 @@ typedef uint32_t word32; | |||
13 | 13 | ||
14 | /* from wolfssl-3.15.3/wolfcrypt/src/aes.c */ | 14 | /* from wolfssl-3.15.3/wolfcrypt/src/aes.c */ |
15 | 15 | ||
16 | #ifdef UNUSED | ||
16 | static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) | 17 | static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) |
17 | { | 18 | { |
18 | /* Multiply the sz by 8 */ | 19 | /* Multiply the sz by 8 */ |
@@ -32,6 +33,7 @@ static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) | |||
32 | // buf[7] = sz & 0xff; | 33 | // buf[7] = sz & 0xff; |
33 | *(uint32_t*)(buf + 4) = SWAP_BE32(sz); | 34 | *(uint32_t*)(buf + 4) = SWAP_BE32(sz); |
34 | } | 35 | } |
36 | #endif | ||
35 | 37 | ||
36 | static void RIGHTSHIFTX(byte* x) | 38 | static void RIGHTSHIFTX(byte* x) |
37 | { | 39 | { |
diff --git a/networking/traceroute.c b/networking/traceroute.c index 0435d6ba6..06d3f19da 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -546,11 +546,11 @@ pr_type(unsigned char t) | |||
546 | }; | 546 | }; |
547 | # if ENABLE_TRACEROUTE6 | 547 | # if ENABLE_TRACEROUTE6 |
548 | static const char *const ttab6[] = { | 548 | static const char *const ttab6[] = { |
549 | [0] "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", | 549 | [0] = "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", |
550 | [4] "Param Problem", | 550 | [4] = "Param Problem", |
551 | [8] "Echo Request", "Echo Reply", "Membership Query", "Membership Report", | 551 | [8] = "Echo Request", "Echo Reply", "Membership Query", "Membership Report", |
552 | [12] "Membership Reduction", "Router Solicit", "Router Advert", "Neighbor Solicit", | 552 | [12] = "Membership Reduction", "Router Solicit", "Router Advert", "Neighbor Solicit", |
553 | [16] "Neighbor Advert", "Redirect", | 553 | [16] = "Neighbor Advert", "Redirect", |
554 | }; | 554 | }; |
555 | 555 | ||
556 | if (dest_lsa->u.sa.sa_family == AF_INET6) { | 556 | if (dest_lsa->u.sa.sa_family == AF_INET6) { |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 4a452cdb9..9ec752dfc 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -539,7 +539,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, | |||
539 | 539 | ||
540 | if (optflag->flags == OPTION_BIN) { | 540 | if (optflag->flags == OPTION_BIN) { |
541 | val = strtok(NULL, ""); /* do not split "'q w e'" */ | 541 | val = strtok(NULL, ""); /* do not split "'q w e'" */ |
542 | trim(val); | 542 | if (val) trim(val); |
543 | } else | 543 | } else |
544 | val = strtok(NULL, ", \t"); | 544 | val = strtok(NULL, ", \t"); |
545 | if (!val) | 545 | if (!val) |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 9d8e17c51..85c410a7c 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -123,6 +123,7 @@ static const char udhcpc6_longopts[] ALIGN1 = | |||
123 | "request-option\0" Required_argument "O" | 123 | "request-option\0" Required_argument "O" |
124 | "no-default-options\0" No_argument "o" | 124 | "no-default-options\0" No_argument "o" |
125 | "foreground\0" No_argument "f" | 125 | "foreground\0" No_argument "f" |
126 | "stateless\0" No_argument "l" | ||
126 | USE_FOR_MMU( | 127 | USE_FOR_MMU( |
127 | "background\0" No_argument "b" | 128 | "background\0" No_argument "b" |
128 | ) | 129 | ) |
@@ -147,9 +148,10 @@ enum { | |||
147 | OPT_o = 1 << 12, | 148 | OPT_o = 1 << 12, |
148 | OPT_x = 1 << 13, | 149 | OPT_x = 1 << 13, |
149 | OPT_f = 1 << 14, | 150 | OPT_f = 1 << 14, |
150 | OPT_d = 1 << 15, | 151 | OPT_l = 1 << 15, |
152 | OPT_d = 1 << 16, | ||
151 | /* The rest has variable bit positions, need to be clever */ | 153 | /* The rest has variable bit positions, need to be clever */ |
152 | OPTBIT_d = 15, | 154 | OPTBIT_d = 16, |
153 | USE_FOR_MMU( OPTBIT_b,) | 155 | USE_FOR_MMU( OPTBIT_b,) |
154 | ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) | 156 | ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) |
155 | IF_FEATURE_UDHCP_PORT( OPTBIT_P,) | 157 | IF_FEATURE_UDHCP_PORT( OPTBIT_P,) |
@@ -479,15 +481,31 @@ static ALWAYS_INLINE uint32_t random_xid(void) | |||
479 | /* Initialize the packet with the proper defaults */ | 481 | /* Initialize the packet with the proper defaults */ |
480 | static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid) | 482 | static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid) |
481 | { | 483 | { |
484 | uint8_t *ptr; | ||
482 | struct d6_option *clientid; | 485 | struct d6_option *clientid; |
486 | unsigned secs; | ||
483 | 487 | ||
484 | memset(packet, 0, sizeof(*packet)); | 488 | memset(packet, 0, sizeof(*packet)); |
485 | 489 | ||
486 | packet->d6_xid32 = xid; | 490 | packet->d6_xid32 = xid; |
487 | packet->d6_msg_type = type; | 491 | packet->d6_msg_type = type; |
488 | 492 | ||
493 | /* ELAPSED_TIME option is required to be present by the RFC, | ||
494 | * and some servers do check for its presense. [which?] | ||
495 | */ | ||
496 | ptr = packet->d6_options; /* NB: it is 32-bit aligned */ | ||
497 | *((uint32_t*)ptr) = htonl((D6_OPT_ELAPSED_TIME << 16) + 2); | ||
498 | ptr += 4; | ||
499 | client_data.last_secs = monotonic_sec(); | ||
500 | if (client_data.first_secs == 0) | ||
501 | client_data.first_secs = client_data.last_secs; | ||
502 | secs = client_data.last_secs - client_data.first_secs; | ||
503 | *((uint16_t*)ptr) = (secs < 0xffff) ? htons(secs) : 0xffff; | ||
504 | ptr += 2; | ||
505 | |||
506 | /* add CLIENTID option */ | ||
489 | clientid = (void*)client_data.clientid; | 507 | clientid = (void*)client_data.clientid; |
490 | return mempcpy(packet->d6_options, clientid, clientid->len + 2+2); | 508 | return mempcpy(ptr, clientid, clientid->len + 2+2); |
491 | } | 509 | } |
492 | 510 | ||
493 | static uint8_t *add_d6_client_options(uint8_t *ptr) | 511 | static uint8_t *add_d6_client_options(uint8_t *ptr) |
@@ -544,6 +562,46 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * | |||
544 | ); | 562 | ); |
545 | } | 563 | } |
546 | 564 | ||
565 | /* RFC 3315 18.1.5. Creation and Transmission of Information-request Messages | ||
566 | * | ||
567 | * The client uses an Information-request message to obtain | ||
568 | * configuration information without having addresses assigned to it. | ||
569 | * | ||
570 | * The client sets the "msg-type" field to INFORMATION-REQUEST. The | ||
571 | * client generates a transaction ID and inserts this value in the | ||
572 | * "transaction-id" field. | ||
573 | * | ||
574 | * The client SHOULD include a Client Identifier option to identify | ||
575 | * itself to the server. If the client does not include a Client | ||
576 | * Identifier option, the server will not be able to return any client- | ||
577 | * specific options to the client, or the server may choose not to | ||
578 | * respond to the message at all. The client MUST include a Client | ||
579 | * Identifier option if the Information-Request message will be | ||
580 | * authenticated. | ||
581 | * | ||
582 | * The client MUST include an Option Request option (see section 22.7) | ||
583 | * to indicate the options the client is interested in receiving. The | ||
584 | * client MAY include options with data values as hints to the server | ||
585 | * about parameter values the client would like to have returned. | ||
586 | */ | ||
587 | /* NOINLINE: limit stack usage in caller */ | ||
588 | static NOINLINE int send_d6_info_request(uint32_t xid) | ||
589 | { | ||
590 | struct d6_packet packet; | ||
591 | uint8_t *opt_ptr; | ||
592 | |||
593 | /* Fill in: msg type, client id */ | ||
594 | opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid); | ||
595 | |||
596 | /* Add options: | ||
597 | * "param req" option according to -O, options specified with -x | ||
598 | */ | ||
599 | opt_ptr = add_d6_client_options(opt_ptr); | ||
600 | |||
601 | bb_error_msg("sending %s", "info request"); | ||
602 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); | ||
603 | } | ||
604 | |||
547 | /* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP. | 605 | /* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP. |
548 | * | 606 | * |
549 | * RFC 3315 17.1.1. Creation of Solicit Messages | 607 | * RFC 3315 17.1.1. Creation of Solicit Messages |
@@ -1129,6 +1187,8 @@ static void client_background(void) | |||
1129 | //usage: "\n -o Don't request any options (unless -O is given)" | 1187 | //usage: "\n -o Don't request any options (unless -O is given)" |
1130 | //usage: "\n -r IPv6 Request this address ('no' to not request any IP)" | 1188 | //usage: "\n -r IPv6 Request this address ('no' to not request any IP)" |
1131 | //usage: "\n -d Request prefix" | 1189 | //usage: "\n -d Request prefix" |
1190 | //usage: "\n -l Send 'information request' instead of 'solicit'" | ||
1191 | //usage: "\n (used for servers which do not assign IPv6 addresses)" | ||
1132 | //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" | 1192 | //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" |
1133 | //usage: "\n Examples of string, numeric, and hex byte opts:" | 1193 | //usage: "\n Examples of string, numeric, and hex byte opts:" |
1134 | //usage: "\n -x hostname:bbox - option 12" | 1194 | //usage: "\n -x hostname:bbox - option 12" |
@@ -1181,7 +1241,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1181 | /* Parse command line */ | 1241 | /* Parse command line */ |
1182 | opt = getopt32long(argv, "^" | 1242 | opt = getopt32long(argv, "^" |
1183 | /* O,x: list; -T,-t,-A take numeric param */ | 1243 | /* O,x: list; -T,-t,-A take numeric param */ |
1184 | "i:np:qRr:s:T:+t:+SA:+O:*ox:*fd" | 1244 | "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld" |
1185 | USE_FOR_MMU("b") | 1245 | USE_FOR_MMU("b") |
1186 | ///IF_FEATURE_UDHCPC_ARPING("a") | 1246 | ///IF_FEATURE_UDHCPC_ARPING("a") |
1187 | IF_FEATURE_UDHCP_PORT("P:") | 1247 | IF_FEATURE_UDHCP_PORT("P:") |
@@ -1198,15 +1258,20 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1198 | ); | 1258 | ); |
1199 | requested_ipv6 = NULL; | 1259 | requested_ipv6 = NULL; |
1200 | option_mask32 |= OPT_r; | 1260 | option_mask32 |= OPT_r; |
1201 | if (opt & OPT_r) { | 1261 | if (opt & OPT_l) { |
1262 | /* for -l, do not require IPv6 assignment from server */ | ||
1263 | option_mask32 &= ~OPT_r; | ||
1264 | } else if (opt & OPT_r) { | ||
1265 | /* explicit "-r ARG" given */ | ||
1202 | if (strcmp(str_r, "no") == 0) { | 1266 | if (strcmp(str_r, "no") == 0) { |
1203 | option_mask32 -= OPT_r; | 1267 | option_mask32 &= ~OPT_r; |
1204 | } else { | 1268 | } else { |
1205 | if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0) | 1269 | if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0) |
1206 | bb_error_msg_and_die("bad IPv6 address '%s'", str_r); | 1270 | bb_error_msg_and_die("bad IPv6 address '%s'", str_r); |
1207 | requested_ipv6 = &ipv6_buf; | 1271 | requested_ipv6 = &ipv6_buf; |
1208 | } | 1272 | } |
1209 | } | 1273 | } |
1274 | |||
1210 | #if ENABLE_FEATURE_UDHCP_PORT | 1275 | #if ENABLE_FEATURE_UDHCP_PORT |
1211 | if (opt & OPT_P) { | 1276 | if (opt & OPT_P) { |
1212 | CLIENT_PORT6 = xatou16(str_P); | 1277 | CLIENT_PORT6 = xatou16(str_P); |
@@ -1353,7 +1418,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1353 | if (packet_num == 0) | 1418 | if (packet_num == 0) |
1354 | xid = random_xid(); | 1419 | xid = random_xid(); |
1355 | /* multicast */ | 1420 | /* multicast */ |
1356 | send_d6_discover(xid, requested_ipv6); | 1421 | if (opt & OPT_l) |
1422 | send_d6_info_request(xid); | ||
1423 | else | ||
1424 | send_d6_discover(xid, requested_ipv6); | ||
1357 | timeout = discover_timeout; | 1425 | timeout = discover_timeout; |
1358 | packet_num++; | 1426 | packet_num++; |
1359 | continue; | 1427 | continue; |
@@ -1418,7 +1486,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1418 | * Anyway, it does recover by eventually failing through | 1486 | * Anyway, it does recover by eventually failing through |
1419 | * into INIT_SELECTING state. | 1487 | * into INIT_SELECTING state. |
1420 | */ | 1488 | */ |
1421 | send_d6_renew(xid, &srv6_buf, requested_ipv6); | 1489 | if (opt & OPT_l) |
1490 | send_d6_info_request(xid); | ||
1491 | else | ||
1492 | send_d6_renew(xid, &srv6_buf, requested_ipv6); | ||
1422 | timeout >>= 1; | 1493 | timeout >>= 1; |
1423 | continue; | 1494 | continue; |
1424 | } | 1495 | } |
@@ -1432,8 +1503,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1432 | /* Lease is *really* about to run out, | 1503 | /* Lease is *really* about to run out, |
1433 | * try to find DHCP server using broadcast */ | 1504 | * try to find DHCP server using broadcast */ |
1434 | if (timeout > 0) { | 1505 | if (timeout > 0) { |
1435 | /* send a broadcast renew request */ | 1506 | if (opt & OPT_l) |
1436 | send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); | 1507 | send_d6_info_request(xid); |
1508 | else /* send a broadcast renew request */ | ||
1509 | send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); | ||
1437 | timeout >>= 1; | 1510 | timeout >>= 1; |
1438 | continue; | 1511 | continue; |
1439 | } | 1512 | } |
@@ -1740,6 +1813,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1740 | prefix_timeout = address_timeout; | 1813 | prefix_timeout = address_timeout; |
1741 | /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ | 1814 | /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ |
1742 | timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; | 1815 | timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; |
1816 | if (opt & OPT_l) { | ||
1817 | /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32) | ||
1818 | * and use its value instead of the default 1 day. | ||
1819 | */ | ||
1820 | timeout = 24 * 60 * 60; | ||
1821 | } | ||
1743 | /* paranoia: must not be too small */ | 1822 | /* paranoia: must not be too small */ |
1744 | /* timeout > 60 - ensures at least one unicast renew attempt */ | 1823 | /* timeout > 60 - ensures at least one unicast renew attempt */ |
1745 | if (timeout < 61) | 1824 | if (timeout < 61) |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 656295ff7..5a1f8fd7a 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -606,7 +606,7 @@ static ALWAYS_INLINE uint32_t random_xid(void) | |||
606 | /* Initialize the packet with the proper defaults */ | 606 | /* Initialize the packet with the proper defaults */ |
607 | static void init_packet(struct dhcp_packet *packet, char type) | 607 | static void init_packet(struct dhcp_packet *packet, char type) |
608 | { | 608 | { |
609 | uint16_t secs; | 609 | unsigned secs; |
610 | 610 | ||
611 | /* Fill in: op, htype, hlen, cookie fields; message type option: */ | 611 | /* Fill in: op, htype, hlen, cookie fields; message type option: */ |
612 | udhcp_init_header(packet, type); | 612 | udhcp_init_header(packet, type); |
@@ -617,7 +617,7 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
617 | if (client_data.first_secs == 0) | 617 | if (client_data.first_secs == 0) |
618 | client_data.first_secs = client_data.last_secs; | 618 | client_data.first_secs = client_data.last_secs; |
619 | secs = client_data.last_secs - client_data.first_secs; | 619 | secs = client_data.last_secs - client_data.first_secs; |
620 | packet->secs = htons(secs); | 620 | packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff; |
621 | 621 | ||
622 | memcpy(packet->chaddr, client_data.client_mac, 6); | 622 | memcpy(packet->chaddr, client_data.client_mac, 6); |
623 | if (client_data.clientid) | 623 | if (client_data.clientid) |
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 42fe71a36..b407a6cdb 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h | |||
@@ -22,8 +22,8 @@ struct client_data_t { | |||
22 | uint8_t *hostname; /* Optional hostname to use */ | 22 | uint8_t *hostname; /* Optional hostname to use */ |
23 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ | 23 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ |
24 | 24 | ||
25 | uint16_t first_secs; | 25 | unsigned first_secs; |
26 | uint16_t last_secs; | 26 | unsigned last_secs; |
27 | 27 | ||
28 | int sockfd; | 28 | int sockfd; |
29 | smallint listen_mode; | 29 | smallint listen_mode; |
diff --git a/networking/wget.c b/networking/wget.c index 5b85cce1f..4365c76ce 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -1142,7 +1142,7 @@ static void download_one_url(const char *url) | |||
1142 | * We are not sure it exists on remote side */ | 1142 | * We are not sure it exists on remote side */ |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | redir_limit = 5; | 1145 | redir_limit = 16; |
1146 | resolve_lsa: | 1146 | resolve_lsa: |
1147 | lsa = xhost2sockaddr(server.host, server.port); | 1147 | lsa = xhost2sockaddr(server.host, server.port); |
1148 | if (!(option_mask32 & WGET_OPT_QUIET)) { | 1148 | if (!(option_mask32 & WGET_OPT_QUIET)) { |
diff --git a/networking/whois.c b/networking/whois.c index 55e1de964..caa71ac51 100644 --- a/networking/whois.c +++ b/networking/whois.c | |||
@@ -53,7 +53,9 @@ static char *query(const char *host, int port, const char *domain) | |||
53 | fp = xfdopen_for_read(fd); | 53 | fp = xfdopen_for_read(fd); |
54 | 54 | ||
55 | success = 0; | 55 | success = 0; |
56 | while (fgets(linebuf, sizeof(linebuf)-1, fp)) { | 56 | while (bufpos < 32*1024 /* paranoia */ |
57 | && fgets(linebuf, sizeof(linebuf)-1, fp) | ||
58 | ) { | ||
57 | unsigned len; | 59 | unsigned len; |
58 | 60 | ||
59 | len = strcspn(linebuf, "\r\n"); | 61 | len = strcspn(linebuf, "\r\n"); |