diff options
author | Ron Yorston <rmy@pobox.com> | 2020-07-09 13:10:58 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-07-09 13:10:58 +0100 |
commit | 9c0b2f7020d7c30b21a930ef54be632e092e533b (patch) | |
tree | b2187c40bd2fd9f49f73599fb08e52cb7a596de0 /networking | |
parent | a8c6e20e332a9e11a9d28cd6770eadb9c9d73cb7 (diff) | |
parent | d21a63f9fca8eb16f79de9b72d4a3484dfaec1fc (diff) | |
download | busybox-w32-9c0b2f7020d7c30b21a930ef54be632e092e533b.tar.gz busybox-w32-9c0b2f7020d7c30b21a930ef54be632e092e533b.tar.bz2 busybox-w32-9c0b2f7020d7c30b21a930ef54be632e092e533b.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r-- | networking/brctl.c | 6 | ||||
-rw-r--r-- | networking/httpd.c | 5 | ||||
-rw-r--r-- | networking/nc_bloaty.c | 24 | ||||
-rw-r--r-- | networking/udhcp/common.c | 98 | ||||
-rw-r--r-- | networking/udhcp/common.h | 12 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 6 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 301 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 8 | ||||
-rw-r--r-- | networking/udhcp/domain_codec.c | 27 | ||||
-rw-r--r-- | networking/wget.c | 21 |
10 files changed, 246 insertions, 262 deletions
diff --git a/networking/brctl.c b/networking/brctl.c index 25640246d..2f4ac4a87 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -107,7 +107,7 @@ static unsigned str_to_jiffies(const char *time_str) | |||
107 | 107 | ||
108 | #define filedata bb_common_bufsiz1 | 108 | #define filedata bb_common_bufsiz1 |
109 | 109 | ||
110 | #if ENABLE_FEATURE_BRCTL_SHOW | 110 | #if ENABLE_FEATURE_BRCTL_SHOW || ENABLE_FEATURE_BRCTL_FANCY |
111 | static int read_file(const char *name) | 111 | static int read_file(const char *name) |
112 | { | 112 | { |
113 | int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); | 113 | int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); |
@@ -120,7 +120,9 @@ static int read_file(const char *name) | |||
120 | } | 120 | } |
121 | return n; | 121 | return n; |
122 | } | 122 | } |
123 | #endif | ||
123 | 124 | ||
125 | #if ENABLE_FEATURE_BRCTL_SHOW | ||
124 | /* NB: we are in /sys/class/net | 126 | /* NB: we are in /sys/class/net |
125 | */ | 127 | */ |
126 | static int show_bridge(const char *name, int need_hdr) | 128 | static int show_bridge(const char *name, int need_hdr) |
@@ -591,6 +593,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
591 | return EXIT_SUCCESS; | 593 | return EXIT_SUCCESS; |
592 | } | 594 | } |
593 | 595 | ||
596 | #if ENABLE_FEATURE_BRCTL_FANCY | ||
594 | if (key == ARG_showmacs) { | 597 | if (key == ARG_showmacs) { |
595 | show_bridge_macs(br); | 598 | show_bridge_macs(br); |
596 | return EXIT_SUCCESS; | 599 | return EXIT_SUCCESS; |
@@ -599,6 +602,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
599 | show_bridge_stp(br); | 602 | show_bridge_stp(br); |
600 | return EXIT_SUCCESS; | 603 | return EXIT_SUCCESS; |
601 | } | 604 | } |
605 | #endif | ||
602 | 606 | ||
603 | if (!*argv) /* All of the below need at least two arguments */ | 607 | if (!*argv) /* All of the below need at least two arguments */ |
604 | bb_show_usage(); | 608 | bb_show_usage(); |
diff --git a/networking/httpd.c b/networking/httpd.c index eeaa4bec1..5105eedac 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -2871,6 +2871,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2871 | #if !BB_MMU | 2871 | #if !BB_MMU |
2872 | if (!(opt & OPT_FOREGROUND)) { | 2872 | if (!(opt & OPT_FOREGROUND)) { |
2873 | bb_daemonize_or_rexec(0, argv); /* don't change current directory */ | 2873 | bb_daemonize_or_rexec(0, argv); /* don't change current directory */ |
2874 | re_execed = 0; /* for the following chdir to work */ | ||
2874 | } | 2875 | } |
2875 | #endif | 2876 | #endif |
2876 | #else /* ENABLE_PLATFORM_MINGW32 */ | 2877 | #else /* ENABLE_PLATFORM_MINGW32 */ |
@@ -2878,8 +2879,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2878 | mingw_daemonize(argv); | 2879 | mingw_daemonize(argv); |
2879 | #endif | 2880 | #endif |
2880 | 2881 | ||
2881 | /* Chdir to home (unless we were re-execed for NOMMU case: | 2882 | /* Chdir to home (unless we were re_exec()ed for NOMMU case |
2882 | * we are already in the home dir then). | 2883 | * in mini_httpd_nommu(): we are already in the home dir then). |
2883 | */ | 2884 | */ |
2884 | #if ENABLE_PLATFORM_MINGW32 | 2885 | #if ENABLE_PLATFORM_MINGW32 |
2885 | if (!(opt & OPT_INETD)) | 2886 | if (!(opt & OPT_INETD)) |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 034e03d21..88eda6b28 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -84,6 +84,7 @@ | |||
84 | //usage: ) | 84 | //usage: ) |
85 | //usage: "\n -n Don't do DNS resolution" | 85 | //usage: "\n -n Don't do DNS resolution" |
86 | //usage: "\n -u UDP mode" | 86 | //usage: "\n -u UDP mode" |
87 | //usage: "\n -b Allow broadcasts" | ||
87 | //usage: "\n -v Verbose" | 88 | //usage: "\n -v Verbose" |
88 | //usage: IF_NC_EXTRA( | 89 | //usage: IF_NC_EXTRA( |
89 | //usage: "\n -o FILE Hex dump traffic" | 90 | //usage: "\n -o FILE Hex dump traffic" |
@@ -171,17 +172,19 @@ enum { | |||
171 | OPT_p = (1 << 1), | 172 | OPT_p = (1 << 1), |
172 | OPT_s = (1 << 2), | 173 | OPT_s = (1 << 2), |
173 | OPT_u = (1 << 3), | 174 | OPT_u = (1 << 3), |
174 | OPT_v = (1 << 4), | 175 | OPT_b = (1 << 4), |
175 | OPT_w = (1 << 5), | 176 | OPT_v = (1 << 5), |
176 | OPT_l = (1 << 6) * ENABLE_NC_SERVER, | 177 | OPT_w = (1 << 6), |
177 | OPT_k = (1 << 7) * ENABLE_NC_SERVER, | 178 | OPT_l = (1 << 7) * ENABLE_NC_SERVER, |
178 | OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | 179 | OPT_k = (1 << 8) * ENABLE_NC_SERVER, |
179 | OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | 180 | OPT_i = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, |
180 | OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | 181 | OPT_o = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, |
182 | OPT_z = (1 << (9+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | #define o_nflag (option_mask32 & OPT_n) | 185 | #define o_nflag (option_mask32 & OPT_n) |
184 | #define o_udpmode (option_mask32 & OPT_u) | 186 | #define o_udpmode (option_mask32 & OPT_u) |
187 | #define o_bcmode (option_mask32 & OPT_b) | ||
185 | #if ENABLE_NC_EXTRA | 188 | #if ENABLE_NC_EXTRA |
186 | #define o_ofile (option_mask32 & OPT_o) | 189 | #define o_ofile (option_mask32 & OPT_o) |
187 | #define o_zero (option_mask32 & OPT_z) | 190 | #define o_zero (option_mask32 & OPT_z) |
@@ -788,7 +791,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
788 | 791 | ||
789 | // -g -G -t -r deleted, unimplemented -a deleted too | 792 | // -g -G -t -r deleted, unimplemented -a deleted too |
790 | getopt32(argv, "^" | 793 | getopt32(argv, "^" |
791 | "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk") | 794 | "np:s:ubvw:+"/* -w N */ IF_NC_SERVER("lk") |
792 | IF_NC_EXTRA("i:o:z") | 795 | IF_NC_EXTRA("i:o:z") |
793 | "\0" | 796 | "\0" |
794 | "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ | 797 | "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ |
@@ -851,8 +854,11 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
851 | } | 854 | } |
852 | xmove_fd(x, netfd); | 855 | xmove_fd(x, netfd); |
853 | setsockopt_reuseaddr(netfd); | 856 | setsockopt_reuseaddr(netfd); |
854 | if (o_udpmode) | 857 | if (o_udpmode) { |
858 | if (o_bcmode) | ||
859 | setsockopt_broadcast(netfd); | ||
855 | socket_want_pktinfo(netfd); | 860 | socket_want_pktinfo(netfd); |
861 | } | ||
856 | if (!ENABLE_FEATURE_UNIX_LOCAL | 862 | if (!ENABLE_FEATURE_UNIX_LOCAL |
857 | || cnt_l != 0 /* listen */ | 863 | || cnt_l != 0 /* listen */ |
858 | || ouraddr->u.sa.sa_family != AF_UNIX | 864 | || ouraddr->u.sa.sa_family != AF_UNIX |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 9ec752dfc..20d843bab 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -15,7 +15,7 @@ const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = { | |||
15 | }; | 15 | }; |
16 | 16 | ||
17 | #if ENABLE_UDHCPC || ENABLE_UDHCPD | 17 | #if ENABLE_UDHCPC || ENABLE_UDHCPD |
18 | /* Supported options are easily added here. | 18 | /* Supported options are easily added here, they need to be sorted. |
19 | * See RFC2132 for more options. | 19 | * See RFC2132 for more options. |
20 | * OPTION_REQ: these options are requested by udhcpc (unless -o). | 20 | * OPTION_REQ: these options are requested by udhcpc (unless -o). |
21 | */ | 21 | */ |
@@ -222,79 +222,91 @@ unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings | |||
222 | } | 222 | } |
223 | } | 223 | } |
224 | 224 | ||
225 | /* Get an option with bounds checking (warning, result is not aligned) */ | 225 | /* Initialize state to be used between subsequent udhcp_scan_options calls */ |
226 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | 226 | void FAST_FUNC init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) |
227 | { | ||
228 | scan_state->overload = 0; | ||
229 | scan_state->rem = sizeof(packet->options); | ||
230 | scan_state->optionptr = packet->options; | ||
231 | } | ||
232 | |||
233 | /* Iterate over packet's options, each call returning the next option. | ||
234 | * scan_state needs to be initialized with init_scan_state beforehand. | ||
235 | * Warning, result is not aligned. */ | ||
236 | uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) | ||
227 | { | 237 | { |
228 | uint8_t *optionptr; | ||
229 | int len; | 238 | int len; |
230 | int rem; | ||
231 | int overload = 0; | ||
232 | enum { | 239 | enum { |
233 | FILE_FIELD101 = FILE_FIELD * 0x101, | 240 | FILE_FIELD101 = FILE_FIELD * 0x101, |
234 | SNAME_FIELD101 = SNAME_FIELD * 0x101, | 241 | SNAME_FIELD101 = SNAME_FIELD * 0x101, |
235 | }; | 242 | }; |
236 | 243 | ||
237 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | 244 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ |
238 | optionptr = packet->options; | ||
239 | rem = sizeof(packet->options); | ||
240 | while (1) { | 245 | while (1) { |
241 | if (rem <= 0) { | 246 | if (scan_state->rem <= 0) { |
242 | complain: | 247 | complain: |
243 | bb_simple_error_msg("bad packet, malformed option field"); | 248 | bb_simple_error_msg("bad packet, malformed option field"); |
244 | return NULL; | 249 | return NULL; |
245 | } | 250 | } |
246 | 251 | ||
247 | /* DHCP_PADDING and DHCP_END have no [len] byte */ | 252 | /* DHCP_PADDING and DHCP_END have no [len] byte */ |
248 | if (optionptr[OPT_CODE] == DHCP_PADDING) { | 253 | if (scan_state->optionptr[OPT_CODE] == DHCP_PADDING) { |
249 | rem--; | 254 | scan_state->rem--; |
250 | optionptr++; | 255 | scan_state->optionptr++; |
251 | continue; | 256 | continue; |
252 | } | 257 | } |
253 | if (optionptr[OPT_CODE] == DHCP_END) { | 258 | if (scan_state->optionptr[OPT_CODE] == DHCP_END) { |
254 | if ((overload & FILE_FIELD101) == FILE_FIELD) { | 259 | if ((scan_state->overload & FILE_FIELD101) == FILE_FIELD) { |
255 | /* can use packet->file, and didn't look at it yet */ | 260 | /* can use packet->file, and didn't look at it yet */ |
256 | overload |= FILE_FIELD101; /* "we looked at it" */ | 261 | scan_state->overload |= FILE_FIELD101; /* "we looked at it" */ |
257 | optionptr = packet->file; | 262 | scan_state->optionptr = packet->file; |
258 | rem = sizeof(packet->file); | 263 | scan_state->rem = sizeof(packet->file); |
259 | continue; | 264 | continue; |
260 | } | 265 | } |
261 | if ((overload & SNAME_FIELD101) == SNAME_FIELD) { | 266 | if ((scan_state->overload & SNAME_FIELD101) == SNAME_FIELD) { |
262 | /* can use packet->sname, and didn't look at it yet */ | 267 | /* can use packet->sname, and didn't look at it yet */ |
263 | overload |= SNAME_FIELD101; /* "we looked at it" */ | 268 | scan_state->overload |= SNAME_FIELD101; /* "we looked at it" */ |
264 | optionptr = packet->sname; | 269 | scan_state->optionptr = packet->sname; |
265 | rem = sizeof(packet->sname); | 270 | scan_state->rem = sizeof(packet->sname); |
266 | continue; | 271 | continue; |
267 | } | 272 | } |
268 | break; | 273 | break; |
269 | } | 274 | } |
270 | 275 | ||
271 | if (rem <= OPT_LEN) | 276 | if (scan_state->rem <= OPT_LEN) |
272 | goto complain; /* complain and return NULL */ | 277 | goto complain; /* complain and return NULL */ |
273 | len = 2 + optionptr[OPT_LEN]; | 278 | len = 2 + scan_state->optionptr[OPT_LEN]; |
274 | rem -= len; | 279 | scan_state->rem -= len; |
275 | if (rem < 0) | 280 | /* So far no valid option with length 0 known. */ |
281 | if (scan_state->rem < 0 || scan_state->optionptr[OPT_LEN] == 0) | ||
276 | goto complain; /* complain and return NULL */ | 282 | goto complain; /* complain and return NULL */ |
277 | 283 | ||
278 | if (optionptr[OPT_CODE] == code) { | 284 | if (scan_state->optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { |
279 | if (optionptr[OPT_LEN] == 0) { | 285 | if (len >= 3) |
280 | /* So far no valid option with length 0 known. | 286 | scan_state->overload |= scan_state->optionptr[OPT_DATA]; |
281 | * Having this check means that searching | 287 | } else { |
282 | * for DHCP_MESSAGE_TYPE need not worry | 288 | uint8_t *return_ptr = scan_state->optionptr; |
283 | * that returned pointer might be unsafe | 289 | scan_state->optionptr += len; |
284 | * to dereference. | 290 | return return_ptr; |
285 | */ | ||
286 | goto complain; /* complain and return NULL */ | ||
287 | } | ||
288 | log_option("option found", optionptr); | ||
289 | return optionptr + OPT_DATA; | ||
290 | } | 291 | } |
292 | scan_state->optionptr += len; | ||
293 | } | ||
291 | 294 | ||
292 | if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { | 295 | return NULL; |
293 | if (len >= 3) | 296 | } |
294 | overload |= optionptr[OPT_DATA]; | 297 | |
295 | /* fall through */ | 298 | /* Get an option with bounds checking (warning, result is not aligned) */ |
299 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | ||
300 | { | ||
301 | uint8_t *optptr; | ||
302 | struct dhcp_scan_state scan_state; | ||
303 | |||
304 | init_scan_state(packet, &scan_state); | ||
305 | while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { | ||
306 | if (optptr[OPT_CODE] == code) { | ||
307 | log_option("option found", optptr); | ||
308 | return optptr + OPT_DATA; | ||
296 | } | 309 | } |
297 | optionptr += len; | ||
298 | } | 310 | } |
299 | 311 | ||
300 | /* log3 because udhcpc uses it a lot - very noisy */ | 312 | /* log3 because udhcpc uses it a lot - very noisy */ |
@@ -431,7 +443,7 @@ static NOINLINE void attach_option( | |||
431 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 443 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
432 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { | 444 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
433 | /* reuse buffer and length for RFC1035-formatted string */ | 445 | /* reuse buffer and length for RFC1035-formatted string */ |
434 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); | 446 | allocated = buffer = (char *)dname_enc(/*NULL, 0,*/ buffer, &length); |
435 | } | 447 | } |
436 | #endif | 448 | #endif |
437 | 449 | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 60255eefa..81c1dcbdc 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -78,7 +78,7 @@ struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { | |||
78 | /*** Options ***/ | 78 | /*** Options ***/ |
79 | 79 | ||
80 | enum { | 80 | enum { |
81 | OPTION_IP = 1, | 81 | OPTION_IP = 0, |
82 | OPTION_IP_PAIR, | 82 | OPTION_IP_PAIR, |
83 | OPTION_STRING, | 83 | OPTION_STRING, |
84 | /* Opts of STRING_HOST type will be sanitized before they are passed | 84 | /* Opts of STRING_HOST type will be sanitized before they are passed |
@@ -107,6 +107,12 @@ enum { | |||
107 | OPTION_LIST = 0x20, | 107 | OPTION_LIST = 0x20, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | struct dhcp_scan_state { | ||
111 | int overload; | ||
112 | int rem; | ||
113 | uint8_t *optionptr; | ||
114 | }; | ||
115 | |||
110 | /* DHCP option codes (partial list). See RFC 2132 and | 116 | /* DHCP option codes (partial list). See RFC 2132 and |
111 | * http://www.iana.org/assignments/bootp-dhcp-parameters/ | 117 | * http://www.iana.org/assignments/bootp-dhcp-parameters/ |
112 | * Commented out options are handled by common option machinery, | 118 | * Commented out options are handled by common option machinery, |
@@ -206,6 +212,8 @@ extern const uint8_t dhcp_option_lengths[] ALIGN1; | |||
206 | 212 | ||
207 | unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); | 213 | unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); |
208 | 214 | ||
215 | void init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; | ||
216 | uint8_t *udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; | ||
209 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; | 217 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; |
210 | /* Same as above + ensures that option length is 4 bytes | 218 | /* Same as above + ensures that option length is 4 bytes |
211 | * (returns NULL if size is different) | 219 | * (returns NULL if size is different) |
@@ -218,7 +226,7 @@ void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t | |||
218 | #endif | 226 | #endif |
219 | #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 | 227 | #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 |
220 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; | 228 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; |
221 | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; | 229 | uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC; |
222 | #endif | 230 | #endif |
223 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; | 231 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; |
224 | 232 | ||
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 85c410a7c..fc2d672b7 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -553,11 +553,15 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * | |||
553 | 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 553 | 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
554 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, | 554 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, |
555 | }; | 555 | }; |
556 | /* IPv6 requires different multicast contents in Ethernet Frame (RFC 2464) */ | ||
557 | static const uint8_t MAC_DHCP6MCAST_ADDR[6] ALIGN2 = { | ||
558 | 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, | ||
559 | }; | ||
556 | 560 | ||
557 | return d6_send_raw_packet( | 561 | return d6_send_raw_packet( |
558 | packet, (end - (uint8_t*) packet), | 562 | packet, (end - (uint8_t*) packet), |
559 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, | 563 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, |
560 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR, | 564 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR, |
561 | client_data.ifindex | 565 | client_data.ifindex |
562 | ); | 566 | ); |
563 | } | 567 | } |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 5a1f8fd7a..50dfead63 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -159,61 +159,27 @@ static int mton(uint32_t mask) | |||
159 | } | 159 | } |
160 | 160 | ||
161 | #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT | 161 | #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT |
162 | /* Check if a given label represents a valid DNS label | 162 | /* Check if a given name represents a valid DNS name */ |
163 | * Return pointer to the first character after the label | 163 | /* See RFC1035, 2.3.1 */ |
164 | * (NUL or dot) upon success, NULL otherwise. | ||
165 | * See RFC1035, 2.3.1 | ||
166 | */ | ||
167 | /* We don't need to be particularly anal. For example, allowing _, hyphen | 164 | /* We don't need to be particularly anal. For example, allowing _, hyphen |
168 | * at the end, or leading and trailing dots would be ok, since it | 165 | * at the end, or leading and trailing dots would be ok, since it |
169 | * can't be used for attacks. (Leading hyphen can be, if someone uses | 166 | * can't be used for attacks. (Leading hyphen can be, if someone uses cmd "$hostname" |
170 | * cmd "$hostname" | ||
171 | * in the script: then hostname may be treated as an option) | 167 | * in the script: then hostname may be treated as an option) |
172 | */ | 168 | */ |
173 | static const char *valid_domain_label(const char *label) | ||
174 | { | ||
175 | unsigned char ch; | ||
176 | //unsigned pos = 0; | ||
177 | |||
178 | if (label[0] == '-') | ||
179 | return NULL; | ||
180 | for (;;) { | ||
181 | ch = *label; | ||
182 | if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { | ||
183 | if (ch < '0' || ch > '9') { | ||
184 | if (ch == '\0' || ch == '.') | ||
185 | return label; | ||
186 | /* DNS allows only '-', but we are more permissive */ | ||
187 | if (ch != '-' && ch != '_') | ||
188 | return NULL; | ||
189 | } | ||
190 | } | ||
191 | label++; | ||
192 | //pos++; | ||
193 | //Do we want this? | ||
194 | //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ | ||
195 | // return NULL; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* Check if a given name represents a valid DNS name */ | ||
200 | /* See RFC1035, 2.3.1 */ | ||
201 | static int good_hostname(const char *name) | 169 | static int good_hostname(const char *name) |
202 | { | 170 | { |
203 | //const char *start = name; | 171 | if (*name == '-') /* Can't start with '-' */ |
204 | 172 | return 0; | |
205 | for (;;) { | 173 | |
206 | name = valid_domain_label(name); | 174 | while (*name) { |
207 | if (!name) | 175 | unsigned char ch = *name++; |
208 | return 0; | 176 | if (!isalnum(ch)) |
209 | if (!name[0]) | 177 | /* DNS allows only '-', but we are more permissive */ |
210 | return 1; | 178 | if (ch != '-' && ch != '_' && ch != '.') |
211 | //Do we want this? | 179 | return 0; |
212 | //return ((name - start) < 1025); /* NS_MAXDNAME */ | 180 | // TODO: do we want to validate lengths against NS_MAXLABEL and NS_MAXDNAME? |
213 | name++; | ||
214 | if (*name == '\0') | ||
215 | return 1; // We allow trailing dot too | ||
216 | } | 181 | } |
182 | return 1; | ||
217 | } | 183 | } |
218 | #else | 184 | #else |
219 | # define good_hostname(name) 1 | 185 | # define good_hostname(name) 1 |
@@ -242,9 +208,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
242 | case OPTION_IP: | 208 | case OPTION_IP: |
243 | case OPTION_IP_PAIR: | 209 | case OPTION_IP_PAIR: |
244 | dest += sprint_nip(dest, "", option); | 210 | dest += sprint_nip(dest, "", option); |
245 | if (type == OPTION_IP) | 211 | if (type == OPTION_IP_PAIR) |
246 | break; | 212 | dest += sprint_nip(dest, "/", option + 4); |
247 | dest += sprint_nip(dest, "/", option + 4); | ||
248 | break; | 213 | break; |
249 | // case OPTION_BOOLEAN: | 214 | // case OPTION_BOOLEAN: |
250 | // dest += sprintf(dest, *option ? "yes" : "no"); | 215 | // dest += sprintf(dest, *option ? "yes" : "no"); |
@@ -346,7 +311,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
346 | * IPv4MaskLen <= 32, | 311 | * IPv4MaskLen <= 32, |
347 | * 6rdPrefixLen <= 128, | 312 | * 6rdPrefixLen <= 128, |
348 | * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 | 313 | * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 |
349 | * (2nd condition need no check - it follows from 1st and 3rd). | 314 | * (2nd condition needs no check - it follows from 1st and 3rd). |
350 | * Else, return envvar with empty value ("optname=") | 315 | * Else, return envvar with empty value ("optname=") |
351 | */ | 316 | */ |
352 | if (len >= (1 + 1 + 16 + 4) | 317 | if (len >= (1 + 1 + 16 + 4) |
@@ -360,17 +325,12 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
360 | /* 6rdPrefix */ | 325 | /* 6rdPrefix */ |
361 | dest += sprint_nip6(dest, /* "", */ option); | 326 | dest += sprint_nip6(dest, /* "", */ option); |
362 | option += 16; | 327 | option += 16; |
363 | len -= 1 + 1 + 16 + 4; | 328 | len -= 1 + 1 + 16; |
364 | /* "+ 4" above corresponds to the length of IPv4 addr | 329 | *dest++ = ' '; |
365 | * we consume in the loop below */ | 330 | /* 6rdBRIPv4Address(es), use common IPv4 logic to process them */ |
366 | while (1) { | 331 | type = OPTION_IP; |
367 | /* 6rdBRIPv4Address(es) */ | 332 | optlen = 4; |
368 | dest += sprint_nip(dest, " ", option); | 333 | continue; |
369 | option += 4; | ||
370 | len -= 4; /* do we have yet another 4+ bytes? */ | ||
371 | if (len < 0) | ||
372 | break; /* no */ | ||
373 | } | ||
374 | } | 334 | } |
375 | 335 | ||
376 | return ret; | 336 | return ret; |
@@ -392,23 +352,18 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
392 | */ | 352 | */ |
393 | option++; | 353 | option++; |
394 | len--; | 354 | len--; |
355 | if (option[-1] == 1) { | ||
356 | /* use common IPv4 logic to process IP addrs */ | ||
357 | type = OPTION_IP; | ||
358 | optlen = 4; | ||
359 | continue; | ||
360 | } | ||
395 | if (option[-1] == 0) { | 361 | if (option[-1] == 0) { |
396 | dest = dname_dec(option, len, ret); | 362 | dest = dname_dec(option, len, ret); |
397 | if (dest) { | 363 | if (dest) { |
398 | free(ret); | 364 | free(ret); |
399 | return dest; | 365 | return dest; |
400 | } | 366 | } |
401 | } else | ||
402 | if (option[-1] == 1) { | ||
403 | const char *pfx = ""; | ||
404 | while (1) { | ||
405 | len -= 4; | ||
406 | if (len < 0) | ||
407 | break; | ||
408 | dest += sprint_nip(dest, pfx, option); | ||
409 | pfx = " "; | ||
410 | option += 4; | ||
411 | } | ||
412 | } | 367 | } |
413 | return ret; | 368 | return ret; |
414 | #endif | 369 | #endif |
@@ -431,59 +386,78 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
431 | return ret; | 386 | return ret; |
432 | } | 387 | } |
433 | 388 | ||
434 | /* put all the parameters into the environment */ | 389 | static void putenvp(llist_t **envp, char *new_opt) |
435 | static char **fill_envp(struct dhcp_packet *packet) | 390 | { |
391 | putenv(new_opt); | ||
392 | log2(" %s", new_opt); | ||
393 | llist_add_to(envp, new_opt); | ||
394 | } | ||
395 | |||
396 | static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh) | ||
436 | { | 397 | { |
437 | int envc; | 398 | /* Find the option: |
438 | int i; | 399 | * dhcp_optflags is sorted so we stop searching when dh->code >= code, which is faster |
439 | char **envp, **curr; | 400 | * than iterating over the entire array. |
440 | const char *opt_name; | 401 | * Options which don't have a match in dhcp_option_strings[], e.g DHCP_REQUESTED_IP, |
441 | uint8_t *temp; | 402 | * are located after the sorted array, so these entries will never be reached |
442 | uint8_t overload = 0; | 403 | * and they'll count as unknown options. |
443 | |||
444 | #define BITMAP unsigned | ||
445 | #define BBITS (sizeof(BITMAP) * 8) | ||
446 | #define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1))) | ||
447 | #define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS]) | ||
448 | BITMAP found_opts[256 / BBITS]; | ||
449 | |||
450 | memset(found_opts, 0, sizeof(found_opts)); | ||
451 | |||
452 | /* We need 7 elements for: | ||
453 | * "interface=IFACE" | ||
454 | * "ip=N.N.N.N" from packet->yiaddr | ||
455 | * "giaddr=IP" from packet->gateway_nip (unless 0) | ||
456 | * "siaddr=IP" from packet->siaddr_nip (unless 0) | ||
457 | * "boot_file=FILE" from packet->file (unless overloaded) | ||
458 | * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) | ||
459 | * terminating NULL | ||
460 | */ | 404 | */ |
461 | envc = 7; | 405 | for (*dh = dhcp_optflags; (*dh)->code && (*dh)->code < code; (*dh)++) |
462 | /* +1 element for each option, +2 for subnet option: */ | 406 | continue; |
463 | if (packet) { | 407 | |
464 | /* note: do not search for "pad" (0) and "end" (255) options */ | 408 | if ((*dh)->code == code) |
465 | //TODO: change logic to scan packet _once_ | 409 | return nth_string(dhcp_option_strings, (*dh - dhcp_optflags)); |
466 | for (i = 1; i < 255; i++) { | 410 | |
467 | temp = udhcp_get_option(packet, i); | 411 | return NULL; |
468 | if (temp) { | 412 | } |
469 | if (i == DHCP_OPTION_OVERLOAD) | 413 | |
470 | overload |= *temp; | 414 | /* put all the parameters into the environment */ |
471 | else if (i == DHCP_SUBNET) | 415 | static llist_t *fill_envp(struct dhcp_packet *packet) |
472 | envc++; /* for $mask */ | 416 | { |
473 | envc++; | 417 | uint8_t *optptr; |
474 | /*if (i != DHCP_MESSAGE_TYPE)*/ | 418 | struct dhcp_scan_state scan_state; |
475 | FOUND_OPTS(i) |= BMASK(i); | 419 | char *new_opt; |
476 | } | 420 | llist_t *envp = NULL; |
477 | } | ||
478 | } | ||
479 | curr = envp = xzalloc(sizeof(envp[0]) * envc); | ||
480 | 421 | ||
481 | *curr = xasprintf("interface=%s", client_data.interface); | 422 | putenvp(&envp, xasprintf("interface=%s", client_data.interface)); |
482 | putenv(*curr++); | ||
483 | 423 | ||
484 | if (!packet) | 424 | if (!packet) |
485 | return envp; | 425 | return envp; |
486 | 426 | ||
427 | init_scan_state(packet, &scan_state); | ||
428 | |||
429 | /* Iterate over the packet options. | ||
430 | * Handle each option based on whether it's an unknown / known option. | ||
431 | * There may be (although unlikely) duplicate options. For now, only the last | ||
432 | * appearing option will be stored in the environment, and all duplicates | ||
433 | * are freed properly. | ||
434 | * Long options may be implemented in the future (see RFC 3396) if needed. | ||
435 | */ | ||
436 | while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { | ||
437 | const struct dhcp_optflag *dh; | ||
438 | const char *opt_name; | ||
439 | uint8_t code = optptr[OPT_CODE]; | ||
440 | uint8_t len = optptr[OPT_LEN]; | ||
441 | uint8_t *data = optptr + OPT_DATA; | ||
442 | |||
443 | opt_name = get_optname(code, &dh); | ||
444 | if (opt_name) { | ||
445 | new_opt = xmalloc_optname_optval(data, dh, opt_name); | ||
446 | if (code == DHCP_SUBNET && len == 4) { | ||
447 | uint32_t subnet; | ||
448 | putenvp(&envp, new_opt); | ||
449 | move_from_unaligned32(subnet, data); | ||
450 | new_opt = xasprintf("mask=%u", mton(subnet)); | ||
451 | } | ||
452 | } else { | ||
453 | unsigned ofs; | ||
454 | new_opt = xmalloc(sizeof("optNNN=") + 1 + len*2); | ||
455 | ofs = sprintf(new_opt, "opt%u=", code); | ||
456 | bin2hex(new_opt + ofs, (char *)data, len)[0] = '\0'; | ||
457 | } | ||
458 | putenvp(&envp, new_opt); | ||
459 | } | ||
460 | |||
487 | /* Export BOOTP fields. Fields we don't (yet?) export: | 461 | /* Export BOOTP fields. Fields we don't (yet?) export: |
488 | * uint8_t op; // always BOOTREPLY | 462 | * uint8_t op; // always BOOTREPLY |
489 | * uint8_t htype; // hardware address type. 1 = 10mb ethernet | 463 | * uint8_t htype; // hardware address type. 1 = 10mb ethernet |
@@ -497,77 +471,31 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
497 | * uint8_t chaddr[16]; // link-layer client hardware address (MAC) | 471 | * uint8_t chaddr[16]; // link-layer client hardware address (MAC) |
498 | */ | 472 | */ |
499 | /* Most important one: yiaddr as $ip */ | 473 | /* Most important one: yiaddr as $ip */ |
500 | *curr = xmalloc(sizeof("ip=255.255.255.255")); | 474 | new_opt = xmalloc(sizeof("ip=255.255.255.255")); |
501 | sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); | 475 | sprint_nip(new_opt, "ip=", (uint8_t *) &packet->yiaddr); |
502 | putenv(*curr++); | 476 | putenvp(&envp, new_opt); |
477 | |||
503 | if (packet->siaddr_nip) { | 478 | if (packet->siaddr_nip) { |
504 | /* IP address of next server to use in bootstrap */ | 479 | /* IP address of next server to use in bootstrap */ |
505 | *curr = xmalloc(sizeof("siaddr=255.255.255.255")); | 480 | new_opt = xmalloc(sizeof("siaddr=255.255.255.255")); |
506 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); | 481 | sprint_nip(new_opt, "siaddr=", (uint8_t *) &packet->siaddr_nip); |
507 | putenv(*curr++); | 482 | putenvp(&envp, new_opt); |
508 | } | 483 | } |
509 | if (packet->gateway_nip) { | 484 | if (packet->gateway_nip) { |
510 | /* IP address of DHCP relay agent */ | 485 | /* IP address of DHCP relay agent */ |
511 | *curr = xmalloc(sizeof("giaddr=255.255.255.255")); | 486 | new_opt = xmalloc(sizeof("giaddr=255.255.255.255")); |
512 | sprint_nip(*curr, "giaddr=", (uint8_t *) &packet->gateway_nip); | 487 | sprint_nip(new_opt, "giaddr=", (uint8_t *) &packet->gateway_nip); |
513 | putenv(*curr++); | 488 | putenvp(&envp, new_opt); |
514 | } | 489 | } |
515 | if (!(overload & FILE_FIELD) && packet->file[0]) { | 490 | if (!(scan_state.overload & FILE_FIELD) && packet->file[0]) { |
516 | /* watch out for invalid packets */ | 491 | /* watch out for invalid packets */ |
517 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); | 492 | new_opt = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); |
518 | putenv(*curr++); | 493 | putenvp(&envp, new_opt); |
519 | } | 494 | } |
520 | if (!(overload & SNAME_FIELD) && packet->sname[0]) { | 495 | if (!(scan_state.overload & SNAME_FIELD) && packet->sname[0]) { |
521 | /* watch out for invalid packets */ | 496 | /* watch out for invalid packets */ |
522 | *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); | 497 | new_opt = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); |
523 | putenv(*curr++); | 498 | putenvp(&envp, new_opt); |
524 | } | ||
525 | |||
526 | /* Export known DHCP options */ | ||
527 | opt_name = dhcp_option_strings; | ||
528 | i = 0; | ||
529 | while (*opt_name) { | ||
530 | uint8_t code = dhcp_optflags[i].code; | ||
531 | BITMAP *found_ptr = &FOUND_OPTS(code); | ||
532 | BITMAP found_mask = BMASK(code); | ||
533 | if (!(*found_ptr & found_mask)) | ||
534 | goto next; | ||
535 | *found_ptr &= ~found_mask; /* leave only unknown options */ | ||
536 | temp = udhcp_get_option(packet, code); | ||
537 | *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); | ||
538 | putenv(*curr++); | ||
539 | if (code == DHCP_SUBNET && temp[-OPT_DATA + OPT_LEN] == 4) { | ||
540 | /* Subnet option: make things like "$ip/$mask" possible */ | ||
541 | uint32_t subnet; | ||
542 | move_from_unaligned32(subnet, temp); | ||
543 | *curr = xasprintf("mask=%u", mton(subnet)); | ||
544 | putenv(*curr++); | ||
545 | } | ||
546 | next: | ||
547 | opt_name += strlen(opt_name) + 1; | ||
548 | i++; | ||
549 | } | ||
550 | /* Export unknown options */ | ||
551 | for (i = 0; i < 256;) { | ||
552 | BITMAP bitmap = FOUND_OPTS(i); | ||
553 | if (!bitmap) { | ||
554 | i += BBITS; | ||
555 | continue; | ||
556 | } | ||
557 | if (bitmap & BMASK(i)) { | ||
558 | unsigned len, ofs; | ||
559 | |||
560 | temp = udhcp_get_option(packet, i); | ||
561 | /* udhcp_get_option returns ptr to data portion, | ||
562 | * need to go back to get len | ||
563 | */ | ||
564 | len = temp[-OPT_DATA + OPT_LEN]; | ||
565 | *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); | ||
566 | ofs = sprintf(*curr, "opt%u=", i); | ||
567 | *bin2hex(*curr + ofs, (void*) temp, len) = '\0'; | ||
568 | putenv(*curr++); | ||
569 | } | ||
570 | i++; | ||
571 | } | 499 | } |
572 | 500 | ||
573 | return envp; | 501 | return envp; |
@@ -576,7 +504,7 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
576 | /* Call a script with a par file and env vars */ | 504 | /* Call a script with a par file and env vars */ |
577 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | 505 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) |
578 | { | 506 | { |
579 | char **envp, **curr; | 507 | llist_t *envp; |
580 | char *argv[3]; | 508 | char *argv[3]; |
581 | 509 | ||
582 | envp = fill_envp(packet); | 510 | envp = fill_envp(packet); |
@@ -588,11 +516,8 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | |||
588 | argv[2] = NULL; | 516 | argv[2] = NULL; |
589 | spawn_and_wait(argv); | 517 | spawn_and_wait(argv); |
590 | 518 | ||
591 | for (curr = envp; *curr; curr++) { | 519 | /* Free all allocated environment variables */ |
592 | log2(" %s", *curr); | 520 | llist_free(envp, (void (*)(void *))bb_unsetenv_and_free); |
593 | bb_unsetenv_and_free(*curr); | ||
594 | } | ||
595 | free(envp); | ||
596 | } | 521 | } |
597 | 522 | ||
598 | 523 | ||
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 9d6604943..acfdaa8c3 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -46,6 +46,12 @@ | |||
46 | #include "dhcpc.h" | 46 | #include "dhcpc.h" |
47 | #include "dhcpd.h" | 47 | #include "dhcpd.h" |
48 | 48 | ||
49 | #if ENABLE_PID_FILE_PATH | ||
50 | #define PID_FILE_PATH CONFIG_PID_FILE_PATH | ||
51 | #else | ||
52 | #define PID_FILE_PATH "/var/run" | ||
53 | #endif | ||
54 | |||
49 | /* globals */ | 55 | /* globals */ |
50 | #define g_leases ((struct dyn_lease*)ptr_to_globals) | 56 | #define g_leases ((struct dyn_lease*)ptr_to_globals) |
51 | /* struct server_data_t server_data is in bb_common_bufsiz1 */ | 57 | /* struct server_data_t server_data is in bb_common_bufsiz1 */ |
@@ -406,7 +412,7 @@ static const struct config_keyword keywords[] = { | |||
406 | {"offer_time" , read_u32 , OFS(offer_time ), "60"}, | 412 | {"offer_time" , read_u32 , OFS(offer_time ), "60"}, |
407 | {"min_lease" , read_u32 , OFS(min_lease_sec), "60"}, | 413 | {"min_lease" , read_u32 , OFS(min_lease_sec), "60"}, |
408 | {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE}, | 414 | {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE}, |
409 | {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"}, | 415 | {"pidfile" , read_str , OFS(pidfile ), PID_FILE_PATH "/udhcpd.pid"}, |
410 | {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"}, | 416 | {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"}, |
411 | /* keywords with no defaults must be last! */ | 417 | /* keywords with no defaults must be last! */ |
412 | {"option" , read_optset , OFS(options ), ""}, | 418 | {"option" , read_optset , OFS(options ), ""}, |
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c index b7a3a5353..752c0a863 100644 --- a/networking/udhcp/domain_codec.c +++ b/networking/udhcp/domain_codec.c | |||
@@ -109,11 +109,11 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) | |||
109 | return ret; | 109 | return ret; |
110 | } | 110 | } |
111 | 111 | ||
112 | /* Convert a domain name (src) from human-readable "foo.blah.com" format into | 112 | /* Convert a domain name (src) from human-readable "foo.BLAH.com" format into |
113 | * RFC1035 encoding "\003foo\004blah\003com\000". Return allocated string, or | 113 | * RFC1035 encoding "\003foo\004blah\003com\000". Return allocated string, or |
114 | * NULL if an error occurs. | 114 | * NULL if an error occurs. |
115 | */ | 115 | */ |
116 | static uint8_t *convert_dname(const char *src) | 116 | static uint8_t *convert_dname(const char *src, int *retlen) |
117 | { | 117 | { |
118 | uint8_t c, *res, *lenptr, *dst; | 118 | uint8_t c, *res, *lenptr, *dst; |
119 | int len; | 119 | int len; |
@@ -129,6 +129,7 @@ static uint8_t *convert_dname(const char *src) | |||
129 | /* label too long, too short, or two '.'s in a row? abort */ | 129 | /* label too long, too short, or two '.'s in a row? abort */ |
130 | if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { | 130 | if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { |
131 | free(res); | 131 | free(res); |
132 | *retlen = 0; | ||
132 | return NULL; | 133 | return NULL; |
133 | } | 134 | } |
134 | *lenptr = len; | 135 | *lenptr = len; |
@@ -144,13 +145,16 @@ static uint8_t *convert_dname(const char *src) | |||
144 | 145 | ||
145 | if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ | 146 | if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ |
146 | free(res); | 147 | free(res); |
148 | *retlen = 0; | ||
147 | return NULL; | 149 | return NULL; |
148 | } | 150 | } |
149 | 151 | ||
150 | *dst = 0; | 152 | *dst++ = 0; |
153 | *retlen = dst - res; | ||
151 | return res; | 154 | return res; |
152 | } | 155 | } |
153 | 156 | ||
157 | #if 0 //UNUSED | ||
154 | /* Returns the offset within cstr at which dname can be found, or -1 */ | 158 | /* Returns the offset within cstr at which dname can be found, or -1 */ |
155 | static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) | 159 | static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) |
156 | { | 160 | { |
@@ -188,28 +192,27 @@ static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) | |||
188 | 192 | ||
189 | return -1; | 193 | return -1; |
190 | } | 194 | } |
195 | #endif | ||
191 | 196 | ||
197 | uint8_t* FAST_FUNC dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) | ||
198 | { | ||
199 | #if 0 //UNUSED, was intended for long, repetitive DHCP_DOMAIN_SEARCH options? | ||
200 | uint8_t *d, *dname; | ||
192 | /* Computes string to be appended to cstr so that src would be added to | 201 | /* Computes string to be appended to cstr so that src would be added to |
193 | * the compression (best case, it's a 2-byte pointer to some offset within | 202 | * the compression (best case, it's a 2-byte pointer to some offset within |
194 | * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). | 203 | * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). |
195 | * The computed string is returned directly; its length is returned via retlen; | 204 | * The computed string is returned directly; its length is returned via retlen; |
196 | * NULL and 0, respectively, are returned if an error occurs. | 205 | * NULL and 0, respectively, are returned if an error occurs. |
197 | */ | 206 | */ |
198 | uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) | 207 | dname = convert_dname(src, retlen); |
199 | { | ||
200 | uint8_t *d, *dname; | ||
201 | int off; | ||
202 | |||
203 | dname = convert_dname(src); | ||
204 | if (dname == NULL) { | 208 | if (dname == NULL) { |
205 | *retlen = 0; | ||
206 | return NULL; | 209 | return NULL; |
207 | } | 210 | } |
208 | 211 | ||
209 | d = dname; | 212 | d = dname; |
210 | while (*d) { | 213 | while (*d) { |
211 | if (cstr) { | 214 | if (cstr) { |
212 | off = find_offset(cstr, clen, d); | 215 | int off = find_offset(cstr, clen, d); |
213 | if (off >= 0) { /* found a match, add pointer and return */ | 216 | if (off >= 0) { /* found a match, add pointer and return */ |
214 | *d++ = NS_CMPRSFLGS | (off >> 8); | 217 | *d++ = NS_CMPRSFLGS | (off >> 8); |
215 | *d = off; | 218 | *d = off; |
@@ -221,6 +224,8 @@ uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int | |||
221 | 224 | ||
222 | *retlen = d - dname + 1; | 225 | *retlen = d - dname + 1; |
223 | return dname; | 226 | return dname; |
227 | #endif | ||
228 | return convert_dname(src, retlen); | ||
224 | } | 229 | } |
225 | 230 | ||
226 | #ifdef DNS_COMPR_TESTING | 231 | #ifdef DNS_COMPR_TESTING |
diff --git a/networking/wget.c b/networking/wget.c index bc237c4a8..8a967fe20 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -679,7 +679,8 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
679 | pid = xvfork(); | 679 | pid = xvfork(); |
680 | if (pid == 0) { | 680 | if (pid == 0) { |
681 | /* Child */ | 681 | /* Child */ |
682 | char *argv[9]; | 682 | char *argv[13]; |
683 | char **argp; | ||
683 | 684 | ||
684 | close(sp[0]); | 685 | close(sp[0]); |
685 | xmove_fd(sp[1], 0); | 686 | xmove_fd(sp[1], 0); |
@@ -702,13 +703,25 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) | |||
702 | * TLS server_name (SNI) field are FQDNs (DNS hostnames). | 703 | * TLS server_name (SNI) field are FQDNs (DNS hostnames). |
703 | * IPv4 and IPv6 addresses, port numbers are not allowed. | 704 | * IPv4 and IPv6 addresses, port numbers are not allowed. |
704 | */ | 705 | */ |
706 | argp = &argv[5]; | ||
705 | if (!is_ip_address(servername)) { | 707 | if (!is_ip_address(servername)) { |
706 | argv[5] = (char*)"-servername"; | 708 | *argp++ = (char*)"-servername"; //[5] |
707 | argv[6] = (char*)servername; | 709 | *argp++ = (char*)servername; //[6] |
708 | } | 710 | } |
709 | if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { | 711 | if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { |
710 | argv[7] = (char*)"-verify_return_error"; | 712 | /* Abort on bad server certificate */ |
713 | *argp++ = (char*)"-verify"; //[7] | ||
714 | *argp++ = (char*)"100"; //[8] | ||
715 | *argp++ = (char*)"-verify_return_error"; //[9] | ||
716 | if (!is_ip_address(servername)) { | ||
717 | *argp++ = (char*)"-verify_hostname"; //[10] | ||
718 | *argp++ = (char*)servername; //[11] | ||
719 | } else { | ||
720 | *argp++ = (char*)"-verify_ip"; //[10] | ||
721 | *argp++ = (char*)host; //[11] | ||
722 | } | ||
711 | } | 723 | } |
724 | //[12] (or earlier) is NULL terminator | ||
712 | 725 | ||
713 | BB_EXECVP(argv[0], argv); | 726 | BB_EXECVP(argv[0], argv); |
714 | xmove_fd(3, 2); | 727 | xmove_fd(3, 2); |