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