]> git.donarmstrong.com Git - unscd.git/blob - nscd.c
Merge branch 'upstream'
[unscd.git] / nscd.c
1 /* This file is part of unscd, a complete nscd replacement.
2  * Copyright (C) 2007-2012 Denys Vlasenko. Licensed under the GPL version 2.
3  */
4
5 /* unscd is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; version 2 of the License.
8  *
9  * unscd 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
12  * GNU General Public License for more details.
13  *
14  * You can download the GNU General Public License from the GNU website
15  * at http://www.gnu.org/ or write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
17
18 /*
19 Build instructions:
20
21 gcc -Wall -Wunused-parameter -Os -o nscd nscd.c
22
23 gcc -fomit-frame-pointer -Wl,--sort-section -Wl,alignment -Wl,--sort-common
24       -Os -o nscd nscd.c
25
26 Description:
27
28 nscd problems are not exactly unheard of. Over the years, there were
29 quite a bit of bugs in it. This leads people to invent babysitters
30 which restart crashed/hung nscd. This is ugly.
31
32 After looking at nscd source in glibc I arrived to the conclusion
33 that its design is contributing to this significantly. Even if nscd's
34 code is 100.00% perfect and bug-free, it can still suffer from bugs
35 in libraries it calls.
36
37 As designed, it's a multithreaded program which calls NSS libraries.
38 These libraries are not part of libc, they may be provided
39 by third-party projects (samba, ldap, you name it).
40
41 Thus nscd cannot be sure that libraries it calls do not have memory
42 or file descriptor leaks and other bugs.
43
44 Since nscd is multithreaded program with single shared cache,
45 any resource leak in any NSS library has cumulative effect.
46 Even if a NSS library leaks a file descriptor 0.01% of the time,
47 this will make nscd crash or hang after some time.
48
49 Of course bugs in NSS .so modules should be fixed, but meanwhile
50 I do want nscd which does not crash or lock up.
51
52 So I went ahead and wrote a replacement.
53
54 It is a single-threaded server process which offloads all NSS
55 lookups to worker children (not threads, but fully independent
56 processes). Cache hits are handled by parent. Only cache misses
57 start worker children. This design is immune against
58 resource leaks and hangs in NSS libraries.
59
60 It is also many times smaller.
61
62 Currently (v0.36) it emulates glibc nscd pretty closely
63 (handles same command line flags and config file), and is moderately tested.
64
65 Please note that as of 2008-08 it is not in wide use (yet?).
66 If you have trouble compiling it, see an incompatibility with
67 "standard" one or experience hangs/crashes, please report it to
68 vda.linux@googlemail.com
69
70 ***********************************************************************/
71
72 /* Make struct ucred appear in sys/socket.h */
73 #define _GNU_SOURCE 1
74 /* For all good things */
75 #include <stdio.h>
76 #include <stddef.h>
77 #include <stdlib.h>
78 #include <stdarg.h>
79 #include <unistd.h>
80 #include <string.h>
81 #include <ctype.h>
82 #include <errno.h>
83 #include <fcntl.h>
84 #include <signal.h>
85 #include <time.h>
86 #include <netdb.h>
87 #include <pwd.h>
88 #include <grp.h>
89 #include <getopt.h>
90 #include <syscall.h>
91 #include <sys/socket.h>
92 #include <sys/time.h>
93 #include <sys/types.h>
94 #include <sys/stat.h>
95 #include <sys/poll.h>
96 #include <sys/un.h>
97 /* For INT_MAX */
98 #include <limits.h>
99 /* For inet_ntoa (for debug build only) */
100 #include <arpa/inet.h>
101
102 /*
103  * 0.21 add SEGV reporting to worker
104  * 0.22 don't do freeaddrinfo() in GETAI worker, it's crashy
105  * 0.23 add parameter parsing
106  * 0.24 add conf file parsing, not using results yet
107  * 0.25 used some of conf file settings (not tested)
108  * 0.26 almost all conf file settings are wired up
109  * 0.27 a bit more of almost all conf file settings are wired up
110  * 0.28 optimized cache aging
111  * 0.29 implemented invalidate and shutdown options
112  * 0.30 fixed buglet (sizeof(ptr) != sizeof(array))
113  * 0.31 reduced client_info by one member
114  * 0.32 fix nttl/size defaults; simpler check for worker child in main()
115  * 0.33 tweak includes so that it builds on my new machine (64-bit userspace);
116  *      do not die on unknown service name, just warn
117  *      ("services" is a new service we don't support)
118  * 0.34 create /var/run/nscd/nscd.pid pidfile like glibc nscd 2.8 does;
119  *      delay setuid'ing itself to server-user after log and pidfile are open
120  * 0.35 readlink /proc/self/exe and use result if execing /proc/self/exe fails
121  * 0.36 excercise extreme paranoia handling server-user option;
122  *      a little bit more verbose logging:
123  *      L_DEBUG2 log level added, use debug-level 7 to get it
124  * 0.37 users reported over-zealous "detected change in /etc/passwd",
125  *      apparently stat() returns random garbage in unused padding
126  *      on some systems. Made the check less paranoid.
127  * 0.38 log POLLHUP better
128  * 0.39 log answers to client better, log getpwnam in the worker,
129  *      pass debug level value down to worker.
130  * 0.40   fix handling of shutdown and invalidate requests;
131  *        fix bug with answer written in several pieces
132  * 0.40.1 set hints.ai_socktype = SOCK_STREAM in GETAI request
133  * 0.41   eliminate double caching of two near-simultaneous identical requests -
134  *        EXPERIMENTAL
135  * 0.42   execute /proc/self/exe by link name first (better comm field)
136  * 0.43   fix off-by-one error in setgroups
137  * 0.44   make -d[ddd] bump up debug - easier to explain to users
138  *        how to produce detailed log (no nscd.conf tweaking)
139  * 0.45   Fix out-of-bounds array access and log/pid file permissions -
140  *        thanks to Sebastian Krahmer (krahmer AT suse.de)
141  * 0.46   fix a case when we forgot to remove a future entry on worker failure
142  * 0.47   fix nscd without -d to not bump debug level
143  * 0.48   fix for changes in __nss_disable_nscd API in glibc-2.15
144  * 0.49   minor tweaks to messages
145  */
146 #define PROGRAM_VERSION "0.49"
147
148 #define DEBUG_BUILD 1
149
150
151 /*
152 ** Generic helpers
153 */
154
155 #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
156
157 #define NORETURN __attribute__ ((__noreturn__))
158
159
160 #ifdef MY_CPU_HATES_CHARS
161 typedef int smallint;
162 #else
163 typedef signed char smallint;
164 #endif
165
166
167 enum {
168         L_INFO   = (1 << 0),
169         L_DEBUG  = ((1 << 1) * DEBUG_BUILD),
170         L_DEBUG2 = ((1 << 2) * DEBUG_BUILD),
171         L_DUMP   = ((1 << 3) * DEBUG_BUILD),
172         L_ALL    = 0xf,
173         D_DAEMON = (1 << 6),
174         D_STAMP  = (1 << 5),
175 };
176
177 static smallint debug = D_DAEMON;
178
179 static void verror(const char *s, va_list p, const char *strerr)
180 {
181         char msgbuf[1024];
182         int sz, rem, strerr_len;
183         struct timeval tv;
184
185         sz = 0;
186         if (debug & D_STAMP) {
187                 gettimeofday(&tv, NULL);
188                 sz = sprintf(msgbuf, "%02u:%02u:%02u.%05u ",
189                         (unsigned)((tv.tv_sec / (60*60)) % 24),
190                         (unsigned)((tv.tv_sec / 60) % 60),
191                         (unsigned)(tv.tv_sec % 60),
192                         (unsigned)(tv.tv_usec / 10));
193         }
194         rem = sizeof(msgbuf) - sz;
195         sz += vsnprintf(msgbuf + sz, rem, s, p);
196         rem = sizeof(msgbuf) - sz; /* can be negative after this! */
197
198         if (strerr) {
199                 strerr_len = strlen(strerr);
200                 if (rem >= strerr_len + 4) { /* ": STRERR\n\0" */
201                         msgbuf[sz++] = ':';
202                         msgbuf[sz++] = ' ';
203                         strcpy(msgbuf + sz, strerr);
204                         sz += strerr_len;
205                 }
206         }
207         if (rem >= 2) {
208                 msgbuf[sz++] = '\n';
209                 msgbuf[sz] = '\0';
210         }
211         fflush(NULL);
212         fputs(msgbuf, stderr);
213 }
214
215 static void error(const char *msg, ...)
216 {
217         va_list p;
218         va_start(p, msg);
219         verror(msg, p, NULL);
220         va_end(p);
221 }
222
223 static void error_and_die(const char *msg, ...) NORETURN;
224 static void error_and_die(const char *msg, ...)
225 {
226         va_list p;
227         va_start(p, msg);
228         verror(msg, p, NULL);
229         va_end(p);
230         _exit(1);
231 }
232
233 static void perror_and_die(const char *msg, ...) NORETURN;
234 static void perror_and_die(const char *msg, ...)
235 {
236         va_list p;
237         va_start(p, msg);
238         /* Guard against "<error message>: Success" */
239         verror(msg, p, errno ? strerror(errno) : NULL);
240         va_end(p);
241         _exit(1);
242 }
243
244 static void nscd_log(int mask, const char *msg, ...)
245 {
246         if (debug & mask) {
247                 va_list p;
248                 va_start(p, msg);
249                 verror(msg, p, NULL);
250                 va_end(p);
251         }
252 }
253
254 #define log(lvl, ...) do { if (lvl) nscd_log(lvl, __VA_ARGS__); } while (0)
255
256 #if DEBUG_BUILD
257 static void dump(const void *ptr, int len)
258 {
259         char text[18];
260         const unsigned char *buf;
261         char *p;
262
263         if (!(debug & L_DUMP))
264                 return;
265
266         buf = ptr;
267         while (len > 0) {
268                 int chunk = ((len >= 16) ? 16 : len);
269                 fprintf(stderr,
270                         "%02x %02x %02x %02x %02x %02x %02x %02x "
271                         "%02x %02x %02x %02x %02x %02x %02x %02x " + (16-chunk) * 5,
272                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
273                         buf[8], buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15]
274                 );
275                 fprintf(stderr, "%*s", (16-chunk) * 3, "");
276                 len -= chunk;
277                 p = text;
278                 do {
279                         unsigned char c = *buf++;
280                         *p++ = (c >= 32 && c < 127 ? c : '.');
281                 } while (--chunk);
282                 *p++ = '\n';
283                 *p = '\0';
284                 fputs(text, stderr);
285         }
286 }
287 #else
288 void dump(const void *ptr, int len);
289 #endif
290
291 #define hex_dump(p,n) do { if (L_DUMP) dump(p,n); } while (0)
292
293 static int xopen3(const char *pathname, int flags, int mode)
294 {
295         int fd = open(pathname, flags, mode);
296         if (fd < 0)
297                 perror_and_die("open");
298         return fd;
299 }
300
301 static void xpipe(int *fds)
302 {
303         if (pipe(fds) < 0)
304                 perror_and_die("pipe");
305 }
306
307 static void xexecve(const char *filename, char **argv, char **envp) NORETURN;
308 static void xexecve(const char *filename, char **argv, char **envp)
309 {
310         execve(filename, argv, envp);
311         perror_and_die("cannot re-exec %s", filename);
312 }
313
314 static void ndelay_on(int fd)
315 {
316         int fl = fcntl(fd, F_GETFL);
317         if (fl < 0)
318                 perror_and_die("F_GETFL");
319         if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) < 0)
320                 perror_and_die("setting O_NONBLOCK");
321 }
322
323 static void close_on_exec(int fd)
324 {
325         if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
326                 perror_and_die("setting FD_CLOEXEC");
327 }
328
329 static unsigned monotonic_ms(void)
330 {
331         struct timespec ts;
332         if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts))
333                 perror_and_die("clock_gettime(MONOTONIC)");
334         return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
335 }
336
337 static unsigned strsize(const char *str)
338 {
339         return strlen(str) + 1;
340 }
341
342 static unsigned strsize_aligned4(const char *str)
343 {
344         return (strlen(str) + 1 + 3) & (~3);
345 }
346
347 static ssize_t safe_read(int fd, void *buf, size_t count)
348 {
349         ssize_t n;
350         do {
351                 n = read(fd, buf, count);
352         } while (n < 0 && errno == EINTR);
353         return n;
354 }
355
356 static ssize_t full_read(int fd, void *buf, size_t len)
357 {
358         ssize_t cc;
359         ssize_t total;
360         total = 0;
361         while (len) {
362                 cc = safe_read(fd, buf, len);
363                 if (cc < 0)
364                         return cc;      /* read() returns -1 on failure. */
365                 if (cc == 0)
366                         break;
367                 buf = ((char *)buf) + cc;
368                 total += cc;
369                 len -= cc;
370         }
371         return total;
372 }
373
374 /* unused
375 static void xsafe_read(int fd, void *buf, size_t len)
376 {
377         if (len != safe_read(fd, buf, len))
378                 perror_and_die("short read");
379 }
380 static void xfull_read(int fd, void *buf, size_t len)
381 {
382         if (len != full_read(fd, buf, len))
383                 perror_and_die("short read");
384 }
385 */
386
387 static ssize_t safe_write(int fd, const void *buf, size_t count)
388 {
389         ssize_t n;
390         do {
391                 n = write(fd, buf, count);
392         } while (n < 0 && errno == EINTR);
393         return n;
394 }
395
396 static ssize_t full_write(int fd, const void *buf, size_t len)
397 {
398         ssize_t cc;
399         ssize_t total;
400
401         total = 0;
402         while (len) {
403                 cc = safe_write(fd, buf, len);
404                 if (cc < 0)
405                         return cc;      /* write() returns -1 on failure. */
406                 total += cc;
407                 buf = ((const char *)buf) + cc;
408                 len -= cc;
409         }
410         return total;
411 }
412
413 static void xsafe_write(int fd, const void *buf, size_t count)
414 {
415         if (count != safe_write(fd, buf, count))
416                 perror_and_die("short write of %ld bytes", (long)count);
417 }
418 static void xfull_write(int fd, const void *buf, size_t count)
419 {
420         if (count != full_write(fd, buf, count))
421                 perror_and_die("short write of %ld bytes", (long)count);
422 }
423
424 static void xmovefd(int from_fd, int to_fd)
425 {
426         if (from_fd != to_fd) {
427                 if (dup2(from_fd, to_fd) < 0)
428                         perror_and_die("dup2");
429                 close(from_fd);
430         }
431 }
432
433 static unsigned getnum(const char *str)
434 {
435         if (str[0] >= '0' && str[0] <= '9') {
436                 char *p;
437                 unsigned long l = strtoul(str, &p, 10);
438                 /* must not overflow int even after x1000 */
439                 if (!*p && l <= INT_MAX / 1000)
440                         return l;
441         }
442         error_and_die("malformed or too big number '%s'", str);
443 };
444
445 static char *skip_whitespace(const char *s)
446 {
447         /* NB: isspace('\0') returns 0 */
448         while (isspace(*s)) ++s;
449         return (char *) s;
450 }
451
452 static char *skip_non_whitespace(const char *s)
453 {
454         while (*s && !isspace(*s)) ++s;
455         return (char *) s;
456 }
457
458 static void *xmalloc(unsigned sz)
459 {
460         void *p = malloc(sz);
461         if (!p)
462                 error_and_die("out of memory");
463         return p;
464 }
465
466 static void *xzalloc(unsigned sz)
467 {
468         void *p = xmalloc(sz);
469         memset(p, 0, sz);
470         return p;
471 }
472
473 static void *xrealloc(void *p, unsigned size)
474 {
475         p = realloc(p, size);
476         if (!p)
477                 error_and_die("out of memory");
478         return p;
479 }
480
481 static const char *xstrdup(const char *str)
482 {
483         const char *p = strdup(str);
484         if (!p)
485                 error_and_die("out of memory");
486         return p;
487 }
488
489
490 /*
491 ** Config data
492 */
493
494 enum {
495         SRV_PASSWD,
496         SRV_GROUP,
497         SRV_HOSTS,
498 };
499
500 static const char srv_name[3][7] = {
501         "passwd",
502         "group",
503         "hosts"
504 };
505
506 static struct {
507         const char *logfile;
508         const char *user;
509         smallint srv_enable[3];
510         smallint check_files[3];
511         unsigned pttl[3];
512         unsigned nttl[3];
513         unsigned size[3];
514 } config = {
515         /* We try to closely mimic glibc nscd */
516         .logfile     = NULL, /* default is to not have a log file */
517         .user        = NULL,
518         .srv_enable  = { 0, 0, 0 },
519         .check_files = { 1, 1, 1 },
520         .pttl        = { 3600, 3600, 3600 },
521         .nttl        = { 20, 60, 20 },
522         /* huh, what is the default cache size in glibc nscd? */
523         .size        = { 256 * 8 / 3, 256 * 8 / 3, 256 * 8 / 3 },
524 };
525
526 static const char default_conffile[] = "/etc/nscd.conf";
527 static const char *self_exe_points_to = "/proc/self/exe";
528
529
530 /*
531 ** Clients, workers machinery
532 */
533
534 /* Header common to all requests */
535 #define USER_REQ_STRUCT \
536         uint32_t version; /* Version number of the daemon interface */ \
537         uint32_t type;    /* Service requested */ \
538         uint32_t key_len; /* Key length */
539
540 typedef struct user_req_header {
541         USER_REQ_STRUCT
542 } user_req_header;
543
544 enum {
545         NSCD_VERSION = 2,
546         MAX_USER_REQ_SIZE = 1024,
547         USER_HDR_SIZE = sizeof(user_req_header),
548         /* DNS queries time out after 20 seconds,
549          * we will allow for a bit more */
550         WORKER_TIMEOUT_SEC = 30,
551         CLIENT_TIMEOUT_MS = 100,
552         SMALL_POLL_TIMEOUT_MS = 200,
553 };
554
555 typedef struct user_req {
556         union {
557                 struct { /* as came from client */
558                         USER_REQ_STRUCT
559                 };
560                 struct { /* when stored in cache, overlaps .version */
561                         unsigned refcount:8;
562                         /* (timestamp24 * 256) == timestamp in ms */
563                         unsigned timestamp24:24;
564                 };
565         };
566         char reqbuf[MAX_USER_REQ_SIZE - USER_HDR_SIZE];
567 } user_req;
568
569 /* Compile-time check for correct size */
570 struct BUG_wrong_user_req_size {
571         char BUG_wrong_user_req_size[sizeof(user_req) == MAX_USER_REQ_SIZE ? 1 : -1];
572 };
573
574 enum {
575         GETPWBYNAME,
576         GETPWBYUID,
577         GETGRBYNAME,
578         GETGRBYGID,
579         GETHOSTBYNAME,
580         GETHOSTBYNAMEv6,
581         GETHOSTBYADDR,
582         GETHOSTBYADDRv6,
583         SHUTDOWN,               /* Shut the server down */
584         GETSTAT,                /* Get the server statistic */
585         INVALIDATE,             /* Invalidate one special cache */
586         GETFDPW,
587         GETFDGR,
588         GETFDHST,
589         GETAI,
590         INITGROUPS,
591         GETSERVBYNAME,
592         GETSERVBYPORT,
593         GETFDSERV,
594         LASTREQ
595 };
596 #if DEBUG_BUILD
597 static const char *const typestr[] = {
598         "GETPWBYNAME",     /* done */
599         "GETPWBYUID",      /* done */
600         "GETGRBYNAME",     /* done */
601         "GETGRBYGID",      /* done */
602         "GETHOSTBYNAME",   /* done */
603         "GETHOSTBYNAMEv6", /* done */
604         "GETHOSTBYADDR",   /* done */
605         "GETHOSTBYADDRv6", /* done */
606         "SHUTDOWN",        /* done */
607         "GETSTAT",         /* info? */
608         "INVALIDATE",      /* done */
609         /* won't do: nscd passes a name of shmem segment
610          * which client can map and "see" the db */
611         "GETFDPW",
612         "GETFDGR",         /* won't do */
613         "GETFDHST",        /* won't do */
614         "GETAI",           /* done */
615         "INITGROUPS",      /* done */
616         "GETSERVBYNAME",   /* prio 3 (no caching?) */
617         "GETSERVBYPORT",   /* prio 3 (no caching?) */
618         "GETFDSERV"        /* won't do */
619 };
620 #else
621 extern const char *const typestr[];
622 #endif
623 static const smallint type_to_srv[] = {
624         [GETPWBYNAME     ] = SRV_PASSWD,
625         [GETPWBYUID      ] = SRV_PASSWD,
626         [GETGRBYNAME     ] = SRV_GROUP,
627         [GETGRBYGID      ] = SRV_GROUP,
628         [GETHOSTBYNAME   ] = SRV_HOSTS,
629         [GETHOSTBYNAMEv6 ] = SRV_HOSTS,
630         [GETHOSTBYADDR   ] = SRV_HOSTS,
631         [GETHOSTBYADDRv6 ] = SRV_HOSTS,
632         [GETAI           ] = SRV_HOSTS,
633         [INITGROUPS      ] = SRV_GROUP,
634 };
635
636 static int unsupported_ureq_type(unsigned type)
637 {
638         if (type == GETAI) return 0;
639         if (type == INITGROUPS) return 0;
640         if (type == GETSTAT) return 1;
641         if (type > INVALIDATE) return 1;
642         return 0;
643 }
644
645
646 typedef struct client_info {
647         /* if client_fd != 0, we are waiting for the reply from worker
648          * on pfd[i].fd, and client_fd is saved client's fd
649          * (we need to put it back into pfd[i].fd later) */
650         int client_fd;
651         unsigned bytecnt;       /* bytes read from client */
652         unsigned bufidx;        /* buffer# in global client_buf[] */
653         unsigned started_ms;
654         unsigned respos;        /* response */
655         user_req *resptr;       /* response */
656         user_req **cache_pp;    /* cache entry address */
657         user_req *ureq;         /* request (points to client_buf[x]) */
658 } client_info;
659
660 static unsigned g_now_ms;
661 static int min_closed = INT_MAX;
662 static int cnt_closed = 0;
663 static int num_clients = 2; /* two listening sockets are "clients" too */
664
665 /* We read up to max_reqnum requests in parallel */
666 static unsigned max_reqnum = 14;
667 static int next_buf;
668 static char          (*client_buf)[MAX_USER_REQ_SIZE];
669 static char          *busy_cbuf;
670 static struct pollfd *pfd;
671 static client_info   *cinfo;
672
673 /* Request, response and cache data structures:
674  *
675  * cache[] (defined later):
676  * cacheline_t cache[cache_size] array, or in other words,
677  * user_req* cache[cache_size][8] array.
678  * Every client request is hashed, hash value determines which cache[x]
679  * will have the response stored in one of its 8 elements.
680  * Cache entries have this format: request, then padding to 32 bits,
681  * then the response.
682  * Addresses in cache[x][y] may be NULL or:
683  * (&client_buf[z]) & 1: the cache miss is in progress ("future entry"):
684  * "the data is not in the cache (yet), wait for it to appear"
685  * (&client_buf[z]) & 3: the cache miss is in progress and other clients
686  * also want the same data ("shared future entry")
687  * else (non-NULL but low two bits are 0): cached data in malloc'ed block
688  *
689  * Each of these is a [max_reqnum] sized array:
690  * pfd[i] - given to poll() to wait for requests and replies.
691  *      .fd: first two pfd[i]: listening Unix domain sockets, else
692  *      .fd: open fd to a client, for reading client's request, or
693  *      .fd: open fd to a worker, to send request and get response back
694  * cinfo[i] - auxiliary client data for pfd[i]
695  *      .client_fd: open fd to a client, in case we already had read its
696  *          request and got a cache miss, and created a worker or
697  *          wait for another client's worker.
698  *          Otherwise, it's 0 and client's fd is in pfd[i].fd
699  *      .bufidx: index in client_buf[] we store client's request in
700  *      .bytecnt: size of the request
701  *      .started_ms: used to time out unresponsive clients
702  *      .respos:
703  *      .resptr:
704  *      .cache_pp: &cache[x][y] where the response is, or will be stored.
705  *      .ureq:
706  * When a client has received its reply (or otherwise closed (timeout etc)),
707  * corresponding pfd[i] and cinfo[i] are removed by shifting [i+1], [i+2] etc
708  * elements down, so that both arrays never have free holes.
709  * [num_clients] is always the first free element.
710  *
711  * Each of these also is a [max_reqnum] sized array, but indexes
712  * do not correspond directly to pfd[i] and cinfo[i]:
713  * client_buf[n][MAX_USER_REQ_SIZE] - buffers we read client requests into
714  * busy_cbuf[n] - bool flags marking busy client_buf[]
715  */
716 /* Possible reductions:
717  * fd, bufidx - uint8_t
718  * started_ms -> uint16_t started_s
719  * ureq - eliminate (derivable from bufidx?)
720  */
721
722 /* Are special bits 0? is it a true cached entry? */
723 #define CACHED_ENTRY(p)     ( ((long)(p) & 3) == 0 )
724 /* Are special bits 11? is it a shared future cache entry? */
725 #define CACHE_SHARED(p)     ( ((long)(p) & 3) == 3 )
726 /* Return a ptr with special bits cleared (used for accessing data) */
727 #define CACHE_PTR(p)        ( (void*) ((long)(p) & ~(long)3) )
728 /* Return a ptr with special bits set to x1: make future cache entry ptr */
729 #define MAKE_FUTURE_PTR(p)  ( (void*) ((long)(p) | 1) )
730 /* Modify ptr, set special bits to 11: shared future cache entry */
731 #define MARK_PTR_SHARED(pp) ( *(long*)(pp) |= 3 )
732
733 static inline unsigned ureq_size(const user_req *ureq)
734 {
735         return sizeof(user_req_header) + ureq->key_len;
736 }
737
738 static unsigned cache_age(const user_req *ureq)
739 {
740         if (!CACHED_ENTRY(ureq))
741                 return 0;
742         return (uint32_t) (g_now_ms - (ureq->timestamp24 << 8));
743 }
744
745 static void set_cache_timestamp(user_req *ureq)
746 {
747         ureq->timestamp24 = g_now_ms >> 8;
748 }
749
750 static int alloc_buf_no(void)
751 {
752         int n = next_buf;
753         do {
754                 int cur = next_buf;
755                 next_buf = (next_buf + 1) % max_reqnum;
756                 if (!busy_cbuf[cur]) {
757                         busy_cbuf[cur] = 1;
758                         return cur;
759                 }
760         } while (next_buf != n);
761         error_and_die("no free bufs?!");
762 }
763
764 static inline void *bufno2buf(int i)
765 {
766         return client_buf[i];
767 }
768
769 static void close_client(unsigned i)
770 {
771         log(L_DEBUG, "closing client %u (fd %u,%u)", i, pfd[i].fd, cinfo[i].client_fd);
772         /* Paranoia. We had nasty bugs where client was closed twice. */
773         if (pfd[i].fd == 0) ////
774                 return;
775         close(pfd[i].fd);
776         if (cinfo[i].client_fd && cinfo[i].client_fd != pfd[i].fd)
777                 close(cinfo[i].client_fd);
778         pfd[i].fd = 0; /* flag as unused (coalescing needs this) */
779         busy_cbuf[cinfo[i].bufidx] = 0;
780         cnt_closed++;
781         if (i < min_closed)
782                 min_closed = i;
783 }
784
785
786 /*
787 ** nscd API <-> C API conversion
788 */
789
790 typedef struct response_header {
791         uint32_t version_or_size;
792         int32_t found;
793         char body[0];
794 } response_header;
795
796 typedef struct initgr_response_header {
797         uint32_t version_or_size;
798         int32_t found;
799         int32_t ngrps;
800         /* code assumes gid_t == int32, let's check that */
801         int32_t gid[sizeof(gid_t) == sizeof(int32_t) ? 0 : -1];
802         /* char user_str[as_needed]; */
803 } initgr_response_header;
804
805 static initgr_response_header *obtain_initgroups(const char *username)
806 {
807         struct initgr_response_header *resp;
808         struct passwd *pw;
809         enum { MAGIC_OFFSET = sizeof(*resp) / sizeof(int32_t) };
810         unsigned sz;
811         int ngroups;
812
813         pw = getpwnam(username);
814         if (!pw) {
815                 resp = xzalloc(8);
816                 resp->version_or_size = sizeof(*resp);
817                 /*resp->found = 0;*/
818                 /*resp->ngrps = 0;*/
819                 goto ret;
820         }
821
822         /* getgrouplist may be very expensive, it's much better to allocate
823          * a bit more than to run getgrouplist twice */
824         ngroups = 128;
825         resp = NULL;
826         do {
827                 sz = sizeof(*resp) + sizeof(resp->gid[0]) * ngroups;
828                 resp = xrealloc(resp, sz);
829         } while (getgrouplist(username, pw->pw_gid, (gid_t*) &resp->gid, &ngroups) == -1);
830         log(L_DEBUG, "ngroups=%d", ngroups);
831
832         sz = sizeof(*resp) + sizeof(resp->gid[0]) * ngroups;
833         /* resp = xrealloc(resp, sz); - why bother */
834         resp->version_or_size = sz;
835         resp->found = 1;
836         resp->ngrps = ngroups;
837  ret:
838         return resp;
839 }
840
841 typedef struct pw_response_header {
842         uint32_t version_or_size;
843         int32_t found;
844         int32_t pw_name_len;
845         int32_t pw_passwd_len;
846         int32_t pw_uid;
847         int32_t pw_gid;
848         int32_t pw_gecos_len;
849         int32_t pw_dir_len;
850         int32_t pw_shell_len;
851         /* char pw_name[pw_name_len]; */
852         /* char pw_passwd[pw_passwd_len]; */
853         /* char pw_gecos[pw_gecos_len]; */
854         /* char pw_dir[pw_dir_len]; */
855         /* char pw_shell[pw_shell_len]; */
856 } pw_response_header;
857
858 static pw_response_header *marshal_passwd(struct passwd *pw)
859 {
860         char *p;
861         pw_response_header *resp;
862         unsigned pw_name_len;
863         unsigned pw_passwd_len;
864         unsigned pw_gecos_len;
865         unsigned pw_dir_len;
866         unsigned pw_shell_len;
867         unsigned sz = sizeof(*resp);
868         if (pw) {
869                 sz += (pw_name_len = strsize(pw->pw_name));
870                 sz += (pw_passwd_len = strsize(pw->pw_passwd));
871                 sz += (pw_gecos_len = strsize(pw->pw_gecos));
872                 sz += (pw_dir_len = strsize(pw->pw_dir));
873                 sz += (pw_shell_len = strsize(pw->pw_shell));
874         }
875         resp = xzalloc(sz);
876         resp->version_or_size = sz;
877         if (!pw) {
878                 /*resp->found = 0;*/
879                 goto ret;
880         }
881         resp->found = 1;
882         resp->pw_name_len = pw_name_len;
883         resp->pw_passwd_len = pw_passwd_len;
884         resp->pw_uid = pw->pw_uid;
885         resp->pw_gid = pw->pw_gid;
886         resp->pw_gecos_len = pw_gecos_len;
887         resp->pw_dir_len = pw_dir_len;
888         resp->pw_shell_len = pw_shell_len;
889         p = (char*)(resp + 1);
890         strcpy(p, pw->pw_name); p += pw_name_len;
891         strcpy(p, pw->pw_passwd); p += pw_passwd_len;
892         strcpy(p, pw->pw_gecos); p += pw_gecos_len;
893         strcpy(p, pw->pw_dir); p += pw_dir_len;
894         strcpy(p, pw->pw_shell); p += pw_shell_len;
895         log(L_DEBUG, "sz:%u realsz:%u", sz, p - (char*)resp);
896  ret:
897         return resp;
898 }
899
900 typedef struct gr_response_header {
901         uint32_t version_or_size;
902         int32_t found;
903         int32_t gr_name_len;    /* strlen(gr->gr_name) + 1; */
904         int32_t gr_passwd_len;  /* strlen(gr->gr_passwd) + 1; */
905         int32_t gr_gid;         /* gr->gr_gid */
906         int32_t gr_mem_cnt;     /* while (gr->gr_mem[gr_mem_cnt]) ++gr_mem_cnt; */
907         /* int32_t gr_mem_len[gr_mem_cnt]; */
908         /* char gr_name[gr_name_len]; */
909         /* char gr_passwd[gr_passwd_len]; */
910         /* char gr_mem[gr_mem_cnt][gr_mem_len[i]]; */
911         /* char gr_gid_str[as_needed]; - huh? */
912         /* char orig_key[as_needed]; - needed?? I don't do this ATM... */
913 /*
914  glibc adds gr_gid_str, but client doesn't get/use it:
915  writev(3, [{"\2\0\0\0\2\0\0\0\5\0\0\0", 12}, {"root\0", 5}], 2) = 17
916  poll([{fd=3, events=POLLIN|POLLERR|POLLHUP, revents=POLLIN}], 1, 5000) = 1
917  read(3, "\2\0\0\0\1\0\0\0\10\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0", 24) = 24
918  readv(3, [{"", 0}, {"root\0\0\0\0\0\0\0\0", 12}], 2) = 12
919  read(3, NULL, 0)        = 0
920 */
921 } gr_response_header;
922
923 static gr_response_header *marshal_group(struct group *gr)
924 {
925         char *p;
926         gr_response_header *resp;
927         unsigned gr_mem_cnt;
928         unsigned sz = sizeof(*resp);
929         if (gr) {
930                 sz += strsize(gr->gr_name);
931                 sz += strsize(gr->gr_passwd);
932                 gr_mem_cnt = 0;
933                 while (gr->gr_mem[gr_mem_cnt]) {
934                         sz += strsize(gr->gr_mem[gr_mem_cnt]);
935                         gr_mem_cnt++;
936                 }
937                 /* for int32_t gr_mem_len[gr_mem_cnt]; */
938                 sz += gr_mem_cnt * sizeof(int32_t);
939         }
940         resp = xzalloc(sz);
941         resp->version_or_size = sz;
942         if (!gr) {
943                 /*resp->found = 0;*/
944                 goto ret;
945         }
946         resp->found = 1;
947         resp->gr_name_len = strsize(gr->gr_name);
948         resp->gr_passwd_len = strsize(gr->gr_passwd);
949         resp->gr_gid = gr->gr_gid;
950         resp->gr_mem_cnt = gr_mem_cnt;
951         p = (char*)(resp + 1);
952 /* int32_t gr_mem_len[gr_mem_cnt]; */
953         gr_mem_cnt = 0;
954         while (gr->gr_mem[gr_mem_cnt]) {
955                 *(uint32_t*)p = strsize(gr->gr_mem[gr_mem_cnt]);
956                 p += 4;
957                 gr_mem_cnt++;
958         }
959 /* char gr_name[gr_name_len]; */
960         strcpy(p, gr->gr_name);
961         p += strsize(gr->gr_name);
962 /* char gr_passwd[gr_passwd_len]; */
963         strcpy(p, gr->gr_passwd);
964         p += strsize(gr->gr_passwd);
965 /* char gr_mem[gr_mem_cnt][gr_mem_len[i]]; */
966         gr_mem_cnt = 0;
967         while (gr->gr_mem[gr_mem_cnt]) {
968                 strcpy(p, gr->gr_mem[gr_mem_cnt]);
969                 p += strsize(gr->gr_mem[gr_mem_cnt]);
970                 gr_mem_cnt++;
971         }
972         log(L_DEBUG, "sz:%u realsz:%u", sz, p - (char*)resp);
973  ret:
974         return resp;
975 }
976
977 typedef struct hst_response_header {
978         uint32_t version_or_size;
979         int32_t found;
980         int32_t h_name_len;
981         int32_t h_aliases_cnt;
982         int32_t h_addrtype;     /* AF_INET or AF_INET6 */
983         int32_t h_length;       /* 4 or 16 */
984         int32_t h_addr_list_cnt;
985         int32_t error;
986         /* char h_name[h_name_len]; - we pad it to 4 bytes */
987         /* uint32_t h_aliases_len[h_aliases_cnt]; */
988         /* char h_addr_list[h_addr_list_cnt][h_length]; - every one is the same size [h_length] (4 or 16) */
989         /* char h_aliases[h_aliases_cnt][h_aliases_len[i]]; */
990 } hst_response_header;
991
992 static hst_response_header *marshal_hostent(struct hostent *h)
993 {
994         char *p;
995         hst_response_header *resp;
996         unsigned h_name_len;
997         unsigned h_aliases_cnt;
998         unsigned h_addr_list_cnt;
999         unsigned sz = sizeof(*resp);
1000         if (h) {
1001 /* char h_name[h_name_len] */
1002                 sz += h_name_len = strsize_aligned4(h->h_name);
1003                 h_addr_list_cnt = 0;
1004                 while (h->h_addr_list[h_addr_list_cnt]) {
1005                         h_addr_list_cnt++;
1006                 }
1007 /* char h_addr_list[h_addr_list_cnt][h_length] */
1008                 sz += h_addr_list_cnt * h->h_length;
1009                 h_aliases_cnt = 0;
1010                 while (h->h_aliases[h_aliases_cnt]) {
1011 /* char h_aliases[h_aliases_cnt][h_aliases_len[i]] */
1012                         sz += strsize(h->h_aliases[h_aliases_cnt]);
1013                         h_aliases_cnt++;
1014                 }
1015 /* uint32_t h_aliases_len[h_aliases_cnt] */
1016                 sz += h_aliases_cnt * 4;
1017         }
1018         resp = xzalloc(sz);
1019         resp->version_or_size = sz;
1020         if (!h) {
1021                 /*resp->found = 0;*/
1022                 resp->error = HOST_NOT_FOUND;
1023                 goto ret;
1024         }
1025         resp->found = 1;
1026         resp->h_name_len = h_name_len;
1027         resp->h_aliases_cnt = h_aliases_cnt;
1028         resp->h_addrtype = h->h_addrtype;
1029         resp->h_length = h->h_length;
1030         resp->h_addr_list_cnt = h_addr_list_cnt;
1031         /*resp->error = 0;*/
1032         p = (char*)(resp + 1);
1033 /* char h_name[h_name_len]; */
1034         strcpy(p, h->h_name);
1035         p += h_name_len;
1036 /* uint32_t h_aliases_len[h_aliases_cnt]; */
1037         h_aliases_cnt = 0;
1038         while (h->h_aliases[h_aliases_cnt]) {
1039                 *(uint32_t*)p = strsize(h->h_aliases[h_aliases_cnt]);
1040                 p += 4;
1041                 h_aliases_cnt++;
1042         }
1043 /* char h_addr_list[h_addr_list_cnt][h_length]; */
1044         h_addr_list_cnt = 0;
1045         while (h->h_addr_list[h_addr_list_cnt]) {
1046                 memcpy(p, h->h_addr_list[h_addr_list_cnt], h->h_length);
1047                 p += h->h_length;
1048                 h_addr_list_cnt++;
1049         }
1050 /* char h_aliases[h_aliases_cnt][h_aliases_len[i]]; */
1051         h_aliases_cnt = 0;
1052         while (h->h_aliases[h_aliases_cnt]) {
1053                 strcpy(p, h->h_aliases[h_aliases_cnt]);
1054                 p += strsize(h->h_aliases[h_aliases_cnt]);
1055                 h_aliases_cnt++;
1056         }
1057         log(L_DEBUG, "sz:%u realsz:%u", sz, p - (char*)resp);
1058  ret:
1059         return resp;
1060 }
1061
1062 /* Reply to addrinfo query */
1063 typedef struct ai_response_header {
1064         uint32_t version_or_size;
1065         int32_t found;
1066         int32_t naddrs;
1067         int32_t addrslen;
1068         int32_t canonlen;
1069         int32_t error;
1070         /* char ai_addr[naddrs][4 or 16]; - addrslen bytes in total */
1071         /* char ai_family[naddrs]; - AF_INET[6] each (determines ai_addr[i] length) */
1072         /* char ai_canonname[canonlen]; */
1073 } ai_response_header;
1074
1075 static ai_response_header *obtain_addrinfo(const char *hostname)
1076 {
1077         struct addrinfo hints;
1078         struct addrinfo *ai;
1079         struct addrinfo *ap;
1080         ai_response_header *resp;
1081         char *p, *family;
1082         int err;
1083         unsigned sz;
1084         unsigned naddrs = 0;
1085         unsigned addrslen = 0;
1086         unsigned canonlen = 0;
1087
1088         memset(&hints, 0, sizeof(hints));
1089         hints.ai_flags = AI_CANONNAME;
1090         /* kills dups (one for each possible SOCK_xxx) */
1091         /* this matches glibc behavior */
1092         hints.ai_socktype = SOCK_STREAM;
1093         ai = NULL; /* on failure getaddrinfo may leave it as-is */
1094         err = getaddrinfo(hostname, NULL, &hints, &ai);
1095
1096         sz = sizeof(*resp);
1097         if (!err) {
1098                 if (ai->ai_canonname)
1099                         sz += canonlen = strsize(ai->ai_canonname);
1100                 ap = ai;
1101                 do {
1102                         naddrs++;
1103                         addrslen += (ap->ai_family == AF_INET ? 4 : 16);
1104                         ap = ap->ai_next;
1105                 } while (ap);
1106                 sz += naddrs + addrslen;
1107         }
1108         resp = xzalloc(sz);
1109         resp->version_or_size = sz;
1110         resp->error = err;
1111         if (err) {
1112                 /*resp->found = 0;*/
1113                 goto ret;
1114         }
1115         resp->found = 1;
1116         resp->naddrs = naddrs;
1117         resp->addrslen = addrslen;
1118         resp->canonlen = canonlen;
1119         p = (char*)(resp + 1);
1120         family = p + addrslen;
1121         ap = ai;
1122         do {
1123 /* char ai_family[naddrs]; */
1124                 *family++ = ap->ai_family;
1125 /* char ai_addr[naddrs][4 or 16]; */
1126                 if (ap->ai_family == AF_INET) {
1127                         memcpy(p, &(((struct sockaddr_in*)(ap->ai_addr))->sin_addr), 4);
1128                         p += 4;
1129                 } else {
1130                         memcpy(p, &(((struct sockaddr_in6*)(ap->ai_addr))->sin6_addr), 16);
1131                         p += 16;
1132                 }
1133                 ap = ap->ai_next;
1134         } while (ap);
1135 /* char ai_canonname[canonlen]; */
1136         if (ai->ai_canonname)
1137                 strcpy(family, ai->ai_canonname);
1138         log(L_DEBUG, "sz:%u realsz:%u", sz, family + strsize(ai->ai_canonname) - (char*)resp);
1139  ret:
1140         /* glibc 2.3.6 segfaults here sometimes
1141          * (maybe my mistake, fixed by "ai = NULL;" above).
1142          * Since we are in worker and are going to exit anyway, why bother? */
1143         /*freeaddrinfo(ai);*/
1144         return resp;
1145 }
1146
1147
1148 /*
1149 ** Cache management
1150 */
1151
1152 /* one 8-element "cacheline" */
1153 typedef user_req *cacheline_t[8];
1154 static unsigned cache_size;
1155 /* Points to cacheline_t  cache[cache_size] array, or in other words,
1156  * points to user_req*    cache[cache_size][8] array */
1157 static cacheline_t *cache;
1158 static unsigned cached_cnt;
1159 static unsigned cache_access_cnt = 1; /* prevent division by zero */
1160 static unsigned cache_hit_cnt = 1;
1161 static unsigned last_age_time;
1162 static unsigned aging_interval_ms;
1163 static unsigned min_aging_interval_ms;
1164
1165 static response_header *ureq_response(user_req *ureq)
1166 {
1167         /* Skip query part, find answer part
1168          * (answer is 32-bit aligned) */
1169         return (void*) ((char*)ureq + ((ureq_size(ureq) + 3) & ~3));
1170 }
1171
1172 /* This hash is supposed to be good for short textual data */
1173 static uint32_t bernstein_hash(void *p, unsigned sz, uint32_t hash)
1174 {
1175         uint8_t *key = p;
1176         do {
1177                 hash = (32 * hash + hash) ^ *key++;
1178         } while (--sz);
1179         return hash;
1180 }
1181
1182 static void free_refcounted_ureq(user_req **ureqp)
1183 {
1184         user_req *ureq = *ureqp;
1185
1186         if (!CACHED_ENTRY(ureq))
1187                 return;
1188
1189         if (ureq->refcount) {
1190                 ureq->refcount--;
1191         } else {
1192                 log(L_DEBUG2, "refcount == 0, free(%p)", ureq);
1193                 free(ureq);
1194         }
1195         *ureqp = NULL;
1196 }
1197
1198 static user_req **lookup_in_cache(user_req *ureq)
1199 {
1200         user_req **cacheline;
1201         int free_cache;
1202         unsigned hash;
1203         unsigned i;
1204         unsigned ureq_sz = ureq_size(ureq);
1205
1206         /* prevent overflow and division by zero */
1207         cache_access_cnt++;
1208         if ((int)cache_access_cnt < 0) {
1209                 cache_access_cnt = (cache_access_cnt >> 1) + 1;
1210                 cache_hit_cnt = (cache_hit_cnt >> 1) + 1;
1211         }
1212
1213         hash = bernstein_hash(&ureq->key_len, ureq_sz - offsetof(user_req, key_len), ureq->type);
1214         log(L_DEBUG2, "hash:%08x", hash);
1215         hash = hash % cache_size;
1216         cacheline = cache[hash];
1217
1218         free_cache = -1;
1219         for (i = 0; i < 8; i++) {
1220                 user_req *cached = CACHE_PTR(cacheline[i]);
1221                 if (!cached) {
1222                         if (free_cache == -1)
1223                                 free_cache = i;
1224                         continue;
1225                 }
1226                 /* ureq->version is always 2 and is reused in cache
1227                  * for other purposes, we need to skip it here */
1228                 if (memcmp(&ureq->type, &cached->type, ureq_sz - offsetof(user_req, type)) == 0) {
1229                         log(L_DEBUG, "found in cache[%u][%u]", hash, i);
1230                         cache_hit_cnt++;
1231                         return &cacheline[i];
1232                 }
1233         }
1234
1235         if (free_cache >= 0) {
1236                 cached_cnt++;
1237                 i = free_cache;
1238                 log(L_DEBUG, "not found, using free cache[%u][%u]", hash, i);
1239                 goto ret;
1240         }
1241
1242         unsigned oldest_idx = 0;
1243         unsigned oldest_age = 0;
1244         for (i = 0; i < 8; i++) {
1245                 unsigned age = cache_age(cacheline[i]);
1246                 if (age > oldest_age) {
1247                         oldest_age = age;
1248                         oldest_idx = i;
1249                 }
1250         }
1251         if (oldest_age == 0) {
1252                 /* All entries in cacheline are "future" entries!
1253                  * This is very unlikely, but we must still work correctly.
1254                  * We call this "fake cache entry".
1255                  * The data will be "cached" only for the duration
1256                  * of this client's request lifetime.
1257                  */
1258                 log(L_DEBUG, "not found, and cache[%u] is full: using fake cache entry", hash);
1259                 return NULL;
1260         }
1261         i = oldest_idx;
1262         log(L_DEBUG, "not found, freeing and reusing cache[%u][%u] (age %u)", hash, i, oldest_age);
1263         free_refcounted_ureq(&cacheline[i]);
1264
1265  ret:
1266         cacheline[i] = MAKE_FUTURE_PTR(ureq);
1267         return &cacheline[i];
1268 }
1269
1270 static void age_cache(unsigned free_all, int srv)
1271 {
1272         user_req **cp = *cache;
1273         int i;
1274         unsigned sv = cached_cnt;
1275
1276         log(L_DEBUG, "aging cache, srv:%d, free_all:%u", srv, free_all);
1277         if (srv == -1 || free_all)
1278                 aging_interval_ms = INT_MAX;
1279         i = cache_size * 8;
1280         do {
1281                 user_req *cached = *cp;
1282                 if (CACHED_ENTRY(cached) && cached != NULL) {
1283                         int csrv = type_to_srv[cached->type];
1284                         if (srv == -1 || srv == csrv) {
1285                                 if (free_all) {
1286                                         cached_cnt--;
1287                                         free_refcounted_ureq(cp);
1288                                 } else {
1289                                         unsigned age = cache_age(cached);
1290                                         response_header *resp = ureq_response(cached);
1291                                         unsigned ttl = (resp->found ? config.pttl : config.nttl)[csrv];
1292                                         if (age >= ttl) {
1293                                                 log(L_DEBUG2, "freeing: age %u positive %d ttl %u", age, resp->found, ttl);
1294                                                 cached_cnt--;
1295                                                 free_refcounted_ureq(cp);
1296                                         } else if (srv == -1) {
1297                                                 ttl -= age;
1298                                                 if (aging_interval_ms > ttl)
1299                                                         aging_interval_ms = ttl;
1300                                         }
1301                                 }
1302                         }
1303                 }
1304                 cp++;
1305         } while (--i);
1306         log(L_INFO, "aged cache, freed:%u, remain:%u", sv - cached_cnt, cached_cnt);
1307         log(L_DEBUG2, "aging interval now %u ms", aging_interval_ms);
1308 }
1309
1310
1311 /*
1312 ** Worker child
1313 */
1314
1315 /* Spawns a worker and feeds it with user query on stdin */
1316 /* Returns stdout fd of the worker, in blocking mode */
1317 static int create_and_feed_worker(user_req *ureq)
1318 {
1319         pid_t pid;
1320         struct {
1321                 int rd;
1322                 int wr;
1323         } to_child, to_parent;
1324
1325         /* NB: these pipe fds are in blocking mode and non-CLOEXECed */
1326         xpipe(&to_child.rd);
1327         xpipe(&to_parent.rd);
1328
1329         pid = vfork();
1330         if (pid < 0) /* error */
1331                 perror_and_die("vfork");
1332         if (!pid) { /* child */
1333                 char param[sizeof(int)*3 + 2];
1334                 char *argv[3];
1335
1336                 close(to_child.wr);
1337                 close(to_parent.rd);
1338                 xmovefd(to_child.rd, 0);
1339                 xmovefd(to_parent.wr, 1);
1340                 sprintf(param, "%u", debug);
1341                 argv[0] = (char*) "worker_nscd";
1342                 argv[1] = param;
1343                 argv[2] = NULL;
1344                 /* Re-exec ourself, cleaning up all allocated memory.
1345                  * fds in parent are marked CLOEXEC and will be closed too
1346                  * (modulo bugs) */
1347                 /* Try link name first: it's better to have comm field
1348                  * of "nscd" than "exe" (pgrep reported to fail to find us
1349                  * by name when comm field contains "exe") */
1350                 execve(self_exe_points_to, argv, argv+2);
1351                 xexecve("/proc/self/exe", argv, argv+2);
1352         }
1353
1354         /* parent */
1355         close(to_child.rd);
1356         close(to_parent.wr);
1357         /* We do not expect child to block for any noticeably long time,
1358          * and also we expect write to be one-piece one:
1359          * ureq size is <= 1k and pipes are guaranteed to accept
1360          * at least PIPE_BUF at once */
1361         xsafe_write(to_child.wr, ureq, ureq_size(ureq));
1362
1363         close(to_child.wr);
1364         close_on_exec(to_parent.rd);
1365         return to_parent.rd;
1366 }
1367
1368 static user_req *worker_ureq;
1369
1370 #if DEBUG_BUILD
1371 static const char *req_str(unsigned type, const char *buf)
1372 {
1373         if (type == GETHOSTBYADDR) {
1374                 struct in_addr in;
1375                 in.s_addr = *((uint32_t*)buf);
1376                 return inet_ntoa(in);
1377         }
1378         if (type == GETHOSTBYADDRv6) {
1379                 return "IPv6";
1380         }
1381         return buf;
1382 }
1383 #else
1384 const char *req_str(unsigned type, const char *buf);
1385 #endif
1386
1387 static void worker_signal_handler(int sig)
1388 {
1389 #if DEBUG_BUILD
1390         log(L_INFO, "worker:%d got sig:%d while handling req "
1391                 "type:%d(%s) key_len:%d '%s'",
1392                 getpid(), sig,
1393                 worker_ureq->type, typestr[worker_ureq->type],
1394                 worker_ureq->key_len,
1395                 req_str(worker_ureq->type, worker_ureq->reqbuf)
1396         );
1397 #else
1398         log(L_INFO, "worker:%d got sig:%d while handling req "
1399                 "type:%d key_len:%d",
1400                 getpid(), sig,
1401                 worker_ureq->type, worker_ureq->key_len);
1402 #endif
1403         _exit(0);
1404 }
1405
1406 static void worker(const char *param) NORETURN;
1407 static void worker(const char *param)
1408 {
1409         user_req ureq;
1410         void *resp;
1411
1412         debug = atoi(param);
1413
1414         worker_ureq = &ureq; /* for signal handler */
1415
1416         /* Make sure we won't hang, but rather die */
1417         if (WORKER_TIMEOUT_SEC)
1418                 alarm(WORKER_TIMEOUT_SEC);
1419
1420         /* NB: fds 0, 1 are in blocking mode */
1421
1422         /* We block here (for a short time) */
1423         /* Due to ureq size < PIPE_BUF read is atomic */
1424         /* No error or size checking: we trust the parent */
1425         safe_read(0, &ureq, sizeof(ureq));
1426
1427         signal(SIGSEGV,   worker_signal_handler);
1428         signal(SIGBUS,    worker_signal_handler);
1429         signal(SIGILL,    worker_signal_handler);
1430         signal(SIGFPE,    worker_signal_handler);
1431         signal(SIGABRT,   worker_signal_handler);
1432 #ifdef SIGSTKFLT
1433         signal(SIGSTKFLT, worker_signal_handler);
1434 #endif
1435
1436         if (ureq.type == GETHOSTBYNAME
1437          || ureq.type == GETHOSTBYNAMEv6
1438         ) {
1439                 resp = marshal_hostent(
1440                         ureq.type == GETHOSTBYNAME
1441                         ? gethostbyname(ureq.reqbuf)
1442                         : gethostbyname2(ureq.reqbuf, AF_INET6)
1443                 );
1444         } else if (ureq.type == GETHOSTBYADDR
1445          || ureq.type == GETHOSTBYADDRv6
1446         ) {
1447                 resp = marshal_hostent(gethostbyaddr(ureq.reqbuf, ureq.key_len,
1448                         (ureq.type == GETHOSTBYADDR ? AF_INET : AF_INET6)
1449                 ));
1450         } else if (ureq.type == GETPWBYNAME) {
1451                 struct passwd *pw;
1452                 log(L_DEBUG2, "getpwnam('%s')", ureq.reqbuf);
1453                 pw = getpwnam(ureq.reqbuf);
1454                 log(L_DEBUG2, "getpwnam result:%p", pw);
1455                 resp = marshal_passwd(pw);
1456         } else if (ureq.type == GETPWBYUID) {
1457                 resp = marshal_passwd(getpwuid(atoi(ureq.reqbuf)));
1458         } else if (ureq.type == GETGRBYNAME) {
1459                 struct group *gr = getgrnam(ureq.reqbuf);
1460                 resp = marshal_group(gr);
1461         } else if (ureq.type == GETGRBYGID) {
1462                 struct group *gr = getgrgid(atoi(ureq.reqbuf));
1463                 resp = marshal_group(gr);
1464         } else if (ureq.type == GETAI) {
1465                 resp = obtain_addrinfo(ureq.reqbuf);
1466         } else /*if (ureq.type == INITGROUPS)*/ {
1467                 resp = obtain_initgroups(ureq.reqbuf);
1468         }
1469
1470         if (!((response_header*)resp)->found) {
1471                 /* Parent knows about this special case */
1472                 xfull_write(1, resp, 8);
1473         } else {
1474                 /* Responses can be big (getgrnam("guest") on a big user db),
1475                  * we cannot rely on them being atomic. full_write loops
1476                  * if needed */
1477                 xfull_write(1, resp, ((response_header*)resp)->version_or_size);
1478         }
1479         _exit(0);
1480 }
1481
1482
1483 /*
1484 ** Main loop
1485 */
1486
1487 static const char checked_filenames[][sizeof("/etc/passwd")] = {
1488         [SRV_PASSWD] = "/etc/passwd", /*  "/etc/shadow"? */
1489         [SRV_GROUP]  = "/etc/group",
1490         [SRV_HOSTS]  = "/etc/hosts", /* "/etc/resolv.conf" "/etc/nsswitch.conf"? */
1491 };
1492
1493 static long checked_status[ARRAY_SIZE(checked_filenames)];
1494
1495 static void check_files(int srv)
1496 {
1497         struct stat tsb;
1498         const char *file = checked_filenames[srv];
1499         long v;
1500
1501         memset(&tsb, 0, sizeof(tsb));
1502         stat(file, &tsb); /* ignore errors */
1503         /* Comparing struct stat's was giving false positives.
1504          * Extracting only those fields which are interesting: */
1505         v = (long)tsb.st_mtime ^ (long)tsb.st_size ^ (long)tsb.st_ino; /* ^ (long)tsb.st_dev ? */
1506
1507         if (v != checked_status[srv]) {
1508                 checked_status[srv] = v;
1509                 log(L_INFO, "detected change in %s", file);
1510                 age_cache(/*free_all:*/ 1, srv);
1511         }
1512 }
1513
1514 /* Returns 1 if we immediately have the answer */
1515 static int handle_client(int i)
1516 {
1517         int srv;
1518         user_req *ureq = cinfo[i].ureq;
1519         user_req **cache_pp;
1520         user_req *ureq_and_resp;
1521
1522 #if DEBUG_BUILD
1523         log(L_DEBUG, "version:%d type:%d(%s) key_len:%d '%s'",
1524                         ureq->version, ureq->type,
1525                         ureq->type < ARRAY_SIZE(typestr) ? typestr[ureq->type] : "?",
1526                         ureq->key_len, req_str(ureq->type, ureq->reqbuf));
1527 #endif
1528
1529         if (ureq->version != NSCD_VERSION) {
1530                 log(L_INFO, "wrong version");
1531                 close_client(i);
1532                 return 0;
1533         }
1534         if (ureq->key_len > sizeof(ureq->reqbuf)) {
1535                 log(L_INFO, "bogus key_len %u - ignoring", ureq->key_len);
1536                 close_client(i);
1537                 return 0;
1538         }
1539         if (cinfo[i].bytecnt < USER_HDR_SIZE + ureq->key_len) {
1540                 log(L_INFO, "read %d, need to read %d",
1541                         cinfo[i].bytecnt, USER_HDR_SIZE + ureq->key_len);
1542                 return 0; /* more to read */
1543         }
1544         if (cinfo[i].bytecnt > USER_HDR_SIZE + ureq->key_len) {
1545                 log(L_INFO, "read overflow: %u > %u",
1546                         (int)cinfo[i].bytecnt, (int)(USER_HDR_SIZE + ureq->key_len));
1547                 close_client(i);
1548                 return 0;
1549         }
1550         if (unsupported_ureq_type(ureq->type)) {
1551                 /* We don't know this request. Just close the connection.
1552                  * (glibc client interprets this like "not supported by this nscd")
1553                  * Happens very often, thus DEBUG, not INFO */
1554                 log(L_DEBUG, "unsupported query, dropping");
1555                 close_client(i);
1556                 return 0;
1557         }
1558         srv = type_to_srv[ureq->type];
1559         if (!config.srv_enable[srv]) {
1560                 log(L_INFO, "service %d is disabled, dropping", srv);
1561                 close_client(i);
1562                 return 0;
1563         }
1564
1565         hex_dump(cinfo[i].ureq, cinfo[i].bytecnt);
1566
1567         if (ureq->type == SHUTDOWN
1568          || ureq->type == INVALIDATE
1569         ) {
1570 #ifdef SO_PEERCRED
1571                 struct ucred caller;
1572                 socklen_t optlen = sizeof(caller);
1573                 if (getsockopt(pfd[i].fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0) {
1574                         log(L_INFO, "ignoring special request - cannot get caller's id: %s", strerror(errno));
1575                         close_client(i);
1576                         return 0;
1577                 }
1578                 if (caller.uid != 0) {
1579                         log(L_INFO, "special request from non-root - ignoring");
1580                         close_client(i);
1581                         return 0;
1582                 }
1583 #endif
1584                 if (ureq->type == SHUTDOWN) {
1585                         log(L_INFO, "got shutdown request, exiting");
1586                         exit(0);
1587                 }
1588                 if (!ureq->key_len || ureq->reqbuf[ureq->key_len - 1]) {
1589                         log(L_INFO, "malformed invalidate request - ignoring");
1590                         close_client(i);
1591                         return 0;
1592                 }
1593                 log(L_INFO, "got invalidate request, flushing cache");
1594                 /* Frees entire cache. TODO: replace -1 with service (in ureq->reqbuf) */
1595                 age_cache(/*free_all:*/ 1, -1);
1596                 close_client(i);
1597                 return 0;
1598         }
1599
1600         if (ureq->type != GETHOSTBYADDR
1601          && ureq->type != GETHOSTBYADDRv6
1602         ) {
1603                 if (ureq->key_len && ureq->reqbuf[ureq->key_len - 1] != '\0') {
1604                         log(L_INFO, "badly terminated buffer");
1605                         close_client(i);
1606                         return 0;
1607                 }
1608         }
1609
1610         if (config.check_files[srv]) {
1611                 check_files(srv);
1612         }
1613
1614         cache_pp = lookup_in_cache(ureq);
1615         ureq_and_resp = cache_pp ? *cache_pp : NULL;
1616
1617         if (ureq_and_resp) {
1618                 if (CACHED_ENTRY(ureq_and_resp)) {
1619                         /* Found. Save ptr to response into cinfo and return */
1620                         response_header *resp = ureq_response(ureq_and_resp);
1621                         unsigned sz = resp->version_or_size;
1622
1623                         log(L_DEBUG, "sz:%u", sz);
1624                         hex_dump(resp, sz);
1625                         ureq_and_resp->refcount++; /* cache shouldn't free it under us! */
1626                         pfd[i].events = POLLOUT; /* we want to write out */
1627                         cinfo[i].resptr = ureq_and_resp;
1628                         /*cinfo[i].respos = 0; - already is */
1629                         /* prevent future matches with anything */
1630                         cinfo[i].cache_pp = (void *) 1;
1631                         return 1; /* "ready to write data out to client" */
1632                 }
1633
1634                 /* Not found. Remember a pointer where it will appear */
1635                 cinfo[i].cache_pp = cache_pp;
1636
1637                 /* If it does not point to our own ureq buffer... */
1638                 if (CACHE_PTR(ureq_and_resp) != ureq) {
1639                         /* We are not the first client who wants this */
1640                         log(L_DEBUG, "another request is in progress (%p), waiting for its result", ureq_and_resp);
1641                         MARK_PTR_SHARED(cache_pp); /* "please inform us when it's ready" */
1642                         /* "we do not wait for client anymore" */
1643                         cinfo[i].client_fd = pfd[i].fd;
1644                         /* Don't wait on fd. Worker response will unblock us */
1645                         pfd[i].events = 0;
1646                         return 0;
1647                 }
1648                 /* else: lookup_in_cache inserted (ureq & 1) into *cache_pp:
1649                  * we are the first client to miss on this ureq. */
1650         }
1651
1652         /* Start worker thread */
1653         log(L_DEBUG, "stored %p in cache, starting a worker", ureq_and_resp);
1654         /* Now we will wait on worker's fd, not client's! */
1655         cinfo[i].client_fd = pfd[i].fd;
1656         pfd[i].fd = create_and_feed_worker(ureq);
1657         return 0;
1658 }
1659
1660 static void prepare_for_writeout(unsigned i, user_req *cached)
1661 {
1662         log(L_DEBUG2, "client %u: data is ready at %p", i, cached);
1663
1664         if (cinfo[i].client_fd) {
1665                 pfd[i].fd = cinfo[i].client_fd;
1666                 cinfo[i].client_fd = 0; /* "we don't wait for worker reply" */
1667         }
1668         pfd[i].events = POLLOUT;
1669
1670         /* Writeout position etc */
1671         cinfo[i].resptr = cached;
1672         /*cinfo[i].respos = 0; - already is */
1673         /* if worker took some time to get info (e.g. DNS query),
1674          * prevent client timeout from triggering at once */
1675         cinfo[i].started_ms = g_now_ms;
1676 }
1677
1678 /* Worker seems to be ready to write the response.
1679  * When we return, response is fully read and stored in cache,
1680  * worker's fd is closed, pfd[i] and cinfo[i] are updated. */
1681 static void handle_worker_response(int i)
1682 {
1683         struct { /* struct response_header + small body */
1684                 uint32_t version_or_size;
1685                 int32_t found;
1686                 char body[256 - 8];
1687         } sz_and_found;
1688         user_req *cached;
1689         user_req *ureq;
1690         response_header *resp;
1691         unsigned sz, resp_sz;
1692         unsigned ureq_sz_aligned;
1693
1694         cached = NULL;
1695         ureq = cinfo[i].ureq;
1696         ureq_sz_aligned = (char*)ureq_response(ureq) - (char*)ureq;
1697
1698         sz = full_read(pfd[i].fd, &sz_and_found, sizeof(sz_and_found));
1699         if (sz < 8) {
1700                 /* worker was killed? */
1701                 log(L_DEBUG, "worker gave short reply:%u < 8", sz);
1702                 goto err;
1703         }
1704
1705         resp_sz = sz_and_found.version_or_size;
1706         if (resp_sz < sz || resp_sz > 0x0fffffff) { /* 256 mb */
1707                 error("BUG: bad size from worker:%u", resp_sz);
1708                 goto err;
1709         }
1710
1711         /* Create new block of cached info */
1712         cached = xzalloc(ureq_sz_aligned + resp_sz);
1713         log(L_DEBUG2, "xzalloc(%u):%p sz:%u resp_sz:%u found:%u",
1714                         ureq_sz_aligned + resp_sz, cached,
1715                         sz, resp_sz,
1716                         (int)sz_and_found.found
1717                         );
1718         resp = (void*) (((char*) cached) + ureq_sz_aligned);
1719         memcpy(cached, ureq, ureq_size(ureq));
1720         memcpy(resp, &sz_and_found, sz);
1721         if (sz_and_found.found && resp_sz > sz) {
1722                 /* We need to read data only if it's found
1723                  * (otherwise worker sends only 8 bytes).
1724                  *
1725                  * Replies can be big (getgrnam("guest") on a big user db),
1726                  * we cannot rely on them being atomic. However, we know
1727                  * that worker _always_ gives reply in one full_write(),
1728                  * so we loop and read it all
1729                  * (looping is implemented inside full_read())
1730                  */
1731                 if (full_read(pfd[i].fd, ((char*) resp) + sz, resp_sz - sz) != resp_sz - sz) {
1732                         /* worker was killed? */
1733                         log(L_DEBUG, "worker gave short reply, free(%p)", cached);
1734  err:
1735                         free(cached);
1736                         cached = NULL;
1737                         goto wo;
1738                 }
1739         }
1740         set_cache_timestamp(cached);
1741         hex_dump(resp, resp_sz);
1742
1743  wo:
1744         close(pfd[i].fd);
1745
1746         /* Save in cache */
1747         unsigned ref = 0;
1748         user_req **cache_pp = cinfo[i].cache_pp;
1749         if (cache_pp != NULL) { /* if not a fake entry */
1750                 ureq = *cache_pp;
1751                 *cache_pp = cached;
1752                 if (CACHE_SHARED(ureq)) {
1753                         /* Other clients wait for this response too,
1754                          * wake them (and us) up and set refcount = no_of_clients */
1755                         unsigned j;
1756
1757                         for (j = 2; j < num_clients; j++) {
1758                                 if (cinfo[j].cache_pp == cache_pp) {
1759                                         /* This client uses the same cache entry */
1760                                         ref++;
1761                                         /* prevent future matches with anything */
1762                                         cinfo[j].cache_pp = (void *) 1;
1763                                         prepare_for_writeout(j, cached);
1764                                 }
1765                         }
1766                         goto ret;
1767                 }
1768                 /* prevent future matches with anything */
1769                 cinfo[i].cache_pp = (void *) 1;
1770                 ref = 1;
1771         }
1772
1773         prepare_for_writeout(i, cached);
1774 ret:
1775         /* cache shouldn't free it under us! */
1776         if (cached)
1777                 cached->refcount = ref;
1778         aging_interval_ms = min_aging_interval_ms;
1779 }
1780
1781 static void main_loop(void)
1782 {
1783         /* 1/2 of smallest negative TTL */
1784         min_aging_interval_ms = config.nttl[0];
1785         if (min_aging_interval_ms > config.nttl[1]) min_aging_interval_ms = config.nttl[1];
1786         if (min_aging_interval_ms > config.nttl[2]) min_aging_interval_ms = config.nttl[2];
1787         min_aging_interval_ms = (min_aging_interval_ms / 2) | 1;
1788         aging_interval_ms = min_aging_interval_ms;
1789
1790         while (1) {
1791                 int i, j;
1792                 int r;
1793
1794                 r = SMALL_POLL_TIMEOUT_MS;
1795                 if (num_clients <= 2 && !cached_cnt)
1796                         r = -1; /* infinite */
1797                 else if (num_clients < max_reqnum)
1798                         r = aging_interval_ms;
1799 #if 0 /* Debug: leak detector */
1800                 {
1801                         static unsigned long long cnt;
1802                         static unsigned long low_malloc = -1L;
1803                         static unsigned long low_sbrk = -1L;
1804                         void *p = malloc(540); /* should not be too small */
1805                         void *s = sbrk(0);
1806                         free(p);
1807                         if ((unsigned long)p < low_malloc)
1808                                 low_malloc = (unsigned long)p;
1809                         if ((unsigned long)s < low_sbrk)
1810                                 low_sbrk = (unsigned long)s;
1811                         log(L_INFO, "poll %llu (%d ms). clients:%u cached:%u %u/%u malloc:%p (%lu), sbrk:%p (%lu)",
1812                                 cnt, r, num_clients, cached_cnt, cache_hit_cnt, cache_access_cnt,
1813                                 p, (unsigned long)p - low_malloc,
1814                                 s, (unsigned long)s - low_sbrk);
1815                         cnt++;
1816                 }
1817 #else
1818                 log(L_DEBUG, "poll %d ms. clients:%u cached:%u hit ratio:%u/%u",
1819                                 r, num_clients, cached_cnt, cache_hit_cnt, cache_access_cnt);
1820 #endif
1821
1822                 r = poll(pfd, num_clients, r);
1823                 log(L_DEBUG2, "poll returns %d", r);
1824                 if (r < 0) {
1825                         if (errno != EINTR)
1826                                 perror_and_die("poll");
1827                         continue;
1828                 }
1829
1830                 /* Everything between polls never sleeps.
1831                  * There is no blocking I/O (except when we talk to worker thread
1832                  * which is guaranteed to not block us for long) */
1833
1834                 g_now_ms = monotonic_ms();
1835                 if (r == 0)
1836                         goto skip_fd_checks;
1837
1838                 for (i = 0; i < 2; i++) {
1839                         int cfd;
1840                         if (!pfd[i].revents)
1841                                 continue;
1842                         /* pfd[i].revents = 0; - not needed */
1843                         cfd = accept(pfd[i].fd, NULL, NULL);
1844                         if (cfd < 0) {
1845                                 /* odd... poll() says we can accept but accept failed? */
1846                                 log(L_DEBUG2, "accept failed with %s", strerror(errno));
1847                                 continue;
1848                         }
1849                         ndelay_on(cfd);
1850                         close_on_exec(cfd);
1851                         /* x[num_clients] is next free element, taking it */
1852                         log(L_DEBUG2, "new client %d, fd %d", num_clients, cfd);
1853                         pfd[num_clients].fd = cfd;
1854                         pfd[num_clients].events = POLLIN;
1855                         /* this will make us do read() in next for() loop: */
1856                         pfd[num_clients].revents = POLLIN;
1857                         memset(&cinfo[num_clients], 0, sizeof(cinfo[num_clients]));
1858                         /* cinfo[num_clients].bytecnt = 0; - done */
1859                         cinfo[num_clients].started_ms = g_now_ms;
1860                         cinfo[num_clients].bufidx = alloc_buf_no();
1861                         cinfo[num_clients].ureq = bufno2buf(cinfo[num_clients].bufidx);
1862                         num_clients++;
1863                         if (num_clients >= max_reqnum) {
1864                                 /* stop accepting new connects for now */
1865                                 pfd[0].events = pfd[0].revents = 0;
1866                                 pfd[1].events = pfd[1].revents = 0;
1867                         }
1868                 }
1869                 for (; i < num_clients; i++) {
1870                         if (!pfd[i].revents)
1871                                 continue;
1872                         log(L_DEBUG2, "pfd[%d].revents:0x%x", i, pfd[i].revents);
1873                         /* pfd[i].revents = 0; - not needed */
1874
1875                         /* "Write out result" case */
1876                         if (pfd[i].revents == POLLOUT) {
1877                                 response_header *resp;
1878                                 uint32_t resp_sz;
1879                                 if (!cinfo[i].resptr) {
1880                                         /* corner case: worker gave bad response earlier */
1881                                         close_client(i);
1882                                         continue;
1883                                 }
1884  write_out:
1885                                 resp = ureq_response(cinfo[i].resptr);
1886                                 resp_sz = resp->version_or_size;
1887                                 resp->version_or_size = NSCD_VERSION;
1888                                 errno = 0;
1889                                 r = safe_write(pfd[i].fd, ((char*) resp) + cinfo[i].respos, resp_sz - cinfo[i].respos);
1890                                 resp->version_or_size = resp_sz;
1891
1892                                 if (r < 0 && errno == EAGAIN)
1893                                         continue;
1894                                 if (r <= 0) { /* client isn't there anymore */
1895                                         log(L_DEBUG, "client %d is gone (write returned:%d err:%s)",
1896                                                         i, r, errno ? strerror(errno) : "-");
1897  write_out_is_done:
1898                                         if (cinfo[i].cache_pp == NULL) {
1899                                                 log(L_DEBUG, "client %d: freeing fake cache entry %p", i, cinfo[i].resptr);
1900                                                 free(cinfo[i].resptr);
1901                                         } else {
1902                                                 /* Most of the time, it is not freed here,
1903                                                  * only refcounted--. Freeing happens
1904                                                  * if it was deleted from cache[] but retained
1905                                                  * for writeout. */
1906                                                 free_refcounted_ureq(&cinfo[i].resptr);
1907                                         }
1908                                         close_client(i);
1909                                         continue;
1910                                 }
1911                                 cinfo[i].respos += r;
1912                                 if (cinfo[i].respos >= resp_sz) {
1913                                         /* We wrote everything */
1914                                         /* No point in trying to get next request, it won't come.
1915                                          * glibc 2.4 client closes its end after each request,
1916                                          * without testing for EOF from server. strace:
1917                                          * ...
1918                                          * read(3, "www.google.com\0\0", 16) = 16
1919                                          * close(3) = 0
1920                                          */
1921                                         log(L_DEBUG, "client %u: sent answer %u bytes", i, cinfo[i].respos);
1922                                         goto write_out_is_done;
1923                                 }
1924                         }
1925
1926                         /* "Read reply from worker" case. Worker may be
1927                          * already dead, revents may contain other bits too */
1928                         if ((pfd[i].revents & POLLIN) && cinfo[i].client_fd) {
1929                                 log(L_DEBUG, "reading response for client %u", i);
1930                                 handle_worker_response(i);
1931                                 /* We can immediately try to write a response
1932                                  * to client */
1933                                 goto write_out;
1934                         }
1935
1936                         /* POLLHUP means pfd[i].fd is closed by peer.
1937                          * POLLHUP+POLLOUT is seen when we switch for writeout
1938                          * and see that pfd[i].fd is closed by peer. */
1939                         if ((pfd[i].revents & ~POLLOUT) == POLLHUP) {
1940                                 int is_client = (cinfo[i].client_fd == 0 || cinfo[i].client_fd == pfd[i].fd);
1941                                 log(L_INFO, "%s %u disappeared (got POLLHUP on fd %d)",
1942                                         is_client ? "client" : "worker",
1943                                         i,
1944                                         pfd[i].fd
1945                                 );
1946                                 if (is_client)
1947                                         close_client(i);
1948                                 else {
1949                                         /* Read worker output anyway, error handling
1950                                          * in that function deals with short read.
1951                                          * Simply closing client is wrong: it leaks
1952                                          * shared future entries. */
1953                                         handle_worker_response(i);
1954                                 }
1955                                 continue;
1956                         }
1957
1958                         /* All strange and unexpected cases */
1959                         if (pfd[i].revents != POLLIN) {
1960                                 /* Not just "can read", but some other bits are there */
1961                                 log(L_INFO, "client %u revents is strange:%x", i, pfd[i].revents);
1962                                 close_client(i);
1963                                 continue;
1964                         }
1965
1966                         /* "Read request from client" case */
1967                         r = safe_read(pfd[i].fd, (char*)(cinfo[i].ureq) + cinfo[i].bytecnt, MAX_USER_REQ_SIZE - cinfo[i].bytecnt);
1968                         if (r < 0) {
1969                                 log(L_DEBUG2, "error reading from client: %s", strerror(errno));
1970                                 if (errno == EAGAIN)
1971                                         continue;
1972                                 close_client(i);
1973                                 continue;
1974                         }
1975                         if (r == 0) {
1976                                 log(L_INFO, "premature EOF from client, dropping");
1977                                 close_client(i);
1978                                 continue;
1979                         }
1980                         cinfo[i].bytecnt += r;
1981                         if (cinfo[i].bytecnt >= sizeof(user_req_header)) {
1982                                 if (handle_client(i)) {
1983                                         /* Response is found in cache! */
1984                                         goto write_out;
1985                                 }
1986                         }
1987                 } /* for each client[2..num_clients-1] */
1988
1989  skip_fd_checks:
1990                 /* Age cache */
1991                 if ((g_now_ms - last_age_time) >= aging_interval_ms) {
1992                         last_age_time = g_now_ms;
1993                         age_cache(/*free_all:*/ 0, -1);
1994                 }
1995
1996                 /* Close timed out client connections */
1997                 for (i = 2; i < num_clients; i++) {
1998                         if (pfd[i].fd != 0 /* not closed yet? */ ////
1999                          && cinfo[i].client_fd == 0 /* do we still wait for client, not worker? */
2000                          && (g_now_ms - cinfo[i].started_ms) > CLIENT_TIMEOUT_MS
2001                         ) {
2002                                 log(L_INFO, "timed out waiting for client %u (%u ms), dropping",
2003                                         i, (unsigned)(g_now_ms - cinfo[i].started_ms));
2004                                 close_client(i);
2005                         }
2006                 }
2007
2008                 if (!cnt_closed)
2009                         continue;
2010
2011                 /* We closed at least one client, coalesce pfd[], cinfo[] */
2012                 if (min_closed + cnt_closed >= num_clients) {
2013                         /* clients [min_closed..num_clients-1] are all closed */
2014                         /* log(L_DEBUG, "taking shortcut"); - almost always happens */
2015                         goto coalesce_done;
2016                 }
2017                 j = min_closed;
2018                 i = min_closed + 1;
2019                 while (i < num_clients) {
2020                         while (1) {
2021                                 if (pfd[i].fd)
2022                                         break;
2023                                 if (++i >= num_clients)
2024                                         goto coalesce_done;
2025                         }
2026                         pfd[j] = pfd[i];
2027                         cinfo[j++] = cinfo[i++];
2028                 }
2029
2030  coalesce_done:
2031                 num_clients -= cnt_closed;
2032                 log(L_DEBUG, "removing %d closed clients. clients:%d", cnt_closed, num_clients);
2033                 min_closed = INT_MAX;
2034                 cnt_closed = 0;
2035                 /* start accepting new connects */
2036                 pfd[0].events = POLLIN;
2037                 pfd[1].events = POLLIN;
2038         } /* while (1) */
2039 }
2040
2041
2042 /*
2043 ** Initialization
2044 */
2045
2046 #define NSCD_PIDFILE    "/var/run/nscd/nscd.pid"
2047 #define NSCD_DIR        "/var/run/nscd"
2048 #define NSCD_SOCKET     "/var/run/nscd/socket"
2049 #define NSCD_SOCKET_OLD "/var/run/.nscd_socket"
2050
2051 static smallint wrote_pidfile;
2052
2053 static void cleanup_on_signal(int sig)
2054 {
2055         if (wrote_pidfile)
2056                 unlink(NSCD_PIDFILE);
2057         unlink(NSCD_SOCKET_OLD);
2058         unlink(NSCD_SOCKET);
2059         exit(0);
2060 }
2061
2062 static void write_pid(void)
2063 {
2064         FILE *pid = fopen(NSCD_PIDFILE, "w");
2065         if (!pid)
2066                 return;
2067         fprintf(pid, "%d\n", getpid());
2068         fclose(pid);
2069         wrote_pidfile = 1;
2070 }
2071
2072 /* Open a listening nscd server socket */
2073 static int open_socket(const char *name)
2074 {
2075         struct sockaddr_un sun;
2076         int sock = socket(AF_UNIX, SOCK_STREAM, 0);
2077         if (sock < 0)
2078                 perror_and_die("cannot create unix domain socket");
2079         ndelay_on(sock);
2080         close_on_exec(sock);
2081         sun.sun_family = AF_UNIX;
2082         strcpy(sun.sun_path, name);
2083         unlink(name);
2084         if (bind(sock, (struct sockaddr *) &sun, sizeof(sun)) < 0)
2085                 perror_and_die("bind(%s)", name);
2086         if (chmod(name, 0666) < 0)
2087                 perror_and_die("chmod(%s)", name);
2088         if (listen(sock, (max_reqnum/8) | 1) < 0)
2089                 perror_and_die("listen");
2090         return sock;
2091 }
2092
2093 static const struct option longopt[] = {
2094         /* name, has_arg, int *flag, int val */
2095         { "debug"      , no_argument      , NULL, 'd' },
2096         { "config-file", required_argument, NULL, 'f' },
2097         { "invalidate" , required_argument, NULL, 'i' },
2098         { "shutdown"   , no_argument      , NULL, 'K' },
2099         { "nthreads"   , required_argument, NULL, 't' },
2100         { "version"    , no_argument      , NULL, 'V' },
2101         { "help"       , no_argument      , NULL, '?' },
2102         { "usage"      , no_argument      , NULL, '?' },
2103         /* just exit(0). TODO: "test" connect? */
2104         { "statistic"  , no_argument      , NULL, 'g' },
2105         { "secure"     , no_argument      , NULL, 'S' }, /* ? */
2106         { }
2107 };
2108
2109 static const char *const help[] = {
2110         "Do not daemonize; log to stderr (-dd: more verbosity)",
2111         "File to read configuration from",
2112         "Invalidate cache",
2113         "Shut the server down",
2114         "Serve N requests in parallel",
2115         "Version",
2116 };
2117
2118 static void print_help_and_die(void)
2119 {
2120         const struct option *opt = longopt;
2121         const char *const *h = help;
2122
2123         puts("Usage: nscd [OPTION...]\n"
2124              "Name Service Cache Daemon\n");
2125         do {
2126                 printf("\t" "-%c,--%-11s %s\n", opt->val, opt->name, *h);
2127                 h++;
2128                 opt++;
2129         } while (opt->val != '?');
2130         exit(1);
2131 }
2132
2133 static char *skip_service(int *srv, const char *s)
2134 {
2135         if (strcmp("passwd", s) == 0) {
2136                 *srv = SRV_PASSWD;
2137                 s++;
2138         } else if (strcmp("group", s) == 0) {
2139                 *srv = SRV_GROUP;
2140         } else if (strcmp("hosts", s) == 0) {
2141                 *srv = SRV_HOSTS;
2142         } else {
2143                 return NULL;
2144         }
2145         return skip_whitespace(s + 6);
2146 }
2147
2148 static void handle_null(const char *str, int srv) {}
2149
2150 static void handle_logfile(const char *str, int srv)
2151 {
2152         config.logfile = xstrdup(str);
2153 }
2154
2155 static void handle_debuglvl(const char *str, int srv)
2156 {
2157         debug |= (uint8_t) getnum(str);
2158 }
2159
2160 static void handle_threads(const char *str, int srv)
2161 {
2162         unsigned n = getnum(str);
2163         if (max_reqnum < n)
2164                 max_reqnum = n;
2165 }
2166
2167 static void handle_user(const char *str, int srv)
2168 {
2169         config.user = xstrdup(str);
2170 }
2171
2172 static void handle_enable(const char *str, int srv)
2173 {
2174         config.srv_enable[srv] = ((str[0] | 0x20) == 'y');
2175 }
2176
2177 static void handle_pttl(const char *str, int srv)
2178 {
2179         config.pttl[srv] = getnum(str);
2180 }
2181
2182 static void handle_nttl(const char *str, int srv)
2183 {
2184         config.nttl[srv] = getnum(str);
2185 }
2186
2187 static void handle_size(const char *str, int srv)
2188 {
2189         config.size[srv] = getnum(str);
2190 }
2191
2192 static void handle_chfiles(const char *str, int srv)
2193 {
2194         config.check_files[srv] = ((str[0] | 0x20) == 'y');
2195 }
2196
2197 static void parse_conffile(const char *conffile, int warn)
2198 {
2199         static const struct confword {
2200                 const char *str;
2201                 void (*handler)(const char *, int);
2202         } conf_words[] = {
2203                 { "_" "logfile"               , handle_logfile  },
2204                 { "_" "debug-level"           , handle_debuglvl },
2205                 { "_" "threads"               , handle_threads  },
2206                 { "_" "max-threads"           , handle_threads  },
2207                 { "_" "server-user"           , handle_user     },
2208                 /* ignore: any user can stat */
2209                 { "_" "stat-user"             , handle_null     },
2210                 { "_" "paranoia"              , handle_null     }, /* ? */
2211                 /* ignore: design goal is to never crash/hang */
2212                 { "_" "reload-count"          , handle_null     },
2213                 { "_" "restart-interval"      , handle_null     },
2214                 { "S" "enable-cache"          , handle_enable   },
2215                 { "S" "positive-time-to-live" , handle_pttl     },
2216                 { "S" "negative-time-to-live" , handle_nttl     },
2217                 { "S" "suggested-size"        , handle_size     },
2218                 { "S" "check-files"           , handle_chfiles  },
2219                 { "S" "persistent"            , handle_null     }, /* ? */
2220                 { "S" "shared"                , handle_null     }, /* ? */
2221                 { "S" "auto-propagate"        , handle_null     }, /* ? */
2222                 { }
2223         };
2224
2225         char buf[128];
2226         FILE *file = fopen(conffile, "r");
2227         int lineno = 0;
2228
2229         if (!file) {
2230                 if (conffile != default_conffile)
2231                         perror_and_die("cannot open %s", conffile);
2232                 return;
2233         }
2234
2235         while (fgets(buf, sizeof(buf), file) != NULL) {
2236                 const struct confword *word;
2237                 char *p;
2238                 int len = strlen(buf);
2239
2240                 lineno++;
2241                 if (len) {
2242                         if (buf[len-1] != '\n') {
2243                                 if (len >= sizeof(buf) - 1)
2244                                         error_and_die("%s:%d: line is too long", conffile, lineno);
2245                                 len++; /* last line, not terminated by '\n' */
2246                         }
2247                         buf[len-1] = '\0';
2248                 }
2249                 p = strchr(buf, '#');
2250                 if (p)
2251                         *p = '\0';
2252
2253                 p = skip_whitespace(buf);
2254                 if (!*p)
2255                         continue;
2256                 *skip_non_whitespace(p) = '\0';
2257                 word = conf_words;
2258                 while (1) {
2259                         if (strcmp(word->str + 1, p) == 0) {
2260                                 int srv = 0;
2261                                 p = skip_whitespace(p + strlen(p) + 1);
2262                                 *skip_non_whitespace(p) = '\0';
2263                                 if (word->str[0] == 'S') {
2264                                         char *p2 = skip_service(&srv, p);
2265                                         if (!p2) {
2266                                                 if (warn)
2267                                                         error("%s:%d: ignoring unknown service name '%s'", conffile, lineno, p);
2268                                                 break;
2269                                         }
2270                                         p = p2;
2271                                         *skip_non_whitespace(p) = '\0';
2272                                 }
2273                                 word->handler(p, srv);
2274                                 break;
2275                         }
2276                         word++;
2277                         if (!word->str) {
2278                                 if (warn)
2279                                         error("%s:%d: ignoring unknown directive '%s'", conffile, lineno, p);
2280                                 break;
2281                         }
2282                 }
2283         }
2284         fclose(file);
2285 }
2286
2287
2288 /* "XX,XX[,XX]..." -> gid_t[] */
2289 static gid_t* env_U_to_uid_and_gids(const char *str, int *sizep)
2290 {
2291         const char *sp;
2292         gid_t *ug, *gp;
2293         int ng;
2294
2295         sp = str;
2296         ng = 1;
2297         while (*sp)
2298                 if (*sp++ == ',')
2299                         ng++;
2300         ug = xmalloc(ng * sizeof(ug[0]));
2301
2302         ng = 0;
2303         gp = ug;
2304         sp = str;
2305         errno = 0;
2306         while (1) {
2307                 ng++;
2308                 *gp++ = strtoul(sp, (char**)&sp, 16);
2309                 if (errno || (*sp != ',' && *sp != '\0'))
2310                         error_and_die("internal error");
2311                 if (*sp == '\0')
2312                         break;
2313                 sp++;
2314         }
2315
2316         *sizep = ng;
2317         return ug;
2318 }
2319
2320
2321 static char* user_to_env_U(const char *user)
2322 {
2323         int ng;
2324         char *ug_str, *sp;
2325         gid_t *ug, *gp;
2326         struct passwd *pw;
2327
2328         pw = getpwnam(user);
2329         if (!pw)
2330                 perror_and_die("user '%s' is not known", user);
2331
2332         ng = 64;
2333         /* 0th cell will be used for uid */
2334         ug = xmalloc((1 + ng) * sizeof(ug[0]));
2335         if (getgrouplist(user, pw->pw_gid, &ug[1], &ng) < 0) {
2336                 ug = xrealloc(ug, (1 + ng) * sizeof(ug[0]));
2337                 if (getgrouplist(user, pw->pw_gid, &ug[1], &ng) < 0)
2338                         perror_and_die("can't get groups of user '%s'", user);
2339         }
2340         ng++;
2341         ug[0] = pw->pw_uid;
2342
2343         /* How much do we need for "-Uxx,xx[,xx]..." string? */
2344         ug_str = xmalloc((sizeof(unsigned long)+1)*2 * ng + 3);
2345         gp = ug;
2346         sp = ug_str;
2347         *sp++ = 'U';
2348         *sp++ = '=';
2349         do {
2350                 sp += sprintf(sp, "%lx,", (unsigned long)(*gp++));
2351         } while (--ng);
2352         sp[-1] = '\0';
2353
2354         free(ug);
2355         return ug_str;
2356 }
2357
2358
2359 /* not static - don't inline me, compiler! */
2360 void readlink_self_exe(void);
2361 void readlink_self_exe(void)
2362 {
2363         char buf[PATH_MAX + 1];
2364         ssize_t sz = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
2365         if (sz < 0)
2366                 perror_and_die("readlink %s failed", "/proc/self/exe");
2367         buf[sz] = 0;
2368         self_exe_points_to = xstrdup(buf);
2369 }
2370
2371
2372 static void special_op(const char *arg) NORETURN;
2373 static void special_op(const char *arg)
2374 {
2375         static const user_req_header ureq = { NSCD_VERSION, SHUTDOWN, 0 };
2376
2377         struct sockaddr_un addr;
2378         int sock;
2379
2380         sock = socket(PF_UNIX, SOCK_STREAM, 0);
2381         if (sock < 0)
2382                 error_and_die("cannot create AF_UNIX socket");
2383
2384         addr.sun_family = AF_UNIX;
2385         strcpy(addr.sun_path, NSCD_SOCKET);
2386         if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
2387                 error_and_die("cannot connect to %s", NSCD_SOCKET);
2388
2389         if (!arg) { /* shutdown */
2390                 xfull_write(sock, &ureq, sizeof(ureq));
2391                 printf("sent shutdown request, exiting\n");
2392         } else { /* invalidate */
2393                 size_t arg_len = strlen(arg) + 1;
2394                 struct {
2395                         user_req_header req;
2396                         char arg[arg_len];
2397                 } reqdata;
2398                 reqdata.req.version = NSCD_VERSION;
2399                 reqdata.req.type = INVALIDATE;
2400                 reqdata.req.key_len = arg_len;
2401                 memcpy(reqdata.arg, arg, arg_len);
2402                 xfull_write(sock, &reqdata, arg_len + sizeof(ureq));
2403                 printf("sent invalidate(%s) request, exiting\n", arg);
2404         }
2405         exit(0);
2406 }
2407
2408
2409 /* Callback for glibc-2.15 */
2410 struct traced_file;
2411 static void do_nothing(size_t dbidx, struct traced_file *finfo)
2412 {
2413         /* nscd from glibc-2.15 does something like this:
2414         if (!dbs[dbidx].enabled || !dbs[dbidx].check_file)
2415                 return;
2416         add_file_to_watch_list(finfo->fname);
2417         */
2418 }
2419
2420 /* This internal glibc function is called to disable trying to contact nscd.
2421  * We _are_ nscd, so we need to do the lookups, and not recurse.
2422  * Until 2.14, this function was taking no parameters.
2423  * In 2.15, it takes a function pointer from hell.
2424  */
2425 void __nss_disable_nscd(void (*hell)(size_t, struct traced_file*));
2426
2427
2428 int main(int argc, char **argv)
2429 {
2430         int n;
2431         unsigned opt_d_cnt;
2432         const char *env_U;
2433         const char *conffile;
2434
2435         /* make sure we don't get recursive calls */
2436         __nss_disable_nscd(do_nothing);
2437
2438         if (argv[0][0] == 'w') /* "worker_nscd" */
2439                 worker(argv[1]);
2440
2441         setlinebuf(stdout);
2442         setlinebuf(stderr);
2443
2444         /* Make sure stdio is not closed */
2445         n = xopen3("/dev/null", O_RDWR, 0);
2446         while (n < 2)
2447                 n = dup(n);
2448         /* Close unexpected open file descriptors */
2449         n |= 0xff; /* start from at least fd# 255 */
2450         do {
2451                 close(n--);
2452         } while (n > 2);
2453
2454         /* For idiotic kernels which disallow "exec /proc/self/exe" */
2455         readlink_self_exe();
2456
2457         conffile = default_conffile;
2458         opt_d_cnt = 0;
2459         while ((n = getopt_long(argc, argv, "df:i:KVgt:", longopt, NULL)) != -1) {
2460                 switch (n) {
2461                 case 'd':
2462                         opt_d_cnt++;
2463                         debug &= ~D_DAEMON;
2464                         break;
2465                 case 'f':
2466                         conffile = optarg;
2467                         break;
2468                 case 'i':
2469                         /* invalidate */
2470                         special_op(optarg); /* exits */
2471                 case 'K':
2472                         /* shutdown server */
2473                         special_op(NULL); /* exits */
2474                 case 'V':
2475                         puts("unscd - nscd which does not hang, v."PROGRAM_VERSION);
2476                         exit(0);
2477                 case 'g':
2478                         exit(0);
2479                 case 't':
2480                         /* N threads */
2481                         max_reqnum = getnum(optarg);
2482                         break;
2483                 case 'S':
2484                         /* secure (?) */
2485                         break;
2486                 default:
2487                         print_help_and_die();
2488                 }
2489         }
2490         /* Multiple -d can bump debug regardless of nscd.conf:
2491          * no -d or -d: 0, -dd: 1,
2492          * -ddd: 3, -dddd: 7, -ddddd: 15
2493          */
2494         if (opt_d_cnt != 0)
2495                 debug |= (((1U << opt_d_cnt) >> 1) - 1) & L_ALL;
2496
2497         env_U = getenv("U");
2498         /* Avoid duplicate warnings if $U exists */
2499         parse_conffile(conffile, /* warn? */ (env_U == NULL));
2500
2501         /* I have a user report of (broken?) ldap nss library
2502          * opening and never closing a socket to a ldap server,
2503          * even across fork() and exec(). This messes up
2504          * worker child's operations for the reporter.
2505          *
2506          * This strenghtens my belief that nscd _must not_ trust
2507          * nss libs to be written correctly.
2508          *
2509          * Here, we need to jump through the hoops to guard against
2510          * such problems. If config file has server-user setting, we need
2511          * to setgroups + setuid. For that, we need to get uid and gid vector.
2512          * And that means possibly using buggy nss libs.
2513          * We will do it here, but then we will re-exec, passing uid+gids
2514          * in an environment variable.
2515          */
2516         if (!env_U && config.user) {
2517                 /* user_to_env_U() does getpwnam and getgrouplist */
2518                 if (putenv(user_to_env_U(config.user)))
2519                         error_and_die("out of memory");
2520                 /* fds leaked by nss will be closed by execed copy */
2521                 execv(self_exe_points_to, argv);
2522                 xexecve("/proc/self/exe", argv, environ);
2523         }
2524
2525         /* Allocate dynamically sized stuff */
2526         max_reqnum += 2; /* account for 2 first "fake" clients */
2527         if (max_reqnum < 8) max_reqnum = 8; /* sanitize */
2528         /* Since refcount is a byte, can't serve more than 255-2 clients
2529          * at once. The rest will block in connect() */
2530         if (max_reqnum > 0xff) max_reqnum = 0xff;
2531         client_buf = xzalloc(max_reqnum * sizeof(client_buf[0]));
2532         busy_cbuf  = xzalloc(max_reqnum * sizeof(busy_cbuf[0]));
2533         pfd        = xzalloc(max_reqnum * sizeof(pfd[0]));
2534         cinfo      = xzalloc(max_reqnum * sizeof(cinfo[0]));
2535
2536         cache_size = (config.size[0] + config.size[1] + config.size[2]) / 8;
2537         if (cache_size < 8) cache_size = 8; /* 8*8 = 64 entries min */
2538         if (cache_size > 0xffff) cache_size = 0xffff; /* 8*64k entries max */
2539         cache_size |= 1; /* force it to be odd */
2540         cache = xzalloc(cache_size * sizeof(cache[0]));
2541
2542         /* Register cleanup hooks */
2543         signal(SIGINT, cleanup_on_signal);
2544         signal(SIGTERM, cleanup_on_signal);
2545         /* Don't die if a client closes a socket on us */
2546         signal(SIGPIPE, SIG_IGN);
2547         /* Avoid creating zombies */
2548         signal(SIGCHLD, SIG_IGN);
2549 #if !DEBUG_BUILD
2550         /* Ensure workers don't have SIGALRM ignored */
2551         signal(SIGALRM, SIG_DFL);
2552 #endif
2553
2554         if (mkdir(NSCD_DIR, 0755) == 0) {
2555                 /* prevent bad mode of NSCD_DIR if umask is e.g. 077 */
2556                 chmod(NSCD_DIR, 0755);
2557         }
2558         pfd[0].fd = open_socket(NSCD_SOCKET);
2559         pfd[1].fd = open_socket(NSCD_SOCKET_OLD);
2560         pfd[0].events = POLLIN;
2561         pfd[1].events = POLLIN;
2562
2563         if (debug & D_DAEMON) {
2564                 daemon(/*nochdir*/ 1, /*noclose*/ 0);
2565                 if (config.logfile) {
2566                         /* nochdir=1: relative paths still work as expected */
2567                         xmovefd(xopen3(config.logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666), 2);
2568                         debug |= D_STAMP;
2569                 } else {
2570                         debug = 0; /* why bother? it's /dev/null'ed anyway */
2571                 }
2572                 chdir("/"); /* compat */
2573                 write_pid();
2574                 setsid();
2575                 /* ignore job control signals */
2576                 signal(SIGTTOU, SIG_IGN);
2577                 signal(SIGTTIN, SIG_IGN);
2578                 signal(SIGTSTP, SIG_IGN);
2579         }
2580
2581         log(L_ALL, "unscd v" PROGRAM_VERSION ", debug level 0x%x", debug & L_ALL);
2582         log(L_DEBUG, "max %u requests in parallel", max_reqnum - 2);
2583         log(L_DEBUG, "cache size %u x 8 entries", cache_size);
2584
2585         if (env_U) {
2586                 int size;
2587                 gid_t *ug = env_U_to_uid_and_gids(env_U, &size);
2588                 if (size > 1)
2589                         if (setgroups(size - 1, &ug[1]) || setgid(ug[1]))
2590                                 perror_and_die("cannot set groups for user '%s'", config.user);
2591                 if (size > 0)
2592                         if (setuid(ug[0]))
2593                                 perror_and_die("cannot set uid to %u", (unsigned)(ug[0]));
2594                 free(ug);
2595         }
2596
2597         for (n = 0; n < 3; n++) {
2598                 log(L_DEBUG, "%s cache enabled:%u pttl:%u nttl:%u",
2599                                 srv_name[n],
2600                                 config.srv_enable[n],
2601                                 config.pttl[n],
2602                                 config.nttl[n]);
2603                 config.pttl[n] *= 1000;
2604                 config.nttl[n] *= 1000;
2605         }
2606
2607         main_loop();
2608
2609         return 0;
2610 }