aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-05-14 08:17:12 +0100
committerRon Yorston <rmy@pobox.com>2021-05-14 08:17:12 +0100
commita3f5a1b7f4275f713acf22f534f95c0da8392e53 (patch)
tree49b65422a3e9c33f508da9ccf3ae79d324bd9e96 /networking
parent375cda9a88024135d630ca8990d9aff4ea414e89 (diff)
parent7de0ab21d939a5a304157f75918d0318a95261a3 (diff)
downloadbusybox-w32-a3f5a1b7f4275f713acf22f534f95c0da8392e53.tar.gz
busybox-w32-a3f5a1b7f4275f713acf22f534f95c0da8392e53.tar.bz2
busybox-w32-a3f5a1b7f4275f713acf22f534f95c0da8392e53.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r--networking/brctl.c1
-rw-r--r--networking/httpd.c305
-rw-r--r--networking/inetd.c2
-rw-r--r--networking/ntpd.c109
-rw-r--r--networking/tls.c120
-rw-r--r--networking/tls.h13
-rw-r--r--networking/tls_fe.c89
-rw-r--r--networking/tls_fe.h7
-rw-r--r--networking/tls_pstm.c8
-rw-r--r--networking/tls_pstm_montgomery_reduce.c30
-rw-r--r--networking/tls_rsa.c4
-rw-r--r--networking/tls_sp_c32.c927
-rw-r--r--networking/udhcp/common.c26
-rw-r--r--networking/udhcp/d6_dhcpc.c122
-rw-r--r--networking/udhcp/dhcpc.c170
-rw-r--r--networking/udhcp/signalpipe.c2
-rw-r--r--networking/wget.c52
17 files changed, 1483 insertions, 504 deletions
diff --git a/networking/brctl.c b/networking/brctl.c
index e1f3e6445..c83aac6e0 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -89,6 +89,7 @@ static unsigned str_to_jiffies(const char *time_str)
89{ 89{
90 double dd; 90 double dd;
91 char *endptr; 91 char *endptr;
92//TODO: needs setlocale(LC_NUMERIC, "C")?
92 dd = /*bb_*/strtod(time_str, &endptr); 93 dd = /*bb_*/strtod(time_str, &endptr);
93 if (endptr == time_str || dd < 0) 94 if (endptr == time_str || dd < 0)
94 bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec"); 95 bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec");
diff --git a/networking/httpd.c b/networking/httpd.c
index 08313bbc7..fcc49853a 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -312,6 +312,12 @@
312 312
313#define DEBUG 0 313#define DEBUG 0
314 314
315#if DEBUG
316# define dbg(...) fprintf(stderr, __VA_ARGS__)
317#else
318# define dbg(...) ((void)0)
319#endif
320
315#define IOBUF_SIZE 8192 321#define IOBUF_SIZE 8192
316#define MAX_HTTP_HEADERS_SIZE (32*1024) 322#define MAX_HTTP_HEADERS_SIZE (32*1024)
317 323
@@ -353,13 +359,6 @@ typedef struct Htaccess_Proxy {
353 char *url_to; 359 char *url_to;
354} Htaccess_Proxy; 360} Htaccess_Proxy;
355 361
356typedef enum CGI_type {
357 CGI_NONE = 0,
358 CGI_NORMAL,
359 CGI_INDEX,
360 CGI_INTERPRETER,
361} CGI_type;
362
363enum { 362enum {
364 HTTP_OK = 200, 363 HTTP_OK = 200,
365 HTTP_PARTIAL_CONTENT = 206, 364 HTTP_PARTIAL_CONTENT = 206,
@@ -564,7 +563,6 @@ enum {
564enum { 563enum {
565 SEND_HEADERS = (1 << 0), 564 SEND_HEADERS = (1 << 0),
566 SEND_BODY = (1 << 1), 565 SEND_BODY = (1 << 1),
567 SEND_HEADERS_AND_BODY = SEND_HEADERS + SEND_BODY,
568}; 566};
569static void send_file_and_exit(const char *url, int what) NORETURN; 567static void send_file_and_exit(const char *url, int what) NORETURN;
570 568
@@ -696,7 +694,7 @@ enum {
696 SIGNALED_PARSE = 1, /* path will be "/etc" */ 694 SIGNALED_PARSE = 1, /* path will be "/etc" */
697 SUBDIR_PARSE = 2, /* path will be derived from URL */ 695 SUBDIR_PARSE = 2, /* path will be derived from URL */
698}; 696};
699static void parse_conf(const char *path, int flag) 697static int parse_conf(const char *path, int flag)
700{ 698{
701 /* internally used extra flag state */ 699 /* internally used extra flag state */
702 enum { TRY_CURDIR_PARSE = 3 }; 700 enum { TRY_CURDIR_PARSE = 3 };
@@ -737,7 +735,7 @@ static void parse_conf(const char *path, int flag)
737 while ((f = fopen_for_read(filename)) == NULL) { 735 while ((f = fopen_for_read(filename)) == NULL) {
738 if (flag >= SUBDIR_PARSE) { /* SUBDIR or TRY_CURDIR */ 736 if (flag >= SUBDIR_PARSE) { /* SUBDIR or TRY_CURDIR */
739 /* config file not found, no changes to config */ 737 /* config file not found, no changes to config */
740 return; 738 return -1;
741 } 739 }
742 if (flag == FIRST_PARSE) { 740 if (flag == FIRST_PARSE) {
743 /* -c CONFFILE given, but CONFFILE doesn't exist? */ 741 /* -c CONFFILE given, but CONFFILE doesn't exist? */
@@ -1000,6 +998,7 @@ static void parse_conf(const char *path, int flag)
1000 } /* while (fgets) */ 998 } /* while (fgets) */
1001 999
1002 fclose(f); 1000 fclose(f);
1001 return 0;
1003} 1002}
1004 1003
1005#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR 1004#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
@@ -1186,8 +1185,7 @@ static void send_headers(unsigned responseNum)
1186 fprintf(stderr, "headers: '%s'\n", iobuf); 1185 fprintf(stderr, "headers: '%s'\n", iobuf);
1187 } 1186 }
1188 full_write(STDOUT_FILENO, iobuf, len); 1187 full_write(STDOUT_FILENO, iobuf, len);
1189 if (DEBUG) 1188 dbg("writing error page: '%s'\n", error_page);
1190 fprintf(stderr, "writing error page: '%s'\n", error_page);
1191 return send_file_and_exit(error_page, SEND_BODY); 1189 return send_file_and_exit(error_page, SEND_BODY);
1192 } 1190 }
1193#endif 1191#endif
@@ -1542,8 +1540,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1542 } 1540 }
1543 if (full_write(STDOUT_FILENO, rbuf, count) != count) 1541 if (full_write(STDOUT_FILENO, rbuf, count) != count)
1544 break; 1542 break;
1545 if (DEBUG) 1543 dbg("cgi read %d bytes: '%.*s'\n", count, count, rbuf);
1546 fprintf(stderr, "cgi read %d bytes: '%.*s'\n", count, count, rbuf);
1547 } /* if (pfd[FROM_CGI].revents) */ 1544 } /* if (pfd[FROM_CGI].revents) */
1548 } /* while (1) */ 1545 } /* while (1) */
1549 log_and_exit(); 1546 log_and_exit();
@@ -1789,8 +1786,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1789 /* file_size and last_mod are already populated */ 1786 /* file_size and last_mod are already populated */
1790 } 1787 }
1791 if (fd < 0) { 1788 if (fd < 0) {
1792 if (DEBUG) 1789 dbg("can't open '%s'\n", url);
1793 bb_perror_msg("can't open '%s'", url);
1794 /* Error pages are sent by using send_file_and_exit(SEND_BODY). 1790 /* Error pages are sent by using send_file_and_exit(SEND_BODY).
1795 * IOW: it is unsafe to call send_headers_and_exit 1791 * IOW: it is unsafe to call send_headers_and_exit
1796 * if what is SEND_BODY! Can recurse! */ 1792 * if what is SEND_BODY! Can recurse! */
@@ -1803,8 +1799,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1803 sprintf(G.etag, "\"%"LL_FMT"x-%"LL_FMT"x\"", (unsigned long long)last_mod, (unsigned long long)file_size); 1799 sprintf(G.etag, "\"%"LL_FMT"x-%"LL_FMT"x\"", (unsigned long long)last_mod, (unsigned long long)file_size);
1804 1800
1805 if (G.if_none_match) { 1801 if (G.if_none_match) {
1806 if (DEBUG) 1802 dbg("If-None-Match:'%s' file's ETag:'%s'\n", G.if_none_match, G.etag);
1807 bb_perror_msg("If-None-Match and file's ETag are: '%s' '%s'\n", G.if_none_match, G.etag);
1808 /* Weak ETag comparision. 1803 /* Weak ETag comparision.
1809 * If-None-Match may have many ETags but they are quoted so we can use simple substring search */ 1804 * If-None-Match may have many ETags but they are quoted so we can use simple substring search */
1810 if (strstr(G.if_none_match, G.etag)) 1805 if (strstr(G.if_none_match, G.etag))
@@ -1880,9 +1875,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1880 } 1875 }
1881 } 1876 }
1882 1877
1883 if (DEBUG) 1878 dbg("sending file '%s' content-type:%s\n", url, found_mime_type);
1884 bb_error_msg("sending file '%s' content-type: %s",
1885 url, found_mime_type);
1886 1879
1887#if ENABLE_FEATURE_HTTPD_RANGES 1880#if ENABLE_FEATURE_HTTPD_RANGES
1888 if (what == SEND_BODY /* err pages and ranges don't mix */ 1881 if (what == SEND_BODY /* err pages and ranges don't mix */
@@ -1952,9 +1945,7 @@ static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip)
1952 Htaccess_IP *cur; 1945 Htaccess_IP *cur;
1953 1946
1954 for (cur = G.ip_a_d; cur; cur = cur->next) { 1947 for (cur = G.ip_a_d; cur; cur = cur->next) {
1955#if DEBUG 1948 dbg("checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n",
1956 fprintf(stderr,
1957 "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n",
1958 rmt_ip_str, 1949 rmt_ip_str,
1959 (unsigned char)(cur->ip >> 24), 1950 (unsigned char)(cur->ip >> 24),
1960 (unsigned char)(cur->ip >> 16), 1951 (unsigned char)(cur->ip >> 16),
@@ -1965,7 +1956,6 @@ static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip)
1965 (unsigned char)(cur->mask >> 8), 1956 (unsigned char)(cur->mask >> 8),
1966 (unsigned char)(cur->mask) 1957 (unsigned char)(cur->mask)
1967 ); 1958 );
1968#endif
1969 if ((remote_ip & cur->mask) == cur->ip) { 1959 if ((remote_ip & cur->mask) == cur->ip) {
1970 if (cur->allow_deny == 'A') 1960 if (cur->allow_deny == 'A')
1971 return; 1961 return;
@@ -2061,8 +2051,7 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
2061#endif 2051#endif
2062 continue; 2052 continue;
2063 2053
2064 if (DEBUG) 2054 dbg("checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd);
2065 fprintf(stderr, "checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd);
2066 2055
2067 /* If it's not a prefix match, continue searching */ 2056 /* If it's not a prefix match, continue searching */
2068 len = strlen(dir_prefix); 2057 len = strlen(dir_prefix);
@@ -2227,7 +2216,6 @@ static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM)
2227static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN; 2216static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN;
2228static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) 2217static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2229{ 2218{
2230 static const char request_GET[] ALIGN1 = "GET";
2231 struct stat sb; 2219 struct stat sb;
2232 char *urlcopy; 2220 char *urlcopy;
2233 char *urlp; 2221 char *urlp;
@@ -2238,14 +2226,21 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2238#if ENABLE_FEATURE_HTTPD_CGI 2226#if ENABLE_FEATURE_HTTPD_CGI
2239 unsigned total_headers_len; 2227 unsigned total_headers_len;
2240#endif 2228#endif
2241#if ENABLE_FEATURE_HTTPD_CGI
2242 static const char request_HEAD[] ALIGN1 = "HEAD";
2243 const char *prequest; 2229 const char *prequest;
2244 unsigned long length = 0; 2230 static const char request_GET[] ALIGN1 = "GET";
2245 enum CGI_type cgi_type = CGI_NONE; 2231 static const char request_HEAD[] ALIGN1 = "HEAD";
2246#elif ENABLE_FEATURE_HTTPD_PROXY 2232#if ENABLE_FEATURE_HTTPD_CGI
2247#define prequest request_GET 2233 static const char request_POST[] ALIGN1 = "POST";
2248 unsigned long length = 0; 2234 unsigned long POST_length;
2235 enum CGI_type {
2236 CGI_NONE = 0,
2237 CGI_NORMAL,
2238 CGI_INDEX,
2239 CGI_INTERPRETER,
2240 } cgi_type = CGI_NONE;
2241#endif
2242#if ENABLE_FEATURE_HTTPD_PROXY
2243 Htaccess_Proxy *proxy_entry;
2249#endif 2244#endif
2250#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2245#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
2251 smallint authorized = -1; 2246 smallint authorized = -1;
@@ -2297,35 +2292,33 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2297 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit); 2292 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit);
2298#endif 2293#endif
2299 2294
2300 if (!get_line()) /* EOF or error or empty line */ 2295 if (!get_line()) { /* EOF or error or empty line */
2301 send_headers_and_exit(HTTP_BAD_REQUEST); 2296 /* Observed Firefox to "speculatively" open
2297 * extra connections to a new site on first access,
2298 * they are closed in ~5 seconds with nothing
2299 * being sent at all.
2300 * (Presumably it's a method to decrease latency?)
2301 */
2302 if (verbose > 2)
2303 bb_simple_error_msg("eof on read, closing");
2304 /* Don't bother generating error page in this case,
2305 * just close the socket.
2306 */
2307 //send_headers_and_exit(HTTP_BAD_REQUEST);
2308 _exit(xfunc_error_retval);
2309 }
2310 dbg("Request:'%s'\n", iobuf);
2302 2311
2303 /* Determine type of request (GET/POST) */ 2312 /* Find URL */
2304 // rfc2616: method and URI is separated by exactly one space 2313 // rfc2616: method and URI is separated by exactly one space
2305 //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed 2314 //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed
2306 urlp = strchr(iobuf, ' '); 2315 urlp = strchr(iobuf, ' ');
2307 if (urlp == NULL) 2316 if (urlp == NULL)
2308 send_headers_and_exit(HTTP_BAD_REQUEST); 2317 send_headers_and_exit(HTTP_BAD_REQUEST);
2309 *urlp++ = '\0'; 2318 *urlp++ = '\0';
2310#if ENABLE_FEATURE_HTTPD_CGI
2311 prequest = request_GET;
2312 if (strcasecmp(iobuf, prequest) != 0) {
2313 prequest = request_HEAD;
2314 if (strcasecmp(iobuf, prequest) != 0) {
2315 prequest = "POST";
2316 if (strcasecmp(iobuf, prequest) != 0)
2317 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
2318 }
2319 }
2320#else
2321 if (strcasecmp(iobuf, request_GET) != 0)
2322 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
2323#endif
2324 // rfc2616: method and URI is separated by exactly one space
2325 //urlp = skip_whitespace(urlp); - should not be necessary 2319 //urlp = skip_whitespace(urlp); - should not be necessary
2326 if (urlp[0] != '/') 2320 if (urlp[0] != '/')
2327 send_headers_and_exit(HTTP_BAD_REQUEST); 2321 send_headers_and_exit(HTTP_BAD_REQUEST);
2328
2329 /* Find end of URL */ 2322 /* Find end of URL */
2330 HTTP_slash = strchr(urlp, ' '); 2323 HTTP_slash = strchr(urlp, ' ');
2331 /* Is it " HTTP/"? */ 2324 /* Is it " HTTP/"? */
@@ -2333,48 +2326,62 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2333 send_headers_and_exit(HTTP_BAD_REQUEST); 2326 send_headers_and_exit(HTTP_BAD_REQUEST);
2334 *HTTP_slash++ = '\0'; 2327 *HTTP_slash++ = '\0';
2335 2328
2336 /* Copy URL from after "GET "/"POST " to stack-allocated char[] */
2337 urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page));
2338 /*if (urlcopy == NULL)
2339 * send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);*/
2340 strcpy(urlcopy, urlp);
2341 /* NB: urlcopy ptr is never changed after this */
2342
2343#if ENABLE_FEATURE_HTTPD_PROXY 2329#if ENABLE_FEATURE_HTTPD_PROXY
2344 { 2330 proxy_entry = find_proxy_entry(urlp);
2331 if (proxy_entry) {
2345 int proxy_fd; 2332 int proxy_fd;
2346 len_and_sockaddr *lsa; 2333 len_and_sockaddr *lsa;
2347 Htaccess_Proxy *proxy_entry = find_proxy_entry(urlcopy); 2334
2348 2335 if (verbose > 1)
2349 if (proxy_entry) { 2336 bb_error_msg("proxy:%s", urlp);
2350 if (verbose > 1) 2337 lsa = host2sockaddr(proxy_entry->host_port, 80);
2351 bb_error_msg("proxy:%s", urlcopy); 2338 if (!lsa)
2352 lsa = host2sockaddr(proxy_entry->host_port, 80); 2339 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2353 if (!lsa) 2340 proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
2354 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2341 if (proxy_fd < 0)
2355 proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); 2342 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2356 if (proxy_fd < 0) 2343 if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0)
2357 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2344 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2358 if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) 2345 /* Disable peer header reading timeout */
2359 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2346 alarm(0);
2360 /* Disable peer header reading timeout */ 2347 /* Config directive was of the form:
2361 alarm(0); 2348 * P:/url:[http://]hostname[:port]/new/path
2362 /* Config directive was of the form: 2349 * When /urlSFX is requested, reverse proxy it
2363 * P:/url:[http://]hostname[:port]/new/path 2350 * to http://hostname[:port]/new/pathSFX
2364 * When /urlSFX is requested, reverse proxy it 2351 */
2365 * to http://hostname[:port]/new/pathSFX 2352 fdprintf(proxy_fd, "%s %s%s %s\r\n",
2366 */ 2353 iobuf, /* "GET" / "POST" / etc */
2367 fdprintf(proxy_fd, "%s %s%s %s\r\n", 2354 proxy_entry->url_to, /* "/new/path" */
2368 prequest, /* "GET" or "POST" */ 2355 urlp + strlen(proxy_entry->url_from), /* "SFX" */
2369 proxy_entry->url_to, /* "/new/path" */ 2356 HTTP_slash /* "HTTP/xyz" */
2370 urlcopy + strlen(proxy_entry->url_from), /* "SFX" */ 2357 );
2371 HTTP_slash /* "HTTP/xyz" */ 2358 cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX);
2372 );
2373 cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX);
2374 }
2375 } 2359 }
2376#endif 2360#endif
2377 2361
2362 /* Determine type of request (GET/POST/...) */
2363 prequest = request_GET;
2364 if (strcasecmp(iobuf, prequest) == 0)
2365 goto found;
2366 prequest = request_HEAD;
2367 if (strcasecmp(iobuf, prequest) == 0)
2368 goto found;
2369#if !ENABLE_FEATURE_HTTPD_CGI
2370 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
2371#else
2372 prequest = request_POST;
2373 if (strcasecmp(iobuf, prequest) == 0)
2374 goto found;
2375 /* For CGI, allow DELETE, PUT, OPTIONS, etc too */
2376 prequest = alloca(16);
2377 safe_strncpy((char*)prequest, iobuf, 16);
2378#endif
2379 found:
2380 /* Copy URL to stack-allocated char[] */
2381 urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page));
2382 strcpy(urlcopy, urlp);
2383 /* NB: urlcopy ptr is never changed after this */
2384
2378 /* Extract url args if present */ 2385 /* Extract url args if present */
2379 g_query = strchr(urlcopy, '?'); 2386 g_query = strchr(urlcopy, '?');
2380 if (g_query) 2387 if (g_query)
@@ -2393,7 +2400,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2393 /* Algorithm stolen from libbb bb_simplify_path(), 2400 /* Algorithm stolen from libbb bb_simplify_path(),
2394 * but don't strdup, retain trailing slash, protect root */ 2401 * but don't strdup, retain trailing slash, protect root */
2395 urlp = tptr = urlcopy; 2402 urlp = tptr = urlcopy;
2396 for (;;) { 2403 while (1) {
2397 if (*urlp == '/') { 2404 if (*urlp == '/') {
2398 /* skip duplicate (or initial) slash */ 2405 /* skip duplicate (or initial) slash */
2399 if (*tptr == '/') { 2406 if (*tptr == '/') {
@@ -2424,13 +2431,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2424 tptr++; 2431 tptr++;
2425 } 2432 }
2426 2433
2427 /* If URL is a directory, add '/' */
2428 if (urlp[-1] != '/') {
2429 if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) {
2430 found_moved_temporarily = urlcopy;
2431 }
2432 }
2433
2434 /* Log it */ 2434 /* Log it */
2435 if (verbose > 1) 2435 if (verbose > 1)
2436 bb_error_msg("url:%s", urlcopy); 2436 bb_error_msg("url:%s", urlcopy);
@@ -2439,11 +2439,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2439 while ((tptr = strchr(tptr + 1, '/')) != NULL) { 2439 while ((tptr = strchr(tptr + 1, '/')) != NULL) {
2440 /* have path1/path2 */ 2440 /* have path1/path2 */
2441 *tptr = '\0'; 2441 *tptr = '\0';
2442 if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) { 2442 /* may have subdir config */
2443 /* may have subdir config */ 2443 if (parse_conf(urlcopy + 1, SUBDIR_PARSE) == 0)
2444 parse_conf(urlcopy + 1, SUBDIR_PARSE);
2445 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); 2444 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip);
2446 }
2447 *tptr = '/'; 2445 *tptr = '/';
2448 } 2446 }
2449 2447
@@ -2470,36 +2468,45 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2470 strcpy(urlp, index_page); 2468 strcpy(urlp, index_page);
2471 } 2469 }
2472 if (stat(tptr, &sb) == 0) { 2470 if (stat(tptr, &sb) == 0) {
2471 /* If URL is a directory with no slash, set up
2472 * "HTTP/1.1 302 Found" "Location: /dir/" reply */
2473 if (urlp[-1] != '/' && S_ISDIR(sb.st_mode)) {
2474 found_moved_temporarily = urlcopy;
2475 } else {
2473#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 2476#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
2474 char *suffix = strrchr(tptr, '.'); 2477 char *suffix = strrchr(tptr, '.');
2475 if (suffix) { 2478 if (suffix) {
2476 Htaccess *cur; 2479 Htaccess *cur;
2477 for (cur = script_i; cur; cur = cur->next) { 2480 for (cur = script_i; cur; cur = cur->next) {
2478 if (strcmp(cur->before_colon + 1, suffix) == 0) { 2481 if (strcmp(cur->before_colon + 1, suffix) == 0) {
2479 cgi_type = CGI_INTERPRETER; 2482 cgi_type = CGI_INTERPRETER;
2480 break; 2483 break;
2484 }
2481 } 2485 }
2482 } 2486 }
2483 }
2484#endif 2487#endif
2485 if (!found_moved_temporarily) {
2486 file_size = sb.st_size; 2488 file_size = sb.st_size;
2487 last_mod = sb.st_mtime; 2489 last_mod = sb.st_mtime;
2488 } 2490 }
2489 } 2491 }
2490#if ENABLE_FEATURE_HTTPD_CGI 2492#if ENABLE_FEATURE_HTTPD_CGI
2491 else if (urlp[-1] == '/') { 2493 else if (urlp[-1] == '/') {
2492 /* It's a dir URL and there is no index.html 2494 /* It's a dir URL and there is no index.html */
2493 * Try cgi-bin/index.cgi */ 2495 /* Is there cgi-bin/index.cgi? */
2494 if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { 2496 if (access("/cgi-bin/index.cgi"+1, X_OK) != 0)
2495 cgi_type = CGI_INDEX; 2497 send_headers_and_exit(HTTP_NOT_FOUND); /* no */
2496 } 2498 cgi_type = CGI_INDEX;
2497 } 2499 }
2498#endif 2500#endif
2501
2502#if ENABLE_FEATURE_HTTPD_BASIC_AUTH || ENABLE_FEATURE_HTTPD_CGI
2503 /* check_user_passwd() would be confused by added .../index.html, truncate it */
2499 urlp[0] = '\0'; 2504 urlp[0] = '\0';
2505#endif
2500 2506
2501#if ENABLE_FEATURE_HTTPD_CGI 2507#if ENABLE_FEATURE_HTTPD_CGI
2502 total_headers_len = 0; 2508 total_headers_len = 0;
2509 POST_length = 0;
2503#endif 2510#endif
2504 2511
2505 /* Read until blank line */ 2512 /* Read until blank line */
@@ -2513,26 +2520,18 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2513 if (total_headers_len >= MAX_HTTP_HEADERS_SIZE) 2520 if (total_headers_len >= MAX_HTTP_HEADERS_SIZE)
2514 send_headers_and_exit(HTTP_ENTITY_TOO_LARGE); 2521 send_headers_and_exit(HTTP_ENTITY_TOO_LARGE);
2515#endif 2522#endif
2516 if (DEBUG) 2523 dbg("header:'%s'\n", iobuf);
2517 bb_error_msg("header: '%s'", iobuf); 2524#if ENABLE_FEATURE_HTTPD_CGI
2518#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY 2525 /* Only POST needs to know POST_length */
2519 /* Try and do our best to parse more lines */ 2526 if (prequest == request_POST && STRNCASECMP(iobuf, "Content-Length:") == 0) {
2520 if (STRNCASECMP(iobuf, "Content-Length:") == 0) { 2527 tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1);
2521 /* extra read only for POST */ 2528 if (!tptr[0])
2522 if (prequest != request_GET 2529 send_headers_and_exit(HTTP_BAD_REQUEST);
2523# if ENABLE_FEATURE_HTTPD_CGI 2530 /* not using strtoul: it ignores leading minus! */
2524 && prequest != request_HEAD 2531 POST_length = bb_strtou(tptr, NULL, 10);
2525# endif 2532 /* length is "ulong", but we need to pass it to int later */
2526 ) { 2533 if (errno || POST_length > INT_MAX)
2527 tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1); 2534 send_headers_and_exit(HTTP_BAD_REQUEST);
2528 if (!tptr[0])
2529 send_headers_and_exit(HTTP_BAD_REQUEST);
2530 /* not using strtoul: it ignores leading minus! */
2531 length = bb_strtou(tptr, NULL, 10);
2532 /* length is "ulong", but we need to pass it to int later */
2533 if (errno || length > INT_MAX)
2534 send_headers_and_exit(HTTP_BAD_REQUEST);
2535 }
2536 continue; 2535 continue;
2537 } 2536 }
2538#endif 2537#endif
@@ -2646,37 +2645,36 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2646 send_headers_and_exit(HTTP_UNAUTHORIZED); 2645 send_headers_and_exit(HTTP_UNAUTHORIZED);
2647#endif 2646#endif
2648 2647
2649 if (found_moved_temporarily) { 2648 if (found_moved_temporarily)
2650 send_headers_and_exit(HTTP_MOVED_TEMPORARILY); 2649 send_headers_and_exit(HTTP_MOVED_TEMPORARILY);
2651 }
2652
2653 tptr = urlcopy + 1; /* skip first '/' */
2654 2650
2655#if ENABLE_FEATURE_HTTPD_CGI 2651#if ENABLE_FEATURE_HTTPD_CGI
2656 if (cgi_type != CGI_NONE) { 2652 if (cgi_type != CGI_NONE) {
2657 send_cgi_and_exit( 2653 send_cgi_and_exit(
2658 (cgi_type == CGI_INDEX) ? "/cgi-bin/index.cgi" 2654 (cgi_type == CGI_INDEX) ? "/cgi-bin/index.cgi"
2659 /*CGI_NORMAL or CGI_INTERPRETER*/ : urlcopy, 2655 /*CGI_NORMAL or CGI_INTERPRETER*/ : urlcopy,
2660 urlcopy, prequest, length 2656 urlcopy, prequest, POST_length
2661 ); 2657 );
2662 } 2658 }
2663#endif 2659#endif
2664 2660
2665 if (urlp[-1] == '/') {
2666 strcpy(urlp, index_page);
2667 }
2668
2669#if ENABLE_FEATURE_HTTPD_CGI 2661#if ENABLE_FEATURE_HTTPD_CGI
2670 if (prequest != request_GET && prequest != request_HEAD) { 2662 if (prequest != request_GET && prequest != request_HEAD) {
2671 /* POST for files does not make sense */ 2663 /* POST / DELETE / PUT / OPTIONS for files do not make sense */
2672 send_headers_and_exit(HTTP_NOT_IMPLEMENTED); 2664 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
2673 } 2665 }
2674 send_file_and_exit(tptr,
2675 (prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS)
2676 );
2677#else 2666#else
2678 send_file_and_exit(tptr, SEND_HEADERS_AND_BODY); 2667 /* !CGI: it can be only GET or HEAD */
2679#endif 2668#endif
2669
2670#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
2671 /* Restore truncated .../index.html */
2672 if (urlp[-1] == '/')
2673 urlp[0] = index_page[0];
2674#endif
2675 send_file_and_exit(urlcopy + 1,
2676 (prequest != request_HEAD ? (SEND_HEADERS + SEND_BODY) : SEND_HEADERS)
2677 );
2680} 2678}
2681 2679
2682 2680
@@ -2705,6 +2703,13 @@ static void mini_httpd(int server_socket)
2705 n = accept(server_socket, &fromAddr.u.sa, &fromAddr.len); 2703 n = accept(server_socket, &fromAddr.u.sa, &fromAddr.len);
2706 if (n < 0) 2704 if (n < 0)
2707 continue; 2705 continue;
2706//TODO: we can reject connects from denied IPs right away;
2707//also, we might want to do one MSG_DONTWAIT'ed recv() here
2708//to detect immediate EOF,
2709//to avoid forking a whole new process for attackers
2710//who open and close lots of connections.
2711//(OTOH, the real mitigtion for this sort of thing is
2712//to ratelimit connects in iptables)
2708 2713
2709 /* set the KEEPALIVE option to cull dead connections */ 2714 /* set the KEEPALIVE option to cull dead connections */
2710 setsockopt_keepalive(n); 2715 setsockopt_keepalive(n);
diff --git a/networking/inetd.c b/networking/inetd.c
index febfb7b73..e5352a555 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1697,7 +1697,7 @@ static void FAST_FUNC chargen_dg(int s, servtab_t *sep)
1697 * we must add 2208988800 seconds to this figure to make up for 1697 * we must add 2208988800 seconds to this figure to make up for
1698 * some seventy years Bell Labs was asleep. 1698 * some seventy years Bell Labs was asleep.
1699 */ 1699 */
1700static uint32_t machtime(void) 1700static NOINLINE uint32_t machtime(void)
1701{ 1701{
1702 struct timeval tv; 1702 struct timeval tv;
1703 1703
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 9c15999f3..6bf6c4e07 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -127,24 +127,15 @@
127 */ 127 */
128#define MAX_VERBOSE 3 128#define MAX_VERBOSE 3
129 129
130
131/* High-level description of the algorithm: 130/* High-level description of the algorithm:
132 * 131 *
133 * We start running with very small poll_exp, BURSTPOLL, 132 * We start running with very small poll_exp, BURSTPOLL,
134 * in order to quickly accumulate INITIAL_SAMPLES datapoints 133 * in order to quickly accumulate INITIAL_SAMPLES datapoints
135 * for each peer. Then, time is stepped if the offset is larger 134 * for each peer. Then, time is stepped if the offset is larger
136 * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge 135 * than STEP_THRESHOLD, otherwise it isn't stepped.
137 * poll_exp to MINPOLL and enter frequency measurement step:
138 * we collect new datapoints but ignore them for WATCH_THRESHOLD
139 * seconds. After WATCH_THRESHOLD seconds we look at accumulated
140 * offset and estimate frequency drift.
141 *
142 * (frequency measurement step seems to not be strictly needed,
143 * it is conditionally disabled with USING_INITIAL_FREQ_ESTIMATION
144 * define set to 0)
145 * 136 *
146 * After this, we enter "steady state": we collect a datapoint, 137 * Then poll_exp is set to MINPOLL, and we enter "steady state": we collect
147 * we select the best peer, if this datapoint is not a new one 138 * a datapoint, we select the best peer, if this datapoint is not a new one
148 * (IOW: if this datapoint isn't for selected peer), sleep 139 * (IOW: if this datapoint isn't for selected peer), sleep
149 * and collect another one; otherwise, use its offset to update 140 * and collect another one; otherwise, use its offset to update
150 * frequency drift, if offset is somewhat large, reduce poll_exp, 141 * frequency drift, if offset is somewhat large, reduce poll_exp,
@@ -169,7 +160,7 @@
169 * datapoints after the step. 160 * datapoints after the step.
170 */ 161 */
171 162
172#define INITIAL_SAMPLES 4 /* how many samples do we want for init */ 163#define INITIAL_SAMPLES 3 /* how many samples do we want for init */
173#define MIN_FREQHOLD 10 /* adjust offset, but not freq in this many first adjustments */ 164#define MIN_FREQHOLD 10 /* adjust offset, but not freq in this many first adjustments */
174#define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this factor */ 165#define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this factor */
175 166
@@ -189,13 +180,10 @@
189// ^^^^ used to be 0.125. 180// ^^^^ used to be 0.125.
190// Since Linux 2.6.26 (circa 2006), kernel accepts (-0.5s, +0.5s) range 181// Since Linux 2.6.26 (circa 2006), kernel accepts (-0.5s, +0.5s) range
191 182
192/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
193//UNUSED: #define WATCH_THRESHOLD 128
194/* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */
195//UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */
196 183
197/* 184// #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */
198 * If we got |offset| > BIGOFF from a peer, cap next query interval 185
186/* If we got |offset| > BIGOFF from a peer, cap next query interval
199 * for this peer by this many seconds: 187 * for this peer by this many seconds:
200 */ 188 */
201#define BIGOFF STEP_THRESHOLD 189#define BIGOFF STEP_THRESHOLD
@@ -204,18 +192,16 @@
204#define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ 192#define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */
205#define BURSTPOLL 0 /* initial poll */ 193#define BURSTPOLL 0 /* initial poll */
206#define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ 194#define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
207/* 195/* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
208 * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
209 * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_). 196 * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_).
210 */ 197 */
211#define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */ 198#define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */
212#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ 199#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
213/* 200/* Actively lower poll when we see such big offsets.
214 * Actively lower poll when we see such big offsets.
215 * With SLEW_THRESHOLD = 0.125, it means we try to sync more aggressively 201 * With SLEW_THRESHOLD = 0.125, it means we try to sync more aggressively
216 * if offset increases over ~0.04 sec 202 * if offset increases over ~0.04 sec
217 */ 203 */
218//#define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3) 204// #define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3)
219#define MINDISP 0.01 /* minimum dispersion (sec) */ 205#define MINDISP 0.01 /* minimum dispersion (sec) */
220#define MAXDISP 16 /* maximum dispersion (sec) */ 206#define MAXDISP 16 /* maximum dispersion (sec) */
221#define MAXSTRAT 16 /* maximum stratum (infinity metric) */ 207#define MAXSTRAT 16 /* maximum stratum (infinity metric) */
@@ -223,7 +209,16 @@
223#define MIN_SELECTED 1 /* minimum intersection survivors */ 209#define MIN_SELECTED 1 /* minimum intersection survivors */
224#define MIN_CLUSTERED 3 /* minimum cluster survivors */ 210#define MIN_CLUSTERED 3 /* minimum cluster survivors */
225 211
226#define MAXDRIFT 0.000500 /* frequency drift we can correct (500 PPM) */ 212/* Correct frequency ourself (0) or let kernel do it (1)? */
213#define USING_KERNEL_PLL_LOOP 1
214// /* frequency drift we can correct (500 PPM) */
215// #define MAXDRIFT 0.000500
216// /* Compromise Allan intercept (sec). doc uses 1500, std ntpd uses 512 */
217// #define ALLAN 512
218// /* PLL loop gain */
219// #define PLL 65536
220// /* FLL loop gain [why it depends on MAXPOLL??] */
221// #define FLL (MAXPOLL + 1)
227 222
228/* Poll-adjust threshold. 223/* Poll-adjust threshold.
229 * When we see that offset is small enough compared to discipline jitter, 224 * When we see that offset is small enough compared to discipline jitter,
@@ -239,12 +234,6 @@
239 */ 234 */
240#define POLLADJ_GATE 4 235#define POLLADJ_GATE 4
241#define TIMECONST_HACK_GATE 2 236#define TIMECONST_HACK_GATE 2
242/* Compromise Allan intercept (sec). doc uses 1500, std ntpd uses 512 */
243#define ALLAN 512
244/* PLL loop gain */
245#define PLL 65536
246/* FLL loop gain [why it depends on MAXPOLL??] */
247#define FLL (MAXPOLL + 1)
248/* Parameter averaging constant */ 237/* Parameter averaging constant */
249#define AVG 4 238#define AVG 4
250 239
@@ -372,9 +361,6 @@ typedef struct {
372 char p_hostname[1]; 361 char p_hostname[1];
373} peer_t; 362} peer_t;
374 363
375
376#define USING_KERNEL_PLL_LOOP 1
377
378enum { 364enum {
379 OPT_n = (1 << 0), 365 OPT_n = (1 << 0),
380 OPT_q = (1 << 1), 366 OPT_q = (1 << 1),
@@ -453,7 +439,7 @@ struct globals {
453 */ 439 */
454#define G_precision_exp -9 440#define G_precision_exp -9
455 /* 441 /*
456 * G_precision_exp is used only for construction outgoing packets. 442 * G_precision_exp is used only for constructing outgoing packets.
457 * It's ok to set G_precision_sec to a slightly different value 443 * It's ok to set G_precision_sec to a slightly different value
458 * (One which is "nicer looking" in logs). 444 * (One which is "nicer looking" in logs).
459 * Exact value would be (1.0 / (1 << (- G_precision_exp))): 445 * Exact value would be (1.0 / (1 << (- G_precision_exp))):
@@ -484,7 +470,6 @@ struct globals {
484}; 470};
485#define G (*ptr_to_globals) 471#define G (*ptr_to_globals)
486 472
487
488#define VERB1 if (MAX_VERBOSE && G.verbose) 473#define VERB1 if (MAX_VERBOSE && G.verbose)
489#define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2) 474#define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2)
490#define VERB3 if (MAX_VERBOSE >= 3 && G.verbose >= 3) 475#define VERB3 if (MAX_VERBOSE >= 3 && G.verbose >= 3)
@@ -567,13 +552,13 @@ gettime1900d(void)
567} 552}
568 553
569static void 554static void
570d_to_tv(double d, struct timeval *tv) 555d_to_tv(struct timeval *tv, double d)
571{ 556{
572 tv->tv_sec = (long)d; 557 tv->tv_sec = (long)d;
573 tv->tv_usec = (d - tv->tv_sec) * 1000000; 558 tv->tv_usec = (d - tv->tv_sec) * 1000000;
574} 559}
575 560
576static double 561static NOINLINE double
577lfp_to_d(l_fixedpt_t lfp) 562lfp_to_d(l_fixedpt_t lfp)
578{ 563{
579 double ret; 564 double ret;
@@ -582,7 +567,7 @@ lfp_to_d(l_fixedpt_t lfp)
582 ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX); 567 ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX);
583 return ret; 568 return ret;
584} 569}
585static double 570static NOINLINE double
586sfp_to_d(s_fixedpt_t sfp) 571sfp_to_d(s_fixedpt_t sfp)
587{ 572{
588 double ret; 573 double ret;
@@ -592,25 +577,25 @@ sfp_to_d(s_fixedpt_t sfp)
592 return ret; 577 return ret;
593} 578}
594#if ENABLE_FEATURE_NTPD_SERVER 579#if ENABLE_FEATURE_NTPD_SERVER
595static l_fixedpt_t 580static NOINLINE void
596d_to_lfp(double d) 581d_to_lfp(l_fixedpt_t *lfp, double d)
597{ 582{
598 l_fixedpt_t lfp; 583 uint32_t intl;
599 lfp.int_partl = (uint32_t)d; 584 uint32_t frac;
600 lfp.fractionl = (uint32_t)((d - lfp.int_partl) * UINT_MAX); 585 intl = (uint32_t)d;
601 lfp.int_partl = htonl(lfp.int_partl); 586 frac = (uint32_t)((d - intl) * UINT_MAX);
602 lfp.fractionl = htonl(lfp.fractionl); 587 lfp->int_partl = htonl(intl);
603 return lfp; 588 lfp->fractionl = htonl(frac);
604} 589}
605static s_fixedpt_t 590static NOINLINE void
606d_to_sfp(double d) 591d_to_sfp(s_fixedpt_t *sfp, double d)
607{ 592{
608 s_fixedpt_t sfp; 593 uint16_t ints;
609 sfp.int_parts = (uint16_t)d; 594 uint16_t frac;
610 sfp.fractions = (uint16_t)((d - sfp.int_parts) * USHRT_MAX); 595 ints = (uint16_t)d;
611 sfp.int_parts = htons(sfp.int_parts); 596 frac = (uint16_t)((d - ints) * USHRT_MAX);
612 sfp.fractions = htons(sfp.fractions); 597 sfp->int_parts = htons(ints);
613 return sfp; 598 sfp->fractions = htons(frac);
614} 599}
615#endif 600#endif
616 601
@@ -989,7 +974,6 @@ send_query_to_peer(peer_t *p)
989 set_next(p, RESPONSE_INTERVAL); 974 set_next(p, RESPONSE_INTERVAL);
990} 975}
991 976
992
993/* Note that there is no provision to prevent several run_scripts 977/* Note that there is no provision to prevent several run_scripts
994 * to be started in quick succession. In fact, it happens rather often 978 * to be started in quick succession. In fact, it happens rather often
995 * if initial syncronization results in a step. 979 * if initial syncronization results in a step.
@@ -1053,7 +1037,7 @@ step_time(double offset)
1053 1037
1054 xgettimeofday(&tvc); 1038 xgettimeofday(&tvc);
1055 dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset; 1039 dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset;
1056 d_to_tv(dtime, &tvn); 1040 d_to_tv(&tvn, dtime);
1057 xsettimeofday(&tvn); 1041 xsettimeofday(&tvn);
1058 1042
1059 VERB2 { 1043 VERB2 {
@@ -1767,7 +1751,6 @@ update_local_clock(peer_t *p)
1767 return 1; /* "ok to increase poll interval" */ 1751 return 1; /* "ok to increase poll interval" */
1768} 1752}
1769 1753
1770
1771/* 1754/*
1772 * We've got a new reply packet from a peer, process it 1755 * We've got a new reply packet from a peer, process it
1773 * (helpers first) 1756 * (helpers first)
@@ -2134,17 +2117,17 @@ recv_and_process_client_pkt(void /*int fd*/)
2134 msg.m_ppoll = G.poll_exp; 2117 msg.m_ppoll = G.poll_exp;
2135 msg.m_precision_exp = G_precision_exp; 2118 msg.m_precision_exp = G_precision_exp;
2136 /* this time was obtained between poll() and recv() */ 2119 /* this time was obtained between poll() and recv() */
2137 msg.m_rectime = d_to_lfp(G.cur_time); 2120 d_to_lfp(&msg.m_rectime, G.cur_time);
2138 msg.m_xmttime = d_to_lfp(gettime1900d()); /* this instant */ 2121 d_to_lfp(&msg.m_xmttime, gettime1900d()); /* this instant */
2139 if (G.peer_cnt == 0) { 2122 if (G.peer_cnt == 0) {
2140 /* we have no peers: "stratum 1 server" mode. reftime = our own time */ 2123 /* we have no peers: "stratum 1 server" mode. reftime = our own time */
2141 G.reftime = G.cur_time; 2124 G.reftime = G.cur_time;
2142 } 2125 }
2143 msg.m_reftime = d_to_lfp(G.reftime); 2126 d_to_lfp(&msg.m_reftime, G.reftime);
2144 msg.m_orgtime = query_xmttime; 2127 msg.m_orgtime = query_xmttime;
2145 msg.m_rootdelay = d_to_sfp(G.rootdelay); 2128 d_to_sfp(&msg.m_rootdelay, G.rootdelay);
2146//simple code does not do this, fix simple code! 2129//simple code does not do this, fix simple code!
2147 msg.m_rootdisp = d_to_sfp(G.rootdisp); 2130 d_to_sfp(&msg.m_rootdisp, G.rootdisp);
2148 //version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */ 2131 //version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
2149 msg.m_refid = G.refid; // (version > (3 << VERSION_SHIFT)) ? G.refid : G.refid3; 2132 msg.m_refid = G.refid; // (version > (3 << VERSION_SHIFT)) ? G.refid : G.refid3;
2150 2133
diff --git a/networking/tls.c b/networking/tls.c
index b05afe1c9..a1b12f9ed 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -18,6 +18,7 @@
18//kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o 18//kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o
19//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o 19//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o
20//kbuild:lib-$(CONFIG_TLS) += tls_fe.o 20//kbuild:lib-$(CONFIG_TLS) += tls_fe.o
21//kbuild:lib-$(CONFIG_TLS) += tls_sp_c32.o
21 22
22#include "tls.h" 23#include "tls.h"
23 24
@@ -265,8 +266,9 @@ enum {
265 GOT_CERT_RSA_KEY_ALG = 1 << 1, 266 GOT_CERT_RSA_KEY_ALG = 1 << 1,
266 GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused 267 GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused
267 GOT_EC_KEY = 1 << 3, 268 GOT_EC_KEY = 1 << 3,
268 ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1) 269 GOT_EC_CURVE_X25519 = 1 << 4, // else P256
269 ENCRYPT_ON_WRITE = 1 << 5, 270 ENCRYPTION_AESGCM = 1 << 5, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1)
271 ENCRYPT_ON_WRITE = 1 << 6,
270}; 272};
271 273
272struct record_hdr { 274struct record_hdr {
@@ -285,7 +287,11 @@ struct tls_handshake_data {
285//TODO: store just the DER key here, parse/use/delete it when sending client key 287//TODO: store just the DER key here, parse/use/delete it when sending client key
286//this way it will stay key type agnostic here. 288//this way it will stay key type agnostic here.
287 psRsaKey_t server_rsa_pub_key; 289 psRsaKey_t server_rsa_pub_key;
288 uint8_t ecc_pub_key32[32]; 290
291 /* peer's elliptic curve key data */
292 /* for x25519, it contains one point in first 32 bytes */
293 /* for P256, it contains x,y point pair, each 32 bytes long */
294 uint8_t ecc_pub_key32[2 * 32];
289 295
290/* HANDSHAKE HASH: */ 296/* HANDSHAKE HASH: */
291 //unsigned saved_client_hello_size; 297 //unsigned saved_client_hello_size;
@@ -1526,20 +1532,13 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1526 }; 1532 };
1527 static const uint8_t supported_groups[] = { 1533 static const uint8_t supported_groups[] = {
1528 0x00,0x0a, //extension_type: "supported_groups" 1534 0x00,0x0a, //extension_type: "supported_groups"
1529 0x00,0x04, //ext len 1535 0x00,0x06, //ext len
1530 0x00,0x02, //list len 1536 0x00,0x04, //list len
1531 0x00,0x1d, //curve_x25519 (RFC 7748) 1537 0x00,0x17, //curve_secp256r1 (aka P256)
1532 //0x00,0x1e, //curve_x448 (RFC 7748)
1533 //0x00,0x17, //curve_secp256r1
1534 //0x00,0x18, //curve_secp384r1 1538 //0x00,0x18, //curve_secp384r1
1535 //0x00,0x19, //curve_secp521r1 1539 //0x00,0x19, //curve_secp521r1
1536//TODO: implement secp256r1 (at least): dl.fedoraproject.org immediately aborts 1540 0x00,0x1d, //curve_x25519 (RFC 7748)
1537//if only x25519/x448 are advertised, seems to support only secpNNNr1 curves: 1541 //0x00,0x1e, //curve_x448 (RFC 7748)
1538// openssl s_client -connect dl.fedoraproject.org:443 -debug -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256
1539//Peer signing digest: SHA512
1540//Peer signature type: RSA
1541//Server Temp Key: ECDH, P-256, 256 bits
1542//TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
1543 }; 1542 };
1544 //static const uint8_t signature_algorithms[] = { 1543 //static const uint8_t signature_algorithms[] = {
1545 // 000d 1544 // 000d
@@ -1877,12 +1876,32 @@ static void process_server_key(tls_state_t *tls, int len)
1877 if (len < (1+2+1+32)) tls_error_die(tls); 1876 if (len < (1+2+1+32)) tls_error_die(tls);
1878 keybuf += 4; 1877 keybuf += 4;
1879 1878
1880 /* So far we only support curve_x25519 */ 1879#if BB_BIG_ENDIAN
1880# define _0x03001741 0x03001741
1881# define _0x03001d20 0x03001d20
1882#else
1883# define _0x03001741 0x41170003
1884# define _0x03001d20 0x201d0003
1885#endif
1881 move_from_unaligned32(t32, keybuf); 1886 move_from_unaligned32(t32, keybuf);
1882 if (t32 != htonl(0x03001d20)) 1887 keybuf += 4;
1883 bb_simple_error_msg_and_die("elliptic curve is not x25519"); 1888 switch (t32) {
1889 case _0x03001d20: //curve_x25519
1890 tls->flags |= GOT_EC_CURVE_X25519;
1891 memcpy(tls->hsd->ecc_pub_key32, keybuf, 32);
1892 break;
1893 case _0x03001741: //curve_secp256r1 (aka P256)
1894 /* P256 point can be transmitted odd- or even-compressed
1895 * (first byte is 3 or 2) or uncompressed (4).
1896 */
1897 if (*keybuf++ != 4)
1898 bb_simple_error_msg_and_die("compressed EC points not supported");
1899 memcpy(tls->hsd->ecc_pub_key32, keybuf, 2 * 32);
1900 break;
1901 default:
1902 bb_error_msg_and_die("elliptic curve is not x25519 or P256: 0x%08x", t32);
1903 }
1884 1904
1885 memcpy(tls->hsd->ecc_pub_key32, keybuf + 4, 32);
1886 tls->flags |= GOT_EC_KEY; 1905 tls->flags |= GOT_EC_KEY;
1887 dbg("got eccPubKey\n"); 1906 dbg("got eccPubKey\n");
1888} 1907}
@@ -1918,9 +1937,7 @@ static void send_client_key_exchange(tls_state_t *tls)
1918 }; 1937 };
1919//FIXME: better size estimate 1938//FIXME: better size estimate
1920 struct client_key_exchange *record = tls_get_zeroed_outbuf(tls, sizeof(*record)); 1939 struct client_key_exchange *record = tls_get_zeroed_outbuf(tls, sizeof(*record));
1921 uint8_t rsa_premaster[RSA_PREMASTER_SIZE]; 1940 uint8_t premaster[RSA_PREMASTER_SIZE > EC_CURVE_KEYSIZE ? RSA_PREMASTER_SIZE : EC_CURVE_KEYSIZE];
1922 uint8_t x25519_premaster[CURVE25519_KEYSIZE];
1923 uint8_t *premaster;
1924 int premaster_size; 1941 int premaster_size;
1925 int len; 1942 int len;
1926 1943
@@ -1929,19 +1946,19 @@ static void send_client_key_exchange(tls_state_t *tls)
1929 if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) 1946 if (!(tls->flags & GOT_CERT_RSA_KEY_ALG))
1930 bb_simple_error_msg("server cert is not RSA"); 1947 bb_simple_error_msg("server cert is not RSA");
1931 1948
1932 tls_get_random(rsa_premaster, sizeof(rsa_premaster)); 1949 tls_get_random(premaster, RSA_PREMASTER_SIZE);
1933 if (TLS_DEBUG_FIXED_SECRETS) 1950 if (TLS_DEBUG_FIXED_SECRETS)
1934 memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); 1951 memset(premaster, 0x44, RSA_PREMASTER_SIZE);
1935 // RFC 5246 1952 // RFC 5246
1936 // "Note: The version number in the PreMasterSecret is the version 1953 // "Note: The version number in the PreMasterSecret is the version
1937 // offered by the client in the ClientHello.client_version, not the 1954 // offered by the client in the ClientHello.client_version, not the
1938 // version negotiated for the connection." 1955 // version negotiated for the connection."
1939 rsa_premaster[0] = TLS_MAJ; 1956 premaster[0] = TLS_MAJ;
1940 rsa_premaster[1] = TLS_MIN; 1957 premaster[1] = TLS_MIN;
1941 dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster)); 1958 dump_hex("premaster:%s\n", premaster, sizeof(premaster));
1942 len = psRsaEncryptPub(/*pool:*/ NULL, 1959 len = psRsaEncryptPub(/*pool:*/ NULL,
1943 /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, 1960 /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key,
1944 rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), 1961 premaster, /*inlen:*/ RSA_PREMASTER_SIZE,
1945 record->key + 2, sizeof(record->key) - 2, 1962 record->key + 2, sizeof(record->key) - 2,
1946 data_param_ignored 1963 data_param_ignored
1947 ); 1964 );
@@ -1949,33 +1966,36 @@ static void send_client_key_exchange(tls_state_t *tls)
1949 record->key[0] = len >> 8; 1966 record->key[0] = len >> 8;
1950 record->key[1] = len & 0xff; 1967 record->key[1] = len & 0xff;
1951 len += 2; 1968 len += 2;
1952 premaster = rsa_premaster; 1969 premaster_size = RSA_PREMASTER_SIZE;
1953 premaster_size = sizeof(rsa_premaster);
1954 } else { 1970 } else {
1955 /* ECDHE */ 1971 /* ECDHE */
1956 static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN1 = {9};
1957 uint8_t privkey[CURVE25519_KEYSIZE]; //[32]
1958
1959 if (!(tls->flags & GOT_EC_KEY)) 1972 if (!(tls->flags & GOT_EC_KEY))
1960 bb_simple_error_msg("server did not provide EC key"); 1973 bb_simple_error_msg_and_die("server did not provide EC key");
1961 1974
1962 /* Generate random private key, see RFC 7748 */ 1975 if (tls->flags & GOT_EC_CURVE_X25519) {
1963 tls_get_random(privkey, sizeof(privkey)); 1976 /* ECDHE, curve x25519 */
1964 privkey[0] &= 0xf8; 1977 dbg("computing x25519_premaster\n");
1965 privkey[CURVE25519_KEYSIZE-1] = ((privkey[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40); 1978 curve_x25519_compute_pubkey_and_premaster(
1966 1979 record->key + 1, premaster,
1967 /* Compute public key */ 1980 /*point:*/ tls->hsd->ecc_pub_key32
1968 curve25519(record->key + 1, privkey, basepoint9); 1981 );
1969 1982 len = CURVE25519_KEYSIZE;
1970 /* Compute premaster using peer's public key */ 1983 //record->key[0] = len;
1971 dbg("computing x25519_premaster\n"); 1984 //len++;
1972 curve25519(x25519_premaster, privkey, tls->hsd->ecc_pub_key32); 1985 //premaster_size = CURVE25519_KEYSIZE;
1973 1986 } else {
1974 len = CURVE25519_KEYSIZE; 1987 /* ECDHE, curve P256 */
1988 dbg("computing P256_premaster\n");
1989 curve_P256_compute_pubkey_and_premaster(
1990 record->key + 2, premaster,
1991 /*point:*/ tls->hsd->ecc_pub_key32
1992 );
1993 record->key[1] = 4; /* "uncompressed point" */
1994 len = 1 + P256_KEYSIZE * 2;
1995 }
1975 record->key[0] = len; 1996 record->key[0] = len;
1976 len++; 1997 len++;
1977 premaster = x25519_premaster; 1998 premaster_size = P256_KEYSIZE; // = CURVE25519_KEYSIZE = 32
1978 premaster_size = sizeof(x25519_premaster);
1979 } 1999 }
1980 2000
1981 record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; 2001 record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE;
diff --git a/networking/tls.h b/networking/tls.h
index d4ac1bef8..215e92b02 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -105,4 +105,15 @@ void xorbuf_aligned_AES_BLOCK_SIZE(void* buf, const void* mask) FAST_FUNC;
105#include "tls_aes.h" 105#include "tls_aes.h"
106#include "tls_aesgcm.h" 106#include "tls_aesgcm.h"
107#include "tls_rsa.h" 107#include "tls_rsa.h"
108#include "tls_fe.h" 108
109#define EC_CURVE_KEYSIZE 32
110#define P256_KEYSIZE 32
111#define CURVE25519_KEYSIZE 32
112
113void curve_x25519_compute_pubkey_and_premaster(
114 uint8_t *pubkey32, uint8_t *premaster32,
115 const uint8_t *peerkey32) FAST_FUNC;
116
117void curve_P256_compute_pubkey_and_premaster(
118 uint8_t *pubkey2x32, uint8_t *premaster32,
119 const uint8_t *peerkey2x32) FAST_FUNC;
diff --git a/networking/tls_fe.c b/networking/tls_fe.c
index f810e112a..ecb410281 100644
--- a/networking/tls_fe.c
+++ b/networking/tls_fe.c
@@ -64,8 +64,8 @@ static void fprime_select(byte *dst, const byte *zero, const byte *one, byte con
64#endif 64#endif
65 65
66static void fe_select(byte *dst, 66static void fe_select(byte *dst,
67 const byte *zero, const byte *one, 67 const byte *zero, const byte *one,
68 byte condition) 68 byte condition)
69{ 69{
70 const byte mask = -condition; 70 const byte mask = -condition;
71 int i; 71 int i;
@@ -108,26 +108,26 @@ static void raw_try_sub(byte *x, const byte *p)
108#if 0 //UNUSED 108#if 0 //UNUSED
109static int prime_msb(const byte *p) 109static int prime_msb(const byte *p)
110{ 110{
111 int i; 111 int i;
112 byte x; 112 byte x;
113 int shift = 1; 113 int shift = 1;
114 int z = F25519_SIZE - 1; 114 int z = F25519_SIZE - 1;
115 115
116 /* 116 /*
117 Test for any hot bits. 117 Test for any hot bits.
118 As soon as one instance is encountered set shift to 0. 118 As soon as one instance is encountered set shift to 0.
119 */ 119 */
120 for (i = F25519_SIZE - 1; i >= 0; i--) { 120 for (i = F25519_SIZE - 1; i >= 0; i--) {
121 shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1); 121 shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1);
122 z -= shift; 122 z -= shift;
123 } 123 }
124 x = p[z]; 124 x = p[z];
125 z <<= 3; 125 z <<= 3;
126 shift = 1; 126 shift = 1;
127 for (i = 0; i < 8; i++) { 127 for (i = 0; i < 8; i++) {
128 shift &= ((-(x >> i) | (x >> i)) >> (7 - i) & 1); 128 shift &= ((-(x >> i) | (x >> i)) >> (7 - i) & 1);
129 z += shift; 129 z += shift;
130 } 130 }
131 131
132 return z - 1; 132 return z - 1;
133} 133}
@@ -163,11 +163,11 @@ static void fprime_mul(byte *r, const byte *a, const byte *b,
163 const byte bit = (b[i >> 3] >> (i & 7)) & 1; 163 const byte bit = (b[i >> 3] >> (i & 7)) & 1;
164 byte plusa[F25519_SIZE]; 164 byte plusa[F25519_SIZE];
165 165
166 for (j = 0; j < F25519_SIZE; j++) { 166 for (j = 0; j < F25519_SIZE; j++) {
167 c |= ((word16)r[j]) << 1; 167 c |= ((word16)r[j]) << 1;
168 r[j] = (byte)c; 168 r[j] = (byte)c;
169 c >>= 8; 169 c >>= 8;
170 } 170 }
171 raw_try_sub(r, modulus); 171 raw_try_sub(r, modulus);
172 172
173 fprime_copy(plusa, r); 173 fprime_copy(plusa, r);
@@ -315,7 +315,7 @@ static void fe_mul__distinct(byte *r, const byte *a, const byte *b)
315 315
316 for (; j < F25519_SIZE; j++) 316 for (; j < F25519_SIZE; j++)
317 c += ((word32)a[j]) * 317 c += ((word32)a[j]) *
318 ((word32)b[i + F25519_SIZE - j]) * 38; 318 ((word32)b[i + F25519_SIZE - j]) * 38;
319 319
320 r[i] = c; 320 r[i] = c;
321 } 321 }
@@ -474,9 +474,9 @@ static void fe_sqrt(byte *r, const byte *a)
474 474
475/* Differential addition */ 475/* Differential addition */
476static void xc_diffadd(byte *x5, byte *z5, 476static void xc_diffadd(byte *x5, byte *z5,
477 const byte *x1, const byte *z1, 477 const byte *x1, const byte *z1,
478 const byte *x2, const byte *z2, 478 const byte *x2, const byte *z2,
479 const byte *x3, const byte *z3) 479 const byte *x3, const byte *z3)
480{ 480{
481 /* Explicit formulas database: dbl-1987-m3 481 /* Explicit formulas database: dbl-1987-m3
482 * 482 *
@@ -516,7 +516,7 @@ static void xc_diffadd(byte *x5, byte *z5,
516 516
517/* Double an X-coordinate */ 517/* Double an X-coordinate */
518static void xc_double(byte *x3, byte *z3, 518static void xc_double(byte *x3, byte *z3,
519 const byte *x1, const byte *z1) 519 const byte *x1, const byte *z1)
520{ 520{
521 /* Explicit formulas database: dbl-1987-m 521 /* Explicit formulas database: dbl-1987-m
522 * 522 *
@@ -544,11 +544,14 @@ static void xc_double(byte *x3, byte *z3,
544 fe_mul_c(z3, x1sq, 4); 544 fe_mul_c(z3, x1sq, 4);
545} 545}
546 546
547void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q) 547static void curve25519(byte *result, const byte *e, const byte *q)
548{ 548{
549 int i; 549 int i;
550 550
551 struct { 551 struct {
552 /* for bbox's special case of q == NULL meaning "use basepoint" */
553 /*static const*/ uint8_t basepoint9[CURVE25519_KEYSIZE]; // = {9};
554
552 /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ 555 /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */
553 /*static const*/ byte f25519_one[F25519_SIZE]; // = {1}; 556 /*static const*/ byte f25519_one[F25519_SIZE]; // = {1};
554 557
@@ -559,6 +562,7 @@ void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q)
559 byte xm1[F25519_SIZE]; // = {1}; 562 byte xm1[F25519_SIZE]; // = {1};
560 byte zm1[F25519_SIZE]; // = {0}; 563 byte zm1[F25519_SIZE]; // = {0};
561 } z; 564 } z;
565#define basepoint9 z.basepoint9
562#define f25519_one z.f25519_one 566#define f25519_one z.f25519_one
563#define xm z.xm 567#define xm z.xm
564#define zm z.zm 568#define zm z.zm
@@ -569,6 +573,11 @@ void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q)
569 zm[0] = 1; 573 zm[0] = 1;
570 xm1[0] = 1; 574 xm1[0] = 1;
571 575
576 if (!q) {
577 basepoint9[0] = 9;
578 q = basepoint9;
579 }
580
572 /* Note: bit 254 is assumed to be 1 */ 581 /* Note: bit 254 is assumed to be 1 */
573 lm_copy(xm, q); 582 lm_copy(xm, q);
574 583
@@ -599,3 +608,23 @@ void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q)
599 fe_mul__distinct(result, zm1, xm); 608 fe_mul__distinct(result, zm1, xm);
600 fe_normalize(result); 609 fe_normalize(result);
601} 610}
611
612/* interface to bbox's TLS code: */
613
614void FAST_FUNC curve_x25519_compute_pubkey_and_premaster(
615 uint8_t *pubkey, uint8_t *premaster,
616 const uint8_t *peerkey32)
617{
618 uint8_t privkey[CURVE25519_KEYSIZE]; //[32]
619
620 /* Generate random private key, see RFC 7748 */
621 tls_get_random(privkey, sizeof(privkey));
622 privkey[0] &= 0xf8;
623 privkey[CURVE25519_KEYSIZE-1] = ((privkey[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40);
624
625 /* Compute public key */
626 curve25519(pubkey, privkey, NULL /* "use base point of x25519" */);
627
628 /* Compute premaster using peer's public key */
629 curve25519(premaster, privkey, peerkey32);
630}
diff --git a/networking/tls_fe.h b/networking/tls_fe.h
deleted file mode 100644
index fe8cff228..000000000
--- a/networking/tls_fe.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/*
2 * Copyright (C) 2018 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#define CURVE25519_KEYSIZE 32
7void curve25519(uint8_t *result, const uint8_t *e, const uint8_t *q) FAST_FUNC;
diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c
index e5544ab11..99929031d 100644
--- a/networking/tls_pstm.c
+++ b/networking/tls_pstm.c
@@ -438,9 +438,9 @@ int32 FAST_FUNC pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
438 int32 idx = (c - 1) & ~3; 438 int32 idx = (c - 1) & ~3;
439 switch (c % 4) { 439 switch (c % 4) {
440 case 0: do { pd[idx+0] = *b++; 440 case 0: do { pd[idx+0] = *b++;
441 case 3: pd[idx+1] = *b++; 441 case 3: pd[idx+1] = *b++;
442 case 2: pd[idx+2] = *b++; 442 case 2: pd[idx+2] = *b++;
443 case 1: pd[idx+3] = *b++; 443 case 1: pd[idx+3] = *b++;
444 idx -= 4; 444 idx -= 4;
445 } while ((c -= 4) > 0); 445 } while ((c -= 4) > 0);
446 } 446 }
@@ -1427,7 +1427,7 @@ static int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1427 } 1427 }
1428 1428
1429 /* while (q{i-t-1} * (yt * b + y{t-1})) > 1429 /* while (q{i-t-1} * (yt * b + y{t-1})) >
1430 xi * b**2 + xi-1 * b + xi-2 1430 xi * b**2 + xi-1 * b + xi-2
1431 1431
1432 do q{i-t-1} -= 1; 1432 do q{i-t-1} -= 1;
1433 */ 1433 */
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c
index 20f9c26d5..4181a0590 100644
--- a/networking/tls_pstm_montgomery_reduce.c
+++ b/networking/tls_pstm_montgomery_reduce.c
@@ -62,6 +62,7 @@
62#define LOOP_START \ 62#define LOOP_START \
63 mu = c[x] * mp 63 mu = c[x] * mp
64 64
65#if 0
65#define INNERMUL \ 66#define INNERMUL \
66asm( \ 67asm( \
67 "movl %5,%%eax \n\t" \ 68 "movl %5,%%eax \n\t" \
@@ -74,15 +75,38 @@ asm( \
74:"=g"(_c[LO]), "=r"(cy) \ 75:"=g"(_c[LO]), "=r"(cy) \
75:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ 76:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \
76: "%eax", "%edx", "cc") 77: "%eax", "%edx", "cc")
78/*
79 * The above generated "error: 'asm' operand has impossible constraints" on Android.
80 * Do they reserve in their ABI a register for something, and there aren't enough left?
81 */
82#else
83/* Let's avoid two explicit "movl" by telling compiler to put input value of *tmpm++
84 * into EAX, and to expect cy result in EDX:
85 */
86#define INNERMUL \
87asm( \
88 "mull %4 \n\t" \
89 "addl %3,%%eax \n\t" \
90 "adcl $0,%%edx \n\t" \
91 "addl %%eax,%0 \n\t" \
92 "adcl $0,%%edx \n\t" \
93:"=g"(_c[LO]), "=&d"(cy) \
94:"0"(_c[LO]), "g"(cy), "g"(mu), "a"(*tmpm++) \
95:"cc")
96/* This doesn't tell compiler that we clobber EAX, but it probably won't need
97 * the value of *tmpm anyway, thus won't try to reuse EAX contents.
98 * TODO: fix it with dummy "=a"(clobbered_eax) output?
99 */
100#endif
77 101
78#define PROPCARRY \ 102#define PROPCARRY \
79asm( \ 103asm( \
80 "addl %1,%0 \n\t" \ 104 "addl %1,%0 \n\t" \
81 "setb %%al \n\t" \ 105 "sbb %1,%1 \n\t" \
82 "movzbl %%al,%1 \n\t" \ 106 "neg %1 \n\t" \
83:"=g"(_c[LO]), "=r"(cy) \ 107:"=g"(_c[LO]), "=r"(cy) \
84:"0"(_c[LO]), "1"(cy) \ 108:"0"(_c[LO]), "1"(cy) \
85: "%eax", "cc") 109:"cc")
86 110
87/******************************************************************************/ 111/******************************************************************************/
88#elif defined(PSTM_X86_64) 112#elif defined(PSTM_X86_64)
diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c
index 5fda1cb49..2dd5a02f4 100644
--- a/networking/tls_rsa.c
+++ b/networking/tls_rsa.c
@@ -15,7 +15,7 @@
15 pkcs1Pad(in, inlen, out, outlen, cryptType) 15 pkcs1Pad(in, inlen, out, outlen, cryptType)
16static //bbox 16static //bbox
17int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out, 17int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
18 uint32 outlen, int32 cryptType, void *userPtr) 18 uint32 outlen, int32 cryptType, void *userPtr)
19{ 19{
20 unsigned char *c; 20 unsigned char *c;
21 int32 randomLen; 21 int32 randomLen;
@@ -60,7 +60,7 @@ int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
60 psRsaCrypt( in, inlen, out, outlen, key, type) 60 psRsaCrypt( in, inlen, out, outlen, key, type)
61static //bbox 61static //bbox
62int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen, 62int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen,
63 unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type, 63 unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type,
64 void *data) 64 void *data)
65{ 65{
66 pstm_int tmp, tmpa, tmpb; 66 pstm_int tmp, tmpa, tmpb;
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c
new file mode 100644
index 000000000..5a84852a5
--- /dev/null
+++ b/networking/tls_sp_c32.c
@@ -0,0 +1,927 @@
1/*
2 * Copyright (C) 2021 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8#define SP_DEBUG 0
9#define FIXED_SECRET 0
10#define FIXED_PEER_PUBKEY 0
11
12#if SP_DEBUG
13# define dbg(...) fprintf(stderr, __VA_ARGS__)
14static void dump_hex(const char *fmt, const void *vp, int len)
15{
16 char hexbuf[32 * 1024 + 4];
17 const uint8_t *p = vp;
18
19 bin2hex(hexbuf, (void*)p, len)[0] = '\0';
20 dbg(fmt, hexbuf);
21}
22#else
23# define dbg(...) ((void)0)
24# define dump_hex(...) ((void)0)
25#endif
26
27#undef DIGIT_BIT
28#define DIGIT_BIT 32
29typedef int32_t sp_digit;
30
31/* The code below is taken from parts of
32 * wolfssl-3.15.3/wolfcrypt/src/sp_c32.c
33 * and heavily modified.
34 * Header comment is kept intact:
35 */
36
37/* sp.c
38 *
39 * Copyright (C) 2006-2018 wolfSSL Inc.
40 *
41 * This file is part of wolfSSL.
42 *
43 * wolfSSL is free software; you can redistribute it and/or modify
44 * it under the terms of the GNU General Public License as published by
45 * the Free Software Foundation; either version 2 of the License, or
46 * (at your option) any later version.
47 *
48 * wolfSSL is distributed in the hope that it will be useful,
49 * but WITHOUT ANY WARRANTY; without even the implied warranty of
50 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 * GNU General Public License for more details.
52 *
53 * You should have received a copy of the GNU General Public License
54 * along with this program; if not, write to the Free Software
55 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
56 */
57
58/* Implementation by Sean Parkinson. */
59
60typedef struct sp_point {
61 sp_digit x[2 * 10];
62 sp_digit y[2 * 10];
63 sp_digit z[2 * 10];
64 int infinity;
65} sp_point;
66
67/* The modulus (prime) of the curve P256. */
68static const sp_digit p256_mod[10] = {
69 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,
70 0x0000000,0x0000000,0x0000400,0x3ff0000,0x03fffff,
71};
72
73#define p256_mp_mod ((sp_digit)0x000001)
74
75/* Write r as big endian to byte aray.
76 * Fixed length number of bytes written: 32
77 *
78 * r A single precision integer.
79 * a Byte array.
80 */
81static void sp_256_to_bin(sp_digit* r, uint8_t* a)
82{
83 int i, j, s = 0, b;
84
85 for (i = 0; i < 9; i++) {
86 r[i+1] += r[i] >> 26;
87 r[i] &= 0x3ffffff;
88 }
89 j = 256 / 8 - 1;
90 a[j] = 0;
91 for (i = 0; i < 10 && j >= 0; i++) {
92 b = 0;
93 a[j--] |= r[i] << s; b += 8 - s;
94 if (j < 0)
95 break;
96 while (b < 26) {
97 a[j--] = r[i] >> b; b += 8;
98 if (j < 0)
99 break;
100 }
101 s = 8 - (b - 26);
102 if (j >= 0)
103 a[j] = 0;
104 if (s != 0)
105 j++;
106 }
107}
108
109/* Read big endian unsigned byte aray into r.
110 *
111 * r A single precision integer.
112 * a Byte array.
113 * n Number of bytes in array to read.
114 */
115static void sp_256_from_bin(sp_digit* r, int max, const uint8_t* a, int n)
116{
117 int i, j = 0, s = 0;
118
119 r[0] = 0;
120 for (i = n-1; i >= 0; i--) {
121 r[j] |= ((sp_digit)a[i]) << s;
122 if (s >= 18) {
123 r[j] &= 0x3ffffff;
124 s = 26 - s;
125 if (j + 1 >= max)
126 break;
127 r[++j] = a[i] >> s;
128 s = 8 - s;
129 }
130 else
131 s += 8;
132 }
133
134 for (j++; j < max; j++)
135 r[j] = 0;
136}
137
138/* Convert a point of big-endian 32-byte x,y pair to type sp_point. */
139static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32)
140{
141 memset(p, 0, sizeof(*p));
142 /*p->infinity = 0;*/
143 sp_256_from_bin(p->x, 2 * 10, bin2x32, 32);
144 sp_256_from_bin(p->y, 2 * 10, bin2x32 + 32, 32);
145 //static const uint8_t one[1] = { 1 };
146 //sp_256_from_bin(p->z, 2 * 10, one, 1);
147 p->z[0] = 1;
148}
149
150/* Compare a with b.
151 *
152 * return -ve, 0 or +ve if a is less than, equal to or greater than b
153 * respectively.
154 */
155static sp_digit sp_256_cmp_10(const sp_digit* a, const sp_digit* b)
156{
157 sp_digit r;
158 int i;
159 for (i = 9; i >= 0; i--) {
160 r = a[i] - b[i];
161 if (r != 0)
162 break;
163 }
164 return r;
165}
166
167/* Compare two numbers to determine if they are equal.
168 *
169 * return 1 when equal and 0 otherwise.
170 */
171static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b)
172{
173 return sp_256_cmp_10(a, b) == 0;
174}
175
176/* Normalize the values in each word to 26 bits. */
177static void sp_256_norm_10(sp_digit* a)
178{
179 int i;
180 for (i = 0; i < 9; i++) {
181 a[i+1] += a[i] >> 26;
182 a[i] &= 0x3ffffff;
183 }
184}
185
186/* Add b to a into r. (r = a + b) */
187static void sp_256_add_10(sp_digit* r, const sp_digit* a, const sp_digit* b)
188{
189 int i;
190 for (i = 0; i < 10; i++)
191 r[i] = a[i] + b[i];
192}
193
194/* Sub b from a into r. (r = a - b) */
195static void sp_256_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b)
196{
197 int i;
198 for (i = 0; i < 10; i++)
199 r[i] = a[i] - b[i];
200}
201
202/* Shift number left one bit. Bottom bit is lost. */
203static void sp_256_rshift1_10(sp_digit* r, sp_digit* a)
204{
205 int i;
206 for (i = 0; i < 9; i++)
207 r[i] = ((a[i] >> 1) | (a[i + 1] << 25)) & 0x3ffffff;
208 r[9] = a[9] >> 1;
209}
210
211/* Mul a by scalar b and add into r. (r += a * b) */
212static void sp_256_mul_add_10(sp_digit* r, const sp_digit* a, sp_digit b)
213{
214 int64_t tb = b;
215 int64_t t = 0;
216 int i;
217
218 for (i = 0; i < 10; i++) {
219 t += (tb * a[i]) + r[i];
220 r[i] = t & 0x3ffffff;
221 t >>= 26;
222 }
223 r[10] += t;
224}
225
226/* Multiply a and b into r. (r = a * b) */
227static void sp_256_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b)
228{
229 int i, j, k;
230 int64_t c;
231
232 c = ((int64_t)a[9]) * b[9];
233 r[19] = (sp_digit)(c >> 26);
234 c = (c & 0x3ffffff) << 26;
235 for (k = 17; k >= 0; k--) {
236 for (i = 9; i >= 0; i--) {
237 j = k - i;
238 if (j >= 10)
239 break;
240 if (j < 0)
241 continue;
242 c += ((int64_t)a[i]) * b[j];
243 }
244 r[k + 2] += c >> 52;
245 r[k + 1] = (c >> 26) & 0x3ffffff;
246 c = (c & 0x3ffffff) << 26;
247 }
248 r[0] = (sp_digit)(c >> 26);
249}
250
251/* Square a and put result in r. (r = a * a) */
252static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
253{
254 int i, j, k;
255 int64_t c;
256
257 c = ((int64_t)a[9]) * a[9];
258 r[19] = (sp_digit)(c >> 26);
259 c = (c & 0x3ffffff) << 26;
260 for (k = 17; k >= 0; k--) {
261 for (i = 9; i >= 0; i--) {
262 j = k - i;
263 if (j >= 10 || i <= j)
264 break;
265 if (j < 0)
266 continue;
267 c += ((int64_t)a[i]) * a[j] * 2;
268 }
269 if (i == j)
270 c += ((int64_t)a[i]) * a[i];
271 r[k + 2] += c >> 52;
272 r[k + 1] = (c >> 26) & 0x3ffffff;
273 c = (c & 0x3ffffff) << 26;
274 }
275 r[0] = (sp_digit)(c >> 26);
276}
277
278/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) */
279static void sp_256_div2_10(sp_digit* r, const sp_digit* a, const sp_digit* m)
280{
281 if (a[0] & 1)
282 sp_256_add_10(r, a, m);
283 sp_256_norm_10(r);
284 sp_256_rshift1_10(r, r);
285}
286
287/* Add two Montgomery form numbers (r = a + b % m) */
288static void sp_256_mont_add_10(sp_digit* r, const sp_digit* a, const sp_digit* b,
289 const sp_digit* m)
290{
291 sp_256_add_10(r, a, b);
292 sp_256_norm_10(r);
293 if ((r[9] >> 22) > 0)
294 sp_256_sub_10(r, r, m);
295 sp_256_norm_10(r);
296}
297
298/* Subtract two Montgomery form numbers (r = a - b % m) */
299static void sp_256_mont_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b,
300 const sp_digit* m)
301{
302 sp_256_sub_10(r, a, b);
303 if (r[9] >> 22)
304 sp_256_add_10(r, r, m);
305 sp_256_norm_10(r);
306}
307
308/* Double a Montgomery form number (r = a + a % m) */
309static void sp_256_mont_dbl_10(sp_digit* r, const sp_digit* a, const sp_digit* m)
310{
311 sp_256_add_10(r, a, a);
312 sp_256_norm_10(r);
313 if ((r[9] >> 22) > 0)
314 sp_256_sub_10(r, r, m);
315 sp_256_norm_10(r);
316}
317
318/* Triple a Montgomery form number (r = a + a + a % m) */
319static void sp_256_mont_tpl_10(sp_digit* r, const sp_digit* a, const sp_digit* m)
320{
321 sp_256_add_10(r, a, a);
322 sp_256_norm_10(r);
323 if ((r[9] >> 22) > 0)
324 sp_256_sub_10(r, r, m);
325 sp_256_norm_10(r);
326 sp_256_add_10(r, r, a);
327 sp_256_norm_10(r);
328 if ((r[9] >> 22) > 0)
329 sp_256_sub_10(r, r, m);
330 sp_256_norm_10(r);
331}
332
333/* Shift the result in the high 256 bits down to the bottom. */
334static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a)
335{
336 int i;
337 sp_digit n, s;
338
339 s = a[10];
340 n = a[9] >> 22;
341 for (i = 0; i < 9; i++) {
342 n += (s & 0x3ffffff) << 4;
343 r[i] = n & 0x3ffffff;
344 n >>= 26;
345 s = a[11 + i] + (s >> 26);
346 }
347 n += s << 4;
348 r[9] = n;
349 memset(&r[10], 0, sizeof(*r) * 10);
350}
351
352/* Reduce the number back to 256 bits using Montgomery reduction.
353 *
354 * a A single precision number to reduce in place.
355 * m The single precision number representing the modulus.
356 * mp The digit representing the negative inverse of m mod 2^n.
357 */
358static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp)
359{
360 int i;
361 sp_digit mu;
362
363 if (mp != 1) {
364 for (i = 0; i < 9; i++) {
365 mu = (a[i] * mp) & 0x3ffffff;
366 sp_256_mul_add_10(a+i, m, mu);
367 a[i+1] += a[i] >> 26;
368 }
369 mu = (a[i] * mp) & 0x3fffffl;
370 sp_256_mul_add_10(a+i, m, mu);
371 a[i+1] += a[i] >> 26;
372 a[i] &= 0x3ffffff;
373 }
374 else {
375 for (i = 0; i < 9; i++) {
376 mu = a[i] & 0x3ffffff;
377 sp_256_mul_add_10(a+i, p256_mod, mu);
378 a[i+1] += a[i] >> 26;
379 }
380 mu = a[i] & 0x3fffffl;
381 sp_256_mul_add_10(a+i, p256_mod, mu);
382 a[i+1] += a[i] >> 26;
383 a[i] &= 0x3ffffff;
384 }
385
386 sp_256_mont_shift_10(a, a);
387 if ((a[9] >> 22) > 0)
388 sp_256_sub_10(a, a, m);
389 sp_256_norm_10(a);
390}
391
392/* Multiply two Montogmery form numbers mod the modulus (prime).
393 * (r = a * b mod m)
394 *
395 * r Result of multiplication.
396 * a First number to multiply in Montogmery form.
397 * b Second number to multiply in Montogmery form.
398 * m Modulus (prime).
399 * mp Montogmery mulitplier.
400 */
401static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b,
402 const sp_digit* m, sp_digit mp)
403{
404 sp_256_mul_10(r, a, b);
405 sp_256_mont_reduce_10(r, m, mp);
406}
407
408/* Square the Montgomery form number. (r = a * a mod m)
409 *
410 * r Result of squaring.
411 * a Number to square in Montogmery form.
412 * m Modulus (prime).
413 * mp Montogmery mulitplier.
414 */
415static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a, const sp_digit* m,
416 sp_digit mp)
417{
418 sp_256_sqr_10(r, a);
419 sp_256_mont_reduce_10(r, m, mp);
420}
421
422/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
423 * P256 curve. (r = 1 / a mod m)
424 *
425 * r Inverse result.
426 * a Number to invert.
427 */
428#if 0
429/* Mod-2 for the P256 curve. */
430static const uint32_t p256_mod_2[8] = {
431 0xfffffffd,0xffffffff,0xffffffff,0x00000000,
432 0x00000000,0x00000000,0x00000001,0xffffffff,
433};
434//Bit pattern:
435//2 2 2 2 2 2 2 1...1
436//5 5 4 3 2 1 0 9...0 9...1
437//543210987654321098765432109876543210987654321098765432109876543210...09876543210...09876543210
438//111111111111111111111111111111110000000000000000000000000000000100...00000111111...11111111101
439#endif
440static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a)
441{
442 sp_digit t[2*10]; //can be just [10]?
443 int i;
444
445 memcpy(t, a, sizeof(sp_digit) * 10);
446 for (i = 254; i >= 0; i--) {
447 sp_256_mont_sqr_10(t, t, p256_mod, p256_mp_mod);
448 /*if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))*/
449 if (i >= 224 || i == 192 || (i <= 95 && i != 1))
450 sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod);
451 }
452 memcpy(r, t, sizeof(sp_digit) * 10);
453}
454
455/* Multiply a number by Montogmery normalizer mod modulus (prime).
456 *
457 * r The resulting Montgomery form number.
458 * a The number to convert.
459 */
460static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a)
461{
462 int64_t t[8];
463 int64_t o;
464 uint32_t a32;
465
466 /* 1 1 0 -1 -1 -1 -1 0 */
467 /* 0 1 1 0 -1 -1 -1 -1 */
468 /* 0 0 1 1 0 -1 -1 -1 */
469 /* -1 -1 0 2 2 1 0 -1 */
470 /* 0 -1 -1 0 2 2 1 0 */
471 /* 0 0 -1 -1 0 2 2 1 */
472 /* -1 -1 0 0 0 1 3 2 */
473 /* 1 0 -1 -1 -1 -1 0 3 */
474 // t[] should be calculated from "a" (converted from 26-bit to 32-bit vector a32[8])
475 // according to the above matrix:
476 //t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6] ;
477 //t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7] ;
478 //t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7] ;
479 //t[3] = 0 - a32[0] - a32[1] + 2*a32[3] + 2*a32[4] + a32[5] - a32[7] ;
480 //t[4] = 0 - a32[1] - a32[2] + 2*a32[4] + 2*a32[5] + a32[6] ;
481 //t[5] = 0 - a32[2] - a32[3] + 2*a32[5] + 2*a32[6] + a32[7] ;
482 //t[6] = 0 - a32[0] - a32[1] + a32[5] + 3*a32[6] + 2*a32[7];
483 //t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3*a32[7];
484 // We can do it "piecemeal" after each a32[i] is known, no need to store entire a32[8] vector:
485
486#define A32 (int64_t)a32
487 a32 = a[0] | (a[1] << 26);
488 t[0] = 0 + A32;
489 t[3] = 0 - A32;
490 t[6] = 0 - A32;
491 t[7] = 0 + A32;
492
493 a32 = (a[1] >> 6) | (a[2] << 20);
494 t[0] += A32 ;
495 t[1] = 0 + A32;
496 t[3] -= A32 ;
497 t[4] = 0 - A32;
498 t[6] -= A32 ;
499
500 a32 = (a[2] >> 12) | (a[3] << 14);
501 t[1] += A32 ;
502 t[2] = 0 + A32;
503 t[4] -= A32 ;
504 t[5] = 0 - A32;
505 t[7] -= A32 ;
506
507 a32 = (a[3] >> 18) | (a[4] << 8);
508 t[0] -= A32 ;
509 t[2] += A32 ;
510 t[3] += 2*A32;
511 t[5] -= A32 ;
512 t[7] -= A32 ;
513
514 a32 = (a[4] >> 24) | (a[5] << 2) | (a[6] << 28);
515 t[0] -= A32 ;
516 t[1] -= A32 ;
517 t[3] += 2*A32;
518 t[4] += 2*A32;
519 t[7] -= A32 ;
520
521 a32 = (a[6] >> 4) | (a[7] << 22);
522 t[0] -= A32 ;
523 t[1] -= A32 ;
524 t[2] -= A32 ;
525 t[3] += A32 ;
526 t[4] += 2*A32;
527 t[5] += 2*A32;
528 t[6] += A32 ;
529 t[7] -= A32 ;
530
531 a32 = (a[7] >> 10) | (a[8] << 16);
532 t[0] -= A32 ;
533 t[1] -= A32 ;
534 t[2] -= A32 ;
535 t[4] += A32 ;
536 t[5] += 2*A32;
537 t[6] += 3*A32;
538
539 a32 = (a[8] >> 16) | (a[9] << 10);
540 t[1] -= A32 ;
541 t[2] -= A32 ;
542 t[3] -= A32 ;
543 t[5] += A32 ;
544 t[6] += 2*A32;
545 t[7] += 3*A32;
546#undef A32
547
548 t[1] += t[0] >> 32; t[0] &= 0xffffffff;
549 t[2] += t[1] >> 32; t[1] &= 0xffffffff;
550 t[3] += t[2] >> 32; t[2] &= 0xffffffff;
551 t[4] += t[3] >> 32; t[3] &= 0xffffffff;
552 t[5] += t[4] >> 32; t[4] &= 0xffffffff;
553 t[6] += t[5] >> 32; t[5] &= 0xffffffff;
554 t[7] += t[6] >> 32; t[6] &= 0xffffffff;
555 o = t[7] >> 32; t[7] &= 0xffffffff;
556 t[0] += o;
557 t[3] -= o;
558 t[6] -= o;
559 t[7] += o;
560 t[1] += t[0] >> 32; //t[0] &= 0xffffffff;
561 t[2] += t[1] >> 32; //t[1] &= 0xffffffff;
562 t[3] += t[2] >> 32; //t[2] &= 0xffffffff;
563 t[4] += t[3] >> 32; //t[3] &= 0xffffffff;
564 t[5] += t[4] >> 32; //t[4] &= 0xffffffff;
565 t[6] += t[5] >> 32; //t[5] &= 0xffffffff;
566 t[7] += t[6] >> 32; //t[6] &= 0xffffffff; - (uint32_t)t[i] casts below accomplish masking
567
568 r[0] = 0x3ffffff & ((sp_digit)((uint32_t)t[0]));
569 r[1] = 0x3ffffff & ((sp_digit)((uint32_t)t[0] >> 26) | ((sp_digit)t[1] << 6));
570 r[2] = 0x3ffffff & ((sp_digit)((uint32_t)t[1] >> 20) | ((sp_digit)t[2] << 12));
571 r[3] = 0x3ffffff & ((sp_digit)((uint32_t)t[2] >> 14) | ((sp_digit)t[3] << 18));
572 r[4] = 0x3ffffff & ((sp_digit)((uint32_t)t[3] >> 8) | ((sp_digit)t[4] << 24));
573 r[5] = 0x3ffffff & ((sp_digit)((uint32_t)t[4] >> 2));
574 r[6] = 0x3ffffff & ((sp_digit)((uint32_t)t[4] >> 28) | ((sp_digit)t[5] << 4));
575 r[7] = 0x3ffffff & ((sp_digit)((uint32_t)t[5] >> 22) | ((sp_digit)t[6] << 10));
576 r[8] = 0x3ffffff & ((sp_digit)((uint32_t)t[6] >> 16) | ((sp_digit)t[7] << 16));
577 r[9] = ((sp_digit)((uint32_t)t[7] >> 10));
578}
579
580/* Map the Montgomery form projective co-ordinate point to an affine point.
581 *
582 * r Resulting affine co-ordinate point.
583 * p Montgomery form projective co-ordinate point.
584 */
585static void sp_256_map_10(sp_point* r, sp_point* p)
586{
587 sp_digit t1[2*10];
588 sp_digit t2[2*10];
589
590 sp_256_mont_inv_10(t1, p->z);
591
592 sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod);
593 sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod);
594
595 /* x /= z^2 */
596 sp_256_mont_mul_10(r->x, p->x, t2, p256_mod, p256_mp_mod);
597 memset(r->x + 10, 0, sizeof(r->x) / 2);
598 sp_256_mont_reduce_10(r->x, p256_mod, p256_mp_mod);
599 /* Reduce x to less than modulus */
600 if (sp_256_cmp_10(r->x, p256_mod) >= 0)
601 sp_256_sub_10(r->x, r->x, p256_mod);
602 sp_256_norm_10(r->x);
603
604 /* y /= z^3 */
605 sp_256_mont_mul_10(r->y, p->y, t1, p256_mod, p256_mp_mod);
606 memset(r->y + 10, 0, sizeof(r->y) / 2);
607 sp_256_mont_reduce_10(r->y, p256_mod, p256_mp_mod);
608 /* Reduce y to less than modulus */
609 if (sp_256_cmp_10(r->y, p256_mod) >= 0)
610 sp_256_sub_10(r->y, r->y, p256_mod);
611 sp_256_norm_10(r->y);
612
613 memset(r->z, 0, sizeof(r->z));
614 r->z[0] = 1;
615}
616
617/* Double the Montgomery form projective point p.
618 *
619 * r Result of doubling point.
620 * p Point to double.
621 */
622static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p)
623{
624 sp_point tp;
625 sp_digit t1[2*10];
626 sp_digit t2[2*10];
627
628 /* Put point to double into result */
629 if (r != p)
630 *r = *p; /* struct copy */
631
632 if (r->infinity) {
633 /* If infinity, don't double (work on dummy value) */
634 r = &tp;
635 }
636 /* T1 = Z * Z */
637 sp_256_mont_sqr_10(t1, r->z, p256_mod, p256_mp_mod);
638 /* Z = Y * Z */
639 sp_256_mont_mul_10(r->z, r->y, r->z, p256_mod, p256_mp_mod);
640 /* Z = 2Z */
641 sp_256_mont_dbl_10(r->z, r->z, p256_mod);
642 /* T2 = X - T1 */
643 sp_256_mont_sub_10(t2, r->x, t1, p256_mod);
644 /* T1 = X + T1 */
645 sp_256_mont_add_10(t1, r->x, t1, p256_mod);
646 /* T2 = T1 * T2 */
647 sp_256_mont_mul_10(t2, t1, t2, p256_mod, p256_mp_mod);
648 /* T1 = 3T2 */
649 sp_256_mont_tpl_10(t1, t2, p256_mod);
650 /* Y = 2Y */
651 sp_256_mont_dbl_10(r->y, r->y, p256_mod);
652 /* Y = Y * Y */
653 sp_256_mont_sqr_10(r->y, r->y, p256_mod, p256_mp_mod);
654 /* T2 = Y * Y */
655 sp_256_mont_sqr_10(t2, r->y, p256_mod, p256_mp_mod);
656 /* T2 = T2/2 */
657 sp_256_div2_10(t2, t2, p256_mod);
658 /* Y = Y * X */
659 sp_256_mont_mul_10(r->y, r->y, r->x, p256_mod, p256_mp_mod);
660 /* X = T1 * T1 */
661 sp_256_mont_mul_10(r->x, t1, t1, p256_mod, p256_mp_mod);
662 /* X = X - Y */
663 sp_256_mont_sub_10(r->x, r->x, r->y, p256_mod);
664 /* X = X - Y */
665 sp_256_mont_sub_10(r->x, r->x, r->y, p256_mod);
666 /* Y = Y - X */
667 sp_256_mont_sub_10(r->y, r->y, r->x, p256_mod);
668 /* Y = Y * T1 */
669 sp_256_mont_mul_10(r->y, r->y, t1, p256_mod, p256_mp_mod);
670 /* Y = Y - T2 */
671 sp_256_mont_sub_10(r->y, r->y, t2, p256_mod);
672}
673
674/* Add two Montgomery form projective points.
675 *
676 * r Result of addition.
677 * p Frist point to add.
678 * q Second point to add.
679 */
680static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q)
681{
682 sp_digit t1[2*10];
683 sp_digit t2[2*10];
684 sp_digit t3[2*10];
685 sp_digit t4[2*10];
686 sp_digit t5[2*10];
687
688 /* Ensure only the first point is the same as the result. */
689 if (q == r) {
690 sp_point* a = p;
691 p = q;
692 q = a;
693 }
694
695 /* Check double */
696 sp_256_sub_10(t1, p256_mod, q->y);
697 sp_256_norm_10(t1);
698 if (sp_256_cmp_equal_10(p->x, q->x)
699 && sp_256_cmp_equal_10(p->z, q->z)
700 && (sp_256_cmp_equal_10(p->y, q->y) || sp_256_cmp_equal_10(p->y, t1))
701 ) {
702 sp_256_proj_point_dbl_10(r, p);
703 }
704 else {
705 sp_point tp;
706 sp_point *v;
707
708 v = r;
709 if (p->infinity | q->infinity) {
710 memset(&tp, 0, sizeof(tp));
711 v = &tp;
712 }
713
714 *r = p->infinity ? *q : *p; /* struct copy */
715
716 /* U1 = X1*Z2^2 */
717 sp_256_mont_sqr_10(t1, q->z, p256_mod, p256_mp_mod);
718 sp_256_mont_mul_10(t3, t1, q->z, p256_mod, p256_mp_mod);
719 sp_256_mont_mul_10(t1, t1, v->x, p256_mod, p256_mp_mod);
720 /* U2 = X2*Z1^2 */
721 sp_256_mont_sqr_10(t2, v->z, p256_mod, p256_mp_mod);
722 sp_256_mont_mul_10(t4, t2, v->z, p256_mod, p256_mp_mod);
723 sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod);
724 /* S1 = Y1*Z2^3 */
725 sp_256_mont_mul_10(t3, t3, v->y, p256_mod, p256_mp_mod);
726 /* S2 = Y2*Z1^3 */
727 sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod);
728 /* H = U2 - U1 */
729 sp_256_mont_sub_10(t2, t2, t1, p256_mod);
730 /* R = S2 - S1 */
731 sp_256_mont_sub_10(t4, t4, t3, p256_mod);
732 /* Z3 = H*Z1*Z2 */
733 sp_256_mont_mul_10(v->z, v->z, q->z, p256_mod, p256_mp_mod);
734 sp_256_mont_mul_10(v->z, v->z, t2, p256_mod, p256_mp_mod);
735 /* X3 = R^2 - H^3 - 2*U1*H^2 */
736 sp_256_mont_sqr_10(v->x, t4, p256_mod, p256_mp_mod);
737 sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod);
738 sp_256_mont_mul_10(v->y, t1, t5, p256_mod, p256_mp_mod);
739 sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod);
740 sp_256_mont_sub_10(v->x, v->x, t5, p256_mod);
741 sp_256_mont_dbl_10(t1, v->y, p256_mod);
742 sp_256_mont_sub_10(v->x, v->x, t1, p256_mod);
743 /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
744 sp_256_mont_sub_10(v->y, v->y, v->x, p256_mod);
745 sp_256_mont_mul_10(v->y, v->y, t4, p256_mod, p256_mp_mod);
746 sp_256_mont_mul_10(t5, t5, t3, p256_mod, p256_mp_mod);
747 sp_256_mont_sub_10(v->y, v->y, t5, p256_mod);
748 }
749}
750
751/* Multiply the point by the scalar and return the result.
752 * If map is true then convert result to affine co-ordinates.
753 *
754 * r Resulting point.
755 * g Point to multiply.
756 * k Scalar to multiply by.
757 * map Indicates whether to convert result to affine.
758 */
759static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit* k /*, int map*/)
760{
761 enum { map = 1 }; /* we always convert result to affine coordinates */
762 sp_point t[3];
763 sp_digit n;
764 int i;
765 int c, y;
766
767 memset(t, 0, sizeof(t));
768
769 /* t[0] = {0, 0, 1} * norm */
770 t[0].infinity = 1;
771 /* t[1] = {g->x, g->y, g->z} * norm */
772 sp_256_mod_mul_norm_10(t[1].x, g->x);
773 sp_256_mod_mul_norm_10(t[1].y, g->y);
774 sp_256_mod_mul_norm_10(t[1].z, g->z);
775
776 i = 9;
777 c = 22;
778 n = k[i--] << (26 - c);
779 for (; ; c--) {
780 if (c == 0) {
781 if (i == -1)
782 break;
783
784 n = k[i--];
785 c = 26;
786 }
787
788 y = (n >> 25) & 1;
789 n <<= 1;
790
791 sp_256_proj_point_add_10(&t[y^1], &t[0], &t[1]);
792 memcpy(&t[2], &t[y], sizeof(sp_point));
793 sp_256_proj_point_dbl_10(&t[2], &t[2]);
794 memcpy(&t[y], &t[2], sizeof(sp_point));
795 }
796
797 if (map)
798 sp_256_map_10(r, &t[0]);
799 else
800 memcpy(r, &t[0], sizeof(sp_point));
801
802 memset(t, 0, sizeof(t)); //paranoia
803}
804
805/* Multiply the base point of P256 by the scalar and return the result.
806 * If map is true then convert result to affine co-ordinates.
807 *
808 * r Resulting point.
809 * k Scalar to multiply by.
810 * map Indicates whether to convert result to affine.
811 */
812static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/)
813{
814 /* Since this function is called only once, save space:
815 * don't have "static const sp_point p256_base = {...}",
816 * it would have more zeros than data.
817 */
818 static const uint8_t p256_base_bin[] = {
819 /* x (big-endian) */
820 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96,
821 /* y */
822 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5,
823 /* z will be set to 1, infinity flag to "false" */
824 };
825 sp_point p256_base;
826
827 sp_256_point_from_bin2x32(&p256_base, p256_base_bin);
828
829 sp_256_ecc_mulmod_10(r, &p256_base, k /*, map*/);
830}
831
832/* Multiply the point by the scalar and serialize the X ordinate.
833 * The number is 0 padded to maximum size on output.
834 *
835 * priv Scalar to multiply the point by.
836 * pub2x32 Point to multiply.
837 * out32 Buffer to hold X ordinate.
838 */
839static void sp_ecc_secret_gen_256(const sp_digit priv[10], const uint8_t *pub2x32, uint8_t* out32)
840{
841 sp_point point[1];
842
843#if FIXED_PEER_PUBKEY
844 memset((void*)pub2x32, 0x55, 64);
845#endif
846 dump_hex("peerkey %s\n", pub2x32, 32); /* in TLS, this is peer's public key */
847 dump_hex(" %s\n", pub2x32 + 32, 32);
848
849 sp_256_point_from_bin2x32(point, pub2x32);
850 dump_hex("point->x %s\n", point->x, sizeof(point->x));
851 dump_hex("point->y %s\n", point->y, sizeof(point->y));
852
853 sp_256_ecc_mulmod_10(point, point, priv);
854
855 sp_256_to_bin(point->x, out32);
856 dump_hex("out32: %s\n", out32, 32);
857}
858
859/* Generates a scalar that is in the range 1..order-1. */
860#define SIMPLIFY 1
861/* Add 1 to a. (a = a + 1) */
862static void sp_256_add_one_10(sp_digit* a)
863{
864 a[0]++;
865 sp_256_norm_10(a);
866}
867static void sp_256_ecc_gen_k_10(sp_digit k[10])
868{
869#if !SIMPLIFY
870 /* The order of the curve P256 minus 2. */
871 static const sp_digit p256_order2[10] = {
872 0x063254f,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,
873 0x3ffffff,0x3ffffff,0x00003ff,0x3ff0000,0x03fffff,
874 };
875#endif
876 uint8_t buf[32];
877
878 for (;;) {
879 tls_get_random(buf, sizeof(buf));
880#if FIXED_SECRET
881 memset(buf, 0x77, sizeof(buf));
882#endif
883 sp_256_from_bin(k, 10, buf, sizeof(buf));
884#if !SIMPLIFY
885 if (sp_256_cmp_10(k, p256_order2) < 0)
886 break;
887#else
888 /* non-loopy version (and not needing p256_order2[]):
889 * if most-significant word seems that k can be larger
890 * than p256_order2, fix it up:
891 */
892 if (k[9] >= 0x03fffff)
893 k[9] = 0x03ffffe;
894 break;
895#endif
896 }
897 sp_256_add_one_10(k);
898#undef SIMPLIFY
899}
900
901/* Makes a random EC key pair. */
902static void sp_ecc_make_key_256(sp_digit privkey[10], uint8_t *pubkey)
903{
904 sp_point point[1];
905
906 sp_256_ecc_gen_k_10(privkey);
907 sp_256_ecc_mulmod_base_10(point, privkey);
908 sp_256_to_bin(point->x, pubkey);
909 sp_256_to_bin(point->y, pubkey + 32);
910
911 memset(point, 0, sizeof(point)); //paranoia
912}
913
914void FAST_FUNC curve_P256_compute_pubkey_and_premaster(
915 uint8_t *pubkey2x32, uint8_t *premaster32,
916 const uint8_t *peerkey2x32)
917{
918 sp_digit privkey[10];
919
920 sp_ecc_make_key_256(privkey, pubkey2x32);
921 dump_hex("pubkey: %s\n", pubkey2x32, 32);
922 dump_hex(" %s\n", pubkey2x32 + 32, 32);
923
924 /* Combine our privkey and peer's public key to generate premaster */
925 sp_ecc_secret_gen_256(privkey, /*x,y:*/peerkey2x32, premaster32);
926 dump_hex("premaster: %s\n", premaster32, 32);
927}
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 4bc719001..f2d6907ad 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -273,17 +273,27 @@ uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_sc
273 break; 273 break;
274 } 274 }
275 275
276 if (scan_state->rem <= OPT_LEN) 276 if (scan_state->rem <= OPT_LEN) /* [len] byte exists? */
277 goto complain; /* complain and return NULL */ 277 goto complain; /* no, complain and return NULL */
278 len = 2 + scan_state->optionptr[OPT_LEN]; 278 len = scan_state->optionptr[OPT_LEN];
279 /* Skip options with zero length.
280 * Users report that DHCP server on a TrendNet router (unknown model)
281 * provides a zero-length option 12 (Host Name)
282 * (this violates RFC 2132 section 3.14).
283 */
284 if (len == 0) {
285 scan_state->rem -= 2;
286 scan_state->optionptr += 2;
287 continue;
288 }
289 len += 2;
279 scan_state->rem -= len; 290 scan_state->rem -= len;
280 /* So far no valid option with length 0 known. */ 291 if (scan_state->rem < 0) /* option is longer than options field? */
281 if (scan_state->rem < 0 || scan_state->optionptr[OPT_LEN] == 0) 292 goto complain; /* yes, complain and return NULL */
282 goto complain; /* complain and return NULL */
283 293
284 if (scan_state->optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { 294 if (scan_state->optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) {
285 if (len >= 3) 295 /* len is known to be >= 3 now, [data] byte exists */
286 scan_state->overload |= scan_state->optionptr[OPT_DATA]; 296 scan_state->overload |= scan_state->optionptr[OPT_DATA];
287 } else { 297 } else {
288 uint8_t *return_ptr = scan_state->optionptr; 298 uint8_t *return_ptr = scan_state->optionptr;
289 scan_state->optionptr += len; 299 scan_state->optionptr += len;
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 76b087b92..0a5cae310 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -1040,7 +1040,6 @@ static int d6_raw_socket(int ifindex)
1040 log2("opening raw socket on ifindex %d", ifindex); 1040 log2("opening raw socket on ifindex %d", ifindex);
1041 1041
1042 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); 1042 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
1043 log3("got raw socket fd %d", fd);
1044 1043
1045 memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ 1044 memset(&sock, 0, sizeof(sock)); /* let's be deterministic */
1046 sock.sll_family = AF_PACKET; 1045 sock.sll_family = AF_PACKET;
@@ -1087,29 +1086,6 @@ static void change_listen_mode(int new_mode)
1087 /* else LISTEN_NONE: client_data.sockfd stays closed */ 1086 /* else LISTEN_NONE: client_data.sockfd stays closed */
1088} 1087}
1089 1088
1090/* Called only on SIGUSR1 */
1091static void perform_renew(void)
1092{
1093 bb_simple_info_msg("performing DHCP renew");
1094 switch (client_data.state) {
1095 case BOUND:
1096 change_listen_mode(LISTEN_KERNEL);
1097 case RENEWING:
1098 case REBINDING:
1099 client_data.state = RENEW_REQUESTED;
1100 break;
1101 case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
1102 d6_run_script_no_option("deconfig");
1103 case REQUESTING:
1104 case RELEASED:
1105 change_listen_mode(LISTEN_RAW);
1106 client_data.state = INIT_SELECTING;
1107 break;
1108 case INIT_SELECTING:
1109 break;
1110 }
1111}
1112
1113static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) 1089static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
1114{ 1090{
1115 /* send release packet */ 1091 /* send release packet */
@@ -1220,7 +1196,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1220 uint32_t xid = 0; 1196 uint32_t xid = 0;
1221 int packet_num; 1197 int packet_num;
1222 int timeout; /* must be signed */ 1198 int timeout; /* must be signed */
1223 unsigned already_waited_sec; 1199 int lease_remaining; /* must be signed */
1224 unsigned opt; 1200 unsigned opt;
1225 int retval; 1201 int retval;
1226 1202
@@ -1348,19 +1324,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1348 change_listen_mode(LISTEN_RAW); 1324 change_listen_mode(LISTEN_RAW);
1349 packet_num = 0; 1325 packet_num = 0;
1350 timeout = 0; 1326 timeout = 0;
1351 already_waited_sec = 0; 1327 lease_remaining = 0;
1352 1328
1353 /* Main event loop. select() waits on signal pipe and possibly 1329 /* Main event loop. select() waits on signal pipe and possibly
1354 * on sockfd. 1330 * on sockfd.
1355 * "continue" statements in code below jump to the top of the loop. 1331 * "continue" statements in code below jump to the top of the loop.
1356 */ 1332 */
1357 for (;;) { 1333 for (;;) {
1358 int tv;
1359 struct pollfd pfds[2]; 1334 struct pollfd pfds[2];
1360 struct d6_packet packet; 1335 struct d6_packet packet;
1361 uint8_t *packet_end; 1336 uint8_t *packet_end;
1362 /* silence "uninitialized!" warning */
1363 unsigned timestamp_before_wait = timestamp_before_wait;
1364 1337
1365 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); 1338 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
1366 1339
@@ -1373,17 +1346,24 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1373 1346
1374 udhcp_sp_fd_set(pfds, client_data.sockfd); 1347 udhcp_sp_fd_set(pfds, client_data.sockfd);
1375 1348
1376 tv = timeout - already_waited_sec;
1377 retval = 0; 1349 retval = 0;
1378 /* If we already timed out, fall through with retval = 0, else... */ 1350 /* If we already timed out, fall through with retval = 0, else... */
1379 if (tv > 0) { 1351 if (timeout > 0) {
1380 log1("waiting %u seconds", tv); 1352 unsigned diff;
1381 timestamp_before_wait = (unsigned)monotonic_sec(); 1353
1382 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX); 1354 if (timeout > INT_MAX/1000)
1355 timeout = INT_MAX/1000;
1356 log1("waiting %u seconds", timeout);
1357 diff = (unsigned)monotonic_sec();
1358 retval = poll(pfds, 2, timeout * 1000);
1383 if (retval < 0) { 1359 if (retval < 0) {
1384 /* EINTR? A signal was caught, don't panic */ 1360 /* EINTR? A signal was caught, don't panic */
1385 if (errno == EINTR) { 1361 if (errno == EINTR) {
1386 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1362 diff = (unsigned)monotonic_sec() - diff;
1363 lease_remaining -= diff;
1364 if (lease_remaining < 0)
1365 lease_remaining = 0;
1366 timeout -= diff;
1387 continue; 1367 continue;
1388 } 1368 }
1389 /* Else: an error occured, panic! */ 1369 /* Else: an error occured, panic! */
@@ -1410,9 +1390,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1410 1390
1411 memcpy(clientid_mac_ptr, client_data.client_mac, 6); 1391 memcpy(clientid_mac_ptr, client_data.client_mac, 6);
1412 1392
1413 /* We will restart the wait in any case */
1414 already_waited_sec = 0;
1415
1416 switch (client_data.state) { 1393 switch (client_data.state) {
1417 case INIT_SELECTING: 1394 case INIT_SELECTING:
1418 if (!discover_retries || packet_num < discover_retries) { 1395 if (!discover_retries || packet_num < discover_retries) {
@@ -1477,7 +1454,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1477 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1454 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1478 case_RENEW_REQUESTED: 1455 case_RENEW_REQUESTED:
1479 case RENEWING: 1456 case RENEWING:
1480 if (timeout >= 60) { 1457 if (packet_num < 3) {
1458 packet_num++;
1481 /* send an unicast renew request */ 1459 /* send an unicast renew request */
1482 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind 1460 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1483 * a new UDP socket for sending inside send_renew. 1461 * a new UDP socket for sending inside send_renew.
@@ -1491,7 +1469,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1491 send_d6_info_request(xid); 1469 send_d6_info_request(xid);
1492 else 1470 else
1493 send_d6_renew(xid, &srv6_buf, requested_ipv6); 1471 send_d6_renew(xid, &srv6_buf, requested_ipv6);
1494 timeout >>= 1; 1472 timeout = discover_timeout;
1473 /* ^^^ used to be = lease_remaining / 2 - WAY too long */
1495 continue; 1474 continue;
1496 } 1475 }
1497 /* Timed out, enter rebinding state */ 1476 /* Timed out, enter rebinding state */
@@ -1503,12 +1482,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1503 change_listen_mode(LISTEN_RAW); 1482 change_listen_mode(LISTEN_RAW);
1504 /* Lease is *really* about to run out, 1483 /* Lease is *really* about to run out,
1505 * try to find DHCP server using broadcast */ 1484 * try to find DHCP server using broadcast */
1506 if (timeout > 0) { 1485 if (lease_remaining > 0) {
1507 if (opt & OPT_l) 1486 if (opt & OPT_l)
1508 send_d6_info_request(xid); 1487 send_d6_info_request(xid);
1509 else /* send a broadcast renew request */ 1488 else /* send a broadcast renew request */
1510 send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); 1489 send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
1511 timeout >>= 1; 1490 timeout = discover_timeout;
1512 continue; 1491 continue;
1513 } 1492 }
1514 /* Timed out, enter init state */ 1493 /* Timed out, enter init state */
@@ -1516,7 +1495,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1516 d6_run_script_no_option("deconfig"); 1495 d6_run_script_no_option("deconfig");
1517 client_data.state = INIT_SELECTING; 1496 client_data.state = INIT_SELECTING;
1518 client_data.first_secs = 0; /* make secs field count from 0 */ 1497 client_data.first_secs = 0; /* make secs field count from 0 */
1519 /*timeout = 0; - already is */ 1498 timeout = 0;
1520 packet_num = 0; 1499 packet_num = 0;
1521 continue; 1500 continue;
1522 /* case RELEASED: */ 1501 /* case RELEASED: */
@@ -1532,22 +1511,26 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1532 switch (udhcp_sp_read()) { 1511 switch (udhcp_sp_read()) {
1533 case SIGUSR1: 1512 case SIGUSR1:
1534 client_data.first_secs = 0; /* make secs field count from 0 */ 1513 client_data.first_secs = 0; /* make secs field count from 0 */
1535 already_waited_sec = 0; 1514 bb_simple_info_msg("performing DHCP renew");
1536 perform_renew(); 1515
1537 if (client_data.state == RENEW_REQUESTED) { 1516 switch (client_data.state) {
1538 /* We might be either on the same network 1517 /* Try to renew/rebind */
1539 * (in which case renew might work), 1518 case BOUND:
1540 * or we might be on a completely different one 1519 case RENEWING:
1541 * (in which case renew won't ever succeed). 1520 case REBINDING:
1542 * For the second case, must make sure timeout 1521 change_listen_mode(LISTEN_KERNEL);
1543 * is not too big, or else we can send 1522 client_data.state = RENEW_REQUESTED;
1544 * futile renew requests for hours.
1545 */
1546 if (timeout > 60)
1547 timeout = 60;
1548 goto case_RENEW_REQUESTED; 1523 goto case_RENEW_REQUESTED;
1549 } 1524
1550 /* Start things over */ 1525 /* Start things over */
1526 case RENEW_REQUESTED: /* two or more SIGUSR1 received */
1527 d6_run_script_no_option("deconfig");
1528 /* case REQUESTING: break; */
1529 /* case RELEASED: break; */
1530 /* case INIT_SELECTING: break; */
1531 }
1532 change_listen_mode(LISTEN_RAW);
1533 client_data.state = INIT_SELECTING;
1551 packet_num = 0; 1534 packet_num = 0;
1552 /* Kill any timeouts, user wants this to hurry along */ 1535 /* Kill any timeouts, user wants this to hurry along */
1553 timeout = 0; 1536 timeout = 0;
@@ -1579,10 +1562,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1579 sleep(discover_timeout); /* 3 seconds by default */ 1562 sleep(discover_timeout); /* 3 seconds by default */
1580 change_listen_mode(client_data.listen_mode); /* just close and reopen */ 1563 change_listen_mode(client_data.listen_mode); /* just close and reopen */
1581 } 1564 }
1582 /* If this packet will turn out to be unrelated/bogus,
1583 * we will go back and wait for next one.
1584 * Be sure timeout is properly decreased. */
1585 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1586 if (len < 0) 1565 if (len < 0)
1587 continue; 1566 continue;
1588 packet_end = (uint8_t*)&packet + len; 1567 packet_end = (uint8_t*)&packet + len;
@@ -1609,6 +1588,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1609 case RENEW_REQUESTED: 1588 case RENEW_REQUESTED:
1610 case REBINDING: 1589 case REBINDING:
1611 if (packet.d6_msg_type == D6_MSG_REPLY) { 1590 if (packet.d6_msg_type == D6_MSG_REPLY) {
1591 unsigned start;
1612 uint32_t lease_seconds; 1592 uint32_t lease_seconds;
1613 struct d6_option *option; 1593 struct d6_option *option;
1614 unsigned address_timeout; 1594 unsigned address_timeout;
@@ -1631,7 +1611,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1631 requested_ipv6 = NULL; 1611 requested_ipv6 = NULL;
1632 timeout = 0; 1612 timeout = 0;
1633 packet_num = 0; 1613 packet_num = 0;
1634 already_waited_sec = 0;
1635 continue; 1614 continue;
1636 } 1615 }
1637 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID); 1616 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID);
@@ -1650,7 +1629,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1650 client_data.state = REQUESTING; 1629 client_data.state = REQUESTING;
1651 timeout = 0; 1630 timeout = 0;
1652 packet_num = 0; 1631 packet_num = 0;
1653 already_waited_sec = 0;
1654 continue; 1632 continue;
1655 } 1633 }
1656 /* It's a D6_MSG_REPLY */ 1634 /* It's a D6_MSG_REPLY */
@@ -1814,21 +1792,26 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1814 address_timeout = prefix_timeout; 1792 address_timeout = prefix_timeout;
1815 if (!prefix_timeout) 1793 if (!prefix_timeout)
1816 prefix_timeout = address_timeout; 1794 prefix_timeout = address_timeout;
1817 /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ 1795 lease_remaining = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout);
1818 timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; 1796 if (lease_remaining < 0) /* signed overflow? */
1797 lease_remaining = INT_MAX;
1819 if (opt & OPT_l) { 1798 if (opt & OPT_l) {
1820 /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32) 1799 /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32)
1821 * and use its value instead of the default 1 day. 1800 * and use its value instead of the default 1 day.
1822 */ 1801 */
1823 timeout = 24 * 60 * 60; 1802 lease_remaining = 24 * 60 * 60;
1824 } 1803 }
1825 /* paranoia: must not be too small */ 1804 /* paranoia: must not be too small */
1826 /* timeout > 60 - ensures at least one unicast renew attempt */ 1805 if (lease_remaining < 30)
1827 if (timeout < 61) 1806 lease_remaining = 30;
1828 timeout = 61; 1807
1829 /* enter bound state */ 1808 /* enter bound state */
1809 start = monotonic_sec();
1830 d6_run_script(packet.d6_options, packet_end, 1810 d6_run_script(packet.d6_options, packet_end,
1831 (client_data.state == REQUESTING ? "bound" : "renew")); 1811 (client_data.state == REQUESTING ? "bound" : "renew"));
1812 timeout = (unsigned)lease_remaining / 2;
1813 timeout -= (unsigned)monotonic_sec() - start;
1814 packet_num = 0;
1832 1815
1833 client_data.state = BOUND; 1816 client_data.state = BOUND;
1834 change_listen_mode(LISTEN_NONE); 1817 change_listen_mode(LISTEN_NONE);
@@ -1844,7 +1827,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1844 opt = ((opt & ~OPT_b) | OPT_f); 1827 opt = ((opt & ~OPT_b) | OPT_f);
1845 } 1828 }
1846#endif 1829#endif
1847 already_waited_sec = 0;
1848 continue; /* back to main loop */ 1830 continue; /* back to main loop */
1849 } 1831 }
1850 continue; 1832 continue;
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index bbcbd1fca..6666cbce6 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1027,7 +1027,6 @@ static int udhcp_raw_socket(int ifindex)
1027 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) 1027 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them)
1028 * ETH_P_IP: want to receive only packets with IPv4 eth type 1028 * ETH_P_IP: want to receive only packets with IPv4 eth type
1029 */ 1029 */
1030 log3("got raw socket fd %d", fd);
1031 1030
1032 memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ 1031 memset(&sock, 0, sizeof(sock)); /* let's be deterministic */
1033 sock.sll_family = AF_PACKET; 1032 sock.sll_family = AF_PACKET;
@@ -1122,29 +1121,6 @@ static void change_listen_mode(int new_mode)
1122 /* else LISTEN_NONE: client_data.sockfd stays closed */ 1121 /* else LISTEN_NONE: client_data.sockfd stays closed */
1123} 1122}
1124 1123
1125/* Called only on SIGUSR1 */
1126static void perform_renew(void)
1127{
1128 bb_simple_info_msg("performing DHCP renew");
1129 switch (client_data.state) {
1130 case BOUND:
1131 change_listen_mode(LISTEN_KERNEL);
1132 case RENEWING:
1133 case REBINDING:
1134 client_data.state = RENEW_REQUESTED;
1135 break;
1136 case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
1137 udhcp_run_script(NULL, "deconfig");
1138 case REQUESTING:
1139 case RELEASED:
1140 change_listen_mode(LISTEN_RAW);
1141 client_data.state = INIT_SELECTING;
1142 break;
1143 case INIT_SELECTING:
1144 break;
1145 }
1146}
1147
1148static void perform_release(uint32_t server_addr, uint32_t requested_ip) 1124static void perform_release(uint32_t server_addr, uint32_t requested_ip)
1149{ 1125{
1150 char buffer[sizeof("255.255.255.255")]; 1126 char buffer[sizeof("255.255.255.255")];
@@ -1247,7 +1223,6 @@ static void client_background(void)
1247//usage: "\n USR1 Renew lease" 1223//usage: "\n USR1 Renew lease"
1248//usage: "\n USR2 Release lease" 1224//usage: "\n USR2 Release lease"
1249 1225
1250
1251int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1226int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1252int udhcpc_main(int argc UNUSED_PARAM, char **argv) 1227int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1253{ 1228{
@@ -1266,7 +1241,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1266 uint32_t xid = xid; /* for compiler */ 1241 uint32_t xid = xid; /* for compiler */
1267 int packet_num; 1242 int packet_num;
1268 int timeout; /* must be signed */ 1243 int timeout; /* must be signed */
1269 unsigned already_waited_sec; 1244 int lease_remaining; /* must be signed */
1270 unsigned opt; 1245 unsigned opt;
1271 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) 1246 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1272 int retval; 1247 int retval;
@@ -1411,18 +1386,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1411 change_listen_mode(LISTEN_RAW); 1386 change_listen_mode(LISTEN_RAW);
1412 packet_num = 0; 1387 packet_num = 0;
1413 timeout = 0; 1388 timeout = 0;
1414 already_waited_sec = 0; 1389 lease_remaining = 0;
1415 1390
1416 /* Main event loop. select() waits on signal pipe and possibly 1391 /* Main event loop. select() waits on signal pipe and possibly
1417 * on sockfd. 1392 * on sockfd.
1418 * "continue" statements in code below jump to the top of the loop. 1393 * "continue" statements in code below jump to the top of the loop.
1419 */ 1394 */
1420 for (;;) { 1395 for (;;) {
1421 int tv;
1422 struct pollfd pfds[2]; 1396 struct pollfd pfds[2];
1423 struct dhcp_packet packet; 1397 struct dhcp_packet packet;
1424 /* silence "uninitialized!" warning */
1425 unsigned timestamp_before_wait = timestamp_before_wait;
1426 1398
1427 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); 1399 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
1428 1400
@@ -1435,17 +1407,24 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1435 1407
1436 udhcp_sp_fd_set(pfds, client_data.sockfd); 1408 udhcp_sp_fd_set(pfds, client_data.sockfd);
1437 1409
1438 tv = timeout - already_waited_sec;
1439 retval = 0; 1410 retval = 0;
1440 /* If we already timed out, fall through with retval = 0, else... */ 1411 /* If we already timed out, fall through with retval = 0, else... */
1441 if (tv > 0) { 1412 if (timeout > 0) {
1442 log1("waiting %u seconds", tv); 1413 unsigned diff;
1443 timestamp_before_wait = (unsigned)monotonic_sec(); 1414
1444 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX); 1415 if (timeout > INT_MAX/1000)
1416 timeout = INT_MAX/1000;
1417 log1("waiting %u seconds", timeout);
1418 diff = (unsigned)monotonic_sec();
1419 retval = poll(pfds, 2, timeout * 1000);
1445 if (retval < 0) { 1420 if (retval < 0) {
1446 /* EINTR? A signal was caught, don't panic */ 1421 /* EINTR? A signal was caught, don't panic */
1447 if (errno == EINTR) { 1422 if (errno == EINTR) {
1448 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1423 diff = (unsigned)monotonic_sec() - diff;
1424 lease_remaining -= diff;
1425 if (lease_remaining < 0)
1426 lease_remaining = 0;
1427 timeout -= diff;
1449 continue; 1428 continue;
1450 } 1429 }
1451 /* Else: an error occurred, panic! */ 1430 /* Else: an error occurred, panic! */
@@ -1472,9 +1451,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1472 if (clientid_mac_ptr) 1451 if (clientid_mac_ptr)
1473 memcpy(clientid_mac_ptr, client_data.client_mac, 6); 1452 memcpy(clientid_mac_ptr, client_data.client_mac, 6);
1474 1453
1475 /* We will restart the wait in any case */
1476 already_waited_sec = 0;
1477
1478 switch (client_data.state) { 1454 switch (client_data.state) {
1479 case INIT_SELECTING: 1455 case INIT_SELECTING:
1480 if (!discover_retries || packet_num < discover_retries) { 1456 if (!discover_retries || packet_num < discover_retries) {
@@ -1536,7 +1512,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1536 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1512 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1537 case_RENEW_REQUESTED: 1513 case_RENEW_REQUESTED:
1538 case RENEWING: 1514 case RENEWING:
1539 if (timeout >= 60) { 1515 if (packet_num < 3) {
1516 packet_num++;
1540 /* send an unicast renew request */ 1517 /* send an unicast renew request */
1541 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind 1518 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1542 * a new UDP socket for sending inside send_renew. 1519 * a new UDP socket for sending inside send_renew.
@@ -1547,14 +1524,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1547 * into INIT_SELECTING state. 1524 * into INIT_SELECTING state.
1548 */ 1525 */
1549 if (send_renew(xid, server_addr, requested_ip) >= 0) { 1526 if (send_renew(xid, server_addr, requested_ip) >= 0) {
1550 timeout >>= 1; 1527 timeout = discover_timeout;
1551//TODO: the timeout to receive an answer for our renew should not be selected 1528 /* ^^^ used to be = lease_remaining / 2 - WAY too long */
1552//with "timeout = lease_seconds / 2; ...; timeout = timeout / 2": it is often huge.
1553//Waiting e.g. 4*3600 seconds for a reply does not make sense
1554//(if reply isn't coming, we keep an open socket for hours),
1555//it should be something like 10 seconds.
1556//Also, it's probably best to try sending renew in kernel mode a few (3-5) times
1557//and fall back to raw mode if it does not work.
1558 continue; 1529 continue;
1559 } 1530 }
1560 /* else: error sending. 1531 /* else: error sending.
@@ -1563,6 +1534,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1563 * which wasn't reachable (and probably did not exist). 1534 * which wasn't reachable (and probably did not exist).
1564 */ 1535 */
1565 } 1536 }
1537//TODO: if 3 renew's failed (no reply) but remaining lease is large,
1538//it might make sense to make a large pause (~1 hour?) and try later?
1566 /* Timed out or error, enter rebinding state */ 1539 /* Timed out or error, enter rebinding state */
1567 log1s("entering rebinding state"); 1540 log1s("entering rebinding state");
1568 client_data.state = REBINDING; 1541 client_data.state = REBINDING;
@@ -1572,10 +1545,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1572 change_listen_mode(LISTEN_RAW); 1545 change_listen_mode(LISTEN_RAW);
1573 /* Lease is *really* about to run out, 1546 /* Lease is *really* about to run out,
1574 * try to find DHCP server using broadcast */ 1547 * try to find DHCP server using broadcast */
1575 if (timeout > 0) { 1548 if (lease_remaining > 0) {
1576 /* send a broadcast renew request */ 1549 /* send a broadcast renew request */
1577 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); 1550 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip);
1578 timeout >>= 1; 1551 timeout = discover_timeout;
1579 continue; 1552 continue;
1580 } 1553 }
1581 /* Timed out, enter init state */ 1554 /* Timed out, enter init state */
@@ -1583,7 +1556,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1583 udhcp_run_script(NULL, "deconfig"); 1556 udhcp_run_script(NULL, "deconfig");
1584 client_data.state = INIT_SELECTING; 1557 client_data.state = INIT_SELECTING;
1585 client_data.first_secs = 0; /* make secs field count from 0 */ 1558 client_data.first_secs = 0; /* make secs field count from 0 */
1586 /*timeout = 0; - already is */ 1559 timeout = 0;
1587 packet_num = 0; 1560 packet_num = 0;
1588 continue; 1561 continue;
1589 /* case RELEASED: */ 1562 /* case RELEASED: */
@@ -1599,22 +1572,26 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1599 switch (udhcp_sp_read()) { 1572 switch (udhcp_sp_read()) {
1600 case SIGUSR1: 1573 case SIGUSR1:
1601 client_data.first_secs = 0; /* make secs field count from 0 */ 1574 client_data.first_secs = 0; /* make secs field count from 0 */
1602 already_waited_sec = 0; 1575 bb_simple_info_msg("performing DHCP renew");
1603 perform_renew(); 1576
1604 if (client_data.state == RENEW_REQUESTED) { 1577 switch (client_data.state) {
1605 /* We might be either on the same network 1578 /* Try to renew/rebind */
1606 * (in which case renew might work), 1579 case BOUND:
1607 * or we might be on a completely different one 1580 case RENEWING:
1608 * (in which case renew won't ever succeed). 1581 case REBINDING:
1609 * For the second case, must make sure timeout 1582 change_listen_mode(LISTEN_KERNEL);
1610 * is not too big, or else we can send 1583 client_data.state = RENEW_REQUESTED;
1611 * futile renew requests for hours.
1612 */
1613 if (timeout > 60)
1614 timeout = 60;
1615 goto case_RENEW_REQUESTED; 1584 goto case_RENEW_REQUESTED;
1616 } 1585
1617 /* Start things over */ 1586 /* Start things over */
1587 case RENEW_REQUESTED: /* two or more SIGUSR1 received */
1588 udhcp_run_script(NULL, "deconfig");
1589 /* case REQUESTING: break; */
1590 /* case RELEASED: break; */
1591 /* case INIT_SELECTING: break; */
1592 }
1593 change_listen_mode(LISTEN_RAW);
1594 client_data.state = INIT_SELECTING;
1618 packet_num = 0; 1595 packet_num = 0;
1619 /* Kill any timeouts, user wants this to hurry along */ 1596 /* Kill any timeouts, user wants this to hurry along */
1620 timeout = 0; 1597 timeout = 0;
@@ -1646,10 +1623,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1646 sleep(discover_timeout); /* 3 seconds by default */ 1623 sleep(discover_timeout); /* 3 seconds by default */
1647 change_listen_mode(client_data.listen_mode); /* just close and reopen */ 1624 change_listen_mode(client_data.listen_mode); /* just close and reopen */
1648 } 1625 }
1649 /* If this packet will turn out to be unrelated/bogus,
1650 * we will go back and wait for next one.
1651 * Be sure timeout is properly decreased. */
1652 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1653 if (len < 0) 1626 if (len < 0)
1654 continue; 1627 continue;
1655 } 1628 }
@@ -1722,7 +1695,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1722 client_data.state = REQUESTING; 1695 client_data.state = REQUESTING;
1723 timeout = 0; 1696 timeout = 0;
1724 packet_num = 0; 1697 packet_num = 0;
1725 already_waited_sec = 0;
1726 } 1698 }
1727 continue; 1699 continue;
1728 case REQUESTING: 1700 case REQUESTING:
@@ -1731,28 +1703,38 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1731 case REBINDING: 1703 case REBINDING:
1732 if (*message == DHCPACK) { 1704 if (*message == DHCPACK) {
1733 unsigned start; 1705 unsigned start;
1734 uint32_t lease_seconds;
1735 struct in_addr temp_addr; 1706 struct in_addr temp_addr;
1736 char server_str[sizeof("255.255.255.255")]; 1707 char server_str[sizeof("255.255.255.255")];
1737 uint8_t *temp; 1708 uint8_t *temp;
1738 1709
1710 temp_addr.s_addr = server_addr;
1711 strcpy(server_str, inet_ntoa(temp_addr));
1712 temp_addr.s_addr = packet.yiaddr;
1713
1739 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); 1714 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
1740 if (!temp) { 1715 if (!temp) {
1741 bb_simple_info_msg("no lease time with ACK, using 1 hour lease"); 1716 lease_remaining = 60 * 60;
1742 lease_seconds = 60 * 60;
1743 } else { 1717 } else {
1718 uint32_t lease;
1744 /* it IS unaligned sometimes, don't "optimize" */ 1719 /* it IS unaligned sometimes, don't "optimize" */
1745 move_from_unaligned32(lease_seconds, temp); 1720 move_from_unaligned32(lease, temp);
1746 lease_seconds = ntohl(lease_seconds); 1721 lease_remaining = ntohl(lease);
1747 /* paranoia: must not be too small and not prone to overflows */
1748 /* timeout > 60 - ensures at least one unicast renew attempt */
1749 if (lease_seconds < 2 * 61)
1750 lease_seconds = 2 * 61;
1751 //if (lease_seconds > 0x7fffffff)
1752 // lease_seconds = 0x7fffffff;
1753 //^^^not necessary since "timeout = lease_seconds / 2"
1754 //does not overflow even for 0xffffffff.
1755 } 1722 }
1723 /* Log message _before_ we sanitize lease */
1724 bb_info_msg("lease of %s obtained from %s, lease time %u%s",
1725 inet_ntoa(temp_addr), server_str, (unsigned)lease_remaining,
1726 temp ? "" : " (default)"
1727 );
1728 /* paranoia: must not be too small and not prone to overflows */
1729 /* NB: 60s leases _are_ used in real world
1730 * (temporary IPs while ISP modem initializes)
1731 * do not break this case by bumping it up.
1732 */
1733 if (lease_remaining < 0) /* signed overflow? */
1734 lease_remaining = INT_MAX;
1735 if (lease_remaining < 30)
1736 lease_remaining = 30;
1737 requested_ip = packet.yiaddr;
1756#if ENABLE_FEATURE_UDHCPC_ARPING 1738#if ENABLE_FEATURE_UDHCPC_ARPING
1757 if (opt & OPT_a) { 1739 if (opt & OPT_a) {
1758/* RFC 2131 3.1 paragraph 5: 1740/* RFC 2131 3.1 paragraph 5:
@@ -1764,7 +1746,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1764 * address is already in use (e.g., through the use of ARP), 1746 * address is already in use (e.g., through the use of ARP),
1765 * the client MUST send a DHCPDECLINE message to the server and restarts 1747 * the client MUST send a DHCPDECLINE message to the server and restarts
1766 * the configuration process..." */ 1748 * the configuration process..." */
1767 if (!arpping(packet.yiaddr, 1749 if (!arpping(requested_ip,
1768 NULL, 1750 NULL,
1769 (uint32_t) 0, 1751 (uint32_t) 0,
1770 client_data.client_mac, 1752 client_data.client_mac,
@@ -1783,27 +1765,18 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1783 requested_ip = 0; 1765 requested_ip = 0;
1784 timeout = tryagain_timeout; 1766 timeout = tryagain_timeout;
1785 packet_num = 0; 1767 packet_num = 0;
1786 already_waited_sec = 0;
1787 continue; /* back to main loop */ 1768 continue; /* back to main loop */
1788 } 1769 }
1789 } 1770 }
1790#endif 1771#endif
1791 /* enter bound state */
1792 temp_addr.s_addr = server_addr;
1793 strcpy(server_str, inet_ntoa(temp_addr));
1794 temp_addr.s_addr = packet.yiaddr;
1795 bb_info_msg("lease of %s obtained from %s, lease time %u",
1796 inet_ntoa(temp_addr), server_str, (unsigned)lease_seconds);
1797 requested_ip = packet.yiaddr;
1798 1772
1773 /* enter bound state */
1799 start = monotonic_sec(); 1774 start = monotonic_sec();
1800 udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); 1775 udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
1801 already_waited_sec = (unsigned)monotonic_sec() - start; 1776 timeout = (unsigned)lease_remaining / 2;
1802 timeout = lease_seconds / 2; 1777//TODO: why / 2?
1803 if ((unsigned)timeout < already_waited_sec) { 1778 timeout -= (unsigned)monotonic_sec() - start;
1804 /* Something went wrong. Back to discover state */ 1779 packet_num = 0;
1805 timeout = already_waited_sec = 0;
1806 }
1807 1780
1808 client_data.state = BOUND; 1781 client_data.state = BOUND;
1809 change_listen_mode(LISTEN_NONE); 1782 change_listen_mode(LISTEN_NONE);
@@ -1856,7 +1829,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1856 requested_ip = 0; 1829 requested_ip = 0;
1857 timeout = 0; 1830 timeout = 0;
1858 packet_num = 0; 1831 packet_num = 0;
1859 already_waited_sec = 0;
1860 } 1832 }
1861 continue; 1833 continue;
1862 /* case BOUND: - ignore all packets */ 1834 /* case BOUND: - ignore all packets */
diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c
index 7df671245..774c4beee 100644
--- a/networking/udhcp/signalpipe.c
+++ b/networking/udhcp/signalpipe.c
@@ -65,7 +65,7 @@ void FAST_FUNC udhcp_sp_setup(void)
65/* Quick little function to setup the pfds. 65/* Quick little function to setup the pfds.
66 * Limited in that you can only pass one extra fd. 66 * Limited in that you can only pass one extra fd.
67 */ 67 */
68void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd) 68void FAST_FUNC udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd)
69{ 69{
70 pfds[0].fd = READ_FD; 70 pfds[0].fd = READ_FD;
71 pfds[0].events = POLLIN; 71 pfds[0].events = POLLIN;
diff --git a/networking/wget.c b/networking/wget.c
index 270eab141..a5369be22 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -25,6 +25,13 @@
25//config: default y 25//config: default y
26//config: depends on WGET 26//config: depends on WGET
27//config: 27//config:
28//config:config FEATURE_WGET_FTP
29//config: bool "Enable FTP protocol (+1k)"
30//config: default y
31//config: depends on WGET
32//config: help
33//config: To support FTPS, enable FEATURE_WGET_HTTPS as well.
34//config:
28//config:config FEATURE_WGET_AUTHENTICATION 35//config:config FEATURE_WGET_AUTHENTICATION
29//config: bool "Enable HTTP authentication" 36//config: bool "Enable HTTP authentication"
30//config: default y 37//config: default y
@@ -48,12 +55,12 @@
48//config: 55//config:
49//config:config FEATURE_WGET_HTTPS 56//config:config FEATURE_WGET_HTTPS
50//config: bool "Support HTTPS using internal TLS code" 57//config: bool "Support HTTPS using internal TLS code"
51//it also enables FTPS support, but it's not well tested yet
52//config: default y 58//config: default y
53//config: depends on WGET 59//config: depends on WGET
54//config: select TLS 60//config: select TLS
55//config: help 61//config: help
56//config: wget will use internal TLS code to connect to https:// URLs. 62//config: wget will use internal TLS code to connect to https:// URLs.
63//config: It also enables FTPS support, but it's not well tested yet.
57//config: Note: 64//config: Note:
58//config: On NOMMU machines, ssl_helper applet should be available 65//config: On NOMMU machines, ssl_helper applet should be available
59//config: in the $PATH for this to work. Make sure to select that applet. 66//config: in the $PATH for this to work. Make sure to select that applet.
@@ -173,6 +180,7 @@
173 180
174 181
175#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS) 182#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS)
183#define FTPS_SUPPORTED (ENABLE_FEATURE_WGET_FTP && ENABLE_FEATURE_WGET_HTTPS)
176 184
177struct host_info { 185struct host_info {
178 char *allocated; 186 char *allocated;
@@ -182,14 +190,16 @@ struct host_info {
182 char *host; 190 char *host;
183 int port; 191 int port;
184}; 192};
185static const char P_FTP[] ALIGN1 = "ftp";
186static const char P_HTTP[] ALIGN1 = "http"; 193static const char P_HTTP[] ALIGN1 = "http";
187#if SSL_SUPPORTED 194#if SSL_SUPPORTED
188# if ENABLE_FEATURE_WGET_HTTPS
189static const char P_FTPS[] ALIGN1 = "ftps";
190# endif
191static const char P_HTTPS[] ALIGN1 = "https"; 195static const char P_HTTPS[] ALIGN1 = "https";
192#endif 196#endif
197#if ENABLE_FEATURE_WGET_FTP
198static const char P_FTP[] ALIGN1 = "ftp";
199#endif
200#if FTPS_SUPPORTED
201static const char P_FTPS[] ALIGN1 = "ftps";
202#endif
193 203
194#if ENABLE_FEATURE_WGET_LONG_OPTIONS 204#if ENABLE_FEATURE_WGET_LONG_OPTIONS
195/* User-specified headers prevent using our corresponding built-in headers. */ 205/* User-specified headers prevent using our corresponding built-in headers. */
@@ -482,6 +492,7 @@ static char fgets_trim_sanitize(FILE *fp, const char *fmt)
482 return c; 492 return c;
483} 493}
484 494
495#if ENABLE_FEATURE_WGET_FTP
485static int ftpcmd(const char *s1, const char *s2, FILE *fp) 496static int ftpcmd(const char *s1, const char *s2, FILE *fp)
486{ 497{
487 int result; 498 int result;
@@ -513,6 +524,7 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
513 G.wget_buf[3] = ' '; 524 G.wget_buf[3] = ' ';
514 return result; 525 return result;
515} 526}
527#endif
516 528
517static void parse_url(const char *src_url, struct host_info *h) 529static void parse_url(const char *src_url, struct host_info *h)
518{ 530{
@@ -521,30 +533,31 @@ static void parse_url(const char *src_url, struct host_info *h)
521 free(h->allocated); 533 free(h->allocated);
522 h->allocated = url = xstrdup(src_url); 534 h->allocated = url = xstrdup(src_url);
523 535
524 h->protocol = P_FTP; 536 h->protocol = P_HTTP;
525 p = strstr(url, "://"); 537 p = strstr(url, "://");
526 if (p) { 538 if (p) {
527 *p = '\0'; 539 *p = '\0';
528 h->host = p + 3; 540 h->host = p + 3;
541#if ENABLE_FEATURE_WGET_FTP
529 if (strcmp(url, P_FTP) == 0) { 542 if (strcmp(url, P_FTP) == 0) {
530 h->port = bb_lookup_std_port(P_FTP, "tcp", 21); 543 h->port = bb_lookup_std_port(P_FTP, "tcp", 21);
544 h->protocol = P_FTP;
531 } else 545 } else
532#if SSL_SUPPORTED 546#endif
533# if ENABLE_FEATURE_WGET_HTTPS 547#if FTPS_SUPPORTED
534 if (strcmp(url, P_FTPS) == 0) { 548 if (strcmp(url, P_FTPS) == 0) {
535 h->port = bb_lookup_std_port(P_FTPS, "tcp", 990); 549 h->port = bb_lookup_std_port(P_FTPS, "tcp", 990);
536 h->protocol = P_FTPS; 550 h->protocol = P_FTPS;
537 } else 551 } else
538# endif 552#endif
553#if SSL_SUPPORTED
539 if (strcmp(url, P_HTTPS) == 0) { 554 if (strcmp(url, P_HTTPS) == 0) {
540 h->port = bb_lookup_std_port(P_HTTPS, "tcp", 443); 555 h->port = bb_lookup_std_port(P_HTTPS, "tcp", 443);
541 h->protocol = P_HTTPS; 556 h->protocol = P_HTTPS;
542 } else 557 } else
543#endif 558#endif
544 if (strcmp(url, P_HTTP) == 0) { 559 if (strcmp(url, P_HTTP) == 0) {
545 http: 560 goto http;
546 h->port = bb_lookup_std_port(P_HTTP, "tcp", 80);
547 h->protocol = P_HTTP;
548 } else { 561 } else {
549 *p = ':'; 562 *p = ':';
550 bb_error_msg_and_die("not an http or ftp url: %s", url); 563 bb_error_msg_and_die("not an http or ftp url: %s", url);
@@ -552,7 +565,8 @@ static void parse_url(const char *src_url, struct host_info *h)
552 } else { 565 } else {
553 // GNU wget is user-friendly and falls back to http:// 566 // GNU wget is user-friendly and falls back to http://
554 h->host = url; 567 h->host = url;
555 goto http; 568 http:
569 h->port = bb_lookup_std_port(P_HTTP, "tcp", 80);
556 } 570 }
557 571
558 // FYI: 572 // FYI:
@@ -829,6 +843,7 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags)
829# endif 843# endif
830#endif 844#endif
831 845
846#if ENABLE_FEATURE_WGET_FTP
832static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) 847static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa)
833{ 848{
834 FILE *sfp; 849 FILE *sfp;
@@ -836,7 +851,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
836 int port; 851 int port;
837 852
838 sfp = open_socket(lsa); 853 sfp = open_socket(lsa);
839#if ENABLE_FEATURE_WGET_HTTPS 854#if FTPS_SUPPORTED
840 if (target->protocol == P_FTPS) 855 if (target->protocol == P_FTPS)
841 spawn_ssl_client(target->host, fileno(sfp), TLSLOOP_EXIT_ON_LOCAL_EOF); 856 spawn_ssl_client(target->host, fileno(sfp), TLSLOOP_EXIT_ON_LOCAL_EOF);
842#endif 857#endif
@@ -892,7 +907,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
892 907
893 *dfpp = open_socket(lsa); 908 *dfpp = open_socket(lsa);
894 909
895#if ENABLE_FEATURE_WGET_HTTPS 910#if FTPS_SUPPORTED
896 if (target->protocol == P_FTPS) { 911 if (target->protocol == P_FTPS) {
897 /* "PROT P" enables encryption of data stream. 912 /* "PROT P" enables encryption of data stream.
898 * Without it (or with "PROT C"), data is sent unencrypted. 913 * Without it (or with "PROT C"), data is sent unencrypted.
@@ -918,6 +933,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
918 933
919 return sfp; 934 return sfp;
920} 935}
936#endif
921 937
922static void NOINLINE retrieve_file_data(FILE *dfp) 938static void NOINLINE retrieve_file_data(FILE *dfp)
923{ 939{
@@ -1363,6 +1379,8 @@ However, in real world it was observed that some web servers
1363 case 301: 1379 case 301:
1364 case 302: 1380 case 302:
1365 case 303: 1381 case 303:
1382 case 307:
1383 case 308:
1366 break; 1384 break;
1367 1385
1368 case 206: /* Partial Content */ 1386 case 206: /* Partial Content */
@@ -1440,10 +1458,12 @@ However, in real world it was observed that some web servers
1440 /* For HTTP, data is pumped over the same connection */ 1458 /* For HTTP, data is pumped over the same connection */
1441 dfp = sfp; 1459 dfp = sfp;
1442 } else { 1460 } else {
1461#if ENABLE_FEATURE_WGET_FTP
1443 /* 1462 /*
1444 * FTP session 1463 * FTP session
1445 */ 1464 */
1446 sfp = prepare_ftp_session(&dfp, &target, lsa); 1465 sfp = prepare_ftp_session(&dfp, &target, lsa);
1466#endif
1447 } 1467 }
1448 1468
1449 free(lsa); 1469 free(lsa);
@@ -1461,6 +1481,7 @@ However, in real world it was observed that some web servers
1461 fprintf(stderr, "remote file exists\n"); 1481 fprintf(stderr, "remote file exists\n");
1462 } 1482 }
1463 1483
1484#if ENABLE_FEATURE_WGET_FTP
1464 if (dfp != sfp) { 1485 if (dfp != sfp) {
1465 /* It's ftp. Close data connection properly */ 1486 /* It's ftp. Close data connection properly */
1466 fclose(dfp); 1487 fclose(dfp);
@@ -1468,6 +1489,7 @@ However, in real world it was observed that some web servers
1468 bb_error_msg_and_die("ftp error: %s", G.wget_buf); 1489 bb_error_msg_and_die("ftp error: %s", G.wget_buf);
1469 /* ftpcmd("QUIT", NULL, sfp); - why bother? */ 1490 /* ftpcmd("QUIT", NULL, sfp); - why bother? */
1470 } 1491 }
1492#endif
1471 fclose(sfp); 1493 fclose(sfp);
1472 1494
1473 free(server.allocated); 1495 free(server.allocated);