diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-10-18 12:54:39 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-10-18 12:54:39 +0000 |
commit | f74194e942b7a65117914ecc9ddb62d9b1cc9e82 (patch) | |
tree | 58799a5cb03d0904e26abef1aa8531b925d80cd6 | |
parent | 03630784374501baa4d6a81144e54aa7601f5e19 (diff) | |
download | busybox-w32-f74194e942b7a65117914ecc9ddb62d9b1cc9e82.tar.gz busybox-w32-f74194e942b7a65117914ecc9ddb62d9b1cc9e82.tar.bz2 busybox-w32-f74194e942b7a65117914ecc9ddb62d9b1cc9e82.zip |
xatonum.h: add comment
lineedit: fix typo in comment
httpd: support for proxying connection to other http server
(by Alex Landau <landau_alex@yahoo.com>)
-rw-r--r-- | include/xatonum.h | 13 | ||||
-rw-r--r-- | libbb/lineedit.c | 2 | ||||
-rw-r--r-- | networking/Config.in | 12 | ||||
-rw-r--r-- | networking/httpd.c | 264 |
4 files changed, 225 insertions, 66 deletions
diff --git a/include/xatonum.h b/include/xatonum.h index 387545518..49ddced50 100644 --- a/include/xatonum.h +++ b/include/xatonum.h | |||
@@ -105,7 +105,18 @@ static ALWAYS_INLINE uint32_t xatou32(const char *numstr) | |||
105 | return BUG_xatou32_unimplemented(); | 105 | return BUG_xatou32_unimplemented(); |
106 | } | 106 | } |
107 | 107 | ||
108 | /* Non-aborting kind of convertors */ | 108 | /* Non-aborting kind of convertors: bb_strto[u][l]l */ |
109 | |||
110 | /* On exit: errno = 0 only if there was non-empty, '\0' terminated value | ||
111 | * errno = EINVAL if value was not '\0' terminated, but othervise ok | ||
112 | * Return value is still valid, caller should just check whether end[0] | ||
113 | * is a valid terminating char for particular case. OTOH, if caller | ||
114 | * requires '\0' terminated input, [s]he can just check errno == 0. | ||
115 | * errno = ERANGE if value had alphanumeric terminating char ("1234abcg"). | ||
116 | * errno = ERANGE if value is out of range, missing, etc. | ||
117 | * errno = ERANGE if value had minus sign for strtouXX (even "-0" is not ok ) | ||
118 | * return value is all-ones in this case. | ||
119 | */ | ||
109 | 120 | ||
110 | unsigned long long bb_strtoull(const char *arg, char **endp, int base); | 121 | unsigned long long bb_strtoull(const char *arg, char **endp, int base); |
111 | long long bb_strtoll(const char *arg, char **endp, int base); | 122 | long long bb_strtoll(const char *arg, char **endp, int base); |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index ccf8ac52d..c44a22843 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -658,7 +658,7 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
658 | j = pos_buf[i] + 1; | 658 | j = pos_buf[i] + 1; |
659 | } | 659 | } |
660 | matchBuf[c] = 0; | 660 | matchBuf[c] = 0; |
661 | /* old lenght matchBuf with quotes symbols */ | 661 | /* old length matchBuf with quotes symbols */ |
662 | *len_with_quotes = j ? j - pos_buf[0] : 0; | 662 | *len_with_quotes = j ? j - pos_buf[0] : 0; |
663 | 663 | ||
664 | return command_mode; | 664 | return command_mode; |
diff --git a/networking/Config.in b/networking/Config.in index 030b1c0de..bd6c6ef7a 100644 --- a/networking/Config.in +++ b/networking/Config.in | |||
@@ -192,6 +192,18 @@ config FEATURE_HTTPD_ERROR_PAGES | |||
192 | '/path/e404.html' file instead of the terse '404 NOT FOUND' | 192 | '/path/e404.html' file instead of the terse '404 NOT FOUND' |
193 | message. | 193 | message. |
194 | 194 | ||
195 | config FEATURE_HTTPD_PROXY | ||
196 | bool "Enable support for reverse proxy" | ||
197 | default n | ||
198 | depends on HTTPD | ||
199 | help | ||
200 | This option allows you to define URLs that will be forwarded | ||
201 | to another HTTP server. To setup add the following line to the | ||
202 | configuration file | ||
203 | P:/url/:http://hostname[:port]/new/path/ | ||
204 | Then a request to /url/myfile will be forwarded to | ||
205 | http://hostname[:port]/new/path/myfile. | ||
206 | |||
195 | config IFCONFIG | 207 | config IFCONFIG |
196 | bool "ifconfig" | 208 | bool "ifconfig" |
197 | default n | 209 | default n |
diff --git a/networking/httpd.c b/networking/httpd.c index 920702141..af1f61d2d 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -43,6 +43,11 @@ | |||
43 | * A:127.0.0.1 # Allow local loopback connections | 43 | * A:127.0.0.1 # Allow local loopback connections |
44 | * D:* # Deny from other IP connections | 44 | * D:* # Deny from other IP connections |
45 | * E404:/path/e404.html # /path/e404.html is the 404 (not found) error page | 45 | * E404:/path/e404.html # /path/e404.html is the 404 (not found) error page |
46 | * | ||
47 | * P:/url:[http://]hostname[:port]/new/path | ||
48 | * # When /urlXXXXXX is requested, reverse proxy | ||
49 | * # it to http://hostname[:port]/new/pathXXXXXX | ||
50 | * | ||
46 | * /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/ | 51 | * /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/ |
47 | * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/ | 52 | * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/ |
48 | * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/ | 53 | * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/ |
@@ -139,6 +144,14 @@ typedef struct Htaccess_IP { | |||
139 | int allow_deny; | 144 | int allow_deny; |
140 | } Htaccess_IP; | 145 | } Htaccess_IP; |
141 | 146 | ||
147 | /* Must have "next" as a first member */ | ||
148 | typedef struct Htaccess_Proxy { | ||
149 | struct Htaccess_Proxy *next; | ||
150 | char *url_from; | ||
151 | char *host_port; | ||
152 | char *url_to; | ||
153 | } Htaccess_Proxy; | ||
154 | |||
142 | enum { | 155 | enum { |
143 | HTTP_OK = 200, | 156 | HTTP_OK = 200, |
144 | HTTP_PARTIAL_CONTENT = 206, | 157 | HTTP_PARTIAL_CONTENT = 206, |
@@ -270,6 +283,9 @@ struct globals { | |||
270 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 283 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
271 | const char *http_error_page[ARRAY_SIZE(http_response_type)]; | 284 | const char *http_error_page[ARRAY_SIZE(http_response_type)]; |
272 | #endif | 285 | #endif |
286 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
287 | Htaccess_Proxy *proxy; | ||
288 | #endif | ||
273 | }; | 289 | }; |
274 | #define G (*ptr_to_globals) | 290 | #define G (*ptr_to_globals) |
275 | #define verbose (G.verbose ) | 291 | #define verbose (G.verbose ) |
@@ -301,6 +317,7 @@ struct globals { | |||
301 | #define hdr_ptr (G.hdr_ptr ) | 317 | #define hdr_ptr (G.hdr_ptr ) |
302 | #define hdr_cnt (G.hdr_cnt ) | 318 | #define hdr_cnt (G.hdr_cnt ) |
303 | #define http_error_page (G.http_error_page ) | 319 | #define http_error_page (G.http_error_page ) |
320 | #define proxy (G.proxy ) | ||
304 | #define INIT_G() do { \ | 321 | #define INIT_G() do { \ |
305 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ | 322 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ |
306 | USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ | 323 | USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ |
@@ -441,6 +458,7 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) | |||
441 | * [adAD]:from # ip address allow/deny, * for wildcard | 458 | * [adAD]:from # ip address allow/deny, * for wildcard |
442 | * /path:user:pass # username/password | 459 | * /path:user:pass # username/password |
443 | * Ennn:error.html # error page for status nnn | 460 | * Ennn:error.html # error page for status nnn |
461 | * P:/url:[http://]hostname[:port]/new/path # reverse proxy | ||
444 | * | 462 | * |
445 | * Any previous IP rules are discarded. | 463 | * Any previous IP rules are discarded. |
446 | * If the flag argument is not SUBDIR_PARSE then all /path and mime rules | 464 | * If the flag argument is not SUBDIR_PARSE then all /path and mime rules |
@@ -469,7 +487,7 @@ static void parse_conf(const char *path, int flag) | |||
469 | #endif | 487 | #endif |
470 | const char *cf = configFile; | 488 | const char *cf = configFile; |
471 | char buf[160]; | 489 | char buf[160]; |
472 | char *p0 = NULL; | 490 | char *p0; |
473 | char *c, *p; | 491 | char *c, *p; |
474 | Htaccess_IP *pip; | 492 | Htaccess_IP *pip; |
475 | 493 | ||
@@ -594,6 +612,42 @@ static void parse_conf(const char *path, int flag) | |||
594 | } | 612 | } |
595 | #endif | 613 | #endif |
596 | 614 | ||
615 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
616 | if (flag == FIRST_PARSE && *p0 == 'P') { | ||
617 | /* P:/url:[http://]hostname[:port]/new/path */ | ||
618 | char *url_from, *host_port, *url_to; | ||
619 | Htaccess_Proxy *proxy_entry; | ||
620 | |||
621 | url_from = c; | ||
622 | host_port = strchr(c, ':'); | ||
623 | if (host_port == NULL) { | ||
624 | bb_error_msg("config error '%s' in '%s'", buf, cf); | ||
625 | continue; | ||
626 | } | ||
627 | *host_port++ = '\0'; | ||
628 | if (strncmp(host_port, "http://", 7) == 0) | ||
629 | c += 7; | ||
630 | if (*host_port == '\0') { | ||
631 | bb_error_msg("config error '%s' in '%s'", buf, cf); | ||
632 | continue; | ||
633 | } | ||
634 | url_to = strchr(host_port, '/'); | ||
635 | if (url_to == NULL) { | ||
636 | bb_error_msg("config error '%s' in '%s'", buf, cf); | ||
637 | continue; | ||
638 | } | ||
639 | *url_to = '\0'; | ||
640 | proxy_entry = xzalloc(sizeof(Htaccess_Proxy)); | ||
641 | proxy_entry->url_from = xstrdup(url_from); | ||
642 | proxy_entry->host_port = xstrdup(host_port); | ||
643 | *url_to = '/'; | ||
644 | proxy_entry->url_to = xstrdup(url_to); | ||
645 | proxy_entry->next = proxy; | ||
646 | proxy = proxy_entry; | ||
647 | continue; | ||
648 | } | ||
649 | #endif | ||
650 | |||
597 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 651 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
598 | if (*p0 == '/') { | 652 | if (*p0 == '/') { |
599 | /* make full path from httpd root / current_path / config_line_path */ | 653 | /* make full path from httpd root / current_path / config_line_path */ |
@@ -639,62 +693,63 @@ static void parse_conf(const char *path, int flag) | |||
639 | || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 693 | || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
640 | /* storing current config line */ | 694 | /* storing current config line */ |
641 | cur = xzalloc(sizeof(Htaccess) + strlen(p0)); | 695 | cur = xzalloc(sizeof(Htaccess) + strlen(p0)); |
642 | if (cur) { | 696 | cf = strcpy(cur->before_colon, p0); |
643 | cf = strcpy(cur->before_colon, p0); | 697 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
644 | c = strchr(cf, ':'); | 698 | if (*p0 == '/') |
645 | *c++ = 0; | 699 | free(p0); |
646 | cur->after_colon = c; | 700 | #endif |
701 | c = strchr(cf, ':'); | ||
702 | *c++ = '\0'; | ||
703 | cur->after_colon = c; | ||
647 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 704 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
648 | if (*cf == '.') { | 705 | if (*cf == '.') { |
649 | /* config .mime line move top for overwrite previous */ | 706 | /* config .mime line move top for overwrite previous */ |
650 | cur->next = mime_a; | 707 | cur->next = mime_a; |
651 | mime_a = cur; | 708 | mime_a = cur; |
652 | continue; | 709 | continue; |
653 | } | 710 | } |
654 | #endif | 711 | #endif |
655 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 712 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
656 | if (*cf == '*' && cf[1] == '.') { | 713 | if (*cf == '*' && cf[1] == '.') { |
657 | /* config script interpreter line move top for overwrite previous */ | 714 | /* config script interpreter line move top for overwrite previous */ |
658 | cur->next = script_i; | 715 | cur->next = script_i; |
659 | script_i = cur; | 716 | script_i = cur; |
660 | continue; | 717 | continue; |
661 | } | 718 | } |
662 | #endif | 719 | #endif |
663 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 720 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
664 | free(p0); | 721 | if (prev == NULL) { |
665 | if (prev == NULL) { | 722 | /* first line */ |
666 | /* first line */ | 723 | g_auth = prev = cur; |
667 | g_auth = prev = cur; | 724 | } else { |
668 | } else { | 725 | /* sort path, if current length eq or bigger then move up */ |
669 | /* sort path, if current lenght eq or bigger then move up */ | 726 | Htaccess *prev_hti = g_auth; |
670 | Htaccess *prev_hti = g_auth; | 727 | size_t l = strlen(cf); |
671 | size_t l = strlen(cf); | 728 | Htaccess *hti; |
672 | Htaccess *hti; | 729 | |
673 | 730 | for (hti = prev_hti; hti; hti = hti->next) { | |
674 | for (hti = prev_hti; hti; hti = hti->next) { | 731 | if (l >= strlen(hti->before_colon)) { |
675 | if (l >= strlen(hti->before_colon)) { | 732 | /* insert before hti */ |
676 | /* insert before hti */ | 733 | cur->next = hti; |
677 | cur->next = hti; | 734 | if (prev_hti != hti) { |
678 | if (prev_hti != hti) { | 735 | prev_hti->next = cur; |
679 | prev_hti->next = cur; | 736 | } else { |
680 | } else { | 737 | /* insert as top */ |
681 | /* insert as top */ | 738 | g_auth = cur; |
682 | g_auth = cur; | ||
683 | } | ||
684 | break; | ||
685 | } | 739 | } |
686 | if (prev_hti != hti) | 740 | break; |
687 | prev_hti = prev_hti->next; | ||
688 | } | ||
689 | if (!hti) { /* not inserted, add to bottom */ | ||
690 | prev->next = cur; | ||
691 | prev = cur; | ||
692 | } | 741 | } |
742 | if (prev_hti != hti) | ||
743 | prev_hti = prev_hti->next; | ||
744 | } | ||
745 | if (!hti) { /* not inserted, add to bottom */ | ||
746 | prev->next = cur; | ||
747 | prev = cur; | ||
693 | } | 748 | } |
694 | #endif | ||
695 | } | 749 | } |
696 | #endif | 750 | #endif /* BASIC_AUTH */ |
697 | } | 751 | #endif /* BASIC_AUTH || MIME_TYPES || SCRIPT_INTERPR */ |
752 | } /* while (fgets) */ | ||
698 | fclose(f); | 753 | fclose(f); |
699 | } | 754 | } |
700 | 755 | ||
@@ -852,7 +907,7 @@ static void decodeBase64(char *Data) | |||
852 | */ | 907 | */ |
853 | static int openServer(void) | 908 | static int openServer(void) |
854 | { | 909 | { |
855 | int n = bb_strtou(bind_addr_or_port, NULL, 10); | 910 | unsigned n = bb_strtou(bind_addr_or_port, NULL, 10); |
856 | if (!errno && n && n <= 0xffff) | 911 | if (!errno && n && n <= 0xffff) |
857 | n = create_and_bind_stream_or_die(NULL, n); | 912 | n = create_and_bind_stream_or_die(NULL, n); |
858 | else | 913 | else |
@@ -1033,7 +1088,7 @@ static int get_line(void) | |||
1033 | return count; | 1088 | return count; |
1034 | } | 1089 | } |
1035 | 1090 | ||
1036 | #if ENABLE_FEATURE_HTTPD_CGI | 1091 | #if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY |
1037 | 1092 | ||
1038 | /* gcc 4.2.1 fares better with NOINLINE */ | 1093 | /* gcc 4.2.1 fares better with NOINLINE */ |
1039 | static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post_len) ATTRIBUTE_NORETURN; | 1094 | static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post_len) ATTRIBUTE_NORETURN; |
@@ -1207,6 +1262,9 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post | |||
1207 | } /* while (1) */ | 1262 | } /* while (1) */ |
1208 | log_and_exit(); | 1263 | log_and_exit(); |
1209 | } | 1264 | } |
1265 | #endif | ||
1266 | |||
1267 | #if ENABLE_FEATURE_HTTPD_CGI | ||
1210 | 1268 | ||
1211 | static void setenv1(const char *name, const char *value) | 1269 | static void setenv1(const char *name, const char *value) |
1212 | { | 1270 | { |
@@ -1655,6 +1713,18 @@ static int checkPerm(const char *path, const char *request) | |||
1655 | } | 1713 | } |
1656 | #endif /* FEATURE_HTTPD_BASIC_AUTH */ | 1714 | #endif /* FEATURE_HTTPD_BASIC_AUTH */ |
1657 | 1715 | ||
1716 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
1717 | static Htaccess_Proxy *find_proxy_entry(const char *url) | ||
1718 | { | ||
1719 | Htaccess_Proxy *p; | ||
1720 | for (p = proxy; p; p = p->next) { | ||
1721 | if (strncmp(url, p->url_from, strlen(p->url_from)) == 0) | ||
1722 | return p; | ||
1723 | } | ||
1724 | return NULL; | ||
1725 | } | ||
1726 | #endif | ||
1727 | |||
1658 | /* | 1728 | /* |
1659 | * Handle timeouts | 1729 | * Handle timeouts |
1660 | */ | 1730 | */ |
@@ -1676,13 +1746,22 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1676 | char *urlcopy; | 1746 | char *urlcopy; |
1677 | char *urlp; | 1747 | char *urlp; |
1678 | char *tptr; | 1748 | char *tptr; |
1679 | int http_major_version; | ||
1680 | int ip_allowed; | 1749 | int ip_allowed; |
1681 | #if ENABLE_FEATURE_HTTPD_CGI | 1750 | #if ENABLE_FEATURE_HTTPD_CGI |
1682 | const char *prequest; | 1751 | const char *prequest; |
1752 | char *cookie = NULL; | ||
1753 | char *content_type = NULL; | ||
1754 | unsigned long length = 0; | ||
1755 | #elif ENABLE_FEATURE_HTTPD_PROXY | ||
1756 | #define prequest request_GET | ||
1683 | unsigned long length = 0; | 1757 | unsigned long length = 0; |
1684 | char *cookie = 0; | 1758 | #endif |
1685 | char *content_type = 0; | 1759 | char http_major_version; |
1760 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
1761 | char http_minor_version; | ||
1762 | char *headers = headers; | ||
1763 | char *headers_ptr = headers_ptr; | ||
1764 | Htaccess_Proxy *proxy_entry; | ||
1686 | #endif | 1765 | #endif |
1687 | struct sigaction sa; | 1766 | struct sigaction sa; |
1688 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1767 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
@@ -1746,11 +1825,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1746 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1825 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1747 | 1826 | ||
1748 | /* Find end of URL and parse HTTP version, if any */ | 1827 | /* Find end of URL and parse HTTP version, if any */ |
1749 | http_major_version = -1; | 1828 | http_major_version = '0'; |
1829 | USE_FEATURE_HTTPD_PROXY(http_minor_version = '0';) | ||
1750 | tptr = strchrnul(urlp, ' '); | 1830 | tptr = strchrnul(urlp, ' '); |
1751 | /* Is it " HTTP/"? */ | 1831 | /* Is it " HTTP/"? */ |
1752 | if (tptr[0] && strncmp(tptr + 1, HTTP_200, 5) == 0) | 1832 | if (tptr[0] && strncmp(tptr + 1, HTTP_200, 5) == 0) { |
1753 | http_major_version = (tptr[6] - '0'); | 1833 | http_major_version = tptr[6]; |
1834 | USE_FEATURE_HTTPD_PROXY(http_minor_version = tptr[8];) | ||
1835 | } | ||
1754 | *tptr = '\0'; | 1836 | *tptr = '\0'; |
1755 | 1837 | ||
1756 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ | 1838 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ |
@@ -1761,8 +1843,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1761 | /* NB: urlcopy ptr is never changed after this */ | 1843 | /* NB: urlcopy ptr is never changed after this */ |
1762 | 1844 | ||
1763 | /* Extract url args if present */ | 1845 | /* Extract url args if present */ |
1764 | tptr = strchr(urlcopy, '?'); | ||
1765 | g_query = NULL; | 1846 | g_query = NULL; |
1847 | tptr = strchr(urlcopy, '?'); | ||
1766 | if (tptr) { | 1848 | if (tptr) { |
1767 | *tptr++ = '\0'; | 1849 | *tptr++ = '\0'; |
1768 | g_query = tptr; | 1850 | g_query = tptr; |
@@ -1830,7 +1912,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1830 | } | 1912 | } |
1831 | *tptr = '/'; | 1913 | *tptr = '/'; |
1832 | } | 1914 | } |
1833 | if (http_major_version >= 0) { | 1915 | |
1916 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
1917 | proxy_entry = find_proxy_entry(urlcopy); | ||
1918 | if (proxy_entry) | ||
1919 | headers = headers_ptr = xmalloc(IOBUF_SIZE); | ||
1920 | #endif | ||
1921 | |||
1922 | if (http_major_version >= '0') { | ||
1834 | /* Request was with "... HTTP/nXXX", and n >= 0 */ | 1923 | /* Request was with "... HTTP/nXXX", and n >= 0 */ |
1835 | 1924 | ||
1836 | /* Read until blank line for HTTP version specified, else parse immediate */ | 1925 | /* Read until blank line for HTTP version specified, else parse immediate */ |
@@ -1841,8 +1930,23 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1841 | if (DEBUG) | 1930 | if (DEBUG) |
1842 | bb_error_msg("header: '%s'", iobuf); | 1931 | bb_error_msg("header: '%s'", iobuf); |
1843 | 1932 | ||
1844 | #if ENABLE_FEATURE_HTTPD_CGI | 1933 | #if ENABLE_FEATURE_HTTPD_PROXY |
1845 | /* try and do our best to parse more lines */ | 1934 | /* We need 2 more bytes for yet another "\r\n" - |
1935 | * see fdprintf(proxy_fd...) further below */ | ||
1936 | if (proxy_entry && headers_ptr - headers < IOBUF_SIZE - 2) { | ||
1937 | int len = strlen(iobuf); | ||
1938 | if (len > IOBUF_SIZE - (headers_ptr - headers) - 4) | ||
1939 | len = IOBUF_SIZE - (headers_ptr - headers) - 4; | ||
1940 | memcpy(headers_ptr, iobuf, len); | ||
1941 | headers_ptr += len; | ||
1942 | headers_ptr[0] = '\r'; | ||
1943 | headers_ptr[1] = '\n'; | ||
1944 | headers_ptr += 2; | ||
1945 | } | ||
1946 | #endif | ||
1947 | |||
1948 | #if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY | ||
1949 | /* Try and do our best to parse more lines */ | ||
1846 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { | 1950 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { |
1847 | /* extra read only for POST */ | 1951 | /* extra read only for POST */ |
1848 | if (prequest != request_GET) { | 1952 | if (prequest != request_GET) { |
@@ -1858,7 +1962,10 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1858 | if (tptr[0] || errno || length > INT_MAX) | 1962 | if (tptr[0] || errno || length > INT_MAX) |
1859 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1963 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1860 | } | 1964 | } |
1861 | } else if (STRNCASECMP(iobuf, "Cookie:") == 0) { | 1965 | } |
1966 | #endif | ||
1967 | #if ENABLE_FEATURE_HTTPD_CGI | ||
1968 | else if (STRNCASECMP(iobuf, "Cookie:") == 0) { | ||
1862 | cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); | 1969 | cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); |
1863 | } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { | 1970 | } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { |
1864 | content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); | 1971 | content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); |
@@ -1885,7 +1992,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1885 | #endif /* FEATURE_HTTPD_BASIC_AUTH */ | 1992 | #endif /* FEATURE_HTTPD_BASIC_AUTH */ |
1886 | #if ENABLE_FEATURE_HTTPD_RANGES | 1993 | #if ENABLE_FEATURE_HTTPD_RANGES |
1887 | if (STRNCASECMP(iobuf, "Range:") == 0) { | 1994 | if (STRNCASECMP(iobuf, "Range:") == 0) { |
1888 | // We know only bytes=NNN-[MMM] | 1995 | /* We know only bytes=NNN-[MMM] */ |
1889 | char *s = skip_whitespace(iobuf + sizeof("Range:")-1); | 1996 | char *s = skip_whitespace(iobuf + sizeof("Range:")-1); |
1890 | if (strncmp(s, "bytes=", 6) == 0) { | 1997 | if (strncmp(s, "bytes=", 6) == 0) { |
1891 | s += sizeof("bytes=")-1; | 1998 | s += sizeof("bytes=")-1; |
@@ -1903,7 +2010,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1903 | } /* while extra header reading */ | 2010 | } /* while extra header reading */ |
1904 | } | 2011 | } |
1905 | 2012 | ||
1906 | /* We read headers, disable peer timeout */ | 2013 | /* We are done reading headers, disable peer timeout */ |
1907 | alarm(0); | 2014 | alarm(0); |
1908 | 2015 | ||
1909 | if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || ip_allowed == 0) { | 2016 | if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || ip_allowed == 0) { |
@@ -1921,6 +2028,35 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1921 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); | 2028 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); |
1922 | } | 2029 | } |
1923 | 2030 | ||
2031 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
2032 | if (proxy_entry != NULL) { | ||
2033 | int proxy_fd; | ||
2034 | len_and_sockaddr *lsa; | ||
2035 | |||
2036 | proxy_fd = socket(AF_INET, SOCK_STREAM, 0); | ||
2037 | if (proxy_fd < 0) | ||
2038 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2039 | lsa = host2sockaddr(proxy_entry->host_port, 80); | ||
2040 | if (lsa == NULL) | ||
2041 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2042 | if (connect(proxy_fd, &lsa->sa, lsa->len) < 0) | ||
2043 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2044 | fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n", | ||
2045 | prequest, /* GET or POST */ | ||
2046 | proxy_entry->url_to, /* url part 1 */ | ||
2047 | urlcopy + strlen(proxy_entry->url_from), /* url part 2 */ | ||
2048 | (g_query ? "?" : ""), /* "?" (maybe) */ | ||
2049 | (g_query ? g_query : ""), /* query string (maybe) */ | ||
2050 | http_major_version, http_minor_version); | ||
2051 | headers_ptr[0] = '\r'; | ||
2052 | headers_ptr[1] = '\n'; | ||
2053 | headers_ptr += 2; | ||
2054 | write(proxy_fd, headers, headers_ptr - headers); | ||
2055 | /* cgi_io_loop_and_exit needs to have two disctinct fds */ | ||
2056 | cgi_io_loop_and_exit(proxy_fd, dup(proxy_fd), length); | ||
2057 | } | ||
2058 | #endif | ||
2059 | |||
1924 | tptr = urlcopy + 1; /* skip first '/' */ | 2060 | tptr = urlcopy + 1; /* skip first '/' */ |
1925 | 2061 | ||
1926 | #if ENABLE_FEATURE_HTTPD_CGI | 2062 | #if ENABLE_FEATURE_HTTPD_CGI |
@@ -2211,7 +2347,7 @@ int httpd_main(int argc, char **argv) | |||
2211 | /* User can do it himself: 'env - PATH="$PATH" httpd' | 2347 | /* User can do it himself: 'env - PATH="$PATH" httpd' |
2212 | * We don't do it because we don't want to screw users | 2348 | * We don't do it because we don't want to screw users |
2213 | * which want to do | 2349 | * which want to do |
2214 | * 'env - VAR1=val1 VAR2=val2 https' | 2350 | * 'env - VAR1=val1 VAR2=val2 httpd' |
2215 | * and have VAR1 and VAR2 values visible in their CGIs. | 2351 | * and have VAR1 and VAR2 values visible in their CGIs. |
2216 | * Besides, it is also smaller. */ | 2352 | * Besides, it is also smaller. */ |
2217 | { | 2353 | { |