Added lance entry to drivers.conf.
[minix3-old.git] / commands / httpd / net.c
blob4d2638593897dc5e1cf49c204554ba1d62bffaad
1 /* net.c
3 * This file is part of httpd.
5 * 01/25/1996 Michael Temari <Michael@TemWare.Com>
6 * 07/07/1996 Initial Release Michael Temari <Michael@TemWare.Com>
7 * 12/29/2002 Michael Temari <Michael@TemWare.Com>
9 */
10 #include <sys/types.h>
11 #include <sys/ioctl.h>
12 #include <sys/wait.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <signal.h>
19 #include <unistd.h>
20 #include <net/netlib.h>
21 #include <net/hton.h>
22 #include <net/gen/in.h>
23 #include <net/gen/inet.h>
24 #include <net/gen/tcp.h>
25 #include <net/gen/tcp_io.h>
26 #include <net/gen/socket.h>
27 #include <net/gen/netdb.h>
29 #include "net.h"
31 _PROTOTYPE(static void release, (int *fd));
33 ipaddr_t myipaddr, rmtipaddr;
34 tcpport_t myport, rmtport;
35 char myhostname[256];
36 char rmthostname[256];
37 char rmthostaddr[3+1+3+1+3+1+3+1];
39 void GetNetInfo()
41 nwio_tcpconf_t tcpconf;
42 int s;
43 struct hostent *hostent;
45 /* Ask the system what our hostname is. */
46 if(gethostname(myhostname, sizeof(myhostname)) < 0)
47 strcpy(myhostname, "unknown");
49 /* lets get our ip address and the clients ip address */
50 s = ioctl(0, NWIOGTCPCONF, &tcpconf);
51 if(s < 0) {
52 myipaddr = 0;
53 myport = 0;
54 rmtipaddr = 0;
55 rmtport = 0;
56 strcpy(rmthostname, "??Unknown??");
57 strcpy(rmthostaddr, "???.???.???.???");
58 return;
61 myipaddr = tcpconf.nwtc_locaddr;
62 myport = tcpconf.nwtc_locport;
63 rmtipaddr = tcpconf.nwtc_remaddr;
64 rmtport = tcpconf.nwtc_remport;
66 /* Look up the host name of the remote host. */
67 hostent = gethostbyaddr((char *) &rmtipaddr, sizeof(rmtipaddr), AF_INET);
68 if(!hostent)
69 strncpy(rmthostname, inet_ntoa(rmtipaddr), sizeof(rmthostname)-1);
70 else
71 strncpy(rmthostname, hostent->h_name, sizeof(rmthostname)-1);
73 strcpy(rmthostaddr, inet_ntoa(rmtipaddr));
75 rmthostname[sizeof(rmthostname)-1] = '\0';
77 return;
80 static void release(fd)
81 int *fd;
83 if(*fd != -1) {
84 close(*fd);
85 *fd= -1;
89 void daemonloop(service)
90 char *service;
92 tcpport_t port;
93 struct nwio_tcpcl tcplistenopt;
94 struct nwio_tcpconf tcpconf;
95 struct nwio_tcpopt tcpopt;
96 struct servent *servent;
97 char *tcp_device;
98 int tcp_fd, client_fd, r;
99 int pfd[2];
100 unsigned stall= 0;
102 if((servent= getservbyname(service, "tcp")) == NULL) {
103 unsigned long p;
104 char *end;
106 p = strtoul(service, &end, 0);
107 if(p <= 0 || p > 0xFFFF || *end != 0) {
108 fprintf(stderr, "httpd: %s: Unknown service\n", service);
109 exit(1);
111 port= htons((tcpport_t) p);
112 } else
113 port= servent->s_port;
115 /* No client yet. */
116 client_fd= -1;
118 while (1) {
119 if((tcp_device = getenv("TCP_DEVICE")) == NULL)
120 tcp_device = TCP_DEVICE;
121 if ((tcp_fd= open(tcp_device, O_RDWR)) < 0) {
122 fprintf(stderr, "httpd: Can't open %s: %s",
123 tcp_device, strerror(errno));
124 if (errno == ENOENT || errno == ENODEV
125 || errno == ENXIO) {
126 exit(1);
128 goto bad;
131 tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
132 tcpconf.nwtc_locport= port;
134 if (ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf) < 0) {
135 fprintf(stderr, "httpd: Can't configure TCP channel",
136 strerror(errno));
137 exit(1);
140 #ifdef NWTO_DEL_RST
141 tcpopt.nwto_flags= NWTO_DEL_RST;
143 if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) < 0) {
144 fprintf(stderr, "httpd: Can't set TCP options",
145 strerror(errno));
146 exit(1);
148 #endif
150 if (client_fd != -1) {
151 /* We have a client, so start a server for it. */
153 #ifdef NWTO_DEL_RST
154 tcpopt.nwto_flags= 0;
155 (void) ioctl(client_fd, NWIOSTCPOPT, &tcpopt);
156 #endif
158 fflush(NULL);
160 /* Create a pipe to serve as an error indicator. */
161 if (pipe(pfd) < 0) {
162 fprintf(stderr, "httpd: pipe", strerror(errno));
163 goto bad;
166 /* Fork twice to daemonize child. */
167 switch (fork()) {
168 case -1:
169 fprintf(stderr, "httpd: fork", strerror(errno));
170 close(pfd[0]);
171 close(pfd[1]);
172 goto bad;
173 case 0:
174 close(tcp_fd);
175 close(pfd[0]);
176 switch (fork()) {
177 case -1:
178 fprintf(stderr, "httpd: fork",
179 strerror(errno));
180 write(pfd[1], &errno, sizeof(errno));
181 exit(1);
182 case 0:
183 break;
184 default:
185 exit(0);
187 dup2(client_fd, 0);
188 dup2(client_fd, 1);
189 close(client_fd);
190 close(pfd[1]);
192 /* Break out of the daemon loop, continuing with
193 * the normal httpd code to serve the client.
195 return;
197 default:
198 release(&client_fd);
199 close(pfd[1]);
200 wait(NULL);
201 r= read(pfd[0], &errno, sizeof(errno));
202 close(pfd[0]);
203 if (r != 0) goto bad;
204 break;
208 /* Wait for a new connection. */
209 tcplistenopt.nwtcl_flags= 0;
211 while (ioctl(tcp_fd, NWIOTCPLISTEN, &tcplistenopt) < 0) {
212 if (errno != EAGAIN) {
213 fprintf(stderr, "httpd: Unable to listen: %s",
214 strerror(errno));
216 goto bad;
219 /* We got a connection. */
220 client_fd= tcp_fd;
221 tcp_fd= -1;
223 /* All is well, no need to stall. */
224 stall= 0;
225 continue;
227 bad:
228 /* All is not well, release resources. */
229 release(&tcp_fd);
230 release(&client_fd);
232 /* Wait a bit if this happens more than once. */
233 if (stall != 0) {
234 sleep(stall);
235 stall <<= 1;
236 } else {
237 stall= 1;