1 /*
2 * radns - Router Advertisement DNS
3 *
4 * Small program to listen for IPv6 Router Advertisements with the
5 * RDNSS (Recursive DNS Server) option.
6 *
7 * If we see an RDNSS option, we get the IPv6 address to the recursive
8 * DNS and store it in a file in the resolv.conf format, resolver(5).
9 *
10 * Originally written by Michael Cardell Widerkrantz (MC) for
11 * Stickybit AB and then maintained by MC.
12 *
13 * Contact:
14 *
15 * mc at the domain hack.org
16 *
17 * Copyright (c) 2008, Stickybit AB.
18 * All rights reserved.
19 *
20 * Copyright (c) 2009, 2010, 2011 Michael Cardell Widerkrantz.
21 * All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 *
27 * * Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 *
30 * * Redistributions in binary form must reproduce the above
31 * copyright notice, this list of conditions and the following
32 * disclaimer in the documentation and/or other materials provided
33 * with the distribution.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
36 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
39 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 *
47 */
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <stdint.h>
52 #include <stdarg.h>
53 #include <stdbool.h>
54 #include <syslog.h>
55 #include <unistd.h>
56 #include <signal.h>
57 #include <getopt.h>
58 #include <pwd.h>
59 #include <time.h>
60 #include <sys/socket.h>
61 #include <sys/wait.h>
62 #include <sys/uio.h>
63 #include <net/if.h>
64 #include <netinet/in.h>
65 #include <netinet/ip6.h>
66 #include <netinet/icmp6.h>
67 #include <arpa/inet.h>
68 #include <sys/stat.h>
69 #include <fcntl.h>
70 #include <string.h>
71 #include <errno.h>
72
73 #include "list.h"
74
75 /* #define TEST 1 */
76
77 #define RESOLVEFILE "./resolv.conf"
78
79 #define PIDFILE "/var/run/radns.pid"
80
81 #define USER "radns"
82
83 /* The Resolving DNS Server option, RFC 6106. */
84 #define ND_OPT_RDNSS 25
85
86 /* The DNS Search List option, RFC 6106. */
87 #define ND_OPT_DNSSL 31
88
89 /* Space for "nameserver %s \n" where %s is the IPv6 address */
90 #define NSADDRSIZE (13 + INET6_ADDRSTRLEN)
91
92 /*
93 * XXX PACKETSIZE really taken out of the blue. Expected size of
94 * incoming packets is:
95 *
96 * ICMP6 header 8 bytes
97 * RA minimum 24 bytes
98 * RDNSS option minimum 24 bytes
99 *
100 * That is, minimum 56 bytes, with unknown max for patological cases.
101 */
102 #define PACKETSIZE 1024
103
104 /*
105 * Minimum length in bytes of the RDNSS option if we're going to care
106 * about it. Exactly 3 * 8 = 24 octets if there is one IPv6 address.
107 */
108 #define RDNSSMINLEN 24
109
110 /*
111 * Lifetime that never expires.
112 */
113 #define NEVEREXP 0xffffffff
114
115 /*
116 * Maximum number of octets in a domain name as per RFC 1035
117 */
118 #define MAXNAME 255
119
120 char *progname; /* argv[0] */
121 char *filename = RESOLVEFILE;
122 char *pidfilename = PIDFILE;
123 char *scriptname = NULL;
124 bool progdone; /* true when we exit the program. */
125 int verbose = 0; /* how much debug output? */
126 int localerrno; /* our own copy of errno. */
127 bool childcare = false; /* true when we need to reap zombies. */
128
129 /*
130 * Default for maximum number of stored resolver addresses. Can be
131 * overridden by a runtime option.
132 *
133 * XXX A default called MAXNS might be in resolv.h, depending on
134 * system. We might want to use that as default if it exists.
135 */
136 int maxres = 3;
137
138 /*
139 * Default for maximum number of stored domain suffixes.
140 */
141 int maxsuf = 6;
142
143 struct resolver
144 {
145 struct in6_addr addr; /* Address to DNS server. */
146 char ifname[IFNAMSIZ]; /* Interface name we received this data on. */
147 time_t expire; /* Expire time of this data. */
148 bool neverexp;
149 struct item *item; /* Pointer to our place in the list. */
150 };
151
152 struct suffix
153 {
154 char name[255];
155 int len; /* Length of domain name suffix. */
156 char ifname[IFNAMSIZ]; /* Interface name we received this data on. */
157 time_t expire; /* Expire time of this data. */
158 bool neverexp;
159 struct item *item; /* Pointer to our place in the list. */
160 };
161
162 /* Recursive DNS Server (RDNSS) option in Router Advertisments. */
163 struct radns_opt_rdnss
164 {
165 uint8_t nd_opt_type; /* Should be 25 (0x19) for RDNSS */
166 uint8_t nd_opt_len; /* Length: 3 (* 8 octets) if one IPv6
167 address. No of addresses = (Length -
168 1) / 2. If less than 3, disregard.*/
169 uint16_t nd_opt_rdns_res; /* Reserved. */
170 uint32_t nd_opt_rdns_life; /* The maximum time in seconds to
171 use this from the time it was
172 sent. */
173 } __attribute__((__packed__));
174
175 /* DNS Search List option in Router Advertisments. */
176 struct radns_opt_dnssl
177 {
178 uint8_t nd_opt_type;
179 uint8_t nd_opt_len;
180 uint16_t nd_opt_dnssl_res;
181 uint32_t nd_opt_dnssl_life;
182 } __attribute__((__packed__));
183
184 static struct resolver *expirenext(struct item *reslist);
185 static struct resolver *findresolv(struct in6_addr addr, struct item *reslist);
186 static bool rdnss(const struct radns_opt_rdnss *rdnssp, int optlen,
187 int lenleft, struct item **reslist, int *storedres,
188 char ifname[IFNAMSIZ]);
189 static bool dnssl(const struct radns_opt_dnssl *dnsslp, int optlen,
190 int lenleft, struct item **suflist, int *storedsuf,
191 char ifname[IFNAMSIZ]);
192 static int dnsname(char *domain, uint8_t *name, int buflen);
193 static void hexdump(uint8_t *buf, uint16_t len);
194 static void printhelp(void);
195 void sigcatch(int sig);
196 static int exithook(char *filename, char *ifname);
197 static int writeresolv(struct item *suflist, int storedsuf,
198 struct item *reslist);
199 static void logmsg(int pri, const char *message, ...);
200 static bool expireresolv(struct item **reslist, int *storedres);
201 static bool addresolver(struct item **reslist, int *storedres, uint32_t ttl,
202 struct in6_addr addr, char *ifname);
203 static bool addsuffix(struct item **suflist, int *storedsuf, uint32_t ttl,
204 char *name, int namelen, char *ifname);
205 static struct suffix *sufexpirenext(struct item *suflist);
206 static bool expiresuffix(struct item **suflist, int *storedsuf);
207 static struct suffix *findsuffix(char *name, int namelen, struct item *suflist);
208 static bool handle_icmp6(int sock, struct item **suflist, int *storedsuf,
209 struct item **reslist, int *storedres,
210 char ifname[IFNAMSIZ]);
211 static int mkpidfile(uid_t owner, gid_t group);
212
213 #ifdef TEST
214 static void deladdr(struct item **reslist, int *storedres,
215 struct in6_addr addr);
216 static void printrewrite(bool rewrite);
217 static void listsuf(struct item *suflist);
218 static void listres(struct item *reslist);
219 static void printrewrite(bool rewrite);
220 #endif
221
222 /*
223 * Find resolver in list reslist that will expire next. Returns a
224 * pointer to the resolver or NULL if there are no resolvers.
225 */
expirenext(struct item * reslist)226 static struct resolver *expirenext(struct item *reslist)
227 {
228 time_t least = 0;
229 struct resolver *res;
230 struct resolver *leastres = NULL;
231 struct item *item;
232
233 for (item = reslist; item != NULL; item = item->next)
234 {
235 res = item->data;
236 if (0 != res->expire)
237 {
238 if (0 == least || res->expire < least)
239 {
240 least = res->expire;
241 leastres = res;
242 }
243 }
244 }
245
246 return leastres;
247 }
248
249 /*
250 * Find resolver with address addr in list reslist. Returns a pointer
251 * to the matching resolver or NULL if not found.
252 */
findresolv(struct in6_addr addr,struct item * reslist)253 static struct resolver *findresolv(struct in6_addr addr, struct item *reslist)
254 {
255 struct item *item;
256 struct resolver *res;
257
258 for (item = reslist; item != NULL; item = item->next)
259 {
260 res = item->data;
261 if (0 == memcmp(&addr, &res->addr, sizeof (addr)))
262 {
263 return res;
264 }
265 }
266
267 return NULL;
268 }
269
rdnss(const struct radns_opt_rdnss * rdnssp,int optlen,int lenleft,struct item ** reslist,int * storedres,char ifname[IFNAMSIZ])270 static bool rdnss(const struct radns_opt_rdnss *rdnssp, int optlen,
271 int lenleft, struct item **reslist, int *storedres,
272 char ifname[IFNAMSIZ])
273 {
274 int nr_of_addrs;
275 int i;
276 struct in6_addr *addrp; /* An IPv6 address. */
277 uint8_t *datap; /* An octet pointer we use for running
278 * through data in rdnssp. */
279 bool rewrite = false;
280
281 datap = (uint8_t *)rdnssp;
282
283 /* We got an RDNSS option, that is,
284 *
285 * type, length, reserved,
286 * lifetime
287 * addresses
288 */
289
290 if (verbose > 2)
291 {
292 printf(" reserved: %d\n", rdnssp->nd_opt_rdns_res);
293 printf(" lifetime: %d\n", ntohl(rdnssp->nd_opt_rdns_life));
294 }
295
296 /* Extract DNS address(es) from option. */
297
298 /*
299 * Length should be 3 (* 8 octets) if there is one IPv6
300 * address. If less than 3 * 8 octets, disregard this
301 * option.
302 */
303 if (optlen < RDNSSMINLEN)
304 {
305 /* No IPv6 address here. Throw away. */
306 logmsg(LOG_INFO, "No IPv6 address in RDNSS option.\n");
307 return rewrite;
308 }
309
310 /* Move to first IPv6 address. */
311 datap += sizeof (struct radns_opt_rdnss);
312 lenleft -= sizeof (struct radns_opt_rdnss);
313
314 if (lenleft <= 0)
315 {
316 /* Out of data! */
317 logmsg(LOG_INFO, "RDNSS option: Out of data.\n");
318 return rewrite;
319 }
320
321 /* How many addresses to DNS servers are there? */
322 nr_of_addrs = (rdnssp->nd_opt_len - 1) / 2;
323
324 if (verbose > 0)
325 {
326 printf("%d address(es) to resolving DNS servers found.\n",
327 nr_of_addrs);
328 }
329
330 /* Find the addresses and store them. */
331 for (i = 0; i < nr_of_addrs
332 && (unsigned)lenleft > sizeof (struct in6_addr); i ++)
333 {
334 addrp = (struct in6_addr *)datap;
335
336 rewrite = addresolver(reslist, storedres,
337 ntohl(rdnssp->nd_opt_rdns_life),
338 *addrp, ifname);
339
340 /* Move to next address, if any. */
341 datap += sizeof (struct in6_addr);
342 lenleft -= sizeof (struct in6_addr);
343 } /* for */
344
345 /* Tell caller if we need to rewrite the file. */
346 return rewrite;
347 }
348
349
350 /*
351 * Get a series of labels with RFC 1035 encoding in name and add them
352 * to a domain string, domain.
353 *
354 * Returns length of final domain string which also happens to be the
355 * number of bytes consumed by parsing in name.
356 *
357 * From RFC 1035:
358 *
359 * Domain names in messages are expressed in terms of a sequence of
360 * labels. Each label is represented as a one octet length field
361 * followed by that number of octets. Since every domain name ends
362 * with the null label of the root, a domain name is terminated by a
363 * length byte of zero. The high order two bits of every length
364 * octet must be zero, and the remaining six bits of the length
365 * field limit the label to 63 octets or less.
366 *
367 * To simplify implementations, the total length of a domain name
368 * (i.e., label octets and label length octets) is restricted to 255
369 * octets or less.
370 */
dnsname(char * domain,uint8_t * name,int buflen)371 static int dnsname(char *domain, uint8_t *name, int buflen)
372 {
373 uint8_t len; /* Length of label. */
374 uint8_t domleft = MAXNAME; /* Number of octets left free in domain. */
375 int strlen; /* Length of domain string. */
376 uint8_t *bytep; /* Octet pointer used to walk the name. */
377
378 strlen = 0;
379
380 /*
381 * Walk through each label and copy each label to the domain
382 * string adding "." between them. When we run out of buffer
383 * (pathological) or find a zero length (fine) we're done.
384 */
385 for (bytep = name; buflen > 0 && (uint8_t) *bytep != 0; )
386 {
387 len = *bytep;
388 bytep ++;
389 domleft --;
390
391 if (domleft > len && len <= (uint8_t)buflen)
392 {
393 if (len != 0)
394 {
395 memcpy(&domain[strlen], bytep, len);
396 bytep += len;
397 domleft -= len;
398 buflen -= len;
399
400 strlen += len;
401 }
402
403 domain[strlen] = '.';
404 strlen ++;
405 }
406 }
407
408 return strlen;
409 }
410
dnssl(const struct radns_opt_dnssl * dnsslp,int optlen,int lenleft,struct item ** suflist,int * storedsuf,char ifname[IFNAMSIZ])411 static bool dnssl(const struct radns_opt_dnssl *dnsslp, int optlen,
412 int lenleft, struct item **suflist, int *storedsuf,
413 char ifname[IFNAMSIZ])
414 {
415 uint8_t *datap; /* An octet pointer we use for running
416 * through data in rdnssp. */
417 bool rewrite = false;
418 char domain[MAXNAME];
419 int domlen;
420 int optlenleft = optlen;
421
422 if (verbose > 0)
423 {
424 printf("We received a DNSSL!\n");
425 }
426
427 datap = (uint8_t *)dnsslp;
428
429 if (verbose > 2)
430 {
431 printf(" reserved: %d\n", dnsslp->nd_opt_dnssl_res);
432 printf(" lifetime: %d\n", ntohl(dnsslp->nd_opt_dnssl_life));
433 }
434
435 /*
436 * Length is at minimum 2 (* 8 octets) if there is exactly one
437 * domain. If less, we disregard this option.
438 */
439 if (optlen < 2)
440 {
441 logmsg(LOG_INFO, "No Domain Suffix in DNSSL option.\n");
442 return rewrite;
443 }
444
445 /*
446 Domain Names of DNS Search List
447 One or more domain names of DNS Search List that MUST
448 be encoded using the technique described in Section
449 3.1 of [RFC1035]. By this technique, each domain
450 name is represented as a sequence of labels ending in
451 a zero octet, defined as domain name representation.
452 For more than one domain name, the corresponding
453 domain name representations are concatenated as they
454 are. Note that for the simple decoding, the domain
455 names MUST NOT be encoded in a compressed form, as
456 described in Section 4.1.4 of [RFC1035]. Because the
457 size of this field MUST be a multiple of 8 octets,
458 for the minimum multiple including the domain name
459 representations, the remaining octets other than the
460 encoding parts of the domain name representations
461 MUST be padded with zeros.
462 */
463
464 /* Move to first domain suffix. */
465 datap += sizeof (struct radns_opt_dnssl);
466 lenleft -= sizeof (struct radns_opt_dnssl);
467 optlenleft -= sizeof (struct radns_opt_dnssl);
468
469 if (lenleft <= 0)
470 {
471 /* Out of data! */
472 logmsg(LOG_INFO, "DNSSL option: Out of data.\n");
473 return rewrite;
474 }
475
476 while (optlenleft > 0 && lenleft > 0)
477 {
478 domlen = dnsname(domain, datap, optlenleft);
479 if (0 == domlen)
480 {
481 break;
482 }
483
484 datap += domlen + 1;
485 lenleft -= domlen + 1;
486 optlenleft -= domlen + 1;
487
488 if (verbose > 0)
489 {
490 printf("Got domain suffix:\n");
491 hexdump((uint8_t *)domain, domlen);
492 }
493
494 rewrite = addsuffix(suflist, storedsuf,
495 ntohl(dnsslp->nd_opt_dnssl_life), domain, domlen,
496 ifname);
497 }
498
499 return rewrite;
500 }
501
502 /*
503 * Callback function when we get an ICMP6 message on socket sock.
504 *
505 * Returns true if we need to rewrite the resolv file and false
506 * otherwise.
507 */
handle_icmp6(int sock,struct item ** suflist,int * storedsuf,struct item ** reslist,int * storedres,char ifname[IFNAMSIZ])508 static bool handle_icmp6(int sock, struct item **suflist, int *storedsuf,
509 struct item **reslist, int *storedres,
510 char ifname[IFNAMSIZ])
511 {
512 uint8_t buf[PACKETSIZE]; /* The entire ICMP6 message. */
513 int buflen; /* The lenght of the ICMP6 buffer. */
514 uint8_t ancbuf[CMSG_SPACE(sizeof (struct in6_pktinfo)) ]; /* Ancillary
515 * data. */
516 const struct nd_router_advert *ra; /* A Router Advertisement */
517 struct nd_opt_hdr *ndhdr;
518 uint8_t *datap; /* An octet pointer we use for running
519 * through data in buf. */
520 int lenleft; /* Length left in buf, in bytes,
521 * counting from datap. */
522 struct sockaddr_in6 src; /* Source address of RA packet. */
523 struct iovec iov[1] =
524 {
525 { .iov_base = buf, .iov_len = sizeof (buf) }
526 }; /* Incoming buffer. */
527 struct msghdr msg =
528 {
529 .msg_name = &src,
530 .msg_namelen = sizeof (src),
531 .msg_iov = iov,
532 .msg_iovlen = sizeof (iov) / sizeof (iov[0]),
533 .msg_control = ancbuf,
534 .msg_controllen = sizeof (ancbuf)
535 }; /* Incoming message. */
536 struct in6_pktinfo *pktinfo = NULL; /* Metadata about the packet. */
537 struct cmsghdr *cmsgp; /* Pointer to ancillary data. */
538 bool rewrite = false;
539
540 if (-1 == (buflen = recvmsg(sock, &msg, 0)))
541 {
542 logmsg(LOG_ERR, "read error on raw socket\n");
543 return rewrite;
544 }
545
546 if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
547 {
548 logmsg(LOG_ERR, "truncated message\n");
549 return rewrite;
550 }
551
552 /* Find our packet information (asked for by the IP6_RECVPKTINFO). */
553 for (cmsgp = CMSG_FIRSTHDR(&msg); cmsgp != NULL;
554 cmsgp = CMSG_NXTHDR(&msg, cmsgp))
555 {
556 if (cmsgp->cmsg_len == 0)
557 {
558 logmsg(LOG_ERR, "ancillary data with zero length.\n");
559 return rewrite;
560 }
561
562 if ((cmsgp->cmsg_level == IPPROTO_IPV6) && (cmsgp->cmsg_type
563 == IPV6_PKTINFO))
564 {
565 pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
566 }
567 }
568
569 if (NULL != pktinfo)
570 {
571 /* Convert it to an interface name. */
572 if (NULL == if_indextoname(pktinfo->ipi6_ifindex, ifname))
573 {
574 logmsg(LOG_ERR, "couldn't find interface name: index %d\n",
575 pktinfo->ipi6_ifindex);
576 strncpy(ifname, "<none>", IFNAMSIZ);
577 }
578 }
579 else
580 {
581 logmsg(LOG_ERR, "couldn't get ancillary data for packet.");
582 strncpy(ifname, "<none>", IFNAMSIZ);
583 }
584
585 if (verbose > 0)
586 {
587 char srcaddrstr[INET6_ADDRSTRLEN];
588
589 if (NULL == inet_ntop(AF_INET6, &src.sin6_addr, srcaddrstr,
590 INET6_ADDRSTRLEN))
591 {
592 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
593 return rewrite;
594 }
595
596 printf("Received an IPv6 Router Advertisement from %s on interface "
597 "%s\n", srcaddrstr, ifname);
598
599 if (NULL == inet_ntop(AF_INET6, &pktinfo->ipi6_addr, srcaddrstr,
600 INET6_ADDRSTRLEN))
601 {
602 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
603 return rewrite;
604 }
605
606 printf("Sent to: %s\n", srcaddrstr);
607 }
608
609 if (verbose > 2)
610 {
611 hexdump(buf, buflen);
612 }
613
614 /*
615 * Keep buf and buflen pristine for possible later use. Walk the
616 * buffer with datap.
617 */
618 datap = buf;
619 lenleft = buflen;
620
621 /* Get the router advertisement. */
622 ra = (struct nd_router_advert *)datap;
623
624 /* Check that it really is an RA, code 134 */
625 if (ra->nd_ra_type != ND_ROUTER_ADVERT && ra->nd_ra_code != 0)
626 {
627 logmsg(LOG_INFO, "Not a Router Advertisement. Type: %d, code: %d. "
628 "Why did we get it?\n",
629 ra->nd_ra_type, ra->nd_ra_code);
630 return rewrite;
631 }
632
633 /*
634
635 RFC 4861, Neighbor Discovery for IP version 6 (IPv6), which defines
636 Router Advertisements says they look like this:
637
638 0 1 2 3
639 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
640 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
641 | Type | Code | Checksum |
642 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
643 | Cur Hop Limit |M|O| Reserved | Router Lifetime |
644 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
645 | Reachable Time |
646 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
647 | Retrans Timer |
648 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649 | Options ...
650 +-+-+-+-+-+-+-+-+-+-+-+-
651 */
652
653 if (verbose > 1)
654 {
655 printf("ICMP6 header\n");
656 printf(" nd_ra_type: %d\n", ra->nd_ra_type);
657 printf(" nd_ra_code: %d\n", ra->nd_ra_code);
658 printf(" nd_ra_cksum: %d\n", ra->nd_ra_cksum);
659
660 printf("RA:\n");
661 printf("...\n");
662 printf(" nd_ra_reachable: %ld\n", (long)ra->nd_ra_reachable);
663 printf(" nd_ra_retransmit: %ld\n", (long)ra->nd_ra_retransmit);
664 }
665
666 /* Move pass the RA header to any options we might find. */
667 datap += sizeof (struct nd_router_advert);
668 lenleft -= sizeof (struct nd_router_advert);
669
670 if (0 >= lenleft)
671 {
672 /* Out of data. */
673 logmsg(LOG_INFO, "Missing data after RA header.\n");
674 return rewrite;
675 }
676
677 /*
678 * Check for the options we want. We're looking for option RDNSS,
679 * 25.
680 */
681 if (verbose > 0)
682 {
683 printf("RA options:\n");
684 }
685 while (lenleft > 0)
686 {
687 int optlen;
688
689 /*
690 * This is what an option looks like:
691 *
692 * 0 1 2 3
693 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
694 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
695 * | Type | Length | ... |
696 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
697 * ~ ... ~
698 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
699 *
700 *
701 * Types:
702 *
703 * Source Link-Layer Address 1
704 * Target Link-Layer Address 2
705 * Prefix Information 3
706 * Redirected Header 4
707 * MTU 5
708 *
709 * RDNSS 25
710 *
711 * Length above is measured as a number of 64 bit components
712 * including the type and length bytes.
713 */
714
715 ndhdr = (struct nd_opt_hdr *)datap;
716
717 if (verbose > 0)
718 {
719 printf(" option type %d (0x%x)\n", ndhdr->nd_opt_type,
720 ndhdr->nd_opt_type);
721 }
722
723 /*
724 * The nd_opt_len is the number of 64 bit units the option
725 * contains including header.
726 */
727 optlen = ndhdr->nd_opt_len * 8;
728
729 if (verbose > 2)
730 {
731 printf(" option length in header: %d (0x%x)\n", ndhdr->nd_opt_len,
732 ndhdr->nd_opt_len);
733
734 printf(" actual length in bytes: %d\n", optlen);
735
736 hexdump(datap, optlen);
737 }
738
739 switch (ndhdr->nd_opt_type)
740 {
741 bool rb;
742
743 case ND_OPT_RDNSS:
744 rb = rdnss((const struct radns_opt_rdnss *)datap,
745 optlen, lenleft, reslist, storedres,
746 ifname);
747
748 rewrite = rewrite || rb;
749
750 break;
751
752 case ND_OPT_DNSSL:
753 rb = dnssl((const struct radns_opt_dnssl *)datap,
754 optlen, lenleft, suflist, storedsuf, ifname);
755
756 rewrite = rewrite || rb;
757
758 break;
759
760 default:
761 /* Not a known option. */
762 if (verbose > 1)
763 {
764 printf("Unknown RA option. Skipping...\n");
765 }
766 break;
767 } /* switch */
768
769 /* Advance beyond this option. */
770 datap += optlen;
771 lenleft -= optlen;
772 } /* while */
773
774 /* Tell caller if we need to rewrite resolv file. */
775 return rewrite;
776 }
777
778 /*
779 * Log a message either through syslog if we are daemonized or through
780 * stderr if we're running in the foreground.
781 *
782 * pri is the syslog priority, such as LOG_INFO, message is the string
783 * including format characters and the rest is optional variables
784 * referenced by the format characters.
785 *
786 */
logmsg(int pri,const char * message,...)787 static void logmsg(int pri, const char *message, ...)
788 {
789 va_list ap;
790
791 va_start(ap, message);
792
793 if (verbose > 0)
794 {
795 vfprintf(stderr, message, ap);
796 }
797 else
798 {
799 vsyslog(pri, message, ap);
800 }
801
802 va_end(ap);
803 }
804
805 /*
806 * Call an external script to handle, for instance, interfacing with
807 * the resolvconf program.
808 *
809 * filename is our own 'resolv.conf' and ifname is the name of the
810 * local interface where we received the RA.
811 *
812 * Returns 0 on success.
813 */
exithook(char * filename,char * ifname)814 static int exithook(char *filename, char *ifname)
815 {
816 pid_t pid;
817
818 if (NULL == scriptname)
819 {
820 /* No script. */
821 return 0;
822 }
823
824 pid = fork();
825 if (-1 == pid)
826 {
827 logmsg(LOG_ERR, "couldn't fork.\n");
828 return -1;
829 }
830 else if (0 == pid)
831 {
832 char *argv[2];
833 char *env[3];
834
835 /* We're in the child. */
836
837 argv[0] = scriptname;
838 argv[1] = NULL;
839
840 if (NULL == (env[0] = calloc(sizeof (char), 3 + 1 + strlen(ifname))))
841 {
842 logmsg(LOG_ERR, "out of memory.\n");
843 exit(1);
844 }
845 snprintf(env[0], 3 + 1 + strlen(ifname), "if=%s", ifname);
846
847 if (NULL == (env[1] = calloc(sizeof (char), 12 + 1 + strlen(filename))))
848 {
849 logmsg(LOG_ERR, "out of memory.\n");
850 exit(1);
851 }
852 snprintf(env[1], 12 + 1 + strlen(filename), "resolv_conf=%s", filename);
853
854 env[2] = NULL;
855
856 if (-1 == execve(scriptname, argv, env))
857 {
858 localerrno = errno;
859 logmsg(LOG_ERR, "couldn't exec(): %s\nexiting...\n",
860 strerror(localerrno));
861 exit(1);
862 }
863 } /* child */
864
865 return 0;
866 }
867
868 /*
869 * Write all the resolver addresses in list reslist in resolv file.
870 * Returns 0 if successful, -1 otherwise.
871 */
writeresolv(struct item * suflist,int storedsuf,struct item * reslist)872 static int writeresolv(struct item *suflist, int storedsuf,
873 struct item *reslist)
874 {
875 int filefd;
876 char buf[NSADDRSIZE];
877 char *tmpfn;
878 struct item *item;
879 struct resolver *res;
880 struct suffix *suf;
881
882 /*
883 * Create a temporary file in the same directory as our real
884 * resolver file.
885 */
886 if (-1 == asprintf(&tmpfn, "%s-work", filename))
887 {
888 logmsg(LOG_ERR, "Out of memory in writeresolv().\n");
889 return -1;
890 }
891
892 if (-1 == (filefd = open(tmpfn, O_CREAT | O_WRONLY | O_TRUNC, 0644)))
893 {
894 logmsg(LOG_ERR, "Couldn't open working file %s\n", tmpfn);
895 goto bad;
896 }
897
898 if (verbose > 2)
899 {
900 printf("Writing addresses to temporary file %s.\n", tmpfn);
901 }
902
903 if (storedsuf > 0)
904 {
905 if (-1 == write(filefd, "search ", 7))
906 {
907 perror("write");
908 goto bad;
909 }
910
911 /* Write search list to file. */
912 for (item = suflist; item != NULL; item = item->next)
913 {
914 suf = item->data;
915
916 /* FIXME: Do this in one write(). */
917 if (-1 == write(filefd, suf->name, suf->len))
918 {
919 perror("write");
920 goto bad;
921 }
922 if (-1 == write(filefd, " ", 1))
923 {
924 perror("write");
925 goto bad;
926 }
927 } /* for */
928
929 if (-1 == write(filefd, "\n", 1))
930 {
931 perror("write");
932 goto bad;
933 }
934 } /* if storedsuf */
935
936 /* Write addresses to file. */
937 for (item = reslist; item != NULL; item = item->next)
938 {
939 char addrstr[INET6_ADDRSTRLEN];
940
941 res = item->data;
942
943 if (NULL == inet_ntop(AF_INET6, &res->addr,
944 addrstr, INET6_ADDRSTRLEN))
945 {
946 logmsg(LOG_ERR, "Couldn't convert IPv6 address to "
947 "string\n");
948 }
949 else
950 {
951 if (-1 == snprintf(buf, NSADDRSIZE, "nameserver %s\n",
952 addrstr))
953 {
954 perror("asprintf");
955 goto bad;
956 }
957
958 if (-1 == write(filefd, buf, strlen(buf)))
959 {
960 perror("write");
961 goto bad;
962 }
963 }
964 } /* for */
965
966 /* Set file mode. */
967 if (-1 == fchmod(filefd, 0644))
968 {
969 localerrno = errno;
970 logmsg(LOG_ERR, "Couldn't set file mode on %s: %s\n", tmpfn,
971 strerror(localerrno));
972 goto bad;
973 }
974
975 close(filefd);
976
977 /* Rename the temporary file to the real resolv.conf file. */
978
979 if (verbose > 0)
980 {
981 printf("Creating resolver file %s.\n", filename);
982 }
983
984 if (-1 == (rename(tmpfn, filename)))
985 {
986 localerrno = errno;
987 logmsg(LOG_ERR, "Couldn't rename %s to %s: %s\n", tmpfn, filename,
988 strerror(localerrno));
989 goto bad;
990 }
991
992 free(tmpfn);
993 return 0;
994
995 bad:
996 close(filefd);
997 free(tmpfn);
998 return -1;
999 }
1000
1001 /*
1002 * Dump the contents of pointer buf of length len as 16 bytes (32
1003 * hexadecimal digits) per row.
1004 */
hexdump(uint8_t * buf,uint16_t len)1005 static void hexdump(uint8_t *buf, uint16_t len)
1006 {
1007 uint8_t *row; /* Pointer to rows of 16 bytes each. */
1008 uint8_t *byte; /* Pointer to each byte in the row. */
1009 uint8_t *max; /* Pointer to the maximum address in buf. */
1010
1011 /*
1012 * Start the row where the buffer begins. Remember where it ends
1013 * (max). Stop when row is at max.
1014 *
1015 * For every byte in each row, print the value. If we reach the
1016 * 16th byte, start a new row.
1017 */
1018 row = buf;
1019 max = &buf[len];
1020 for (byte = 0; byte != max; row = byte)
1021 {
1022 /* Print byte offset. */
1023 printf("%07tx ", row - buf);
1024
1025 for (byte = row; byte != max && byte != (row + 16); byte ++)
1026 {
1027 printf("%02x ", *byte);
1028 }
1029
1030 (void)putchar('\n');
1031 } /* Outer for */
1032 }
1033
1034 /* Prints a helpful message. */
printhelp(void)1035 static void printhelp(void)
1036 {
1037 fprintf(stderr, "Usage: %s [-v [-v] [-v]] [-f filename] [-l max suffixes ]"
1038 "\n[-m max resolvers] [-u user] [-s script] [-p pidfile ]\n",
1039 progname);
1040
1041 fprintf(stderr, "\n\n-f filename gives the filename the DNS resolving "
1042 "address is written to.\n Default is ./resolv.conf.\n");
1043 fprintf(stderr, "\n\n-l number-of-domain-suffixes sets an upper limit of "
1044 "how many domain suffixes\n to store in search list. 0 means no "
1045 "upper limit.\n");
1046 fprintf(stderr, "\n\n-m number-of-resolvers sets an upper limit of how "
1047 "many resolver addresses\n to store. 0 means no upper limit.\n");
1048 fprintf(stderr, "\n\n-u user sets username to drop privileges to. "
1049 "Default is 'radns'.\n");
1050 fprintf(stderr, "\n\n-s script executes 'script' after changing resolv "
1051 "file.\n");
1052 fprintf(stderr, "\n\n-p pidfile writes the process ID to 'pidfile'. "
1053 "By default it writes\n the process ID to %s.\n", PIDFILE);
1054
1055 fprintf(stderr, "\n\n-v means more verbosity. Repeat for more.\n");
1056 fprintf(stderr, "\n\n-V to get version information.\n");
1057 }
1058
1059 /* Signal handler for SIGCHLD. */
sigcatch(int sig)1060 void sigcatch(int sig)
1061 {
1062 if (SIGCHLD == sig)
1063 {
1064 /* A child process died. Tell main loop to deal with it. */
1065 childcare = true;
1066 }
1067 else
1068 {
1069 progdone = true;
1070 }
1071 }
1072
findsuffix(char * name,int namelen,struct item * suflist)1073 static struct suffix *findsuffix(char *name, int namelen, struct item *suflist)
1074 {
1075 struct item *item;
1076 struct suffix *suf;
1077
1078 for (item = suflist; item != NULL; item = item->next)
1079 {
1080 suf = item->data;
1081
1082 if (namelen == suf->len && 0 == memcmp(name, suf->name, suf->len))
1083 {
1084 return suf;
1085 }
1086 }
1087
1088 return NULL;
1089 }
1090
sufexpirenext(struct item * suflist)1091 static struct suffix *sufexpirenext(struct item *suflist)
1092 {
1093 time_t least = 0;
1094 struct suffix *suf;
1095 struct suffix *leastsuf = NULL;
1096 struct item *item;
1097
1098 for (item = suflist; item != NULL; item = item->next)
1099 {
1100 suf = item->data;
1101 if (0 != suf->expire)
1102 {
1103 if (0 == least || suf->expire < least)
1104 {
1105 least = suf->expire;
1106 leastsuf = suf;
1107 }
1108 }
1109 }
1110
1111 return leastsuf;
1112 }
1113
expiresuffix(struct item ** suflist,int * storedsuf)1114 static bool expiresuffix(struct item **suflist, int *storedsuf)
1115 {
1116 int expired = false;
1117 struct timespec now;
1118 struct item *item;
1119 struct suffix *suf;
1120
1121 if (-1 == clock_gettime(CLOCK_MONOTONIC, &now))
1122 {
1123 logmsg(LOG_ERR, "Couldn't get current time. Can't expire.\n");
1124 return expired;
1125 }
1126
1127 for (item = *suflist; item != NULL; item = item->next)
1128 {
1129 suf = item->data;
1130 if (NEVEREXP == (unsigned) suf->expire)
1131 {
1132 break;
1133 }
1134
1135 if (0 != suf->expire && suf->expire <= now.tv_sec)
1136 {
1137 expired = true;
1138
1139 freeitem(suflist, storedsuf, suf->item);
1140
1141 if (verbose > 1)
1142 {
1143 printf("Suffix expired.\n");
1144 }
1145 }
1146 } /* for */
1147
1148 return expired;
1149 }
1150
1151 /*
1152 * Add or update a domain name suffix in list suflist. Returns true if
1153 * we need to rewrite the resolv file.
1154 */
addsuffix(struct item ** suflist,int * storedsuf,uint32_t ttl,char * name,int namelen,char * ifname)1155 static bool addsuffix(struct item **suflist, int *storedsuf, uint32_t ttl,
1156 char *name, int namelen, char *ifname)
1157 {
1158 struct timespec now;
1159 struct suffix *suf;
1160 struct item *item;
1161
1162 if (-1 == clock_gettime(CLOCK_MONOTONIC, &now))
1163 {
1164 logmsg(LOG_ERR, "Couldn't get current time. Can't set expire time.\n");
1165 now.tv_sec = 0;
1166 }
1167
1168 /* Do we know this address already? */
1169 suf = findsuffix(name, namelen, *suflist);
1170
1171 if (verbose > 0)
1172 {
1173 printf("New suffix is ");
1174
1175 if (NULL == suf)
1176 {
1177 printf("unknown.\n");
1178 }
1179 else
1180 {
1181 printf("already known.\n");
1182 }
1183 }
1184
1185 if (NULL != suf)
1186 {
1187 /* Yes we know this suffix. */
1188 if (0 == ttl)
1189 {
1190 /*
1191 * TTL from RA is 0, so we're asked to delete this domain
1192 * suffix. Requires rewriting of file. Finished.
1193 */
1194 if (verbose > 0)
1195 {
1196 printf("We have been asked to remove it, so we do.\n");
1197 }
1198
1199 freeitem(suflist, storedsuf, suf->item);
1200 return true;
1201 }
1202 else
1203 {
1204 /*
1205 * Time to live != 0: Increase expire time or set the
1206 * resolver to never expire. Doesn't require rewriting.
1207 * Finished.
1208 */
1209 if (verbose > 0)
1210 {
1211 printf("Updating ttl with %d seconds from now.\n", ttl);
1212 }
1213 if (NEVEREXP == ttl)
1214 {
1215 suf->neverexp = true;
1216 }
1217 else
1218 {
1219 suf->expire = now.tv_sec + ttl;
1220 }
1221
1222 return false;
1223 }
1224 }
1225 else
1226 {
1227 /*
1228 * The new suffix is unknown to us.
1229 *
1230 * Insert at head. If the list has a maximum number of items
1231 * and we're full, replace the suffix about to expire next.
1232 *
1233 * Requires rewriting of resolv file.
1234 *
1235 */
1236
1237 if (verbose > 1)
1238 {
1239 printf("%d suffixes of max %d already stored.\n", *storedsuf,
1240 maxsuf);
1241 }
1242
1243 /* 0 is the special case of unlimited number of elements. */
1244 if (0 != maxsuf && *storedsuf == maxsuf)
1245 {
1246 /*
1247 * We're full. Find the first to expire and replace that.
1248 */
1249 if (verbose > 1)
1250 {
1251 printf("We're full. Finding a suffix to replace.");
1252 }
1253 suf = sufexpirenext(*suflist);
1254 }
1255 else
1256 {
1257 if (verbose > 1)
1258 {
1259 printf("Adding a new suffix.\n");
1260 }
1261
1262 item = additem(suflist);
1263 if (NULL == item)
1264 {
1265 logmsg(LOG_ERR, "Couldn't allocate memory for new suffix.\n");
1266 return false;
1267 }
1268
1269 suf = malloc(sizeof (struct suffix));
1270 if (NULL == suf)
1271 {
1272 logmsg(LOG_ERR, "Couldn't allocate memory for new suffix.\n");
1273 delitem(suflist, item);
1274 return false;
1275 }
1276
1277 item->data = suf;
1278 suf->item = item;
1279
1280 (*storedsuf) ++;
1281 }
1282
1283 memcpy(suf->name, name, namelen);
1284 suf->len = namelen;
1285 strncpy(suf->ifname, ifname, IFNAMSIZ);
1286
1287 if (NEVEREXP == ttl)
1288 {
1289 if (verbose > 2)
1290 {
1291 printf("Never expire.\n");
1292 }
1293 suf->neverexp = true;
1294 }
1295 else
1296 {
1297 if (verbose > 2)
1298 {
1299 printf("New expire is now (%d) + ttl (%d) = %d\n", (int)now.tv_sec,
1300 ttl, (int)now.tv_sec + ttl);
1301 }
1302 suf->expire = now.tv_sec + ttl;
1303 }
1304
1305 return true;
1306 }
1307 }
1308
1309 /*
1310 * Add or update a resolver address in list reslist. Returns true if
1311 * we need to rewrite the resolv file.
1312 *
1313 * storedres - pointer to number of stored resolvers.
1314 * ttl - time to live as from RA.
1315 * addr - the IPv6 address to the resolver.
1316 * ifname - interface name string
1317 */
addresolver(struct item ** reslist,int * storedres,uint32_t ttl,struct in6_addr addr,char * ifname)1318 static bool addresolver(struct item **reslist, int *storedres, uint32_t ttl,
1319 struct in6_addr addr, char *ifname)
1320 {
1321 struct timespec now;
1322 struct resolver *res;
1323 struct item *item;
1324
1325 if (-1 == clock_gettime(CLOCK_MONOTONIC, &now))
1326 {
1327 logmsg(LOG_ERR, "Couldn't get current time. Can't set expire time.\n");
1328 now.tv_sec = 0;
1329 }
1330
1331 /* Do we know this address already? */
1332 res = findresolv(addr, *reslist);
1333
1334 if (verbose > 0)
1335 {
1336 char addrstr[INET6_ADDRSTRLEN];
1337
1338 if (NULL == inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN))
1339 {
1340 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string.\n");
1341 return false;
1342 }
1343
1344 printf("%s is ", addrstr);
1345 if (NULL == res)
1346 {
1347 printf("unknown.\n");
1348 }
1349 else
1350 {
1351 printf("already known.\n");
1352 }
1353 }
1354
1355 if (NULL != res)
1356 {
1357 /* Yes we know this address. */
1358 if (0 == ttl)
1359 {
1360 /*
1361 * TTL from RA is 0, so we're asked to delete this
1362 * resolver. Requires rewriting of file. Finished.
1363 */
1364 if (verbose > 0)
1365 {
1366 printf("We have been asked to remove it, so we do.\n");
1367 }
1368
1369 freeitem(reslist, storedres, res->item);
1370
1371 return true;
1372 }
1373 else
1374 {
1375 /*
1376 * Time to live != 0: Increase expire time or set the
1377 * resolver to never expire. Doesn't require rewriting.
1378 * Finished.
1379 */
1380 if (verbose > 0)
1381 {
1382 printf("Updating ttl with %d seconds from now.\n", ttl);
1383 }
1384 if (NEVEREXP == ttl)
1385 {
1386 res->neverexp = true;
1387 }
1388 else
1389 {
1390 res->expire = now.tv_sec + ttl;
1391 }
1392
1393 return false;
1394 }
1395 }
1396 else
1397 {
1398 /*
1399 * The new resolver is unknown to us.
1400 *
1401 * Insert at head. If the list has a maximum number of items
1402 * and we're full, replace the resolver about to expire next.
1403 *
1404 * Requires rewriting of resolv file.
1405 *
1406 */
1407
1408 if (verbose > 1)
1409 {
1410 printf("%d resolvers of max %d already stored.\n", *storedres,
1411 maxres);
1412 }
1413
1414 /* 0 is the special case of unlimited number of elements. */
1415 if (0 != maxres && *storedres == maxres)
1416 {
1417 /*
1418 * We're full. Find the first address to expire and
1419 * replace that.
1420 */
1421 if (verbose > 1)
1422 {
1423 printf("We're full. Finding a resolver to replace.");
1424 }
1425 res = expirenext(*reslist);
1426 }
1427 else
1428 {
1429 /* We have room. Add new item. */
1430 if (verbose > 1)
1431 {
1432 printf("Adding a new resolver.\n");
1433 }
1434
1435 item = additem(reslist);
1436 if (NULL == item)
1437 {
1438 logmsg(LOG_ERR, "Couldn't allocate memory for new resolver.\n");
1439 return false;
1440 }
1441
1442 res = malloc(sizeof (struct resolver));
1443 if (NULL == res)
1444 {
1445 logmsg(LOG_ERR, "Couldn't allocate memory for new resolver.\n");
1446 delitem(reslist, item);
1447 return false;
1448 }
1449
1450 item->data = res;
1451 res->item = item;
1452 (*storedres) ++;
1453 }
1454
1455 memcpy(&res->addr, &addr, sizeof (struct in6_addr));
1456 strncpy(res->ifname, ifname, IFNAMSIZ);
1457
1458 if (NEVEREXP == ttl)
1459 {
1460 if (verbose > 2)
1461 {
1462 printf("Never expire.\n");
1463 }
1464 res->neverexp = true;
1465 }
1466 else
1467 {
1468 if (verbose > 2)
1469 {
1470 printf("New expire is now (%d) + ttl (%d) = %d\n", (int)now.tv_sec,
1471 ttl, (int)now.tv_sec + ttl);
1472 }
1473 res->expire = now.tv_sec + ttl;
1474 }
1475
1476 return true;
1477 }
1478 }
1479
1480 /*
1481 * Delete any expired DNS resolvers in list reslist with storedres
1482 * number of resolvers. Returns need to rewrite.
1483 */
expireresolv(struct item ** reslist,int * storedres)1484 static bool expireresolv(struct item **reslist, int *storedres)
1485 {
1486 int expired = false;
1487 struct timespec now;
1488 struct item *item;
1489 struct resolver *res;
1490
1491 if (-1 == clock_gettime(CLOCK_MONOTONIC, &now))
1492 {
1493 logmsg(LOG_ERR, "Couldn't get current time. Can't expire.\n");
1494 return expired;
1495 }
1496
1497 for (item = *reslist; item != NULL; item = item->next)
1498 {
1499 res = item->data;
1500 if (NEVEREXP == (unsigned) res->expire)
1501 {
1502 break;
1503 }
1504
1505 if (0 != res->expire && res->expire <= now.tv_sec)
1506 {
1507 expired = true;
1508
1509 freeitem(reslist, storedres, res->item);
1510
1511 if (verbose > 1)
1512 {
1513 char srcaddrstr[INET6_ADDRSTRLEN];
1514
1515 if (NULL == inet_ntop(AF_INET6, &res->addr,
1516 srcaddrstr, INET6_ADDRSTRLEN))
1517 {
1518 logmsg(LOG_ERR, "Couldn't convert IPv6 address to "
1519 "string\n");
1520 }
1521 else
1522 {
1523 printf("Resolver %s expired.\n", srcaddrstr);
1524 }
1525 }
1526 } /* if expire */
1527 } /* for */
1528
1529 return expired;
1530 }
1531
1532 /*
1533 * Write a file with the current process ID.
1534 *
1535 * Returns 0 on success.
1536 */
mkpidfile(uid_t owner,gid_t group)1537 static int mkpidfile(uid_t owner, gid_t group)
1538 {
1539 int filefd;
1540 char *buf = NULL;
1541 int rc = 0;
1542
1543 if (-1 == (filefd = open(pidfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644)))
1544 {
1545 logmsg(LOG_ERR, "couldn't open pidfile %s\n", pidfilename);
1546 rc = -1;
1547 goto end;
1548 }
1549
1550 if (-1 == asprintf(&buf, "%u\n", (unsigned) getpid()))
1551 {
1552 logmsg(LOG_ERR, "couldn't allocate memory for pid\n");
1553 rc = -1;
1554 goto end;
1555 }
1556
1557 if (-1 == write(filefd, buf, strlen(buf)))
1558 {
1559 localerrno = errno;
1560 logmsg(LOG_ERR, "couldn't write pid: %s\n", strerror(localerrno));
1561 rc = -1;
1562 goto end;
1563 }
1564
1565 /*
1566 * Change owner of file to our new user so we are allowed to
1567 * remove it later, after dropping privileges.
1568 */
1569 if (0 != lchown(pidfilename, owner, group))
1570 {
1571 localerrno = errno;
1572 logmsg(LOG_ERR, "couldn't change owner of file %s\n", pidfilename,
1573 strerror(localerrno));
1574 rc = -1;
1575 goto end;
1576 }
1577
1578 end:
1579 close(filefd);
1580
1581 if (NULL != buf)
1582 {
1583 free(buf);
1584 }
1585
1586 return rc;
1587 }
1588
1589 #ifdef TEST
1590 /*
1591 * Delete the resolver with address addr in list reslist.
1592 */
deladdr(struct item ** reslist,int * storedres,struct in6_addr addr)1593 static void deladdr(struct item **reslist, int *storedres, struct in6_addr addr)
1594 {
1595 struct resolver *res;
1596
1597 res = findresolv(addr, *reslist);
1598 if (NULL == res)
1599 {
1600 }
1601 else
1602 {
1603 freeitem(reslist, storedres, res->item);
1604 }
1605 }
1606
1607 /*
1608 * Print a list of all domain suffixes in suflist to stdout.
1609 */
listsuf(struct item * suflist)1610 static void listsuf(struct item *suflist)
1611 {
1612 struct item *item;
1613 struct suffix *suf;
1614 int i;
1615
1616 for (item = suflist, i = 1; item != NULL; item = item->next, i ++)
1617 {
1618 suf = item->data;
1619
1620 printf("%i: received on if %s, expires at %d\n", i,
1621 suf->ifname, (int)suf->expire);
1622
1623 write(1, suf->name, suf->len);
1624 putchar('\n');
1625 }
1626 }
1627
1628
1629 /*
1630 * Print a list of all resolvers in reslist to stdout.
1631 */
listres(struct item * reslist)1632 static void listres(struct item *reslist)
1633 {
1634 struct item *item;
1635 struct resolver *res;
1636 int i;
1637 char addrstr[INET6_ADDRSTRLEN];
1638
1639 for (item = reslist, i = 1; item != NULL; item = item->next, i ++)
1640 {
1641 res = item->data;
1642 if (0 == res->expire)
1643 {
1644 printf("%i: empty.\n", i);
1645 }
1646 else
1647 {
1648 if (NULL == inet_ntop(AF_INET6, &res->addr,
1649 addrstr, INET6_ADDRSTRLEN))
1650 {
1651 logmsg(LOG_ERR, "Couldn't convert IPv6 address to "
1652 "string\n");
1653 }
1654 else
1655 {
1656 printf("%i: %s, if %s, expire at %d\n", i, addrstr,
1657 res->ifname, (int)res->expire);
1658 }
1659 }
1660 }
1661 }
1662
1663 /*
1664 * Print on stdout if we need to rewrite or not.
1665 */
printrewrite(bool rewrite)1666 static void printrewrite(bool rewrite)
1667 {
1668 if (rewrite)
1669 {
1670 printf("Rewrite.\n");
1671 }
1672 else
1673 {
1674 printf("No rewrite.\n");
1675 }
1676 }
1677
1678 #endif
1679
1680 /************************************************************************/
1681 /* Test main */
1682 /************************************************************************/
1683 #ifdef TEST
main(void)1684 int main(void)
1685 {
1686 struct item *reslist = NULL; /* Linked list of resolvers. */
1687 struct item *suflist = NULL; /* Linked list of domain suffixes. */
1688 int storedres = 0;
1689 int storedsuf = 0;
1690 struct in6_addr addr;
1691 bool rewrite;
1692 struct suffix *suf;
1693
1694 char domain[MAXNAME];
1695 int domainlen;
1696
1697 domainlen = dnsname(domain, (uint8_t *)"\007example\003com\000", 13);
1698
1699 printf("Domain length %d\n", domainlen);
1700 hexdump((uint8_t *)domain, domainlen);
1701
1702 domainlen = dnsname(domain, (uint8_t *)"\007example\003com\000foobar",
1703 13 + 6);
1704
1705 printf("Domain length %d\n", domainlen);
1706 hexdump((uint8_t *)domain, domainlen);
1707
1708 printf("Suffixes (should be none)\n");
1709 listsuf(suflist);
1710
1711 printf("Adding hack.org.\n");
1712 rewrite = addsuffix(&suflist, &storedsuf, 30, "hack.org.", 9, "em0");
1713 printrewrite(rewrite);
1714 listsuf(suflist);
1715
1716 suf = sufexpirenext(suflist);
1717
1718 printf("Deleting suffix.\n");
1719 freeitem(&suflist, &storedsuf, suf->item);
1720 listsuf(suflist);
1721
1722 printf("Resolvers (should be none):\n");
1723 listres(reslist);
1724
1725 /* Add a new resolver. */
1726 puts("\n1:");
1727 if (-1 == inet_pton(AF_INET6, "::1", &addr))
1728 {
1729 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1730 exit(1);
1731 }
1732 rewrite = addresolver(&reslist, &storedres, 30, addr, "em0");
1733 printrewrite(rewrite);
1734 listres(reslist);
1735 sleep(1);
1736
1737 puts("\nAdd the same again:");
1738 if (-1 == inet_pton(AF_INET6, "::1", &addr))
1739 {
1740 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1741 exit(1);
1742 }
1743 rewrite = addresolver(&reslist, &storedres, 30, addr, "em0");
1744 printrewrite(rewrite);
1745 listres(reslist);
1746 sleep(1);
1747
1748 /* Add a new resolver. */
1749 puts("\n3:");
1750 if (-1 == inet_pton(AF_INET6, "fe80::216:d3ff:fe21:5a5a", &addr))
1751 {
1752 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1753 exit(1);
1754 }
1755 rewrite = addresolver(&reslist,&storedres, 120, addr, "em0");
1756 printrewrite(rewrite);
1757 listres(reslist);
1758 sleep(1);
1759
1760 /* Delete a resolver. */
1761 if (-1 == inet_pton(AF_INET6, "::1", &addr))
1762 {
1763 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1764 exit(1);
1765 }
1766 printf("Deleting ::1.\n");
1767 deladdr(&reslist, &storedres, addr);
1768
1769 /* Add a new resolver. */
1770 puts("\n4:");
1771 if (-1 == inet_pton(AF_INET6, "2001::216:d3ff:fe21:5a5a", &addr))
1772 {
1773 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1774 exit(1);
1775 }
1776 rewrite = addresolver(&reslist,&storedres, 120, addr, "em0");
1777 printrewrite(rewrite);
1778 listres(reslist);
1779 sleep(1);
1780
1781 /* Add a new resolver. */
1782 puts("\n5:");
1783 if (-1 == inet_pton(AF_INET6, "2001:16d8:ffff:1:213:2ff:fe0e:9cfa", &addr))
1784 {
1785 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1786 exit(1);
1787 }
1788 rewrite = addresolver(&reslist,&storedres, 120, addr, "wlan1");
1789 printrewrite(rewrite);
1790 listres(reslist);
1791 sleep(1);
1792
1793 /* Add a new resolver. */
1794 puts("\n6:");
1795 if (-1 == inet_pton(AF_INET6, "2001:16d8:ffff:1:213:2ff:cafe:babe", &addr))
1796 {
1797 logmsg(LOG_ERR, "Couldn't convert IPv6 address to string\n");
1798 exit(1);
1799 }
1800 rewrite = addresolver(&reslist,&storedres, 120, addr, "wlan1");
1801 printrewrite(rewrite);
1802 listres(reslist);
1803 sleep(1);
1804
1805 delallitems(&reslist, &storedres);
1806
1807 exit(0);
1808 }
1809 #else
1810 /************************************************************************/
1811 /* Real main */
1812 /************************************************************************/
main(int argc,char ** argv)1813 int main(int argc, char **argv)
1814 {
1815 char ch; /* Option character */
1816 int sock; /* Raw socket file descriptor */
1817 struct icmp6_filter filter; /* Filter for raw socket. */
1818 int on; /* Just a flag for setsockopts... */
1819 fd_set in;
1820 int found;
1821 char *user = USER; /* Username we will run as. */
1822 struct passwd *pw; /* User data, for uid and gid. */
1823 struct sigaction sigact; /* Signal handler. */
1824 struct stat sb; /* For stat() */
1825 struct item *reslist = NULL; /* List of resolver addresses. */
1826 int storedres = 0; /* Number of addresses in list. */
1827 struct item *suflist = NULL; /* List of domain suffixes. */
1828 int storedsuf = 0; /* Number of suffixes in list. */
1829 char ifname[IFNAMSIZ]; /* Name of local interface. */
1830
1831 progname = argv[0];
1832
1833 /* Install signal handlers. */
1834
1835 sigact.sa_flags = 0;
1836 sigact.sa_handler = sigcatch;
1837 sigemptyset(&sigact.sa_mask);
1838
1839 sigaction(SIGCHLD, &sigact, NULL);
1840 sigaction(SIGINT, &sigact, NULL);
1841 sigaction(SIGQUIT, &sigact, NULL);
1842 sigaction(SIGTERM, &sigact, NULL);
1843
1844 sigact.sa_handler = SIG_IGN;
1845 sigaction(SIGHUP, &sigact, NULL);
1846
1847 while (1)
1848 {
1849 ch = getopt(argc, argv, "f:l:m:s:p:u:vV");
1850 if (-1 == ch)
1851 {
1852 /* No more options, break out of while loop. */
1853 break;
1854 }
1855
1856 switch (ch)
1857 {
1858 case 'f':
1859 filename = optarg;
1860 break;
1861 case 'l':
1862 maxsuf = atoi(optarg);
1863 break;
1864 case 'm':
1865 maxres = atoi(optarg);
1866 break;
1867 case 'p':
1868 pidfilename = optarg;
1869 break;
1870 case 's':
1871 scriptname = optarg;
1872 break;
1873 case 'u':
1874 user = optarg;
1875 break;
1876 case 'v':
1877 verbose ++;
1878 break;
1879 case 'V':
1880 fprintf(stderr, "radns version %s\n", VERSION);
1881 exit(0);
1882 break;
1883 default:
1884 printhelp();
1885 exit(1);
1886 }
1887 } /* while */
1888
1889 if (-1 == (sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)))
1890 {
1891 logmsg(LOG_ERR, "Error from socket(). Perhaps you're not running as "
1892 "root? Terminating.\n");
1893 exit(1);
1894 }
1895
1896 /*
1897 * Daemonize if we're not told to do otherwise. Don't change
1898 * directory to /, though.
1899 */
1900 if (0 == verbose)
1901 {
1902 openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_DAEMON);
1903
1904 if (0 != daemon(1, 0))
1905 {
1906 logmsg(LOG_ERR, "Error from daemon(). Terminating.\n");
1907 exit(1);
1908 }
1909 }
1910
1911 /* Get user information. */
1912 if (NULL == (pw = getpwnam(user)))
1913 {
1914 logmsg(LOG_ERR, "couldn't find user '%s'.\n", user);
1915 exit(1);
1916 }
1917
1918 /* Write our pid to a file. We still need to be root to be able to
1919 * write to /var/run...
1920 */
1921 if (-1 == mkpidfile(pw->pw_uid, pw->pw_gid))
1922 {
1923 logmsg(LOG_ERR, "Couldn't create pid file.\n");
1924 }
1925
1926 /* Dropping privileges. */
1927 /* FIXME: setgroups() as well? */
1928 if (0 != setgid(pw->pw_gid) || 0 != setuid(pw->pw_uid))
1929 {
1930 logmsg(LOG_ERR, "couldn't drop privileges\n");
1931 exit(1);
1932 }
1933
1934 /****************** Now running as radns user. ******************/
1935
1936 /* Check if there's a script. */
1937 if (NULL != scriptname && 0 != stat(scriptname, &sb))
1938 {
1939 localerrno = errno;
1940 logmsg(LOG_ERR, "Script file %s: %s. Terminating.\n", scriptname,
1941 strerror(localerrno));
1942 exit(1);
1943 }
1944
1945 /* Initialize resolv file and make sure we can write to it early. */
1946 if (0 != writeresolv(suflist, storedsuf, reslist))
1947 {
1948 logmsg(LOG_ERR, "Couldn't create resolv file %s. Exiting...\n",
1949 filename);
1950 exit(1);
1951 }
1952
1953 /* Set a filter so we only get ICMPv6 packets. */
1954 ICMP6_FILTER_SETBLOCKALL(&filter);
1955 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
1956
1957 if (-1 == setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
1958 sizeof(filter)))
1959 {
1960 logmsg(LOG_ERR, "Error from setsockopt(). Terminating.\n");
1961 exit(1);
1962 }
1963
1964 /*
1965 * Ask for ancillary data with each ICMPv6 packet so we can get
1966 * the incoming interface name.
1967 */
1968 on = 1;
1969 if (-1 == setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
1970 sizeof(on)))
1971 {
1972 logmsg(LOG_ERR, "Error from setsockopt(). Terminating.\n");
1973 exit(1);
1974 }
1975
1976 /* Main loop. */
1977 for (progdone = false; !progdone; )
1978 {
1979 int status;
1980 bool newresolv = false;
1981 struct timeval tv;
1982 struct timespec now;
1983 struct resolver *res;
1984
1985 /* Figure out when to wake up. */
1986 if (-1 == clock_gettime(CLOCK_MONOTONIC, &now))
1987 {
1988 logmsg(LOG_ERR, "Couldn't get current time.\n");
1989 now.tv_sec = 0;
1990 now.tv_nsec = 0;
1991 }
1992
1993 res = expirenext(reslist);
1994 if (NULL == res)
1995 {
1996 tv.tv_sec = 0;
1997 }
1998 else
1999 {
2000 tv.tv_sec = res->expire - now.tv_sec;
2001 tv.tv_usec = 0;
2002 }
2003
2004 FD_ZERO(&in);
2005 FD_SET(sock, &in);
2006
2007 if (0 == tv.tv_sec)
2008 {
2009 /* No timeout. Block while waiting for incoming packet. */
2010 found = select(sock + 1, &in, NULL, NULL, NULL);
2011 }
2012 else
2013 {
2014 /* Wait for incoming packet or the next expire. */
2015 found = select(sock + 1, &in, NULL, NULL, &tv);
2016 }
2017
2018 if (-1 == found)
2019 {
2020 localerrno = errno;
2021 if (EINTR != localerrno)
2022 {
2023 logmsg(LOG_ERR, "select failed: %s\n", strerror(localerrno));
2024 exit(1);
2025 }
2026 }
2027 else
2028 {
2029 if (-1 != sock && FD_ISSET(sock, &in))
2030 {
2031 if (handle_icmp6(sock, &suflist, &storedsuf, &reslist,
2032 &storedres, ifname))
2033 {
2034 /* We got a new message and we need to rewrite. */
2035 newresolv = true;
2036 }
2037 } /* sock */
2038 } /* if found */
2039
2040 /* Check for expired DNS servers. */
2041 if (expireresolv(&reslist, &storedres))
2042 {
2043 /* Some resolvers expired. Maybe do something. */
2044 newresolv = true;
2045 }
2046
2047 /* Check for expired domain suffixes. */
2048 if (expiresuffix(&suflist, &storedsuf))
2049 {
2050 /* Some suffixes expired. Maybe do something. */
2051 newresolv = true;
2052 }
2053
2054 if (newresolv)
2055 {
2056 /* Write address(es) to file. */
2057 writeresolv(suflist, storedsuf, reslist);
2058
2059 /* Call external script, if any. */
2060 (void)exithook(filename, ifname);
2061
2062 newresolv = false;
2063 }
2064
2065 /* Reap any zombie exit hook script(s) we might have. */
2066 if (childcare)
2067 {
2068 while (-1 != waitpid(-1, &status, WNOHANG))
2069 ;
2070 childcare = false;
2071 }
2072
2073 } /* for */
2074
2075 logmsg(LOG_INFO, "Terminating.\n");
2076
2077 /* Free all resolvers and suffixes. Write an empty resolv file. */
2078 delallitems(&reslist, &storedres);
2079 delallitems(&suflist, &storedsuf);
2080 writeresolv(suflist, storedsuf, reslist);
2081
2082 exit(0);
2083 }
2084 #endif
2085