aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2014-10-06 12:50:22 +0100
committerRon Yorston <rmy@pobox.com>2014-10-06 12:50:22 +0100
commitb04d11dcbadda2620743a1dd923938f2f3043a38 (patch)
tree971afe425a81304b79e44122e220c7a69efe2616 /networking
parent124bbf02948b7ac0babb4ead04acd1559db182d3 (diff)
parent760d035699c4a878f9109544c1d35ea0d5f6b76c (diff)
downloadbusybox-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.src7
-rw-r--r--networking/ftpd.c63
-rw-r--r--networking/ntpd.c270
-rw-r--r--networking/ping.c25
-rw-r--r--networking/tftp.c21
-rw-r--r--networking/udhcp/common.c2
-rw-r--r--networking/udhcp/common.h1
-rw-r--r--networking/zcip.c38
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
137config 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
137config FTPGET 144config 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
1111int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1112int 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
983static 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 */
1659static unsigned 1675static unsigned
1660retry_interval(void) 1676poll_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}
1670static unsigned
1671poll_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}
1688static void
1689adjust_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}
1684static NOINLINE void 1723static NOINLINE void
1685recv_and_process_peer_pkt(peer_t *p) 1724recv_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"))
334enum { 336enum {
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)
850static int common_ping_main(int opt, char **argv) 854static 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 /* &eth_addr, */ null_ip, 372 /* &eth_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 /* &eth_addr, */ ip, 383 /* &eth_addr, */ ip,
383 &eth_addr, ip); 384 &eth_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 /* &eth_addr, */ ip, 396 /* &eth_addr, */ ip,
396 &eth_addr, ip); 397 &eth_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 /* &eth_addr, */ ip, 408 /* &eth_addr, */ ip,
408 &eth_addr, ip); 409 &eth_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, &eth_addr, ETH_ALEN) != 0) {
505 && memcmp(&p.arp.arp_sha, &eth_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, &eth_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",