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