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