diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-12 10:35:23 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-12 10:35:23 +0000 |
commit | 6536a9b5833febe719988526a095a9cacb8a1042 (patch) | |
tree | 07b65c5cf7e1f51909d4e7b516253bae7611fa48 /networking/httpd.c | |
parent | f8138d1f91c913166bffb0077a0fe06831a77ecf (diff) | |
download | busybox-w32-6536a9b5833febe719988526a095a9cacb8a1042.tar.gz busybox-w32-6536a9b5833febe719988526a095a9cacb8a1042.tar.bz2 busybox-w32-6536a9b5833febe719988526a095a9cacb8a1042.zip |
next part of ipv6-ization is here: wget & httpd
Diffstat (limited to 'networking/httpd.c')
-rw-r--r-- | networking/httpd.c | 133 |
1 files changed, 74 insertions, 59 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 818590f78..f8773685e 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -142,7 +142,7 @@ typedef struct { | |||
142 | 142 | ||
143 | unsigned int rmt_ip; | 143 | unsigned int rmt_ip; |
144 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | 144 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
145 | char rmt_ip_str[16]; /* for set env REMOTE_ADDR */ | 145 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ |
146 | #endif | 146 | #endif |
147 | unsigned port; /* server initial port and for | 147 | unsigned port; /* server initial port and for |
148 | set env REMOTE_PORT */ | 148 | set env REMOTE_PORT */ |
@@ -817,30 +817,11 @@ static void decodeBase64(char *Data) | |||
817 | ****************************************************************************/ | 817 | ****************************************************************************/ |
818 | static int openServer(void) | 818 | static int openServer(void) |
819 | { | 819 | { |
820 | struct sockaddr_in lsocket; | ||
821 | int fd; | 820 | int fd; |
822 | 821 | ||
823 | /* create the socket right now */ | 822 | /* create the socket right now */ |
824 | /* inet_addr() returns a value that is already in network order */ | 823 | fd = create_and_bind_stream_or_die(NULL, config->port); |
825 | memset(&lsocket, 0, sizeof(lsocket)); | ||
826 | lsocket.sin_family = AF_INET; | ||
827 | lsocket.sin_addr.s_addr = INADDR_ANY; | ||
828 | lsocket.sin_port = htons(config->port); | ||
829 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
830 | /* tell the OS it's OK to reuse a previous address even though */ | ||
831 | /* it may still be in a close down state. Allows bind to succeed. */ | ||
832 | #ifdef SO_REUSEPORT | ||
833 | { | ||
834 | static const int on = 1; | ||
835 | setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, | ||
836 | (void *)&on, sizeof(on)); | ||
837 | } | ||
838 | #else | ||
839 | setsockopt_reuseaddr(fd); | ||
840 | #endif | ||
841 | xbind(fd, (struct sockaddr *)&lsocket, sizeof(lsocket)); | ||
842 | xlisten(fd, 9); | 824 | xlisten(fd, 9); |
843 | signal(SIGCHLD, SIG_IGN); /* prevent zombie (defunct) processes */ | ||
844 | return fd; | 825 | return fd; |
845 | } | 826 | } |
846 | 827 | ||
@@ -1070,7 +1051,19 @@ static int sendCgi(const char *url, | |||
1070 | setenv1("SERVER_SOFTWARE", httpdVersion); | 1051 | setenv1("SERVER_SOFTWARE", httpdVersion); |
1071 | putenv("SERVER_PROTOCOL=HTTP/1.0"); | 1052 | putenv("SERVER_PROTOCOL=HTTP/1.0"); |
1072 | putenv("GATEWAY_INTERFACE=CGI/1.1"); | 1053 | putenv("GATEWAY_INTERFACE=CGI/1.1"); |
1073 | setenv1("REMOTE_ADDR", config->rmt_ip_str); | 1054 | /* Having _separate_ variables for IP and port defeats |
1055 | * the purpose of having socket abstraction. Which "port" | ||
1056 | * are you using on Unix domain socket? | ||
1057 | * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense. | ||
1058 | * Oh well... */ | ||
1059 | { | ||
1060 | char *p = config->rmt_ip_str ? : ""; | ||
1061 | char *cp = strrchr(p, ':'); | ||
1062 | if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']')) | ||
1063 | cp = NULL; | ||
1064 | if (cp) *cp = '\0'; /* delete :PORT */ | ||
1065 | setenv1("REMOTE_ADDR", p); | ||
1066 | } | ||
1074 | #if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | 1067 | #if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV |
1075 | setenv_long("REMOTE_PORT", config->port); | 1068 | setenv_long("REMOTE_PORT", config->port); |
1076 | #endif | 1069 | #endif |
@@ -1330,17 +1323,17 @@ static int checkPermIP(void) | |||
1330 | for (cur = config->ip_a_d; cur; cur = cur->next) { | 1323 | for (cur = config->ip_a_d; cur; cur = cur->next) { |
1331 | #if DEBUG | 1324 | #if DEBUG |
1332 | fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); | 1325 | fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); |
1326 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", | ||
1327 | (unsigned char)(cur->ip >> 24), | ||
1328 | (unsigned char)(cur->ip >> 16), | ||
1329 | (unsigned char)(cur->ip >> 8), | ||
1330 | (unsigned char)(cur->ip), | ||
1331 | (unsigned char)(cur->mask >> 24), | ||
1332 | (unsigned char)(cur->mask >> 16), | ||
1333 | (unsigned char)(cur->mask >> 8), | ||
1334 | (unsigned char)(cur->mask) | ||
1335 | ); | ||
1333 | #endif | 1336 | #endif |
1334 | if (DEBUG) | ||
1335 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", | ||
1336 | (unsigned char)(cur->ip >> 24), | ||
1337 | (unsigned char)(cur->ip >> 16), | ||
1338 | (unsigned char)(cur->ip >> 8), | ||
1339 | cur->ip & 0xff, | ||
1340 | (unsigned char)(cur->mask >> 24), | ||
1341 | (unsigned char)(cur->mask >> 16), | ||
1342 | (unsigned char)(cur->mask >> 8), | ||
1343 | cur->mask & 0xff); | ||
1344 | if ((config->rmt_ip & cur->mask) == cur->ip) | 1337 | if ((config->rmt_ip & cur->mask) == cur->ip) |
1345 | return cur->allow_deny == 'A'; /* Allow/Deny */ | 1338 | return cur->allow_deny == 'A'; /* Allow/Deny */ |
1346 | } | 1339 | } |
@@ -1765,6 +1758,8 @@ static void handleIncoming(void) | |||
1765 | ****************************************************************************/ | 1758 | ****************************************************************************/ |
1766 | static int miniHttpd(int server) | 1759 | static int miniHttpd(int server) |
1767 | { | 1760 | { |
1761 | static const int on = 1; | ||
1762 | |||
1768 | fd_set readfd, portfd; | 1763 | fd_set readfd, portfd; |
1769 | 1764 | ||
1770 | FD_ZERO(&portfd); | 1765 | FD_ZERO(&portfd); |
@@ -1772,9 +1767,13 @@ static int miniHttpd(int server) | |||
1772 | 1767 | ||
1773 | /* copy the ports we are watching to the readfd set */ | 1768 | /* copy the ports we are watching to the readfd set */ |
1774 | while (1) { | 1769 | while (1) { |
1775 | int on, s; | 1770 | int s; |
1776 | socklen_t fromAddrLen; | 1771 | union { |
1777 | struct sockaddr_in fromAddr; | 1772 | struct sockaddr sa; |
1773 | struct sockaddr_in sin; | ||
1774 | USE_FEATURE_IPV6(struct sockaddr_in6 sin6;) | ||
1775 | } fromAddr; | ||
1776 | socklen_t fromAddrLen = sizeof(fromAddr); | ||
1778 | 1777 | ||
1779 | /* Now wait INDEFINITELY on the set of sockets! */ | 1778 | /* Now wait INDEFINITELY on the set of sockets! */ |
1780 | readfd = portfd; | 1779 | readfd = portfd; |
@@ -1782,27 +1781,31 @@ static int miniHttpd(int server) | |||
1782 | continue; | 1781 | continue; |
1783 | if (!FD_ISSET(server, &readfd)) | 1782 | if (!FD_ISSET(server, &readfd)) |
1784 | continue; | 1783 | continue; |
1785 | fromAddrLen = sizeof(fromAddr); | 1784 | s = accept(server, &fromAddr.sa, &fromAddrLen); |
1786 | s = accept(server, (struct sockaddr *)&fromAddr, &fromAddrLen); | ||
1787 | if (s < 0) | 1785 | if (s < 0) |
1788 | continue; | 1786 | continue; |
1789 | config->accepted_socket = s; | 1787 | config->accepted_socket = s; |
1790 | config->rmt_ip = ntohl(fromAddr.sin_addr.s_addr); | 1788 | config->rmt_ip = 0; |
1789 | config->port = 0; | ||
1791 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | 1790 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
1792 | sprintf(config->rmt_ip_str, "%u.%u.%u.%u", | 1791 | free(config->rmt_ip_str); |
1793 | (unsigned char)(config->rmt_ip >> 24), | 1792 | config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
1794 | (unsigned char)(config->rmt_ip >> 16), | ||
1795 | (unsigned char)(config->rmt_ip >> 8), | ||
1796 | config->rmt_ip & 0xff); | ||
1797 | config->port = ntohs(fromAddr.sin_port); | ||
1798 | #if DEBUG | 1793 | #if DEBUG |
1799 | bb_error_msg("connection from IP=%s, port %u", | 1794 | bb_error_msg("connection from '%s'", config->rmt_ip_str); |
1800 | config->rmt_ip_str, config->port); | ||
1801 | #endif | 1795 | #endif |
1802 | #endif /* FEATURE_HTTPD_CGI */ | 1796 | #endif /* FEATURE_HTTPD_CGI */ |
1797 | if (fromAddr.sa.sa_family == AF_INET) { | ||
1798 | config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | ||
1799 | config->port = ntohs(fromAddr.sin.sin_port); | ||
1800 | } | ||
1801 | #if ENABLE_FEATURE_IPV6 | ||
1802 | if (fromAddr.sa.sa_family == AF_INET6) { | ||
1803 | //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | ||
1804 | config->port = ntohs(fromAddr.sin6.sin6_port); | ||
1805 | } | ||
1806 | #endif | ||
1803 | 1807 | ||
1804 | /* set the KEEPALIVE option to cull dead connections */ | 1808 | /* set the KEEPALIVE option to cull dead connections */ |
1805 | on = 1; | ||
1806 | setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); | 1809 | setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); |
1807 | 1810 | ||
1808 | if (DEBUG || fork() == 0) { | 1811 | if (DEBUG || fork() == 0) { |
@@ -1823,19 +1826,30 @@ static int miniHttpd(int server) | |||
1823 | /* from inetd */ | 1826 | /* from inetd */ |
1824 | static int miniHttpd_inetd(void) | 1827 | static int miniHttpd_inetd(void) |
1825 | { | 1828 | { |
1826 | struct sockaddr_in fromAddrLen; | 1829 | union { |
1827 | socklen_t sinlen = sizeof(struct sockaddr_in); | 1830 | struct sockaddr sa; |
1828 | 1831 | struct sockaddr_in sin; | |
1829 | getpeername(0, (struct sockaddr *)&fromAddrLen, &sinlen); | 1832 | USE_FEATURE_IPV6(struct sockaddr_in6 sin6;) |
1830 | config->rmt_ip = ntohl(fromAddrLen.sin_addr.s_addr); | 1833 | } fromAddr; |
1831 | #if ENABLE_FEATURE_HTTPD_CGI | 1834 | socklen_t fromAddrLen = sizeof(fromAddr); |
1832 | sprintf(config->rmt_ip_str, "%u.%u.%u.%u", | 1835 | |
1833 | (unsigned char)(config->rmt_ip >> 24), | 1836 | getpeername(0, &fromAddr.sa, &fromAddrLen); |
1834 | (unsigned char)(config->rmt_ip >> 16), | 1837 | config->rmt_ip = 0; |
1835 | (unsigned char)(config->rmt_ip >> 8), | 1838 | config->port = 0; |
1836 | config->rmt_ip & 0xff); | 1839 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
1840 | free(config->rmt_ip_str); | ||
1841 | config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); | ||
1842 | #endif | ||
1843 | if (fromAddr.sa.sa_family == AF_INET) { | ||
1844 | config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | ||
1845 | config->port = ntohs(fromAddr.sin.sin_port); | ||
1846 | } | ||
1847 | #if ENABLE_FEATURE_IPV6 | ||
1848 | if (fromAddr.sa.sa_family == AF_INET6) { | ||
1849 | //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | ||
1850 | config->port = ntohs(fromAddr.sin6.sin6_port); | ||
1851 | } | ||
1837 | #endif | 1852 | #endif |
1838 | config->port = ntohs(fromAddrLen.sin_port); | ||
1839 | handleIncoming(); | 1853 | handleIncoming(); |
1840 | return 0; | 1854 | return 0; |
1841 | } | 1855 | } |
@@ -1945,6 +1959,7 @@ int httpd_main(int argc, char *argv[]) | |||
1945 | 1959 | ||
1946 | xchdir(home_httpd); | 1960 | xchdir(home_httpd); |
1947 | if (!(opt & OPT_INETD)) { | 1961 | if (!(opt & OPT_INETD)) { |
1962 | signal(SIGCHLD, SIG_IGN); | ||
1948 | config->server_socket = openServer(); | 1963 | config->server_socket = openServer(); |
1949 | #if ENABLE_FEATURE_HTTPD_SETUID | 1964 | #if ENABLE_FEATURE_HTTPD_SETUID |
1950 | /* drop privileges */ | 1965 | /* drop privileges */ |