aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/httpd.c135
1 files changed, 133 insertions, 2 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index 1757e09c9..7e1c187a5 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -229,7 +229,12 @@
229//usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" 229//usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING"
230//usage:#define httpd_full_usage "\n\n" 230//usage:#define httpd_full_usage "\n\n"
231//usage: "Listen for incoming HTTP requests\n" 231//usage: "Listen for incoming HTTP requests\n"
232//usage: IF_NOT_PLATFORM_MINGW32(
232//usage: "\n -i Inetd mode" 233//usage: "\n -i Inetd mode"
234//usage: )
235//usage: IF_PLATFORM_MINGW32(
236//usage: "\n -i fd Inetd mode file descriptor"
237//usage: )
233//usage: "\n -f Don't daemonize" 238//usage: "\n -f Don't daemonize"
234//usage: "\n -v[v] Verbose" 239//usage: "\n -v[v] Verbose"
235//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:80)" 240//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:80)"
@@ -267,6 +272,8 @@
267 272
268#define HEADER_READ_TIMEOUT 60 273#define HEADER_READ_TIMEOUT 60
269 274
275static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
276
270static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; 277static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc";
271static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; 278static const char HTTPD_CONF[] ALIGN1 = "httpd.conf";
272static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; 279static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n";
@@ -652,8 +659,16 @@ static void parse_conf(const char *path, int flag)
652 659
653 filename = opt_c_configFile; 660 filename = opt_c_configFile;
654 if (flag == SUBDIR_PARSE || filename == NULL) { 661 if (flag == SUBDIR_PARSE || filename == NULL) {
662#if !ENABLE_PLATFORM_MINGW32
655 filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2); 663 filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2);
656 sprintf((char *)filename, "%s/%s", path, HTTPD_CONF); 664 sprintf((char *)filename, "%s/%s", path, HTTPD_CONF);
665#else
666 char *sd = get_system_drive();
667
668 filename = auto_string(xasprintf("%s%s/%s",
669 (sd && path[0] == '/' && root_len(path) == 0) ? sd : "",
670 path, HTTPD_CONF));
671#endif
657 } 672 }
658 673
659 while ((f = fopen_for_read(filename)) == NULL) { 674 while ((f = fopen_for_read(filename)) == NULL) {
@@ -702,6 +717,7 @@ static void parse_conf(const char *path, int flag)
702 * without needless copying, therefore we don't merge 717 * without needless copying, therefore we don't merge
703 * this operation into next while loop. */ 718 * this operation into next while loop. */
704 while ((ch = *p0) != '\0' && ch != '\n' && ch != '#' 719 while ((ch = *p0) != '\0' && ch != '\n' && ch != '#'
720 IF_PLATFORM_MINGW32(&& ch != '\r')
705 && ch != ' ' && ch != '\t' 721 && ch != ' ' && ch != '\t'
706 ) { 722 ) {
707 p0++; 723 p0++;
@@ -709,7 +725,11 @@ static void parse_conf(const char *path, int flag)
709 p = p0; 725 p = p0;
710 /* if we enter this loop, we have some whitespace. 726 /* if we enter this loop, we have some whitespace.
711 * discard it */ 727 * discard it */
728#if !ENABLE_PLATFORM_MINGW32
712 while (ch != '\0' && ch != '\n' && ch != '#') { 729 while (ch != '\0' && ch != '\n' && ch != '#') {
730#else
731 while (ch != '\0' && ch != '\n' && ch != '\r' && ch != '#') {
732#endif
713 if (ch != ' ' && ch != '\t') { 733 if (ch != ' ' && ch != '\t') {
714 *p++ = ch; 734 *p++ = ch;
715 } 735 }
@@ -1249,7 +1269,21 @@ static unsigned get_line(void)
1249 count = 0; 1269 count = 0;
1250 while (1) { 1270 while (1) {
1251 if (hdr_cnt <= 0) { 1271 if (hdr_cnt <= 0) {
1272#if ENABLE_PLATFORM_MINGW32
1273 int nfds = 1;
1274 struct pollfd fds = {STDIN_FILENO, POLLIN, 0};
1275
1276 switch (poll(&fds, nfds, HEADER_READ_TIMEOUT*1000)) {
1277 case 0:
1278 send_REQUEST_TIMEOUT_and_exit(0);
1279 break;
1280 case -1:
1281 bb_simple_perror_msg_and_die("poll");
1282 break;
1283 }
1284#else
1252 alarm(HEADER_READ_TIMEOUT); 1285 alarm(HEADER_READ_TIMEOUT);
1286#endif
1253 hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf); 1287 hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
1254 if (hdr_cnt <= 0) 1288 if (hdr_cnt <= 0)
1255 goto ret; 1289 goto ret;
@@ -2090,7 +2124,6 @@ static Htaccess_Proxy *find_proxy_entry(const char *url)
2090/* 2124/*
2091 * Handle timeouts 2125 * Handle timeouts
2092 */ 2126 */
2093static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
2094static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM) 2127static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM)
2095{ 2128{
2096 send_headers_and_exit(HTTP_REQUEST_TIMEOUT); 2129 send_headers_and_exit(HTTP_REQUEST_TIMEOUT);
@@ -2134,11 +2167,21 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2134 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); 2167 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr);
2135 } 2168 }
2136#if ENABLE_FEATURE_IPV6 2169#if ENABLE_FEATURE_IPV6
2170# if !ENABLE_PLATFORM_MINGW32
2137 if (fromAddr->u.sa.sa_family == AF_INET6 2171 if (fromAddr->u.sa.sa_family == AF_INET6
2138 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 2172 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0
2139 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 2173 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0
2140 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) 2174 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff)
2141 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); 2175 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]);
2176# else
2177 if (fromAddr->u.sa.sa_family == AF_INET6
2178 && fromAddr->u.sin6.sin6_addr.s6_words[0] == 0
2179 && fromAddr->u.sin6.sin6_addr.s6_words[1] == 0
2180 && fromAddr->u.sin6.sin6_addr.s6_words[2] == 0
2181 && fromAddr->u.sin6.sin6_addr.s6_words[3] == 0
2182 && ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+4)) == 0xffff)
2183 remote_ip = ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+6));
2184# endif
2142#endif 2185#endif
2143 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) { 2186 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
2144 /* NB: can be NULL (user runs httpd -i by hand?) */ 2187 /* NB: can be NULL (user runs httpd -i by hand?) */
@@ -2153,8 +2196,10 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2153 } 2196 }
2154 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); 2197 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip);
2155 2198
2199#ifdef SIGALRM
2156 /* Install timeout handler. get_line() needs it. */ 2200 /* Install timeout handler. get_line() needs it. */
2157 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit); 2201 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit);
2202#endif
2158 2203
2159 if (!get_line()) /* EOF or error or empty line */ 2204 if (!get_line()) /* EOF or error or empty line */
2160 send_headers_and_exit(HTTP_BAD_REQUEST); 2205 send_headers_and_exit(HTTP_BAD_REQUEST);
@@ -2527,12 +2572,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2527#endif 2572#endif
2528} 2573}
2529 2574
2575
2530/* 2576/*
2531 * The main http server function. 2577 * The main http server function.
2532 * Given a socket, listen for new connections and farm out 2578 * Given a socket, listen for new connections and farm out
2533 * the processing as a [v]forked process. 2579 * the processing as a [v]forked process.
2534 * Never returns. 2580 * Never returns.
2535 */ 2581 */
2582# if !ENABLE_PLATFORM_MINGW32
2536#if BB_MMU 2583#if BB_MMU
2537static void mini_httpd(int server_socket) NORETURN; 2584static void mini_httpd(int server_socket) NORETURN;
2538static void mini_httpd(int server_socket) 2585static void mini_httpd(int server_socket)
@@ -2614,6 +2661,39 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv)
2614 /* never reached */ 2661 /* never reached */
2615} 2662}
2616#endif 2663#endif
2664#else /* ENABLE_PLATFORM_MINGW32 */
2665static void mini_httpd_win32(int fg, int sock, int argc, char **argv) NORETURN;
2666static void mini_httpd_win32(int fg, int sock, int argc, char **argv)
2667{
2668 char *argv_copy[argc + 5];
2669
2670 argv_copy[0] = (char *)bb_busybox_exec_path;
2671 argv_copy[1] = (char *)"--busybox";
2672 argv_copy[2] = (char *)"httpd";
2673 argv_copy[3] = (char *)"-i";
2674 memcpy(&argv_copy[5], &argv[1], argc * sizeof(argv[0]));
2675
2676 while (1) {
2677 int n;
2678
2679 /* Wait for connections... */
2680 n = accept(sock, NULL, NULL);
2681 if (n < 0)
2682 continue;
2683
2684 /* set the KEEPALIVE option to cull dead connections */
2685 setsockopt_keepalive(n);
2686
2687 argv_copy[4] = itoa(n);
2688 if ((fg ? spawn(argv_copy) : mingw_spawn_detach(argv_copy)) == -1)
2689 bb_perror_msg_and_die("can't execute 'httpd'");
2690
2691 /* parent, or spawn failed */
2692 close(n);
2693 } /* while (1) */
2694 /* never reached */
2695}
2696#endif
2617 2697
2618/* 2698/*
2619 * Process a HTTP connection on stdin/out. 2699 * Process a HTTP connection on stdin/out.
@@ -2631,12 +2711,39 @@ static void mini_httpd_inetd(void)
2631 handle_incoming_and_exit(&fromAddr); 2711 handle_incoming_and_exit(&fromAddr);
2632} 2712}
2633 2713
2714#if ENABLE_PLATFORM_MINGW32
2715static void mingw_daemonize(char **argv)
2716{
2717 char **new_argv;
2718 int argc, fd;
2719
2720 argc = string_array_len((char **)argv);
2721 new_argv = xmalloc(sizeof(*argv)*(argc+3));
2722 new_argv[0] = (char *)bb_busybox_exec_path;
2723 new_argv[1] = (char *)"--busybox";
2724 new_argv[2] = (char *)"-httpd";
2725 memcpy(&new_argv[3], &argv[1], sizeof(*argv)*argc);
2726
2727 fd = xopen(bb_dev_null, O_RDWR);
2728 xdup2(fd, 0);
2729 xdup2(fd, 1);
2730 xdup2(fd, 2);
2731 close(fd);
2732
2733 if (mingw_spawn_detach(new_argv))
2734 exit(EXIT_SUCCESS); /* parent */
2735 exit(EXIT_FAILURE); /* parent */
2736}
2737#endif
2738
2739#ifdef SIGHUP
2634static void sighup_handler(int sig UNUSED_PARAM) 2740static void sighup_handler(int sig UNUSED_PARAM)
2635{ 2741{
2636 int sv = errno; 2742 int sv = errno;
2637 parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE); 2743 parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE);
2638 errno = sv; 2744 errno = sv;
2639} 2745}
2746#endif
2640 2747
2641enum { 2748enum {
2642 c_opt_config_file = 0, 2749 c_opt_config_file = 0,
@@ -2674,6 +2781,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2674 IF_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;) 2781 IF_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;)
2675 IF_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;) 2782 IF_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;)
2676 IF_FEATURE_HTTPD_AUTH_MD5(const char *pass;) 2783 IF_FEATURE_HTTPD_AUTH_MD5(const char *pass;)
2784 IF_PLATFORM_MINGW32(int fd;)
2677 2785
2678 INIT_G(); 2786 INIT_G();
2679 2787
@@ -2692,7 +2800,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2692 IF_FEATURE_HTTPD_BASIC_AUTH("r:") 2800 IF_FEATURE_HTTPD_BASIC_AUTH("r:")
2693 IF_FEATURE_HTTPD_AUTH_MD5("m:") 2801 IF_FEATURE_HTTPD_AUTH_MD5("m:")
2694 IF_FEATURE_HTTPD_SETUID("u:") 2802 IF_FEATURE_HTTPD_SETUID("u:")
2695 "p:ifv" 2803 IF_NOT_PLATFORM_MINGW32("p:ifv")
2804 IF_PLATFORM_MINGW32("p:i:+fv")
2696 "\0" 2805 "\0"
2697 /* -v counts, -i implies -f */ 2806 /* -v counts, -i implies -f */
2698 "vv:if", 2807 "vv:if",
@@ -2702,6 +2811,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2702 IF_FEATURE_HTTPD_AUTH_MD5(, &pass) 2811 IF_FEATURE_HTTPD_AUTH_MD5(, &pass)
2703 IF_FEATURE_HTTPD_SETUID(, &s_ugid) 2812 IF_FEATURE_HTTPD_SETUID(, &s_ugid)
2704 , &bind_addr_or_port 2813 , &bind_addr_or_port
2814 IF_PLATFORM_MINGW32(, &fd)
2705 , &verbose 2815 , &verbose
2706 ); 2816 );
2707 if (opt & OPT_DECODE_URL) { 2817 if (opt & OPT_DECODE_URL) {
@@ -2731,15 +2841,22 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2731 } 2841 }
2732#endif 2842#endif
2733 2843
2844#if !ENABLE_PLATFORM_MINGW32
2734#if !BB_MMU 2845#if !BB_MMU
2735 if (!(opt & OPT_FOREGROUND)) { 2846 if (!(opt & OPT_FOREGROUND)) {
2736 bb_daemonize_or_rexec(0, argv); /* don't change current directory */ 2847 bb_daemonize_or_rexec(0, argv); /* don't change current directory */
2737 } 2848 }
2738#endif 2849#endif
2850#else /* ENABLE_PLATFORM_MINGW32 */
2851 if (!(opt & OPT_FOREGROUND) && argv[0][0] != '-')
2852 mingw_daemonize(argv);
2853#endif
2739 2854
2740 xchdir(home_httpd); 2855 xchdir(home_httpd);
2741 if (!(opt & OPT_INETD)) { 2856 if (!(opt & OPT_INETD)) {
2857#ifdef SIGCHLD
2742 signal(SIGCHLD, SIG_IGN); 2858 signal(SIGCHLD, SIG_IGN);
2859#endif
2743 server_socket = openServer(); 2860 server_socket = openServer();
2744#if ENABLE_FEATURE_HTTPD_SETUID 2861#if ENABLE_FEATURE_HTTPD_SETUID
2745 /* drop privileges */ 2862 /* drop privileges */
@@ -2773,12 +2890,23 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2773#endif 2890#endif
2774 2891
2775 parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE); 2892 parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE);
2893#ifdef SIGHUP
2776 if (!(opt & OPT_INETD)) 2894 if (!(opt & OPT_INETD))
2777 signal(SIGHUP, sighup_handler); 2895 signal(SIGHUP, sighup_handler);
2896#endif
2778 2897
2779 xfunc_error_retval = 0; 2898 xfunc_error_retval = 0;
2899#if ENABLE_PLATFORM_MINGW32
2900 if (opt & OPT_INETD) {
2901 xmove_fd(fd, 0);
2902 xdup2(0, 1);
2903 while (--fd > 2)
2904 close(fd);
2905 }
2906#endif
2780 if (opt & OPT_INETD) 2907 if (opt & OPT_INETD)
2781 mini_httpd_inetd(); /* never returns */ 2908 mini_httpd_inetd(); /* never returns */
2909#if !ENABLE_PLATFORM_MINGW32
2782#if BB_MMU 2910#if BB_MMU
2783 if (!(opt & OPT_FOREGROUND)) 2911 if (!(opt & OPT_FOREGROUND))
2784 bb_daemonize(0); /* don't change current directory */ 2912 bb_daemonize(0); /* don't change current directory */
@@ -2786,5 +2914,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2786#else 2914#else
2787 mini_httpd_nommu(server_socket, argc, argv); /* never returns */ 2915 mini_httpd_nommu(server_socket, argc, argv); /* never returns */
2788#endif 2916#endif
2917#else /* ENABLE_PLATFORM_MINGW32 */
2918 mini_httpd_win32(opt & OPT_FOREGROUND, server_socket, argc, argv);
2919#endif
2789 /* return 0; */ 2920 /* return 0; */
2790} 2921}