diff options
author | Ron Yorston <rmy@pobox.com> | 2014-10-06 12:50:22 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2014-10-06 12:50:22 +0100 |
commit | b04d11dcbadda2620743a1dd923938f2f3043a38 (patch) | |
tree | 971afe425a81304b79e44122e220c7a69efe2616 /networking | |
parent | 124bbf02948b7ac0babb4ead04acd1559db182d3 (diff) | |
parent | 760d035699c4a878f9109544c1d35ea0d5f6b76c (diff) | |
download | busybox-w32-b04d11dcbadda2620743a1dd923938f2f3043a38.tar.gz busybox-w32-b04d11dcbadda2620743a1dd923938f2f3043a38.tar.bz2 busybox-w32-b04d11dcbadda2620743a1dd923938f2f3043a38.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r-- | networking/Config.src | 7 | ||||
-rw-r--r-- | networking/ftpd.c | 63 | ||||
-rw-r--r-- | networking/ntpd.c | 270 | ||||
-rw-r--r-- | networking/ping.c | 25 | ||||
-rw-r--r-- | networking/tftp.c | 21 | ||||
-rw-r--r-- | networking/udhcp/common.c | 2 | ||||
-rw-r--r-- | networking/udhcp/common.h | 1 | ||||
-rw-r--r-- | networking/zcip.c | 38 |
8 files changed, 253 insertions, 174 deletions
diff --git a/networking/Config.src b/networking/Config.src index fbad7ecb2..e56646917 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -134,6 +134,13 @@ config FEATURE_FTPD_ACCEPT_BROKEN_LIST | |||
134 | it increases the code size by ~40 bytes. | 134 | it increases the code size by ~40 bytes. |
135 | Most other ftp servers seem to behave similar to this. | 135 | Most other ftp servers seem to behave similar to this. |
136 | 136 | ||
137 | config FEATURE_FTP_AUTHENTICATION | ||
138 | bool "Enable authentication" | ||
139 | default y | ||
140 | depends on FTPD | ||
141 | help | ||
142 | Enable basic system login as seen in telnet etc. | ||
143 | |||
137 | config FTPGET | 144 | config FTPGET |
138 | bool "ftpget" | 145 | bool "ftpget" |
139 | default y | 146 | default y |
diff --git a/networking/ftpd.c b/networking/ftpd.c index 2d2a3a44c..6adcb1dee 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -622,7 +622,7 @@ popen_ls(const char *opt) | |||
622 | pid_t pid; | 622 | pid_t pid; |
623 | 623 | ||
624 | argv[0] = "ftpd"; | 624 | argv[0] = "ftpd"; |
625 | argv[1] = opt; /* "-l" or "-1" */ | 625 | argv[1] = opt; /* "-lA" or "-1A" */ |
626 | argv[2] = "--"; | 626 | argv[2] = "--"; |
627 | argv[3] = G.ftp_arg; | 627 | argv[3] = G.ftp_arg; |
628 | argv[4] = NULL; | 628 | argv[4] = NULL; |
@@ -699,7 +699,7 @@ handle_dir_common(int opts) | |||
699 | if (!(opts & USE_CTRL_CONN) && !port_or_pasv_was_seen()) | 699 | if (!(opts & USE_CTRL_CONN) && !port_or_pasv_was_seen()) |
700 | return; /* port_or_pasv_was_seen emitted error response */ | 700 | return; /* port_or_pasv_was_seen emitted error response */ |
701 | 701 | ||
702 | ls_fd = popen_ls((opts & LONG_LISTING) ? "-l" : "-1"); | 702 | ls_fd = popen_ls((opts & LONG_LISTING) ? "-lA" : "-1A"); |
703 | ls_fp = xfdopen_for_read(ls_fd); | 703 | ls_fp = xfdopen_for_read(ls_fd); |
704 | /* FIXME: filenames with embedded newlines are mishandled */ | 704 | /* FIXME: filenames with embedded newlines are mishandled */ |
705 | 705 | ||
@@ -1102,10 +1102,11 @@ enum { | |||
1102 | #if !BB_MMU | 1102 | #if !BB_MMU |
1103 | OPT_l = (1 << 0), | 1103 | OPT_l = (1 << 0), |
1104 | OPT_1 = (1 << 1), | 1104 | OPT_1 = (1 << 1), |
1105 | OPT_A = (1 << 2), | ||
1105 | #endif | 1106 | #endif |
1106 | OPT_v = (1 << ((!BB_MMU) * 2 + 0)), | 1107 | OPT_v = (1 << ((!BB_MMU) * 3 + 0)), |
1107 | OPT_S = (1 << ((!BB_MMU) * 2 + 1)), | 1108 | OPT_S = (1 << ((!BB_MMU) * 3 + 1)), |
1108 | OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE, | 1109 | OPT_w = (1 << ((!BB_MMU) * 3 + 2)) * ENABLE_FEATURE_FTP_WRITE, |
1109 | }; | 1110 | }; |
1110 | 1111 | ||
1111 | int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1112 | int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -1126,12 +1127,11 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) | |||
1126 | G.timeout = 2 * 60; | 1127 | G.timeout = 2 * 60; |
1127 | opt_complementary = "t+:T+:vv:SS"; | 1128 | opt_complementary = "t+:T+:vv:SS"; |
1128 | #if BB_MMU | 1129 | #if BB_MMU |
1129 | opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); | 1130 | opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); |
1130 | #else | 1131 | #else |
1131 | opts = getopt32(argv, "l1vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); | 1132 | opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); |
1132 | if (opts & (OPT_l|OPT_1)) { | 1133 | if (opts & (OPT_l|OPT_1)) { |
1133 | /* Our secret backdoor to ls */ | 1134 | /* Our secret backdoor to ls */ |
1134 | /* TODO: pass -A? It shows dot files */ | ||
1135 | /* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */ | 1135 | /* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */ |
1136 | if (fchdir(3) != 0) | 1136 | if (fchdir(3) != 0) |
1137 | _exit(127); | 1137 | _exit(127); |
@@ -1172,18 +1172,6 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) | |||
1172 | if (logmode) | 1172 | if (logmode) |
1173 | applet_name = xasprintf("%s[%u]", applet_name, (int)getpid()); | 1173 | applet_name = xasprintf("%s[%u]", applet_name, (int)getpid()); |
1174 | 1174 | ||
1175 | #if !BB_MMU | ||
1176 | G.root_fd = -1; | ||
1177 | #endif | ||
1178 | argv += optind; | ||
1179 | if (argv[0]) { | ||
1180 | #if !BB_MMU | ||
1181 | G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY); | ||
1182 | close_on_exec_on(G.root_fd); | ||
1183 | #endif | ||
1184 | xchroot(argv[0]); | ||
1185 | } | ||
1186 | |||
1187 | //umask(077); - admin can set umask before starting us | 1175 | //umask(077); - admin can set umask before starting us |
1188 | 1176 | ||
1189 | /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */ | 1177 | /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */ |
@@ -1199,23 +1187,22 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) | |||
1199 | WRITE_OK(FTP_GREET); | 1187 | WRITE_OK(FTP_GREET); |
1200 | signal(SIGALRM, timeout_handler); | 1188 | signal(SIGALRM, timeout_handler); |
1201 | 1189 | ||
1202 | #ifdef IF_WE_WANT_TO_REQUIRE_LOGIN | 1190 | #if ENABLE_FEATURE_FTP_AUTHENTICATION |
1203 | { | 1191 | { |
1204 | smallint user_was_specified = 0; | 1192 | struct passwd *pw = NULL; |
1193 | |||
1205 | while (1) { | 1194 | while (1) { |
1206 | uint32_t cmdval = cmdio_get_cmd_and_arg(); | 1195 | uint32_t cmdval = cmdio_get_cmd_and_arg(); |
1207 | 1196 | ||
1208 | if (cmdval == const_USER) { | 1197 | if (cmdval == const_USER) { |
1209 | if (G.ftp_arg == NULL || strcasecmp(G.ftp_arg, "anonymous") != 0) | 1198 | pw = getpwnam(G.ftp_arg); |
1210 | cmdio_write_raw(STR(FTP_LOGINERR)" Server is anonymous only\r\n"); | 1199 | cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); |
1211 | else { | ||
1212 | user_was_specified = 1; | ||
1213 | cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify the password\r\n"); | ||
1214 | } | ||
1215 | } else if (cmdval == const_PASS) { | 1200 | } else if (cmdval == const_PASS) { |
1216 | if (user_was_specified) | 1201 | if (check_password(pw, G.ftp_arg) > 0) { |
1217 | break; | 1202 | break; /* login success */ |
1218 | cmdio_write_raw(STR(FTP_NEEDUSER)" Login with USER\r\n"); | 1203 | } |
1204 | cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n"); | ||
1205 | pw = NULL; | ||
1219 | } else if (cmdval == const_QUIT) { | 1206 | } else if (cmdval == const_QUIT) { |
1220 | WRITE_OK(FTP_GOODBYE); | 1207 | WRITE_OK(FTP_GOODBYE); |
1221 | return 0; | 1208 | return 0; |
@@ -1223,10 +1210,24 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) | |||
1223 | cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n"); | 1210 | cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n"); |
1224 | } | 1211 | } |
1225 | } | 1212 | } |
1213 | change_identity(pw); | ||
1226 | } | 1214 | } |
1227 | WRITE_OK(FTP_LOGINOK); | 1215 | WRITE_OK(FTP_LOGINOK); |
1228 | #endif | 1216 | #endif |
1229 | 1217 | ||
1218 | /* Do this after auth, else /etc/passwd is not accessible */ | ||
1219 | #if !BB_MMU | ||
1220 | G.root_fd = -1; | ||
1221 | #endif | ||
1222 | argv += optind; | ||
1223 | if (argv[0]) { | ||
1224 | #if !BB_MMU | ||
1225 | G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY); | ||
1226 | close_on_exec_on(G.root_fd); | ||
1227 | #endif | ||
1228 | xchroot(argv[0]); | ||
1229 | } | ||
1230 | |||
1230 | /* RFC-959 Section 5.1 | 1231 | /* RFC-959 Section 5.1 |
1231 | * The following commands and options MUST be supported by every | 1232 | * The following commands and options MUST be supported by every |
1232 | * server-FTP and user-FTP, except in cases where the underlying | 1233 | * server-FTP and user-FTP, except in cases where the underlying |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 59607ed23..2d4f076d9 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -29,7 +29,7 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | //usage:#define ntpd_trivial_usage | 31 | //usage:#define ntpd_trivial_usage |
32 | //usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l")"] [-S PROG] [-p PEER]..." | 32 | //usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..." |
33 | //usage:#define ntpd_full_usage "\n\n" | 33 | //usage:#define ntpd_full_usage "\n\n" |
34 | //usage: "NTP client/server\n" | 34 | //usage: "NTP client/server\n" |
35 | //usage: "\n -d Verbose" | 35 | //usage: "\n -d Verbose" |
@@ -39,6 +39,7 @@ | |||
39 | //usage: "\n -w Do not set time (only query peers), implies -n" | 39 | //usage: "\n -w Do not set time (only query peers), implies -n" |
40 | //usage: IF_FEATURE_NTPD_SERVER( | 40 | //usage: IF_FEATURE_NTPD_SERVER( |
41 | //usage: "\n -l Run as server on port 123" | 41 | //usage: "\n -l Run as server on port 123" |
42 | //usage: "\n -I IFACE Bind server to IFACE, implies -l" | ||
42 | //usage: ) | 43 | //usage: ) |
43 | //usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" | 44 | //usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" |
44 | //usage: "\n -p PEER Obtain time from PEER (may be repeated)" | 45 | //usage: "\n -p PEER Obtain time from PEER (may be repeated)" |
@@ -108,36 +109,44 @@ | |||
108 | * datapoints after the step. | 109 | * datapoints after the step. |
109 | */ | 110 | */ |
110 | 111 | ||
111 | #define RETRY_INTERVAL 5 /* on error, retry in N secs */ | ||
112 | #define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */ | ||
113 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ | 112 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ |
114 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ | 113 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ |
115 | 114 | ||
116 | /* Clock discipline parameters and constants */ | 115 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ |
116 | #define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */ | ||
117 | #define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ | ||
117 | 118 | ||
118 | /* Step threshold (sec). std ntpd uses 0.128. | 119 | /* Step threshold (sec). std ntpd uses 0.128. |
119 | * Using exact power of 2 (1/8) results in smaller code */ | 120 | * Using exact power of 2 (1/8) results in smaller code |
121 | */ | ||
120 | #define STEP_THRESHOLD 0.125 | 122 | #define STEP_THRESHOLD 0.125 |
121 | #define WATCH_THRESHOLD 128 /* stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ | 123 | /* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ |
124 | #define WATCH_THRESHOLD 128 | ||
122 | /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ | 125 | /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ |
123 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ | 126 | //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ |
124 | 127 | ||
128 | /* | ||
129 | * If we got |offset| > BIGOFF from a peer, cap next query interval | ||
130 | * for this peer by this many seconds: | ||
131 | */ | ||
132 | #define BIGOFF (STEP_THRESHOLD * 8) | ||
133 | #define BIGOFF_INTERVAL (1 << 7) /* 128 s */ | ||
134 | |||
125 | #define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ | 135 | #define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ |
126 | #define BURSTPOLL 0 /* initial poll */ | 136 | #define BURSTPOLL 0 /* initial poll */ |
127 | #define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ | 137 | #define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ |
128 | /* If we got largish offset from a peer, cap next query interval | 138 | /* |
129 | * for this peer by this many seconds: | 139 | * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL, |
130 | */ | 140 | * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_). |
131 | #define BIGOFF_INTERVAL (1 << 6) | ||
132 | /* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL, | ||
133 | * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_). | ||
134 | */ | 141 | */ |
135 | #define BIGPOLL 10 /* 2^10 sec ~= 17 min */ | 142 | #define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */ |
136 | #define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ | 143 | #define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ |
137 | /* Actively lower poll when we see such big offsets. | 144 | /* |
145 | * Actively lower poll when we see such big offsets. | ||
138 | * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively | 146 | * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively |
139 | * if offset increases over ~0.04 sec */ | 147 | * if offset increases over ~0.04 sec |
140 | #define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) | 148 | */ |
149 | //#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) | ||
141 | #define MINDISP 0.01 /* minimum dispersion (sec) */ | 150 | #define MINDISP 0.01 /* minimum dispersion (sec) */ |
142 | #define MAXDISP 16 /* maximum dispersion (sec) */ | 151 | #define MAXDISP 16 /* maximum dispersion (sec) */ |
143 | #define MAXSTRAT 16 /* maximum stratum (infinity metric) */ | 152 | #define MAXSTRAT 16 /* maximum stratum (infinity metric) */ |
@@ -283,6 +292,7 @@ enum { | |||
283 | OPT_p = (1 << 5), | 292 | OPT_p = (1 << 5), |
284 | OPT_S = (1 << 6), | 293 | OPT_S = (1 << 6), |
285 | OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER, | 294 | OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER, |
295 | OPT_I = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER, | ||
286 | /* We hijack some bits for other purposes */ | 296 | /* We hijack some bits for other purposes */ |
287 | OPT_qq = (1 << 31), | 297 | OPT_qq = (1 << 31), |
288 | }; | 298 | }; |
@@ -301,6 +311,7 @@ struct globals { | |||
301 | llist_t *ntp_peers; | 311 | llist_t *ntp_peers; |
302 | #if ENABLE_FEATURE_NTPD_SERVER | 312 | #if ENABLE_FEATURE_NTPD_SERVER |
303 | int listen_fd; | 313 | int listen_fd; |
314 | char *if_name; | ||
304 | # define G_listen_fd (G.listen_fd) | 315 | # define G_listen_fd (G.listen_fd) |
305 | #else | 316 | #else |
306 | # define G_listen_fd (-1) | 317 | # define G_listen_fd (-1) |
@@ -969,6 +980,16 @@ step_time(double offset) | |||
969 | } | 980 | } |
970 | } | 981 | } |
971 | 982 | ||
983 | static void clamp_pollexp_and_set_MAXSTRAT(void) | ||
984 | { | ||
985 | if (G.poll_exp < MINPOLL) | ||
986 | G.poll_exp = MINPOLL; | ||
987 | if (G.poll_exp > BIGPOLL) | ||
988 | G.poll_exp = BIGPOLL; | ||
989 | G.polladj_count = 0; | ||
990 | G.stratum = MAXSTRAT; | ||
991 | } | ||
992 | |||
972 | 993 | ||
973 | /* | 994 | /* |
974 | * Selection and clustering, and their helpers | 995 | * Selection and clustering, and their helpers |
@@ -1450,9 +1471,7 @@ update_local_clock(peer_t *p) | |||
1450 | exit(0); | 1471 | exit(0); |
1451 | } | 1472 | } |
1452 | 1473 | ||
1453 | G.polladj_count = 0; | 1474 | clamp_pollexp_and_set_MAXSTRAT(); |
1454 | G.poll_exp = MINPOLL; | ||
1455 | G.stratum = MAXSTRAT; | ||
1456 | 1475 | ||
1457 | run_script("step", offset); | 1476 | run_script("step", offset); |
1458 | 1477 | ||
@@ -1469,11 +1488,10 @@ update_local_clock(peer_t *p) | |||
1469 | 1488 | ||
1470 | } else { /* abs_offset <= STEP_THRESHOLD */ | 1489 | } else { /* abs_offset <= STEP_THRESHOLD */ |
1471 | 1490 | ||
1472 | if (G.poll_exp < MINPOLL && G.initial_poll_complete) { | 1491 | /* The ratio is calculated before jitter is updated to make |
1473 | VERB4 bb_error_msg("small offset:%+f, disabling burst mode", offset); | 1492 | * poll adjust code more sensitive to large offsets. |
1474 | G.polladj_count = 0; | 1493 | */ |
1475 | G.poll_exp = MINPOLL; | 1494 | G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter; |
1476 | } | ||
1477 | 1495 | ||
1478 | /* Compute the clock jitter as the RMS of exponentially | 1496 | /* Compute the clock jitter as the RMS of exponentially |
1479 | * weighted offset differences. Used by the poll adjust code. | 1497 | * weighted offset differences. Used by the poll adjust code. |
@@ -1481,6 +1499,8 @@ update_local_clock(peer_t *p) | |||
1481 | etemp = SQUARE(G.discipline_jitter); | 1499 | etemp = SQUARE(G.discipline_jitter); |
1482 | dtemp = SQUARE(offset - G.last_update_offset); | 1500 | dtemp = SQUARE(offset - G.last_update_offset); |
1483 | G.discipline_jitter = SQRT(etemp + (dtemp - etemp) / AVG); | 1501 | G.discipline_jitter = SQRT(etemp + (dtemp - etemp) / AVG); |
1502 | if (G.discipline_jitter < G_precision_sec) | ||
1503 | G.discipline_jitter = G_precision_sec; | ||
1484 | 1504 | ||
1485 | switch (G.discipline_state) { | 1505 | switch (G.discipline_state) { |
1486 | case STATE_NSET: | 1506 | case STATE_NSET: |
@@ -1557,10 +1577,6 @@ update_local_clock(peer_t *p) | |||
1557 | } | 1577 | } |
1558 | } | 1578 | } |
1559 | 1579 | ||
1560 | if (G.discipline_jitter < G_precision_sec) | ||
1561 | G.discipline_jitter = G_precision_sec; | ||
1562 | G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter; | ||
1563 | |||
1564 | G.reftime = G.cur_time; | 1580 | G.reftime = G.cur_time; |
1565 | G.ntp_status = p->lastpkt_status; | 1581 | G.ntp_status = p->lastpkt_status; |
1566 | G.refid = p->lastpkt_refid; | 1582 | G.refid = p->lastpkt_refid; |
@@ -1657,30 +1673,53 @@ update_local_clock(peer_t *p) | |||
1657 | * (helpers first) | 1673 | * (helpers first) |
1658 | */ | 1674 | */ |
1659 | static unsigned | 1675 | static unsigned |
1660 | retry_interval(void) | 1676 | poll_interval(int upper_bound) |
1661 | { | ||
1662 | /* Local problem, want to retry soon */ | ||
1663 | unsigned interval, r; | ||
1664 | interval = RETRY_INTERVAL; | ||
1665 | r = rand(); | ||
1666 | interval += r % (unsigned)(RETRY_INTERVAL / 4); | ||
1667 | VERB4 bb_error_msg("chose retry interval:%u", interval); | ||
1668 | return interval; | ||
1669 | } | ||
1670 | static unsigned | ||
1671 | poll_interval(int exponent) | ||
1672 | { | 1677 | { |
1673 | unsigned interval, r, mask; | 1678 | unsigned interval, r, mask; |
1674 | exponent = G.poll_exp + exponent; | 1679 | interval = 1 << G.poll_exp; |
1675 | if (exponent < 0) | 1680 | if (interval > upper_bound) |
1676 | exponent = 0; | 1681 | interval = upper_bound; |
1677 | interval = 1 << exponent; | ||
1678 | mask = ((interval-1) >> 4) | 1; | 1682 | mask = ((interval-1) >> 4) | 1; |
1679 | r = rand(); | 1683 | r = rand(); |
1680 | interval += r & mask; /* ~ random(0..1) * interval/16 */ | 1684 | interval += r & mask; /* ~ random(0..1) * interval/16 */ |
1681 | VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent); | 1685 | VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp); |
1682 | return interval; | 1686 | return interval; |
1683 | } | 1687 | } |
1688 | static void | ||
1689 | adjust_poll(int count) | ||
1690 | { | ||
1691 | G.polladj_count += count; | ||
1692 | if (G.polladj_count > POLLADJ_LIMIT) { | ||
1693 | G.polladj_count = 0; | ||
1694 | if (G.poll_exp < MAXPOLL) { | ||
1695 | G.poll_exp++; | ||
1696 | VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d", | ||
1697 | G.discipline_jitter, G.poll_exp); | ||
1698 | } | ||
1699 | } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp > BIGPOLL)) { | ||
1700 | G.polladj_count = 0; | ||
1701 | if (G.poll_exp > MINPOLL) { | ||
1702 | llist_t *item; | ||
1703 | |||
1704 | G.poll_exp--; | ||
1705 | /* Correct p->next_action_time in each peer | ||
1706 | * which waits for sending, so that they send earlier. | ||
1707 | * Old pp->next_action_time are on the order | ||
1708 | * of t + (1 << old_poll_exp) + small_random, | ||
1709 | * we simply need to subtract ~half of that. | ||
1710 | */ | ||
1711 | for (item = G.ntp_peers; item != NULL; item = item->link) { | ||
1712 | peer_t *pp = (peer_t *) item->data; | ||
1713 | if (pp->p_fd < 0) | ||
1714 | pp->next_action_time -= (1 << G.poll_exp); | ||
1715 | } | ||
1716 | VERB4 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d", | ||
1717 | G.discipline_jitter, G.poll_exp); | ||
1718 | } | ||
1719 | } else { | ||
1720 | VERB4 bb_error_msg("polladj: count:%d", G.polladj_count); | ||
1721 | } | ||
1722 | } | ||
1684 | static NOINLINE void | 1723 | static NOINLINE void |
1685 | recv_and_process_peer_pkt(peer_t *p) | 1724 | recv_and_process_peer_pkt(peer_t *p) |
1686 | { | 1725 | { |
@@ -1700,19 +1739,23 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1700 | * ntp servers reply from their *other IP*. | 1739 | * ntp servers reply from their *other IP*. |
1701 | * TODO: maybe we should check at least what we can: from.port == 123? | 1740 | * TODO: maybe we should check at least what we can: from.port == 123? |
1702 | */ | 1741 | */ |
1742 | recv_again: | ||
1703 | size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT); | 1743 | size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT); |
1704 | if (size == -1) { | 1744 | if (size < 0) { |
1705 | bb_perror_msg("recv(%s) error", p->p_dotted); | 1745 | if (errno == EINTR) |
1706 | if (errno == EHOSTUNREACH || errno == EHOSTDOWN | 1746 | /* Signal caught */ |
1707 | || errno == ENETUNREACH || errno == ENETDOWN | 1747 | goto recv_again; |
1708 | || errno == ECONNREFUSED || errno == EADDRNOTAVAIL | 1748 | if (errno == EAGAIN) |
1709 | || errno == EAGAIN | 1749 | /* There was no packet after all |
1710 | ) { | 1750 | * (poll() returning POLLIN for a fd |
1711 | //TODO: always do this? | 1751 | * is not a ironclad guarantee that data is there) |
1712 | interval = retry_interval(); | 1752 | */ |
1713 | goto set_next_and_ret; | 1753 | return; |
1714 | } | 1754 | /* |
1715 | xfunc_die(); | 1755 | * If you need a different handling for a specific |
1756 | * errno, always explain it in comment. | ||
1757 | */ | ||
1758 | bb_perror_msg_and_die("recv(%s) error", p->p_dotted); | ||
1716 | } | 1759 | } |
1717 | 1760 | ||
1718 | if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { | 1761 | if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { |
@@ -1738,10 +1781,15 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1738 | || msg.m_stratum == 0 | 1781 | || msg.m_stratum == 0 |
1739 | || msg.m_stratum > NTP_MAXSTRATUM | 1782 | || msg.m_stratum > NTP_MAXSTRATUM |
1740 | ) { | 1783 | ) { |
1741 | // TODO: stratum 0 responses may have commands in 32-bit m_refid field: | ||
1742 | // "DENY", "RSTR" - peer does not like us at all | ||
1743 | // "RATE" - peer is overloaded, reduce polling freq | ||
1744 | bb_error_msg("reply from %s: peer is unsynced", p->p_dotted); | 1784 | bb_error_msg("reply from %s: peer is unsynced", p->p_dotted); |
1785 | /* | ||
1786 | * Stratum 0 responses may have commands in 32-bit m_refid field: | ||
1787 | * "DENY", "RSTR" - peer does not like us at all, | ||
1788 | * "RATE" - peer is overloaded, reduce polling freq. | ||
1789 | * If poll interval is small, increase it. | ||
1790 | */ | ||
1791 | if (G.poll_exp < BIGPOLL) | ||
1792 | goto increase_interval; | ||
1745 | goto pick_normal_interval; | 1793 | goto pick_normal_interval; |
1746 | } | 1794 | } |
1747 | 1795 | ||
@@ -1830,21 +1878,36 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1830 | /* Muck with statictics and update the clock */ | 1878 | /* Muck with statictics and update the clock */ |
1831 | filter_datapoints(p); | 1879 | filter_datapoints(p); |
1832 | q = select_and_cluster(); | 1880 | q = select_and_cluster(); |
1833 | rc = -1; | 1881 | rc = 0; |
1834 | if (q) { | 1882 | if (q) { |
1835 | rc = 0; | ||
1836 | if (!(option_mask32 & OPT_w)) { | 1883 | if (!(option_mask32 & OPT_w)) { |
1837 | rc = update_local_clock(q); | 1884 | rc = update_local_clock(q); |
1885 | #if 0 | ||
1886 | //Disabled this because there is a case where largish offsets | ||
1887 | //are unavoidable: if network round-trip delay is, say, ~0.6s, | ||
1888 | //error in offset estimation would be ~delay/2 ~= 0.3s. | ||
1889 | //Thus, offsets will be usually in -0.3...0.3s range. | ||
1890 | //In this case, this code would keep poll interval small, | ||
1891 | //but it won't be helping. | ||
1892 | //BIGOFF check below deals with a case of seeing multi-second offsets. | ||
1893 | |||
1838 | /* If drift is dangerously large, immediately | 1894 | /* If drift is dangerously large, immediately |
1839 | * drop poll interval one step down. | 1895 | * drop poll interval one step down. |
1840 | */ | 1896 | */ |
1841 | if (fabs(q->filter_offset) >= POLLDOWN_OFFSET) { | 1897 | if (fabs(q->filter_offset) >= POLLDOWN_OFFSET) { |
1842 | VERB4 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset); | 1898 | VERB4 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset); |
1843 | goto poll_down; | 1899 | adjust_poll(-POLLADJ_LIMIT * 3); |
1900 | rc = 0; | ||
1844 | } | 1901 | } |
1902 | #endif | ||
1845 | } | 1903 | } |
1904 | } else { | ||
1905 | /* No peer selected. | ||
1906 | * If poll interval is small, increase it. | ||
1907 | */ | ||
1908 | if (G.poll_exp < BIGPOLL) | ||
1909 | goto increase_interval; | ||
1846 | } | 1910 | } |
1847 | /* else: no peer selected, rc = -1: we want to poll more often */ | ||
1848 | 1911 | ||
1849 | if (rc != 0) { | 1912 | if (rc != 0) { |
1850 | /* Adjust the poll interval by comparing the current offset | 1913 | /* Adjust the poll interval by comparing the current offset |
@@ -1856,50 +1919,17 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1856 | if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) { | 1919 | if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) { |
1857 | /* was += G.poll_exp but it is a bit | 1920 | /* was += G.poll_exp but it is a bit |
1858 | * too optimistic for my taste at high poll_exp's */ | 1921 | * too optimistic for my taste at high poll_exp's */ |
1859 | G.polladj_count += MINPOLL; | 1922 | increase_interval: |
1860 | if (G.polladj_count > POLLADJ_LIMIT) { | 1923 | adjust_poll(MINPOLL); |
1861 | G.polladj_count = 0; | ||
1862 | if (G.poll_exp < MAXPOLL) { | ||
1863 | G.poll_exp++; | ||
1864 | VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d", | ||
1865 | G.discipline_jitter, G.poll_exp); | ||
1866 | } | ||
1867 | } else { | ||
1868 | VERB4 bb_error_msg("polladj: incr:%d", G.polladj_count); | ||
1869 | } | ||
1870 | } else { | 1924 | } else { |
1871 | G.polladj_count -= G.poll_exp * 2; | 1925 | adjust_poll(-G.poll_exp * 2); |
1872 | if (G.polladj_count < -POLLADJ_LIMIT || G.poll_exp >= BIGPOLL) { | ||
1873 | poll_down: | ||
1874 | G.polladj_count = 0; | ||
1875 | if (G.poll_exp > MINPOLL) { | ||
1876 | llist_t *item; | ||
1877 | |||
1878 | G.poll_exp--; | ||
1879 | /* Correct p->next_action_time in each peer | ||
1880 | * which waits for sending, so that they send earlier. | ||
1881 | * Old pp->next_action_time are on the order | ||
1882 | * of t + (1 << old_poll_exp) + small_random, | ||
1883 | * we simply need to subtract ~half of that. | ||
1884 | */ | ||
1885 | for (item = G.ntp_peers; item != NULL; item = item->link) { | ||
1886 | peer_t *pp = (peer_t *) item->data; | ||
1887 | if (pp->p_fd < 0) | ||
1888 | pp->next_action_time -= (1 << G.poll_exp); | ||
1889 | } | ||
1890 | VERB4 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d", | ||
1891 | G.discipline_jitter, G.poll_exp); | ||
1892 | } | ||
1893 | } else { | ||
1894 | VERB4 bb_error_msg("polladj: decr:%d", G.polladj_count); | ||
1895 | } | ||
1896 | } | 1926 | } |
1897 | } | 1927 | } |
1898 | 1928 | ||
1899 | /* Decide when to send new query for this peer */ | 1929 | /* Decide when to send new query for this peer */ |
1900 | pick_normal_interval: | 1930 | pick_normal_interval: |
1901 | interval = poll_interval(0); | 1931 | interval = poll_interval(INT_MAX); |
1902 | if (fabs(offset) >= STEP_THRESHOLD * 8 && interval > BIGOFF_INTERVAL) { | 1932 | if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) { |
1903 | /* If we are synced, offsets are less than STEP_THRESHOLD, | 1933 | /* If we are synced, offsets are less than STEP_THRESHOLD, |
1904 | * or at the very least not much larger than it. | 1934 | * or at the very least not much larger than it. |
1905 | * Now we see a largish one. | 1935 | * Now we see a largish one. |
@@ -1914,7 +1944,6 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1914 | interval = BIGOFF_INTERVAL; | 1944 | interval = BIGOFF_INTERVAL; |
1915 | } | 1945 | } |
1916 | 1946 | ||
1917 | set_next_and_ret: | ||
1918 | set_next(p, interval); | 1947 | set_next(p, interval); |
1919 | } | 1948 | } |
1920 | 1949 | ||
@@ -2085,6 +2114,7 @@ static NOINLINE void ntp_init(char **argv) | |||
2085 | bb_error_msg_and_die(bb_msg_you_must_be_root); | 2114 | bb_error_msg_and_die(bb_msg_you_must_be_root); |
2086 | 2115 | ||
2087 | /* Set some globals */ | 2116 | /* Set some globals */ |
2117 | G.discipline_jitter = G_precision_sec; | ||
2088 | G.stratum = MAXSTRAT; | 2118 | G.stratum = MAXSTRAT; |
2089 | if (BURSTPOLL != 0) | 2119 | if (BURSTPOLL != 0) |
2090 | G.poll_exp = BURSTPOLL; /* speeds up initial sync */ | 2120 | G.poll_exp = BURSTPOLL; /* speeds up initial sync */ |
@@ -2092,13 +2122,19 @@ static NOINLINE void ntp_init(char **argv) | |||
2092 | 2122 | ||
2093 | /* Parse options */ | 2123 | /* Parse options */ |
2094 | peers = NULL; | 2124 | peers = NULL; |
2095 | opt_complementary = "dd:p::wn"; /* d: counter; p: list; -w implies -n */ | 2125 | opt_complementary = "dd:p::wn" /* -d: counter; -p: list; -w implies -n */ |
2126 | IF_FEATURE_NTPD_SERVER(":Il"); /* -I implies -l */ | ||
2096 | opts = getopt32(argv, | 2127 | opts = getopt32(argv, |
2097 | "nqNx" /* compat */ | 2128 | "nqNx" /* compat */ |
2098 | "wp:S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ | 2129 | "wp:S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ |
2130 | IF_FEATURE_NTPD_SERVER("I:") /* compat */ | ||
2099 | "d" /* compat */ | 2131 | "d" /* compat */ |
2100 | "46aAbgL", /* compat, ignored */ | 2132 | "46aAbgL", /* compat, ignored */ |
2101 | &peers, &G.script_name, &G.verbose); | 2133 | &peers,&G.script_name, |
2134 | #if ENABLE_FEATURE_NTPD_SERVER | ||
2135 | &G.if_name, | ||
2136 | #endif | ||
2137 | &G.verbose); | ||
2102 | 2138 | ||
2103 | // if (opts & OPT_x) /* disable stepping, only slew is allowed */ | 2139 | // if (opts & OPT_x) /* disable stepping, only slew is allowed */ |
2104 | // G.time_was_stepped = 1; | 2140 | // G.time_was_stepped = 1; |
@@ -2130,18 +2166,22 @@ static NOINLINE void ntp_init(char **argv) | |||
2130 | /* -l but no peers: "stratum 1 server" mode */ | 2166 | /* -l but no peers: "stratum 1 server" mode */ |
2131 | G.stratum = 1; | 2167 | G.stratum = 1; |
2132 | } | 2168 | } |
2133 | if (!(opts & OPT_n)) { | ||
2134 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); | ||
2135 | logmode = LOGMODE_NONE; | ||
2136 | } | ||
2137 | #if ENABLE_FEATURE_NTPD_SERVER | 2169 | #if ENABLE_FEATURE_NTPD_SERVER |
2138 | G_listen_fd = -1; | 2170 | G_listen_fd = -1; |
2139 | if (opts & OPT_l) { | 2171 | if (opts & OPT_l) { |
2140 | G_listen_fd = create_and_bind_dgram_or_die(NULL, 123); | 2172 | G_listen_fd = create_and_bind_dgram_or_die(NULL, 123); |
2173 | if (opts & OPT_I) { | ||
2174 | if (setsockopt_bindtodevice(G_listen_fd, G.if_name)) | ||
2175 | xfunc_die(); | ||
2176 | } | ||
2141 | socket_want_pktinfo(G_listen_fd); | 2177 | socket_want_pktinfo(G_listen_fd); |
2142 | setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); | 2178 | setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); |
2143 | } | 2179 | } |
2144 | #endif | 2180 | #endif |
2181 | if (!(opts & OPT_n)) { | ||
2182 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); | ||
2183 | logmode = LOGMODE_NONE; | ||
2184 | } | ||
2145 | /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ | 2185 | /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ |
2146 | if (opts & OPT_N) | 2186 | if (opts & OPT_N) |
2147 | setpriority(PRIO_PROCESS, 0, -15); | 2187 | setpriority(PRIO_PROCESS, 0, -15); |
@@ -2229,6 +2269,9 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
2229 | if (p->p_fd == -1) { | 2269 | if (p->p_fd == -1) { |
2230 | /* Time to send new req */ | 2270 | /* Time to send new req */ |
2231 | if (--cnt == 0) { | 2271 | if (--cnt == 0) { |
2272 | VERB4 bb_error_msg("disabling burst mode"); | ||
2273 | G.polladj_count = 0; | ||
2274 | G.poll_exp = MINPOLL; | ||
2232 | G.initial_poll_complete = 1; | 2275 | G.initial_poll_complete = 1; |
2233 | } | 2276 | } |
2234 | send_query_to_peer(p); | 2277 | send_query_to_peer(p); |
@@ -2236,7 +2279,10 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
2236 | /* Timed out waiting for reply */ | 2279 | /* Timed out waiting for reply */ |
2237 | close(p->p_fd); | 2280 | close(p->p_fd); |
2238 | p->p_fd = -1; | 2281 | p->p_fd = -1; |
2239 | timeout = poll_interval(-2); /* -2: try a bit sooner */ | 2282 | /* If poll interval is small, increase it */ |
2283 | if (G.poll_exp < BIGPOLL) | ||
2284 | adjust_poll(MINPOLL); | ||
2285 | timeout = poll_interval(NOREPLY_INTERVAL); | ||
2240 | bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", | 2286 | bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", |
2241 | p->p_dotted, p->reachable_bits, timeout); | 2287 | p->p_dotted, p->reachable_bits, timeout); |
2242 | set_next(p, timeout); | 2288 | set_next(p, timeout); |
@@ -2327,9 +2373,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
2327 | goto have_reachable_peer; | 2373 | goto have_reachable_peer; |
2328 | } | 2374 | } |
2329 | /* No peer responded for last 8 packets, panic */ | 2375 | /* No peer responded for last 8 packets, panic */ |
2330 | G.polladj_count = 0; | 2376 | clamp_pollexp_and_set_MAXSTRAT(); |
2331 | G.poll_exp = MINPOLL; | ||
2332 | G.stratum = MAXSTRAT; | ||
2333 | run_script("unsync", 0.0); | 2377 | run_script("unsync", 0.0); |
2334 | have_reachable_peer: ; | 2378 | have_reachable_peer: ; |
2335 | } | 2379 | } |
diff --git a/networking/ping.c b/networking/ping.c index 5e4771f5a..c475395e7 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -100,8 +100,9 @@ | |||
100 | //usage: "\n (after all -c CNT packets are sent)" | 100 | //usage: "\n (after all -c CNT packets are sent)" |
101 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" | 101 | //usage: "\n -w SEC Seconds until ping exits (default:infinite)" |
102 | //usage: "\n (can exit earlier with -c CNT)" | 102 | //usage: "\n (can exit earlier with -c CNT)" |
103 | //usage: "\n -q Quiet, only displays output at start" | 103 | //usage: "\n -q Quiet, only display output at start" |
104 | //usage: "\n and when finished" | 104 | //usage: "\n and when finished" |
105 | //usage: "\n -p Pattern to use for payload" | ||
105 | //usage: | 106 | //usage: |
106 | //usage:# define ping6_trivial_usage | 107 | //usage:# define ping6_trivial_usage |
107 | //usage: "[OPTIONS] HOST" | 108 | //usage: "[OPTIONS] HOST" |
@@ -110,8 +111,9 @@ | |||
110 | //usage: "\n -c CNT Send only CNT pings" | 111 | //usage: "\n -c CNT Send only CNT pings" |
111 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" | 112 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" |
112 | //usage: "\n -I IFACE/IP Use interface or IP address as source" | 113 | //usage: "\n -I IFACE/IP Use interface or IP address as source" |
113 | //usage: "\n -q Quiet, only displays output at start" | 114 | //usage: "\n -q Quiet, only display output at start" |
114 | //usage: "\n and when finished" | 115 | //usage: "\n and when finished" |
116 | //usage: "\n -p Pattern to use for payload" | ||
115 | //usage: | 117 | //usage: |
116 | //usage:#endif | 118 | //usage:#endif |
117 | //usage: | 119 | //usage: |
@@ -330,7 +332,7 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
330 | 332 | ||
331 | /* Full(er) version */ | 333 | /* Full(er) version */ |
332 | 334 | ||
333 | #define OPT_STRING ("qvc:s:t:w:W:I:n4" IF_PING6("6")) | 335 | #define OPT_STRING ("qvc:s:t:w:W:I:np:4" IF_PING6("6")) |
334 | enum { | 336 | enum { |
335 | OPT_QUIET = 1 << 0, | 337 | OPT_QUIET = 1 << 0, |
336 | OPT_VERBOSE = 1 << 1, | 338 | OPT_VERBOSE = 1 << 1, |
@@ -341,8 +343,9 @@ enum { | |||
341 | OPT_W = 1 << 6, | 343 | OPT_W = 1 << 6, |
342 | OPT_I = 1 << 7, | 344 | OPT_I = 1 << 7, |
343 | /*OPT_n = 1 << 8, - ignored */ | 345 | /*OPT_n = 1 << 8, - ignored */ |
344 | OPT_IPV4 = 1 << 9, | 346 | OPT_p = 1 << 9, |
345 | OPT_IPV6 = (1 << 10) * ENABLE_PING6, | 347 | OPT_IPV4 = 1 << 10, |
348 | OPT_IPV6 = (1 << 11) * ENABLE_PING6, | ||
346 | }; | 349 | }; |
347 | 350 | ||
348 | 351 | ||
@@ -355,6 +358,7 @@ struct globals { | |||
355 | unsigned opt_ttl; | 358 | unsigned opt_ttl; |
356 | unsigned long ntransmitted, nreceived, nrepeats; | 359 | unsigned long ntransmitted, nreceived, nrepeats; |
357 | uint16_t myid; | 360 | uint16_t myid; |
361 | uint8_t pattern; | ||
358 | unsigned tmin, tmax; /* in us */ | 362 | unsigned tmin, tmax; /* in us */ |
359 | unsigned long long tsum; /* in us, sum of all times */ | 363 | unsigned long long tsum; /* in us, sum of all times */ |
360 | unsigned deadline; | 364 | unsigned deadline; |
@@ -485,7 +489,7 @@ static void sendping4(int junk UNUSED_PARAM) | |||
485 | { | 489 | { |
486 | struct icmp *pkt = G.snd_packet; | 490 | struct icmp *pkt = G.snd_packet; |
487 | 491 | ||
488 | //memset(pkt, 0, datalen + ICMP_MINLEN + 4); - G.snd_packet was xzalloced | 492 | memset(pkt, G.pattern, datalen + ICMP_MINLEN + 4); |
489 | pkt->icmp_type = ICMP_ECHO; | 493 | pkt->icmp_type = ICMP_ECHO; |
490 | /*pkt->icmp_code = 0;*/ | 494 | /*pkt->icmp_code = 0;*/ |
491 | pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */ | 495 | pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */ |
@@ -508,7 +512,7 @@ static void sendping6(int junk UNUSED_PARAM) | |||
508 | { | 512 | { |
509 | struct icmp6_hdr *pkt = G.snd_packet; | 513 | struct icmp6_hdr *pkt = G.snd_packet; |
510 | 514 | ||
511 | //memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4); | 515 | memset(pkt, G.pattern, datalen + sizeof(struct icmp6_hdr) + 4); |
512 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; | 516 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; |
513 | /*pkt->icmp6_code = 0;*/ | 517 | /*pkt->icmp6_code = 0;*/ |
514 | /*pkt->icmp6_cksum = 0;*/ | 518 | /*pkt->icmp6_cksum = 0;*/ |
@@ -850,13 +854,13 @@ static void ping(len_and_sockaddr *lsa) | |||
850 | static int common_ping_main(int opt, char **argv) | 854 | static int common_ping_main(int opt, char **argv) |
851 | { | 855 | { |
852 | len_and_sockaddr *lsa; | 856 | len_and_sockaddr *lsa; |
853 | char *str_s; | 857 | char *str_s, *str_p; |
854 | 858 | ||
855 | INIT_G(); | 859 | INIT_G(); |
856 | 860 | ||
857 | /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */ | 861 | /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */ |
858 | opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+"; | 862 | opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+"; |
859 | opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I); | 863 | opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p); |
860 | if (opt & OPT_s) | 864 | if (opt & OPT_s) |
861 | datalen = xatou16(str_s); // -s | 865 | datalen = xatou16(str_s); // -s |
862 | if (opt & OPT_I) { // -I | 866 | if (opt & OPT_I) { // -I |
@@ -867,6 +871,9 @@ static int common_ping_main(int opt, char **argv) | |||
867 | str_I = NULL; /* don't try to bind to device later */ | 871 | str_I = NULL; /* don't try to bind to device later */ |
868 | } | 872 | } |
869 | } | 873 | } |
874 | if (opt & OPT_p) | ||
875 | G.pattern = xstrtou_range(str_p, 16, 0, 255); | ||
876 | |||
870 | myid = (uint16_t) getpid(); | 877 | myid = (uint16_t) getpid(); |
871 | hostname = argv[optind]; | 878 | hostname = argv[optind]; |
872 | #if ENABLE_PING6 | 879 | #if ENABLE_PING6 |
diff --git a/networking/tftp.c b/networking/tftp.c index 630fdaf9a..7c0ee58d7 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -117,8 +117,10 @@ struct globals { | |||
117 | /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ | 117 | /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ |
118 | uint8_t error_pkt[4 + 32]; | 118 | uint8_t error_pkt[4 + 32]; |
119 | struct passwd *pw; | 119 | struct passwd *pw; |
120 | /* used in tftpd_main(), a bit big for stack: */ | 120 | /* Used in tftpd_main() for initial packet */ |
121 | char block_buf[TFTP_BLKSIZE_DEFAULT]; | 121 | /* Some HP PA-RISC firmware always sends fixed 516-byte requests */ |
122 | char block_buf[516]; | ||
123 | char block_buf_tail[1]; | ||
122 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR | 124 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR |
123 | off_t pos; | 125 | off_t pos; |
124 | off_t size; | 126 | off_t size; |
@@ -793,14 +795,16 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
793 | xchroot(argv[0]); | 795 | xchroot(argv[0]); |
794 | } | 796 | } |
795 | 797 | ||
796 | result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf), | 798 | result = recv_from_to(STDIN_FILENO, |
799 | G.block_buf, sizeof(G.block_buf) + 1, | ||
800 | /* ^^^ sizeof+1 to reliably detect oversized input */ | ||
797 | 0 /* flags */, | 801 | 0 /* flags */, |
798 | &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); | 802 | &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); |
799 | 803 | ||
800 | error_msg = "malformed packet"; | 804 | error_msg = "malformed packet"; |
801 | opcode = ntohs(*(uint16_t*)G.block_buf); | 805 | opcode = ntohs(*(uint16_t*)G.block_buf); |
802 | if (result < 4 || result >= sizeof(G.block_buf) | 806 | if (result < 4 || result > sizeof(G.block_buf) |
803 | || G.block_buf[result-1] != '\0' | 807 | /*|| G.block_buf[result-1] != '\0' - bug compatibility, see below */ |
804 | || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ | 808 | || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ |
805 | IF_GETPUT(&&) | 809 | IF_GETPUT(&&) |
806 | IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ | 810 | IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ |
@@ -808,6 +812,13 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
808 | ) { | 812 | ) { |
809 | goto err; | 813 | goto err; |
810 | } | 814 | } |
815 | /* Some HP PA-RISC firmware always sends fixed 516-byte requests, | ||
816 | * with trailing garbage. | ||
817 | * Support that by not requiring NUL to be the last byte (see above). | ||
818 | * To make strXYZ() ops safe, force NUL termination: | ||
819 | */ | ||
820 | G.block_buf_tail[0] = '\0'; | ||
821 | |||
811 | local_file = G.block_buf + 2; | 822 | local_file = G.block_buf + 2; |
812 | if (local_file[0] == '.' || strstr(local_file, "/.")) { | 823 | if (local_file[0] == '.' || strstr(local_file, "/.")) { |
813 | error_msg = "dot in file name"; | 824 | error_msg = "dot in file name"; |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index fe322db4f..bc41c8d4d 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -63,6 +63,7 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
63 | { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ | 63 | { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ |
64 | #endif | 64 | #endif |
65 | { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ | 65 | { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ |
66 | { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ | ||
66 | { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ | 67 | { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ |
67 | { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ | 68 | { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ |
68 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | 69 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ |
@@ -130,6 +131,7 @@ const char dhcp_option_strings[] ALIGN1 = | |||
130 | "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ | 131 | "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ |
131 | #endif | 132 | #endif |
132 | "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ | 133 | "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ |
134 | "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ | ||
133 | "ip6rd" "\0" /* DHCP_6RD */ | 135 | "ip6rd" "\0" /* DHCP_6RD */ |
134 | "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ | 136 | "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ |
135 | "wpad" "\0" /* DHCP_WPAD */ | 137 | "wpad" "\0" /* DHCP_WPAD */ |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 5e70d609f..e5e0f2599 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -152,6 +152,7 @@ enum { | |||
152 | //#define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ | 152 | //#define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ |
153 | //#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ | 153 | //#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ |
154 | //#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */ | 154 | //#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */ |
155 | //#define DHCP_PXE_PATH_PREFIX 0xd2 /* RFC 5071 Configuration File */ | ||
155 | //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ | 156 | //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ |
156 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ | 157 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ |
157 | #define DHCP_END 0xff | 158 | #define DHCP_END 0xff |
diff --git a/networking/zcip.c b/networking/zcip.c index 7314ff8db..45d1f7c1c 100644 --- a/networking/zcip.c +++ b/networking/zcip.c | |||
@@ -366,11 +366,11 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
366 | nprobes++; | 366 | nprobes++; |
367 | VDBG("probe/%u %s@%s\n", | 367 | VDBG("probe/%u %s@%s\n", |
368 | nprobes, argv_intf, inet_ntoa(ip)); | 368 | nprobes, argv_intf, inet_ntoa(ip)); |
369 | timeout_ms = PROBE_MIN * 1000; | ||
370 | timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); | ||
369 | arp(/* ARPOP_REQUEST, */ | 371 | arp(/* ARPOP_REQUEST, */ |
370 | /* ð_addr, */ null_ip, | 372 | /* ð_addr, */ null_ip, |
371 | &null_addr, ip); | 373 | &null_addr, ip); |
372 | timeout_ms = PROBE_MIN * 1000; | ||
373 | timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); | ||
374 | } | 374 | } |
375 | else { | 375 | else { |
376 | // Switch to announce state. | 376 | // Switch to announce state. |
@@ -378,10 +378,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
378 | nclaims = 0; | 378 | nclaims = 0; |
379 | VDBG("announce/%u %s@%s\n", | 379 | VDBG("announce/%u %s@%s\n", |
380 | nclaims, argv_intf, inet_ntoa(ip)); | 380 | nclaims, argv_intf, inet_ntoa(ip)); |
381 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | ||
381 | arp(/* ARPOP_REQUEST, */ | 382 | arp(/* ARPOP_REQUEST, */ |
382 | /* ð_addr, */ ip, | 383 | /* ð_addr, */ ip, |
383 | ð_addr, ip); | 384 | ð_addr, ip); |
384 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | ||
385 | } | 385 | } |
386 | break; | 386 | break; |
387 | case RATE_LIMIT_PROBE: | 387 | case RATE_LIMIT_PROBE: |
@@ -391,10 +391,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
391 | nclaims = 0; | 391 | nclaims = 0; |
392 | VDBG("announce/%u %s@%s\n", | 392 | VDBG("announce/%u %s@%s\n", |
393 | nclaims, argv_intf, inet_ntoa(ip)); | 393 | nclaims, argv_intf, inet_ntoa(ip)); |
394 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | ||
394 | arp(/* ARPOP_REQUEST, */ | 395 | arp(/* ARPOP_REQUEST, */ |
395 | /* ð_addr, */ ip, | 396 | /* ð_addr, */ ip, |
396 | ð_addr, ip); | 397 | ð_addr, ip); |
397 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | ||
398 | break; | 398 | break; |
399 | case ANNOUNCE: | 399 | case ANNOUNCE: |
400 | // timeouts in the ANNOUNCE state mean no conflicting ARP packets | 400 | // timeouts in the ANNOUNCE state mean no conflicting ARP packets |
@@ -403,10 +403,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
403 | nclaims++; | 403 | nclaims++; |
404 | VDBG("announce/%u %s@%s\n", | 404 | VDBG("announce/%u %s@%s\n", |
405 | nclaims, argv_intf, inet_ntoa(ip)); | 405 | nclaims, argv_intf, inet_ntoa(ip)); |
406 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | ||
406 | arp(/* ARPOP_REQUEST, */ | 407 | arp(/* ARPOP_REQUEST, */ |
407 | /* ð_addr, */ ip, | 408 | /* ð_addr, */ ip, |
408 | ð_addr, ip); | 409 | ð_addr, ip); |
409 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | ||
410 | } | 410 | } |
411 | else { | 411 | else { |
412 | // Switch to monitor state. | 412 | // Switch to monitor state. |
@@ -495,22 +495,28 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
495 | } | 495 | } |
496 | #endif | 496 | #endif |
497 | if (p.arp.arp_op != htons(ARPOP_REQUEST) | 497 | if (p.arp.arp_op != htons(ARPOP_REQUEST) |
498 | && p.arp.arp_op != htons(ARPOP_REPLY)) | 498 | && p.arp.arp_op != htons(ARPOP_REPLY) |
499 | ) { | ||
499 | continue; | 500 | continue; |
501 | } | ||
500 | 502 | ||
501 | source_ip_conflict = 0; | 503 | source_ip_conflict = 0; |
502 | target_ip_conflict = 0; | 504 | target_ip_conflict = 0; |
503 | 505 | ||
504 | if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 | 506 | if (memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0) { |
505 | && memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0 | 507 | if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr))) { |
506 | ) { | 508 | /* A probe or reply with source_ip == chosen ip */ |
507 | source_ip_conflict = 1; | 509 | source_ip_conflict = 1; |
508 | } | 510 | } |
509 | if (p.arp.arp_op == htons(ARPOP_REQUEST) | 511 | if (p.arp.arp_op == htons(ARPOP_REQUEST) |
510 | && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 | 512 | && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0 |
511 | && memcmp(&p.arp.arp_tha, ð_addr, ETH_ALEN) != 0 | 513 | && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 |
512 | ) { | 514 | ) { |
513 | target_ip_conflict = 1; | 515 | /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip: |
516 | * another host trying to claim this ip! | ||
517 | */ | ||
518 | target_ip_conflict = 1; | ||
519 | } | ||
514 | } | 520 | } |
515 | 521 | ||
516 | VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", | 522 | VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", |