source: trunk/minix/commands/httpd/net.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.0 KB
Line 
1/* net.c
2 *
3 * This file is part of httpd.
4 *
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>
8 *
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>
28
29#include "net.h"
30
31_PROTOTYPE(static void release, (int *fd));
32
33ipaddr_t myipaddr, rmtipaddr;
34tcpport_t myport, rmtport;
35char myhostname[256];
36char rmthostname[256];
37char rmthostaddr[3+1+3+1+3+1+3+1];
38
39void GetNetInfo()
40{
41nwio_tcpconf_t tcpconf;
42int s;
43struct hostent *hostent;
44
45 /* Ask the system what our hostname is. */
46 if(gethostname(myhostname, sizeof(myhostname)) < 0)
47 strcpy(myhostname, "unknown");
48
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;
59 }
60
61 myipaddr = tcpconf.nwtc_locaddr;
62 myport = tcpconf.nwtc_locport;
63 rmtipaddr = tcpconf.nwtc_remaddr;
64 rmtport = tcpconf.nwtc_remport;
65
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);
72
73 strcpy(rmthostaddr, inet_ntoa(rmtipaddr));
74
75 rmthostname[sizeof(rmthostname)-1] = '\0';
76
77 return;
78}
79
80static void release(fd)
81int *fd;
82{
83 if(*fd != -1) {
84 close(*fd);
85 *fd= -1;
86 }
87}
88
89void daemonloop(service)
90char *service;
91{
92tcpport_t port;
93struct nwio_tcpcl tcplistenopt;
94struct nwio_tcpconf tcpconf;
95struct nwio_tcpopt tcpopt;
96struct servent *servent;
97char *tcp_device;
98int tcp_fd, client_fd, r;
99int pfd[2];
100unsigned stall= 0;
101
102 if((servent= getservbyname(service, "tcp")) == NULL) {
103 unsigned long p;
104 char *end;
105
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);
110 }
111 port= htons((tcpport_t) p);
112 } else
113 port= servent->s_port;
114
115 /* No client yet. */
116 client_fd= -1;
117
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);
127 }
128 goto bad;
129 }
130
131 tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
132 tcpconf.nwtc_locport= port;
133
134 if (ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf) < 0) {
135 fprintf(stderr, "httpd: Can't configure TCP channel",
136 strerror(errno));
137 exit(1);
138 }
139
140#ifdef NWTO_DEL_RST
141 tcpopt.nwto_flags= NWTO_DEL_RST;
142
143 if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) < 0) {
144 fprintf(stderr, "httpd: Can't set TCP options",
145 strerror(errno));
146 exit(1);
147 }
148#endif
149
150 if (client_fd != -1) {
151 /* We have a client, so start a server for it. */
152
153#ifdef NWTO_DEL_RST
154 tcpopt.nwto_flags= 0;
155 (void) ioctl(client_fd, NWIOSTCPOPT, &tcpopt);
156#endif
157
158 fflush(NULL);
159
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;
164 }
165
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);
186 }
187 dup2(client_fd, 0);
188 dup2(client_fd, 1);
189 close(client_fd);
190 close(pfd[1]);
191
192 /* Break out of the daemon loop, continuing with
193 * the normal httpd code to serve the client.
194 */
195 return;
196
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;
205 }
206 }
207
208 /* Wait for a new connection. */
209 tcplistenopt.nwtcl_flags= 0;
210
211 while (ioctl(tcp_fd, NWIOTCPLISTEN, &tcplistenopt) < 0) {
212 if (errno != EAGAIN) {
213 fprintf(stderr, "httpd: Unable to listen: %s",
214 strerror(errno));
215 }
216 goto bad;
217 }
218
219 /* We got a connection. */
220 client_fd= tcp_fd;
221 tcp_fd= -1;
222
223 /* All is well, no need to stall. */
224 stall= 0;
225 continue;
226
227 bad:
228 /* All is not well, release resources. */
229 release(&tcp_fd);
230 release(&client_fd);
231
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;
238 }
239 }
240}
Note: See TracBrowser for help on using the repository browser.