Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/rtadvd Unicast solicited RA's as per RFC 7772.



details:   https://anonhg.NetBSD.org/src/rev/566fc70926b2
branches:  trunk
changeset: 322160:566fc70926b2
user:      roy <roy%NetBSD.org@localhost>
date:      Fri Apr 20 15:57:23 2018 +0000

description:
Unicast solicited RA's as per RFC 7772.

This is done by having a secondary timer against rainfo so we
can delay unicasting by the required randomised amount of time
without affecting the unsolicited RA timer.

diffstat:

 usr.sbin/rtadvd/config.c |    6 +-
 usr.sbin/rtadvd/rtadvd.c |  128 ++++++++++++++++++++++++++++------------------
 usr.sbin/rtadvd/rtadvd.h |    8 +-
 3 files changed, 87 insertions(+), 55 deletions(-)

diffs (truncated from 316 to 300 lines):

diff -r 47a9a737ce7f -r 566fc70926b2 usr.sbin/rtadvd/config.c
--- a/usr.sbin/rtadvd/config.c  Fri Apr 20 15:29:19 2018 +0000
+++ b/usr.sbin/rtadvd/config.c  Fri Apr 20 15:57:23 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: config.c,v 1.39 2018/04/20 15:29:19 roy Exp $  */
+/*     $NetBSD: config.c,v 1.40 2018/04/20 15:57:23 roy Exp $  */
 /*     $KAME: config.c,v 1.93 2005/10/17 14:40:02 suz Exp $    */
 
 /*
@@ -113,6 +113,7 @@
        struct dnssl_domain *dnsd;
 
        rtadvd_remove_timer(&rai->timer);
+       rtadvd_remove_timer(&rai->timer_sol);
 
        while ((sol = TAILQ_FIRST(&rai->soliciter))) {
                TAILQ_REMOVE(&rai->soliciter, sol, next);
@@ -791,7 +792,8 @@
                return;
        tmp->timer = rtadvd_add_timer(ra_timeout, ra_timer_update,
                                      tmp, tmp);
-       ra_timer_set_short_delay(tmp);
+       ra_timer_set_short_delay(tmp, tmp->timer);
+       tmp->timer_sol = rtadvd_add_timer(ra_timeout_sol, NULL, tmp, NULL);
 
        return;
 
diff -r 47a9a737ce7f -r 566fc70926b2 usr.sbin/rtadvd/rtadvd.c
--- a/usr.sbin/rtadvd/rtadvd.c  Fri Apr 20 15:29:19 2018 +0000
+++ b/usr.sbin/rtadvd/rtadvd.c  Fri Apr 20 15:57:23 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtadvd.c,v 1.64 2018/04/20 11:31:54 roy Exp $  */
+/*     $NetBSD: rtadvd.c,v 1.65 2018/04/20 15:57:23 roy Exp $  */
 /*     $KAME: rtadvd.c,v 1.92 2005/10/17 14:40:02 suz Exp $    */
 
 /*
@@ -166,7 +166,7 @@
     struct in6_pktinfo *, struct sockaddr_in6 *);
 static void ra_input(int, struct nd_router_advert *,
     struct in6_pktinfo *, struct sockaddr_in6 *);
-static struct rainfo *ra_output(struct rainfo *);
+static struct rainfo *ra_output(struct rainfo *, bool);
 static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *,
     struct sockaddr_in6 *);
 static int nd6_options(struct nd_opt_hdr *, int, union nd_opts *, uint32_t);
@@ -440,7 +440,7 @@
                rai->mininterval = MIN_DELAY_BETWEEN_RAS;
                rai->maxinterval = MIN_DELAY_BETWEEN_RAS;
                rai->leaving_adv = MAX_FINAL_RTR_ADVERTISEMENTS;
-               ra_output(rai);
+               ra_output(rai, false);
                ra_timer_update(rai, &rai->timer->tm);
                rtadvd_set_timer(&rai->timer->tm, rai->timer);
        }
@@ -698,13 +698,16 @@
                            ra_timer_update, rai, rai);
                        ra_timer_update(rai, &rai->timer->tm);
                        rtadvd_set_timer(&rai->timer->tm, rai->timer);
+                       rtadvd_remove_timer(&rai->timer_sol);
+                       rai->timer_sol = rtadvd_add_timer(ra_timeout_sol,
+                           NULL, rai, NULL);
                } else if (prefixchange && rai->ifflags & IFF_UP) {
                        /*
                         * An advertised prefix has been added or invalidated.
                         * Will notice the change in a short delay.
                         */
                        rai->initcounter = 0;
-                       ra_timer_set_short_delay(rai);
+                       ra_timer_set_short_delay(rai, rai->timer);
                }
        }
 
@@ -965,12 +968,20 @@
         */
 
        /* record sockaddr waiting for RA, if possible */
-       sol = malloc(sizeof(*sol));
-       if (sol) {
-               sol->addr = *from;
-               /* XXX RFC2553 need clarification on flowinfo */
-               sol->addr.sin6_flowinfo = 0;
-               TAILQ_INSERT_HEAD(&rai->soliciter, sol, next);
+       TAILQ_FOREACH(sol, &rai->soliciter, next) {
+               if (IN6_ARE_ADDR_EQUAL(&sol->addr.sin6_addr, &from->sin6_addr))
+                       break;
+       }
+       if (sol == NULL) {
+               sol = malloc(sizeof(*sol));
+               if (sol == NULL) {
+                       logit(LOG_ERR, "%s: malloc: %m", __func__);
+               } else {
+                       sol->addr = *from;
+                       /* XXX RFC2553 need clarification on flowinfo */
+                       sol->addr.sin6_flowinfo = 0;
+                       TAILQ_INSERT_TAIL(&rai->soliciter, sol, next);
+               }
        }
 
        /*
@@ -980,14 +991,14 @@
        if (rai->waiting++)
                goto done;
 
-       ra_timer_set_short_delay(rai);
+       ra_timer_set_short_delay(rai, rai->timer_sol);
 
 done:
        free_ndopts(&ndopts);
 }
 
 void
-ra_timer_set_short_delay(struct rainfo *rai)
+ra_timer_set_short_delay(struct rainfo *rai, struct rtadvd_timer *timer)
 {
        long delay;     /* must not be greater than 1000000 */
        struct timespec interval, now, min_delay, tm_tmp, *rest;
@@ -1024,7 +1035,7 @@
                timespecsub(&min_delay, &tm_tmp, &min_delay);
                timespecadd(&min_delay, &interval, &interval);
        }
-       rtadvd_set_timer(&interval, rai->timer);
+       rtadvd_set_timer(&interval, timer);
 }
 
 static void
@@ -1503,7 +1514,8 @@
                exit(EXIT_FAILURE);
        }
 
-       sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+       sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
+                               CMSG_SPACE(sizeof(int));
        sndcmsgbuf = malloc(sndcmsgbuflen);
        if (sndcmsgbuf == NULL) {
                logit(LOG_ERR, "%s: malloc: %m", __func__);
@@ -1522,6 +1534,12 @@
                logit(LOG_ERR, "%s: IPV6_MULTICAST_HOPS: %m", __func__);
                exit(EXIT_FAILURE);
        }
+       on = 255;
+       if (prog_setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &on,
+                      sizeof(on)) == -1) {
+               logit(LOG_ERR, "%s: IPV6_UNICAST_HOPS: %m", __func__);
+               exit(EXIT_FAILURE);
+       }
 
        /* specify to tell receiving interface */
        on = 1;
@@ -1661,7 +1679,7 @@
 }
 
 struct rainfo *
-ra_output(struct rainfo *rai)
+ra_output(struct rainfo *rai, bool solicited)
 {
        int i;
        struct cmsghdr *cm;
@@ -1680,8 +1698,8 @@
        sndmhdr.msg_iov[0].iov_base = (void *)rai->ra_data;
        sndmhdr.msg_iov[0].iov_len = rai->ra_datalen;
 
+       /* specify the outgoing interface */
        cm = CMSG_FIRSTHDR(&sndmhdr);
-       /* specify the outgoing interface */
        cm->cmsg_level = IPPROTO_IPV6;
        cm->cmsg_type = IPV6_PKTINFO;
        cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
@@ -1693,8 +1711,32 @@
               "%s: send RA on %s, # of waitings = %d",
               __func__, rai->ifname, rai->waiting); 
 
+       if (solicited) {
+               /* unicast solicited RA's as per RFC 7772 */
+               while ((sol = TAILQ_FIRST(&rai->soliciter)) != NULL) {
+                       sndmhdr.msg_name = (void *)&sol->addr;
+                       i = prog_sendmsg(sock, &sndmhdr, 0);
+                       if (i < 0 || (size_t)i != rai->ra_datalen)  {
+                               if (i < 0) {
+                                       logit(LOG_ERR,
+                                           "%s: unicast sendmsg on %s: %m",
+                                           __func__, rai->ifname);
+                               }
+                       }
+                       TAILQ_REMOVE(&rai->soliciter, sol, next);
+                       free(sol);
+               }
+
+               /* reset waiting conter */
+               rai->waiting = 0;
+
+               /* disable timer */
+               rai->timer_sol->enabled = false;
+
+               return rai;
+       }
+
        i = prog_sendmsg(sock, &sndmhdr, 0);
-
        if (i < 0 || (size_t)i != rai->ra_datalen)  {
                if (i < 0) {
                        logit(LOG_ERR, "%s: sendmsg on %s: %m",
@@ -1702,27 +1744,6 @@
                }
        }
 
-       /*
-        * unicast advertisements
-        * XXX commented out.  reason: though spec does not forbit it, unicast
-        * advert does not really help
-        */
-       while ((sol = TAILQ_FIRST(&rai->soliciter)) != NULL) {
-#if 0
-               sndmhdr.msg_name = (void *)&sol->addr;
-               i = sendmsg(sock, &sndmhdr, 0);
-               if (i < 0 || i != rai->ra_datalen)  {
-                       if (i < 0) {
-                               logit(LOG_ERR,
-                                   "%s: unicast sendmsg on %s: %m",
-                                   __func__, rai->ifname);
-                       }
-               }
-#endif
-               TAILQ_REMOVE(&rai->soliciter, sol, next);
-               free(sol);
-       }
-
        if (rai->leaving_adv > 0) {
                if (--(rai->leaving_adv) == 0) {
                        /* leaving for ourself means we're shutting down */
@@ -1738,7 +1759,7 @@
                        rai->leaving_for->timer = rtadvd_add_timer(ra_timeout,
                            ra_timer_update,
                            rai->leaving_for, rai->leaving_for);
-                       ra_timer_set_short_delay(rai->leaving_for);
+                       ra_timer_set_short_delay(rai->leaving_for, rai->timer);
                        rai->leaving_for->leaving = NULL;
                        free_rainfo(rai);
                        return NULL;
@@ -1752,29 +1773,36 @@
 
        /* update timestamp */
        prog_clock_gettime(CLOCK_MONOTONIC, &rai->lastsent);
-
-       /* reset waiting conter */
-       rai->waiting = 0;
-
        return rai;
 }
 
-/* process RA timer */
+/* process unsolicited RA timer */
 struct rtadvd_timer *
 ra_timeout(void *data)
 {
        struct rainfo *rai = (struct rainfo *)data;
 
-#ifdef notyet
-       /* if necessary, reconstruct the packet. */
-#endif
+       logit(LOG_DEBUG,
+              "%s: unsolicited RA timer on %s is expired",
+              __func__, rai->ifname);
+
+       if (ra_output(rai, false))
+               return rai->timer;
+       return NULL;
+}
+
+/* process solicited RA timer */
+struct rtadvd_timer *
+ra_timeout_sol(void *data)
+{
+       struct rainfo *rai = (struct rainfo *)data;
 
        logit(LOG_DEBUG,
-              "%s: RA timer on %s is expired",
+              "%s: solicited RA timer on %s is expired",
               __func__, rai->ifname);
 
-       if (ra_output(rai))
-               return rai->timer;
+       if (ra_output(rai, true))
+               return rai->timer_sol;
        return NULL;
 }
 
diff -r 47a9a737ce7f -r 566fc70926b2 usr.sbin/rtadvd/rtadvd.h
--- a/usr.sbin/rtadvd/rtadvd.h  Fri Apr 20 15:29:19 2018 +0000
+++ b/usr.sbin/rtadvd/rtadvd.h  Fri Apr 20 15:57:23 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtadvd.h,v 1.16 2018/04/20 10:39:37 roy Exp $  */
+/*     $NetBSD: rtadvd.h,v 1.17 2018/04/20 15:57:23 roy Exp $  */
 /*     $KAME: rtadvd.h,v 1.30 2005/10/17 14:40:02 suz Exp $    */
 
 /*
@@ -136,7 +136,8 @@
        TAILQ_ENTRY(rainfo) next;
 
        /* timer related parameters */
-       struct rtadvd_timer *timer;



Home | Main Index | Thread Index | Old Index