aboutsummaryrefslogtreecommitdiff
path: root/networking/httpd.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-01-12 10:35:23 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-01-12 10:35:23 +0000
commit6536a9b5833febe719988526a095a9cacb8a1042 (patch)
tree07b65c5cf7e1f51909d4e7b516253bae7611fa48 /networking/httpd.c
parentf8138d1f91c913166bffb0077a0fe06831a77ecf (diff)
downloadbusybox-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.c133
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 ****************************************************************************/
818static int openServer(void) 818static 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 ****************************************************************************/
1766static int miniHttpd(int server) 1759static 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 */
1824static int miniHttpd_inetd(void) 1827static 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 */