aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-10-18 12:54:39 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-10-18 12:54:39 +0000
commitf74194e942b7a65117914ecc9ddb62d9b1cc9e82 (patch)
tree58799a5cb03d0904e26abef1aa8531b925d80cd6
parent03630784374501baa4d6a81144e54aa7601f5e19 (diff)
downloadbusybox-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.h13
-rw-r--r--libbb/lineedit.c2
-rw-r--r--networking/Config.in12
-rw-r--r--networking/httpd.c264
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
110unsigned long long bb_strtoull(const char *arg, char **endp, int base); 121unsigned long long bb_strtoull(const char *arg, char **endp, int base);
111long long bb_strtoll(const char *arg, char **endp, int base); 122long 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
195config 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
195config IFCONFIG 207config 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 */
148typedef struct Htaccess_Proxy {
149 struct Htaccess_Proxy *next;
150 char *url_from;
151 char *host_port;
152 char *url_to;
153} Htaccess_Proxy;
154
142enum { 155enum {
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 */
853static int openServer(void) 908static 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 */
1039static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post_len) ATTRIBUTE_NORETURN; 1094static 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
1211static void setenv1(const char *name, const char *value) 1269static 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
1717static 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 {