1 /*
2  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2008, 2009,
3  *               2010, 2011, 2019, 2020
4  *      Inferno Nettverk A/S, Norway.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. The above copyright notice, this list of conditions and the following
10  *    disclaimer must appear in all copies of the software, derivative works
11  *    or modified versions, and any portions thereof, aswell as in all
12  *    supporting documentation.
13  * 2. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by
16  *      Inferno Nettverk A/S, Norway.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Inferno Nettverk A/S requests users of this software to return to
32  *
33  *  Software Distribution Coordinator  or  sdc@inet.no
34  *  Inferno Nettverk A/S
35  *  Oslo Research Park
36  *  Gaustadall�en 21
37  *  NO-0349 Oslo
38  *  Norway
39  *
40  * any improvements or extensions that they make and grant Inferno Nettverk A/S
41  * the rights to redistribute these changes.
42  *
43  */
44 
45 #include "common.h"
46 
47 static const char rcsid[] =
48 "$Id: sockd_child.c,v 1.454.4.7.6.5 2020/11/22 19:40:49 karls Exp $";
49 
50 #define MOTHER  (0)  /* descriptor mother reads/writes on.   */
51 #define CHILD   (1)  /* descriptor child reads/writes on.    */
52 
53 static int
54 setchildtype(int type, sockd_child_t ***childv, size_t **childc,
55              void (**function)(void));
56 /*
57  * Sets "childv", "childc" and "function" to the correct value depending
58  * on "type".
59  */
60 
61 static ssize_t
62 findchild(pid_t pid, size_t childc, const sockd_child_t *childv);
63 /*
64  * Finds the child with pid "pid" in the array "childv".  Searching
65  * Elements in "childv" is given by "childc".
66  * Returns:
67  *      On success: the index of the child in "childv".
68  *      On failure: -1.
69  */
70 
71 static sockd_child_t *
72 addchild(const int type);
73 /*
74  * Adds a new child that can accept objects of type "type" from mother.
75  * Returns:
76  *    On success: a pointer to the added child.
77  *    On failure: NULL.  (resource shortage.)
78  */
79 
80 
81 static sockd_child_t *monitorv;          /* all our monitorchildren.          */
82 static size_t monitorc;
83 
84 static sockd_child_t *negchildv;         /* all our negotiatorchildren        */
85 static size_t negchildc;
86 
87 static sockd_child_t *reqchildv;         /* all our requestchildren           */
88 static size_t reqchildc;
89 
90 static sockd_child_t *iochildv;          /* all our iochildren                */
91 static size_t iochildc;
92 
93 void
enable_childcreate(void)94 enable_childcreate(void)
95 {
96    const char *function = "enable_childcreate()";
97 
98    if (sockscf.child.noaddchild) {
99       static int firsttime = 1;
100 
101       if (firsttime)
102          firsttime = 0;
103       else
104          slog(LOG_INFO, "%s: creation of new child processes enabled again",
105               function);
106 
107       sockscf.child.noaddchild = 0;
108    }
109 
110    sockscf.child.noaddchild_errno = 0;
111 }
112 
113 void
disable_childcreate(err,reason)114 disable_childcreate(err, reason)
115    const int err;
116    const char *reason;
117 {
118    const char *function = "disable_childcreate()";
119 
120    if (!sockscf.child.noaddchild) {
121       slog(LOG_INFO,
122            "%s: disabling creation of new child processes%s%s (%s)",
123            function,
124            reason == NULL ? "" : ": ",
125            reason == NULL ? "" : reason,
126            strerror(errno));
127 
128       sockscf.child.noaddchild = 1;
129    }
130 
131    sockscf.child.noaddchild_errno  = err;
132    sockscf.child.noaddchild_reason = reason;
133 }
134 
135 size_t
childcheck(type)136 childcheck(type)
137    int type;
138 {
139    const char *function = "childcheck()";
140    static time_t lastaddchildfailure_time;
141    const int errno_s = errno;
142    sockd_child_t **childv, *idlechild;
143    size_t child, *childc, minfreeslots, maxslotsperproc, proxyc,
144           minclientshandled;
145    time_t  minlifetime;
146 #if BAREFOOTD
147    pid_t hasfreeudpslot = (pid_t)-1;
148 #endif /* BAREFOOTD */
149 
150    switch (type) {
151       /*
152        * Special one-child-only processes.
153        */
154       case -PROC_MONITOR:
155       case PROC_MONITOR:
156          childc            = &monitorc;
157          childv            = &monitorv;
158          minfreeslots      = 1;
159          minclientshandled = 1;
160          maxslotsperproc   = 1;
161          break;
162 
163 
164       case -PROC_NEGOTIATE:
165       case PROC_NEGOTIATE:
166          childc            = &negchildc;
167          childv            = &negchildv;
168          minfreeslots      = SOCKD_FREESLOTS_NEGOTIATE;
169          minclientshandled = SOCKD_MIN_CLIENTS_HANDLED_NEGOTIATE;
170          maxslotsperproc   = SOCKD_NEGOTIATEMAX;
171          break;
172 
173       case -PROC_REQUEST:
174       case PROC_REQUEST:
175          childc            = &reqchildc;
176          childv            = &reqchildv;
177          minfreeslots      = SOCKD_FREESLOTS_REQUEST;
178          minclientshandled = SOCKD_MIN_CLIENTS_HANDLED_REQUEST;
179          maxslotsperproc   = SOCKD_REQUESTMAX;
180          break;
181 
182       case -PROC_IO:
183       case PROC_IO:
184          childc            = &iochildc;
185          childv            = &iochildv;
186          minfreeslots      = SOCKD_FREESLOTS_IO;
187          minclientshandled = SOCKD_MIN_CLIENTS_HANDLED_IO;
188          maxslotsperproc   = SOCKD_IOMAX;
189          break;
190 
191       default:
192          SERRX(type);
193    }
194 
195    if (sockscf.child.maxrequests != 0)
196       minclientshandled = MIN(minclientshandled, sockscf.child.maxrequests);
197 
198    /* minlifetime is the same for all. */
199    if (sockscf.child.maxlifetime != 0)
200       minlifetime = MIN(SOCKD_MIN_LIFETIME_SECONDS, sockscf.child.maxlifetime);
201    else
202       minlifetime = SOCKD_MIN_LIFETIME_SECONDS;
203 
204 
205    /*
206     * get an estimate over how many (new or in total) clients our children are
207     * able to accept, so we know if we need to create more children, or if we
208     * can remove some.
209     */
210    idlechild = NULL;
211    for (child = proxyc = 0; child < *childc; ++child) {
212       SASSERTX((*childv)[child].freec <= maxslotsperproc);
213 
214       if ((*childv)[child].waitingforexit)
215          continue;
216 
217       if (child_should_retire(&(*childv)[child])) {
218          slog(LOG_DEBUG,
219               "%s: not counting %s %ld.  Should be retired when "
220               "possible.  Currently has %lu/%lu slots free.",
221               function,
222               childtype2string((*childv)[child].type),
223               (long)(*childv)[child].pid,
224               (unsigned long)(*childv)[child].freec,
225               (unsigned long)maxfreeslots((*childv)[child].type));
226 
227          if ((*childv)[child].freec == maxfreeslots((*childv)[child].type))
228             closechild((*childv)[child].pid, 1);
229 
230          continue;
231       }
232 
233 #if BAREFOOTD
234       if (type == PROC_IO) {
235          if (!(*childv)[child].hasudpsession)
236             hasfreeudpslot = (*childv)[child].pid;
237          else
238             slog(LOG_DEBUG, "%s: not counting process %lu: no free udp slots",
239                  function, (unsigned long)(*childv)[child].pid);
240       }
241 #endif /* BAREFOOTD */
242 
243       proxyc += type < 0 ? maxslotsperproc :
244 #if BAREFOOTD
245                            /*
246                             * Don't know what the next client for this
247                             * child will be (udp or tcp), so safer to assume
248                             * that if it can not handle any more udp clients,
249                             * it has no free slots.  Means we will get more
250                             * i/o processes than might be required, but
251                             * better that than too few.
252                             */
253                            ((type == PROC_IO
254                            && (*childv)[child].hasudpsession) ?
255                               0 : (*childv)[child].freec);
256 #else /* !BAREFOOTD */
257 
258                            (*childv)[child].freec;
259 
260 #endif /* !BAREFOOTD */
261 
262       if ((*childv)[child].freec == maxslotsperproc) {
263 #if BAREFOOTD
264          if (type == PROC_IO) {
265             if (hasfreeudpslot != (pid_t)-1
266             && hasfreeudpslot  != (*childv)[child].pid)
267                ;
268             else {
269                /*
270                 * Want to keep this regardless, as we have not seen any
271                 * other child with a free udp slot so far, so don't
272                 * include it in the idle count where it could possibly be
273                 * shut down by maxidle/maxreq code.
274                 */
275                hasfreeudpslot = (*childv)[child].pid;
276                continue;
277             }
278          }
279 #endif /* BAREFOOTD */
280 
281          /*
282           * all slots in this child are idle.  See later if we can remove an
283           * idle child.  Shouldn't matter much which, but choose the one that
284           * has handled most clients; if we are using buggy libraries, that
285           * increases the chance of some leaked memory being freed too.
286           *
287           * Ignore children that have only handled a few clients to prevent
288           * removing and then re-creating immediately after as the current
289           * free slots count goes down by one when a slot is freed.
290           * Should work as a cheap form of hysteresis.
291           */
292          if (sockscf.child.noaddchild     /* in trouble.  Remove what we can. */
293          || (*childv)[child].sentc >= minclientshandled
294          || socks_difftime(time_monotonic(NULL), (*childv)[child].created)
295              >= (time_t)minlifetime) {
296             if (idlechild == NULL || (*childv)[child].sentc > idlechild->sentc)
297                idlechild = &(*childv)[child];
298          }
299       }
300    }
301 
302    if (sockscf.child.noaddchild) {
303       if (socks_difftime(time_monotonic(NULL), lastaddchildfailure_time)
304       >= (time_t)MAX_ADDCHILD_SECONDS
305       &&  socks_difftime(time_monotonic(NULL), sockscf.state.firstdeath_time)
306           >= (time_t)MAX_ADDCHILD_SECONDS)
307          enable_childcreate();
308    }
309 
310    if (type >= 0) {
311       /*
312        * Idle child to remove?
313        */
314       if (idlechild != NULL
315       && (proxyc - maxslotsperproc) >= minfreeslots) {
316          slog(LOG_DEBUG,
317               "%s: counted %lu free %s slots.  Removing pid %ld which has "
318               "handled %lu client%s during %lds",
319               function,
320               (unsigned long)(proxyc - maxslotsperproc),
321               childtype2string(idlechild->type),
322               (long)(idlechild->pid),
323               (unsigned long)(idlechild->sentc),
324               idlechild->sentc == 1 ? "" : "s",
325               (long)socks_difftime(time_monotonic(NULL), idlechild->created));
326 
327          /*
328           * will remove this now, no longer part of free slots pool.
329           */
330          SASSERTX(idlechild->freec == maxslotsperproc);
331          proxyc -= idlechild->freec;
332          closechild(idlechild->pid, 1);
333       }
334 
335       /*
336        * Should we create an additional child?
337        */
338       if (!sockscf.child.noaddchild
339       && ((proxyc < minfreeslots)
340 #if BAREFOOTD
341             ||    (type == PROC_IO && hasfreeudpslot == (pid_t)-1)
342 #endif /* BAREFOOTD */
343          )) {
344          int reservedv[  MAX(FDPASS_MAX, /* max we can receive from children  */
345                              1)          /* need a socket for accept(2).      */
346 
347                          + 1             /* to reopen-sockd.conf              */
348 
349                          + 1             /*
350                                           * if no syslog socket is open, so
351                                           * a new sockd.conf is able to open
352                                           * one if necessary.
353                                           */
354 
355                          + 1             /* things we don't know about.       */
356                       ];
357 
358          size_t i, freec;
359 
360          /*
361           * It is better to reserve some descriptors for temporary use
362           * than to get errors when receiving from a child and lose clients
363           * that way.  Make sure we always have some descriptors available,
364           * and don't try to add a child if we don't.
365           * If we can add a child after reserving the below number of
366           * descriptors, things are ok.  If not, it means we have to few
367           * fds available.
368           */
369          for (i = 0, freec = 0; i < ELEMENTS(reservedv); ++i)
370             if ((reservedv[i] = makedummyfd(0, 0)) != -1)
371                ++freec;
372 
373          if (freec < ELEMENTS(reservedv)) {
374             swarn("%s: not enough free sockets/file descriptors to add any "
375                   "new child.  Need at least %lu, but have only %lu",
376                   function,
377                   (unsigned long)ELEMENTS(reservedv),
378                   (unsigned long)freec);
379 
380             disable_childcreate(errno,
381                                 "not enough free sockets/file descriptors");
382 
383             /* don't retry until a child exits, or enough time has passed. */
384             time_monotonic(&lastaddchildfailure_time);
385          }
386 
387          while (!sockscf.child.noaddchild
388          &&       ((proxyc < minfreeslots)
389 #if BAREFOOTD
390             ||    (type == PROC_IO && hasfreeudpslot == (pid_t)-1)
391 #endif /* BAREFOOTD */
392          )) {
393             sockd_child_t *addedchild;
394 
395 #if BAREFOOTD
396             if (type == PROC_IO && hasfreeudpslot == (pid_t)-1)
397                slog(LOG_DEBUG, "%s: no free udp slots: need to add more %sren",
398                     function, childtype2string(type));
399             else
400 #endif /* BAREFOOTD */
401             slog(LOG_DEBUG,
402                   "%s: current # of free %s slots is %lu, configured minimum "
403                   "is %lu: need to add more %sren",
404                   function,
405                   childtype2string(type),
406                   (unsigned long)proxyc,
407                   (unsigned long)minfreeslots,
408                   childtype2string(type));
409 
410             if ((addedchild = addchild(type)) != NULL) {
411                slog(LOG_DEBUG, "%s: added child, pid %lu",
412                     function, (unsigned long)addedchild->pid);
413 
414                proxyc += maxslotsperproc;
415 
416 #if BAREFOOTD
417                if (type == PROC_IO)
418                  hasfreeudpslot = addedchild->pid;
419 #endif /* BAREFOOTD */
420 
421             }
422             else {
423                log_addchild_failed();
424 
425                disable_childcreate(errno, NULL);
426 
427                /* don't retry until a child exits, or enough time has passed. */
428                time_monotonic(&lastaddchildfailure_time);
429             }
430          }
431 
432          closev(ELEMENTS(reservedv), reservedv);
433       }
434    }
435 
436    /* if errno was set, it was also logged.  Don't drag it with us. */
437    errno = errno_s;
438 
439    return proxyc;
440 }
441 
442 int
fillset(set,negc,reqc,ioc)443 fillset(set, negc, reqc, ioc)
444    fd_set *set;
445    size_t *negc;
446    size_t *reqc;
447    size_t *ioc;
448 {
449 /*   const char *function = "fillset()"; */
450    size_t i;
451    int dbits;
452 
453    /*
454     * There is no point in setting data descriptor of child type N unless
455     * child type N+1 is able to accept the data from child N.  So find
456     * out if we have slots of the various types available before setting
457     * the descriptor.  The same goes for the ack descriptor; we don't
458     * want to think the process has a lot of free slots because we have
459     * read the ack, but are unable to read the data.
460     */
461 
462    *negc = childcheck(PROC_NEGOTIATE);
463    *reqc = childcheck(PROC_REQUEST);
464    *ioc  = childcheck(PROC_IO);
465 
466    FD_ZERO(set);
467    dbits = -1;
468 
469    for (i = 0; i < sockscf.internal.addrc; ++i) {
470 #if BAREFOOTD
471       if (sockscf.internal.addrv[i].protocol != SOCKS_TCP)
472          continue; /* udp handled by io children. */
473 #endif /* BAREFOOTD */
474 
475       /*
476        * Before we checked whether we had available negotiate slots
477        * before accept(2)'ing a new client, but if we do not have
478        * negotiate slots available, it will look like we have hung
479        * because we are not accepting any new clients.
480        * Also, if we get into the situation where we have no negotiate slots
481        * and are unable to fork new negotiate processes, things are probably
482        * pretty bad, so it might be better to drop new clients
483        * and log a warning about it.
484        */
485 
486       SASSERTX(sockscf.internal.addrv[i].s >= 0);
487       FD_SET(sockscf.internal.addrv[i].s, set);
488       dbits = MAX(dbits, sockscf.internal.addrv[i].s);
489    }
490 
491    /* negotiator children. */
492    for (i = 0; i < negchildc; ++i) {
493       if (negchildv[i].waitingforexit)
494          continue;
495 
496       if (*reqc > 0) {
497          SASSERTX(negchildv[i].s >= 0);
498          FD_SET(negchildv[i].s, set);
499          dbits = MAX(dbits, negchildv[i].s);
500 
501          SASSERTX(negchildv[i].ack >= 0);
502          FD_SET(negchildv[i].ack, set);
503          dbits = MAX(dbits, negchildv[i].ack);
504       }
505    }
506 
507    /* request children. */
508    for (i = 0; i < reqchildc; ++i) {
509       if (reqchildv[i].waitingforexit)
510          continue;
511 
512       if (*ioc > 0) {
513          SASSERTX(reqchildv[i].s >= 0);
514          FD_SET(reqchildv[i].s, set);
515          dbits = MAX(dbits, reqchildv[i].s);
516 
517          SASSERTX(reqchildv[i].ack >= 0);
518          FD_SET(reqchildv[i].ack, set);
519          dbits = MAX(dbits, reqchildv[i].ack);
520       }
521    }
522 
523    /*
524     * io children are last in chain, unless we are covenant, which may
525     * need to send a client object back from  i/o child to a negotiate
526     * child.
527     */
528    for (i = 0; i < iochildc; ++i) {
529       if (iochildv[i].waitingforexit)
530          continue;
531 
532 #if COVENANT
533       if (*negc > 0) {
534          SASSERTX(iochildv[i].s >= 0);
535          FD_SET(iochildv[i].s, set);
536          dbits = MAX(dbits, iochildv[i].s);
537 #endif /* COVENANT */
538 
539          SASSERTX(iochildv[i].ack >= 0);
540          FD_SET(iochildv[i].ack, set);
541          dbits = MAX(dbits, iochildv[i].ack);
542 #if COVENANT
543       }
544 #endif /* COVENANT */
545 
546    }
547 
548    return dbits;
549 }
550 
551 
552 void
clearchildtype(childtype,pipetype,nfds,set)553 clearchildtype(childtype, pipetype, nfds, set)
554    const int childtype;
555    whichpipe_t pipetype;
556    const int nfds;
557    fd_set *set;
558 {
559    const char *function = "clearchildtype()";
560    sockd_child_t **childv;
561    size_t i, *childc;
562 
563 
564    slog(LOG_DEBUG, "%s: clearing all childs of type %s from set",
565         function, childtype2string(childtype));
566 
567    setchildtype(childtype, &childv, &childc, NULL);
568 
569    for (i = 0; i < *childc; ++i)
570       clearset(pipetype, &(*childv)[i], set);
571 }
572 
573 void
clearset(type,child,set)574 clearset(type, child, set)
575    whichpipe_t type;
576    const sockd_child_t *child;
577    fd_set *set;
578 {
579 #if DEBUG
580    const char *function = "clearset()";
581    char buf[10240];
582 #endif /* DEBUG */
583    int fdtoclear;
584 
585    switch (type) {
586       case ACKPIPE:
587          fdtoclear = child->ack;
588          break;
589 
590       case DATAPIPE:
591          fdtoclear = child->s;
592          break;
593 
594       default:
595          SERRX(type);
596    }
597 
598    if (fdtoclear <= 0) {
599       SASSERTX(child->waitingforexit);
600       return;
601    }
602 
603 #if DEBUG
604    if (sockscf.option.debug >= DEBUG_DEBUG)
605       slog(LOG_DEBUG, "%s: will clear fd %d from the fd-set containing: %s",
606            function,
607            fdtoclear,
608           fdset2string(sockscf.state.highestfdinuse, set, 1, buf, sizeof(buf)));
609 #endif
610 
611    FD_CLR(fdtoclear, set);
612 }
613 
614 sockd_child_t *
getset(type,set)615 getset(type, set)
616    whichpipe_t type;
617    fd_set *set;
618 {
619 /*   const char *function = "getset()"; */
620    size_t i;
621 
622    /*
623     * check negotiator children for match.
624     */
625    for (i = 0; i < negchildc; ++i) {
626       if (negchildv[i].waitingforexit)
627          continue;
628 
629       switch (type) {
630          case DATAPIPE:
631 #if BAREFOOTD
632             if (!ALL_UDP_BOUNCED()) { /* have some left to fake. */
633                static fd_set *zero;
634 
635                if (zero == NULL) {
636                   zero = allocate_maxsize_fdset();
637                   FD_ZERO(zero);
638                }
639 
640                if (FD_CMP(zero, set) == 0) {
641                   slog(LOG_DEBUG,
642                        "no fds set in set, but have not yet bounced all "
643                        "udp sessions, so faking it for negchild %lu",
644                        (unsigned long)negchildv[i].pid);
645 
646                   return &negchildv[i];
647                }
648             }
649 #endif /* BAREFOOTD */
650 
651             if (FD_ISSET(negchildv[i].s, set))
652                return &negchildv[i];
653             break;
654 
655          case ACKPIPE:
656             if (FD_ISSET(negchildv[i].ack, set))
657                return &negchildv[i];
658             break;
659       }
660    }
661 
662    /*
663     * check request children for match.
664     */
665    for (i = 0; i < reqchildc; ++i) {
666       if (reqchildv[i].waitingforexit)
667          continue;
668 
669       switch (type) {
670          case DATAPIPE:
671             if (FD_ISSET(reqchildv[i].s, set))
672                return &reqchildv[i];
673             break;
674 
675          case ACKPIPE:
676             if (FD_ISSET(reqchildv[i].ack, set))
677                return &reqchildv[i];
678             break;
679       }
680    }
681 
682    /*
683     * check io children for match.
684     */
685    for (i = 0; i < iochildc; ++i) {
686       if (iochildv[i].waitingforexit)
687          continue;
688 
689       switch (type) {
690          case DATAPIPE:
691             if (FD_ISSET(iochildv[i].s, set))
692                return &iochildv[i];
693             break;
694 
695          case ACKPIPE:
696             if (FD_ISSET(iochildv[i].ack, set))
697                return &iochildv[i];
698             break;
699       }
700    }
701 
702    return NULL;
703 }
704 
705 void
removechild(pid)706 removechild(pid)
707    const pid_t pid;
708 {
709    const char *function = "removechild()";
710    sockd_child_t **childv;
711    ssize_t child;
712    size_t *childc;
713 
714    slog(LOG_DEBUG, "%s: pid = %lu", function, (unsigned long)pid);
715 
716    if (pid == 0) { /* remove all children. */
717       int childtypev[] = {PROC_MONITOR, PROC_NEGOTIATE, PROC_REQUEST, PROC_IO};
718       size_t i;
719 
720       for (i = 0; i < ELEMENTS(childtypev); ++i) {
721          if (childtypev[i]                 == PROC_MONITOR
722          && pidismother(sockscf.state.pid) != 1)
723             continue; /* only main mother controls the monitor child. */
724 
725          while (1) { /* removechild() will remove it from our child array. */
726             setchildtype(childtypev[i], &childv, &childc, NULL);
727             if (*childc == 0)
728                break;
729 
730             SASSERTX((*childv)[0].pid != 0);
731             removechild((*childv)[0].pid);
732          }
733       }
734 
735       return;
736    }
737 
738    setchildtype(childtype(pid), &childv, &childc, NULL);
739    child = findchild(pid, *childc, *childv);
740    if (child < 0) {
741       SWARNX(child);
742       return;
743    }
744 
745    /* shift all following one down */
746    while ((size_t)child < *childc - 1) {
747       (*childv)[child] = (*childv)[child + 1];
748       ++child;
749    }
750    --(*childc);
751 
752    /*
753     * Don't bother with realloc(3) when reducing size.
754     */
755 }
756 
757 void
closechild(pid,isnormalexit)758 closechild(pid, isnormalexit)
759    pid_t pid;
760    const int isnormalexit;
761 {
762    const char *function = "closechild()";
763    const char cmd = SOCKD_EXITNORMALLY;
764    sockd_child_t **childv;
765    ssize_t child;
766    size_t *childc;
767 
768    slog(LOG_DEBUG, "%s: pid = %lu, isnormalexit = %d",
769         function, (unsigned long)pid, isnormalexit);
770 
771    if (pid == 0) {
772       int childtypev[] = {PROC_MONITOR, PROC_NEGOTIATE, PROC_REQUEST, PROC_IO};
773       size_t childtypec;
774 
775       for (childtypec = 0; childtypec < ELEMENTS(childtypev); ++childtypec) {
776          size_t i;
777 
778          if (childtypev[childtypec]        == PROC_MONITOR
779          && pidismother(sockscf.state.pid) != 1)
780             continue; /* only main mother controls the monitor child. */
781 
782          setchildtype(childtypev[childtypec], &childv, &childc, NULL);
783 
784          if (*childc == 0)
785             continue;
786 
787          for (i = 0; i < *childc; ++i) {
788             SASSERTX((*childv)[i].pid != 0);
789             closechild((*childv)[i].pid, isnormalexit);
790          }
791       }
792 
793       return;
794    }
795 
796    setchildtype(childtype(pid), &childv, &childc, NULL);
797    child = findchild(pid, *childc, *childv);
798    if (child < 0) {
799       SWARNX(child);
800       return;
801    }
802 
803    if (isnormalexit && (*childv)[child].ack != -1) /* notify child. */
804       if (write((*childv)[child].ack, &cmd, sizeof(cmd)) != sizeof(cmd))
805          swarn("%s: failed to notify %s %ld it should exit normally",
806                function,
807                childtype2string((*childv)[child].type),
808                (long)(*childv)[child].pid);
809 
810    if (((*childv)[child].s) != -1) {
811       close((*childv)[child].s);
812       (*childv)[child].s = -1;
813    }
814 
815    if (((*childv)[child].ack) != -1) {
816       close((*childv)[child].ack);
817       (*childv)[child].ack = -1;
818    }
819 
820    (*childv)[child].waitingforexit  = 1;
821    (*childv)[child].exitingnormally = isnormalexit;
822 }
823 
824 sockd_child_t *
nextchild(type,protocol)825 nextchild(type, protocol)
826    const int type;
827    const int protocol;
828 {
829    const char *function = "nextchild()";
830    sockd_child_t **childv, *mostbusy;
831    size_t i, *childc;
832    int triedagain = 0;
833 
834 tryagain:
835 
836    setchildtype(type, &childv, &childc, NULL);
837 
838    /*
839     * Try to find the child that is most busy, so that we converge to
840     * filling up slots in existing children and removing idle ones.
841     */
842    mostbusy = NULL;
843 
844    for (i = 0; i < *childc; ++i) {
845       if ((*childv)[i].freec > 0) {
846 #if BAREFOOTD
847          if (protocol == SOCKS_UDP && (*childv)[i].hasudpsession) {
848             slog(LOG_DEBUG,
849                  "%s: skipping child %ld.  Has %lu free slot%s, but also "
850                  "has an udp sessions already",
851                  function,
852                  (long)(*childv)[i].pid,
853                  (unsigned long)(*childv)[i].freec,
854                  (unsigned long)(*childv)[i].freec == 1 ? "" : "s");
855 
856             continue;
857          }
858 #endif /* BAREFOOTD */
859 
860          if (child_should_retire(&(*childv)[i]))
861             continue;
862 
863          if ((*childv)[i].waitingforexit)
864             continue;
865 
866          /*
867           * Child has at least one free slot.
868           * We want to find the child with the fewest free slots, to avoid
869           * processes with only a few clients that can not be shut down by
870           * child.maxidle.  Trying to fit as many clients as possible
871           * into each processes allows us to reduce the process count.
872           */
873          if (mostbusy == NULL
874          || (*childv)[i].freec < mostbusy->freec)
875             mostbusy = &(*childv)[i];
876 
877          if (mostbusy->freec == 1)
878             break; /* no need to look further, got the busiest we can get. */
879       }
880    }
881 
882    if (mostbusy != NULL)
883       return mostbusy;
884 
885    slog(LOG_DEBUG, "%s: no free %s slots for protocol %s, triedagain = %d",
886         function,
887         childtype2string(type),
888         protocol2string(protocol),
889         triedagain);
890 
891    if (!triedagain) {
892       slog(LOG_DEBUG, "%s: calling childcheck() and trying again", function);
893 
894       if (childcheck(type) > 0) {
895          triedagain = 1;
896          goto tryagain;
897       }
898    }
899 
900    return NULL;
901 }
902 
903 int
childtype(pid)904 childtype(pid)
905    const pid_t pid;
906 {
907 
908    if (findchild(pid, monitorc, monitorv) >= 0)
909       return PROC_MONITOR;
910 
911    if (findchild(pid, negchildc, negchildv) >= 0)
912       return PROC_NEGOTIATE;
913 
914    if (findchild(pid, reqchildc, reqchildv) >= 0)
915       return PROC_REQUEST;
916 
917    if (findchild(pid, iochildc, iochildv) >= 0)
918       return PROC_IO;
919 
920    if (pidismother(pid))
921       return PROC_MOTHER;
922 
923    return PROC_NOTOURS;
924 }
925 
926 sockd_child_t *
getchild(pid)927 getchild(pid)
928    pid_t pid;
929 {
930    ssize_t child;
931    size_t *childc;
932    sockd_child_t **childv;
933    int type;
934 
935    switch (type = childtype(pid)) {
936       case PROC_MONITOR:
937       case PROC_NEGOTIATE:
938       case PROC_REQUEST:
939       case PROC_IO:
940          break;
941 
942       case PROC_MOTHER: /* XXX should have an array for mothers also. */
943          return NULL;
944 
945       case PROC_NOTOURS:
946          return NULL;
947 
948       default:
949          SERRX(type);
950    }
951 
952    setchildtype(type, &childv, &childc, NULL);
953 
954    if ((child = findchild(pid, *childc, *childv)) >= 0)
955       return &(*childv)[child];
956 
957    SERRX(pid);
958    /* NOTREACHED */
959 }
960 
961 int
send_io(s,io)962 send_io(s, io)
963    int s;
964    sockd_io_t *io;
965 {
966    const char *function = "send_io()";
967    struct iovec iov[2];
968    struct msghdr msg;
969    int ioc, fdtosend, length;
970 #if HAVE_GSSAPI
971    gss_buffer_desc gssapistate = { 0, NULL };
972    gss_ctx_id_t original_gssidvalue, *gssid = NULL;
973    char gssapistatemem[MAXGSSAPITOKENLEN];
974 #endif /* HAVE_GSSAPI */
975    CMSG_AALLOC(cmsg, sizeof(int) * FDPASS_MAX);
976 
977    SASSERTX(io->allocated == 0);
978 
979    log_ruleinfo_shmid(CRULE_OR_HRULE(io), function, NULL);
980 
981    if (io->srule.type == object_none) {
982       SASSERTX(io->state.protocol == SOCKS_UDP);
983       SASSERTX(!HAVE_SOCKS_RULES);
984    }
985    else
986       log_ruleinfo_shmid(&io->srule, function, NULL);
987 
988    SASSERTX(!(SHMID_ISSET(CRULE_OR_HRULE(io)) && SHMID_ISSET(&io->srule)));
989 
990 #if HAVE_SOCKS_RULES
991    SASSERTX(!SHMID_ISSET(CRULE_OR_HRULE(io)));
992 
993 #else /* !HAVE_SOCKS_RULES */
994    SASSERTX(!SHMID_ISSET(&io->srule));
995 
996 #endif /* !HAVE_SOCKS_RULES */
997 
998    SASSERTX(!SHMID_ISATTACHED(CRULE_OR_HRULE(io)));
999    SASSERTX(!SHMID_ISATTACHED(&io->srule));
1000 
1001    bzero(iov, sizeof(iov));
1002    length = 0;
1003    ioc    = 0;
1004 
1005    iov[ioc].iov_base  = io;
1006    iov[ioc].iov_len   = sizeof(*io);
1007    length            += iov[ioc].iov_len;
1008    ++ioc;
1009 
1010    fdtosend = 0;
1011    CMSG_ADDOBJECT(io->src.s, cmsg, sizeof(io->src.s) * fdtosend++);
1012 
1013    switch (io->state.command) {
1014       case SOCKS_BIND:
1015          CMSG_ADDOBJECT(io->dst.s, cmsg, sizeof(io->dst.s) * fdtosend++);
1016 
1017 #if HAVE_GSSAPI
1018          if (io->src.auth.method == AUTHMETHOD_GSSAPI)
1019             gssid = &io->src.auth.mdata.gssapi.state.id;
1020 #endif /* HAVE_GSSAPI */
1021 
1022          if (io->state.extension.bind)
1023             CMSG_ADDOBJECT(io->control.s,
1024                            cmsg,
1025                            sizeof(io->control.s) * fdtosend++);
1026          break;
1027 
1028       case SOCKS_BINDREPLY:
1029          CMSG_ADDOBJECT(io->dst.s, cmsg, sizeof(io->dst.s) * fdtosend++);
1030 
1031 #if HAVE_GSSAPI
1032          if (io->dst.auth.method == AUTHMETHOD_GSSAPI)
1033             gssid = &io->dst.auth.mdata.gssapi.state.id;
1034 #endif /* HAVE_GSSAPI */
1035 
1036          if (io->state.extension.bind)
1037             CMSG_ADDOBJECT(io->control.s, cmsg,
1038             sizeof(io->control.s) * fdtosend++);
1039          break;
1040 
1041       case SOCKS_UDPASSOCIATE:
1042          SASSERTX(io->dst.s == -1);
1043 
1044 #if HAVE_GSSAPI
1045          if (io->src.auth.method == AUTHMETHOD_GSSAPI)
1046             gssid = &io->src.auth.mdata.gssapi.state.id;
1047 #endif /* HAVE_GSSAPI */
1048 
1049 #if !BAREFOOTD /* no control. */
1050          CMSG_ADDOBJECT(io->control.s, cmsg,
1051                        sizeof(io->control.s) * fdtosend++);
1052 #endif /* !BAREFOOTD */
1053          break;
1054 
1055       case SOCKS_CONNECT:
1056          CMSG_ADDOBJECT(io->dst.s, cmsg, sizeof(io->dst.s) * fdtosend++);
1057 
1058 #if HAVE_GSSAPI
1059          if (io->src.auth.method == AUTHMETHOD_GSSAPI)
1060             gssid = &io->src.auth.mdata.gssapi.state.id;
1061 #endif /* HAVE_GSSAPI */
1062          break;
1063 
1064       default:
1065          SERRX(io->state.command);
1066    }
1067 
1068 #if HAVE_GSSAPI
1069    if (gssid == NULL) {
1070       gssapistate.value  = NULL;
1071       gssapistate.length = 0;
1072    }
1073    else {
1074       original_gssidvalue = *gssid;
1075 
1076       gssapistate.value  = gssapistatemem;
1077       gssapistate.length = sizeof(gssapistatemem);
1078 
1079       if (gssapi_export_state(gssid, &gssapistate) != 0)
1080          return -1;
1081 
1082       iov[ioc].iov_base = gssapistate.value;
1083       iov[ioc].iov_len  = gssapistate.length;
1084       length           += gssapistate.length;
1085       ++ioc;
1086 
1087       if (sockscf.option.debug >= DEBUG_VERBOSE)
1088          slog(LOG_DEBUG, "%s: gssapistate has length %lu",
1089               function, (long unsigned)gssapistate.length);
1090    }
1091 #endif /* HAVE_GSSAPI */
1092 
1093    bzero(&msg, sizeof(msg));
1094    msg.msg_iov     = iov;
1095    msg.msg_iovlen  = ioc;
1096    msg.msg_name    = NULL;
1097 
1098    CMSG_SETHDR_SEND(msg, cmsg, sizeof(int) * fdtosend);
1099 
1100    if (sockscf.option.debug >= DEBUG_VERBOSE) {
1101       char ctrlbuf[MAXSOCKADDRSTRING * 2 + 64],
1102            srcbuf[sizeof(ctrlbuf)], dstbuf[sizeof(ctrlbuf)];
1103 
1104       slog(LOG_DEBUG,
1105            "%s: sending %d descriptors for command %d on fd %d.  "
1106            "bw_shmid %lu, mstats_shmid %lu, ss_shmid %lu\n"
1107            "Control: %d (%s)\n"
1108            "Src    : %d (%s)\n"
1109            "Dst    : %d (%s)",
1110            function,
1111            fdtosend,
1112            io->state.command,
1113            s,
1114            (unsigned long)io->srule.bw_shmid,
1115            (unsigned long)io->srule.mstats_shmid,
1116            (unsigned long)io->srule.ss_shmid,
1117            io->control.s,
1118            socket2string(io->control.s, ctrlbuf, sizeof(ctrlbuf)),
1119            io->src.s,
1120            socket2string(io->src.s, srcbuf, sizeof(srcbuf)),
1121            io->dst.s,
1122            io->dst.s == -1 ?
1123                "N/A" : socket2string(io->dst.s, dstbuf, sizeof(dstbuf)));
1124    }
1125 
1126    /*
1127     * if not mother, request child.  Since that child only handles one
1128     * client at a time, it's safe to block as long as it takes.  Mother
1129     * on the other hand can not block.
1130     */
1131    if (sendmsgn(s, &msg, 0, sockscf.state.type == PROC_MOTHER ? 0 : -1)
1132    != length) {
1133 #if HAVE_GSSAPI
1134       if (gssapistate.value != NULL) {
1135          *gssid = original_gssidvalue;
1136 
1137          if (gssapi_import_state(gssid, &gssapistate) != 0)
1138             swarnx("%s: could not re-import gssapi state", function);
1139       }
1140 #endif /* HAVE_GSSAPI */
1141 
1142       slog(LOG_DEBUG,
1143            "%s: sending client %s to %s failed: %s",
1144            function,
1145            sockaddr2string(&CONTROLIO(io)->raddr, NULL, 0),
1146            sockscf.state.type == PROC_MOTHER ? "child" : "mother",
1147            strerror(errno));
1148 
1149       return -1;
1150    }
1151 
1152    return 0;
1153 }
1154 
1155 int
send_client(s,_client,buf,buflen)1156 send_client(s, _client, buf, buflen)
1157    int s;
1158    const sockd_client_t *_client;
1159    const char *buf;
1160    const size_t buflen;
1161 {
1162    const char *function = "send_client()";
1163    sockd_client_t client = *_client;
1164    struct iovec iovec[1];
1165    struct msghdr msg;
1166    CMSG_AALLOC(cmsg, sizeof(int));
1167    int fdtosend;
1168 
1169    slog(LOG_DEBUG, "%s: buflen = %lu", function, (unsigned long)buflen);
1170 
1171 #if COVENANT
1172    if (buflen > 0) {
1173       memcpy(client.clientdata, buf, buflen);
1174       client.clientdatalen = buflen;
1175    }
1176 #endif /* COVENANT */
1177 
1178    bzero(iovec, sizeof(iovec));
1179    iovec[0].iov_base = &client;
1180    iovec[0].iov_len  = sizeof(client);
1181 
1182    fdtosend = 0;
1183    CMSG_ADDOBJECT(client.s, cmsg, sizeof(client.s) * fdtosend++);
1184 
1185    bzero(&msg, sizeof(msg));
1186    msg.msg_iov     = iovec;
1187    msg.msg_iovlen  = ELEMENTS(iovec);
1188    msg.msg_name    = NULL;
1189 
1190    CMSG_SETHDR_SEND(msg, cmsg, sizeof(int) * fdtosend);
1191 
1192    if (sockscf.option.debug >= DEBUG_VERBOSE)
1193       slog(LOG_DEBUG, "%s: sending fd %d (%s) on fd %d ...",
1194            function, client.s, socket2string(client.s, NULL, 0), s);
1195 
1196    if (sendmsgn(s, &msg, 0, sockscf.state.type == PROC_MOTHER ? 0 : -1)
1197    != (ssize_t)sizeof(client)) {
1198       slog(LOG_DEBUG, "%s: sending client to mother on fd %d failed: %s",
1199            function, s, strerror(errno));
1200 
1201       return -1;
1202    }
1203 
1204    return 0;
1205 }
1206 
1207 int
send_req(s,req)1208 send_req(s, req)
1209    int s;
1210    sockd_request_t *req;
1211 {
1212    const char *function = "send_req()";
1213    struct iovec iov[2];
1214    struct msghdr msg;
1215    int fdtosend, ioc, length;
1216 #if HAVE_GSSAPI
1217    gss_buffer_desc gssapistate;
1218    char gssapistatemem[MAXGSSAPITOKENLEN];
1219 #endif /* HAVE_GSSAPI */
1220    CMSG_AALLOC(cmsg, sizeof(int));
1221 
1222    ioc    = 0;
1223    length = 0;
1224 
1225    bzero(iov, sizeof(iov));
1226    iov[ioc].iov_base = req;
1227    iov[ioc].iov_len  = sizeof(*req);
1228    length           += iov[ioc].iov_len;
1229    ++ioc;
1230 
1231 #if HAVE_GSSAPI
1232    if (req->sauth.method == AUTHMETHOD_GSSAPI) {
1233       gssapistate.value   = gssapistatemem;
1234       gssapistate.length  = sizeof(gssapistatemem);
1235 
1236       if (gssapi_export_state(&req->sauth.mdata.gssapi.state.id, &gssapistate)
1237       != 0)
1238          return 1;
1239 
1240       iov[ioc].iov_base = gssapistate.value;
1241       iov[ioc].iov_len  = gssapistate.length;
1242       length += iov[ioc].iov_len;
1243       ++ioc;
1244 
1245       if (sockscf.option.debug >= DEBUG_VERBOSE)
1246          slog(LOG_DEBUG, "%s: gssapistate length is %lu",
1247               function, (long unsigned)gssapistate.length);
1248    }
1249    else {
1250       gssapistate.value   = NULL;
1251       gssapistate.length  = 0;
1252    }
1253 #endif /* HAVE_GSSAPI */
1254 
1255    fdtosend = 0;
1256 
1257    if (req->s == -1) {
1258 #if BAREFOOTD
1259       SASSERT(req->req.command == SOCKS_UDPASSOCIATE);
1260 #else /* !BAREFOOTD */
1261       SERRX(req->s);
1262 #endif /* !BAREFTOOD */
1263    }
1264    else
1265       CMSG_ADDOBJECT(req->s, cmsg, sizeof(req->s) * fdtosend++);
1266 
1267    bzero(&msg, sizeof(msg));
1268    msg.msg_iov     = iov;
1269    msg.msg_iovlen  = ELEMENTS(iov);
1270    msg.msg_name    = NULL;
1271 
1272    CMSG_SETHDR_SEND(msg, cmsg, sizeof(int) * fdtosend);
1273 
1274    if (sockscf.option.debug >= DEBUG_VERBOSE && req->s != -1)
1275       slog(LOG_DEBUG, "%s: sending fd %d (%s) on fd %d ...",
1276            function, req->s, socket2string(req->s, NULL, 0), s);
1277 
1278    if (sendmsgn(s, &msg, 0, sockscf.state.type == PROC_MOTHER ? 0 : -1)
1279    != length) {
1280       if (sockscf.state.type == PROC_MOTHER)
1281          swarn("%s: sending client to child failed", function);
1282       else
1283          slog(sockd_motherexists() ? LOG_WARNING : LOG_DEBUG,
1284               "%s: sending client to mother failed: %s",
1285               function, strerror(errno));
1286 
1287 #if HAVE_GSSAPI
1288       if (gssapistate.value != NULL) {
1289          /* re-import so it's still here when/if we retry sending client. */
1290          if (gssapi_import_state(&req->sauth.mdata.gssapi.state.id,
1291                                  &gssapistate) != 0)
1292             swarnx("%s: could not re-import gssapi state", function);
1293       }
1294 #endif /* HAVE_GSSAPI */
1295 
1296       return -1;
1297    }
1298 
1299    return 0;
1300 }
1301 
1302 void
sigchildbroadcast(sig)1303 sigchildbroadcast(sig)
1304    int sig;
1305 {
1306    const char *function = "sigchildbroadcast()";
1307    int childtypesv[] =  { PROC_MONITOR, PROC_NEGOTIATE, PROC_REQUEST, PROC_IO };
1308    size_t *childc, childtypec;
1309    sockd_child_t **childv;
1310 
1311    for (childtypec = 0; childtypec < ELEMENTS(childtypesv); ++childtypec) {
1312       size_t i;
1313 
1314       if (childtypesv[childtypec]       == PROC_MONITOR
1315       && pidismother(sockscf.state.pid) != 1)
1316          continue; /* only main mother controls the monitor child. */
1317 
1318       setchildtype(childtypesv[childtypec], &childv, &childc, NULL);
1319 
1320       for (i = 0; i < *childc; ++i) {
1321          slog(LOG_DEBUG, "%s: sending signal %d to %s %ld",
1322               function,
1323               sig,
1324               childtype2string(childtypesv[childtypec]),
1325               (long)(*childv)[i].pid);
1326 
1327          if (kill((*childv)[i].pid, sig) != 0) {
1328             if ((*childv)[i].waitingforexit)
1329                slog(LOG_DEBUG,
1330                     "%s: could not send signal %d to child process %ld: "
1331                     "child has exited already",
1332                     function, sig, (long)(*childv)[i].pid);
1333             else
1334                swarn("%s: could not send signal %d to child process %ld",
1335                      function, sig, (long)(*childv)[i].pid);
1336          }
1337       }
1338    }
1339 }
1340 
1341 size_t
maxfreeslots(childtype)1342 maxfreeslots(childtype)
1343    const int childtype;
1344 {
1345 
1346    switch (childtype) {
1347       case PROC_MONITOR:
1348          return 1;
1349 
1350       case PROC_NEGOTIATE:
1351          return SOCKD_NEGOTIATEMAX;
1352 
1353       case PROC_REQUEST:
1354          return SOCKD_REQUESTMAX;
1355 
1356       case PROC_IO:
1357          return SOCKD_IOMAX;
1358 
1359       default:
1360          SERRX(childtype);
1361    }
1362 
1363    return 0; /* NOTREACHED */
1364 }
1365 
1366 int
child_should_retire(child)1367 child_should_retire(child)
1368    const sockd_child_t *child;
1369 {
1370    const char *function = "child_should_retire()";
1371 
1372    if (sockscf.child.maxrequests != 0
1373    &&  child->sentc >= sockscf.child.maxrequests) {
1374       slog(LOG_DEBUG,
1375            "%s: %s %ld has served %lu requests, while the max is %lu.  "
1376            "It should retire as soon as it has finished serving its %d "
1377            "remaining client%s%s",
1378            function,
1379            childtype2string(child->type),
1380            (long)child->pid,
1381            (unsigned long)child->sentc,
1382            (unsigned long)sockscf.child.maxrequests,
1383            (int)(maxfreeslots(child->type) - child->freec),
1384            maxfreeslots(child->type) - child->freec == 1 ? "" : "s",
1385            maxfreeslots(child->type) - child->freec == 0 ?
1386                                                          ", meaning now" : "");
1387 
1388       return 1;
1389    }
1390 
1391    if (sockscf.child.maxlifetime != 0) {
1392       time_t tnow;
1393 
1394       if (socks_difftime(time_monotonic(&tnow), child->created)
1395       >=  (time_t)sockscf.child.maxlifetime) {
1396          slog(LOG_DEBUG,
1397               "%s: %s %d has served for %ld seconds, while the max is %ld.  "
1398               "It should retire as soon as it has finished serving its %d "
1399               "remaining client%s%s",
1400               function,
1401               childtype2string(child->type),
1402               (int)child->pid,
1403               socks_difftime(tnow, child->created),
1404               (long)sockscf.child.maxlifetime,
1405               (int)(maxfreeslots(child->type) - child->freec),
1406               maxfreeslots(child->type) - child->freec == 1 ? "" : "s",
1407               maxfreeslots(child->type) - child->freec == 0 ?
1408                                                          ", meaning now" : "");
1409 
1410          return 1;
1411       }
1412    }
1413 
1414    return 0;
1415 }
1416 
1417 
1418 
1419 void
sockd_print_child_ready_message(freefds)1420 sockd_print_child_ready_message(freefds)
1421    const size_t freefds;
1422 {
1423    const char *function = "sockd_print_child_ready_message()";
1424 
1425    slog(LOG_DEBUG,
1426         "%s: I'm %s and ready to serve with %lu free fd%s and %lu free slot%s",
1427         function,
1428         childtype2string(sockscf.state.type),
1429         (unsigned long)freefds, freefds == 1 ? "" : "s",
1430         (unsigned long)maxfreeslots(sockscf.state.type),
1431         maxfreeslots(sockscf.state.type) == 1 ? "" : "s");
1432 }
1433 
1434 
1435 static sockd_child_t *
addchild(type)1436 addchild(type)
1437    const int type;
1438 {
1439    const char *function = "addchild()";
1440    void (*childfunction)(void);
1441    sigset_t all, oldmask;
1442    sockd_mother_t mother;
1443    sockd_child_t **childv;
1444    pid_t pid;
1445    socklen_t optlen;
1446    size_t *childc;
1447    char *reason;
1448    int min, rcvbuf, sndbuf, rcvbuf_set1, rcvbuf_set2, sndbuf_set1, sndbuf_set2,
1449        p, optname_sndbuf, optname_rcvbuf, ackpipev[2], datapipev[2];
1450 
1451    slog(LOG_DEBUG, "%s: type is %s", function, childtype2string(type));
1452 
1453    if (sockscf.state.highestfdinuse == 0)
1454       freedescriptors(NULL, &sockscf.state.highestfdinuse);
1455 
1456    /*
1457     * create datapipe ...
1458     */
1459    if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, datapipev) != 0) {
1460       swarn("%s: socketpair(AF_LOCAL, SOCK_DGRAM)", function);
1461       return NULL;
1462    }
1463 
1464    /* ... and ackpipe. */
1465    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, ackpipev) != 0) {
1466       swarn("%s: socketpair(AF_LOCAL, SOCK_STREAM)", function);
1467 
1468       closev(ELEMENTS(datapipev), datapipev);
1469       return NULL;
1470    }
1471 
1472    /*
1473     * Need to set the datapipe non-blocking too, even though it's a
1474     * DGRAM-based pipe, or we will block on read/write, because it's
1475     * AF_LOCAL?
1476     */
1477 
1478 #if HAVE_VALGRIND_VALGRIND_H
1479    if (RUNNING_ON_VALGRIND)
1480       reason = "pipe between moter and child (probable Valgrind bug)";
1481    else
1482       reason = "pipe between moter and child";
1483 #else /* !HAVE_VALGRIND_VALGRIND_H */
1484    reason = "pipe between moter and child";
1485 #endif /* !HAVE_VALGRIND_VALGRIND_H */
1486 
1487    if (setnonblocking(ackpipev[0],  reason)  == -1
1488    ||  setnonblocking(ackpipev[1],  reason)  == -1
1489    ||  setnonblocking(datapipev[0], reason)  == -1
1490    ||  setnonblocking(datapipev[1], reason)  == -1) {
1491 #if HAVE_VALGRIND_VALGRIND_H
1492          if (RUNNING_ON_VALGRIND) {
1493          /*
1494           * Valgrind seems to have some problems with programs that
1495           * increase the max number of open files in some cases.
1496           * Ref http://sourceforge.net/mailarchive/forum.php?thread_name=4F3F7A23.8020808%40gentoo.org&forum_name=valgrind-users
1497           */
1498 
1499          if (fdisopen(datapipev[0]))
1500             close(datapipev[0]);
1501          else
1502             swarn("%s: probable valgrind bug triggered", function);
1503 
1504          if (fdisopen(datapipev[1]))
1505             close(datapipev[1]);
1506          else
1507             slog(LOG_NOTICE, "%s: probable valgrind bug triggered", function);
1508 
1509          if (fdisopen(ackpipev[0]))
1510             close(ackpipev[0]);
1511          else
1512             slog(LOG_NOTICE, "%s: probable valgrind bug triggered", function);
1513 
1514          if (fdisopen(ackpipev[1]))
1515             close(ackpipev[1]);
1516          else
1517             slog(LOG_NOTICE, "%s: probable valgrind bug triggered", function);
1518 
1519          return NULL;
1520       }
1521 #endif /* HAVE_VALGRIND_VALGRIND_H */
1522 
1523       closev(ELEMENTS(datapipev), datapipev);
1524       closev(ELEMENTS(ackpipev), ackpipev);
1525 
1526       return NULL;
1527    }
1528 
1529    /*
1530     * Try to set socket buffers to a optimal size depending on the size of
1531     * the data that passes over the pipes.  Could fine tune this further by
1532     * differentiating between snd/rcv-sizes for mother/child, but not
1533     * bothering with that at the moment.
1534     */
1535    switch (setchildtype(type, &childv, &childc, &childfunction)) {
1536       case PROC_MONITOR:
1537          /* only exit message is expected, so set to some small size. */
1538          sndbuf = sizeof(SOCKD_EXITNORMALLY);
1539          rcvbuf = sizeof(SOCKD_EXITNORMALLY);
1540          break;
1541 
1542       case PROC_NEGOTIATE:
1543          /*
1544           * A negotiator child receives a sockd_client_t struct,
1545           * and sends back a sockd_request_t struct.
1546           */
1547          rcvbuf = (MAX(sizeof(sockd_client_t), sizeof(sockd_request_t))
1548                 + sizeof(struct msghdr)
1549                 + CMSG_SPACE(sizeof(int)) * FDPASS_MAX);
1550 
1551          rcvbuf += SENDMSG_PADBYTES;
1552 
1553 #if HAVE_GSSAPI
1554          rcvbuf += (MAX_GSS_STATE + sizeof(struct iovec));
1555 #endif /* HAVE_GSSAPI */
1556 
1557          sndbuf = rcvbuf * SOCKD_NEGOTIATEMAX;
1558          break;
1559 
1560       case PROC_REQUEST:
1561          /*
1562           * A request child receives a sockd_request_t structure,
1563           * it sends back a sockd_io_t structure.
1564           */
1565          rcvbuf = (MAX(sizeof(sockd_request_t), sizeof(sockd_io_t))
1566                 + sizeof(struct msghdr)
1567                 + CMSG_SPACE(sizeof(int)) * FDPASS_MAX);
1568 
1569          rcvbuf += SENDMSG_PADBYTES;
1570 
1571 #if HAVE_GSSAPI
1572          rcvbuf += (MAX_GSS_STATE + sizeof(struct iovec));
1573 #endif /* HAVE_GSSAPI */
1574 
1575          sndbuf = rcvbuf * SOCKD_REQUESTMAX;
1576          break;
1577 
1578       case PROC_IO:
1579          /*
1580           * A io child receives a sockd_io_t structure,
1581           * it sends back only an ack-byte.
1582           * XXX that is not true in COVENANT's case.
1583           */
1584          rcvbuf = (sizeof(sockd_io_t)
1585                 +  sizeof(struct msghdr)
1586                 +  CMSG_SPACE(sizeof(int)) * FDPASS_MAX);
1587 
1588          rcvbuf += SENDMSG_PADBYTES;
1589 
1590 #if HAVE_GSSAPI
1591          rcvbuf += (MAX_GSS_STATE + sizeof(struct iovec));
1592 #endif /* HAVE_GSSAPI */
1593 
1594          sndbuf = rcvbuf * SOCKD_IOMAX;
1595          break;
1596 
1597       default:
1598          SERRX(type);
1599    }
1600 
1601    min = rcvbuf;
1602 
1603    if (HAVE_PIPEBUFFER_SEND_BASED)
1604       ; /* as expected. */
1605    else if (HAVE_PIPEBUFFER_RECV_BASED) {
1606       /*
1607        * reverse of our assumption that how much we can write to the pipe
1608        * depends on the pipe's sndbuf.  On this platform it instead depends
1609        * on the pipe's rcvbuf.
1610        */
1611       const size_t tmp    = sndbuf;
1612                    sndbuf = rcvbuf;
1613                    rcvbuf = tmp;
1614    }
1615    else if (HAVE_PIPEBUFFER_UNKNOWN) { /* wastes a lot of memory. */
1616       rcvbuf = MAX(sndbuf, rcvbuf);
1617       sndbuf = MAX(sndbuf, rcvbuf);
1618    }
1619 
1620 #ifdef SO_RCVBUFFORCE
1621    if (sockscf.state.haveprivs) {
1622       optname_rcvbuf = SO_RCVBUFFORCE;
1623       sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
1624    }
1625    else
1626 #endif /* !SO_RCVBUFFORCE */
1627       optname_rcvbuf = SO_RCVBUF;
1628 
1629    p = rcvbuf;
1630    do {
1631       if (setsockopt(datapipev[MOTHER],
1632                      SOL_SOCKET,
1633                      optname_rcvbuf,
1634                      &p,
1635                      sizeof(p)) != 0
1636       ||  setsockopt(datapipev[CHILD],
1637                      SOL_SOCKET,
1638                      optname_rcvbuf,
1639                      &p,
1640                      sizeof(p)) != 0) {
1641          slog(LOG_DEBUG, "%s: could not set SO_RCVBUF to %d: %s",
1642               function, p, strerror(errno));
1643 
1644          p -= min;
1645       }
1646       else
1647          break;
1648    } while (p > min);
1649 
1650 #ifdef SO_RCVBUFFORCE
1651    if (sockscf.state.haveprivs)
1652       sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
1653 #endif /* !SO_RCVBUFFORCE */
1654 
1655    optlen = sizeof(rcvbuf_set1);
1656    if (getsockopt(datapipev[MOTHER],
1657                   SOL_SOCKET,
1658                   SO_RCVBUF,
1659                   &rcvbuf_set1,
1660                   &optlen) != 0
1661    ||  getsockopt(datapipev[CHILD],
1662                   SOL_SOCKET,
1663                   SO_RCVBUF,
1664                   &rcvbuf_set2,
1665                   &optlen) != 0) {
1666       swarn("%s: could not get size of SO_RCVBUF", function);
1667 
1668       closev(ELEMENTS(datapipev), datapipev);
1669       closev(ELEMENTS(ackpipev), ackpipev);
1670 
1671       return NULL;
1672    }
1673 
1674 #ifdef SO_SNDBUFFORCE
1675    if (sockscf.state.haveprivs) {
1676       optname_sndbuf = SO_SNDBUFFORCE;
1677       sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
1678    }
1679    else
1680 #endif /* !SO_SNDBUFFORCE */
1681       optname_sndbuf = SO_SNDBUF;
1682 
1683    p = sndbuf;
1684    do {
1685       if (setsockopt(datapipev[MOTHER],
1686                      SOL_SOCKET,
1687                      optname_sndbuf,
1688                      &p,
1689                      sizeof(p)) != 0
1690       ||  setsockopt(datapipev[CHILD],
1691                      SOL_SOCKET,
1692                      optname_sndbuf,
1693                      &p,
1694                      sizeof(p)) != 0) {
1695 
1696          slog(LOG_DEBUG, "%s: could not set SO_SNDBUF to %d: %s",
1697               function, p, strerror(errno));
1698 
1699          p -= min;
1700       }
1701       else
1702          break;
1703    } while (p > min);
1704 
1705 #ifdef SO_SNDBUFFORCE
1706    if (sockscf.state.haveprivs)
1707       sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
1708 #endif /* !SO_SNDBUFFORCE */
1709 
1710    optlen = sizeof(sndbuf_set1);
1711    if (getsockopt(datapipev[MOTHER],
1712                   SOL_SOCKET,
1713                   SO_SNDBUF,
1714                   &sndbuf_set1,
1715                   &optlen) != 0
1716    ||  getsockopt(datapipev[CHILD],
1717                   SOL_SOCKET,
1718                   SO_SNDBUF,
1719                   &sndbuf_set2,
1720                   &optlen) != 0) {
1721       swarn("%s: could not get size of SO_SNDBUF", function);
1722 
1723       closev(ELEMENTS(datapipev), datapipev);
1724       closev(ELEMENTS(ackpipev), ackpipev);
1725 
1726       return NULL;
1727    }
1728 
1729 
1730    if (rcvbuf_set1 < rcvbuf || rcvbuf_set2 < rcvbuf
1731    ||  sndbuf_set1 < sndbuf || sndbuf_set2 < sndbuf) {
1732       const int isfatal = (rcvbuf_set1 < min || rcvbuf_set2 < min
1733                         || sndbuf_set1 < min || sndbuf_set2 < min);
1734       char *value;
1735       int loggedalready;
1736 
1737       switch (type) {
1738          case PROC_NEGOTIATE: {
1739              static int local_loggedalready;
1740 
1741              loggedalready       = local_loggedalready;
1742              local_loggedalready = 1;
1743 
1744              value = "SOCKD_NEGOTIATEMAX";
1745              break;
1746          }
1747 
1748          case PROC_REQUEST: {
1749              static int local_loggedalready;
1750 
1751              loggedalready       = local_loggedalready;
1752              local_loggedalready = 1;
1753 
1754             value = "SOCKD_REQUESTMAX";
1755             break;
1756          }
1757 
1758          case PROC_IO: {
1759              static int local_loggedalready;
1760 
1761              loggedalready       = local_loggedalready;
1762              local_loggedalready = 1;
1763 
1764             value = "SOCKD_IOMAX";
1765             break;
1766          }
1767 
1768          case PROC_MONITOR: {
1769              /*
1770               * Very strange.  Our requested size should be minimal.
1771               */
1772              static int local_loggedalready;
1773 
1774              loggedalready       = local_loggedalready;
1775              local_loggedalready = 1;
1776 
1777             value = "N/A";
1778             break;
1779          }
1780 
1781          default:
1782             SERRX(type);
1783       }
1784 
1785       /*
1786        * Ideally we should shrink the size of the objects we IPC around.
1787        * Keep this message to remind ourselves.
1788        */
1789 #if PRERELEASE
1790       slog(isfatal ? LOG_WARNING : (loggedalready ?  LOG_DEBUG : LOG_NOTICE),
1791 #else /* !PRERELEASE */
1792       slog(isfatal ? LOG_WARNING : (loggedalready ?  LOG_DEBUG : LOG_DEBUG),
1793 #endif /* !PRERELEASE */
1794 
1795            "%s: kernel did not honour requested size concerning send/receive "
1796            "buffers for IPC between mother and child processes.  "
1797            "Requested send size: %d, returned: %d and %d.  "
1798            "Requested receive size: %d, returned: %d and %d. "
1799            "This probably means %s's %s was at compile-time set to a value "
1800            "too large for the current kernel settings.  "
1801            "To avoid this warning you will need to either increase the "
1802            "kernel's max-size socket buffers somehow, or decrease the %s "
1803            "value in %s and recompile.  "
1804            "%s",
1805            function,
1806            sndbuf, sndbuf_set1, sndbuf_set2,
1807            rcvbuf, rcvbuf_set1, rcvbuf_set2,
1808            PRODUCT,
1809            value,
1810            value,
1811            PRODUCT,
1812            isfatal ? "" : "We will continue with the smaller buffersize, as "
1813                           "if our internal maxvalue was reduced, but "
1814                           "performance might be degraded");
1815 
1816       if (isfatal) {
1817          closev(ELEMENTS(datapipev), datapipev);
1818          closev(ELEMENTS(ackpipev), ackpipev);
1819 
1820          return NULL;
1821       }
1822    }
1823 
1824    /*
1825     * All set to create the new child.  Update highestfdinuse now.
1826     * Never mind that it will not be exactly the same in child and
1827     * mother.  The important thing is that the value saved is not lower
1828     * than what the value really is.
1829     */
1830    sockscf.state.highestfdinuse = MAX(sockscf.state.highestfdinuse,
1831                                       MAX(datapipev[0], datapipev[1]));
1832 
1833    sockscf.state.highestfdinuse = MAX(sockscf.state.highestfdinuse,
1834                                       MAX(ackpipev[0], ackpipev[1]));
1835 
1836    slog(LOG_DEBUG, "%s: highest fd in use at the moment: %d",
1837         function, sockscf.state.highestfdinuse);
1838 
1839    /*
1840     * Temporarily block signals to avoid mixing up signals to us
1841     * and to child created as well as any races between child receiving
1842     * signal and child having finished setting up signalhandlers.
1843     */
1844    (void)sigfillset(&all);
1845    if (sigprocmask(SIG_SETMASK, &all, &oldmask) != 0)
1846       swarn("%s: sigprocmask(SIG_SETMASK)", function);
1847 
1848    switch ((pid = fork())) {
1849       case -1:
1850          if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0)
1851             swarn("%s: sigprocmask(SIG_SETMASK, &oldmask, NULL)", function);
1852 
1853          swarn("%s: fork()", function);
1854 
1855          closev(ELEMENTS(datapipev), datapipev);
1856          closev(ELEMENTS(ackpipev), ackpipev);
1857 
1858          return NULL;
1859 
1860       case 0: {
1861          struct sigaction sigact;
1862          size_t i, maxfd;
1863 
1864 #if HAVE_PROFILING && HAVE_MONCONTROL /* XXX is this only needed on Linux? */
1865          moncontrol(1);
1866 #endif /* HAVE_PROFILING && HAVE_MONCONTROL */
1867 
1868          bzero(&sigact, sizeof(sigact));
1869 
1870          /*
1871           * signals mother has set up but which we need ignore at this
1872           * point, lest we accidentally run mothers signal handler if the
1873           * child does not install it's own signal handler for the
1874           * particular signal.
1875           * Later on, the child sets up its own signal handlers.
1876           */
1877 #if HAVE_BSDAUTH
1878          /*
1879           * For BSD authentication on OpenBSD, libc forks sub process,
1880           * so SIG_DFL is needed for waitpid() to work.
1881           */
1882          sigact.sa_handler = SIG_DFL;
1883 #else /* !HAVE_BSDAUTH */
1884          sigact.sa_handler = SIG_IGN;
1885 #endif /* !HAVE_BSDAUTH */
1886 
1887          if (sigaction(SIGCHLD, &sigact, NULL) != 0)
1888             swarn("%s: sigaction(SIGCHLD)", function);
1889 
1890          sigact.sa_handler = SIG_IGN;
1891 
1892 #if HAVE_SIGNAL_SIGINFO
1893          if (sigaction(SIGINFO, &sigact, NULL) != 0)
1894             swarn("%s: sigaction(SIGINFO)", function);
1895 #endif /* HAVE_SIGNAL_SIGINFO */
1896 
1897          if (sigaction(SIGUSR1, &sigact, NULL) != 0)
1898             swarn("%s: sigaction(SIGUSR1)", function);
1899 
1900          /*
1901           * Next install a SIGHUP handler.  Same for all children and
1902           * different from the one mother uses.
1903           */
1904          sigact.sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_SIGINFO;
1905 
1906          sigact.sa_sigaction = sighup_child;
1907          if (sigaction(SIGHUP, &sigact, NULL) != 0)
1908             serr("%s: could not install signalhandler for SIGHUP", function);
1909 
1910          mother.s           = datapipev[CHILD];
1911          mother.ack         = ackpipev[CHILD];
1912          sockscf.state.type = type;
1913 
1914          newprocinit();
1915          postconfigloadinit(); /* may be something special for this process. */
1916 
1917 #if 0
1918          slog(LOG_DEBUG, "sleeping...");
1919          sleep(20);
1920 #endif
1921 
1922          /*
1923           * It would be nice to be able to lose all root privileges here
1924           * but unfortunately we can't.  All children may need it for
1925           * re-opening logfiles or sockd.conf on SIGHUP.  In addition:
1926           *
1927           * monitor children:
1928           *      - Nothing known.
1929           *
1930           * negotiation children:
1931           *      - could need privileges to check password.
1932           *
1933           * request children:
1934           *      - could need privileges to bind port.
1935           *      - could need privileges to check password.
1936           *
1937           * io children:
1938           *      - could need privileges to create a raw socket to listen
1939           *        for icmp errors.
1940           *      - could need privileges to bind port if using the
1941           *        redirect() module.
1942           *
1943           * Also may need it to write to the logfiles.
1944           * If we have privilege-support, give up what we can though.
1945           */
1946 
1947          switch (type) {
1948             case PROC_MONITOR:
1949                break;
1950 
1951             case PROC_NEGOTIATE:
1952 #if HAVE_LIBWRAP
1953 #if SOCKD_NEGOTIATEMAX > 1
1954                resident = 1;
1955 #endif /* SOCKD_NEGOTIATEMAX > 1 */
1956 #endif /* HAVE_LIBWRAP */
1957 
1958 #if HAVE_PRIVILEGES
1959                if (sockscf.state.haveprivs) {
1960                   /* don't need this privilege so permanently loose it. */
1961                   priv_delset(sockscf.privileges.privileged, PRIV_NET_PRIVADDR);
1962 
1963                   if (setppriv(PRIV_SET,
1964                                PRIV_PERMITTED,
1965                                sockscf.privileges.privileged) != 0)
1966                      swarn("%s: setppriv() failed to relinquish "
1967                            "PRIV_NET_PRIVADDR",
1968                            function);
1969                }
1970 #endif /* HAVE_PRIVILEGES */
1971 
1972                break;
1973 
1974             case PROC_REQUEST:
1975 #if HAVE_LIBWRAP
1976 #if SOCKD_REQUESTMAX > 1
1977                resident = 1;
1978 #endif /* SOCKD_REQUESTMAX > 1 */
1979 #endif /* HAVE_LIBWRAP */
1980                break;
1981 
1982             case PROC_IO:
1983 #if HAVE_LIBWRAP
1984 #if SOCKD_IOMAX > 1
1985                resident = 1;
1986 #endif /* SOCKD_IOMAX > 1 */
1987 #endif /* HAVE_LIBWRAP */
1988                break;
1989 
1990             default:
1991                SERRX(type);
1992          }
1993 
1994          /*
1995           * delete all fd's  we got from parent, with a few exceptions.
1996           */
1997 
1998          maxfd = (size_t)sockscf.state.highestfdinuse;
1999          SASSERTX(maxfd != 0);
2000 
2001          for (i = 0; i <= maxfd; ++i) {
2002             /*
2003              * exceptions.
2004              */
2005 
2006             if (i == (size_t)mother.s || i == (size_t)mother.ack)
2007                continue;
2008 
2009             if (descriptorisreserved((int)i))
2010                continue;
2011 
2012             (void)close((int)i);
2013          }
2014 
2015          /*
2016           * Needs to be called again after closing, since if using syslog we
2017           * don't know what descriptor that uses, so it will have been closed
2018           * in the above close(2) loop.
2019           *
2020           * This must happen as the first thing after the above loop as
2021           * newprocinit() will close the old syslog descriptor, if any,
2022           * before opening a new one.  If we have started to use the
2023           * descriptor for something else already (e.g. due to dup(2)),
2024           * newprocinit(), will still close the old descriptor, even
2025           * though it's no longer a syslog descriptor.
2026           */
2027          newprocinit();
2028 
2029          /*
2030           * This is minor optimization to make things faster for select(2)
2031           * by avoiding having two increasingly high-numbered descriptors
2032           * to check for, with most of the other descriptors in the lower-end.
2033           */
2034 
2035           datapipev[0] = mother.s;
2036           datapipev[1] = mother.ack;
2037 
2038           if ((mother.s   = dup(mother.s))   == -1
2039           ||  (mother.ack = dup(mother.ack)) == -1)
2040             serr("%s: failed to dup(2) pipe to mother", function);
2041 
2042           close(datapipev[0]);
2043           close(datapipev[1]);
2044 
2045          if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0)
2046             swarn("%s: sigprocmask(SIG_SETMASK, &oldmask, NULL)", function);
2047 
2048          /*
2049           * Ok, all set for this process.
2050           */
2051 
2052          slog(LOG_DEBUG, "%s: I am a new %s with data-pipe %d and ack-pipe %d",
2053               function, childtype2string(type), mother.s, mother.ack);
2054 
2055          sockscf.state.mother = mother;
2056          time_monotonic(&sockscf.stat.boot);
2057 
2058          errno = 0;
2059          childfunction();
2060          /* NOTREACHED */
2061          break;
2062       }
2063 
2064       default: {
2065          sockd_child_t *p;
2066 
2067          if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0)
2068             swarn("%s: sigprocmask(SIG_SETMASK, &oldmask, NULL)", function);
2069 
2070          if ((p = realloc(*childv, sizeof(**childv) * (*childc + 1))) == NULL) {
2071             swarn("%s: %s", function, NOMEM);
2072 
2073             closev(ELEMENTS(datapipev), datapipev);
2074             closev(ELEMENTS(ackpipev), ackpipev);
2075 
2076             return NULL;
2077          }
2078          *childv = p;
2079 
2080          bzero(&((*childv)[*childc]), sizeof((*childv)[*childc]));
2081 
2082          time_monotonic(&(*childv)[*childc].created);
2083          (*childv)[*childc].type           = type;
2084          (*childv)[*childc].pid            = pid;
2085          (*childv)[*childc].s              = datapipev[MOTHER];
2086          (*childv)[*childc].ack            = ackpipev[MOTHER];
2087 
2088          close(datapipev[CHILD]);
2089          close(ackpipev[CHILD]);
2090 
2091          slog(LOG_DEBUG,
2092               "%s: created new %s with pid %ld, data-pipe %d and ack-pipe %d.  "
2093               "Minimum rcvbuf: %d, set: %d and %d.  "
2094               "Minimum sndbuf: %d, set: %d and %d",
2095               function,
2096               childtype2string((*childv)[*childc].type),
2097               (long)(*childv)[*childc].pid,
2098               (*childv)[*childc].s,
2099               (*childv)[*childc].ack,
2100               rcvbuf, rcvbuf_set1, rcvbuf_set2,
2101               sndbuf, sndbuf_set1, sndbuf_set2);
2102 
2103          switch ((*childv)[*childc].type) {
2104             case PROC_MONITOR:
2105                /*
2106                 * Doesn't really have slots, so just set 1.  Will remain
2107                 * at one for the entire lifespans, as there are no slots.
2108                 */
2109                (*childv)[*childc].freec = 1;
2110                break;
2111 
2112             case PROC_NEGOTIATE:
2113                (*childv)[*childc].freec = SOCKD_NEGOTIATEMAX;
2114                break;
2115 
2116             case PROC_REQUEST:
2117                (*childv)[*childc].freec = SOCKD_REQUESTMAX;
2118                break;
2119 
2120             case PROC_IO:
2121                (*childv)[*childc].freec = SOCKD_IOMAX;
2122                break;
2123 
2124             default:
2125                SERRX((*childv)[*childc].type);
2126          }
2127       }
2128    }
2129 
2130    return &(*childv)[(*childc)++];
2131 }
2132 
2133 
2134 static int
setchildtype(type,childv,childc,function)2135 setchildtype(type, childv, childc, function)
2136    int type;
2137    sockd_child_t ***childv;
2138    size_t **childc;
2139    void (**function)(void);
2140 {
2141    size_t *c;
2142    sockd_child_t **v;
2143    void (*f)(void);
2144 
2145    switch (type) {
2146       case PROC_MONITOR:
2147          c = &monitorc;
2148          v = &monitorv;
2149          f = &run_monitor;
2150          break;
2151 
2152       case PROC_NEGOTIATE:
2153          c = &negchildc;
2154          v = &negchildv;
2155          f = &run_negotiate;
2156          break;
2157 
2158       case PROC_IO:
2159          c = &iochildc;
2160          v = &iochildv;
2161          f = &run_io;
2162          break;
2163 
2164       case PROC_REQUEST:
2165          c = &reqchildc;
2166          v = &reqchildv;
2167          f = &run_request;
2168          break;
2169 
2170       default:
2171          SERRX(type);
2172    }
2173 
2174    if (childv != NULL)
2175       *childv = v;
2176 
2177    if (childc != NULL)
2178       *childc = c;
2179 
2180    if (function != NULL)
2181       *function = f;
2182 
2183    SASSERTX(c != NULL);
2184    SASSERTX(v != NULL);
2185    SASSERTX(f != NULL);
2186 
2187    return type;
2188 }
2189 
2190 static ssize_t
findchild(pid,childc,childv)2191 findchild(pid, childc, childv)
2192    pid_t pid;
2193    size_t childc;
2194    const sockd_child_t *childv;
2195 {
2196    static size_t i;
2197 
2198    if (i < childc && childv[i].pid == pid)
2199       return i;
2200 
2201    for (i = 0; i < childc; ++i)
2202       if (childv[i].pid == pid)
2203          return i;
2204 
2205    return -1;
2206 }
2207 
2208 
2209 /* ARGSUSED */
2210 void
sighup_child(sig,si,sc)2211 sighup_child(sig, si, sc)
2212    int sig;
2213    siginfo_t *si;
2214    void *sc;
2215 {
2216    const char *function = "sighup_child()";
2217    const int errno_s = errno;
2218    struct config *shmemconfig, config;
2219    ptrdiff_t offset;
2220 #if DIAGNOSTIC
2221    size_t i;
2222 #endif /* DIAGNOSTIC */
2223 
2224    SIGNAL_PROLOGUE(sig, si, errno_s);
2225 
2226    /*
2227     * we are not main mother.  Can we assume the signal is from mother?
2228     * If not, ignore it.
2229     * Some systems don't set si_pid correctly, so check if the value is set
2230     * first.
2231     */
2232    if (si->si_pid != 0  /* some systems don't fill this in. */
2233    && !pidismother(si->si_pid)) {
2234       swarnx("%s: received SIGHUP from pid %ld, but only expecting it from "
2235              "mother (pid %ld).  Ignored",
2236              function, (long)si->si_pid, (long)getppid());
2237 
2238       return;
2239    }
2240 
2241    if (sockscf.shmeminfo->configsize == 0) {
2242       swarnx("%s: Strange.  Received a SIGHUP signal, but the size of "
2243              "mother's shmemconfig is zero, which does not make sense.  "
2244              "Ignoring it",
2245              function);
2246       return;
2247    }
2248 
2249    slog(LOG_INFO, "%s: received SIGHUP: reloading config", function);
2250 
2251    socks_lock(sockscf.shmemconfigfd, 0, 0, 0, 1);
2252 
2253 #if 1
2254    shmemconfig = sockd_mmap(NULL,
2255                             sockscf.shmeminfo->configsize,
2256                             /*
2257                              * Need PROT_WRITE also as we may need to adjust
2258                              * the pointer addresses before accessing.
2259                              */
2260                             PROT_READ | PROT_WRITE,
2261                             MAP_PRIVATE,
2262                             sockscf.shmemconfigfd,
2263                             0);
2264 
2265 #else /* just for testing */
2266    shmemconfig = mmap((void *)((uintptr_t)sockscf.shmeminfo->config
2267                                           + sockscf.state.pagesize),
2268                       sockscf.shmeminfo->configsize,
2269                       /*
2270                        * Need PROT_WRITE also as we update
2271                        * the pointer addresses as we go.
2272                        */
2273                       PROT_READ | PROT_WRITE,
2274                       MAP_PRIVATE | MAP_FIXED,
2275                       sockscf.shmemconfigfd,
2276                       0);
2277 #endif /* just for testing. */
2278 
2279    if (shmemconfig  == MAP_FAILED) {
2280       swarn("%s: could not mmap(2) %lu bytes of memory for config reload",
2281             function, (unsigned long)sockscf.shmeminfo->configsize);
2282 
2283       socks_unlock(sockscf.shmemconfigfd, 0, 0);
2284       return;
2285    }
2286 
2287    offset = (uintptr_t)shmemconfig - (uintptr_t)sockscf.shmeminfo->config;
2288 
2289    slog(LOG_DEBUG,
2290         "%s: mmap(2)-ed %lu bytes of memory at offset %p.  "
2291         "Mothers offset is at %p, %ld bytes away",
2292         function,
2293         (unsigned long)sockscf.shmeminfo->configsize,
2294         shmemconfig,
2295         sockscf.shmeminfo->config,
2296         (long)offset);
2297 
2298    /*
2299     * shallow copy what we can.
2300     */
2301 
2302    config = *shmemconfig;
2303 
2304    if (pointer_copy(shmemconfig,  offset, &config, NULL, 0) != 0) {
2305       swarnx("%s: could not update pointers in config-object after reload",
2306              function);
2307 
2308       if (munmap(shmemconfig, sockscf.shmeminfo->configsize) != 0)
2309          swarn("%s: munmap(%p, %lu) failed",
2310                function,
2311                shmemconfig,
2312                (unsigned long)sockscf.shmeminfo->configsize);
2313 
2314       socks_unlock(sockscf.shmemconfigfd, 0, 0);
2315       return;
2316    }
2317 
2318 
2319 #if DIAGNOSTIC
2320    slog(LOG_DEBUG, "%s: updated config, doing compare test ...", function);
2321    i = compareconfigs(shmemconfig, &config);
2322 #endif /* DIAGNOSTIC */
2323 
2324    if (munmap(shmemconfig, sockscf.shmeminfo->configsize) != 0)
2325       swarn("%s: munmap(%p, %lu) failed",
2326             function,
2327             shmemconfig,
2328             (unsigned long)sockscf.shmeminfo->configsize);
2329 
2330 #if DIAGNOSTIC
2331    if (i == 0) {
2332       swarnx("%s: created config not identical to config in shmem", function);
2333       return;
2334    }
2335    else
2336       slog(LOG_DEBUG,
2337            "%s: created config identical to shmem config.  %lu bytes compared",
2338            function, (unsigned long)i);
2339 #endif /* DIAGNOSTIC */
2340 
2341    socks_unlock(sockscf.shmemconfigfd, 0, 0);
2342 
2343    SASSERTX(!pidismainmother(sockscf.state.pid));
2344 
2345    SASSERTX(config.state.type == sockscf.state.type);
2346 
2347    resetconfig(&sockscf, 0); /* reset old before loading new. */
2348 
2349    SASSERTX(config.state.type == sockscf.state.type);
2350 
2351    /*
2352     * needs to be handled specially.
2353     */
2354 
2355    sockd_freelogobject(&sockscf.errlog, 1);
2356    sockd_reopenlogfiles(&config.errlog, 0);
2357 
2358    sockd_freelogobject(&sockscf.log, 1);
2359    sockd_reopenlogfiles(&config.log, 0);
2360 
2361    sockscf = config;
2362 
2363 #if DIAGNOSTIC
2364    /*
2365     * compareconfig() will dereference pointers.  If there's something left
2366     * pointing to the shmem by mistake, things will hopefully crash now.
2367     */
2368    SASSERTX(compareconfigs(&sockscf, &config) != 0);
2369 #endif /* DIAGNOSTIC */
2370 
2371    postconfigloadinit();
2372 
2373    if (pidismother(sockscf.state.pid))
2374       sigchildbroadcast(sig); /* each mother process has its own children. */
2375 
2376    resetprivileges();
2377 
2378    time_monotonic(&sockscf.stat.configload);
2379 
2380    SIGNAL_EPILOGUE(sig, si, errno_s);
2381 }
2382