source: rtems-libbsd/dhcpcd/ipv6nd.c @ f2ed769

4.115-freebsd-12freebsd-9.3
Last change on this file since f2ed769 was f2ed769, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 30, 2014 at 12:29:46 PM

DHCPCD(8): Import

Import DHCPCD(8) from:

http://roy.marples.name/projects/dhcpcd/

The upstream sources can be obtained via:

fossil clone http://roy.marples.name/projects/dhcpcd

The imported version is 2014-01-29 19:46:44 [6b209507bb].

  • Property mode set to 100644
File size: 44.0 KB
Line 
1/*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2014 Roy Marples <roy@marples.name>
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/ioctl.h>
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/ip6.h>
34#include <netinet/icmp6.h>
35
36#ifdef __linux__
37#  define _LINUX_IN6_H
38#  include <linux/ipv6.h>
39#endif
40
41#include <errno.h>
42#include <stddef.h>
43#include <stdlib.h>
44#include <string.h>
45#include <syslog.h>
46#include <unistd.h>
47
48#define ELOOP_QUEUE 2
49#include "common.h"
50#include "dhcpcd.h"
51#include "dhcp6.h"
52#include "eloop.h"
53#include "ipv6.h"
54#include "ipv6nd.h"
55#include "script.h"
56
57#if defined(LISTEN_DAD) && defined(INET6)
58#  warning kernel does not report DAD results to userland
59#  warning listening to duplicated addresses on the wire
60#endif
61
62/* Debugging Router Solicitations is a lot of spam, so disable it */
63//#define DEBUG_RS
64
65#define RTR_SOLICITATION_INTERVAL       4 /* seconds */
66#define MAX_RTR_SOLICITATIONS           3 /* times */
67
68#ifndef ND_OPT_RDNSS
69#define ND_OPT_RDNSS                    25
70struct nd_opt_rdnss {           /* RDNSS option RFC 6106 */
71        uint8_t         nd_opt_rdnss_type;
72        uint8_t         nd_opt_rdnss_len;
73        uint16_t        nd_opt_rdnss_reserved;
74        uint32_t        nd_opt_rdnss_lifetime;
75        /* followed by list of IP prefixes */
76} __packed;
77#endif
78
79#ifndef ND_OPT_DNSSL
80#define ND_OPT_DNSSL                    31
81struct nd_opt_dnssl {           /* DNSSL option RFC 6106 */
82        uint8_t         nd_opt_dnssl_type;
83        uint8_t         nd_opt_dnssl_len;
84        uint16_t        nd_opt_dnssl_reserved;
85        uint32_t        nd_opt_dnssl_lifetime;
86        /* followed by list of DNS servers */
87} __packed;
88#endif
89
90/* Minimal IPv6 MTU */
91#ifndef IPV6_MMTU
92#define IPV6_MMTU 1280
93#endif
94
95#ifndef ND_RA_FLAG_RTPREF_HIGH
96#define ND_RA_FLAG_RTPREF_MASK          0x18
97#define ND_RA_FLAG_RTPREF_HIGH          0x08
98#define ND_RA_FLAG_RTPREF_MEDIUM        0x00
99#define ND_RA_FLAG_RTPREF_LOW           0x18
100#define ND_RA_FLAG_RTPREF_RSV           0x10
101#endif
102
103/* RTPREF_MEDIUM has to be 0! */
104#define RTPREF_HIGH     1
105#define RTPREF_MEDIUM   0
106#define RTPREF_LOW      (-1)
107#define RTPREF_RESERVED (-2)
108#define RTPREF_INVALID  (-3)    /* internal */
109
110#define MIN_RANDOM_FACTOR       500                             /* millisecs */
111#define MAX_RANDOM_FACTOR       1500                            /* millisecs */
112#define MIN_RANDOM_FACTOR_U     MIN_RANDOM_FACTOR * 1000        /* usecs */
113#define MAX_RANDOM_FACTOR_U     MAX_RANDOM_FACTOR * 1000        /* usecs */
114
115#if BYTE_ORDER == BIG_ENDIAN
116#define IPV6_ADDR_INT32_ONE     1
117#define IPV6_ADDR_INT16_MLL     0xff02
118#elif BYTE_ORDER == LITTLE_ENDIAN
119#define IPV6_ADDR_INT32_ONE     0x01000000
120#define IPV6_ADDR_INT16_MLL     0x02ff
121#endif
122
123/* Debugging Neighbor Solicitations is a lot of spam, so disable it */
124//#define DEBUG_NS
125//
126
127/* Currently, no known kernel allows us to send from the unspecified address
128 * which is required for DAD to work. This isn't that much of a problem as
129 * the kernel will do DAD for us correctly, however we don't know the exact
130 * randomness the kernel applies to the timeouts. So we just follow the same
131 * logic and have a little faith.
132 * This define is purely for completeness */
133// #define IPV6_SEND_DAD
134
135static int sock = -1;
136#ifdef IPV6_SEND_DAD
137static int unspec_sock = -1;
138#endif
139static struct sockaddr_in6 allrouters, from;
140static struct msghdr sndhdr;
141static struct iovec sndiov[2];
142static unsigned char *sndbuf;
143static struct msghdr rcvhdr;
144static struct iovec rcviov[2];
145static unsigned char *rcvbuf;
146static unsigned char ansbuf[1500];
147static char ntopbuf[INET6_ADDRSTRLEN];
148static const char *sfrom;
149static struct icmp6_filter filt;
150
151struct rahead ipv6_routers = TAILQ_HEAD_INITIALIZER(ipv6_routers);
152
153static void ipv6nd_handledata(void *arg);
154
155/*
156 * Android ships buggy ICMP6 filter headers.
157 * Supply our own until they fix their shit.
158 * References:
159 *     https://android-review.googlesource.com/#/c/58438/
160 *     http://code.google.com/p/android/issues/original?id=32621&seq=24
161 */
162#ifdef __ANDROID__
163#undef ICMP6_FILTER_WILLPASS
164#undef ICMP6_FILTER_WILLBLOCK
165#undef ICMP6_FILTER_SETPASS
166#undef ICMP6_FILTER_SETBLOCK
167#undef ICMP6_FILTER_SETPASSALL
168#undef ICMP6_FILTER_SETBLOCKALL
169#define ICMP6_FILTER_WILLPASS(type, filterp) \
170        ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
171#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
172        ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
173#define ICMP6_FILTER_SETPASS(type, filterp) \
174        ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
175#define ICMP6_FILTER_SETBLOCK(type, filterp) \
176        ((((filterp)->icmp6_filt[(type) >> 5]) |=  (1 << ((type) & 31))))
177#define ICMP6_FILTER_SETPASSALL(filterp) \
178        memset(filterp, 0, sizeof(struct icmp6_filter));
179#define ICMP6_FILTER_SETBLOCKALL(filterp) \
180        memset(filterp, 0xff, sizeof(struct icmp6_filter));
181#endif
182
183#if DEBUG_MEMORY
184static void
185ipv6nd_cleanup(void)
186{
187
188        free(sndbuf);
189        free(rcvbuf);
190}
191#endif
192
193static int
194ipv6nd_open(void)
195{
196        int on;
197        int len;
198#ifdef IPV6_SEND_DAD
199        union {
200                struct sockaddr sa;
201                struct sockaddr_in6 sin;
202        } su;
203#endif
204
205        sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
206        if (sock == -1)
207                return -1;
208
209        memset(&allrouters, 0, sizeof(allrouters));
210        allrouters.sin6_family = AF_INET6;
211#ifdef SIN6_LEN
212        allrouters.sin6_len = sizeof(allrouters);
213#endif
214        if (inet_pton(AF_INET6, ALLROUTERS, &allrouters.sin6_addr.s6_addr) != 1)
215                goto eexit;
216        on = 1;
217        if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
218                &on, sizeof(on)) == -1)
219                goto eexit;
220
221        on = 1;
222        if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
223                &on, sizeof(on)) == -1)
224                goto eexit;
225
226        ICMP6_FILTER_SETBLOCKALL(&filt);
227        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
228        if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
229                &filt, sizeof(filt)) == -1)
230                goto eexit;
231
232        set_cloexec(sock);
233#if DEBUG_MEMORY
234        atexit(ipv6nd_cleanup);
235#endif
236
237        len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
238        sndbuf = calloc(1, len);
239        if (sndbuf == NULL)
240                goto eexit;
241        sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
242        sndhdr.msg_iov = sndiov;
243        sndhdr.msg_iovlen = 1;
244        sndhdr.msg_control = sndbuf;
245        sndhdr.msg_controllen = len;
246        rcvbuf = calloc(1, len);
247        if (rcvbuf == NULL)
248                goto eexit;
249        rcvhdr.msg_name = &from;
250        rcvhdr.msg_namelen = sizeof(from);
251        rcvhdr.msg_iov = rcviov;
252        rcvhdr.msg_iovlen = 1;
253        rcvhdr.msg_control = rcvbuf;
254        rcvhdr.msg_controllen = len;
255        rcviov[0].iov_base = ansbuf;
256        rcviov[0].iov_len = sizeof(ansbuf);
257        return sock;
258
259eexit:
260        close(sock);
261        sock = -1;
262        free(sndbuf);
263        sndbuf = NULL;
264        free(rcvbuf);
265        rcvbuf = NULL;
266        return -1;
267}
268
269static int
270ipv6nd_naopen(void)
271{
272        static int naopen = 0;
273        struct icmp6_filter unspec_filt;
274#ifdef IPV6_SEND_DAD
275        union {
276                struct sockaddr sa;
277                struct sockaddr_in6 sin;
278        } su;
279#endif
280
281        if (naopen)
282                return sock;
283
284        ICMP6_FILTER_SETBLOCKALL(&unspec_filt);
285
286#ifdef IPV6_SEND_DAD
287        /* We send DAD requests from the unspecified address. */
288        unspec_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
289        if (unspec_sock == -1)
290                return -1;
291        if (setsockopt(unspec_sock, IPPROTO_ICMPV6, ICMP6_FILTER,
292            &unspec_filt, sizeof(unspec_filt)) == -1)
293                goto eexit;
294        memset(&su, 0, sizeof(su));
295        su.sin.sin6_family = AF_INET6;
296#ifdef SIN6_LEN
297        su.sin.sin6_len = sizeof(su.sin);
298#endif
299        if (bind(unspec_sock, &su.sa, sizeof(su.sin)) == -1)
300                goto eexit;
301#endif
302
303        if (sock == -1) {
304                if (ipv6nd_open() == -1)
305                        goto eexit;
306                eloop_event_add(sock, ipv6nd_handledata, NULL);
307        }
308
309        ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
310        if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
311            &filt, sizeof(filt)) == -1)
312                goto eexit;
313
314#ifdef LISTEN_DAD
315        syslog(LOG_WARNING, "kernel does not report DAD results to userland");
316        syslog(LOG_WARNING,
317            "warning listening to duplicated addresses on the wire");
318#endif
319
320        naopen = sock;
321        return sock;
322
323eexit:
324        syslog(LOG_ERR, "%s: %m", __func__);
325#ifdef IPV6_SEND_DAD
326        close(unspec_sock);
327        unspec_sock = -1;
328#endif
329        return -1;
330}
331
332static int
333ipv6nd_makersprobe(struct interface *ifp)
334{
335        struct rs_state *state;
336        struct nd_router_solicit *rs;
337        struct nd_opt_hdr *nd;
338
339        state = RS_STATE(ifp);
340        free(state->rs);
341        state->rslen = sizeof(*rs) + ROUNDUP8(ifp->hwlen + 2);
342        state->rs = calloc(1, state->rslen);
343        if (state->rs == NULL)
344                return -1;
345        rs = (struct nd_router_solicit *)(void *)state->rs;
346        rs->nd_rs_type = ND_ROUTER_SOLICIT;
347        rs->nd_rs_code = 0;
348        rs->nd_rs_cksum = 0;
349        rs->nd_rs_reserved = 0;
350        nd = (struct nd_opt_hdr *)(state->rs + sizeof(*rs));
351        nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
352        nd->nd_opt_len = (ROUNDUP8(ifp->hwlen + 2)) >> 3;
353        memcpy(nd + 1, ifp->hwaddr, ifp->hwlen);
354        return 0;
355}
356
357static void
358ipv6nd_sendrsprobe(void *arg)
359{
360        struct interface *ifp = arg;
361        struct rs_state *state;
362        struct sockaddr_in6 dst;
363        struct cmsghdr *cm;
364        struct in6_pktinfo pi;
365        int hoplimit = HOPLIMIT;
366
367        if (ipv6_linklocal(ifp) == NULL) {
368                syslog(LOG_DEBUG,
369                    "%s: delaying Router Solicitation for LL address",
370                    ifp->name);
371                ipv6_addlinklocalcallback(ifp, ipv6nd_sendrsprobe, ifp);
372                return;
373        }
374
375        dst = allrouters;
376        dst.sin6_scope_id = ifp->index;
377
378        state = RS_STATE(ifp);
379        sndhdr.msg_name = (caddr_t)&dst;
380        sndhdr.msg_iov[0].iov_base = state->rs;
381        sndhdr.msg_iov[0].iov_len = state->rslen;
382
383        /* Set the outbound interface */
384        cm = CMSG_FIRSTHDR(&sndhdr);
385        cm->cmsg_level = IPPROTO_IPV6;
386        cm->cmsg_type = IPV6_PKTINFO;
387        cm->cmsg_len = CMSG_LEN(sizeof(pi));
388        memset(&pi, 0, sizeof(pi));
389        pi.ipi6_ifindex = ifp->index;
390        memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
391
392        /* Hop limit */
393        cm = CMSG_NXTHDR(&sndhdr, cm);
394        cm->cmsg_level = IPPROTO_IPV6;
395        cm->cmsg_type = IPV6_HOPLIMIT;
396        cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
397        memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));
398
399        syslog(LOG_DEBUG, "%s: sending Router Solicitation", ifp->name);
400        if (sendmsg(sock, &sndhdr, 0) == -1) {
401                syslog(LOG_ERR, "%s: %s: sendmsg: %m", ifp->name, __func__);
402                ipv6nd_drop(ifp);
403                ifp->options->options &= ~(DHCPCD_IPV6 | DHCPCD_IPV6RS);
404                return;
405        }
406
407        if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
408                eloop_timeout_add_sec(RTR_SOLICITATION_INTERVAL,
409                    ipv6nd_sendrsprobe, ifp);
410        else
411                syslog(LOG_WARNING, "%s: no IPv6 Routers available", ifp->name);
412}
413
414static void
415ipv6nd_free_opts(struct ra *rap)
416{
417        struct ra_opt *rao;
418
419        while ((rao = TAILQ_FIRST(&rap->options))) {
420                TAILQ_REMOVE(&rap->options, rao, next);
421                free(rao->option);
422                free(rao);
423        }
424}
425
426int
427ipv6nd_addrexists(const struct ipv6_addr *addr)
428{
429        struct ra *rap;
430        struct ipv6_addr *ap;
431
432        TAILQ_FOREACH(rap, &ipv6_routers, next) {
433                TAILQ_FOREACH(ap, &rap->addrs, next) {
434                        if (addr == NULL) {
435                                if ((ap->flags &
436                                    (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) ==
437                                    (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED))
438                                        return 1;
439                        } else if (IN6_ARE_ADDR_EQUAL(&ap->addr, &addr->addr))
440                                return 1;
441                }
442        }
443        return 0;
444}
445
446void ipv6nd_freedrop_ra(struct ra *rap, int drop)
447{
448
449        eloop_timeout_delete(NULL, rap->iface);
450        eloop_timeout_delete(NULL, rap);
451        if (!drop)
452                TAILQ_REMOVE(&ipv6_routers, rap, next);
453        ipv6_freedrop_addrs(&rap->addrs, drop, NULL);
454        ipv6nd_free_opts(rap);
455        free(rap->data);
456        free(rap->ns);
457        free(rap);
458}
459
460ssize_t
461ipv6nd_free(struct interface *ifp)
462{
463        struct rs_state *state;
464        struct ra *rap, *ran;
465        ssize_t n;
466
467        state = RS_STATE(ifp);
468        if (state) {
469                free(state->rs);
470                free(state);
471                ifp->if_data[IF_DATA_IPV6ND] = NULL;
472        }
473        n = 0;
474        TAILQ_FOREACH_SAFE(rap, &ipv6_routers, next, ran) {
475                if (rap->iface == ifp) {
476                        ipv6nd_free_ra(rap);
477                        n++;
478                }
479        }
480        return n;
481}
482
483static int
484rtpref(struct ra *rap)
485{
486
487        switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
488        case ND_RA_FLAG_RTPREF_HIGH:
489                return (RTPREF_HIGH);
490        case ND_RA_FLAG_RTPREF_MEDIUM:
491        case ND_RA_FLAG_RTPREF_RSV:
492                return (RTPREF_MEDIUM);
493        case ND_RA_FLAG_RTPREF_LOW:
494                return (RTPREF_LOW);
495        default:
496                syslog(LOG_ERR, "rtpref: impossible RA flag %x", rap->flags);
497                return (RTPREF_INVALID);
498        }
499        /* NOTREACHED */
500}
501
502static void
503add_router(struct ra *router)
504{
505        struct ra *rap;
506
507        TAILQ_FOREACH(rap, &ipv6_routers, next) {
508                if (router->iface->metric < rap->iface->metric ||
509                    (router->iface->metric == rap->iface->metric &&
510                    rtpref(router) > rtpref(rap)))
511                {
512                        TAILQ_INSERT_BEFORE(rap, router, next);
513                        return;
514                }
515        }
516        TAILQ_INSERT_TAIL(&ipv6_routers, router, next);
517}
518
519static void
520ipv6nd_scriptrun(struct ra *rap)
521{
522        int hasdns;
523        struct ipv6_addr *ap;
524        const struct ra_opt *rao;
525
526        /* If all addresses have completed DAD run the script */
527        TAILQ_FOREACH(ap, &rap->addrs, next) {
528                if ((ap->flags & (IPV6_AF_ONLINK | IPV6_AF_AUTOCONF)) ==
529                    (IPV6_AF_ONLINK | IPV6_AF_AUTOCONF))
530                {
531                        if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
532                            ipv6_findaddr(ap->iface, &ap->addr))
533                                ap->flags |= IPV6_AF_DADCOMPLETED;
534                        if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
535                                syslog(LOG_DEBUG,
536                                    "%s: waiting for Router Advertisement"
537                                    " DAD to complete",
538                                    rap->iface->name);
539                                return;
540                        }
541                }
542        }
543
544        /* If we don't require RDNSS then set hasdns = 1 so we fork */
545        if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
546                hasdns = 1;
547        else {
548                hasdns = 0;
549                TAILQ_FOREACH(rao, &rap->options, next) {
550                        if (rao->type == ND_OPT_RDNSS &&
551                            rao->option &&
552                            timerisset(&rao->expire))
553                        {
554                                hasdns = 1;
555                                break;
556                        }
557                }
558        }
559
560        script_runreason(rap->iface, "ROUTERADVERT");
561        if (hasdns)
562                daemonise();
563#if 0
564        else if (options & DHCPCD_DAEMONISE &&
565            !(options & DHCPCD_DAEMONISED) && new_data)
566                syslog(LOG_WARNING,
567                    "%s: did not fork due to an absent"
568                    " RDNSS option in the RA",
569                    ifp->name);
570}
571#endif
572}
573
574static void
575ipv6nd_dadcallback(void *arg)
576{
577        struct ipv6_addr *ap = arg, *rapap;
578        struct interface *ifp;
579        struct ra *rap;
580        int wascompleted, found;
581
582        wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
583        ipv6nd_cancelprobeaddr(ap);
584        ap->flags |= IPV6_AF_DADCOMPLETED;
585        if (ap->flags & IPV6_AF_DUPLICATED)
586                /* No idea what how to try and make another address :( */
587                syslog(LOG_WARNING, "%s: DAD detected %s",
588                    ap->iface->name, ap->saddr);
589#ifdef IPV6_SEND_DAD
590        else
591                ipv6_addaddr(ap);
592#endif
593
594        if (!wascompleted) {
595                ifp = ap->iface;
596
597                TAILQ_FOREACH(rap, &ipv6_routers, next) {
598                        if (rap->iface != ifp)
599                                continue;
600                        wascompleted = 1;
601                        found = 0;
602                        TAILQ_FOREACH(rapap, &rap->addrs, next) {
603                                if (rapap->flags & IPV6_AF_AUTOCONF &&
604                                    (rapap->flags & IPV6_AF_DADCOMPLETED) == 0)
605                                {
606                                        wascompleted = 0;
607                                        break;
608                                }
609                                if (rapap == ap)
610                                        found = 1;
611                        }
612
613                        if (wascompleted && found && rap->lifetime) {
614                                syslog(LOG_DEBUG,
615                                    "%s: Router Advertisement DAD completed",
616                                    rap->iface->name);
617                                ipv6nd_scriptrun(rap);
618                        }
619                }
620        }
621}
622
623static void
624ipv6nd_handlera(struct interface *ifp, struct icmp6_hdr *icp, ssize_t len)
625{
626        ssize_t l, m, n, olen;
627        struct nd_router_advert *nd_ra;
628        struct nd_opt_prefix_info *pi;
629        struct nd_opt_mtu *mtu;
630        struct nd_opt_rdnss *rdnss;
631        struct nd_opt_dnssl *dnssl;
632        uint32_t lifetime, mtuv;
633        uint8_t *p, *op;
634        struct in6_addr addr;
635        char buf[INET6_ADDRSTRLEN];
636        const char *cbp;
637        struct ra *rap;
638        struct nd_opt_hdr *ndo;
639        struct ra_opt *rao;
640        struct ipv6_addr *ap;
641        char *opt, *tmp;
642        struct timeval expire;
643        uint8_t new_rap, new_data;
644
645        if ((size_t)len < sizeof(struct nd_router_advert)) {
646                syslog(LOG_ERR, "IPv6 RA packet too short from %s", sfrom);
647                return;
648        }
649
650        if (!IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) {
651                syslog(LOG_ERR, "RA from non local address %s", sfrom);
652                return;
653        }
654
655        if (ifp == NULL) {
656#ifdef DEBUG_RS
657                syslog(LOG_DEBUG, "RA for unexpected interface from %s", sfrom);
658#endif
659                return;
660        }
661        if (!(ifp->options->options & DHCPCD_IPV6RS)) {
662#ifdef DEBUG_RS
663                syslog(LOG_DEBUG, "%s: unexpected RA from %s",
664                    ifp->name, sfrom);
665#endif
666                return;
667        }
668
669        /* We could receive a RA before we sent a RS*/
670        if (ipv6_linklocal(ifp) == NULL) {
671#ifdef DEBUG_RS
672                syslog(LOG_DEBUG, "%s: received RA from %s (no link-local)",
673                    ifp->name, sfrom);
674#endif
675                return;
676        }
677
678        TAILQ_FOREACH(rap, &ipv6_routers, next) {
679                if (ifp == rap->iface &&
680                    memcmp(rap->from.s6_addr, from.sin6_addr.s6_addr,
681                    sizeof(rap->from.s6_addr)) == 0)
682                        break;
683        }
684
685        nd_ra = (struct nd_router_advert *)icp;
686        /* Don't bother doing anything if we don't know about a router
687         * expiring */
688        if ((rap == NULL || rap->lifetime == 0)
689            && nd_ra->nd_ra_router_lifetime == 0)
690                return;
691
692        /* We don't want to spam the log with the fact we got an RA every
693         * 30 seconds or so, so only spam the log if it's different. */
694        if (rap == NULL || (rap->data_len != len ||
695             memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
696        {
697                if (rap) {
698                        free(rap->data);
699                        rap->data_len = 0;
700                        free(rap->ns);
701                        rap->ns = NULL;
702                        rap->nslen = 0;
703                }
704                new_data = 1;
705        } else
706                new_data = 0;
707        if (new_data || ifp->options->options & DHCPCD_DEBUG)
708                syslog(LOG_INFO, "%s: Router Advertisement from %s",
709                    ifp->name, sfrom);
710
711        if (rap == NULL) {
712                rap = calloc(1, sizeof(*rap));
713                if (rap == NULL) {
714                        syslog(LOG_ERR, "%s: %m", __func__);
715                        return;
716                }
717                rap->iface = ifp;
718                memcpy(rap->from.s6_addr, from.sin6_addr.s6_addr,
719                    sizeof(rap->from.s6_addr));
720                strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
721                TAILQ_INIT(&rap->addrs);
722                TAILQ_INIT(&rap->options);
723                new_rap = 1;
724        } else
725                new_rap = 0;
726        if (rap->data_len == 0) {
727                rap->data = malloc(len);
728                if (rap->data == NULL) {
729                        syslog(LOG_ERR, "%s: %m", __func__);
730                        if (new_rap)
731                                free(rap);
732                        return;
733                }
734                memcpy(rap->data, icp, len);
735                rap->data_len = len;
736        }
737
738        get_monotonic(&rap->received);
739        rap->flags = nd_ra->nd_ra_flags_reserved;
740        if (new_rap == 0 && rap->lifetime == 0)
741                syslog(LOG_WARNING, "%s: %s router available",
742                   ifp->name, rap->sfrom);
743        rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
744        if (nd_ra->nd_ra_reachable) {
745                rap->reachable = ntohl(nd_ra->nd_ra_reachable);
746                if (rap->reachable > MAX_REACHABLE_TIME)
747                        rap->reachable = 0;
748        }
749        if (nd_ra->nd_ra_retransmit)
750                rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
751        if (rap->lifetime)
752                rap->expired = 0;
753
754        len -= sizeof(struct nd_router_advert);
755        p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
756        olen = 0;
757        lifetime = ~0U;
758        for (olen = 0; len > 0; p += olen, len -= olen) {
759                if ((size_t)len < sizeof(struct nd_opt_hdr)) {
760                        syslog(LOG_ERR, "%s: Short option", ifp->name);
761                        break;
762                }
763                ndo = (struct nd_opt_hdr *)p;
764                olen = ndo->nd_opt_len * 8 ;
765                if (olen == 0) {
766                        syslog(LOG_ERR, "%s: zero length option", ifp->name);
767                        break;
768                }
769                if (olen > len) {
770                        syslog(LOG_ERR,
771                            "%s: Option length exceeds message", ifp->name);
772                        break;
773                }
774
775                opt = NULL;
776                switch (ndo->nd_opt_type) {
777                case ND_OPT_PREFIX_INFORMATION:
778                        pi = (struct nd_opt_prefix_info *)(void *)ndo;
779                        if (pi->nd_opt_pi_len != 4) {
780                                syslog(LOG_ERR,
781                                    "%s: invalid option len for prefix",
782                                    ifp->name);
783                                break;
784                        }
785                        if (pi->nd_opt_pi_prefix_len > 128) {
786                                syslog(LOG_ERR, "%s: invalid prefix len",
787                                    ifp->name);
788                                break;
789                        }
790                        if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix) ||
791                            IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix))
792                        {
793                                syslog(LOG_ERR,
794                                    "%s: invalid prefix in RA", ifp->name);
795                                break;
796                        }
797                        if (ntohl(pi->nd_opt_pi_preferred_time) >
798                            ntohl(pi->nd_opt_pi_valid_time))
799                        {
800                                syslog(LOG_ERR,
801                                    "%s: pltime > vltime", ifp->name);
802                                break;
803                        }
804                        TAILQ_FOREACH(ap, &rap->addrs, next)
805                                if (ap->prefix_len ==pi->nd_opt_pi_prefix_len &&
806                                    memcmp(ap->prefix.s6_addr,
807                                    pi->nd_opt_pi_prefix.s6_addr,
808                                    sizeof(ap->prefix.s6_addr)) == 0)
809                                        break;
810                        if (ap == NULL) {
811                                if (!(pi->nd_opt_pi_flags_reserved &
812                                    ND_OPT_PI_FLAG_AUTO) &&
813                                    !(pi->nd_opt_pi_flags_reserved &
814                                    ND_OPT_PI_FLAG_ONLINK))
815                                        break;
816                                ap = calloc(1, sizeof(*ap));
817                                if (ap == NULL) {
818                                        syslog(LOG_ERR, "%s: %m", __func__);
819                                        break;
820                                }
821                                ap->iface = rap->iface;
822                                ap->flags = IPV6_AF_NEW;
823                                ap->prefix_len = pi->nd_opt_pi_prefix_len;
824                                memcpy(ap->prefix.s6_addr,
825                                   pi->nd_opt_pi_prefix.s6_addr,
826                                   sizeof(ap->prefix.s6_addr));
827                                if (pi->nd_opt_pi_flags_reserved &
828                                    ND_OPT_PI_FLAG_AUTO)
829                                {
830                                        ap->flags |= IPV6_AF_AUTOCONF;
831                                        ipv6_makeaddr(&ap->addr, ifp,
832                                            &ap->prefix,
833                                            pi->nd_opt_pi_prefix_len);
834                                        cbp = inet_ntop(AF_INET6,
835                                            ap->addr.s6_addr,
836                                            ntopbuf, INET6_ADDRSTRLEN);
837                                        if (cbp)
838                                                snprintf(ap->saddr,
839                                                    sizeof(ap->saddr),
840                                                    "%s/%d",
841                                                    cbp, ap->prefix_len);
842                                        else
843                                                ap->saddr[0] = '\0';
844                                } else {
845                                        memset(&ap->addr, 0, sizeof(ap->addr));
846                                        ap->saddr[0] = '\0';
847                                }
848                                ap->dadcallback = ipv6nd_dadcallback;
849                                TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
850                        }
851                        if (pi->nd_opt_pi_flags_reserved &
852                            ND_OPT_PI_FLAG_ONLINK)
853                                ap->flags |= IPV6_AF_ONLINK;
854                        ap->prefix_vltime =
855                            ntohl(pi->nd_opt_pi_valid_time);
856                        ap->prefix_pltime =
857                            ntohl(pi->nd_opt_pi_preferred_time);
858                        ap->nsprobes = 0;
859                        if (opt) {
860                                l = strlen(opt);
861                                tmp = realloc(opt,
862                                        l + strlen(ap->saddr) + 2);
863                                if (tmp) {
864                                        opt = tmp;
865                                        opt[l] = ' ';
866                                        strcpy(opt + l + 1, ap->saddr);
867                                }
868                        } else
869                                opt = strdup(ap->saddr);
870                        lifetime = ap->prefix_vltime;
871                        break;
872
873                case ND_OPT_MTU:
874                        mtu = (struct nd_opt_mtu *)(void *)p;
875                        mtuv = ntohl(mtu->nd_opt_mtu_mtu);
876                        if (mtuv < IPV6_MMTU) {
877                                syslog(LOG_ERR, "%s: invalid MTU %d",
878                                    ifp->name, mtuv);
879                                break;
880                        }
881                        rap->mtu = mtuv;
882                        snprintf(buf, sizeof(buf), "%d", mtuv);
883                        opt = strdup(buf);
884                        break;
885
886                case ND_OPT_RDNSS:
887                        rdnss = (struct nd_opt_rdnss *)p;
888                        lifetime = ntohl(rdnss->nd_opt_rdnss_lifetime);
889                        op = (uint8_t *)ndo;
890                        op += offsetof(struct nd_opt_rdnss,
891                            nd_opt_rdnss_lifetime);
892                        op += sizeof(rdnss->nd_opt_rdnss_lifetime);
893                        l = 0;
894                        for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
895                            op += sizeof(addr.s6_addr))
896                        {
897                                m = ipv6_printaddr(NULL, 0, op, ifp->name);
898                                if (m != -1)
899                                        l += m + 1;
900                        }
901                        op = (uint8_t *)ndo;
902                        op += offsetof(struct nd_opt_rdnss,
903                            nd_opt_rdnss_lifetime);
904                        op += sizeof(rdnss->nd_opt_rdnss_lifetime);
905                        tmp = opt = malloc(l);
906                        if (opt) {
907                                for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
908                                    op += sizeof(addr.s6_addr))
909                                {
910                                        m = ipv6_printaddr(tmp, l, op,
911                                            ifp->name);
912                                        if (m != -1) {
913                                                l -= (m + 1);
914                                                tmp += m;
915                                                *tmp++ = ' ';
916                                        }
917                                }
918                                if (tmp != opt)
919                                        (*--tmp) = '\0';
920                                else
921                                        *opt = '\0';
922                        }
923                        break;
924
925                case ND_OPT_DNSSL:
926                        dnssl = (struct nd_opt_dnssl *)p;
927                        lifetime = ntohl(dnssl->nd_opt_dnssl_lifetime);
928                        op = p + offsetof(struct nd_opt_dnssl,
929                            nd_opt_dnssl_lifetime);
930                        op += sizeof(dnssl->nd_opt_dnssl_lifetime);
931                        n = (dnssl->nd_opt_dnssl_len - 1) * 8;
932                        l = decode_rfc3397(NULL, 0, n, op);
933                        if (l < 1) {
934                                syslog(LOG_ERR, "%s: invalid DNSSL option",
935                                    ifp->name);
936                        } else {
937                                tmp = malloc(l);
938                                if (tmp) {
939                                        decode_rfc3397(tmp, l, n, op);
940                                        n = print_string(NULL, 0,
941                                            l - 1, (const uint8_t *)tmp);
942                                        opt = malloc(n);
943                                        if (opt)
944                                                print_string(opt, n,
945                                                    l - 1,
946                                                    (const uint8_t *)tmp);
947                                        free(tmp);
948                                }
949                        }
950                        break;
951
952                default:
953                        continue;
954                }
955
956                if (opt == NULL) {
957                        syslog(LOG_ERR, "%s: %m", __func__);
958                        continue;
959                }
960                TAILQ_FOREACH(rao, &rap->options, next) {
961                        if (rao->type == ndo->nd_opt_type &&
962                            strcmp(rao->option, opt) == 0)
963                                break;
964                }
965                if (lifetime == 0) {
966                        if (rao) {
967                                TAILQ_REMOVE(&rap->options, rao, next);
968                                free(rao->option);
969                                free(rao);
970                        }
971                        free(opt);
972                        continue;
973                }
974
975                if (rao == NULL) {
976                        rao = malloc(sizeof(*rao));
977                        if (rao == NULL) {
978                                syslog(LOG_ERR, "%s: %m", __func__);
979                                continue;
980                        }
981                        rao->type = ndo->nd_opt_type;
982                        rao->option = opt;
983                        TAILQ_INSERT_TAIL(&rap->options, rao, next);
984                } else
985                        free(opt);
986                if (lifetime == ~0U)
987                        timerclear(&rao->expire);
988                else {
989                        expire.tv_sec = lifetime;
990                        expire.tv_usec = 0;
991                        timeradd(&rap->received, &expire, &rao->expire);
992                }
993        }
994
995        if (new_rap)
996                add_router(rap);
997        if (options & DHCPCD_TEST) {
998                script_runreason(ifp, "TEST");
999                goto handle_flag;
1000        }
1001        ipv6nd_probeaddrs(&rap->addrs);
1002        ipv6_buildroutes();
1003
1004        /* We will get run by the expire function */
1005        if (rap->lifetime)
1006                ipv6nd_scriptrun(rap);
1007
1008        eloop_timeout_delete(NULL, ifp);
1009        eloop_timeout_delete(NULL, rap); /* reachable timer */
1010
1011        /* If we're owning the RA then we need to try and ensure the
1012         * router is actually reachable */
1013        if (ifp->options->options & DHCPCD_IPV6RA_OWN ||
1014            ifp->options->options & DHCPCD_IPV6RA_OWN_DEFAULT)
1015        {
1016                rap->nsprobes = 0;
1017                if (rap->lifetime)
1018                        ipv6nd_proberouter(rap);
1019        }
1020
1021handle_flag:
1022        if (rap->flags & ND_RA_FLAG_MANAGED) {
1023                if (rap->lifetime && new_data &&
1024                    dhcp6_start(ifp, DH6S_INIT) == -1)
1025                        syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
1026        } else if (rap->flags & ND_RA_FLAG_OTHER) {
1027                if (rap->lifetime && new_data &&
1028                    dhcp6_start(ifp, DH6S_INFORM) == -1)
1029                        syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
1030        } else {
1031                if (rap->lifetime && new_data)
1032                        syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA",
1033                            ifp->name);
1034                if (options & DHCPCD_TEST)
1035                        exit(EXIT_SUCCESS);
1036        }
1037
1038        /* Expire should be called last as the rap object could be destroyed */
1039        ipv6nd_expirera(ifp);
1040}
1041
1042int
1043ipv6nd_has_ra(const struct interface *ifp)
1044{
1045        const struct ra *rap;
1046
1047        TAILQ_FOREACH(rap, &ipv6_routers, next)
1048                if (rap->iface == ifp)
1049                        return 1;
1050        return 0;
1051}
1052
1053ssize_t
1054ipv6nd_env(char **env, const char *prefix, const struct interface *ifp)
1055{
1056        ssize_t l;
1057        size_t len;
1058        struct timeval now;
1059        const struct ra *rap;
1060        const struct ra_opt *rao;
1061        int i;
1062        char buffer[32];
1063        const char *optn;
1064        char **pref, **mtu, **rdnss, **dnssl, ***var, *new;
1065
1066        i = 0;
1067        l = 0;
1068        get_monotonic(&now);
1069        TAILQ_FOREACH(rap, &ipv6_routers, next) {
1070                i++;
1071                if (rap->iface != ifp)
1072                        continue;
1073                if (env) {
1074                        snprintf(buffer, sizeof(buffer),
1075                            "ra%d_from", i);
1076                        if (setvar(&env, prefix, buffer, rap->sfrom) == -1)
1077                                return -1;
1078                }
1079                l++;
1080
1081                pref = mtu = rdnss = dnssl = NULL;
1082                TAILQ_FOREACH(rao, &rap->options, next) {
1083                        if (rao->option == NULL)
1084                                continue;
1085                        var = NULL;
1086                        switch(rao->type) {
1087                        case ND_OPT_PREFIX_INFORMATION:
1088                                optn = "prefix";
1089                                var = &pref;
1090                                break;
1091                        case ND_OPT_MTU:
1092                                optn = "mtu";
1093                                var = &mtu;
1094                                break;
1095                        case ND_OPT_RDNSS:
1096                                optn = "rdnss";
1097                                var = &rdnss;
1098                                break;
1099                        case ND_OPT_DNSSL:
1100                                optn = "dnssl";
1101                                var = &dnssl;
1102                                break;
1103                        default:
1104                                continue;
1105                        }
1106                        if (*var == NULL) {
1107                                *var = env ? env : &new;
1108                                l++;
1109                        } else if (env) {
1110                                /* With single only options, last one takes
1111                                 * precedence */
1112                                if (rao->type == ND_OPT_MTU) {
1113                                        new = strchr(**var, '=');
1114                                        if (new == NULL) {
1115                                                syslog(LOG_ERR, "new is null");
1116                                                continue;
1117                                        } else
1118                                                new++;
1119                                        len = (new - **var) +
1120                                            strlen(rao->option) + 1;
1121                                        if (len > strlen(**var))
1122                                                new = realloc(**var, len);
1123                                        else
1124                                                new = **var;
1125                                        if (new) {
1126                                                **var = new;
1127                                                new = strchr(**var, '=');
1128                                                if (new)
1129                                                        strcpy(new + 1,
1130                                                            rao->option);
1131                                                else
1132                                                        syslog(LOG_ERR,
1133                                                            "new is null");
1134                                        }
1135                                        continue;
1136                                }
1137                                new = realloc(**var,
1138                                    strlen(**var) + 1 +
1139                                    strlen(rao->option) + 1);
1140                                if (new == NULL)
1141                                        return -1;
1142                                **var = new;
1143                                new += strlen(new);
1144                                *new++ = ' ';
1145                                strcpy(new, rao->option);
1146                                continue;
1147                        }
1148                        if (env) {
1149                                snprintf(buffer, sizeof(buffer),
1150                                    "ra%d_%s", i, optn);
1151                                if (setvar(&env, prefix, buffer, rao->option)
1152                                    == -1)
1153                                        return -1;
1154                        }
1155                }
1156        }
1157
1158        if (env) {
1159                if (setvard(&env, prefix, "ra_count", i) == -1)
1160                        return -1;
1161        }
1162        l++;
1163        return l;
1164}
1165
1166void
1167ipv6nd_handleifa(int cmd, const char *ifname,
1168    const struct in6_addr *addr, int flags)
1169{
1170        struct ra *rap;
1171
1172        TAILQ_FOREACH(rap, &ipv6_routers, next) {
1173                if (strcmp(rap->iface->name, ifname))
1174                        continue;
1175                ipv6_handleifa_addrs(cmd, &rap->addrs, addr, flags);
1176        }
1177}
1178
1179void
1180ipv6nd_expirera(void *arg)
1181{
1182        struct interface *ifp;
1183        struct ra *rap, *ran;
1184        struct ra_opt *rao, *raon;
1185        struct timeval now, lt, expire, next;
1186        int expired, valid;
1187
1188        ifp = arg;
1189        get_monotonic(&now);
1190        expired = 0;
1191        timerclear(&next);
1192
1193        TAILQ_FOREACH_SAFE(rap, &ipv6_routers, next, ran) {
1194                if (rap->iface != ifp)
1195                        continue;
1196                lt.tv_sec = rap->lifetime;
1197                lt.tv_usec = 0;
1198                timeradd(&rap->received, &lt, &expire);
1199                if (rap->lifetime == 0 || timercmp(&now, &expire, >)) {
1200                        valid = 0;
1201                        if (!rap->expired) {
1202                                syslog(LOG_WARNING,
1203                                    "%s: %s: router expired",
1204                                    ifp->name, rap->sfrom);
1205                                rap->expired = expired = 1;
1206                                ipv6nd_cancelproberouter(rap);
1207                        }
1208                } else {
1209                        valid = 1;
1210                        timersub(&expire, &now, &lt);
1211                        if (!timerisset(&next) || timercmp(&next, &lt, >))
1212                                next = lt;
1213                }
1214
1215                /* Addresses are expired in ipv6ns_probeaddrs
1216                 * so that DHCPv6 addresses can be removed also. */
1217                TAILQ_FOREACH_SAFE(rao, &rap->options, next, raon) {
1218                        if (rap->expired) {
1219                                switch(rao->type) {
1220                                case ND_OPT_RDNSS: /* FALLTHROUGH */
1221                                case ND_OPT_DNSSL:
1222                                        /* RFC6018 end of section 5.2 states
1223                                         * that if tha RA has a lifetime of 0
1224                                         * then we should expire these
1225                                         * options */
1226                                        TAILQ_REMOVE(&rap->options, rao, next);
1227                                        expired = 1;
1228                                        free(rao->option);
1229                                        free(rao);
1230                                        continue;
1231                                }
1232                        }
1233                        if (!timerisset(&rao->expire))
1234                                continue;
1235                        if (timercmp(&now, &rao->expire, >)) {
1236                                /* Expired prefixes are logged above */
1237                                if (rao->type != ND_OPT_PREFIX_INFORMATION)
1238                                        syslog(LOG_WARNING,
1239                                            "%s: %s: expired option %d",
1240                                            ifp->name, rap->sfrom, rao->type);
1241                                TAILQ_REMOVE(&rap->options, rao, next);
1242                                expired = 1;
1243                                free(rao->option);
1244                                free(rao);
1245                                continue;
1246                        }
1247                        valid = 1;
1248                        timersub(&rao->expire, &now, &lt);
1249                        if (!timerisset(&next) || timercmp(&next, &lt, >))
1250                                next = lt;
1251                }
1252
1253                /* No valid lifetimes are left on the RA, so we might
1254                 * as well punt it. */
1255                if (!valid && TAILQ_FIRST(&rap->addrs) == NULL)
1256                        ipv6nd_free_ra(rap);
1257        }
1258
1259        if (timerisset(&next))
1260                eloop_timeout_add_tv(&next, ipv6nd_expirera, ifp);
1261        if (expired) {
1262                ipv6_buildroutes();
1263                script_runreason(ifp, "ROUTERADVERT");
1264        }
1265}
1266
1267void
1268ipv6nd_drop(struct interface *ifp)
1269{
1270        struct ra *rap;
1271        int expired = 0;
1272        TAILQ_HEAD(rahead, ra) rtrs;
1273
1274        eloop_timeout_delete(NULL, ifp);
1275        TAILQ_INIT(&rtrs);
1276        TAILQ_FOREACH(rap, &ipv6_routers, next) {
1277                if (rap->iface == ifp) {
1278                        rap->expired = expired = 1;
1279                        TAILQ_REMOVE(&ipv6_routers, rap, next);
1280                        TAILQ_INSERT_TAIL(&rtrs, rap, next);
1281                }
1282        }
1283        if (expired) {
1284                while ((rap = TAILQ_FIRST(&rtrs))) {
1285                        TAILQ_REMOVE(&rtrs, rap, next);
1286                        ipv6nd_drop_ra(rap);
1287                }
1288                ipv6_buildroutes();
1289                if ((ifp->options->options &
1290                    (DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
1291                    (DHCPCD_EXITING | DHCPCD_PERSISTENT))
1292                        script_runreason(ifp, "ROUTERADVERT");
1293        }
1294}
1295static void
1296ipv6nd_unreachable(void *arg)
1297{
1298        struct ra *rap = arg;
1299        struct timeval tv;
1300
1301        /* We could add an unreachable flag and persist the information,
1302         * but that is more effort than it's probably worth. */
1303        syslog(LOG_WARNING, "%s: %s is unreachable, expiring it",
1304            rap->iface->name, rap->sfrom);
1305        rap->expired = 1;
1306        ipv6_buildroutes();
1307        script_runreason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
1308
1309        /* We should still test if it's reachable or not so
1310         * incase it comes back to life and it's preferable. */
1311        if (rap->reachable) {
1312                ms_to_tv(&tv, rap->reachable);
1313        } else {
1314                tv.tv_sec = REACHABLE_TIME;
1315                tv.tv_usec = 0;
1316        }
1317        eloop_timeout_add_tv(&tv, ipv6nd_proberouter, rap);
1318}
1319
1320#ifdef LISTEN_DAD
1321void
1322ipv6nd_cancelprobeaddr(struct ipv6_addr *ap)
1323{
1324
1325        eloop_timeout_delete(ipv6nd_probeaddr, ap);
1326        if (ap->dadcallback)
1327                eloop_timeout_delete(ap->dadcallback, ap);
1328}
1329#endif
1330
1331void
1332ipv6nd_probeaddr(void *arg)
1333{
1334        struct ipv6_addr *ap = arg;
1335#ifdef IPV6_SEND_DAD
1336        struct nd_neighbor_solicit *ns;
1337        struct nd_opt_hdr *nd;
1338        struct sockaddr_in6 dst;
1339        struct cmsghdr *cm;
1340        struct in6_pktinfo pi;
1341        int hoplimit = HOPLIMIT;
1342#else
1343#ifdef LISTEN_DAD
1344        struct timeval tv, rtv;
1345        struct timeval mtv;
1346        int i;
1347#endif
1348#endif
1349
1350        if (ap->dadcallback &&
1351            ((ap->flags & IPV6_AF_NEW) == 0 ||
1352            ap->nsprobes >= ap->iface->options->dadtransmits))
1353        {
1354#ifdef IPV6_SEND_DAD
1355                ap->dadcallback(ap);
1356#else
1357                if (!(ap->flags & IPV6_AF_AUTOCONF) ||
1358                    ap->iface->options->options & DHCPCD_IPV6RA_OWN)
1359                        ipv6_addaddr(ap);
1360#endif
1361                return;
1362        }
1363
1364        if (ipv6nd_naopen() == -1)
1365                return;
1366
1367        ap->flags &= ~IPV6_AF_DADCOMPLETED;
1368
1369#ifdef IPV6_SEND_DAD
1370        if (!ap->ns) {
1371                ap->nslen = sizeof(*ns) + ROUNDUP8(ap->iface->hwlen + 2);
1372                ap->ns = calloc(1, ap->nslen);
1373                if (ap->ns == NULL) {
1374                        syslog(LOG_ERR, "%s: %m", __func__);
1375                        return;
1376                }
1377                ns = (struct nd_neighbor_solicit *)(void *)ap->ns;
1378                ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
1379                //ns->nd_ns_cksum = 0;
1380                //ns->nd_ns_code = 0;
1381                //ns->nd_ns_reserved = 0;
1382                ns->nd_ns_target = ap->addr;
1383                nd = (struct nd_opt_hdr *)(ap->ns + sizeof(*ns));
1384                nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
1385                nd->nd_opt_len = (ROUNDUP8(ap->iface->hwlen + 2)) >> 3;
1386                memcpy(nd + 1, ap->iface->hwaddr, ap->iface->hwlen);
1387        }
1388
1389        memset(&dst, 0, sizeof(dst));
1390        dst.sin6_family = AF_INET6;
1391#ifdef SIN6_LEN
1392        dst.sin6_len = sizeof(dst);
1393#endif
1394        dst.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
1395        dst.sin6_addr.s6_addr16[1] = 0;
1396        dst.sin6_addr.s6_addr32[1] = 0;
1397        dst.sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
1398        dst.sin6_addr.s6_addr32[3] = ap->addr.s6_addr32[3];
1399        dst.sin6_addr.s6_addr[12] = 0xff;
1400
1401        //memcpy(&dst.sin6_addr, &ap->addr, sizeof(dst.sin6_addr));
1402        dst.sin6_scope_id = ap->iface->index;
1403
1404        sndhdr.msg_name = (caddr_t)&dst;
1405        sndhdr.msg_iov[0].iov_base = ap->ns;
1406        sndhdr.msg_iov[0].iov_len = ap->nslen;
1407
1408        /* Set the outbound interface */
1409        cm = CMSG_FIRSTHDR(&sndhdr);
1410        cm->cmsg_level = IPPROTO_IPV6;
1411        cm->cmsg_type = IPV6_PKTINFO;
1412        cm->cmsg_len = CMSG_LEN(sizeof(pi));
1413        memset(&pi, 0, sizeof(pi));
1414        pi.ipi6_ifindex = ap->iface->index;
1415        memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
1416
1417        /* Hop limit */
1418        cm = CMSG_NXTHDR(&sndhdr, cm);
1419        cm->cmsg_level = IPPROTO_IPV6;
1420        cm->cmsg_type = IPV6_HOPLIMIT;
1421        cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
1422        memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));
1423
1424#ifdef DEBUG_NS
1425        syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
1426            ap->iface->name, ap->saddr);
1427        if (ap->dadcallback == NULL)
1428                syslog(LOG_WARNING, "%s: no callback!", ap->iface->name);
1429#endif
1430        if (sendmsg(unspec_sock, &sndhdr, 0) == -1) {
1431                syslog(LOG_ERR, "%s: %s: sendmsg: %m",
1432                    ap->iface->name, __func__);
1433                return;
1434        }
1435
1436        if (ap->dadcallback) {
1437                ms_to_tv(&tv, RETRANS_TIMER);
1438                ms_to_tv(&rtv, MIN_RANDOM_FACTOR);
1439                timeradd(&tv, &rtv, &tv);
1440                rtv.tv_sec = 0;
1441                rtv.tv_usec = arc4random() %
1442                    (MAX_RANDOM_FACTOR_U - MIN_RANDOM_FACTOR_U);
1443                timeradd(&tv, &rtv, &tv);
1444
1445                eloop_timeout_add_tv(&tv,
1446                    ++(ap->nsprobes) < ap->iface->options->dadtransmits ?
1447                    ipv6nd_probeaddr : ap->dadcallback,
1448                    ap);
1449        }
1450#else /* IPV6_SEND_DAD */
1451
1452        if (!(ap->flags & IPV6_AF_AUTOCONF) ||
1453            ap->iface->options->options & DHCPCD_IPV6RA_OWN)
1454                ipv6_addaddr(ap);
1455
1456#ifdef LISTEN_DAD
1457        /* Let the kernel handle DAD.
1458         * We don't know the timings, so just wait for the max */
1459        if (ap->dadcallback) {
1460                mtv.tv_sec = 0;
1461                mtv.tv_usec = 0;
1462                for (i = 0; i < ap->iface->options->dadtransmits; i++) {
1463                        ms_to_tv(&tv, RETRANS_TIMER);
1464                        ms_to_tv(&rtv, MAX_RANDOM_FACTOR);
1465                        timeradd(&tv, &rtv, &tv);
1466                        timeradd(&mtv, &tv, &mtv);
1467                }
1468                eloop_timeout_add_tv(&mtv, ap->dadcallback, ap);
1469        }
1470#endif
1471#endif /* IPV6_SEND_DAD */
1472}
1473
1474ssize_t
1475ipv6nd_probeaddrs(struct ipv6_addrhead *addrs)
1476{
1477        struct ipv6_addr *ap, *apn;
1478        ssize_t i;
1479
1480        i = 0;
1481        TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
1482                if (ap->prefix_vltime == 0) {
1483                        TAILQ_REMOVE(addrs, ap, next);
1484                        if (ap->flags & IPV6_AF_ADDED) {
1485                                syslog(LOG_INFO, "%s: deleting address %s",
1486                                    ap->iface->name, ap->saddr);
1487                                i++;
1488                                if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
1489                                    del_address6(ap) == -1 &&
1490                                    errno != EADDRNOTAVAIL && errno != ENXIO)
1491                                        syslog(LOG_ERR, "del_address6 %m");
1492                        }
1493                        if (ap->dadcallback)
1494                                eloop_q_timeout_delete(0, NULL,
1495                                    ap->dadcallback);
1496                        free(ap);
1497                } else if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr)) {
1498                        ipv6nd_probeaddr(ap);
1499                        if (ap->flags & IPV6_AF_NEW)
1500                                i++;
1501                }
1502        }
1503
1504        return i;
1505}
1506
1507void
1508ipv6nd_proberouter(void *arg)
1509{
1510        struct ra *rap = arg;
1511        struct nd_neighbor_solicit *ns;
1512        struct nd_opt_hdr *nd;
1513        struct sockaddr_in6 dst;
1514        struct cmsghdr *cm;
1515        struct in6_pktinfo pi;
1516        int hoplimit = HOPLIMIT;
1517        struct timeval tv, rtv;
1518
1519        if (ipv6nd_naopen() == -1)
1520                return;
1521
1522        if (!rap->ns) {
1523                rap->nslen = sizeof(*ns) + ROUNDUP8(rap->iface->hwlen + 2);
1524                rap->ns = calloc(1, rap->nslen);
1525                if (rap->ns == NULL) {
1526                        syslog(LOG_ERR, "%s: %m", __func__);
1527                        return;
1528                }
1529                ns = (struct nd_neighbor_solicit *)(void *)rap->ns;
1530                ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
1531                //ns->nd_ns_cksum = 0;
1532                //ns->nd_ns_code = 0;
1533                //ns->nd_ns_reserved = 0;
1534                ns->nd_ns_target = rap->from;
1535                nd = (struct nd_opt_hdr *)(rap->ns + sizeof(*ns));
1536                nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
1537                nd->nd_opt_len = (ROUNDUP8(rap->iface->hwlen + 2)) >> 3;
1538                memcpy(nd + 1, rap->iface->hwaddr, rap->iface->hwlen);
1539        }
1540
1541        memset(&dst, 0, sizeof(dst));
1542        dst.sin6_family = AF_INET6;
1543#ifdef SIN6_LEN
1544        dst.sin6_len = sizeof(dst);
1545#endif
1546        memcpy(&dst.sin6_addr, &rap->from, sizeof(dst.sin6_addr));
1547        dst.sin6_scope_id = rap->iface->index;
1548
1549        sndhdr.msg_name = (caddr_t)&dst;
1550        sndhdr.msg_iov[0].iov_base = rap->ns;
1551        sndhdr.msg_iov[0].iov_len = rap->nslen;
1552
1553        /* Set the outbound interface */
1554        cm = CMSG_FIRSTHDR(&sndhdr);
1555        cm->cmsg_level = IPPROTO_IPV6;
1556        cm->cmsg_type = IPV6_PKTINFO;
1557        cm->cmsg_len = CMSG_LEN(sizeof(pi));
1558        memset(&pi, 0, sizeof(pi));
1559        pi.ipi6_ifindex = rap->iface->index;
1560        memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
1561
1562        /* Hop limit */
1563        cm = CMSG_NXTHDR(&sndhdr, cm);
1564        cm->cmsg_level = IPPROTO_IPV6;
1565        cm->cmsg_type = IPV6_HOPLIMIT;
1566        cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
1567        memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));
1568
1569#ifdef DEBUG_NS
1570        syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
1571            rap->iface->name, rap->sfrom);
1572#endif
1573        if (sendmsg(sock, &sndhdr, 0) == -1) {
1574                syslog(LOG_ERR, "%s: %s: sendmsg: %m",
1575                    rap->iface->name, __func__);
1576                return;
1577        }
1578
1579        ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans);
1580        ms_to_tv(&rtv, MIN_RANDOM_FACTOR);
1581        timeradd(&tv, &rtv, &tv);
1582        rtv.tv_sec = 0;
1583        rtv.tv_usec = arc4random() % (MAX_RANDOM_FACTOR_U -MIN_RANDOM_FACTOR_U);
1584        timeradd(&tv, &rtv, &tv);
1585        eloop_timeout_add_tv(&tv, ipv6nd_proberouter, rap);
1586
1587        if (rap->nsprobes++ == 0)
1588                eloop_timeout_add_sec(DELAY_FIRST_PROBE_TIME,
1589                    ipv6nd_unreachable, rap);
1590}
1591
1592void
1593ipv6nd_cancelproberouter(struct ra *rap)
1594{
1595
1596        eloop_timeout_delete(ipv6nd_proberouter, rap);
1597        eloop_timeout_delete(ipv6nd_unreachable, rap);
1598}
1599
1600/* ARGSUSED */
1601static void
1602ipv6nd_handlena(struct interface *ifp, struct icmp6_hdr *icp, ssize_t len)
1603{
1604        struct nd_neighbor_advert *nd_na;
1605        struct ra *rap;
1606        int is_router, is_solicited;
1607#ifdef DEBUG_NS
1608        int found;
1609#endif
1610        struct timeval tv;
1611
1612#ifdef LISTEN_DAD
1613        struct dhcp6_state *d6state;
1614        struct ipv6_addr *ap;
1615#endif
1616
1617        if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
1618                syslog(LOG_ERR, "IPv6 NA packet too short from %s", sfrom);
1619                return;
1620        }
1621
1622        if (ifp == NULL) {
1623#ifdef DEBUG_NS
1624                syslog(LOG_DEBUG, "NA for unexpected interface from %s", sfrom);
1625#endif
1626                return;
1627        }
1628
1629        nd_na = (struct nd_neighbor_advert *)icp;
1630        is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER;
1631        is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED;
1632
1633        if (IN6_IS_ADDR_MULTICAST(&nd_na->nd_na_target)) {
1634                syslog(LOG_ERR, "%s: NA for multicast address from %s",
1635                    ifp->name, sfrom);
1636                return;
1637        }
1638
1639#ifdef DEBUG_NS
1640        found = 0;
1641#endif
1642        TAILQ_FOREACH(rap, &ipv6_routers, next) {
1643                if (rap->iface != ifp)
1644                        continue;
1645                if (memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr,
1646                    sizeof(rap->from.s6_addr)) == 0)
1647                        break;
1648#ifdef LISTEN_DAD
1649                TAILQ_FOREACH(ap, &rap->addrs, next) {
1650                        if (memcmp(ap->addr.s6_addr,
1651                            nd_na->nd_na_target.s6_addr,
1652                            sizeof(ap->addr.s6_addr)) == 0)
1653                        {
1654                                ap->flags |= IPV6_AF_DUPLICATED;
1655                                if (ap->dadcallback)
1656                                        ap->dadcallback(ap);
1657#ifdef DEBUG_NS
1658                                found++;
1659#endif
1660                        }
1661                }
1662#endif
1663        }
1664        if (rap == NULL) {
1665#ifdef LISTEN_DAD
1666                d6state = D6_STATE(ifp);
1667                if (d6state) {
1668                        TAILQ_FOREACH(ap, &d6state->addrs, next) {
1669                                if (memcmp(ap->addr.s6_addr,
1670                                    nd_na->nd_na_target.s6_addr,
1671                                    sizeof(ap->addr.s6_addr)) == 0)
1672                                {
1673                                        ap->flags |= IPV6_AF_DUPLICATED;
1674                                        if (ap->dadcallback)
1675                                                ap->dadcallback(ap);
1676#ifdef DEBUG_NS
1677                                        found++;
1678#endif
1679                                }
1680                        }
1681                }
1682#endif
1683
1684#ifdef DEBUG_NS
1685                if (found == 0)
1686                        syslog(LOG_DEBUG, "%s: unexpected NA from %s",
1687                            ifp->name, sfrom);
1688#endif
1689                return;
1690        }
1691
1692#ifdef DEBUG_NS
1693        syslog(LOG_DEBUG, "%s: %sNA from %s",
1694            ifp->name, is_solicited ? "solicited " : "",  sfrom);
1695#endif
1696
1697        /* Node is no longer a router, so remove it from consideration */
1698        if (!is_router && !rap->expired) {
1699                syslog(LOG_INFO, "%s: %s is no longer a router",
1700                    ifp->name, sfrom);
1701                rap->expired = 1;
1702                ipv6nd_cancelproberouter(rap);
1703                ipv6_buildroutes();
1704                script_runreason(ifp, "ROUTERADVERT");
1705                return;
1706        }
1707
1708        if (is_solicited && is_router && rap->lifetime) {
1709                if (rap->expired) {
1710                        rap->expired = 0;
1711                        syslog(LOG_INFO, "%s: %s is reachable again",
1712                                ifp->name, sfrom);
1713                        ipv6_buildroutes();
1714                        script_runreason(rap->iface, "ROUTERADVERT"); /* XXX */
1715                }
1716                rap->nsprobes = 0;
1717                if (rap->reachable) {
1718                        ms_to_tv(&tv, rap->reachable);
1719                } else {
1720                        tv.tv_sec = REACHABLE_TIME;
1721                        tv.tv_usec = 0;
1722                }
1723                eloop_timeout_add_tv(&tv, ipv6nd_proberouter, rap);
1724                eloop_timeout_delete(ipv6nd_unreachable, rap);
1725        }
1726}
1727
1728/* ARGSUSED */
1729static void
1730ipv6nd_handledata(__unused void *arg)
1731{
1732        ssize_t len;
1733        struct cmsghdr *cm;
1734        int hoplimit;
1735        struct in6_pktinfo pkt;
1736        struct icmp6_hdr *icp;
1737        struct interface *ifp;
1738
1739        len = recvmsg(sock, &rcvhdr, 0);
1740        if (len == -1) {
1741                syslog(LOG_ERR, "recvmsg: %m");
1742                return;
1743        }
1744        sfrom = inet_ntop(AF_INET6, &from.sin6_addr,
1745            ntopbuf, INET6_ADDRSTRLEN);
1746        if ((size_t)len < sizeof(struct icmp6_hdr)) {
1747                syslog(LOG_ERR, "IPv6 ICMP packet too short from %s", sfrom);
1748                return;
1749        }
1750
1751        pkt.ipi6_ifindex = hoplimit = 0;
1752        for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvhdr);
1753             cm;
1754             cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvhdr, cm))
1755        {
1756                if (cm->cmsg_level != IPPROTO_IPV6)
1757                        continue;
1758                switch(cm->cmsg_type) {
1759                case IPV6_PKTINFO:
1760                        if (cm->cmsg_len == CMSG_LEN(sizeof(pkt)))
1761                                memcpy(&pkt, CMSG_DATA(cm), sizeof(pkt));
1762                        break;
1763                case IPV6_HOPLIMIT:
1764                        if (cm->cmsg_len == CMSG_LEN(sizeof(int)))
1765                                memcpy(&hoplimit, CMSG_DATA(cm), sizeof(int));
1766                        break;
1767                }
1768        }
1769
1770        if (pkt.ipi6_ifindex == 0 || hoplimit == 0) {
1771                syslog(LOG_ERR,
1772                    "IPv6 RA did not contain index or hop limit from %s",
1773                    sfrom);
1774                return;
1775        }
1776
1777        TAILQ_FOREACH(ifp, ifaces, next) {
1778                if (ifp->index == (unsigned int)pkt.ipi6_ifindex)
1779                        break;
1780        }
1781
1782        icp = (struct icmp6_hdr *)rcvhdr.msg_iov[0].iov_base;
1783        if (icp->icmp6_code == 0) {
1784                switch(icp->icmp6_type) {
1785                        case ND_NEIGHBOR_ADVERT:
1786                                ipv6nd_handlena(ifp, icp, len);
1787                                return;
1788                        case ND_ROUTER_ADVERT:
1789                                ipv6nd_handlera(ifp, icp, len);
1790                                return;
1791                }
1792        }
1793
1794        syslog(LOG_ERR, "invalid IPv6 type %d or code %d from %s",
1795            icp->icmp6_type, icp->icmp6_code, sfrom);
1796}
1797
1798int
1799ipv6nd_startrs(struct interface *ifp)
1800{
1801        struct rs_state *state;
1802
1803        syslog(LOG_INFO, "%s: soliciting an IPv6 router", ifp->name);
1804        if (sock == -1) {
1805                if (ipv6nd_open() == -1) {
1806                        syslog(LOG_ERR, "%s: ipv6nd_open: %m", __func__);
1807                        return -1;
1808                }
1809                eloop_event_add(sock, ipv6nd_handledata, NULL);
1810        }
1811
1812        eloop_timeout_delete(NULL, ifp);
1813
1814        state = RS_STATE(ifp);
1815        if (state == NULL) {
1816                ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
1817                state = RS_STATE(ifp);
1818                if (state == NULL) {
1819                        syslog(LOG_ERR, "%s: %m", __func__);
1820                        return -1;
1821                }
1822        }
1823
1824        /* Always make a new probe as the underlying hardware
1825         * address could have changed. */
1826        ipv6nd_makersprobe(ifp);
1827        if (state->rs == NULL) {
1828                syslog(LOG_ERR, "%s: ipv6ns_makersprobe: %m", __func__);
1829                return -1;
1830        }
1831
1832        state->rsprobes = 0;
1833        ipv6nd_sendrsprobe(ifp);
1834        return 0;
1835}
Note: See TracBrowser for help on using the repository browser.