aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-07-09 13:10:58 +0100
committerRon Yorston <rmy@pobox.com>2020-07-09 13:10:58 +0100
commit9c0b2f7020d7c30b21a930ef54be632e092e533b (patch)
treeb2187c40bd2fd9f49f73599fb08e52cb7a596de0 /networking
parenta8c6e20e332a9e11a9d28cd6770eadb9c9d73cb7 (diff)
parentd21a63f9fca8eb16f79de9b72d4a3484dfaec1fc (diff)
downloadbusybox-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.c6
-rw-r--r--networking/httpd.c5
-rw-r--r--networking/nc_bloaty.c24
-rw-r--r--networking/udhcp/common.c98
-rw-r--r--networking/udhcp/common.h12
-rw-r--r--networking/udhcp/d6_dhcpc.c6
-rw-r--r--networking/udhcp/dhcpc.c301
-rw-r--r--networking/udhcp/dhcpd.c8
-rw-r--r--networking/udhcp/domain_codec.c27
-rw-r--r--networking/wget.c21
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
111static int read_file(const char *name) 111static 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 */
126static int show_bridge(const char *name, int need_hdr) 128static 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 */
226uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) 226void 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. */
236uint8_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) */
299uint8_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
80enum { 80enum {
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
110struct 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
207unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); 213unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings);
208 214
215void init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC;
216uint8_t *udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC;
209uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; 217uint8_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
220char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; 228char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC;
221uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; 229uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC;
222#endif 230#endif
223struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; 231struct 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 */
173static 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 */
201static int good_hostname(const char *name) 169static 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 */ 389static void putenvp(llist_t **envp, char *new_opt)
435static 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
396static 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) 415static 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 */
577static void udhcp_run_script(struct dhcp_packet *packet, const char *name) 505static 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 */
116static uint8_t *convert_dname(const char *src) 116static 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 */
155static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) 159static 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
197uint8_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 */
198uint8_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);