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