Annotation of embedaddon/dnsmasq/src/dnsmasq.c, revision 1.1.1.3
1.1.1.3 ! misho 1: /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
1.1 misho 2:
3: This program is free software; you can redistribute it and/or modify
4: it under the terms of the GNU General Public License as published by
5: the Free Software Foundation; version 2 dated June, 1991, or
6: (at your option) version 3 dated 29 June, 2007.
7:
8: This program 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 should have received a copy of the GNU General Public License
14: along with this program. If not, see <http://www.gnu.org/licenses/>.
15: */
16:
17: /* Declare static char *compiler_opts in config.h */
18: #define DNSMASQ_COMPILE_OPTS
19:
20: #include "dnsmasq.h"
21:
22: struct daemon *daemon;
23:
24: static volatile pid_t pid = 0;
25: static volatile int pipewrite;
26:
1.1.1.3 ! misho 27: static int set_dns_listeners(time_t now);
! 28: static void check_dns_listeners(time_t now);
1.1 misho 29: static void sig_handler(int sig);
30: static void async_event(int pipe, time_t now);
31: static void fatal_event(struct event_desc *ev, char *msg);
32: static int read_event(int fd, struct event_desc *evp, char **msg);
1.1.1.3 ! misho 33: static void poll_resolv(int force, int do_reload, time_t now);
1.1 misho 34:
35: int main (int argc, char **argv)
36: {
37: int bind_fallback = 0;
38: time_t now;
39: struct sigaction sigact;
40: struct iname *if_tmp;
41: int piperead, pipefd[2], err_pipe[2];
42: struct passwd *ent_pw = NULL;
43: #if defined(HAVE_SCRIPT)
44: uid_t script_uid = 0;
45: gid_t script_gid = 0;
46: #endif
47: struct group *gp = NULL;
48: long i, max_fd = sysconf(_SC_OPEN_MAX);
49: char *baduser = NULL;
50: int log_err;
51: #if defined(HAVE_LINUX_NETWORK)
52: cap_user_header_t hdr = NULL;
53: cap_user_data_t data = NULL;
1.1.1.2 misho 54: char *bound_device = NULL;
55: int did_bind = 0;
1.1 misho 56: #endif
1.1.1.2 misho 57: #if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
1.1 misho 58: struct dhcp_context *context;
1.1.1.2 misho 59: struct dhcp_relay *relay;
60: #endif
1.1.1.3 ! misho 61: #ifdef HAVE_TFTP
! 62: int tftp_prefix_missing = 0;
! 63: #endif
1.1 misho 64:
65: #ifdef LOCALEDIR
66: setlocale(LC_ALL, "");
67: bindtextdomain("dnsmasq", LOCALEDIR);
68: textdomain("dnsmasq");
69: #endif
70:
71: sigact.sa_handler = sig_handler;
72: sigact.sa_flags = 0;
73: sigemptyset(&sigact.sa_mask);
74: sigaction(SIGUSR1, &sigact, NULL);
75: sigaction(SIGUSR2, &sigact, NULL);
76: sigaction(SIGHUP, &sigact, NULL);
77: sigaction(SIGTERM, &sigact, NULL);
78: sigaction(SIGALRM, &sigact, NULL);
79: sigaction(SIGCHLD, &sigact, NULL);
80:
81: /* ignore SIGPIPE */
82: sigact.sa_handler = SIG_IGN;
83: sigaction(SIGPIPE, &sigact, NULL);
84:
85: umask(022); /* known umask, create leases and pid files as 0644 */
1.1.1.3 ! misho 86:
! 87: rand_init(); /* Must precede read_opts() */
! 88:
1.1 misho 89: read_opts(argc, argv, compile_opts);
1.1.1.2 misho 90:
1.1 misho 91: if (daemon->edns_pktsz < PACKETSZ)
92: daemon->edns_pktsz = PACKETSZ;
1.1.1.2 misho 93:
1.1.1.3 ! misho 94: /* Min buffer size: we check after adding each record, so there must be
! 95: memory for the largest packet, and the largest record so the
! 96: min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
! 97: This might be increased is EDNS packet size if greater than the minimum. */
! 98: daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
1.1 misho 99: daemon->packet = safe_malloc(daemon->packet_buff_sz);
1.1.1.2 misho 100:
1.1 misho 101: daemon->addrbuff = safe_malloc(ADDRSTRLEN);
1.1.1.3 ! misho 102: if (option_bool(OPT_EXTRALOG))
! 103: daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
1.1.1.2 misho 104:
105: #ifdef HAVE_DNSSEC
106: if (option_bool(OPT_DNSSEC_VALID))
107: {
1.1.1.3 ! misho 108: /* Note that both /000 and '.' are allowed within labels. These get
! 109: represented in presentation format using NAME_ESCAPE as an escape
! 110: character when in DNSSEC mode.
! 111: In theory, if all the characters in a name were /000 or
! 112: '.' or NAME_ESCAPE then all would have to be escaped, so the
! 113: presentation format would be twice as long as the spec.
! 114:
! 115: daemon->namebuff was previously allocated by the option-reading
! 116: code before we knew if we're in DNSSEC mode, so reallocate here. */
! 117: free(daemon->namebuff);
! 118: daemon->namebuff = safe_malloc(MAXDNAME * 2);
! 119: daemon->keyname = safe_malloc(MAXDNAME * 2);
! 120: daemon->workspacename = safe_malloc(MAXDNAME * 2);
1.1.1.2 misho 121: }
122: #endif
1.1 misho 123:
124: #ifdef HAVE_DHCP
125: if (!daemon->lease_file)
126: {
127: if (daemon->dhcp || daemon->dhcp6)
128: daemon->lease_file = LEASEFILE;
129: }
130: #endif
131:
132: /* Close any file descriptors we inherited apart from std{in|out|err}
133:
134: Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
135: otherwise file descriptors we create can end up being 0, 1, or 2
136: and then get accidentally closed later when we make 0, 1, and 2
137: open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
138: but it's not guaranteed. By opening /dev/null three times, we
139: ensure that we're not using those fds for real stuff. */
140: for (i = 0; i < max_fd; i++)
141: if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
142: close(i);
143: else
144: open("/dev/null", O_RDWR);
145:
146: #ifndef HAVE_LINUX_NETWORK
147: # if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
148: if (!option_bool(OPT_NOWILD))
149: {
150: bind_fallback = 1;
151: set_option_bool(OPT_NOWILD);
152: }
153: # endif
154:
155: /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
156: if (option_bool(OPT_CLEVERBIND))
157: {
158: bind_fallback = 1;
159: set_option_bool(OPT_NOWILD);
160: reset_option_bool(OPT_CLEVERBIND);
161: }
162: #endif
1.1.1.3 ! misho 163:
! 164: #ifndef HAVE_INOTIFY
! 165: if (daemon->dynamic_dirs)
! 166: die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
! 167: #endif
1.1 misho 168:
1.1.1.2 misho 169: if (option_bool(OPT_DNSSEC_VALID))
170: {
171: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho 172: struct ds_config *ds;
! 173:
! 174: /* Must have at least a root trust anchor, or the DNSSEC code
! 175: can loop forever. */
! 176: for (ds = daemon->ds; ds; ds = ds->next)
! 177: if (ds->name[0] == 0)
! 178: break;
! 179:
! 180: if (!ds)
! 181: die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
1.1.1.2 misho 182:
183: if (daemon->cachesize < CACHESIZ)
1.1.1.3 ! misho 184: die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
1.1.1.2 misho 185: #else
186: die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
187: #endif
188: }
189:
1.1 misho 190: #ifndef HAVE_TFTP
191: if (option_bool(OPT_TFTP))
192: die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
193: #endif
194:
195: #ifdef HAVE_CONNTRACK
196: if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
1.1.1.3 ! misho 197: die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
1.1 misho 198: #else
199: if (option_bool(OPT_CONNTRACK))
1.1.1.3 ! misho 200: die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
1.1 misho 201: #endif
202:
203: #ifdef HAVE_SOLARIS_NETWORK
204: if (daemon->max_logs != 0)
205: die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
206: #endif
207:
208: #ifdef __ANDROID__
209: if (daemon->max_logs != 0)
210: die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
211: #endif
212:
213: #ifndef HAVE_AUTH
214: if (daemon->authserver)
215: die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
216: #endif
217:
1.1.1.3 ! misho 218: #ifndef HAVE_LOOP
! 219: if (option_bool(OPT_LOOP_DETECT))
! 220: die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
! 221: #endif
! 222:
! 223: if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
! 224: daemon->min_port = 1024u;
! 225:
! 226: if (daemon->max_port < daemon->min_port)
! 227: die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
! 228:
1.1 misho 229: now = dnsmasq_time();
230:
231: /* Create a serial at startup if not configured. */
232: if (daemon->authinterface && daemon->soa_sn == 0)
233: #ifdef HAVE_BROKEN_RTC
234: die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
235: #else
236: daemon->soa_sn = now;
237: #endif
238:
1.1.1.2 misho 239: #ifdef HAVE_DHCP6
240: if (daemon->dhcp6)
241: {
242: daemon->doing_ra = option_bool(OPT_RA);
1.1 misho 243:
1.1.1.2 misho 244: for (context = daemon->dhcp6; context; context = context->next)
1.1 misho 245: {
1.1.1.2 misho 246: if (context->flags & CONTEXT_DHCP)
247: daemon->doing_dhcp6 = 1;
248: if (context->flags & CONTEXT_RA)
249: daemon->doing_ra = 1;
250: #if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
251: if (context->flags & CONTEXT_TEMPLATE)
252: die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
1.1 misho 253: #endif
254: }
1.1.1.2 misho 255: }
256: #endif
257:
258: #ifdef HAVE_DHCP
259: /* Note that order matters here, we must call lease_init before
260: creating any file descriptors which shouldn't be leaked
261: to the lease-script init process. We need to call common_init
1.1.1.3 ! misho 262: before lease_init to allocate buffers it uses.
! 263: The script subsystem relies on DHCP buffers, hence the last two
! 264: conditions below. */
! 265: if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
! 266: daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
1.1.1.2 misho 267: {
268: dhcp_common_init();
1.1 misho 269: if (daemon->dhcp || daemon->doing_dhcp6)
1.1.1.2 misho 270: lease_init(now);
271: }
272:
273: if (daemon->dhcp || daemon->relay4)
274: dhcp_init();
275:
1.1 misho 276: # ifdef HAVE_DHCP6
1.1.1.2 misho 277: if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
278: ra_init(now);
279:
280: if (daemon->doing_dhcp6 || daemon->relay6)
281: dhcp6_init();
1.1 misho 282: # endif
283:
284: #endif
285:
286: #ifdef HAVE_IPSET
287: if (daemon->ipsets)
288: ipset_init();
289: #endif
290:
1.1.1.2 misho 291: #if defined(HAVE_LINUX_NETWORK)
1.1 misho 292: netlink_init();
1.1.1.2 misho 293: #elif defined(HAVE_BSD_NETWORK)
294: route_init();
1.1 misho 295: #endif
296:
1.1.1.2 misho 297: if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
298: die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
299:
300: if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
1.1 misho 301: die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
302:
303: if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
304: {
305: create_bound_listeners(1);
306:
307: if (!option_bool(OPT_CLEVERBIND))
308: for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
309: if (if_tmp->name && !if_tmp->used)
310: die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
311:
312: #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
313: /* after enumerate_interfaces() */
1.1.1.2 misho 314: bound_device = whichdevice();
315:
1.1 misho 316: if (daemon->dhcp)
317: {
1.1.1.2 misho 318: if (!daemon->relay4 && bound_device)
319: {
320: bindtodevice(bound_device, daemon->dhcpfd);
321: did_bind = 1;
322: }
323: if (daemon->enable_pxe && bound_device)
324: {
325: bindtodevice(bound_device, daemon->pxefd);
326: did_bind = 1;
327: }
1.1 misho 328: }
329: #endif
330:
331: #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
1.1.1.2 misho 332: if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
333: {
334: bindtodevice(bound_device, daemon->dhcp6fd);
335: did_bind = 1;
336: }
1.1 misho 337: #endif
338: }
339: else
340: create_wildcard_listeners();
341:
342: #ifdef HAVE_DHCP6
343: /* after enumerate_interfaces() */
1.1.1.2 misho 344: if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1.1 misho 345: join_multicast(1);
1.1.1.2 misho 346:
347: /* After netlink_init() and before create_helper() */
348: lease_make_duid(now);
1.1 misho 349: #endif
350:
351: if (daemon->port != 0)
1.1.1.2 misho 352: {
353: cache_init();
1.1.1.3 ! misho 354:
1.1.1.2 misho 355: #ifdef HAVE_DNSSEC
356: blockdata_init();
357: #endif
358: }
1.1.1.3 ! misho 359:
! 360: #ifdef HAVE_INOTIFY
! 361: if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
! 362: inotify_dnsmasq_init();
! 363: else
! 364: daemon->inotifyfd = -1;
! 365: #endif
! 366:
1.1 misho 367: if (option_bool(OPT_DBUS))
368: #ifdef HAVE_DBUS
369: {
370: char *err;
371: daemon->dbus = NULL;
372: daemon->watches = NULL;
373: if ((err = dbus_init()))
374: die(_("DBus error: %s"), err, EC_MISC);
375: }
376: #else
377: die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
378: #endif
1.1.1.3 ! misho 379:
1.1 misho 380: if (daemon->port != 0)
381: pre_allocate_sfds();
382:
383: #if defined(HAVE_SCRIPT)
384: /* Note getpwnam returns static storage */
385: if ((daemon->dhcp || daemon->dhcp6) &&
386: daemon->scriptuser &&
387: (daemon->lease_change_command || daemon->luascript))
388: {
389: if ((ent_pw = getpwnam(daemon->scriptuser)))
390: {
391: script_uid = ent_pw->pw_uid;
392: script_gid = ent_pw->pw_gid;
393: }
394: else
395: baduser = daemon->scriptuser;
396: }
397: #endif
398:
399: if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
400: baduser = daemon->username;
401: else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
402: baduser = daemon->groupname;
403:
404: if (baduser)
405: die(_("unknown user or group: %s"), baduser, EC_BADCONF);
1.1.1.3 ! misho 406:
1.1 misho 407: /* implement group defaults, "dip" if available, or group associated with uid */
408: if (!daemon->group_set && !gp)
409: {
410: if (!(gp = getgrnam(CHGRP)) && ent_pw)
411: gp = getgrgid(ent_pw->pw_gid);
412:
413: /* for error message */
414: if (gp)
415: daemon->groupname = gp->gr_name;
416: }
417:
418: #if defined(HAVE_LINUX_NETWORK)
419: /* determine capability API version here, while we can still
420: call safe_malloc */
421: if (ent_pw && ent_pw->pw_uid != 0)
422: {
423: int capsize = 1; /* for header version 1 */
424: hdr = safe_malloc(sizeof(*hdr));
425:
426: /* find version supported by kernel */
427: memset(hdr, 0, sizeof(*hdr));
428: capget(hdr, NULL);
429:
430: if (hdr->version != LINUX_CAPABILITY_VERSION_1)
431: {
432: /* if unknown version, use largest supported version (3) */
433: if (hdr->version != LINUX_CAPABILITY_VERSION_2)
434: hdr->version = LINUX_CAPABILITY_VERSION_3;
435: capsize = 2;
436: }
437:
438: data = safe_malloc(sizeof(*data) * capsize);
439: memset(data, 0, sizeof(*data) * capsize);
440: }
441: #endif
442:
443: /* Use a pipe to carry signals and other events back to the event loop
444: in a race-free manner and another to carry errors to daemon-invoking process */
445: safe_pipe(pipefd, 1);
446:
447: piperead = pipefd[0];
448: pipewrite = pipefd[1];
449: /* prime the pipe to load stuff first time. */
1.1.1.2 misho 450: send_event(pipewrite, EVENT_INIT, 0, NULL);
1.1 misho 451:
452: err_pipe[1] = -1;
453:
454: if (!option_bool(OPT_DEBUG))
455: {
456: /* The following code "daemonizes" the process.
457: See Stevens section 12.4 */
458:
459: if (chdir("/") != 0)
460: die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
461:
462: #ifndef NO_FORK
463: if (!option_bool(OPT_NO_FORK))
464: {
465: pid_t pid;
466:
467: /* pipe to carry errors back to original process.
468: When startup is complete we close this and the process terminates. */
469: safe_pipe(err_pipe, 0);
470:
471: if ((pid = fork()) == -1)
472: /* fd == -1 since we've not forked, never returns. */
473: send_event(-1, EVENT_FORK_ERR, errno, NULL);
474:
475: if (pid != 0)
476: {
477: struct event_desc ev;
478: char *msg;
479:
480: /* close our copy of write-end */
1.1.1.3 ! misho 481: while (retry_send(close(err_pipe[1])));
1.1 misho 482:
483: /* check for errors after the fork */
484: if (read_event(err_pipe[0], &ev, &msg))
485: fatal_event(&ev, msg);
486:
487: _exit(EC_GOOD);
488: }
489:
1.1.1.3 ! misho 490: while (retry_send(close(err_pipe[0])));
1.1 misho 491:
492: /* NO calls to die() from here on. */
493:
494: setsid();
495:
496: if ((pid = fork()) == -1)
497: send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
498:
499: if (pid != 0)
500: _exit(0);
501: }
502: #endif
503:
504: /* write pidfile _after_ forking ! */
505: if (daemon->runfile)
506: {
507: int fd, err = 0;
508:
509: sprintf(daemon->namebuff, "%d\n", (int) getpid());
510:
511: /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
512: in a directory which is writable by the non-privileged user that dnsmasq runs as. This
513: allows the daemon to delete the file as part of its shutdown. This is a security hole to the
514: extent that an attacker running as the unprivileged user could replace the pidfile with a
515: symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
516:
517: The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
518: ensuring that the open() fails should there be any existing file (because the unlink() failed,
519: or an attacker exploited the race between unlink() and open()). This ensures that no symlink
520: attack can succeed.
521:
522: Any compromise of the non-privileged user still theoretically allows the pid-file to be
523: replaced whilst dnsmasq is running. The worst that could allow is that the usual
524: "shutdown dnsmasq" shell command could be tricked into stopping any other process.
525:
526: Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
527: failure to write the pid-file.
528: */
529:
530: unlink(daemon->runfile);
531:
532: if ((fd = open(daemon->runfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1)
533: {
534: /* only complain if started as root */
535: if (getuid() == 0)
536: err = 1;
537: }
538: else
539: {
540: if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
541: err = 1;
1.1.1.3 ! misho 542: else
! 543: {
! 544: while (retry_send(close(fd)));
! 545: if (errno != 0)
! 546: err = 1;
! 547: }
1.1 misho 548: }
549:
550: if (err)
551: {
552: send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
553: _exit(0);
554: }
555: }
556: }
557:
558: log_err = log_start(ent_pw, err_pipe[1]);
559:
560: if (!option_bool(OPT_DEBUG))
561: {
562: /* open stdout etc to /dev/null */
563: int nullfd = open("/dev/null", O_RDWR);
1.1.1.3 ! misho 564: if (nullfd != -1)
! 565: {
! 566: dup2(nullfd, STDOUT_FILENO);
! 567: dup2(nullfd, STDERR_FILENO);
! 568: dup2(nullfd, STDIN_FILENO);
! 569: close(nullfd);
! 570: }
1.1 misho 571: }
572:
573: /* if we are to run scripts, we need to fork a helper before dropping root. */
574: daemon->helperfd = -1;
575: #ifdef HAVE_SCRIPT
1.1.1.3 ! misho 576: if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
! 577: (daemon->lease_change_command || daemon->luascript))
! 578: daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
1.1 misho 579: #endif
580:
581: if (!option_bool(OPT_DEBUG) && getuid() == 0)
582: {
583: int bad_capabilities = 0;
584: gid_t dummy;
585:
586: /* remove all supplimentary groups */
587: if (gp &&
588: (setgroups(0, &dummy) == -1 ||
589: setgid(gp->gr_gid) == -1))
590: {
591: send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
592: _exit(0);
593: }
594:
595: if (ent_pw && ent_pw->pw_uid != 0)
596: {
597: #if defined(HAVE_LINUX_NETWORK)
598: /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
599: CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
600: ports because of DAD, or we're doing it dynamically,
601: we need CAP_NET_BIND_SERVICE too. */
602: if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
603: data->effective = data->permitted = data->inheritable =
604: (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
605: (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
606: else
607: data->effective = data->permitted = data->inheritable =
608: (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
609:
610: /* Tell kernel to not clear capabilities when dropping root */
611: if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
612: bad_capabilities = errno;
613:
614: #elif defined(HAVE_SOLARIS_NETWORK)
615: /* http://developers.sun.com/solaris/articles/program_privileges.html */
616: priv_set_t *priv_set;
617:
618: if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
619: priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
620: priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
621: bad_capabilities = errno;
622:
623: if (priv_set && bad_capabilities == 0)
624: {
625: priv_inverse(priv_set);
626:
627: if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
628: bad_capabilities = errno;
629: }
630:
631: if (priv_set)
632: priv_freeset(priv_set);
633:
634: #endif
635:
636: if (bad_capabilities != 0)
637: {
638: send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
639: _exit(0);
640: }
641:
642: /* finally drop root */
643: if (setuid(ent_pw->pw_uid) == -1)
644: {
645: send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
646: _exit(0);
647: }
648:
649: #ifdef HAVE_LINUX_NETWORK
650: if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
651: data->effective = data->permitted =
652: (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
653: else
654: data->effective = data->permitted =
655: (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
656: data->inheritable = 0;
657:
658: /* lose the setuid and setgid capbilities */
659: if (capset(hdr, data) == -1)
660: {
661: send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
662: _exit(0);
663: }
664: #endif
665:
666: }
667: }
668:
669: #ifdef HAVE_LINUX_NETWORK
1.1.1.3 ! misho 670: free(hdr);
! 671: free(data);
1.1 misho 672: if (option_bool(OPT_DEBUG))
673: prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
674: #endif
675:
676: #ifdef HAVE_TFTP
1.1.1.3 ! misho 677: if (option_bool(OPT_TFTP))
1.1 misho 678: {
679: DIR *dir;
680: struct tftp_prefix *p;
681:
682: if (daemon->tftp_prefix)
683: {
684: if (!((dir = opendir(daemon->tftp_prefix))))
685: {
1.1.1.3 ! misho 686: tftp_prefix_missing = 1;
! 687: if (!option_bool(OPT_TFTP_NO_FAIL))
! 688: {
! 689: send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
! 690: _exit(0);
! 691: }
1.1 misho 692: }
1.1.1.3 ! misho 693: else
! 694: closedir(dir);
1.1 misho 695: }
696:
697: for (p = daemon->if_prefix; p; p = p->next)
698: {
1.1.1.3 ! misho 699: p->missing = 0;
1.1 misho 700: if (!((dir = opendir(p->prefix))))
1.1.1.3 ! misho 701: {
! 702: p->missing = 1;
! 703: if (!option_bool(OPT_TFTP_NO_FAIL))
! 704: {
! 705: send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
! 706: _exit(0);
! 707: }
! 708: }
! 709: else
! 710: closedir(dir);
1.1 misho 711: }
712: }
713: #endif
714:
715: if (daemon->port == 0)
716: my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
717: else if (daemon->cachesize != 0)
718: my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
719: else
720: my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
721:
722: my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
723:
724: #ifdef HAVE_DBUS
725: if (option_bool(OPT_DBUS))
726: {
727: if (daemon->dbus)
728: my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
729: else
730: my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
731: }
732: #endif
733:
1.1.1.2 misho 734: if (option_bool(OPT_LOCAL_SERVICE))
735: my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
736:
737: #ifdef HAVE_DNSSEC
738: if (option_bool(OPT_DNSSEC_VALID))
739: {
1.1.1.3 ! misho 740: int rc;
! 741:
! 742: /* Delay creating the timestamp file until here, after we've changed user, so that
! 743: it has the correct owner to allow updating the mtime later.
! 744: This means we have to report fatal errors via the pipe. */
! 745: if ((rc = setup_timestamp()) == -1)
! 746: {
! 747: send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
! 748: _exit(0);
! 749: }
! 750:
1.1.1.2 misho 751: my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
1.1.1.3 ! misho 752:
1.1.1.2 misho 753: if (option_bool(OPT_DNSSEC_TIME))
754: my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
1.1.1.3 ! misho 755:
! 756: if (rc == 1)
! 757: my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
1.1.1.2 misho 758: }
759: #endif
760:
1.1 misho 761: if (log_err != 0)
762: my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
763: daemon->log_file, strerror(log_err));
1.1.1.2 misho 764:
1.1 misho 765: if (bind_fallback)
766: my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
1.1.1.2 misho 767:
768: if (option_bool(OPT_NOWILD))
769: warn_bound_listeners();
770:
771: warn_int_names();
1.1 misho 772:
773: if (!option_bool(OPT_NOWILD))
774: for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
775: if (if_tmp->name && !if_tmp->used)
776: my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
777:
778: if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
779: {
780: if (daemon->resolv_files && !daemon->resolv_files->is_default)
781: my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
782: daemon->resolv_files = NULL;
783: if (!daemon->servers)
784: my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
785: }
786:
787: if (daemon->max_logs != 0)
788: my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
789:
790:
791: #ifdef HAVE_DHCP
792: for (context = daemon->dhcp; context; context = context->next)
793: log_context(AF_INET, context);
794:
1.1.1.2 misho 795: for (relay = daemon->relay4; relay; relay = relay->next)
796: log_relay(AF_INET, relay);
797:
1.1 misho 798: # ifdef HAVE_DHCP6
799: for (context = daemon->dhcp6; context; context = context->next)
800: log_context(AF_INET6, context);
801:
1.1.1.2 misho 802: for (relay = daemon->relay6; relay; relay = relay->next)
803: log_relay(AF_INET6, relay);
804:
1.1 misho 805: if (daemon->doing_dhcp6 || daemon->doing_ra)
806: dhcp_construct_contexts(now);
807:
808: if (option_bool(OPT_RA))
809: my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
810: # endif
811:
1.1.1.2 misho 812: # ifdef HAVE_LINUX_NETWORK
813: if (did_bind)
814: my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
815: # endif
816:
1.1 misho 817: /* after dhcp_contruct_contexts */
818: if (daemon->dhcp || daemon->doing_dhcp6)
819: lease_find_interfaces(now);
820: #endif
821:
822: #ifdef HAVE_TFTP
1.1.1.3 ! misho 823: if (option_bool(OPT_TFTP))
1.1 misho 824: {
1.1.1.3 ! misho 825: struct tftp_prefix *p;
1.1 misho 826:
827: my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
828: daemon->tftp_prefix ? _("root is ") : _("enabled"),
829: daemon->tftp_prefix ? daemon->tftp_prefix: "",
830: option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
1.1.1.3 ! misho 831:
! 832: if (tftp_prefix_missing)
! 833: my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
! 834:
! 835: for (p = daemon->if_prefix; p; p = p->next)
! 836: if (p->missing)
! 837: my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
! 838:
1.1 misho 839: /* This is a guess, it assumes that for small limits,
840: disjoint files might be served, but for large limits,
841: a single file will be sent to may clients (the file only needs
842: one fd). */
843:
844: max_fd -= 30; /* use other than TFTP */
845:
846: if (max_fd < 0)
847: max_fd = 5;
848: else if (max_fd < 100)
849: max_fd = max_fd/2;
850: else
851: max_fd = max_fd - 20;
852:
853: /* if we have to use a limited range of ports,
854: that will limit the number of transfers */
855: if (daemon->start_tftp_port != 0 &&
856: daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
857: max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
858:
859: if (daemon->tftp_max > max_fd)
860: {
861: daemon->tftp_max = max_fd;
862: my_syslog(MS_TFTP | LOG_WARNING,
863: _("restricting maximum simultaneous TFTP transfers to %d"),
864: daemon->tftp_max);
865: }
866: }
867: #endif
868:
869: /* finished start-up - release original process */
870: if (err_pipe[1] != -1)
1.1.1.3 ! misho 871: while (retry_send(close(err_pipe[1])));
1.1 misho 872:
873: if (daemon->port != 0)
874: check_servers();
875:
876: pid = getpid();
877:
1.1.1.3 ! misho 878: #ifdef HAVE_INOTIFY
! 879: /* Using inotify, have to select a resolv file at startup */
! 880: poll_resolv(1, 0, now);
! 881: #endif
! 882:
1.1 misho 883: while (1)
884: {
1.1.1.3 ! misho 885: int t, timeout = -1;
! 886:
! 887: poll_reset();
1.1 misho 888:
889: /* if we are out of resources, find how long we have to wait
890: for some to come free, we'll loop around then and restart
891: listening for queries */
1.1.1.3 ! misho 892: if ((t = set_dns_listeners(now)) != 0)
! 893: timeout = t * 1000;
1.1 misho 894:
895: /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
896: if (daemon->tftp_trans ||
897: (option_bool(OPT_DBUS) && !daemon->dbus))
1.1.1.3 ! misho 898: timeout = 250;
! 899:
1.1 misho 900: /* Wake every second whilst waiting for DAD to complete */
901: else if (is_dad_listeners())
1.1.1.3 ! misho 902: timeout = 1000;
1.1 misho 903:
904: #ifdef HAVE_DBUS
1.1.1.3 ! misho 905: set_dbus_listeners();
1.1 misho 906: #endif
907:
908: #ifdef HAVE_DHCP
1.1.1.2 misho 909: if (daemon->dhcp || daemon->relay4)
1.1 misho 910: {
1.1.1.3 ! misho 911: poll_listen(daemon->dhcpfd, POLLIN);
1.1 misho 912: if (daemon->pxefd != -1)
1.1.1.3 ! misho 913: poll_listen(daemon->pxefd, POLLIN);
1.1 misho 914: }
915: #endif
916:
917: #ifdef HAVE_DHCP6
1.1.1.2 misho 918: if (daemon->doing_dhcp6 || daemon->relay6)
1.1.1.3 ! misho 919: poll_listen(daemon->dhcp6fd, POLLIN);
! 920:
1.1 misho 921: if (daemon->doing_ra)
1.1.1.3 ! misho 922: poll_listen(daemon->icmp6fd, POLLIN);
! 923: #endif
! 924:
! 925: #ifdef HAVE_INOTIFY
! 926: if (daemon->inotifyfd != -1)
! 927: poll_listen(daemon->inotifyfd, POLLIN);
1.1 misho 928: #endif
929:
1.1.1.2 misho 930: #if defined(HAVE_LINUX_NETWORK)
1.1.1.3 ! misho 931: poll_listen(daemon->netlinkfd, POLLIN);
1.1.1.2 misho 932: #elif defined(HAVE_BSD_NETWORK)
1.1.1.3 ! misho 933: poll_listen(daemon->routefd, POLLIN);
1.1 misho 934: #endif
1.1.1.3 ! misho 935:
! 936: poll_listen(piperead, POLLIN);
1.1.1.2 misho 937:
1.1.1.3 ! misho 938: #ifdef HAVE_SCRIPT
! 939: # ifdef HAVE_DHCP
! 940: while (helper_buf_empty() && do_script_run(now));
! 941: # endif
1.1 misho 942:
1.1.1.3 ! misho 943: /* Refresh cache */
! 944: if (option_bool(OPT_SCRIPT_ARP))
! 945: find_mac(NULL, NULL, 0, now);
! 946: while (helper_buf_empty() && do_arp_script_run());
1.1 misho 947:
948: # ifdef HAVE_TFTP
949: while (helper_buf_empty() && do_tftp_script_run());
950: # endif
951:
952: if (!helper_buf_empty())
1.1.1.3 ! misho 953: poll_listen(daemon->helperfd, POLLOUT);
! 954: #else
1.1 misho 955: /* need this for other side-effects */
1.1.1.3 ! misho 956: # ifdef HAVE_DHCP
1.1 misho 957: while (do_script_run(now));
1.1.1.3 ! misho 958: # endif
! 959:
! 960: while (do_arp_script_run());
1.1 misho 961:
962: # ifdef HAVE_TFTP
963: while (do_tftp_script_run());
964: # endif
965:
966: #endif
1.1.1.3 ! misho 967:
1.1 misho 968:
969: /* must do this just before select(), when we know no
970: more calls to my_syslog() can occur */
1.1.1.3 ! misho 971: set_log_writer();
! 972:
! 973: if (do_poll(timeout) < 0)
! 974: continue;
1.1 misho 975:
976: now = dnsmasq_time();
977:
1.1.1.3 ! misho 978: check_log_writer(0);
1.1.1.2 misho 979:
980: /* prime. */
981: enumerate_interfaces(1);
982:
1.1 misho 983: /* Check the interfaces to see if any have exited DAD state
984: and if so, bind the address. */
985: if (is_dad_listeners())
986: {
1.1.1.2 misho 987: enumerate_interfaces(0);
1.1 misho 988: /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
989: create_bound_listeners(0);
1.1.1.2 misho 990: warn_bound_listeners();
1.1 misho 991: }
992:
1.1.1.2 misho 993: #if defined(HAVE_LINUX_NETWORK)
1.1.1.3 ! misho 994: if (poll_check(daemon->netlinkfd, POLLIN))
! 995: netlink_multicast();
1.1.1.2 misho 996: #elif defined(HAVE_BSD_NETWORK)
1.1.1.3 ! misho 997: if (poll_check(daemon->routefd, POLLIN))
! 998: route_sock();
1.1 misho 999: #endif
1000:
1.1.1.3 ! misho 1001: #ifdef HAVE_INOTIFY
! 1002: if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
! 1003: {
! 1004: if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
! 1005: poll_resolv(1, 1, now);
! 1006: }
! 1007: #else
1.1 misho 1008: /* Check for changes to resolv files once per second max. */
1009: /* Don't go silent for long periods if the clock goes backwards. */
1010: if (daemon->last_resolv == 0 ||
1011: difftime(now, daemon->last_resolv) > 1.0 ||
1012: difftime(now, daemon->last_resolv) < -1.0)
1013: {
1014: /* poll_resolv doesn't need to reload first time through, since
1015: that's queued anyway. */
1016:
1017: poll_resolv(0, daemon->last_resolv != 0, now);
1018: daemon->last_resolv = now;
1019: }
1.1.1.3 ! misho 1020: #endif
! 1021:
! 1022: if (poll_check(piperead, POLLIN))
1.1 misho 1023: async_event(piperead, now);
1024:
1025: #ifdef HAVE_DBUS
1026: /* if we didn't create a DBus connection, retry now. */
1027: if (option_bool(OPT_DBUS) && !daemon->dbus)
1028: {
1029: char *err;
1030: if ((err = dbus_init()))
1031: my_syslog(LOG_WARNING, _("DBus error: %s"), err);
1032: if (daemon->dbus)
1033: my_syslog(LOG_INFO, _("connected to system DBus"));
1034: }
1.1.1.3 ! misho 1035: check_dbus_listeners();
1.1 misho 1036: #endif
1037:
1.1.1.3 ! misho 1038: check_dns_listeners(now);
1.1 misho 1039:
1040: #ifdef HAVE_TFTP
1.1.1.3 ! misho 1041: check_tftp_listeners(now);
1.1 misho 1042: #endif
1043:
1044: #ifdef HAVE_DHCP
1.1.1.2 misho 1045: if (daemon->dhcp || daemon->relay4)
1.1 misho 1046: {
1.1.1.3 ! misho 1047: if (poll_check(daemon->dhcpfd, POLLIN))
1.1 misho 1048: dhcp_packet(now, 0);
1.1.1.3 ! misho 1049: if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
1.1 misho 1050: dhcp_packet(now, 1);
1051: }
1052:
1053: #ifdef HAVE_DHCP6
1.1.1.3 ! misho 1054: if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
1.1 misho 1055: dhcp6_packet(now);
1056:
1.1.1.3 ! misho 1057: if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
1.1 misho 1058: icmp6_packet(now);
1059: #endif
1060:
1061: # ifdef HAVE_SCRIPT
1.1.1.3 ! misho 1062: if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
1.1 misho 1063: helper_write();
1064: # endif
1065: #endif
1066:
1067: }
1068: }
1069:
1070: static void sig_handler(int sig)
1071: {
1072: if (pid == 0)
1073: {
1074: /* ignore anything other than TERM during startup
1075: and in helper proc. (helper ignore TERM too) */
1076: if (sig == SIGTERM)
1077: exit(EC_MISC);
1078: }
1079: else if (pid != getpid())
1080: {
1081: /* alarm is used to kill TCP children after a fixed time. */
1082: if (sig == SIGALRM)
1083: _exit(0);
1084: }
1085: else
1086: {
1087: /* master process */
1088: int event, errsave = errno;
1089:
1090: if (sig == SIGHUP)
1091: event = EVENT_RELOAD;
1092: else if (sig == SIGCHLD)
1093: event = EVENT_CHILD;
1094: else if (sig == SIGALRM)
1095: event = EVENT_ALARM;
1096: else if (sig == SIGTERM)
1097: event = EVENT_TERM;
1098: else if (sig == SIGUSR1)
1099: event = EVENT_DUMP;
1100: else if (sig == SIGUSR2)
1101: event = EVENT_REOPEN;
1102: else
1103: return;
1104:
1105: send_event(pipewrite, event, 0, NULL);
1106: errno = errsave;
1107: }
1108: }
1109:
1110: /* now == 0 -> queue immediate callback */
1111: void send_alarm(time_t event, time_t now)
1112: {
1113: if (now == 0 || event != 0)
1114: {
1115: /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1116: if ((now == 0 || difftime(event, now) <= 0.0))
1117: send_event(pipewrite, EVENT_ALARM, 0, NULL);
1118: else
1119: alarm((unsigned)difftime(event, now));
1120: }
1121: }
1122:
1.1.1.3 ! misho 1123: void queue_event(int event)
! 1124: {
! 1125: send_event(pipewrite, event, 0, NULL);
! 1126: }
! 1127:
1.1 misho 1128: void send_event(int fd, int event, int data, char *msg)
1129: {
1130: struct event_desc ev;
1131: struct iovec iov[2];
1132:
1133: ev.event = event;
1134: ev.data = data;
1135: ev.msg_sz = msg ? strlen(msg) : 0;
1136:
1137: iov[0].iov_base = &ev;
1138: iov[0].iov_len = sizeof(ev);
1139: iov[1].iov_base = msg;
1140: iov[1].iov_len = ev.msg_sz;
1141:
1142: /* error pipe, debug mode. */
1143: if (fd == -1)
1144: fatal_event(&ev, msg);
1145: else
1146: /* pipe is non-blocking and struct event_desc is smaller than
1147: PIPE_BUF, so this either fails or writes everything */
1148: while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
1149: }
1150:
1151: /* NOTE: the memory used to return msg is leaked: use msgs in events only
1152: to describe fatal errors. */
1153: static int read_event(int fd, struct event_desc *evp, char **msg)
1154: {
1155: char *buf;
1156:
1157: if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1158: return 0;
1159:
1160: *msg = NULL;
1161:
1162: if (evp->msg_sz != 0 &&
1163: (buf = malloc(evp->msg_sz + 1)) &&
1164: read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1165: {
1166: buf[evp->msg_sz] = 0;
1167: *msg = buf;
1168: }
1169:
1170: return 1;
1171: }
1172:
1173: static void fatal_event(struct event_desc *ev, char *msg)
1174: {
1175: errno = ev->data;
1176:
1177: switch (ev->event)
1178: {
1179: case EVENT_DIE:
1180: exit(0);
1181:
1182: case EVENT_FORK_ERR:
1183: die(_("cannot fork into background: %s"), NULL, EC_MISC);
1184:
1185: case EVENT_PIPE_ERR:
1186: die(_("failed to create helper: %s"), NULL, EC_MISC);
1187:
1188: case EVENT_CAP_ERR:
1189: die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1190:
1191: case EVENT_USER_ERR:
1192: die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
1193:
1194: case EVENT_GROUP_ERR:
1195: die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
1196:
1197: case EVENT_PIDFILE:
1198: die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
1199:
1200: case EVENT_LOG_ERR:
1201: die(_("cannot open log %s: %s"), msg, EC_FILE);
1202:
1203: case EVENT_LUA_ERR:
1204: die(_("failed to load Lua script: %s"), msg, EC_MISC);
1205:
1206: case EVENT_TFTP_ERR:
1207: die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
1.1.1.3 ! misho 1208:
! 1209: case EVENT_TIME_ERR:
! 1210: die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
1.1 misho 1211: }
1212: }
1213:
1214: static void async_event(int pipe, time_t now)
1215: {
1216: pid_t p;
1217: struct event_desc ev;
1.1.1.2 misho 1218: int i, check = 0;
1.1 misho 1219: char *msg;
1220:
1221: /* NOTE: the memory used to return msg is leaked: use msgs in events only
1222: to describe fatal errors. */
1223:
1224: if (read_event(pipe, &ev, &msg))
1225: switch (ev.event)
1226: {
1227: case EVENT_RELOAD:
1.1.1.2 misho 1228: #ifdef HAVE_DNSSEC
1229: if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1230: {
1231: my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1232: reset_option_bool(OPT_DNSSEC_TIME);
1233: }
1234: #endif
1235: /* fall through */
1236:
1237: case EVENT_INIT:
1.1 misho 1238: clear_cache_and_reload(now);
1.1.1.2 misho 1239:
1240: if (daemon->port != 0)
1.1 misho 1241: {
1.1.1.2 misho 1242: if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1243: {
1244: reload_servers(daemon->resolv_files->name);
1245: check = 1;
1246: }
1247:
1248: if (daemon->servers_file)
1249: {
1250: read_servers_file();
1251: check = 1;
1252: }
1253:
1254: if (check)
1255: check_servers();
1.1 misho 1256: }
1.1.1.2 misho 1257:
1.1 misho 1258: #ifdef HAVE_DHCP
1259: rerun_scripts();
1260: #endif
1261: break;
1262:
1263: case EVENT_DUMP:
1264: if (daemon->port != 0)
1265: dump_cache(now);
1266: break;
1267:
1268: case EVENT_ALARM:
1269: #ifdef HAVE_DHCP
1270: if (daemon->dhcp || daemon->doing_dhcp6)
1271: {
1272: lease_prune(NULL, now);
1273: lease_update_file(now);
1274: }
1275: #ifdef HAVE_DHCP6
1276: else if (daemon->doing_ra)
1277: /* Not doing DHCP, so no lease system, manage alarms for ra only */
1278: send_alarm(periodic_ra(now), now);
1279: #endif
1280: #endif
1281: break;
1282:
1283: case EVENT_CHILD:
1284: /* See Stevens 5.10 */
1285: while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1286: if (p == -1)
1287: {
1288: if (errno != EINTR)
1289: break;
1290: }
1291: else
1292: for (i = 0 ; i < MAX_PROCS; i++)
1293: if (daemon->tcp_pids[i] == p)
1294: daemon->tcp_pids[i] = 0;
1295: break;
1296:
1297: case EVENT_KILLED:
1298: my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
1299: break;
1300:
1301: case EVENT_EXITED:
1302: my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
1303: break;
1304:
1305: case EVENT_EXEC_ERR:
1306: my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1307: daemon->lease_change_command, strerror(ev.data));
1308: break;
1309:
1310: /* necessary for fatal errors in helper */
1311: case EVENT_USER_ERR:
1312: case EVENT_DIE:
1313: case EVENT_LUA_ERR:
1314: fatal_event(&ev, msg);
1315: break;
1316:
1317: case EVENT_REOPEN:
1318: /* Note: this may leave TCP-handling processes with the old file still open.
1319: Since any such process will die in CHILD_LIFETIME or probably much sooner,
1320: we leave them logging to the old file. */
1321: if (daemon->log_file != NULL)
1322: log_reopen(daemon->log_file);
1323: break;
1.1.1.3 ! misho 1324:
! 1325: case EVENT_NEWADDR:
! 1326: newaddress(now);
! 1327: break;
! 1328:
! 1329: case EVENT_NEWROUTE:
! 1330: resend_query();
! 1331: /* Force re-reading resolv file right now, for luck. */
! 1332: poll_resolv(0, 1, now);
! 1333: break;
! 1334:
1.1 misho 1335: case EVENT_TERM:
1336: /* Knock all our children on the head. */
1337: for (i = 0; i < MAX_PROCS; i++)
1338: if (daemon->tcp_pids[i] != 0)
1339: kill(daemon->tcp_pids[i], SIGALRM);
1340:
1.1.1.3 ! misho 1341: #if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
1.1 misho 1342: /* handle pending lease transitions */
1343: if (daemon->helperfd != -1)
1344: {
1345: /* block in writes until all done */
1346: if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1347: fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1348: do {
1349: helper_write();
1350: } while (!helper_buf_empty() || do_script_run(now));
1.1.1.3 ! misho 1351: while (retry_send(close(daemon->helperfd)));
1.1 misho 1352: }
1353: #endif
1354:
1355: if (daemon->lease_stream)
1356: fclose(daemon->lease_stream);
1357:
1.1.1.3 ! misho 1358: #ifdef HAVE_DNSSEC
! 1359: /* update timestamp file on TERM if time is considered valid */
! 1360: if (daemon->back_to_the_future)
! 1361: {
! 1362: if (utime(daemon->timestamp_file, NULL) == -1)
! 1363: my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
! 1364: }
! 1365: #endif
! 1366:
1.1 misho 1367: if (daemon->runfile)
1368: unlink(daemon->runfile);
1369:
1370: my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1371: flush_log();
1372: exit(EC_GOOD);
1373: }
1374: }
1375:
1.1.1.3 ! misho 1376: static void poll_resolv(int force, int do_reload, time_t now)
1.1 misho 1377: {
1378: struct resolvc *res, *latest;
1379: struct stat statbuf;
1380: time_t last_change = 0;
1381: /* There may be more than one possible file.
1382: Go through and find the one which changed _last_.
1383: Warn of any which can't be read. */
1384:
1385: if (daemon->port == 0 || option_bool(OPT_NO_POLL))
1386: return;
1387:
1388: for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1389: if (stat(res->name, &statbuf) == -1)
1390: {
1391: if (force)
1392: {
1393: res->mtime = 0;
1394: continue;
1395: }
1396:
1397: if (!res->logged)
1398: my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1399: res->logged = 1;
1400:
1401: if (res->mtime != 0)
1402: {
1403: /* existing file evaporated, force selection of the latest
1404: file even if its mtime hasn't changed since we last looked */
1405: poll_resolv(1, do_reload, now);
1406: return;
1407: }
1408: }
1409: else
1410: {
1411: res->logged = 0;
1412: if (force || (statbuf.st_mtime != res->mtime))
1413: {
1414: res->mtime = statbuf.st_mtime;
1415: if (difftime(statbuf.st_mtime, last_change) > 0.0)
1416: {
1417: last_change = statbuf.st_mtime;
1418: latest = res;
1419: }
1420: }
1421: }
1422:
1423: if (latest)
1424: {
1425: static int warned = 0;
1426: if (reload_servers(latest->name))
1427: {
1428: my_syslog(LOG_INFO, _("reading %s"), latest->name);
1429: warned = 0;
1430: check_servers();
1431: if (option_bool(OPT_RELOAD) && do_reload)
1432: clear_cache_and_reload(now);
1433: }
1434: else
1435: {
1436: latest->mtime = 0;
1437: if (!warned)
1438: {
1439: my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1440: warned = 1;
1441: }
1442: }
1443: }
1444: }
1445:
1446: void clear_cache_and_reload(time_t now)
1447: {
1.1.1.2 misho 1448: (void)now;
1449:
1.1 misho 1450: if (daemon->port != 0)
1451: cache_reload();
1452:
1453: #ifdef HAVE_DHCP
1454: if (daemon->dhcp || daemon->doing_dhcp6)
1455: {
1456: if (option_bool(OPT_ETHERS))
1457: dhcp_read_ethers();
1458: reread_dhcp();
1.1.1.3 ! misho 1459: #ifdef HAVE_INOTIFY
! 1460: set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
! 1461: #endif
1.1 misho 1462: dhcp_update_configs(daemon->dhcp_conf);
1463: lease_update_from_configs();
1464: lease_update_file(now);
1465: lease_update_dns(1);
1466: }
1467: #ifdef HAVE_DHCP6
1468: else if (daemon->doing_ra)
1469: /* Not doing DHCP, so no lease system, manage
1470: alarms for ra only */
1471: send_alarm(periodic_ra(now), now);
1472: #endif
1473: #endif
1474: }
1475:
1.1.1.3 ! misho 1476: static int set_dns_listeners(time_t now)
1.1 misho 1477: {
1478: struct serverfd *serverfdp;
1479: struct listener *listener;
1480: int wait = 0, i;
1481:
1482: #ifdef HAVE_TFTP
1483: int tftp = 0;
1484: struct tftp_transfer *transfer;
1485: for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1486: {
1487: tftp++;
1.1.1.3 ! misho 1488: poll_listen(transfer->sockfd, POLLIN);
1.1 misho 1489: }
1490: #endif
1491:
1492: /* will we be able to get memory? */
1493: if (daemon->port != 0)
1.1.1.2 misho 1494: get_new_frec(now, &wait, 0);
1.1 misho 1495:
1496: for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
1.1.1.3 ! misho 1497: poll_listen(serverfdp->fd, POLLIN);
! 1498:
1.1 misho 1499: if (daemon->port != 0 && !daemon->osport)
1500: for (i = 0; i < RANDOM_SOCKS; i++)
1501: if (daemon->randomsocks[i].refcount != 0)
1.1.1.3 ! misho 1502: poll_listen(daemon->randomsocks[i].fd, POLLIN);
! 1503:
1.1 misho 1504: for (listener = daemon->listeners; listener; listener = listener->next)
1505: {
1506: /* only listen for queries if we have resources */
1507: if (listener->fd != -1 && wait == 0)
1.1.1.3 ! misho 1508: poll_listen(listener->fd, POLLIN);
! 1509:
1.1 misho 1510: /* death of a child goes through the select loop, so
1511: we don't need to explicitly arrange to wake up here */
1512: if (listener->tcpfd != -1)
1513: for (i = 0; i < MAX_PROCS; i++)
1514: if (daemon->tcp_pids[i] == 0)
1515: {
1.1.1.3 ! misho 1516: poll_listen(listener->tcpfd, POLLIN);
1.1 misho 1517: break;
1518: }
1519:
1520: #ifdef HAVE_TFTP
1521: if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
1.1.1.3 ! misho 1522: poll_listen(listener->tftpfd, POLLIN);
1.1 misho 1523: #endif
1524:
1525: }
1526:
1527: return wait;
1528: }
1529:
1.1.1.3 ! misho 1530: static void check_dns_listeners(time_t now)
1.1 misho 1531: {
1532: struct serverfd *serverfdp;
1533: struct listener *listener;
1534: int i;
1535:
1536: for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
1.1.1.3 ! misho 1537: if (poll_check(serverfdp->fd, POLLIN))
1.1 misho 1538: reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1539:
1540: if (daemon->port != 0 && !daemon->osport)
1541: for (i = 0; i < RANDOM_SOCKS; i++)
1542: if (daemon->randomsocks[i].refcount != 0 &&
1.1.1.3 ! misho 1543: poll_check(daemon->randomsocks[i].fd, POLLIN))
1.1 misho 1544: reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
1545:
1546: for (listener = daemon->listeners; listener; listener = listener->next)
1547: {
1.1.1.3 ! misho 1548: if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
1.1 misho 1549: receive_query(listener, now);
1550:
1551: #ifdef HAVE_TFTP
1.1.1.3 ! misho 1552: if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
1.1 misho 1553: tftp_request(listener, now);
1554: #endif
1555:
1.1.1.3 ! misho 1556: if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
1.1 misho 1557: {
1558: int confd, client_ok = 1;
1559: struct irec *iface = NULL;
1560: pid_t p;
1561: union mysockaddr tcp_addr;
1562: socklen_t tcp_len = sizeof(union mysockaddr);
1563:
1564: while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
1565:
1566: if (confd == -1)
1567: continue;
1.1.1.2 misho 1568:
1.1 misho 1569: if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1570: {
1.1.1.3 ! misho 1571: while (retry_send(close(confd)));
1.1 misho 1572: continue;
1573: }
1.1.1.2 misho 1574:
1575: /* Make sure that the interface list is up-to-date.
1576:
1577: We do this here as we may need the results below, and
1578: the DNS code needs them for --interface-name stuff.
1579:
1580: Multiple calls to enumerate_interfaces() per select loop are
1581: inhibited, so calls to it in the child process (which doesn't select())
1582: have no effect. This avoids two processes reading from the same
1583: netlink fd and screwing the pooch entirely.
1584: */
1.1 misho 1585:
1.1.1.2 misho 1586: enumerate_interfaces(0);
1587:
1588: if (option_bool(OPT_NOWILD))
1589: iface = listener->iface; /* May be NULL */
1590: else
1591: {
1592: int if_index;
1593: char intr_name[IF_NAMESIZE];
1594:
1595: /* if we can find the arrival interface, check it's one that's allowed */
1596: if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1597: indextoname(listener->tcpfd, if_index, intr_name))
1598: {
1599: struct all_addr addr;
1600: addr.addr.addr4 = tcp_addr.in.sin_addr;
1.1 misho 1601: #ifdef HAVE_IPV6
1.1.1.2 misho 1602: if (tcp_addr.sa.sa_family == AF_INET6)
1603: addr.addr.addr6 = tcp_addr.in6.sin6_addr;
1.1 misho 1604: #endif
1.1.1.2 misho 1605:
1606: for (iface = daemon->interfaces; iface; iface = iface->next)
1607: if (iface->index == if_index)
1608: break;
1609:
1610: if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1611: client_ok = 0;
1612: }
1613:
1614: if (option_bool(OPT_CLEVERBIND))
1615: iface = listener->iface; /* May be NULL */
1616: else
1617: {
1618: /* Check for allowed interfaces when binding the wildcard address:
1619: we do this by looking for an interface with the same address as
1620: the local address of the TCP connection, then looking to see if that's
1621: an allowed interface. As a side effect, we get the netmask of the
1622: interface too, for localisation. */
1623:
1624: for (iface = daemon->interfaces; iface; iface = iface->next)
1625: if (sockaddr_isequal(&iface->addr, &tcp_addr))
1626: break;
1627:
1628: if (!iface)
1629: client_ok = 0;
1630: }
1631: }
1632:
1.1 misho 1633: if (!client_ok)
1634: {
1635: shutdown(confd, SHUT_RDWR);
1.1.1.3 ! misho 1636: while (retry_send(close(confd)));
1.1 misho 1637: }
1638: #ifndef NO_FORK
1639: else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
1640: {
1641: if (p != -1)
1642: {
1643: int i;
1644: for (i = 0; i < MAX_PROCS; i++)
1645: if (daemon->tcp_pids[i] == 0)
1646: {
1647: daemon->tcp_pids[i] = p;
1648: break;
1649: }
1650: }
1.1.1.3 ! misho 1651: while (retry_send(close(confd)));
! 1652:
! 1653: /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
! 1654: daemon->log_id += TCP_MAX_QUERIES;
1.1 misho 1655: }
1656: #endif
1657: else
1658: {
1659: unsigned char *buff;
1660: struct server *s;
1661: int flags;
1662: struct in_addr netmask;
1663: int auth_dns;
1664:
1665: if (iface)
1666: {
1667: netmask = iface->netmask;
1668: auth_dns = iface->dns_auth;
1669: }
1670: else
1671: {
1672: netmask.s_addr = 0;
1673: auth_dns = 0;
1674: }
1675:
1676: #ifndef NO_FORK
1677: /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
1678: terminate the process. */
1679: if (!option_bool(OPT_DEBUG))
1680: alarm(CHILD_LIFETIME);
1681: #endif
1682:
1683: /* start with no upstream connections. */
1684: for (s = daemon->servers; s; s = s->next)
1685: s->tcpfd = -1;
1686:
1687: /* The connected socket inherits non-blocking
1688: attribute from the listening socket.
1689: Reset that here. */
1690: if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1691: fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1692:
1693: buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
1694:
1695: shutdown(confd, SHUT_RDWR);
1.1.1.3 ! misho 1696: while (retry_send(close(confd)));
1.1 misho 1697:
1698: if (buff)
1699: free(buff);
1700:
1701: for (s = daemon->servers; s; s = s->next)
1702: if (s->tcpfd != -1)
1703: {
1704: shutdown(s->tcpfd, SHUT_RDWR);
1.1.1.3 ! misho 1705: while (retry_send(close(s->tcpfd)));
1.1 misho 1706: }
1707: #ifndef NO_FORK
1708: if (!option_bool(OPT_DEBUG))
1709: {
1710: flush_log();
1711: _exit(0);
1712: }
1713: #endif
1714: }
1715: }
1716: }
1717: }
1718:
1719: #ifdef HAVE_DHCP
1720: int make_icmp_sock(void)
1721: {
1722: int fd;
1723: int zeroopt = 0;
1724:
1725: if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1726: {
1727: if (!fix_fd(fd) ||
1728: setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1729: {
1730: close(fd);
1731: fd = -1;
1732: }
1733: }
1734:
1735: return fd;
1736: }
1737:
1738: int icmp_ping(struct in_addr addr)
1739: {
1740: /* Try and get an ICMP echo from a machine. */
1741:
1742: /* Note that whilst in the three second wait, we check for
1743: (and service) events on the DNS and TFTP sockets, (so doing that
1744: better not use any resources our caller has in use...)
1745: but we remain deaf to signals or further DHCP packets. */
1746:
1.1.1.3 ! misho 1747: /* There can be a problem using dnsmasq_time() to end the loop, since
! 1748: it's not monotonic, and can go backwards if the system clock is
! 1749: tweaked, leading to the code getting stuck in this loop and
! 1750: ignoring DHCP requests. To fix this, we check to see if select returned
! 1751: as a result of a timeout rather than a socket becoming available. We
! 1752: only allow this to happen as many times as it takes to get to the wait time
! 1753: in quarter-second chunks. This provides a fallback way to end loop. */
! 1754:
! 1755: int fd, rc;
1.1 misho 1756: struct sockaddr_in saddr;
1757: struct {
1758: struct ip ip;
1759: struct icmp icmp;
1760: } packet;
1761: unsigned short id = rand16();
1.1.1.3 ! misho 1762: unsigned int i, j, timeout_count;
1.1 misho 1763: int gotreply = 0;
1764: time_t start, now;
1765:
1766: #if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
1767: if ((fd = make_icmp_sock()) == -1)
1768: return 0;
1769: #else
1770: int opt = 2000;
1771: fd = daemon->dhcp_icmp_fd;
1772: setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1773: #endif
1774:
1775: saddr.sin_family = AF_INET;
1776: saddr.sin_port = 0;
1777: saddr.sin_addr = addr;
1778: #ifdef HAVE_SOCKADDR_SA_LEN
1779: saddr.sin_len = sizeof(struct sockaddr_in);
1780: #endif
1781:
1782: memset(&packet.icmp, 0, sizeof(packet.icmp));
1783: packet.icmp.icmp_type = ICMP_ECHO;
1784: packet.icmp.icmp_id = id;
1785: for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1786: j += ((u16 *)&packet.icmp)[i];
1787: while (j>>16)
1788: j = (j & 0xffff) + (j >> 16);
1789: packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1790:
1.1.1.3 ! misho 1791: while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
! 1792: (struct sockaddr *)&saddr, sizeof(saddr))));
1.1 misho 1793:
1.1.1.3 ! misho 1794: for (now = start = dnsmasq_time(), timeout_count = 0;
! 1795: (difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
1.1 misho 1796: {
1797: struct sockaddr_in faddr;
1798: socklen_t len = sizeof(faddr);
1799:
1.1.1.3 ! misho 1800: poll_reset();
! 1801: poll_listen(fd, POLLIN);
! 1802: set_dns_listeners(now);
! 1803: set_log_writer();
1.1 misho 1804:
1805: #ifdef HAVE_DHCP6
1806: if (daemon->doing_ra)
1.1.1.3 ! misho 1807: poll_listen(daemon->icmp6fd, POLLIN);
1.1 misho 1808: #endif
1809:
1.1.1.3 ! misho 1810: rc = do_poll(250);
! 1811:
! 1812: if (rc < 0)
! 1813: continue;
! 1814: else if (rc == 0)
! 1815: timeout_count++;
1.1 misho 1816:
1817: now = dnsmasq_time();
1818:
1.1.1.3 ! misho 1819: check_log_writer(0);
! 1820: check_dns_listeners(now);
1.1 misho 1821:
1822: #ifdef HAVE_DHCP6
1.1.1.3 ! misho 1823: if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
1.1 misho 1824: icmp6_packet(now);
1825: #endif
1826:
1827: #ifdef HAVE_TFTP
1.1.1.3 ! misho 1828: check_tftp_listeners(now);
1.1 misho 1829: #endif
1830:
1.1.1.3 ! misho 1831: if (poll_check(fd, POLLIN) &&
1.1 misho 1832: recvfrom(fd, &packet, sizeof(packet), 0,
1833: (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1834: saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
1835: packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1836: packet.icmp.icmp_seq == 0 &&
1837: packet.icmp.icmp_id == id)
1838: {
1839: gotreply = 1;
1840: break;
1841: }
1842: }
1843:
1844: #if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1.1.1.3 ! misho 1845: while (retry_send(close(fd)));
1.1 misho 1846: #else
1847: opt = 1;
1848: setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1849: #endif
1850:
1851: return gotreply;
1852: }
1853: #endif
1854:
1855:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>