aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-23 11:13:23 +0000
committerRon Yorston <rmy@pobox.com>2012-03-23 11:13:23 +0000
commit40514a0309939f2446f0d4ed9600cad5de396e7f (patch)
tree0f5f4a57d4bb7893418b5bb11d482858eb17ba8b /networking
parent9db164d6e39050d09f38288c6045cd2a2cbf6d63 (diff)
parentc0cae52662ccced9df19f19ec94238d1b1e3bd71 (diff)
downloadbusybox-w32-40514a0309939f2446f0d4ed9600cad5de396e7f.tar.gz
busybox-w32-40514a0309939f2446f0d4ed9600cad5de396e7f.tar.bz2
busybox-w32-40514a0309939f2446f0d4ed9600cad5de396e7f.zip
Merge commit 'c0cae52662ccced9df19f19ec94238d1b1e3bd71' into merge
Conflicts: Makefile.flags scripts/basic/fixdep.c
Diffstat (limited to 'networking')
-rw-r--r--networking/httpd.c76
-rw-r--r--networking/ifupdown.c40
-rw-r--r--networking/inetd.c68
-rw-r--r--networking/nc_bloaty.c3
-rw-r--r--networking/ping.c37
-rw-r--r--networking/tftp.c3
-rw-r--r--networking/traceroute.c35
-rw-r--r--networking/udhcp/common.c6
-rw-r--r--networking/udhcp/common.h7
-rw-r--r--networking/udhcp/dhcpc.c220
-rw-r--r--networking/udhcp/dhcpd.c4
-rw-r--r--networking/udhcp/packet.c34
-rw-r--r--networking/wget.c13
-rw-r--r--networking/zcip.c2
14 files changed, 277 insertions, 271 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index ba5eebad5..24482fe52 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -820,78 +820,6 @@ static char *encodeString(const char *string)
820} 820}
821#endif 821#endif
822 822
823/*
824 * Given a URL encoded string, convert it to plain ascii.
825 * Since decoding always makes strings smaller, the decode is done in-place.
826 * Thus, callers should xstrdup() the argument if they do not want the
827 * argument modified. The return is the original pointer, allowing this
828 * function to be easily used as arguments to other functions.
829 *
830 * string The first string to decode.
831 * option_d 1 if called for httpd -d
832 *
833 * Returns a pointer to the decoded string (same as input).
834 */
835static unsigned hex_to_bin(unsigned char c)
836{
837 unsigned v;
838
839 v = c - '0';
840 if (v <= 9)
841 return v;
842 /* c | 0x20: letters to lower case, non-letters
843 * to (potentially different) non-letters */
844 v = (unsigned)(c | 0x20) - 'a';
845 if (v <= 5)
846 return v + 10;
847 return ~0;
848/* For testing:
849void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
850int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
851t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
852*/
853}
854static char *decodeString(char *orig, int option_d)
855{
856 /* note that decoded string is always shorter than original */
857 char *string = orig;
858 char *ptr = string;
859 char c;
860
861 while ((c = *ptr++) != '\0') {
862 unsigned v;
863
864 if (option_d && c == '+') {
865 *string++ = ' ';
866 continue;
867 }
868 if (c != '%') {
869 *string++ = c;
870 continue;
871 }
872 v = hex_to_bin(ptr[0]);
873 if (v > 15) {
874 bad_hex:
875 if (!option_d)
876 return NULL;
877 *string++ = '%';
878 continue;
879 }
880 v = (v * 16) | hex_to_bin(ptr[1]);
881 if (v > 255)
882 goto bad_hex;
883 if (!option_d && (v == '/' || v == '\0')) {
884 /* caller takes it as indication of invalid
885 * (dangerous wrt exploits) chars */
886 return orig + 1;
887 }
888 *string++ = v;
889 ptr += 2;
890 }
891 *string = '\0';
892 return orig;
893}
894
895#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 823#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
896/* 824/*
897 * Decode a base64 data stream as per rfc1521. 825 * Decode a base64 data stream as per rfc1521.
@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
1949 } 1877 }
1950 1878
1951 /* Decode URL escape sequences */ 1879 /* Decode URL escape sequences */
1952 tptr = decodeString(urlcopy, 0); 1880 tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
1953 if (tptr == NULL) 1881 if (tptr == NULL)
1954 send_headers_and_exit(HTTP_BAD_REQUEST); 1882 send_headers_and_exit(HTTP_BAD_REQUEST);
1955 if (tptr == urlcopy + 1) { 1883 if (tptr == urlcopy + 1) {
@@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2408 , &verbose 2336 , &verbose
2409 ); 2337 );
2410 if (opt & OPT_DECODE_URL) { 2338 if (opt & OPT_DECODE_URL) {
2411 fputs(decodeString(url_for_decode, 1), stdout); 2339 fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
2412 return 0; 2340 return 0;
2413 } 2341 }
2414#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR 2342#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 382033038..5946323d0 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -87,7 +87,6 @@ struct mapping_defn_t {
87 87
88 char *script; 88 char *script;
89 89
90 int max_mappings;
91 int n_mappings; 90 int n_mappings;
92 char **mapping; 91 char **mapping;
93}; 92};
@@ -102,7 +101,6 @@ struct interface_defn_t {
102 const struct method_t *method; 101 const struct method_t *method;
103 102
104 char *iface; 103 char *iface;
105 int max_options;
106 int n_options; 104 int n_options;
107 struct variable_t *option; 105 struct variable_t *option;
108}; 106};
@@ -138,6 +136,16 @@ struct globals {
138#define INIT_G() do { } while (0) 136#define INIT_G() do { } while (0)
139 137
140 138
139static const char keywords_up_down[] ALIGN1 =
140 "up\0"
141 "down\0"
142 "pre-up\0"
143 "pre-down\0"
144 "post-up\0"
145 "post-down\0"
146;
147
148
141#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6 149#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6
142 150
143static void addstr(char **bufp, const char *str, size_t str_length) 151static void addstr(char **bufp, const char *str, size_t str_length)
@@ -803,7 +811,6 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
803 currmap->match = xrealloc_vector(currmap->match, 4, currmap->n_matches); 811 currmap->match = xrealloc_vector(currmap->match, 4, currmap->n_matches);
804 currmap->match[currmap->n_matches++] = xstrdup(first_word); 812 currmap->match[currmap->n_matches++] = xstrdup(first_word);
805 } 813 }
806 /*currmap->max_mappings = 0; - done by xzalloc */
807 /*currmap->n_mappings = 0;*/ 814 /*currmap->n_mappings = 0;*/
808 /*currmap->mapping = NULL;*/ 815 /*currmap->mapping = NULL;*/
809 /*currmap->script = NULL;*/ 816 /*currmap->script = NULL;*/
@@ -888,23 +895,16 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
888 if (rest_of_line[0] == '\0') 895 if (rest_of_line[0] == '\0')
889 bb_error_msg_and_die("option with empty value \"%s\"", buf); 896 bb_error_msg_and_die("option with empty value \"%s\"", buf);
890 897
891 if (strcmp(first_word, "up") != 0 898 /* If not one of "up", "down",... words... */
892 && strcmp(first_word, "down") != 0 899 if (index_in_strings(keywords_up_down, first_word) < 0) {
893 && strcmp(first_word, "pre-up") != 0
894 && strcmp(first_word, "post-down") != 0
895 ) {
896 int i; 900 int i;
897 for (i = 0; i < currif->n_options; i++) { 901 for (i = 0; i < currif->n_options; i++) {
898 if (strcmp(currif->option[i].name, first_word) == 0) 902 if (strcmp(currif->option[i].name, first_word) == 0)
899 bb_error_msg_and_die("duplicate option \"%s\"", buf); 903 bb_error_msg_and_die("duplicate option \"%s\"", buf);
900 } 904 }
901 } 905 }
902 if (currif->n_options >= currif->max_options) {
903 currif->max_options += 10;
904 currif->option = xrealloc(currif->option,
905 sizeof(*currif->option) * currif->max_options);
906 }
907 debug_noise("\t%s=%s\n", first_word, rest_of_line); 906 debug_noise("\t%s=%s\n", first_word, rest_of_line);
907 currif->option = xrealloc_vector(currif->option, 4, currif->n_options);
908 currif->option[currif->n_options].name = xstrdup(first_word); 908 currif->option[currif->n_options].name = xstrdup(first_word);
909 currif->option[currif->n_options].value = xstrdup(rest_of_line); 909 currif->option[currif->n_options].value = xstrdup(rest_of_line);
910 currif->n_options++; 910 currif->n_options++;
@@ -916,11 +916,7 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
916 bb_error_msg_and_die("duplicate script in mapping \"%s\"", buf); 916 bb_error_msg_and_die("duplicate script in mapping \"%s\"", buf);
917 currmap->script = xstrdup(next_word(&rest_of_line)); 917 currmap->script = xstrdup(next_word(&rest_of_line));
918 } else if (strcmp(first_word, "map") == 0) { 918 } else if (strcmp(first_word, "map") == 0) {
919 if (currmap->n_mappings >= currmap->max_mappings) { 919 currmap->mapping = xrealloc_vector(currmap->mapping, 2, currmap->n_mappings);
920 currmap->max_mappings = currmap->max_mappings * 2 + 1;
921 currmap->mapping = xrealloc(currmap->mapping,
922 sizeof(char *) * currmap->max_mappings);
923 }
924 currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&rest_of_line)); 920 currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&rest_of_line));
925 currmap->n_mappings++; 921 currmap->n_mappings++;
926 } else { 922 } else {
@@ -984,11 +980,7 @@ static void set_environ(struct interface_defn_t *iface, const char *mode)
984 pp = G.my_environ; 980 pp = G.my_environ;
985 981
986 for (i = 0; i < iface->n_options; i++) { 982 for (i = 0; i < iface->n_options; i++) {
987 if (strcmp(iface->option[i].name, "up") == 0 983 if (index_in_strings(keywords_up_down, iface->option[i].name) >= 0) {
988 || strcmp(iface->option[i].name, "down") == 0
989 || strcmp(iface->option[i].name, "pre-up") == 0
990 || strcmp(iface->option[i].name, "post-down") == 0
991 ) {
992 continue; 984 continue;
993 } 985 }
994 *pp++ = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value); 986 *pp++ = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value);
@@ -1056,6 +1048,7 @@ static int iface_up(struct interface_defn_t *iface)
1056 if (!execute_all(iface, "pre-up")) return 0; 1048 if (!execute_all(iface, "pre-up")) return 0;
1057 if (!iface->method->up(iface, doit)) return 0; 1049 if (!iface->method->up(iface, doit)) return 0;
1058 if (!execute_all(iface, "up")) return 0; 1050 if (!execute_all(iface, "up")) return 0;
1051 if (!execute_all(iface, "post-up")) return 0;
1059 return 1; 1052 return 1;
1060} 1053}
1061 1054
@@ -1063,6 +1056,7 @@ static int iface_down(struct interface_defn_t *iface)
1063{ 1056{
1064 if (!iface->method->down(iface,check)) return -1; 1057 if (!iface->method->down(iface,check)) return -1;
1065 set_environ(iface, "stop"); 1058 set_environ(iface, "stop");
1059 if (!execute_all(iface, "pre-down")) return 0;
1066 if (!execute_all(iface, "down")) return 0; 1060 if (!execute_all(iface, "down")) return 0;
1067 if (!iface->method->down(iface, doit)) return 0; 1061 if (!iface->method->down(iface, doit)) return 0;
1068 if (!execute_all(iface, "post-down")) return 0; 1062 if (!execute_all(iface, "post-down")) return 0;
diff --git a/networking/inetd.c b/networking/inetd.c
index 873fd9528..26b66992d 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -357,10 +357,26 @@ struct BUG_G_too_big {
357 config_filename = "/etc/inetd.conf"; \ 357 config_filename = "/etc/inetd.conf"; \
358} while (0) 358} while (0)
359 359
360#if 1
361# define dbg(...) ((void)0)
362#else
363# define dbg(...) \
364do { \
365 int dbg_fd = open("inetd_debug.log", O_WRONLY | O_CREAT | O_APPEND, 0666); \
366 if (dbg_fd >= 0) { \
367 fdprintf(dbg_fd, "%d: ", getpid()); \
368 fdprintf(dbg_fd, __VA_ARGS__); \
369 close(dbg_fd); \
370 } \
371} while (0)
372#endif
373
360static void maybe_close(int fd) 374static void maybe_close(int fd)
361{ 375{
362 if (fd >= 0) 376 if (fd >= 0) {
363 close(fd); 377 close(fd);
378 dbg("closed fd:%d\n", fd);
379 }
364} 380}
365 381
366// TODO: move to libbb? 382// TODO: move to libbb?
@@ -464,7 +480,9 @@ static void remove_fd_from_set(int fd)
464{ 480{
465 if (fd >= 0) { 481 if (fd >= 0) {
466 FD_CLR(fd, &allsock); 482 FD_CLR(fd, &allsock);
483 dbg("stopped listening on fd:%d\n", fd);
467 maxsock = -1; 484 maxsock = -1;
485 dbg("maxsock:%d\n", maxsock);
468 } 486 }
469} 487}
470 488
@@ -472,8 +490,10 @@ static void add_fd_to_set(int fd)
472{ 490{
473 if (fd >= 0) { 491 if (fd >= 0) {
474 FD_SET(fd, &allsock); 492 FD_SET(fd, &allsock);
493 dbg("started listening on fd:%d\n", fd);
475 if (maxsock >= 0 && fd > maxsock) { 494 if (maxsock >= 0 && fd > maxsock) {
476 prev_maxsock = maxsock = fd; 495 prev_maxsock = maxsock = fd;
496 dbg("maxsock:%d\n", maxsock);
477 if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN) 497 if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN)
478 bump_nofile(); 498 bump_nofile();
479 } 499 }
@@ -492,6 +512,7 @@ static void recalculate_maxsock(void)
492 maxsock = fd; 512 maxsock = fd;
493 fd++; 513 fd++;
494 } 514 }
515 dbg("recalculated maxsock:%d\n", maxsock);
495 prev_maxsock = maxsock; 516 prev_maxsock = maxsock;
496 if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN) 517 if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
497 bump_nofile(); 518 bump_nofile();
@@ -549,8 +570,13 @@ static void prepare_socket_fd(servtab_t *sep)
549 rearm_alarm(); 570 rearm_alarm();
550 return; 571 return;
551 } 572 }
552 if (sep->se_socktype == SOCK_STREAM) 573
574 if (sep->se_socktype == SOCK_STREAM) {
553 listen(fd, global_queuelen); 575 listen(fd, global_queuelen);
576 dbg("new sep->se_fd:%d (stream)\n", fd);
577 } else {
578 dbg("new sep->se_fd:%d (!stream)\n", fd);
579 }
554 580
555 add_fd_to_set(fd); 581 add_fd_to_set(fd);
556 sep->se_fd = fd; 582 sep->se_fd = fd;
@@ -1012,7 +1038,7 @@ static void reread_config_file(int sig UNUSED_PARAM)
1012 * new config file doesnt have them. */ 1038 * new config file doesnt have them. */
1013 block_CHLD_HUP_ALRM(&omask); 1039 block_CHLD_HUP_ALRM(&omask);
1014 sepp = &serv_list; 1040 sepp = &serv_list;
1015 while ((sep = *sepp)) { 1041 while ((sep = *sepp) != NULL) {
1016 if (sep->se_checked) { 1042 if (sep->se_checked) {
1017 sepp = &sep->se_next; 1043 sepp = &sep->se_next;
1018 continue; 1044 continue;
@@ -1206,11 +1232,13 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1206 } 1232 }
1207 continue; 1233 continue;
1208 } 1234 }
1235 dbg("ready_fd_cnt:%d\n", ready_fd_cnt);
1209 1236
1210 for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) { 1237 for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) {
1211 if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable)) 1238 if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable))
1212 continue; 1239 continue;
1213 1240
1241 dbg("ready fd:%d\n", sep->se_fd);
1214 ready_fd_cnt--; 1242 ready_fd_cnt--;
1215 ctrl = sep->se_fd; 1243 ctrl = sep->se_fd;
1216 accepted_fd = -1; 1244 accepted_fd = -1;
@@ -1218,6 +1246,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1218 if (!sep->se_wait) { 1246 if (!sep->se_wait) {
1219 if (sep->se_socktype == SOCK_STREAM) { 1247 if (sep->se_socktype == SOCK_STREAM) {
1220 ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL); 1248 ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL);
1249 dbg("accepted_fd:%d\n", accepted_fd);
1221 if (ctrl < 0) { 1250 if (ctrl < 0) {
1222 if (errno != EINTR) 1251 if (errno != EINTR)
1223 bb_perror_msg("accept (for %s)", sep->se_service); 1252 bb_perror_msg("accept (for %s)", sep->se_service);
@@ -1238,19 +1267,22 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1238 * (can create many copies of same child, etc). 1267 * (can create many copies of same child, etc).
1239 * Parent must create and use new socket instead. */ 1268 * Parent must create and use new socket instead. */
1240 new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0); 1269 new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0);
1270 dbg("new_udp_fd:%d\n", new_udp_fd);
1241 if (new_udp_fd < 0) { /* error: eat packet, forget about it */ 1271 if (new_udp_fd < 0) { /* error: eat packet, forget about it */
1242 udp_err: 1272 udp_err:
1243 recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT); 1273 recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT);
1244 continue; 1274 continue;
1245 } 1275 }
1246 setsockopt_reuseaddr(new_udp_fd); 1276 setsockopt_reuseaddr(new_udp_fd);
1247 /* TODO: better do bind after vfork in parent, 1277 /* TODO: better do bind after fork in parent,
1248 * so that we don't have two wildcard bound sockets 1278 * so that we don't have two wildcard bound sockets
1249 * even for a brief moment? */ 1279 * even for a brief moment? */
1250 if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) { 1280 if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) {
1281 dbg("bind(new_udp_fd) failed\n");
1251 close(new_udp_fd); 1282 close(new_udp_fd);
1252 goto udp_err; 1283 goto udp_err;
1253 } 1284 }
1285 dbg("bind(new_udp_fd) succeeded\n");
1254 } 1286 }
1255 } 1287 }
1256 1288
@@ -1278,6 +1310,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1278 sep->se_count = 0; 1310 sep->se_count = 0;
1279 rearm_alarm(); /* will revive it in RETRYTIME sec */ 1311 rearm_alarm(); /* will revive it in RETRYTIME sec */
1280 restore_sigmask(&omask); 1312 restore_sigmask(&omask);
1313 maybe_close(new_udp_fd);
1281 maybe_close(accepted_fd); 1314 maybe_close(accepted_fd);
1282 continue; /* -> check next fd in fd set */ 1315 continue; /* -> check next fd in fd set */
1283 } 1316 }
@@ -1298,17 +1331,18 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1298 bb_perror_msg("vfork"+1); 1331 bb_perror_msg("vfork"+1);
1299 sleep(1); 1332 sleep(1);
1300 restore_sigmask(&omask); 1333 restore_sigmask(&omask);
1334 maybe_close(new_udp_fd);
1301 maybe_close(accepted_fd); 1335 maybe_close(accepted_fd);
1302 continue; /* -> check next fd in fd set */ 1336 continue; /* -> check next fd in fd set */
1303 } 1337 }
1304 if (pid == 0) 1338 if (pid == 0)
1305 pid--; /* -1: "we did fork and we are child" */ 1339 pid--; /* -1: "we did fork and we are child" */
1306 } 1340 }
1307 /* if pid == 0 here, we never forked */ 1341 /* if pid == 0 here, we didn't fork */
1308 1342
1309 if (pid > 0) { /* parent */ 1343 if (pid > 0) { /* parent */
1310 if (sep->se_wait) { 1344 if (sep->se_wait) {
1311 /* tcp wait: we passed listening socket to child, 1345 /* wait: we passed socket to child,
1312 * will wait for child to terminate */ 1346 * will wait for child to terminate */
1313 sep->se_wait = pid; 1347 sep->se_wait = pid;
1314 remove_fd_from_set(sep->se_fd); 1348 remove_fd_from_set(sep->se_fd);
@@ -1317,17 +1351,19 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1317 /* udp nowait: child connected the socket, 1351 /* udp nowait: child connected the socket,
1318 * we created and will use new, unconnected one */ 1352 * we created and will use new, unconnected one */
1319 xmove_fd(new_udp_fd, sep->se_fd); 1353 xmove_fd(new_udp_fd, sep->se_fd);
1354 dbg("moved new_udp_fd:%d to sep->se_fd:%d\n", new_udp_fd, sep->se_fd);
1320 } 1355 }
1321 restore_sigmask(&omask); 1356 restore_sigmask(&omask);
1322 maybe_close(accepted_fd); 1357 maybe_close(accepted_fd);
1323 continue; /* -> check next fd in fd set */ 1358 continue; /* -> check next fd in fd set */
1324 } 1359 }
1325 1360
1326 /* we are either child or didn't vfork at all */ 1361 /* we are either child or didn't fork at all */
1327#ifdef INETD_BUILTINS_ENABLED 1362#ifdef INETD_BUILTINS_ENABLED
1328 if (sep->se_builtin) { 1363 if (sep->se_builtin) {
1329 if (pid) { /* "pid" is -1: we did vfork */ 1364 if (pid) { /* "pid" is -1: we did fork */
1330 close(sep->se_fd); /* listening socket */ 1365 close(sep->se_fd); /* listening socket */
1366 dbg("closed sep->se_fd:%d\n", sep->se_fd);
1331 logmode = LOGMODE_NONE; /* make xwrite etc silent */ 1367 logmode = LOGMODE_NONE; /* make xwrite etc silent */
1332 } 1368 }
1333 restore_sigmask(&omask); 1369 restore_sigmask(&omask);
@@ -1335,7 +1371,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1335 sep->se_builtin->bi_stream_fn(ctrl, sep); 1371 sep->se_builtin->bi_stream_fn(ctrl, sep);
1336 else 1372 else
1337 sep->se_builtin->bi_dgram_fn(ctrl, sep); 1373 sep->se_builtin->bi_dgram_fn(ctrl, sep);
1338 if (pid) /* we did vfork */ 1374 if (pid) /* we did fork */
1339 _exit(EXIT_FAILURE); 1375 _exit(EXIT_FAILURE);
1340 maybe_close(accepted_fd); 1376 maybe_close(accepted_fd);
1341 continue; /* -> check next fd in fd set */ 1377 continue; /* -> check next fd in fd set */
@@ -1345,9 +1381,14 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1345 setsid(); 1381 setsid();
1346 /* "nowait" udp */ 1382 /* "nowait" udp */
1347 if (new_udp_fd >= 0) { 1383 if (new_udp_fd >= 0) {
1348 len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family); 1384 len_and_sockaddr *lsa;
1385 int r;
1386
1387 close(new_udp_fd);
1388 dbg("closed new_udp_fd:%d\n", new_udp_fd);
1389 lsa = xzalloc_lsa(sep->se_family);
1349 /* peek at the packet and remember peer addr */ 1390 /* peek at the packet and remember peer addr */
1350 int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT, 1391 r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
1351 &lsa->u.sa, &lsa->len); 1392 &lsa->u.sa, &lsa->len);
1352 if (r < 0) 1393 if (r < 0)
1353 goto do_exit1; 1394 goto do_exit1;
@@ -1355,6 +1396,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1355 * only packets from this peer will be recv'ed, 1396 * only packets from this peer will be recv'ed,
1356 * and bare write()/send() will work on it */ 1397 * and bare write()/send() will work on it */
1357 connect(ctrl, &lsa->u.sa, lsa->len); 1398 connect(ctrl, &lsa->u.sa, lsa->len);
1399 dbg("connected ctrl:%d to remote peer\n", ctrl);
1358 free(lsa); 1400 free(lsa);
1359 } 1401 }
1360 /* prepare env and exec program */ 1402 /* prepare env and exec program */
@@ -1372,7 +1414,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1372 bb_error_msg("non-root must run services as himself"); 1414 bb_error_msg("non-root must run services as himself");
1373 goto do_exit1; 1415 goto do_exit1;
1374 } 1416 }
1375 if (pwd->pw_uid) { 1417 if (pwd->pw_uid != 0) {
1376 if (sep->se_group) 1418 if (sep->se_group)
1377 pwd->pw_gid = grp->gr_gid; 1419 pwd->pw_gid = grp->gr_gid;
1378 /* initgroups, setgid, setuid: */ 1420 /* initgroups, setgid, setuid: */
@@ -1391,6 +1433,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1391 */ 1433 */
1392 xmove_fd(ctrl, STDIN_FILENO); 1434 xmove_fd(ctrl, STDIN_FILENO);
1393 xdup2(STDIN_FILENO, STDOUT_FILENO); 1435 xdup2(STDIN_FILENO, STDOUT_FILENO);
1436 dbg("moved ctrl:%d to fd 0,1[,2]\n", ctrl);
1394 /* manpages of inetd I managed to find either say 1437 /* manpages of inetd I managed to find either say
1395 * that stderr is also redirected to the network, 1438 * that stderr is also redirected to the network,
1396 * or do not talk about redirection at all (!) */ 1439 * or do not talk about redirection at all (!) */
@@ -1403,6 +1446,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1403 maybe_close(sep2->se_fd); 1446 maybe_close(sep2->se_fd);
1404 sigaction_set(SIGPIPE, &saved_pipe_handler); 1447 sigaction_set(SIGPIPE, &saved_pipe_handler);
1405 restore_sigmask(&omask); 1448 restore_sigmask(&omask);
1449 dbg("execing:'%s'\n", sep->se_program);
1406 BB_EXECVP(sep->se_program, sep->se_argv); 1450 BB_EXECVP(sep->se_program, sep->se_argv);
1407 bb_perror_msg("can't execute '%s'", sep->se_program); 1451 bb_perror_msg("can't execute '%s'", sep->se_program);
1408 do_exit1: 1452 do_exit1:
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index 1daad1358..d184f689b 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -428,8 +428,7 @@ create new one, and bind() it. TODO */
428 428
429 rr = getsockopt(netfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x); 429 rr = getsockopt(netfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
430 if (rr >= 0 && x) { /* we've got options, lessee em... */ 430 if (rr >= 0 && x) { /* we've got options, lessee em... */
431 bin2hex(bigbuf_net, optbuf, x); 431 *bin2hex(bigbuf_net, optbuf, x) = '\0';
432 bigbuf_net[2*x] = '\0';
433 fprintf(stderr, "IP options: %s\n", bigbuf_net); 432 fprintf(stderr, "IP options: %s\n", bigbuf_net);
434 } 433 }
435#endif 434#endif
diff --git a/networking/ping.c b/networking/ping.c
index efd4f210b..b8a438ba8 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -149,31 +149,6 @@ enum {
149 PINGINTERVAL = 1, /* 1 second */ 149 PINGINTERVAL = 1, /* 1 second */
150}; 150};
151 151
152/* Common routines */
153
154static int in_cksum(unsigned short *buf, int sz)
155{
156 int nleft = sz;
157 int sum = 0;
158 unsigned short *w = buf;
159 unsigned short ans = 0;
160
161 while (nleft > 1) {
162 sum += *w++;
163 nleft -= 2;
164 }
165
166 if (nleft == 1) {
167 *(unsigned char *) (&ans) = *(unsigned char *) w;
168 sum += ans;
169 }
170
171 sum = (sum >> 16) + (sum & 0xFFFF);
172 sum += (sum >> 16);
173 ans = ~sum;
174 return ans;
175}
176
177#if !ENABLE_FEATURE_FANCY_PING 152#if !ENABLE_FEATURE_FANCY_PING
178 153
179/* Simple version */ 154/* Simple version */
@@ -201,7 +176,7 @@ static void ping4(len_and_sockaddr *lsa)
201 pkt = (struct icmp *) G.packet; 176 pkt = (struct icmp *) G.packet;
202 memset(pkt, 0, sizeof(G.packet)); 177 memset(pkt, 0, sizeof(G.packet));
203 pkt->icmp_type = ICMP_ECHO; 178 pkt->icmp_type = ICMP_ECHO;
204 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(G.packet)); 179 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));
205 180
206 xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); 181 xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len);
207 182
@@ -493,7 +468,7 @@ static void sendping4(int junk UNUSED_PARAM)
493 /* No hton: we'll read it back on the same machine */ 468 /* No hton: we'll read it back on the same machine */
494 *(uint32_t*)&pkt->icmp_dun = monotonic_us(); 469 *(uint32_t*)&pkt->icmp_dun = monotonic_us();
495 470
496 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN); 471 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, datalen + ICMP_MINLEN);
497 472
498 sendping_tail(sendping4, ICMP_MINLEN); 473 sendping_tail(sendping4, ICMP_MINLEN);
499} 474}
@@ -512,7 +487,7 @@ static void sendping6(int junk UNUSED_PARAM)
512 /*if (datalen >= 4)*/ 487 /*if (datalen >= 4)*/
513 *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); 488 *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
514 489
515 //TODO? pkt->icmp_cksum = in_cksum(...); 490 //TODO? pkt->icmp_cksum = inet_cksum(...);
516 491
517 sendping_tail(sendping6, sizeof(struct icmp6_hdr)); 492 sendping_tail(sendping6, sizeof(struct icmp6_hdr));
518} 493}
@@ -638,7 +613,7 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from)
638 } 613 }
639} 614}
640#if ENABLE_PING6 615#if ENABLE_PING6
641static void unpack6(char *packet, int sz, /*struct sockaddr_in6 *from,*/ int hoplimit) 616static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit)
642{ 617{
643 struct icmp6_hdr *icmppkt; 618 struct icmp6_hdr *icmppkt;
644 char buf[INET6_ADDRSTRLEN]; 619 char buf[INET6_ADDRSTRLEN];
@@ -658,7 +633,7 @@ static void unpack6(char *packet, int sz, /*struct sockaddr_in6 *from,*/ int hop
658 if (sz >= sizeof(struct icmp6_hdr) + sizeof(uint32_t)) 633 if (sz >= sizeof(struct icmp6_hdr) + sizeof(uint32_t))
659 tp = (uint32_t *) &icmppkt->icmp6_data8[4]; 634 tp = (uint32_t *) &icmppkt->icmp6_data8[4];
660 unpack_tail(sz, tp, 635 unpack_tail(sz, tp,
661 inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, 636 inet_ntop(AF_INET6, &from->sin6_addr,
662 buf, sizeof(buf)), 637 buf, sizeof(buf)),
663 recv_seq, hoplimit); 638 recv_seq, hoplimit);
664 } else if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) { 639 } else if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) {
@@ -808,7 +783,7 @@ static void ping6(len_and_sockaddr *lsa)
808 move_from_unaligned_int(hoplimit, CMSG_DATA(mp)); 783 move_from_unaligned_int(hoplimit, CMSG_DATA(mp));
809 } 784 }
810 } 785 }
811 unpack6(G.rcv_packet, c, /*&from,*/ hoplimit); 786 unpack6(G.rcv_packet, c, &from, hoplimit);
812 if (pingcount && nreceived >= pingcount) 787 if (pingcount && nreceived >= pingcount)
813 break; 788 break;
814 } 789 }
diff --git a/networking/tftp.c b/networking/tftp.c
index 17485a527..043b879af 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -813,7 +813,8 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
813 goto err; 813 goto err;
814 } 814 }
815 mode = local_file + strlen(local_file) + 1; 815 mode = local_file + strlen(local_file) + 1;
816 if (mode >= block_buf + result || strcmp(mode, "octet") != 0) { 816 /* RFC 1350 says mode string is case independent */
817 if (mode >= block_buf + result || strcasecmp(mode, "octet") != 0) {
817 goto err; 818 goto err;
818 } 819 }
819# if ENABLE_FEATURE_TFTP_BLOCKSIZE 820# if ENABLE_FEATURE_TFTP_BLOCKSIZE
diff --git a/networking/traceroute.c b/networking/traceroute.c
index c32103519..d197e5410 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -418,39 +418,6 @@ wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timest
418 return read_len; 418 return read_len;
419} 419}
420 420
421/*
422 * Checksum routine for Internet Protocol family headers (C Version)
423 */
424static uint16_t
425in_cksum(uint16_t *addr, int len)
426{
427 int nleft = len;
428 uint16_t *w = addr;
429 uint16_t answer;
430 int sum = 0;
431
432 /*
433 * Our algorithm is simple, using a 32 bit accumulator (sum),
434 * we add sequential 16 bit words to it, and at the end, fold
435 * back all the carry bits from the top 16 bits into the lower
436 * 16 bits.
437 */
438 while (nleft > 1) {
439 sum += *w++;
440 nleft -= 2;
441 }
442
443 /* mop up an odd byte, if necessary */
444 if (nleft == 1)
445 sum += *(unsigned char *)w;
446
447 /* add back carry outs from top 16 bits to low 16 bits */
448 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
449 sum += (sum >> 16); /* add carry */
450 answer = ~sum; /* truncate to 16 bits */
451 return answer;
452}
453
454static void 421static void
455send_probe(int seq, int ttl) 422send_probe(int seq, int ttl)
456{ 423{
@@ -477,7 +444,7 @@ send_probe(int seq, int ttl)
477 444
478 /* Always calculate checksum for icmp packets */ 445 /* Always calculate checksum for icmp packets */
479 outicmp->icmp_cksum = 0; 446 outicmp->icmp_cksum = 0;
480 outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, 447 outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp,
481 packlen - (sizeof(*outip) + optlen)); 448 packlen - (sizeof(*outip) + optlen));
482 if (outicmp->icmp_cksum == 0) 449 if (outicmp->icmp_cksum == 0)
483 outicmp->icmp_cksum = 0xffff; 450 outicmp->icmp_cksum = 0xffff;
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 70e34614c..2e6113627 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -36,6 +36,9 @@ const struct dhcp_optflag dhcp_optflags[] = {
36 { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ 36 { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */
37 { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ 37 { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */
38 { OPTION_U16 , 0x1a }, /* DHCP_MTU */ 38 { OPTION_U16 , 0x1a }, /* DHCP_MTU */
39//TODO: why do we request DHCP_BROADCAST? Can't we assume that
40//in the unlikely case it is different from typical N.N.255.255,
41//server would let us know anyway?
39 { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ 42 { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */
40 { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ 43 { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */
41 { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ 44 { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */
@@ -59,6 +62,7 @@ const struct dhcp_optflag dhcp_optflags[] = {
59 { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */ 62 { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */
60 { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ 63 { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */
61#endif 64#endif
65 { OPTION_6RD , 0xd4 }, /* DHCP_6RD */
62 { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ 66 { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
63 { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ 67 { OPTION_STRING , 0xfc }, /* DHCP_WPAD */
64 68
@@ -126,6 +130,7 @@ const char dhcp_option_strings[] ALIGN1 =
126 "vlanid" "\0" /* DHCP_VLAN_ID */ 130 "vlanid" "\0" /* DHCP_VLAN_ID */
127 "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ 131 "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */
128#endif 132#endif
133 "ip6rd" "\0" /* DHCP_6RD */
129 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ 134 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
130 "wpad" "\0" /* DHCP_WPAD */ 135 "wpad" "\0" /* DHCP_WPAD */
131 ; 136 ;
@@ -154,6 +159,7 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = {
154 [OPTION_S32] = 4, 159 [OPTION_S32] = 4,
155 /* Just like OPTION_STRING, we use minimum length here */ 160 /* Just like OPTION_STRING, we use minimum length here */
156 [OPTION_STATIC_ROUTES] = 5, 161 [OPTION_STATIC_ROUTES] = 5,
162 [OPTION_6RD] = 22, /* ignored by udhcp_str2optset */
157}; 163};
158 164
159 165
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index ad6991c94..a7f9395b8 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -88,6 +88,7 @@ enum {
88 OPTION_S32, 88 OPTION_S32,
89 OPTION_BIN, 89 OPTION_BIN,
90 OPTION_STATIC_ROUTES, 90 OPTION_STATIC_ROUTES,
91 OPTION_6RD,
91#if ENABLE_FEATURE_UDHCP_RFC3397 92#if ENABLE_FEATURE_UDHCP_RFC3397
92 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ 93 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */
93 OPTION_SIP_SERVERS, 94 OPTION_SIP_SERVERS,
@@ -103,7 +104,7 @@ enum {
103/* DHCP option codes (partial list). See RFC 2132 and 104/* DHCP option codes (partial list). See RFC 2132 and
104 * http://www.iana.org/assignments/bootp-dhcp-parameters/ 105 * http://www.iana.org/assignments/bootp-dhcp-parameters/
105 * Commented out options are handled by common option machinery, 106 * Commented out options are handled by common option machinery,
106 * uncommented ones have spacial cases (grep for them to see). 107 * uncommented ones have special cases (grep for them to see).
107 */ 108 */
108#define DHCP_PADDING 0x00 109#define DHCP_PADDING 0x00
109#define DHCP_SUBNET 0x01 110#define DHCP_SUBNET 0x01
@@ -248,6 +249,7 @@ struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code)
248/*** Logging ***/ 249/*** Logging ***/
249 250
250#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 251#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
252# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
251extern unsigned dhcp_verbose; 253extern unsigned dhcp_verbose;
252# define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) 254# define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0)
253# if CONFIG_UDHCP_DEBUG >= 2 255# if CONFIG_UDHCP_DEBUG >= 2
@@ -263,6 +265,7 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
263# define log3(...) ((void)0) 265# define log3(...) ((void)0)
264# endif 266# endif
265#else 267#else
268# define IF_UDHCP_VERBOSE(...)
266# define udhcp_dump_packet(...) ((void)0) 269# define udhcp_dump_packet(...) ((void)0)
267# define log1(...) ((void)0) 270# define log1(...) ((void)0)
268# define log2(...) ((void)0) 271# define log2(...) ((void)0)
@@ -277,8 +280,6 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg);
277/* 2nd param is "struct option_set**" */ 280/* 2nd param is "struct option_set**" */
278int FAST_FUNC udhcp_str2optset(const char *str, void *arg); 281int FAST_FUNC udhcp_str2optset(const char *str, void *arg);
279 282
280uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC;
281
282void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; 283void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC;
283 284
284int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC; 285int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC;
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 4d755e6b8..3d4c397ff 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -100,6 +100,7 @@ static const uint8_t len_of_option_as_string[] = {
100 [OPTION_IP ] = sizeof("255.255.255.255 "), 100 [OPTION_IP ] = sizeof("255.255.255.255 "),
101 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 101 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
102 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 102 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
103 [OPTION_6RD ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
103 [OPTION_STRING ] = 1, 104 [OPTION_STRING ] = 1,
104#if ENABLE_FEATURE_UDHCP_RFC3397 105#if ENABLE_FEATURE_UDHCP_RFC3397
105 [OPTION_DNS_STRING ] = 1, /* unused */ 106 [OPTION_DNS_STRING ] = 1, /* unused */
@@ -123,6 +124,24 @@ static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
123 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); 124 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
124} 125}
125 126
127static int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip)
128{
129 char hexstrbuf[16 * 2];
130 bin2hex(hexstrbuf, (void*)ip, 16);
131 return sprintf(dest, /* "%s" */
132 "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
133 /* pre, */
134 hexstrbuf + 0 * 4,
135 hexstrbuf + 1 * 4,
136 hexstrbuf + 2 * 4,
137 hexstrbuf + 3 * 4,
138 hexstrbuf + 4 * 4,
139 hexstrbuf + 5 * 4,
140 hexstrbuf + 6 * 4,
141 hexstrbuf + 7 * 4
142 );
143}
144
126/* really simple implementation, just count the bits */ 145/* really simple implementation, just count the bits */
127static int mton(uint32_t mask) 146static int mton(uint32_t mask)
128{ 147{
@@ -142,27 +161,25 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
142 int len, type, optlen; 161 int len, type, optlen;
143 char *dest, *ret; 162 char *dest, *ret;
144 163
145 /* option points to OPT_DATA, need to go back and get OPT_LEN */ 164 /* option points to OPT_DATA, need to go back to get OPT_LEN */
146 len = option[OPT_LEN - OPT_DATA]; 165 len = option[-OPT_DATA + OPT_LEN];
147 166
148 type = optflag->flags & OPTION_TYPE_MASK; 167 type = optflag->flags & OPTION_TYPE_MASK;
149 optlen = dhcp_option_lengths[type]; 168 optlen = dhcp_option_lengths[type];
150 upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); 169 upper_length = len_of_option_as_string[type]
170 * ((unsigned)(len + optlen - 1) / (unsigned)optlen);
151 171
152 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); 172 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
153 dest += sprintf(ret, "%s=", opt_name); 173 dest += sprintf(ret, "%s=", opt_name);
154 174
155 while (len >= optlen) { 175 while (len >= optlen) {
156 unsigned ip_ofs = 0;
157
158 switch (type) { 176 switch (type) {
177 case OPTION_IP:
159 case OPTION_IP_PAIR: 178 case OPTION_IP_PAIR:
160 dest += sprint_nip(dest, "", option); 179 dest += sprint_nip(dest, "", option);
161 *dest++ = '/'; 180 if (type == OPTION_IP)
162 ip_ofs = 4; 181 break;
163 /* fall through */ 182 dest += sprint_nip(dest, "/", option + 4);
164 case OPTION_IP:
165 dest += sprint_nip(dest, "", option + ip_ofs);
166 break; 183 break;
167// case OPTION_BOOLEAN: 184// case OPTION_BOOLEAN:
168// dest += sprintf(dest, *option ? "yes" : "no"); 185// dest += sprintf(dest, *option ? "yes" : "no");
@@ -184,10 +201,14 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
184 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32)); 201 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32));
185 break; 202 break;
186 } 203 }
204 /* Note: options which use 'return' instead of 'break'
205 * (for example, OPTION_STRING) skip the code which handles
206 * the case of list of options.
207 */
187 case OPTION_STRING: 208 case OPTION_STRING:
188 memcpy(dest, option, len); 209 memcpy(dest, option, len);
189 dest[len] = '\0'; 210 dest[len] = '\0';
190 return ret; /* Short circuit this case */ 211 return ret;
191 case OPTION_STATIC_ROUTES: { 212 case OPTION_STATIC_ROUTES: {
192 /* Option binary format: 213 /* Option binary format:
193 * mask [one byte, 0..32] 214 * mask [one byte, 0..32]
@@ -232,6 +253,53 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
232 253
233 return ret; 254 return ret;
234 } 255 }
256 case OPTION_6RD:
257 /* Option binary format (see RFC 5969):
258 * 0 1 2 3
259 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
260 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261 * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen |
262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * | 6rdPrefix |
264 * ... (16 octets) ...
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * ... 6rdBRIPv4Address(es) ...
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * We convert it to a string
269 * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..."
270 *
271 * Sanity check: ensure that our length is at least 22 bytes, that
272 * IPv4MaskLen <= 32,
273 * 6rdPrefixLen <= 128,
274 * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128
275 * (2nd condition need no check - it follows from 1st and 3rd).
276 * Else, return envvar with empty value ("optname=")
277 */
278 if (len >= (1 + 1 + 16 + 4)
279 && option[0] <= 32
280 && (option[1] + 32 - option[0]) <= 128
281 ) {
282 /* IPv4MaskLen */
283 dest += sprintf(dest, "%u ", *option++);
284 /* 6rdPrefixLen */
285 dest += sprintf(dest, "%u ", *option++);
286 /* 6rdPrefix */
287 dest += sprint_nip6(dest, /* "", */ option);
288 option += 16;
289 len -= 1 + 1 + 16 + 4;
290 /* "+ 4" above corresponds to the length of IPv4 addr
291 * we consume in the loop below */
292 while (1) {
293 /* 6rdBRIPv4Address(es) */
294 dest += sprint_nip(dest, " ", option);
295 option += 4;
296 len -= 4; /* do we have yet another 4+ bytes? */
297 if (len < 0)
298 break; /* no */
299 }
300 }
301
302 return ret;
235#if ENABLE_FEATURE_UDHCP_RFC3397 303#if ENABLE_FEATURE_UDHCP_RFC3397
236 case OPTION_DNS_STRING: 304 case OPTION_DNS_STRING:
237 /* unpack option into dest; use ret for prefix (i.e., "optname=") */ 305 /* unpack option into dest; use ret for prefix (i.e., "optname=") */
@@ -271,16 +339,21 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
271 return ret; 339 return ret;
272#endif 340#endif
273 } /* switch */ 341 } /* switch */
342
343 /* If we are here, try to format any remaining data
344 * in the option as another, similarly-formatted option
345 */
274 option += optlen; 346 option += optlen;
275 len -= optlen; 347 len -= optlen;
276// TODO: it can be a list only if (optflag->flags & OPTION_LIST). 348// TODO: it can be a list only if (optflag->flags & OPTION_LIST).
277// Should we bail out/warn if we see multi-ip option which is 349// Should we bail out/warn if we see multi-ip option which is
278// not allowed to be such (for example, DHCP_BROADCAST)? - 350// not allowed to be such (for example, DHCP_BROADCAST)? -
279 if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */) 351 if (len < optlen /* || !(optflag->flags & OPTION_LIST) */)
280 break; 352 break;
281 *dest++ = ' '; 353 *dest++ = ' ';
282 *dest = '\0'; 354 *dest = '\0';
283 } 355 } /* while */
356
284 return ret; 357 return ret;
285} 358}
286 359
@@ -320,7 +393,7 @@ static char **fill_envp(struct dhcp_packet *packet)
320 if (i == DHCP_OPTION_OVERLOAD) 393 if (i == DHCP_OPTION_OVERLOAD)
321 overload = *temp; 394 overload = *temp;
322 else if (i == DHCP_SUBNET) 395 else if (i == DHCP_SUBNET)
323 envc++; /* for mton */ 396 envc++; /* for $mask */
324 envc++; 397 envc++;
325 /*if (i != DHCP_MESSAGE_TYPE)*/ 398 /*if (i != DHCP_MESSAGE_TYPE)*/
326 FOUND_OPTS(i) |= BMASK(i); 399 FOUND_OPTS(i) |= BMASK(i);
@@ -335,10 +408,42 @@ static char **fill_envp(struct dhcp_packet *packet)
335 if (!packet) 408 if (!packet)
336 return envp; 409 return envp;
337 410
411 /* Export BOOTP fields. Fields we don't (yet?) export:
412 * uint8_t op; // always BOOTREPLY
413 * uint8_t htype; // hardware address type. 1 = 10mb ethernet
414 * uint8_t hlen; // hardware address length
415 * uint8_t hops; // used by relay agents only
416 * uint32_t xid;
417 * uint16_t secs; // elapsed since client began acquisition/renewal
418 * uint16_t flags; // only one flag so far: bcast. Never set by server
419 * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different
420 * // if during renew server wants to give us differn IP?)
421 * uint32_t gateway_nip; // relay agent IP address
422 * uint8_t chaddr[16]; // link-layer client hardware address (MAC)
423 * TODO: export gateway_nip as $giaddr?
424 */
425 /* Most important one: yiaddr as $ip */
338 *curr = xmalloc(sizeof("ip=255.255.255.255")); 426 *curr = xmalloc(sizeof("ip=255.255.255.255"));
339 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); 427 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr);
340 putenv(*curr++); 428 putenv(*curr++);
429 if (packet->siaddr_nip) {
430 /* IP address of next server to use in bootstrap */
431 *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
432 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
433 putenv(*curr++);
434 }
435 if (!(overload & FILE_FIELD) && packet->file[0]) {
436 /* watch out for invalid packets */
437 *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
438 putenv(*curr++);
439 }
440 if (!(overload & SNAME_FIELD) && packet->sname[0]) {
441 /* watch out for invalid packets */
442 *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
443 putenv(*curr++);
444 }
341 445
446 /* Export known DHCP options */
342 opt_name = dhcp_option_strings; 447 opt_name = dhcp_option_strings;
343 i = 0; 448 i = 0;
344 while (*opt_name) { 449 while (*opt_name) {
@@ -355,29 +460,14 @@ static char **fill_envp(struct dhcp_packet *packet)
355 /* Subnet option: make things like "$ip/$mask" possible */ 460 /* Subnet option: make things like "$ip/$mask" possible */
356 uint32_t subnet; 461 uint32_t subnet;
357 move_from_unaligned32(subnet, temp); 462 move_from_unaligned32(subnet, temp);
358 *curr = xasprintf("mask=%d", mton(subnet)); 463 *curr = xasprintf("mask=%u", mton(subnet));
359 putenv(*curr++); 464 putenv(*curr++);
360 } 465 }
361 next: 466 next:
362 opt_name += strlen(opt_name) + 1; 467 opt_name += strlen(opt_name) + 1;
363 i++; 468 i++;
364 } 469 }
365 if (packet->siaddr_nip) { 470 /* Export unknown options */
366 *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
367 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
368 putenv(*curr++);
369 }
370 if (!(overload & FILE_FIELD) && packet->file[0]) {
371 /* watch out for invalid packets */
372 *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
373 putenv(*curr++);
374 }
375 if (!(overload & SNAME_FIELD) && packet->sname[0]) {
376 /* watch out for invalid packets */
377 *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
378 putenv(*curr++);
379 }
380 /* Handle unknown options */
381 for (i = 0; i < 256;) { 471 for (i = 0; i < 256;) {
382 BITMAP bitmap = FOUND_OPTS(i); 472 BITMAP bitmap = FOUND_OPTS(i);
383 if (!bitmap) { 473 if (!bitmap) {
@@ -394,11 +484,12 @@ static char **fill_envp(struct dhcp_packet *packet)
394 len = temp[-OPT_DATA + OPT_LEN]; 484 len = temp[-OPT_DATA + OPT_LEN];
395 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); 485 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2);
396 ofs = sprintf(*curr, "opt%u=", i); 486 ofs = sprintf(*curr, "opt%u=", i);
397 bin2hex(*curr + ofs, (void*) temp, len)[0] = '\0'; 487 *bin2hex(*curr + ofs, (void*) temp, len) = '\0';
398 putenv(*curr++); 488 putenv(*curr++);
399 } 489 }
400 i++; 490 i++;
401 } 491 }
492
402 return envp; 493 return envp;
403} 494}
404 495
@@ -726,7 +817,8 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
726 bytes = ntohs(packet.ip.tot_len); 817 bytes = ntohs(packet.ip.tot_len);
727 818
728 /* make sure its the right packet for us, and that it passes sanity checks */ 819 /* make sure its the right packet for us, and that it passes sanity checks */
729 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION 820 if (packet.ip.protocol != IPPROTO_UDP
821 || packet.ip.version != IPVERSION
730 || packet.ip.ihl != (sizeof(packet.ip) >> 2) 822 || packet.ip.ihl != (sizeof(packet.ip) >> 2)
731 || packet.udp.dest != htons(CLIENT_PORT) 823 || packet.udp.dest != htons(CLIENT_PORT)
732 /* || bytes > (int) sizeof(packet) - can't happen */ 824 /* || bytes > (int) sizeof(packet) - can't happen */
@@ -739,7 +831,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
739 /* verify IP checksum */ 831 /* verify IP checksum */
740 check = packet.ip.check; 832 check = packet.ip.check;
741 packet.ip.check = 0; 833 packet.ip.check = 0;
742 if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) { 834 if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
743 log1("Bad IP header checksum, ignoring"); 835 log1("Bad IP header checksum, ignoring");
744 return -2; 836 return -2;
745 } 837 }
@@ -750,20 +842,22 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
750 packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ 842 packet.ip.tot_len = packet.udp.len; /* yes, this is needed */
751 check = packet.udp.check; 843 check = packet.udp.check;
752 packet.udp.check = 0; 844 packet.udp.check = 0;
753 if (check && check != udhcp_checksum(&packet, bytes)) { 845 if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
754 log1("Packet with bad UDP checksum received, ignoring"); 846 log1("Packet with bad UDP checksum received, ignoring");
755 return -2; 847 return -2;
756 } 848 }
757 849
758 memcpy(dhcp_pkt, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp))); 850 if (packet.data.cookie != htonl(DHCP_MAGIC)) {
759
760 if (dhcp_pkt->cookie != htonl(DHCP_MAGIC)) {
761 bb_info_msg("Packet with bad magic, ignoring"); 851 bb_info_msg("Packet with bad magic, ignoring");
762 return -2; 852 return -2;
763 } 853 }
854
764 log1("Got valid DHCP packet"); 855 log1("Got valid DHCP packet");
765 udhcp_dump_packet(dhcp_pkt); 856 udhcp_dump_packet(&packet.data);
766 return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); 857
858 bytes -= sizeof(packet.ip) + sizeof(packet.udp);
859 memcpy(dhcp_pkt, &packet.data, bytes);
860 return bytes;
767} 861}
768 862
769 863
@@ -1077,11 +1171,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1077 1171
1078 /* Parse command line */ 1172 /* Parse command line */
1079 /* O,x: list; -T,-t,-A take numeric param */ 1173 /* O,x: list; -T,-t,-A take numeric param */
1080 opt_complementary = "O::x::T+:t+:A+" 1174 opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ;
1081#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
1082 ":vv"
1083#endif
1084 ;
1085 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1175 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
1086 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" 1176 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
1087 USE_FOR_MMU("b") 1177 USE_FOR_MMU("b")
@@ -1095,9 +1185,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1095 , &list_O 1185 , &list_O
1096 , &list_x 1186 , &list_x
1097 IF_FEATURE_UDHCP_PORT(, &str_P) 1187 IF_FEATURE_UDHCP_PORT(, &str_P)
1098#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1188 IF_UDHCP_VERBOSE(, &dhcp_verbose)
1099 , &dhcp_verbose
1100#endif
1101 ); 1189 );
1102 if (opt & (OPT_h|OPT_H)) 1190 if (opt & (OPT_h|OPT_H))
1103 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); 1191 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
@@ -1361,9 +1449,23 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1361 switch (udhcp_sp_read(&rfds)) { 1449 switch (udhcp_sp_read(&rfds)) {
1362 case SIGUSR1: 1450 case SIGUSR1:
1363 client_config.first_secs = 0; /* make secs field count from 0 */ 1451 client_config.first_secs = 0; /* make secs field count from 0 */
1452 already_waited_sec = 0;
1364 perform_renew(); 1453 perform_renew();
1365 if (state == RENEW_REQUESTED) 1454 if (state == RENEW_REQUESTED) {
1455 /* We might be either on the same network
1456 * (in which case renew might work),
1457 * or we might be on a completely different one
1458 * (in which case renew won't ever succeed).
1459 * For the second case, must make sure timeout
1460 * is not too big, or else we can send
1461 * futile renew requests for hours.
1462 * (Ab)use -A TIMEOUT value (usually 20 sec)
1463 * as a cap on the timeout.
1464 */
1465 if (timeout > tryagain_timeout)
1466 timeout = tryagain_timeout;
1366 goto case_RENEW_REQUESTED; 1467 goto case_RENEW_REQUESTED;
1468 }
1367 /* Start things over */ 1469 /* Start things over */
1368 packet_num = 0; 1470 packet_num = 0;
1369 /* Kill any timeouts, user wants this to hurry along */ 1471 /* Kill any timeouts, user wants this to hurry along */
@@ -1431,7 +1533,25 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1431 case INIT_SELECTING: 1533 case INIT_SELECTING:
1432 /* Must be a DHCPOFFER to one of our xid's */ 1534 /* Must be a DHCPOFFER to one of our xid's */
1433 if (*message == DHCPOFFER) { 1535 if (*message == DHCPOFFER) {
1434 /* TODO: why we don't just fetch server's IP from IP header? */ 1536/* What exactly is server's IP? There are several values.
1537 * Example DHCP offer captured with tchdump:
1538 *
1539 * 10.34.25.254:67 > 10.34.25.202:68 // IP header's src
1540 * BOOTP fields:
1541 * Your-IP 10.34.25.202
1542 * Server-IP 10.34.32.125 // "next server" IP
1543 * Gateway-IP 10.34.25.254 // relay's address (if DHCP relays are in use)
1544 * DHCP options:
1545 * DHCP-Message Option 53, length 1: Offer
1546 * Server-ID Option 54, length 4: 10.34.255.7 // "server ID"
1547 * Default-Gateway Option 3, length 4: 10.34.25.254 // router
1548 *
1549 * We think that real server IP (one to use in renew/release)
1550 * is one in Server-ID option. But I am not 100% sure.
1551 * IP header's src and Gateway-IP (same in this example)
1552 * might work too.
1553 * "Next server" and router are definitely wrong ones to use, though...
1554 */
1435 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1555 temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1436 if (!temp) { 1556 if (!temp) {
1437 bb_error_msg("no server ID, ignoring packet"); 1557 bb_error_msg("no server ID, ignoring packet");
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 747472d0c..dd55e70f4 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -314,9 +314,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
314#endif 314#endif
315 opt = getopt32(argv, "fSv" 315 opt = getopt32(argv, "fSv"
316 IF_FEATURE_UDHCP_PORT("P:", &str_P) 316 IF_FEATURE_UDHCP_PORT("P:", &str_P)
317#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 317 IF_UDHCP_VERBOSE(, &dhcp_verbose)
318 , &dhcp_verbose
319#endif
320 ); 318 );
321 if (!(opt & 1)) { /* no -f */ 319 if (!(opt & 1)) { /* no -f */
322 bb_daemonize_or_rexec(0, argv); 320 bb_daemonize_or_rexec(0, argv);
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index 66b42c5e1..4d5ff0676 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -129,35 +129,6 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd)
129 return bytes; 129 return bytes;
130} 130}
131 131
132uint16_t FAST_FUNC udhcp_checksum(void *addr, int count)
133{
134 /* Compute Internet Checksum for "count" bytes
135 * beginning at location "addr".
136 */
137 int32_t sum = 0;
138 uint16_t *source = (uint16_t *) addr;
139
140 while (count > 1) {
141 /* This is the inner loop */
142 sum += *source++;
143 count -= 2;
144 }
145
146 /* Add left-over byte, if any */
147 if (count > 0) {
148 /* Make sure that the left-over byte is added correctly both
149 * with little and big endian hosts */
150 uint16_t tmp = 0;
151 *(uint8_t*)&tmp = *(uint8_t*)source;
152 sum += tmp;
153 }
154 /* Fold 32-bit sum to 16 bits */
155 while (sum >> 16)
156 sum = (sum & 0xffff) + (sum >> 16);
157
158 return ~sum;
159}
160
161/* Construct a ip/udp header for a packet, send packet */ 132/* Construct a ip/udp header for a packet, send packet */
162int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, 133int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
163 uint32_t source_nip, int source_port, 134 uint32_t source_nip, int source_port,
@@ -212,13 +183,14 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
212 packet.udp.len = htons(UDP_DHCP_SIZE - padding); 183 packet.udp.len = htons(UDP_DHCP_SIZE - padding);
213 /* for UDP checksumming, ip.len is set to UDP packet len */ 184 /* for UDP checksumming, ip.len is set to UDP packet len */
214 packet.ip.tot_len = packet.udp.len; 185 packet.ip.tot_len = packet.udp.len;
215 packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding); 186 packet.udp.check = inet_cksum((uint16_t *)&packet,
187 IP_UDP_DHCP_SIZE - padding);
216 /* but for sending, it is set to IP packet len */ 188 /* but for sending, it is set to IP packet len */
217 packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); 189 packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
218 packet.ip.ihl = sizeof(packet.ip) >> 2; 190 packet.ip.ihl = sizeof(packet.ip) >> 2;
219 packet.ip.version = IPVERSION; 191 packet.ip.version = IPVERSION;
220 packet.ip.ttl = IPDEFTTL; 192 packet.ip.ttl = IPDEFTTL;
221 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); 193 packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip));
222 194
223 udhcp_dump_packet(dhcp_pkt); 195 udhcp_dump_packet(dhcp_pkt);
224 result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, 196 result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0,
diff --git a/networking/wget.c b/networking/wget.c
index eca673a86..4dd42de9d 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -298,8 +298,13 @@ static void parse_url(const char *src_url, struct host_info *h)
298 298
299 sp = strrchr(h->host, '@'); 299 sp = strrchr(h->host, '@');
300 if (sp != NULL) { 300 if (sp != NULL) {
301 h->user = h->host; 301 // URL-decode "user:password" string before base64-encoding:
302 // wget http://test:my%20pass@example.com should send
303 // Authorization: Basic dGVzdDpteSBwYXNz
304 // which decodes to "test:my pass".
305 // Standard wget and curl do this too.
302 *sp = '\0'; 306 *sp = '\0';
307 h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
303 h->host = sp + 1; 308 h->host = sp + 1;
304 } 309 }
305 310
@@ -660,12 +665,6 @@ static void download_one_url(const char *url)
660 665
661#if ENABLE_FEATURE_WGET_AUTHENTICATION 666#if ENABLE_FEATURE_WGET_AUTHENTICATION
662 if (target.user) { 667 if (target.user) {
663//TODO: URL-decode "user:password" string before base64-encoding:
664//wget http://test:my%20pass@example.com should send
665// Authorization: Basic dGVzdDpteSBwYXNz
666//which decodes to "test:my pass", instead of what we send now:
667// Authorization: Basic dGVzdDpteSUyMHBhc3M=
668//Can reuse decodeString() from httpd.c
669 fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, 668 fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
670 base64enc(target.user)); 669 base64enc(target.user));
671 } 670 }
diff --git a/networking/zcip.c b/networking/zcip.c
index 8a35eca5d..7314ff8db 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -91,6 +91,7 @@ struct globals {
91#define G (*(struct globals*)&bb_common_bufsiz1) 91#define G (*(struct globals*)&bb_common_bufsiz1)
92#define saddr (G.saddr ) 92#define saddr (G.saddr )
93#define eth_addr (G.eth_addr) 93#define eth_addr (G.eth_addr)
94#define INIT_G() do { } while (0)
94 95
95 96
96/** 97/**
@@ -223,6 +224,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
223#define verbose (L.verbose ) 224#define verbose (L.verbose )
224 225
225 memset(&L, 0, sizeof(L)); 226 memset(&L, 0, sizeof(L));
227 INIT_G();
226 228
227#define FOREGROUND (opts & 1) 229#define FOREGROUND (opts & 1)
228#define QUIT (opts & 2) 230#define QUIT (opts & 2)