diff options
author | Ron Yorston <rmy@pobox.com> | 2021-05-14 08:17:12 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-05-14 08:17:12 +0100 |
commit | a3f5a1b7f4275f713acf22f534f95c0da8392e53 (patch) | |
tree | 49b65422a3e9c33f508da9ccf3ae79d324bd9e96 /networking | |
parent | 375cda9a88024135d630ca8990d9aff4ea414e89 (diff) | |
parent | 7de0ab21d939a5a304157f75918d0318a95261a3 (diff) | |
download | busybox-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.c | 1 | ||||
-rw-r--r-- | networking/httpd.c | 305 | ||||
-rw-r--r-- | networking/inetd.c | 2 | ||||
-rw-r--r-- | networking/ntpd.c | 109 | ||||
-rw-r--r-- | networking/tls.c | 120 | ||||
-rw-r--r-- | networking/tls.h | 13 | ||||
-rw-r--r-- | networking/tls_fe.c | 89 | ||||
-rw-r--r-- | networking/tls_fe.h | 7 | ||||
-rw-r--r-- | networking/tls_pstm.c | 8 | ||||
-rw-r--r-- | networking/tls_pstm_montgomery_reduce.c | 30 | ||||
-rw-r--r-- | networking/tls_rsa.c | 4 | ||||
-rw-r--r-- | networking/tls_sp_c32.c | 927 | ||||
-rw-r--r-- | networking/udhcp/common.c | 26 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 122 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 170 | ||||
-rw-r--r-- | networking/udhcp/signalpipe.c | 2 | ||||
-rw-r--r-- | networking/wget.c | 52 |
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 | ||
356 | typedef enum CGI_type { | ||
357 | CGI_NONE = 0, | ||
358 | CGI_NORMAL, | ||
359 | CGI_INDEX, | ||
360 | CGI_INTERPRETER, | ||
361 | } CGI_type; | ||
362 | |||
363 | enum { | 362 | enum { |
364 | HTTP_OK = 200, | 363 | HTTP_OK = 200, |
365 | HTTP_PARTIAL_CONTENT = 206, | 364 | HTTP_PARTIAL_CONTENT = 206, |
@@ -564,7 +563,6 @@ enum { | |||
564 | enum { | 563 | enum { |
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 | }; |
569 | static void send_file_and_exit(const char *url, int what) NORETURN; | 567 | static 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 | }; |
699 | static void parse_conf(const char *path, int flag) | 697 | static 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) | |||
2227 | static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN; | 2216 | static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN; |
2228 | static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | 2217 | static 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 | */ |
1700 | static uint32_t machtime(void) | 1700 | static 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 | |||
378 | enum { | 364 | enum { |
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 | ||
569 | static void | 554 | static void |
570 | d_to_tv(double d, struct timeval *tv) | 555 | d_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 | ||
576 | static double | 561 | static NOINLINE double |
577 | lfp_to_d(l_fixedpt_t lfp) | 562 | lfp_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 | } |
585 | static double | 570 | static NOINLINE double |
586 | sfp_to_d(s_fixedpt_t sfp) | 571 | sfp_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 |
595 | static l_fixedpt_t | 580 | static NOINLINE void |
596 | d_to_lfp(double d) | 581 | d_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 | } |
605 | static s_fixedpt_t | 590 | static NOINLINE void |
606 | d_to_sfp(double d) | 591 | d_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 | ||
272 | struct record_hdr { | 274 | struct 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 | |||
113 | void curve_x25519_compute_pubkey_and_premaster( | ||
114 | uint8_t *pubkey32, uint8_t *premaster32, | ||
115 | const uint8_t *peerkey32) FAST_FUNC; | ||
116 | |||
117 | void 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 | ||
66 | static void fe_select(byte *dst, | 66 | static 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 |
109 | static int prime_msb(const byte *p) | 109 | static 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 */ |
476 | static void xc_diffadd(byte *x5, byte *z5, | 476 | static 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 */ |
518 | static void xc_double(byte *x3, byte *z3, | 518 | static 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 | ||
547 | void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q) | 547 | static 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 | |||
614 | void 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 | ||
7 | void 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 \ |
66 | asm( \ | 67 | asm( \ |
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 \ | ||
87 | asm( \ | ||
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 \ |
79 | asm( \ | 103 | asm( \ |
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) |
16 | static //bbox | 16 | static //bbox |
17 | int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out, | 17 | int32 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) |
61 | static //bbox | 61 | static //bbox |
62 | int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen, | 62 | int32 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__) | ||
14 | static 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 | ||
29 | typedef 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 | |||
60 | typedef 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. */ | ||
68 | static 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 | */ | ||
81 | static 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 | */ | ||
115 | static 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. */ | ||
139 | static 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 | */ | ||
155 | static 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 | */ | ||
171 | static 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. */ | ||
177 | static 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) */ | ||
187 | static 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) */ | ||
195 | static 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. */ | ||
203 | static 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) */ | ||
212 | static 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) */ | ||
227 | static 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) */ | ||
252 | static 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) */ | ||
279 | static 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) */ | ||
288 | static 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) */ | ||
299 | static 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) */ | ||
309 | static 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) */ | ||
319 | static 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. */ | ||
334 | static 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 | */ | ||
358 | static 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 | */ | ||
401 | static 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 | */ | ||
415 | static 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. */ | ||
430 | static 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 | ||
440 | static 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 | */ | ||
460 | static 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 | */ | ||
585 | static 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 | */ | ||
622 | static 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 | */ | ||
680 | static 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 | */ | ||
759 | static 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 | */ | ||
812 | static 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 | */ | ||
839 | static 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) */ | ||
862 | static void sp_256_add_one_10(sp_digit* a) | ||
863 | { | ||
864 | a[0]++; | ||
865 | sp_256_norm_10(a); | ||
866 | } | ||
867 | static 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. */ | ||
902 | static 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 | |||
914 | void 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 */ | ||
1091 | static 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 | |||
1113 | static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | 1089 | static 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 */ | ||
1126 | static 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 | |||
1148 | static void perform_release(uint32_t server_addr, uint32_t requested_ip) | 1124 | static 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 | |||
1251 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1226 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1252 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) | 1227 | int 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 | */ |
68 | void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd) | 68 | void 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 | ||
177 | struct host_info { | 185 | struct 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 | }; |
185 | static const char P_FTP[] ALIGN1 = "ftp"; | ||
186 | static const char P_HTTP[] ALIGN1 = "http"; | 193 | static const char P_HTTP[] ALIGN1 = "http"; |
187 | #if SSL_SUPPORTED | 194 | #if SSL_SUPPORTED |
188 | # if ENABLE_FEATURE_WGET_HTTPS | ||
189 | static const char P_FTPS[] ALIGN1 = "ftps"; | ||
190 | # endif | ||
191 | static const char P_HTTPS[] ALIGN1 = "https"; | 195 | static const char P_HTTPS[] ALIGN1 = "https"; |
192 | #endif | 196 | #endif |
197 | #if ENABLE_FEATURE_WGET_FTP | ||
198 | static const char P_FTP[] ALIGN1 = "ftp"; | ||
199 | #endif | ||
200 | #if FTPS_SUPPORTED | ||
201 | static 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 | ||
485 | static int ftpcmd(const char *s1, const char *s2, FILE *fp) | 496 | static 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 | ||
517 | static void parse_url(const char *src_url, struct host_info *h) | 529 | static 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 | ||
832 | static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) | 847 | static 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 | ||
922 | static void NOINLINE retrieve_file_data(FILE *dfp) | 938 | static 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); |