/[hydra]/hydra/src/boa.c
ViewVC logotype

Annotation of /hydra/src/boa.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations)
Fri Sep 27 21:09:11 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
Changes since 1.7: +46 -1 lines
File MIME type: text/plain
Added some preliminary support for fast CGI support (Hydra Internally handled CGI) or HIC. Currently it can be used with php.

1 nmav 1.1 /*
2     * Boa, an http server
3     * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4     * Some changes Copyright (C) 1996 Charles F. Randall <crandall@goldsys.com>
5     * Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
6     * Some changes Copyright (C) 1996-2002 Jon Nelson <jnelson@boa.org>
7     * Portions Copyright (C) 2002 Nikos Mavroyanopoulos <nmav@gnutls.org>
8     *
9     * This program is free software; you can redistribute it and/or modify
10     * it under the terms of the GNU General Public License as published by
11     * the Free Software Foundation; either version 1, or (at your option)
12     * any later version.
13     *
14     * This program is distributed in the hope that it will be useful,
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     * GNU General Public License for more details.
18     *
19     * You should have received a copy of the GNU General Public License
20     * along with this program; if not, write to the Free Software
21     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22     *
23     */
24    
25 nmav 1.8 /* $Id: boa.c,v 1.7 2002/09/27 07:03:45 nmav Exp $*/
26 nmav 1.1
27     #include "boa.h"
28     #include "ssl.h"
29     #include <sys/resource.h>
30     #ifdef ENABLE_SMP
31     pthread_t father_id;
32     #endif
33    
34     extern int ssl_params_refresh;
35 nmav 1.8 int hic_write_fd; /* fd to write to HIC thread */
36 nmav 1.1
37     /* globals */
38     int backlog = SO_MAXCONN;
39     time_t start_time;
40    
41     time_t current_time;
42    
43    
44     /* static to boa.c */
45     static void fixup_server_root(void);
46     static socket_type create_server_socket( int port, int);
47 nmav 1.8 static int hic_init(void);
48 nmav 1.1 static void drop_privs(void);
49     static server_params *smp_init(socket_type server_s[2]);
50     static int sock_opt = 1;
51     static int do_fork = 1;
52     int devnullfd = -1;
53    
54     int main(int argc, char **argv)
55     {
56     int c; /* command line arg */
57 nmav 1.3 socket_type server_s[2] = {{ -1, 0, 0, 0}, { -1, -1, 0, 0 }}; /* boa socket */
58 nmav 1.1 server_params *params;
59    
60     /* set umask to u+rw, u-x, go-rwx */
61     c = umask(~0600);
62     if (c == -1) {
63     perror("umask");
64     exit(1);
65     }
66    
67     devnullfd = open("/dev/null", 0);
68    
69     /* make STDIN and STDOUT point to /dev/null */
70     if (devnullfd == -1) {
71     DIE("can't open /dev/null");
72     }
73    
74     if (dup2(devnullfd, STDIN_FILENO) == -1) {
75     DIE("can't dup2 /dev/null to STDIN_FILENO");
76     }
77    
78     if (dup2(devnullfd, STDOUT_FILENO) == -1) {
79     DIE("can't dup2 /dev/null to STDOUT_FILENO");
80     }
81    
82     /* but first, update timestamp, because log_error_time uses it */
83     (void) time(&current_time);
84    
85     while ((c = getopt(argc, argv, "c:r:d")) != -1) {
86     switch (c) {
87     case 'c':
88     if (server_root)
89     free(server_root);
90     server_root = strdup(optarg);
91     if (!server_root) {
92     perror("strdup (for server_root)");
93     exit(1);
94     }
95     break;
96     case 'r':
97     if (chdir(optarg) == -1) {
98     log_error_time();
99     perror("chdir (to chroot)");
100     exit(1);
101     }
102     if (chroot(optarg) == -1) {
103     log_error_time();
104     perror("chroot");
105     exit(1);
106     }
107     if (chdir("/") == -1) {
108     log_error_time();
109     perror("chdir (after chroot)");
110     exit(1);
111     }
112     break;
113     case 'd':
114     do_fork = 0;
115     break;
116     default:
117     fprintf(stderr, "Usage: %s [-c serverroot] [-r chroot] [-d]\n", argv[0]);
118     exit(1);
119     }
120     }
121    
122     fixup_server_root();
123     read_config_files();
124     open_logs();
125    
126     if ((boa_ssl >= 2 || boa_ssl == 0) && server_port > 0) {
127     server_s[0] = create_server_socket( server_port, 0);
128     }
129    
130     if (boa_ssl != 0 && ssl_port > 0) {
131     server_s[1] = create_server_socket( ssl_port, 1);
132     }
133    
134     if (server_s[1].socket == -1 && server_s[0].socket == -1) {
135     log_error_time();
136     fprintf(stderr, "Could not initialize sockets\n");
137     exit(1);
138     }
139    
140     init_signals();
141     drop_privs();
142     create_common_env();
143     build_needs_escape();
144    
145     if (boa_ssl) {
146     initialize_ssl();
147     }
148 nmav 1.5
149     initialize_mmap();
150 nmav 1.1
151     if (max_connections < 1) {
152     struct rlimit rl;
153    
154     /* has not been set explicitly */
155     c = getrlimit(RLIMIT_NOFILE, &rl);
156     if (c < 0) {
157     perror("getrlimit");
158     exit(1);
159     }
160     max_connections = rl.rlim_cur;
161     }
162    
163     /* background ourself */
164     if (do_fork) {
165     switch(fork()) {
166     case -1:
167     /* error */
168     perror("fork");
169     exit(1);
170     break;
171     case 0:
172     /* child, success */
173     break;
174     default:
175     /* parent, success */
176     exit(0);
177     break;
178     }
179     }
180    
181     /* main loop */
182     timestamp();
183    
184     start_time = current_time;
185    
186     /* Blocks signals that are not supposed to be catched
187     * by the children.
188     */
189     block_main_signals();
190 nmav 1.8
191     hic_write_fd = hic_init();
192 nmav 1.1
193     /* spawn the children pool
194     */
195     params = smp_init( server_s);
196    
197     /* unblock signals for daddy
198     */
199     unblock_main_signals();
200    
201     /* regenerate parameters in that time interval
202     */
203     if (boa_ssl) {
204 nmav 1.4 if (ssl_params_refresh < DEFAULT_SSL_PARAMS_REFRESH) {
205     log_error_time();
206     fprintf(stderr, "SSL parameters will be refreshed every %d minutes\n",
207     DEFAULT_SSL_PARAMS_REFRESH/60);
208     ssl_params_refresh = DEFAULT_SSL_PARAMS_REFRESH;
209     }
210 nmav 1.1 alarm( ssl_params_refresh);
211     }
212    
213     select_loop( params);
214    
215     return 0;
216     }
217    
218     server_params *global_server_params;
219     int global_server_params_size;
220    
221     extern int server_max_threads;
222    
223     /* This function will return a server_params pointer. This
224     * pointer is to be used as a pointer to the select loop.
225     */
226     static server_params* smp_init( socket_type server_s[2])
227     {
228     int i;
229     server_params *params;
230    
231     #ifdef ENABLE_SMP
232     pthread_t tid;
233     int max_threads = server_max_threads;
234    
235     father_id = pthread_self();
236     #else
237     const int max_threads = 1;
238     #endif
239    
240     params = malloc( sizeof(server_params) * max_threads);
241     if (params == NULL) {
242     log_error_time();
243     fprintf(stderr,
244     "Could not allocate memory.\n");
245     exit(1);
246     }
247    
248     for (i=0;i<max_threads;i++) {
249     params[i].server_s[0] = server_s[0];
250     params[i].server_s[1] = server_s[1];
251     params[i].request_ready = NULL;
252     params[i].request_block = NULL;
253     params[i].request_free = NULL;
254    
255     /* for signal handling */
256     params[i].sighup_flag = 0;
257     params[i].sigchld_flag = 0;
258     params[i].sigalrm_flag = 0;
259     params[i].sigusr1_flag = 0;
260     params[i].sigterm_flag = 0;
261    
262     params[i].sockbufsize = SOCKETBUF_SIZE;
263    
264     params[i].status.requests = 0;
265     params[i].status.errors = 0;
266    
267     params[i].total_connections = 0;
268     params[i].max_fd = 0;
269    
270     params[i].handle_sigbus = 0;
271     }
272    
273     #ifdef ENABLE_SMP
274     params[0].tid = father_id;
275    
276     for( i=1;i<max_threads;i++) {
277     if (pthread_create( &tid, NULL, &select_loop, &params[i]) != 0)
278     {
279     log_error_time();
280     fprintf(stderr,
281     "Could not dispatch threads.\n");
282     exit(1);
283     }
284     params[i].tid = tid;
285     }
286     #endif
287    
288     if (max_threads > 1) {
289     log_error_time();
290     fprintf(stderr,
291     "Generated pool of %d threads.\n", max_threads);
292     }
293    
294     global_server_params_size = max_threads;
295     global_server_params = params;
296    
297     return &params[0];
298     }
299    
300     void smp_reinit()
301     {
302     #ifdef ENABLE_SMP
303 nmav 1.2 int i;
304     server_params *params = global_server_params;
305     int max_threads = server_max_threads;
306 nmav 1.1 #else
307 nmav 1.2 int max_threads = 1;
308 nmav 1.1 #endif
309    
310 nmav 1.2 if (global_server_params_size < max_threads) {
311 nmav 1.1 log_error_time();
312     fprintf(stderr,
313     "Cannot increase threads on runtime.\n");
314     max_threads = global_server_params_size;
315 nmav 1.2 }
316 nmav 1.1
317     #ifdef ENABLE_SMP
318 nmav 1.2 for( i=1;i<max_threads;i++) {
319 nmav 1.1 pthread_t tid;
320     if (pthread_create( &tid, NULL, &select_loop, &params[i]) != 0)
321     {
322     log_error_time();
323     fprintf(stderr,
324     "Could not dispatch threads.\n");
325     exit(1);
326     }
327     params[i].tid = tid;
328 nmav 1.2 }
329 nmav 1.1 #endif
330    
331 nmav 1.2 if (max_threads > 0) {
332 nmav 1.1 log_error_time();
333     fprintf(stderr,
334     "Regenerated a pool of %d threads.\n", max_threads);
335 nmav 1.2 }
336 nmav 1.1
337 nmav 1.2 return;
338 nmav 1.1 }
339    
340 nmav 1.8 #ifdef ENABLE_HIC
341     #define hic_max_threads 1
342     static int hic_fd[2];
343    
344     /* This function will return a server_params pointer. This
345     * pointer is to be used as a pointer to the select loop.
346     */
347     static int hic_init()
348     {
349     //int *hic_fd[2];
350    
351     #ifdef ENABLE_SMP
352     pthread_t tid;
353    
354     if (pipe( hic_fd) == -1) {
355     log_error_time();
356     fprintf(stderr, "Error in pipe() for hic_fd.\n");
357     exit(1);
358     }
359    
360     // for( i=0;i<hic_max_threads;i++) {
361     if (pthread_create( &tid, NULL, &hic_main_loop, (void*)hic_fd) != 0)
362     {
363     log_error_time();
364     fprintf(stderr,
365     "Could not dispatch hic thread.\n");
366     exit(1);
367     }
368     // }
369    
370     log_error_time();
371     fprintf(stderr,
372     "Dispatched HIC main thread.\n");
373    
374    
375     #endif
376    
377     return hic_fd[1];
378     }
379    
380     #endif /* ENABLE_HIC */
381 nmav 1.1
382     static socket_type create_server_socket( int port, int secure)
383     {
384     socket_type server_s;
385    
386     server_s.secure = secure;
387 nmav 1.3 server_s.port = port;
388 nmav 1.1
389     server_s.socket = socket(SERVER_AF, SOCK_STREAM, IPPROTO_TCP);
390     if (server_s.socket == -1) {
391     DIE("unable to create socket");
392     }
393    
394     /* server socket is nonblocking */
395     if (set_nonblock_fd(server_s.socket) == -1) {
396     DIE("fcntl: unable to set server socket to nonblocking");
397     }
398    
399     /* close server socket on exec so cgi's can't write to it */
400     if (fcntl(server_s.socket, F_SETFD, 1) == -1) {
401     DIE("can't set close-on-exec on server socket!");
402     }
403    
404     /* reuse socket addr */
405     if ((setsockopt(server_s.socket, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
406     sizeof (sock_opt))) == -1) {
407     DIE("setsockopt");
408     }
409    
410     /* internet family-specific code encapsulated in bind_server() */
411     if (bind_server(server_s.socket, server_ip, port) == -1) {
412     DIE("unable to bind");
413     }
414    
415     /* listen: large number just in case your kernel is nicely tweaked */
416     if (listen(server_s.socket, backlog) == -1) {
417     DIE("unable to listen");
418     }
419     return server_s;
420     }
421    
422     static void drop_privs(void)
423     {
424     /* give away our privs if we can */
425     if (getuid() == 0) {
426     struct passwd *passwdbuf;
427     passwdbuf = getpwuid(server_uid);
428     if (passwdbuf == NULL) {
429     DIE("getpwuid");
430     }
431     if (initgroups(passwdbuf->pw_name, passwdbuf->pw_gid) == -1) {
432     DIE("initgroups");
433     }
434     if (setgid(server_gid) == -1) {
435     DIE("setgid");
436     }
437     if (setuid(server_uid) == -1) {
438     DIE("setuid");
439     }
440     /* test for failed-but-return-was-successful setuid
441     * http://www.securityportal.com/list-archive/bugtraq/2000/Jun/0101.html
442     */
443     if (setuid(0) != -1) {
444     DIE("icky Linux kernel bug!");
445     }
446     } else {
447     if (server_gid || server_uid) {
448     log_error_time();
449     fprintf(stderr, "Warning: "
450     "Not running as root: no attempt to change"
451     " to uid %d gid %d\n", server_uid, server_gid);
452     }
453     server_gid = getgid();
454     server_uid = getuid();
455     }
456     }
457    
458     /*
459     * Name: fixup_server_root
460     *
461     * Description: Makes sure the server root is valid.
462     *
463     */
464    
465     static void fixup_server_root()
466     {
467     char *dirbuf;
468    
469     if (!server_root) {
470     #ifdef SERVER_ROOT
471     server_root = strdup(SERVER_ROOT);
472     if (!server_root) {
473     perror("strdup (SERVER_ROOT)");
474     exit(1);
475     }
476     #else
477 nmav 1.6 fputs(SERVER_NAME": don't know where server root is. Please #define "
478 nmav 1.5 "SERVER_ROOT in defines.h\n"
479 nmav 1.1 "and recompile, or use the -c command line option to "
480     "specify it.\n", stderr);
481     exit(1);
482     #endif
483     }
484    
485     if (chdir(server_root) == -1) {
486     fprintf(stderr, "Could not chdir to \"%s\": aborting\n",
487     server_root);
488     exit(1);
489     }
490    
491     dirbuf = normalize_path(server_root);
492     free(server_root);
493     server_root = dirbuf;
494     }
495    

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26