Line data Source code
1 : #include "../burp.h"
2 : #include "../asfd.h"
3 : #include "../async.h"
4 : #include "../cntr.h"
5 : #include "../conf.h"
6 : #include "../conffile.h"
7 : #include "../fsops.h"
8 : #include "../handy.h"
9 : #include "../iobuf.h"
10 : #include "../lock.h"
11 : #include "../log.h"
12 : #include "auth.h"
13 : #include "ca.h"
14 : #include "child.h"
15 : #include "main.h"
16 : #include "monitor/status_server.h"
17 :
18 : // FIX THIS: Should be able to configure multiple addresses and ports.
19 : #define LISTEN_SOCKETS 32
20 :
21 : static int hupreload=0;
22 : static int hupreload_logged=0;
23 : static int gentleshutdown=0;
24 : static int gentleshutdown_logged=0;
25 :
26 : // These will also be used as the exit codes of the program and are therefore
27 : // unsigned integers.
28 : // Remember to update the man page if you update these.
29 : enum serret
30 : {
31 : SERVER_OK=0,
32 : SERVER_ERROR=1
33 : };
34 :
35 0 : static void huphandler(__attribute__ ((unused)) int sig)
36 : {
37 0 : hupreload=1;
38 : // Be careful about not logging inside a signal handler.
39 0 : hupreload_logged=0;
40 0 : }
41 :
42 0 : static void usr2handler(__attribute__ ((unused)) int sig)
43 : {
44 0 : gentleshutdown=1;
45 : // Be careful about not logging inside a signal handler.
46 0 : gentleshutdown_logged=0;
47 0 : }
48 :
49 : static void init_fds(int *fds)
50 : {
51 0 : for(int i=0; i<LISTEN_SOCKETS; i++) fds[i]=-1;
52 : }
53 :
54 : static void close_fds(int *fds)
55 : {
56 0 : for(int i=0; i<LISTEN_SOCKETS; i++) close_fd(&(fds[i]));
57 : }
58 :
59 : // Remove any exiting child pids from our list.
60 0 : static void chld_check_for_exiting(struct async *mainas)
61 : {
62 : pid_t p;
63 : int status;
64 : struct asfd *asfd;
65 :
66 0 : while((p=waitpid(-1, &status, WNOHANG))>0)
67 : {
68 : // Logging a message here appeared to occasionally lock burp up
69 : // on a Ubuntu server that I used to use.
70 0 : for(asfd=mainas->asfd; asfd; asfd=asfd->next)
71 : {
72 0 : if(p!=asfd->pid) continue;
73 0 : mainas->asfd_remove(mainas, asfd);
74 0 : asfd_free(&asfd);
75 0 : break;
76 : }
77 : }
78 0 : }
79 :
80 0 : static int init_listen_socket(const char *address, const char *port, int *fds)
81 : {
82 : int i;
83 : int gai_ret;
84 : struct addrinfo hints;
85 0 : struct addrinfo *rp=NULL;
86 0 : struct addrinfo *info=NULL;
87 :
88 : close_fds(fds);
89 :
90 : memset(&hints, 0, sizeof(struct addrinfo));
91 : hints.ai_family=AF_UNSPEC;
92 0 : hints.ai_socktype=SOCK_STREAM;
93 0 : hints.ai_protocol=IPPROTO_TCP;
94 0 : hints.ai_flags=AI_NUMERICHOST;
95 0 : hints.ai_flags|=AI_PASSIVE;
96 :
97 0 : if((gai_ret=getaddrinfo(address, port, &hints, &info)))
98 : {
99 0 : logp("unable to getaddrinfo on port %s: %s\n",
100 : port, gai_strerror(gai_ret));
101 0 : return -1;
102 : }
103 :
104 0 : i=0;
105 0 : for(rp=info; rp && i<LISTEN_SOCKETS; rp=rp->ai_next)
106 : {
107 0 : fds[i]=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
108 0 : if(fds[i]<0)
109 : {
110 0 : logp("unable to create socket on port %s: %s\n",
111 0 : port, strerror(errno));
112 0 : continue;
113 : }
114 0 : set_keepalive(fds[i], 1);
115 : #ifdef HAVE_IPV6
116 0 : if(rp->ai_family==AF_INET6)
117 : {
118 : // Attempt to say that it should not listen on IPv6
119 : // only.
120 0 : int optval=0;
121 0 : setsockopt(fds[i], IPPROTO_IPV6, IPV6_V6ONLY,
122 : &optval, sizeof(optval));
123 : }
124 : #endif
125 0 : reuseaddr(fds[i]);
126 0 : if(bind(fds[i], rp->ai_addr, rp->ai_addrlen))
127 : {
128 0 : logp("unable to bind socket on port %s: %s\n",
129 0 : port, strerror(errno));
130 0 : close(fds[i]);
131 0 : fds[i]=-1;
132 0 : continue;
133 : }
134 :
135 : // Say that we are happy to accept connections.
136 0 : if(listen(fds[i], 5)<0)
137 : {
138 0 : close_fd(&(fds[i]));
139 0 : logp("could not listen on main socket %s\n", port);
140 0 : return -1;
141 : }
142 :
143 : #ifdef HAVE_WIN32
144 : {
145 : u_long ioctlArg=0;
146 : ioctlsocket(fds[i], FIONBIO, &ioctlArg);
147 : }
148 : #endif
149 0 : i++;
150 : }
151 :
152 0 : freeaddrinfo(info);
153 :
154 0 : if(!i)
155 : {
156 0 : logp("could not listen on address: %s\n", address);
157 : #ifdef HAVE_IPV6
158 0 : if(strchr(address, ':'))
159 0 : logp("maybe check whether your OS has IPv6 enabled.\n");
160 : #endif
161 : return -1;
162 : }
163 :
164 : return 0;
165 : }
166 :
167 0 : void setup_signals(void)
168 : {
169 : // Ignore SIGPIPE - we are careful with read and write return values.
170 0 : signal(SIGPIPE, SIG_IGN);
171 :
172 0 : setup_signal(SIGHUP, huphandler);
173 0 : setup_signal(SIGUSR2, usr2handler);
174 0 : }
175 :
176 0 : static int run_child(int *cfd, SSL_CTX *ctx, struct sockaddr_storage *addr,
177 : int status_wfd, int status_rfd, const char *conffile, int forking)
178 : {
179 0 : int ret=-1;
180 0 : int ca_ret=0;
181 0 : SSL *ssl=NULL;
182 0 : BIO *sbio=NULL;
183 0 : struct conf **confs=NULL;
184 0 : struct conf **cconfs=NULL;
185 0 : struct cntr *cntr=NULL;
186 0 : struct async *as=NULL;
187 0 : const char *cname=NULL;
188 0 : struct asfd *asfd=NULL;
189 0 : int is_status_server=0;
190 :
191 0 : if(!(confs=confs_alloc())
192 0 : || !(cconfs=confs_alloc()))
193 : goto end;
194 :
195 0 : set_peer_env_vars(addr);
196 :
197 : // Reload global config, in case things have changed. This means that
198 : // the server does not need to be restarted for most conf changes.
199 0 : confs_init(confs);
200 0 : confs_init(cconfs);
201 0 : if(conf_load_global_only(conffile, confs)) goto end;
202 :
203 : // Hack to keep forking turned off if it was specified as off on the
204 : // command line.
205 0 : if(!forking) set_int(confs[OPT_FORK], 0);
206 :
207 0 : if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE))
208 0 : || !(ssl=SSL_new(ctx)))
209 : {
210 0 : logp("There was a problem joining ssl to the socket\n");
211 0 : goto end;
212 : }
213 0 : SSL_set_bio(ssl, sbio, sbio);
214 :
215 : /* Do not try to check peer certificate straight away.
216 : Clients can send a certificate signing request when they have
217 : no certificate. */
218 0 : SSL_set_verify(ssl, SSL_VERIFY_PEER
219 : /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0);
220 :
221 0 : if(ssl_do_accept(ssl))
222 : goto end;
223 0 : if(!(as=async_alloc())
224 0 : || as->init(as, 0)
225 0 : || !(asfd=setup_asfd_ssl(as, "main socket", cfd, ssl)))
226 : goto end;
227 0 : asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT]));
228 0 : asfd->ratelimit=get_float(confs[OPT_RATELIMIT]);
229 :
230 0 : if(authorise_server(as->asfd, confs, cconfs)
231 0 : || !(cname=get_string(cconfs[OPT_CNAME])) || !*cname)
232 : {
233 : // Add an annoying delay in case they are tempted to
234 : // try repeatedly.
235 0 : log_and_send(as->asfd, "unable to authorise on server");
236 0 : sleep(1);
237 0 : goto end;
238 : }
239 :
240 0 : if(!get_int(cconfs[OPT_ENABLED]))
241 : {
242 0 : log_and_send(as->asfd, "client not enabled on server");
243 0 : sleep(1);
244 0 : goto end;
245 : }
246 :
247 : // Set up counters. Have to wait until here to get cname.
248 0 : if(!(cntr=cntr_alloc())
249 0 : || cntr_init(cntr, cname))
250 : goto end;
251 0 : set_cntr(confs[OPT_CNTR], cntr);
252 0 : set_cntr(cconfs[OPT_CNTR], cntr);
253 :
254 : /* At this point, the client might want to get a new certificate
255 : signed. Clients on 1.3.2 or newer can do this. */
256 0 : if((ca_ret=ca_server_maybe_sign_client_cert(as->asfd, confs, cconfs))<0)
257 : {
258 0 : logp("Error signing client certificate request for %s\n",
259 : cname);
260 0 : goto end;
261 : }
262 0 : else if(ca_ret>0)
263 : {
264 : // Certificate signed and sent back.
265 : // Everything is OK, but we will close this instance
266 : // so that the client can start again with a new
267 : // connection and its new certificates.
268 0 : logp("Signed and returned client certificate request for %s\n",
269 : cname);
270 0 : ret=0;
271 0 : goto end;
272 : }
273 :
274 : /* Now it is time to check the certificate. */
275 0 : if(ssl_check_cert(ssl, confs, cconfs))
276 : {
277 0 : log_and_send(as->asfd, "check cert failed on server");
278 0 : goto end;
279 : }
280 :
281 0 : if(status_rfd>=0)
282 : {
283 0 : is_status_server=1;
284 0 : if(!setup_asfd(as, "status server parent socket", &status_rfd))
285 : goto end;
286 : }
287 :
288 0 : ret=child(as, is_status_server, status_wfd, confs, cconfs);
289 : end:
290 0 : *cfd=-1;
291 0 : if(as && asfd_flush_asio(as->asfd))
292 0 : ret=-1;
293 0 : async_asfd_free_all(&as); // This closes cfd for us.
294 0 : logp("exit child\n");
295 0 : if(cntr) cntr_free(&cntr);
296 0 : if(confs)
297 : {
298 0 : set_cntr(confs[OPT_CNTR], NULL);
299 0 : confs_free(&confs);
300 : }
301 0 : if(cconfs)
302 : {
303 0 : set_cntr(cconfs[OPT_CNTR], NULL);
304 0 : confs_free(&cconfs);
305 : }
306 0 : return ret;
307 : }
308 :
309 0 : static int chld_check_counts(struct conf **confs, struct asfd *asfd)
310 : {
311 0 : int c_count=0;
312 0 : int sc_count=0;
313 : struct asfd *a;
314 :
315 : // Need to count status children separately from normal children.
316 0 : for(a=asfd->as->asfd; a; a=a->next)
317 : {
318 0 : switch(a->fdtype)
319 : {
320 : case ASFD_FD_SERVER_PIPE_READ:
321 0 : c_count++; break;
322 : case ASFD_FD_SERVER_PIPE_WRITE:
323 0 : sc_count++; break;
324 : default:
325 : break;
326 : }
327 : }
328 :
329 0 : switch(asfd->fdtype)
330 : {
331 : case ASFD_FD_SERVER_LISTEN_MAIN:
332 0 : if(c_count<get_int(confs[OPT_MAX_CHILDREN]))
333 : break;
334 0 : logp("Too many child processes.\n");
335 : return -1;
336 : case ASFD_FD_SERVER_LISTEN_STATUS:
337 0 : if(sc_count<get_int(confs[OPT_MAX_STATUS_CHILDREN]))
338 : break;
339 0 : logp("Too many status child processes.\n");
340 : return -1;
341 : default:
342 0 : logp("Unexpected fdtype in %s: %d.\n",
343 : __func__, asfd->fdtype);
344 : return -1;
345 : }
346 :
347 : return 0;
348 : }
349 :
350 : static struct asfd *setup_parent_child_pipe(struct async *as,
351 : const char *desc,
352 : int *fd_to_use, int *fd_to_close, pid_t childpid,
353 : enum asfd_fdtype fdtype)
354 : {
355 : struct asfd *newfd;
356 0 : close_fd(fd_to_close);
357 0 : if(!(newfd=setup_asfd(as, desc, fd_to_use)))
358 : return NULL;
359 0 : newfd->pid=childpid;
360 0 : newfd->fdtype=fdtype;
361 : return newfd;
362 : }
363 :
364 0 : static int setup_parent_child_pipes(struct asfd *asfd,
365 : pid_t childpid, int *rfd, int *wfd)
366 : {
367 : struct asfd *newfd;
368 0 : struct async *as=asfd->as;
369 0 : switch(asfd->fdtype)
370 : {
371 : case ASFD_FD_SERVER_LISTEN_MAIN:
372 0 : logp("forked child: %d\n", childpid);
373 0 : if(!(newfd=setup_parent_child_pipe(as,
374 : "pipe from child",
375 : rfd, wfd, childpid,
376 : ASFD_FD_SERVER_PIPE_READ)))
377 : return -1;
378 : return 0;
379 : case ASFD_FD_SERVER_LISTEN_STATUS:
380 0 : logp("forked status server child: %d\n", childpid);
381 0 : if(!(newfd=setup_parent_child_pipe(as,
382 : "pipe to status child",
383 : wfd, rfd, childpid,
384 : ASFD_FD_SERVER_PIPE_WRITE)))
385 : return -1;
386 0 : newfd->attempt_reads=0;
387 : return 0;
388 : default:
389 0 : logp("Strange fdtype after fork: %d\n",
390 : asfd->fdtype);
391 : return -1;
392 : }
393 :
394 : return 0;
395 : }
396 :
397 0 : static int process_incoming_client(struct asfd *asfd, SSL_CTX *ctx,
398 : const char *conffile, struct conf **confs)
399 : {
400 0 : int cfd=-1;
401 : pid_t childpid;
402 : int pipe_rfd[2];
403 : int pipe_wfd[2];
404 0 : socklen_t client_length=0;
405 : struct sockaddr_storage client_name;
406 0 : enum asfd_fdtype fdtype=asfd->fdtype;
407 0 : int forking=get_int(confs[OPT_FORK]);
408 :
409 0 : client_length=sizeof(client_name);
410 0 : if((cfd=accept(asfd->fd,
411 : (struct sockaddr *)&client_name, &client_length))==-1)
412 : {
413 : // Look out, accept will get interrupted by SIGCHLDs.
414 0 : if(errno==EINTR) return 0;
415 0 : logp("accept failed on %s (%d) in %s: %s\n", asfd->desc,
416 : asfd->fd, __func__, strerror(errno));
417 0 : return -1;
418 : }
419 0 : reuseaddr(cfd);
420 0 : if(log_peer_address(&client_name))
421 : return -1;
422 :
423 0 : if(!forking)
424 0 : return run_child(&cfd, ctx,
425 : &client_name, -1, -1, conffile, forking);
426 :
427 0 : if(chld_check_counts(confs, asfd))
428 : {
429 0 : logp("Closing new connection.\n");
430 0 : close_fd(&cfd);
431 0 : return 0;
432 : }
433 :
434 0 : if(pipe(pipe_rfd)<0 || pipe(pipe_wfd)<0)
435 : {
436 0 : logp("pipe failed: %s", strerror(errno));
437 0 : close_fd(&cfd);
438 0 : return -1;
439 : }
440 :
441 0 : switch((childpid=fork()))
442 : {
443 : case -1:
444 0 : logp("fork failed: %s\n", strerror(errno));
445 0 : return -1;
446 : case 0:
447 : {
448 : // Child.
449 : int p;
450 : int ret;
451 : struct sigaction sa;
452 0 : struct async *as=asfd->as;
453 0 : async_asfd_free_all(&as);
454 :
455 : // Close unnecessary file descriptors.
456 : // Go up to FD_SETSIZE and hope for the best.
457 : // FIX THIS: Now that async_asfd_free_all() is doing
458 : // everything, double check whether this is needed.
459 0 : for(p=3; p<(int)FD_SETSIZE; p++)
460 : {
461 0 : if(p!=pipe_rfd[1]
462 0 : && p!=pipe_wfd[0]
463 0 : && p!=cfd)
464 0 : close(p);
465 : }
466 :
467 : // Set SIGCHLD back to default, so that I
468 : // can get sensible returns from waitpid.
469 : memset(&sa, 0, sizeof(sa));
470 : sa.sa_handler=SIG_DFL;
471 0 : sigaction(SIGCHLD, &sa, NULL);
472 :
473 0 : close(pipe_rfd[0]); // close read end
474 0 : close(pipe_wfd[1]); // close write end
475 :
476 0 : confs_free_content(confs);
477 0 : confs_init(confs);
478 :
479 0 : ret=run_child(&cfd, ctx, &client_name, pipe_rfd[1],
480 : fdtype==ASFD_FD_SERVER_LISTEN_STATUS?pipe_wfd[0]:-1,
481 : conffile, forking);
482 :
483 0 : close(pipe_rfd[1]);
484 0 : close(pipe_wfd[0]);
485 0 : close_fd(&cfd);
486 0 : exit(ret);
487 : }
488 : default:
489 : // Parent.
490 0 : close(pipe_rfd[1]); // close write end
491 0 : close(pipe_wfd[0]); // close read end
492 0 : close_fd(&cfd);
493 :
494 0 : return setup_parent_child_pipes(asfd, childpid,
495 : &pipe_rfd[0], &pipe_wfd[1]);
496 : }
497 : }
498 :
499 0 : static int daemonise(void)
500 : {
501 : /* process ID */
502 : pid_t pid;
503 :
504 : /* session ID */
505 : pid_t sid;
506 :
507 : /* fork new child and end parent */
508 0 : pid=fork();
509 :
510 : /* did we fork? */
511 0 : if(pid<0)
512 : {
513 0 : logp("error forking\n");
514 0 : return -1;
515 : }
516 :
517 : /* parent? */
518 0 : if(pid>0)
519 0 : exit(EXIT_SUCCESS);
520 :
521 : /* now we are in the child process */
522 :
523 : /* create a session and set the process group ID */
524 0 : sid=setsid();
525 0 : if(sid<0)
526 : {
527 0 : logp("error setting sid\n");
528 0 : return -1;
529 : }
530 :
531 : /* leave and unblock current working dir */
532 0 : if(chdir("/")<0)
533 : {
534 0 : logp("error changing working dir\n");
535 0 : return -1;
536 : }
537 :
538 : /* close std* */
539 0 : close(STDIN_FILENO);
540 0 : close(STDOUT_FILENO);
541 0 : close(STDERR_FILENO);
542 :
543 0 : return 0;
544 : }
545 :
546 0 : static int relock(struct lock *lock)
547 : {
548 0 : int tries=5;
549 0 : for(; tries>0; tries--)
550 : {
551 0 : lock_get(lock);
552 0 : switch(lock->status)
553 : {
554 : case GET_LOCK_GOT: return 0;
555 : case GET_LOCK_NOT_GOT:
556 0 : sleep(2);
557 : break;
558 : case GET_LOCK_ERROR:
559 : default:
560 0 : logp("Error when trying to re-get lockfile after forking.\n");
561 0 : return -1;
562 : }
563 : }
564 0 : logp("Unable to re-get lockfile after forking.\n");
565 0 : return -1;
566 : }
567 :
568 0 : static int run_server(struct conf **confs, const char *conffile,
569 : int *rfds, int *sfds)
570 : {
571 0 : int i=0;
572 0 : int ret=-1;
573 0 : SSL_CTX *ctx=NULL;
574 0 : int found_normal_child=0;
575 0 : struct asfd *asfd=NULL;
576 0 : struct asfd *scfd=NULL;
577 0 : struct async *mainas=NULL;
578 0 : const char *port=get_string(confs[OPT_PORT]);
579 0 : const char *address=get_string(confs[OPT_ADDRESS]);
580 0 : const char *status_port=get_string(confs[OPT_STATUS_PORT]);
581 0 : const char *status_address=get_string(confs[OPT_STATUS_ADDRESS]);
582 :
583 0 : if(!(ctx=ssl_initialise_ctx(confs)))
584 : {
585 0 : logp("error initialising ssl ctx\n");
586 0 : goto end;
587 : }
588 0 : if((ssl_load_dh_params(ctx, confs)))
589 : {
590 0 : logp("error loading dh params\n");
591 0 : goto end;
592 : }
593 :
594 0 : if(init_listen_socket(address, port, rfds)
595 0 : || init_listen_socket(status_address, status_port, sfds))
596 : goto end;
597 :
598 0 : if(!(mainas=async_alloc())
599 0 : || mainas->init(mainas, 0))
600 : goto end;
601 :
602 0 : for(i=0; i<LISTEN_SOCKETS && rfds[i]!=-1; i++)
603 : {
604 : struct asfd *newfd;
605 0 : if(!(newfd=setup_asfd(mainas,
606 : "main server socket", &rfds[i])))
607 : goto end;
608 0 : newfd->fdtype=ASFD_FD_SERVER_LISTEN_MAIN;
609 : }
610 0 : for(i=0; i<LISTEN_SOCKETS && sfds[i]!=-1; i++)
611 : {
612 : struct asfd *newfd;
613 0 : if(!(newfd=setup_asfd(mainas,
614 : "main server status socket", &sfds[i])))
615 : goto end;
616 0 : newfd->fdtype=ASFD_FD_SERVER_LISTEN_STATUS;
617 : }
618 :
619 0 : while(!hupreload)
620 : {
621 : int removed;
622 0 : switch(mainas->read_write(mainas))
623 : {
624 : case 0:
625 0 : for(asfd=mainas->asfd; asfd; asfd=asfd->next)
626 : {
627 0 : if(asfd->new_client)
628 : {
629 : // Incoming client.
630 0 : asfd->new_client=0;
631 0 : if(process_incoming_client(asfd,
632 : ctx, conffile, confs))
633 : goto end;
634 0 : if(!get_int(confs[OPT_FORK]))
635 : {
636 0 : gentleshutdown++;
637 0 : ret=1;
638 0 : goto end;
639 : }
640 0 : continue;
641 : }
642 : }
643 : break;
644 : default:
645 0 : removed=0;
646 : // Maybe one of the fds had a problem.
647 : // Find and remove it and carry on if possible.
648 0 : for(asfd=mainas->asfd; asfd; )
649 : {
650 : struct asfd *a;
651 0 : if(!asfd->want_to_remove)
652 : {
653 0 : asfd=asfd->next;
654 0 : continue;
655 : }
656 0 : mainas->asfd_remove(mainas, asfd);
657 0 : logp("%s: disconnected fd %d\n",
658 0 : asfd->desc, asfd->fd);
659 0 : a=asfd->next;
660 0 : asfd_free(&asfd);
661 0 : asfd=a;
662 0 : removed++;
663 : }
664 0 : if(removed) break;
665 : // If we got here, there was no fd to remove.
666 : // It is a fatal error.
667 : goto end;
668 : }
669 :
670 0 : for(asfd=mainas->asfd; asfd; asfd=asfd->next)
671 : {
672 : size_t wlen;
673 0 : if(asfd->fdtype!=ASFD_FD_SERVER_PIPE_READ
674 0 : || !asfd->rbuf->buf) continue;
675 0 : wlen=asfd->rbuf->len;
676 : // One of the child processes is giving us information.
677 : // Try to append it to any of the status child pipes.
678 0 : for(scfd=mainas->asfd; scfd; scfd=scfd->next)
679 : {
680 0 : if(scfd->fdtype!=ASFD_FD_SERVER_PIPE_WRITE)
681 0 : continue;
682 0 : switch(scfd->append_all_to_write_buffer(scfd,
683 0 : asfd->rbuf))
684 : {
685 : case APPEND_OK:
686 : // Hack - the append function
687 : // will set the length to zero
688 : // on success. Set it back for
689 : // the next status child pipe.
690 0 : asfd->rbuf->len=wlen;
691 0 : break;
692 : case APPEND_BLOCKED:
693 : break;
694 : default:
695 : goto end;
696 : }
697 : }
698 : // Free the information, even if we did not manage
699 : // to append it. That should be OK, more will be along
700 : // soon.
701 0 : iobuf_free_content(asfd->rbuf);
702 : }
703 :
704 0 : chld_check_for_exiting(mainas);
705 :
706 : // Leave if we had a SIGUSR1 and there are no children running.
707 0 : if(gentleshutdown)
708 : {
709 0 : if(!gentleshutdown_logged)
710 : {
711 0 : logp("got SIGUSR2 gentle reload signal\n");
712 0 : logp("will shut down once children have exited\n");
713 0 : gentleshutdown_logged++;
714 : }
715 : // FIX THIS:
716 : // found_normal_child=chld_add_fd_to_normal_sets(confs, &fsr, &fse, &mfd);
717 : else if(!found_normal_child)
718 : {
719 0 : logp("all children have exited - shutting down\n");
720 0 : break;
721 : }
722 : }
723 : }
724 :
725 0 : if(hupreload) logp("got SIGHUP reload signal\n");
726 :
727 : ret=0;
728 : end:
729 0 : async_asfd_free_all(&mainas);
730 0 : if(ctx) ssl_destroy_ctx(ctx);
731 0 : return ret;
732 : }
733 :
734 0 : int server(struct conf **confs, const char *conffile,
735 : struct lock *lock, int generate_ca_only)
736 : {
737 0 : enum serret ret=SERVER_ERROR;
738 : int rfds[LISTEN_SOCKETS]; // Sockets for clients to connect to.
739 : int sfds[LISTEN_SOCKETS]; // Status server sockets.
740 :
741 : //return champ_test(confs);
742 :
743 : init_fds(rfds);
744 : init_fds(sfds);
745 :
746 0 : if(ca_server_setup(confs)) goto error;
747 0 : if(generate_ca_only)
748 : {
749 0 : logp("The '-g' command line option was given. Exiting now.\n");
750 0 : goto end;
751 : }
752 :
753 0 : if(get_int(confs[OPT_FORK]) && get_int(confs[OPT_DAEMON]))
754 : {
755 0 : if(daemonise() || relock(lock)) goto error;
756 : }
757 :
758 0 : ssl_load_globals();
759 :
760 0 : while(!gentleshutdown)
761 : {
762 0 : if(run_server(confs, conffile, rfds, sfds))
763 : goto error;
764 :
765 0 : if(hupreload && !gentleshutdown)
766 : {
767 0 : if(reload(confs, conffile,
768 : 0 // Not first time.
769 : ))
770 : goto error;
771 : }
772 0 : hupreload=0;
773 : }
774 :
775 : end:
776 : ret=SERVER_OK;
777 : error:
778 : close_fds(rfds);
779 : close_fds(sfds);
780 :
781 : // FIX THIS: Have an enum for a return value, so that it is more obvious what
782 : // is happening, like client.c does.
783 0 : return ret;
784 : }
|