1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 2008-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library; If not, see
16    <http://www.gnu.org/licenses/>.  */
17 
18 /* This is an `m-server' - a universal framework for multi-process TCP
19    servers. An `m-' stands for `mail-', or `multi-' or maybe `meta-',
20    I don't remember what. */
21 
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <syslog.h>
32 #include <netdb.h>
33 #include <sys/socket.h>
34 #include <sys/un.h>
35 #include <sys/stat.h>
36 #include <limits.h>
37 #include <mailutils/cctype.h>
38 #include <mailutils/server.h>
39 #include <mailutils/error.h>
40 #include <mailutils/errno.h>
41 #include <mailutils/cfg.h>
42 #include <mailutils/nls.h>
43 #include <mailutils/daemon.h>
44 #include <mailutils/acl.h>
45 #include <mailutils/sockaddr.h>
46 #include <mailutils/url.h>
47 #include <mailutils/util.h>
48 
49 typedef RETSIGTYPE (*mu_sig_handler_t) (int);
50 
51 static mu_sig_handler_t
set_signal(int sig,mu_sig_handler_t handler)52 set_signal (int sig, mu_sig_handler_t handler)
53 {
54 #ifdef HAVE_SIGACTION
55   {
56     struct sigaction act, oldact;
57     act.sa_handler = handler;
58     sigemptyset (&act.sa_mask);
59     act.sa_flags = 0;
60     sigaction (sig, &act, &oldact);
61     return oldact.sa_handler;
62   }
63 #else
64   return signal (sig, handler);
65 #endif
66 }
67 
68 #ifndef NSIG
69 # define NSIG 64
70 #endif
71 
72 struct _mu_m_server
73 {
74   char *ident;                   /* Server identifier, for logging purposes.*/
75   int deftype;                   /* Default server type: MU_IP_TCP/MU_IP_UDP */
76   mu_server_t server;            /* The server object. */
77   mu_list_t srvlist;             /* A list of configured mu_ip_server_t
78 				    objects. It is cleared after the objects
79 				    are opened and attached to the server. */
80   mu_m_server_preflight_fp preflight; /* Pre-flight check function */
81   mu_m_server_handler_fp conn;   /* Connection handler function. */
82   mu_m_server_handler_fp prefork;/* Pre-fork function. */
83   void *data;                    /* User-supplied data for conn and prefork. */
84   size_t app_data_size;
85 
86   int mode;                      /* Server mode: should be removed. */
87 
88   int foreground;                /* Should the server remain in foregorund? */
89   size_t max_children;           /* Maximum number of sub-processes to run. */
90   size_t num_children;           /* Current number of running sub-processes. */
91   pid_t *child_pid;
92   char *pidfile;                 /* Name of a PID-file. */
93   struct mu_sockaddr_hints hints; /* Default address hints. */
94   time_t timeout;                /* Default idle timeout. */
95   mu_acl_t acl;                  /* Global access control list. */
96 
97   sigset_t sigmask;              /* A set of signals to handle by the
98 				    m-server.  */
99   mu_sig_handler_t sigtab[NSIG]; /* Keeps old signal handlers. */
100   const char *(*strexit) (int);  /* Convert integer exit code to textual
101 				    description. */
102 };
103 
104 
105 static int need_cleanup = 0;
106 static int stop = 0; /* FIXME: Must be per-m-server */
107 static mu_list_t m_server_list;
108 
109 #define UNUSED_PID ((pid_t)-1)
110 
111 static void
alloc_children(mu_m_server_t srv)112 alloc_children (mu_m_server_t srv)
113 {
114   int i;
115   size_t size = srv->max_children * sizeof (srv->child_pid[0]);
116 
117   srv->child_pid = malloc (size);
118 
119   if (!srv->child_pid)
120     {
121       mu_error ("%s", mu_strerror (ENOMEM));
122       abort ();
123     }
124 
125   for (i = 0; i < srv->max_children; i++)
126     srv->child_pid[i] = UNUSED_PID;
127 }
128 
129 static void
register_child(mu_m_server_t msrv,pid_t pid)130 register_child (mu_m_server_t msrv, pid_t pid)
131 {
132   int i;
133 
134   msrv->num_children++;
135   for (i = 0; i < msrv->max_children; i++)
136     if (msrv->child_pid[i] == UNUSED_PID)
137       {
138 	msrv->child_pid[i] = pid;
139 	return;
140       }
141   mu_error ("%s:%d: cannot find free PID slot (internal error?)",
142 	    __FILE__, __LINE__);
143 }
144 
145 static int
unregister_child(mu_m_server_t msrv,pid_t pid)146 unregister_child (mu_m_server_t msrv, pid_t pid)
147 {
148   int i;
149 
150   msrv->num_children--;
151   for (i = 0; i < msrv->max_children; i++)
152     if (msrv->child_pid[i] == pid)
153       {
154 	msrv->child_pid[i] = UNUSED_PID;
155 	return 0;
156       }
157   return 1;
158 }
159 
160 static void
terminate_children(mu_m_server_t msrv)161 terminate_children (mu_m_server_t msrv)
162 {
163   if (msrv->child_pid)
164     {
165       int i;
166 
167       for (i = 0; i < msrv->max_children; i++)
168 	if (msrv->child_pid[i] != UNUSED_PID)
169 	  kill (msrv->child_pid[i], SIGTERM);
170     }
171 }
172 
173 void
mu_m_server_stop(int code)174 mu_m_server_stop (int code)
175 {
176   stop = code;
177 }
178 
179 struct exit_data
180 {
181   pid_t pid;
182   int status;
183 };
184 
185 static int
m_server_cleanup(void * item,void * data)186 m_server_cleanup (void *item, void *data)
187 {
188   mu_m_server_t msrv = item;
189   struct exit_data *datp = data;
190 
191   if (unregister_child (msrv, datp->pid) == 0)
192     {
193       if (WIFEXITED (datp->status))
194 	{
195 	  int prio = MU_DIAG_INFO;
196 	  int code = WEXITSTATUS (datp->status);
197 	  if (code == 0)
198 	    prio = MU_DIAG_DEBUG;
199 	  if (msrv->strexit)
200 	    mu_diag_output (prio,
201 			    _("process %lu finished with code %d (%s)"),
202 			    (unsigned long) datp->pid,
203 			    code,
204 			    msrv->strexit (code));
205 	  else
206 	    mu_diag_output (prio,
207 			    _("process %lu finished with code %d"),
208 			    (unsigned long) datp->pid,
209 			    code);
210 	}
211       else if (WIFSIGNALED (datp->status))
212 	mu_diag_output (MU_DIAG_ERR, "process %lu terminated on signal %d",
213 			(unsigned long) datp->pid,
214 			WTERMSIG (datp->status));
215       else
216 	mu_diag_output (MU_DIAG_ERR,
217 			"process %lu terminated (cause unknown)",
218 			(unsigned long) datp->pid);
219       return MU_ERR_USER0;
220     }
221   return 0;
222 }
223 
224 static int
mu_m_server_idle(void * server_data MU_ARG_UNUSED)225 mu_m_server_idle (void *server_data MU_ARG_UNUSED)
226 {
227   if (need_cleanup)
228     {
229       struct exit_data ex;
230 
231       need_cleanup = 0;
232       while ( (ex.pid = waitpid (-1, &ex.status, WNOHANG)) > 0)
233 	/* Iterate over all m-servers and notify them about the fact. */
234 	mu_list_foreach (m_server_list, m_server_cleanup, &ex);
235     }
236   return stop;
237 }
238 
239 static RETSIGTYPE
m_srv_signal(int signo)240 m_srv_signal (int signo)
241 {
242   switch (signo)
243     {
244     case SIGCHLD:
245       need_cleanup = 1;
246       break;
247 
248     default:
249       stop = 1;
250       break;
251     }
252 #ifndef HAVE_SIGACTION
253   signal (signo, m_srv_sigchld);
254 #endif
255 }
256 
257 void
mu_m_server_create(mu_m_server_t * psrv,const char * ident)258 mu_m_server_create (mu_m_server_t *psrv, const char *ident)
259 {
260   mu_m_server_t srv = calloc (1, sizeof *srv);
261   if (!srv)
262     {
263       mu_error ("%s", mu_strerror (ENOMEM));
264       exit (1);
265     }
266   if (ident)
267     {
268       srv->ident = strdup (ident);
269       if (!srv->ident)
270 	{
271 	  mu_error ("%s", mu_strerror (ENOMEM));
272 	  exit (1);
273 	}
274     }
275   srv->deftype = MU_IP_TCP;
276   MU_ASSERT (mu_server_create (&srv->server));
277   mu_server_set_idle (srv->server, mu_m_server_idle);
278   sigemptyset (&srv->sigmask);
279   sigaddset (&srv->sigmask, SIGCHLD);
280   sigaddset (&srv->sigmask, SIGINT);
281   sigaddset (&srv->sigmask, SIGTERM);
282   sigaddset (&srv->sigmask, SIGQUIT);
283   sigaddset (&srv->sigmask, SIGHUP);
284   *psrv = srv;
285   if (!m_server_list)
286     mu_list_create (&m_server_list);
287   mu_list_append (m_server_list, srv);
288 }
289 
290 void
mu_m_server_set_type(mu_m_server_t srv,int type)291 mu_m_server_set_type (mu_m_server_t srv, int type)
292 {
293   srv->deftype = type;
294 }
295 
296 void
mu_m_server_get_type(mu_m_server_t srv,int * type)297 mu_m_server_get_type (mu_m_server_t srv, int *type)
298 {
299   *type = srv->deftype;
300 }
301 
302 void
mu_m_server_set_sigset(mu_m_server_t srv,sigset_t * sigset)303 mu_m_server_set_sigset (mu_m_server_t srv, sigset_t *sigset)
304 {
305   srv->sigmask = *sigset;
306   sigaddset (&srv->sigmask, SIGCHLD);
307 }
308 
309 void
mu_m_server_get_sigset(mu_m_server_t srv,sigset_t * sigset)310 mu_m_server_get_sigset (mu_m_server_t srv, sigset_t *sigset)
311 {
312   *sigset = srv->sigmask;
313 }
314 
315 void
mu_m_server_set_mode(mu_m_server_t srv,int mode)316 mu_m_server_set_mode (mu_m_server_t srv, int mode)
317 {
318   srv->mode = mode;
319 }
320 
321 void
mu_m_server_set_conn(mu_m_server_t srv,mu_m_server_handler_fp conn)322 mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_handler_fp conn)
323 {
324   srv->conn = conn;
325 }
326 
327 void
mu_m_server_set_prefork(mu_m_server_t srv,mu_m_server_handler_fp fun)328 mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_handler_fp fun)
329 {
330   srv->prefork = fun;
331 }
332 
333 void
mu_m_server_set_data(mu_m_server_t srv,void * data)334 mu_m_server_set_data (mu_m_server_t srv, void *data)
335 {
336   srv->data = data;
337 }
338 
339 void
mu_m_server_set_max_children(mu_m_server_t srv,size_t num)340 mu_m_server_set_max_children (mu_m_server_t srv, size_t num)
341 {
342   srv->max_children = num;
343 }
344 
345 int
mu_m_server_set_pidfile(mu_m_server_t srv,const char * pidfile)346 mu_m_server_set_pidfile (mu_m_server_t srv, const char *pidfile)
347 {
348   char *p = strdup (pidfile);
349   if (!p)
350     return errno;
351   free (srv->pidfile);
352   srv->pidfile = p;
353   return 0;
354 }
355 
356 int
mu_m_server_set_foreground(mu_m_server_t srv,int enable)357 mu_m_server_set_foreground (mu_m_server_t srv, int enable)
358 {
359   srv->foreground = enable;
360   return 0;
361 }
362 
363 void
mu_m_server_set_strexit(mu_m_server_t srv,const char * (* fun)(int))364 mu_m_server_set_strexit (mu_m_server_t srv, const char *(*fun) (int))
365 {
366   srv->strexit = fun;
367 }
368 
369 void
mu_m_server_set_preflight(mu_m_server_t srv,mu_m_server_preflight_fp fun)370 mu_m_server_set_preflight (mu_m_server_t srv, mu_m_server_preflight_fp fun)
371 {
372   srv->preflight = fun;
373 }
374 
375 int
mu_m_server_get_srvlist(mu_m_server_t srv,mu_list_t * plist)376 mu_m_server_get_srvlist (mu_m_server_t srv, mu_list_t *plist)
377 {
378   *plist = srv->srvlist;
379   return 0;
380 }
381 
382 const char *
mu_m_server_pidfile(mu_m_server_t srv)383 mu_m_server_pidfile (mu_m_server_t srv)
384 {
385   return srv->pidfile;
386 }
387 
388 void
mu_m_server_set_hints(mu_m_server_t srv,struct mu_sockaddr_hints * hints)389 mu_m_server_set_hints (mu_m_server_t srv, struct mu_sockaddr_hints *hints)
390 {
391   if (!hints)
392     memset (&srv->hints, 0, sizeof (srv->hints));
393   else
394     memcpy (&srv->hints, hints, sizeof (srv->hints));
395 }
396 
397 int
mu_m_server_get_hints(mu_m_server_t srv,struct mu_sockaddr_hints * hints)398 mu_m_server_get_hints (mu_m_server_t srv, struct mu_sockaddr_hints *hints)
399 {
400   if (!hints)
401     return EINVAL;
402   memcpy (hints, &srv->hints, sizeof (*hints));
403   return 0;
404 }
405 
406 
407 void
mu_m_server_set_default_port(mu_m_server_t srv,int num)408 mu_m_server_set_default_port (mu_m_server_t srv, int num)
409 {
410   srv->hints.port = num;
411 }
412 
413 void
mu_m_server_set_timeout(mu_m_server_t srv,time_t t)414 mu_m_server_set_timeout (mu_m_server_t srv, time_t t)
415 {
416   srv->timeout = t;
417 }
418 
419 int
mu_m_server_mode(mu_m_server_t srv)420 mu_m_server_mode (mu_m_server_t srv)
421 {
422   return srv->mode;
423 }
424 
425 time_t
mu_m_server_timeout(mu_m_server_t srv)426 mu_m_server_timeout (mu_m_server_t srv)
427 {
428   return srv->timeout;
429 }
430 
431 int
mu_m_server_foreground(mu_m_server_t srv)432 mu_m_server_foreground (mu_m_server_t srv)
433 {
434   return srv->foreground;
435 }
436 
437 void
mu_m_server_set_app_data_size(mu_m_server_t srv,size_t size)438 mu_m_server_set_app_data_size (mu_m_server_t srv, size_t size)
439 {
440   srv->app_data_size = size;
441 }
442 
443 int
mu_m_server_set_config_size(mu_m_server_t srv,size_t size)444 mu_m_server_set_config_size (mu_m_server_t srv, size_t size)
445 {
446   if (size < sizeof (struct mu_srv_config))
447     return EINVAL;
448   srv->app_data_size = size - sizeof (struct mu_srv_config);
449   return 0;
450 }
451 
452 void
mu_srv_config_free(void * data)453 mu_srv_config_free (void *data)
454 {
455   struct mu_srv_config *pconf = data;
456   /* FIXME */
457   free (pconf);
458 }
459 
460 static int m_srv_conn (int fd, struct sockaddr *sa, int salen,
461 		       void *server_data, void *call_data,
462 		       mu_ip_server_t srv);
463 
464 struct mu_srv_config *
mu_m_server_listen(mu_m_server_t msrv,struct mu_sockaddr * s,int type)465 mu_m_server_listen (mu_m_server_t msrv, struct mu_sockaddr *s, int type)
466 {
467   mu_ip_server_t tcpsrv;
468   struct mu_srv_config *pconf;
469 
470   MU_ASSERT (mu_ip_server_create (&tcpsrv, s, type)); /* FIXME: type */
471   MU_ASSERT (mu_ip_server_set_conn (tcpsrv, m_srv_conn));
472   pconf = calloc (1, sizeof (*pconf) + msrv->app_data_size);
473   if (!pconf)
474     {
475       mu_error ("%s", mu_strerror (ENOMEM));
476       exit (1);
477     }
478   pconf->msrv = msrv;
479   pconf->tcpsrv = tcpsrv;
480   pconf->single_process = 0;
481   pconf->timeout = msrv->timeout;
482   MU_ASSERT (mu_ip_server_set_data (tcpsrv, pconf, mu_srv_config_free));
483   if (!msrv->srvlist)
484     MU_ASSERT (mu_list_create (&msrv->srvlist));
485   MU_ASSERT (mu_list_append (msrv->srvlist, tcpsrv));
486   return pconf;
487 }
488 
489 void
mu_m_server_configured_count(mu_m_server_t msrv,size_t * count)490 mu_m_server_configured_count (mu_m_server_t msrv, size_t *count)
491 {
492   mu_list_count (msrv->srvlist, count);
493 }
494 
495 void
mu_m_server_begin(mu_m_server_t msrv)496 mu_m_server_begin (mu_m_server_t msrv)
497 {
498   int i, rc;
499   size_t count = 0;
500 
501   if (!msrv->child_pid)
502     alloc_children (msrv);
503 
504   mu_list_count (msrv->srvlist, &count);
505   if (count == 0)
506     {
507       struct mu_sockaddr *ta;
508 
509       msrv->hints.flags = MU_AH_PASSIVE;
510       rc = mu_sockaddr_from_node (&ta, NULL, NULL, &msrv->hints);
511       if (rc == 0)
512 	while (ta)
513 	  {
514 	    struct mu_sockaddr *next = ta->next;
515 	    ta->next = ta->prev = NULL;
516 	    mu_m_server_listen (msrv, ta, msrv->deftype);
517 	    ta = next;
518 	  }
519     }
520 
521   if (!msrv->foreground)
522     {
523       /* Become a daemon. Take care to close inherited fds and to hold
524 	 first three one, in, out, err   */
525       if ((rc = mu_daemon ()) != 0)
526 	{
527 	  mu_error (_("failed to become a daemon: %s"), mu_strerror (rc));
528 	  exit (EXIT_FAILURE);
529 	}
530       mu_onexit_reset ();
531     }
532 
533   if (msrv->pidfile)
534     switch (rc = mu_daemon_create_pidfile (msrv->pidfile))
535       {
536       case 0:
537 	break;
538 
539       case EINVAL:
540 	mu_error (_("%s: invalid name for a pidfile"), msrv->pidfile);
541 	break;
542 
543       default:
544 	mu_error (_("cannot create pidfile `%s': %s"), msrv->pidfile,
545 		  mu_strerror (rc));
546       }
547 
548   for (i = 0; i < NSIG; i++)
549     if (sigismember (&msrv->sigmask, i))
550       msrv->sigtab[i] = set_signal (i, m_srv_signal);
551 }
552 
553 void
mu_m_server_restore_signals(mu_m_server_t msrv)554 mu_m_server_restore_signals (mu_m_server_t msrv)
555 {
556   int i;
557 
558   for (i = 0; i < NSIG; i++)
559     if (sigismember (&msrv->sigmask, i))
560       set_signal (i, msrv->sigtab[i]);
561 }
562 
563 void
mu_m_server_end(mu_m_server_t msrv)564 mu_m_server_end (mu_m_server_t msrv)
565 {
566   mu_m_server_restore_signals (msrv);
567 }
568 
569 void
mu_m_server_destroy(mu_m_server_t * pmsrv)570 mu_m_server_destroy (mu_m_server_t *pmsrv)
571 {
572   mu_m_server_t msrv = *pmsrv;
573   mu_list_remove (m_server_list, msrv);
574   mu_list_destroy (&msrv->srvlist);
575   mu_server_destroy (&msrv->server);
576   free (msrv->child_pid);
577   /* FIXME: Send processes the TERM signal here?*/
578   free (msrv->ident);
579   free (msrv);
580   *pmsrv = NULL;
581 }
582 
583 static int
tcp_conn_handler(int fd,void * conn_data,void * server_data)584 tcp_conn_handler (int fd, void *conn_data, void *server_data)
585 {
586   mu_ip_server_t tcpsrv = (mu_ip_server_t) conn_data;
587   int rc = mu_ip_server_accept (tcpsrv, server_data);
588   if (rc && rc != EINTR)
589     {
590       mu_ip_server_shutdown (tcpsrv);
591       return MU_SERVER_CLOSE_CONN;
592     }
593   return stop ? MU_SERVER_SHUTDOWN : MU_SERVER_SUCCESS;
594 }
595 
596 static void
tcp_conn_free(void * conn_data,void * server_data)597 tcp_conn_free (void *conn_data, void *server_data)
598 {
599   mu_ip_server_t tcpsrv = (mu_ip_server_t) conn_data;
600   mu_ip_server_destroy (&tcpsrv);
601 }
602 
603 static int
open_connection(mu_ip_server_t tcpsrv,mu_m_server_t msrv)604 open_connection (mu_ip_server_t tcpsrv, mu_m_server_t msrv)
605 {
606   int rc = mu_ip_server_open (tcpsrv);
607   if (rc)
608     {
609       mu_error (_("cannot open connection on %s: %s"),
610 		mu_ip_server_addrstr (tcpsrv), mu_strerror (rc));
611       return rc;
612     }
613 
614   rc = mu_server_add_connection (msrv->server,
615 				 mu_ip_server_get_fd (tcpsrv),
616 				 tcpsrv,
617 				 tcp_conn_handler, tcp_conn_free);
618   if (rc)
619     {
620       mu_error (_("cannot add connection %s: %s"),
621 		mu_ip_server_addrstr (tcpsrv), mu_strerror (rc));
622       mu_ip_server_shutdown (tcpsrv);
623     }
624   return rc;
625 }
626 
627 int
mu_m_server_run(mu_m_server_t msrv)628 mu_m_server_run (mu_m_server_t msrv)
629 {
630   int rc;
631   size_t count;
632   mode_t saved_umask;
633   mu_iterator_t itr;
634 
635   saved_umask = umask (0117);
636   mu_list_get_iterator (msrv->srvlist, &itr);
637   for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
638     {
639       mu_ip_server_t tcpsrv;
640       mu_iterator_current (itr, (void**) &tcpsrv);
641       if (open_connection (tcpsrv, msrv))
642 	{
643 	  mu_iterator_ctl (itr, mu_itrctl_delete_nd, NULL);
644 	  mu_ip_server_destroy (&tcpsrv);
645 	}
646     }
647   umask (saved_umask);
648   mu_iterator_destroy (&itr);
649 
650   MU_ASSERT (mu_server_count (msrv->server, &count));
651   if (count == 0)
652     {
653       mu_error (_("no servers configured: exiting"));
654       exit (1);
655     }
656   if (msrv->preflight && msrv->preflight (msrv))
657     {
658       mu_error (_("%s: preflight check failed"), msrv->ident);
659       return MU_ERR_FAILURE;
660     }
661 
662   if (msrv->ident)
663     mu_diag_output (MU_DIAG_INFO, _("%s started"), msrv->ident);
664   rc = mu_server_run (msrv->server);
665   terminate_children (msrv);
666   if (msrv->ident)
667     mu_diag_output (MU_DIAG_INFO, _("%s terminated"), msrv->ident);
668   return rc;
669 }
670 
671 int
mu_m_server_check_acl(mu_m_server_t msrv,struct sockaddr * s,int salen)672 mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen)
673 {
674   if (msrv->acl)
675     {
676       mu_acl_result_t res;
677       int rc;
678 
679       rc = mu_acl_check_sockaddr (msrv->acl, s, salen, &res);
680       if (rc)
681 	{
682 	  char *p = mu_sys_sockaddr_to_astr (s, salen);
683 	  mu_error (_("access from %s blocked: cannot check ACLs: %s"),
684 		    p, mu_strerror (rc));
685 	  free (p);
686 	  return 1;
687 	}
688       switch (res)
689 	{
690 	case mu_acl_result_undefined:
691 	  {
692 	    char *p = mu_sys_sockaddr_to_astr (s, salen);
693 	    mu_diag_output (MU_DIAG_INFO,
694 			    _("%s: undefined ACL result; access allowed"),
695 			    p);
696 	    free (p);
697 	  }
698 	  break;
699 
700 	case mu_acl_result_accept:
701 	  break;
702 
703 	case mu_acl_result_deny:
704 	  {
705 	    char *p = mu_sys_sockaddr_to_astr (s, salen);
706 	    mu_error (_("access from %s blocked"), p);
707 	    free (p);
708 	    return 1;
709 	  }
710 	}
711     }
712   return 0;
713 }
714 
715 int
m_srv_conn(int fd,struct sockaddr * sa,int salen,void * server_data,void * call_data,mu_ip_server_t srv)716 m_srv_conn (int fd, struct sockaddr *sa, int salen,
717 	    void *server_data, void *call_data,
718 	    mu_ip_server_t srv)
719 {
720   int status;
721   struct mu_srv_config *pconf = server_data;
722 
723   if (mu_m_server_check_acl (pconf->msrv, sa, salen))
724     return 0;
725 
726   if (!pconf->single_process)
727     {
728       pid_t pid;
729 
730       if (mu_m_server_idle (server_data))
731 	return MU_SERVER_SHUTDOWN;
732       if (pconf->msrv->max_children
733 	  && pconf->msrv->num_children >= pconf->msrv->max_children)
734         {
735 	  mu_diag_output (MU_DIAG_ERROR, _("too many children (%lu)"),
736 			  (unsigned long) pconf->msrv->num_children);
737           pause ();
738           return 0;
739         }
740       if (pconf->msrv->prefork
741 	  && pconf->msrv->prefork (fd, sa, salen, pconf, pconf->msrv->data))
742 	return 0;
743 
744       pid = fork ();
745       if (pid == -1)
746 	mu_diag_output (MU_DIAG_ERROR, "fork: %s", strerror (errno));
747       else if (pid == 0) /* Child.  */
748 	{
749 	  mu_ip_server_shutdown (srv); /* FIXME: does it harm for MU_IP_UDP? */
750 	  mu_m_server_restore_signals (pconf->msrv);
751 	  status = pconf->msrv->conn (fd, sa, salen, pconf,
752 				      pconf->msrv->data);
753 	  closelog ();
754 	  exit (status);
755 	}
756       else
757 	{
758 	  register_child (pconf->msrv, pid);
759 	}
760     }
761   else if (!pconf->msrv->prefork
762 	   || pconf->msrv->prefork (fd, sa, salen, pconf,
763 				    pconf->msrv->data) == 0)
764     pconf->msrv->conn (fd, sa, salen, pconf, pconf->msrv->data);
765   return 0;
766 }
767 
768 
769 int
mu_m_server_parse_url(mu_m_server_t msrv,const char * arg,struct mu_sockaddr ** psa)770 mu_m_server_parse_url (mu_m_server_t msrv, const char *arg,
771 		       struct mu_sockaddr **psa)
772 {
773   int rc;
774   mu_url_t url, url_hint;
775 
776   if (arg[0] == '/')
777     url_hint = NULL;
778   else
779     {
780       rc = mu_url_create (&url_hint, "inet://");
781       if (rc)
782 	return rc;
783     }
784   rc = mu_url_create_hint (&url, arg, MU_URL_PARSE_DEFAULT, url_hint);
785   mu_url_destroy (&url_hint);
786   if (rc)
787     {
788       mu_error (_("cannot parse URL `%s': %s"), arg, mu_strerror (rc));
789       return rc;
790     }
791 
792   msrv->hints.flags = MU_AH_PASSIVE;
793   rc = mu_sockaddr_from_url (psa, url, &msrv->hints);
794   if (rc)
795     mu_error (_("cannot create sockaddr for URL `%s': %s"), arg,
796 	      mu_strerror (rc));
797   mu_url_destroy (&url);
798   return rc;
799 }
800 
801 static int
server_block_begin(const char * arg,mu_m_server_t msrv,void ** pdata)802 server_block_begin (const char *arg, mu_m_server_t msrv, void **pdata)
803 {
804   struct mu_sockaddr *s;
805   if (mu_m_server_parse_url (msrv, arg, &s))
806     return 1;
807   if (s->next)
808     {
809       /* FIXME: (1) Find a way to handle all addresses.
810 	        (2) Print which address is being used.
811       */
812       mu_diag_output (MU_DIAG_WARNING,
813 		      _("%s resolves to several addresses, "
814 			"only the first is used"), arg);
815       mu_sockaddr_free (s->next);
816     }
817   *pdata = mu_m_server_listen (msrv, s, msrv->deftype);
818   return 0;
819 }
820 
821 static int
server_section_parser(enum mu_cfg_section_stage stage,const mu_cfg_node_t * node,const char * section_label,void ** section_data,void * call_data,mu_cfg_tree_t * tree)822 server_section_parser (enum mu_cfg_section_stage stage,
823 		       const mu_cfg_node_t *node,
824 		       const char *section_label, void **section_data,
825 		       void *call_data,
826 		       mu_cfg_tree_t *tree)
827 {
828   switch (stage)
829     {
830     case mu_cfg_section_start:
831       {
832 	if (node->label == NULL || node->label->type != MU_CFG_STRING)
833 	  return 1;
834 	/* FIXME: should not modify 2nd arg, or it should not be const */
835 	return server_block_begin (node->label->v.string,
836 				   *section_data, section_data);
837       }
838       break;
839 
840     case mu_cfg_section_end:
841       {
842 	struct mu_srv_config *pconf = *section_data;
843 	if (pconf->acl)
844 	  mu_ip_server_set_acl (pconf->tcpsrv, pconf->acl);
845       }
846       break;
847     }
848   return 0;
849 }
850 
851 static int
_cb_daemon_mode(void * data,mu_config_value_t * val)852 _cb_daemon_mode (void *data, mu_config_value_t *val)
853 {
854   int *pmode = data;
855 
856   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
857     return 1;
858   if (strcmp (val->v.string, "inetd") == 0
859       || strcmp (val->v.string, "interactive") == 0)
860     *pmode = MODE_INTERACTIVE;
861   else if (strcmp (val->v.string, "daemon") == 0)
862     *pmode = MODE_DAEMON;
863   else
864     {
865       mu_error (_("unknown daemon mode"));
866       return 1;
867     }
868   return 0;
869 }
870 
871 unsigned short
get_port(const char * p)872 get_port (const char *p)
873 {
874   if (p)
875     {
876       char *q;
877       unsigned long n = strtoul (p, &q, 0);
878       if (*q == 0)
879 	{
880 	  if (n > USHRT_MAX)
881 	    {
882 	      mu_error (_("invalid port number: %s"), p);
883 	      return 1;
884 	    }
885 
886 	  return n;
887 	}
888       else
889 	{
890 	  struct servent *sp = getservbyname (p, "tcp");
891 	  if (!sp)
892 	    return 0;
893 	  return ntohs (sp->s_port);
894 	}
895     }
896   return 0;
897 }
898 
899 static int
_cb_port(void * data,mu_config_value_t * val)900 _cb_port (void *data, mu_config_value_t *val)
901 {
902   struct mu_sockaddr_hints *hp = data;
903   unsigned short num;
904 
905   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
906     return 1;
907   num = get_port (val->v.string);
908   if (!num)
909     return 1;
910   hp->port = num;
911   return 0;
912 }
913 
914 static struct mu_cfg_param dot_server_cfg_param[] = {
915   { "max-children", mu_c_size,
916     NULL, mu_offsetof (struct _mu_m_server,max_children), NULL,
917     N_("Maximum number of children processes to run simultaneously.") },
918   { "mode", mu_cfg_callback,
919     NULL, mu_offsetof (struct _mu_m_server,mode), _cb_daemon_mode,
920     N_("Set operation mode."),
921     /* TRANSLATORS: Words to the right of : are keywords. */
922     N_("mode: inetd|interactive|daemon") },
923   { "foreground", mu_c_bool,
924     NULL, mu_offsetof (struct _mu_m_server, foreground), NULL,
925     N_("Run in foreground.") },
926   { "pidfile", mu_c_string,
927     NULL, mu_offsetof (struct _mu_m_server,pidfile), NULL,
928     N_("Store PID of the master process in this file."),
929     N_("file") },
930   { "port", mu_cfg_callback,
931     NULL, mu_offsetof (struct _mu_m_server, hints), _cb_port,
932     N_("Default port number."),
933     N_("arg: port number or service name") },
934   { "timeout", mu_c_time,
935     NULL, mu_offsetof (struct _mu_m_server,timeout), NULL,
936     N_("Set idle timeout.") },
937   { "server", mu_cfg_section, NULL, 0, NULL,
938     N_("Server configuration.") },
939   { "acl", mu_cfg_section, NULL, mu_offsetof (struct _mu_m_server,acl), NULL,
940     N_("Per-server access control list") },
941   { NULL }
942 };
943 
944 static struct mu_cfg_param server_cfg_param[] = {
945   { "single-process", mu_c_bool,
946     NULL, mu_offsetof (struct mu_srv_config, single_process), NULL,
947     N_("Do not spawn sub-process to handle requests in this server.") },
948   { "transcript", mu_c_bool,
949     NULL, mu_offsetof (struct mu_srv_config, transcript), NULL,
950     N_("Log the session transcript.") },
951   { "timeout", mu_c_time,
952     NULL, mu_offsetof (struct mu_srv_config, timeout), NULL,
953     N_("Set idle timeout.") },
954   { "acl", mu_cfg_section,
955     NULL, mu_offsetof (struct mu_srv_config, acl), NULL,
956     N_("Global access control list.") },
957   { NULL }
958 };
959 
960 static int
_cb_backlog(void * data,mu_config_value_t * val)961 _cb_backlog (void *data, mu_config_value_t *val)
962 {
963   mu_ip_server_t *psrv = data;
964   int backlog;
965 
966   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
967     return 1;
968   if (sscanf (val->v.string, "%d", &backlog) != 1 || backlog <= 0
969       || mu_tcp_server_set_backlog (*psrv, backlog))
970     {
971       mu_error (_("invalid argument"));
972       return 1;
973     }
974   return 0;
975 }
976 
977 static struct mu_cfg_param server_tcp_param[] = {
978   { "backlog", mu_cfg_callback,
979     NULL, mu_offsetof (struct mu_srv_config, tcpsrv), _cb_backlog,
980     N_("Size of the queue of pending connections"),
981     N_("number") },
982   { NULL }
983 };
984 
985 void
mu_m_server_cfg_init(mu_m_server_t srv,struct mu_cfg_param * app_param)986 mu_m_server_cfg_init (mu_m_server_t srv, struct mu_cfg_param *app_param)
987 {
988   struct mu_cfg_section *section;
989   if (mu_create_canned_section ("server", &section) == 0)
990     {
991       section->parser = server_section_parser;
992       section->label = N_("ipaddr[:port]");
993       mu_cfg_section_add_params (section, server_cfg_param);
994       if (srv->deftype == MU_IP_TCP)
995 	mu_cfg_section_add_params (section, server_tcp_param);
996       if (app_param)
997 	mu_cfg_section_add_params (section, app_param);
998     }
999   if (mu_create_canned_section (".server", &section) == 0)
1000     {
1001       mu_cfg_section_add_params (section, dot_server_cfg_param);
1002     }
1003 }
1004 
1005 
1006 
1007