Author: hrs
Date: Wed Jun  8 16:03:29 2011
New Revision: 222861
URL: http://svn.freebsd.org/changeset/base/222861

Log:
  - Accumulate RA options instead of replacing old ones when a new RA arrived.
    RFC 4861 6.3.4 clearly defines handling multiple RAs in this way.
  
  - RDNSS/DNSSL options from multiple RAs on a single link will be
    gathered and sent to resolvconf(8).
  
  - Call "resolvconf -d" only after at least one RDNSS or DNSSL option is
    received and then all of them are expired.
  
  - The rtsold.dump output now supports displaying a list of the RA options.
  
  - Use more human-readable expression for logging values of struct timeval.
  
  Discussed with:       ume

Modified:
  head/usr.sbin/rtsold/dump.c
  head/usr.sbin/rtsold/rtsol.c
  head/usr.sbin/rtsold/rtsold.c
  head/usr.sbin/rtsold/rtsold.h

Modified: head/usr.sbin/rtsold/dump.c
==============================================================================
--- head/usr.sbin/rtsold/dump.c Wed Jun  8 16:00:30 2011        (r222860)
+++ head/usr.sbin/rtsold/dump.c Wed Jun  8 16:03:29 2011        (r222861)
@@ -39,6 +39,7 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/icmp6.h>
+#include <arpa/inet.h>
 
 #include <syslog.h>
 #include <time.h>
@@ -53,14 +54,16 @@ static FILE *fp;
 extern struct ifinfo *iflist;
 
 static void dump_interface_status(void);
-static const char *sec2str(time_t);
 static const char * const ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", 
"TENTATIVE"};
 
 static void
 dump_interface_status(void)
 {
        struct ifinfo *ifi;
+       struct rainfo *rai;
+       struct ra_opt *rao;
        struct timeval now;
+       char ntopbuf[INET6_ADDRSTRLEN];
 
        gettimeofday(&now, NULL);
 
@@ -91,9 +94,33 @@ dump_interface_status(void)
                            (int)ifi->timer.tv_sec,
                            (int)ifi->timer.tv_usec,
                            (ifi->expire.tv_sec < now.tv_sec) ? "expired"
-                           : sec2str(ifi->expire.tv_sec - now.tv_sec));
+                           : sec2str(&ifi->expire));
                }
                fprintf(fp, "  number of valid RAs: %d\n", ifi->racnt);
+
+               TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
+                       fprintf(fp, "   RA from %s\n",
+                           inet_ntop(AF_INET6, &rai->rai_saddr.sin6_addr,
+                               ntopbuf, sizeof(ntopbuf)));
+                       TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
+                               fprintf(fp, "    option: ");
+                               switch (rao->rao_type) {
+                               case ND_OPT_RDNSS:
+                                       fprintf(fp, "RDNSS: %s (expire: %s)\n",
+                                           (char *)rao->rao_msg,
+                                           sec2str(&rao->rao_expire));
+                                       break;
+                               case ND_OPT_DNSSL:
+                                       fprintf(fp, "DNSSL: %s (expire: %s)\n",
+                                           (char *)rao->rao_msg,
+                                           sec2str(&rao->rao_expire));
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+                       fprintf(fp, "\n");
+               }
        }
 }
 
@@ -109,8 +136,8 @@ rtsold_dump_file(const char *dumpfile)
        fclose(fp);
 }
 
-static const char *
-sec2str(time_t total)
+const char *
+sec2str(const struct timeval *total)
 {
        static char result[256];
        int days, hours, mins, secs;
@@ -118,11 +145,19 @@ sec2str(time_t total)
        char *p = result;
        char *ep = &result[sizeof(result)];
        int n;
+       struct timeval now;
+       time_t tsec;
 
-       days = total / 3600 / 24;
-       hours = (total / 3600) % 24;
-       mins = (total / 60) % 60;
-       secs = total % 60;
+       gettimeofday(&now, NULL);
+       tsec  = total->tv_sec;
+       tsec += total->tv_usec / 1000000;
+       tsec -= now.tv_sec;
+       tsec -= now.tv_usec / 1000000;
+
+       days = tsec / 3600 / 24;
+       hours = (tsec / 3600) % 24;
+       mins = (tsec / 60) % 60;
+       secs = tsec % 60;
 
        if (days) {
                first = 0;

Modified: head/usr.sbin/rtsold/rtsol.c
==============================================================================
--- head/usr.sbin/rtsold/rtsol.c        Wed Jun  8 16:00:30 2011        
(r222860)
+++ head/usr.sbin/rtsold/rtsol.c        Wed Jun  8 16:03:29 2011        
(r222861)
@@ -85,6 +85,7 @@ static const struct sockaddr_in6 sin6_al
 static void call_script(const int, const char *const *, void *);
 static size_t dname_labeldec(char *, size_t, const char *);
 static int safefile(const char *);
+static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t);
 
 #define        _ARGS_OTHER     otherconf_script, ifi->ifname
 #define        _ARGS_RESADD    resolvconf_script, "-a", ifi->ifname
@@ -240,6 +241,7 @@ rtsol_input(int s)
        struct icmp6_hdr *icp;
        struct nd_router_advert *nd_ra;
        struct cmsghdr *cm;
+       struct rainfo *rai;
        char *raoptp;
        char *p;
        struct in6_addr *addr;
@@ -251,6 +253,8 @@ rtsol_input(int s)
        char dname[NI_MAXHOST];
        struct timeval now;
        struct timeval lifetime;
+       int newent_rai;
+       int newent_rao;
 
        /* get message.  namelen and controllen must always be initialized. */
        rcvmhdr.msg_namelen = sizeof(from);
@@ -367,22 +371,20 @@ rtsol_input(int s)
                ifi->otherconfig = 1;
                CALL_SCRIPT(OTHER, NULL);
        }
-
-       /* Initialize ra_opt per-interface structure. */
        gettimeofday(&now, NULL);
-       if (!TAILQ_EMPTY(&ifi->ifi_ra_opt))
-               while ((rao = TAILQ_FIRST(&ifi->ifi_ra_opt)) != NULL) {
-                       if (rao->rao_msg != NULL)
-                               free(rao->rao_msg);
-                       TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
-                       free(rao);
-               }
-       else
-               TAILQ_INIT(&ifi->ifi_ra_opt);
+       newent_rai = 0;
+       rai = find_rainfo(ifi, &from);
+       if (rai == NULL) {
+               ELM_MALLOC(rai, exit(1));
+               rai->rai_ifinfo = ifi;
+               TAILQ_INIT(&rai->rai_ra_opt);
+               memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr,
+                   sizeof(rai->rai_saddr.sin6_addr));
+               newent_rai = 1;
+       }
 
 #define        RA_OPT_NEXT_HDR(x)      (struct nd_opt_hdr *)((char *)x + \
                                (((struct nd_opt_hdr *)x)->nd_opt_len * 8))
-
        /* Process RA options. */
        warnmsg(LOG_DEBUG, __func__, "Processing RA");
        raoptp = (char *)icp + sizeof(struct nd_router_advert);
@@ -439,25 +441,35 @@ rtsol_input(int s)
                                warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
                                    nsbuf);
 
-                               ELM_MALLOC(rao, break);
-                               rao->rao_type = ndo->nd_opt_type;
-                               rao->rao_len = strlen(nsbuf);
-                               rao->rao_msg = strdup(nsbuf);
-                               if (rao->rao_msg == NULL) {
-                                       warnmsg(LOG_ERR, __func__,
-                                           "strdup failed: %s",
-                                           strerror(errno));
-                                       free(rao);
-                                       addr++;
-                                       continue;
+                               newent_rao = 0;
+                               rao = find_raopt(rai, ndo->nd_opt_type, nsbuf,
+                                   strlen(nsbuf));
+                               if (rao == NULL) {
+                                       ELM_MALLOC(rao, break);
+                                       rao->rao_type = ndo->nd_opt_type;
+                                       rao->rao_len = strlen(nsbuf);
+                                       rao->rao_msg = strdup(nsbuf);
+                                       if (rao->rao_msg == NULL) {
+                                               warnmsg(LOG_ERR, __func__,
+                                                   "strdup failed: %s",
+                                                   strerror(errno));
+                                               free(rao);
+                                               addr++;
+                                               continue;
+                                       }
+                                       newent_rao = 1;
                                }
                                /* Set expiration timer */
-                               memset(&rao->rao_expire, 0, 
sizeof(rao->rao_expire));
+                               memset(&rao->rao_expire, 0,
+                                   sizeof(rao->rao_expire));
                                memset(&lifetime, 0, sizeof(lifetime));
-                               lifetime.tv_sec = 
ntohl(rdnss->nd_opt_rdnss_lifetime);
+                               lifetime.tv_sec =
+                                   ntohl(rdnss->nd_opt_rdnss_lifetime);
                                timeradd(&now, &lifetime, &rao->rao_expire);
 
-                               TAILQ_INSERT_TAIL(&ifi->ifi_ra_opt, rao, 
rao_next);
+                               if (newent_rao)
+                                       TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
+                                           rao, rao_next);
                                addr++;
                        }
                        break;
@@ -488,24 +500,35 @@ rtsol_input(int s)
                                warnmsg(LOG_DEBUG, __func__, "dname = %s",
                                    dname);
 
-                               ELM_MALLOC(rao, break);
-                               rao->rao_type = ndo->nd_opt_type;
-                               rao->rao_len = strlen(dname);
-                               rao->rao_msg = strdup(dname);
-                               if (rao->rao_msg == NULL) {
-                                       warnmsg(LOG_ERR, __func__,
-                                           "strdup failed: %s",
-                                           strerror(errno));
-                                       free(rao);
-                                       break;
+                               newent_rao = 0;
+                               rao = find_raopt(rai, ndo->nd_opt_type, dname,
+                                   strlen(dname));
+                               if (rao == NULL) {
+                                       ELM_MALLOC(rao, break);
+                                       rao->rao_type = ndo->nd_opt_type;
+                                       rao->rao_len = strlen(dname);
+                                       rao->rao_msg = strdup(dname);
+                                       if (rao->rao_msg == NULL) {
+                                               warnmsg(LOG_ERR, __func__,
+                                                   "strdup failed: %s",
+                                                   strerror(errno));
+                                               free(rao);
+                                               addr++;
+                                               continue;
+                                       }
+                                       newent_rao = 1;
                                }
                                /* Set expiration timer */
-                               memset(&rao->rao_expire, 0, 
sizeof(rao->rao_expire));
+                               memset(&rao->rao_expire, 0,
+                                   sizeof(rao->rao_expire));
                                memset(&lifetime, 0, sizeof(lifetime));
-                               lifetime.tv_sec = 
ntohl(dnssl->nd_opt_dnssl_lifetime);
+                               lifetime.tv_sec =
+                                   ntohl(dnssl->nd_opt_dnssl_lifetime);
                                timeradd(&now, &lifetime, &rao->rao_expire);
 
-                               TAILQ_INSERT_TAIL(&ifi->ifi_ra_opt, rao, 
rao_next);
+                               if (newent_rao)
+                                       TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
+                                           rao, rao_next);
                                p += len;
                        }
                        break;
@@ -515,6 +538,9 @@ rtsol_input(int s)
                }
                raoptp = (char *)RA_OPT_NEXT_HDR(raoptp);
        }
+       if (newent_rai)
+               TAILQ_INSERT_TAIL(&ifi->ifi_rainfo, rai, rai_next);
+
        ra_opt_handler(ifi);
        ifi->racnt++;
 
@@ -539,6 +565,7 @@ int
 ra_opt_handler(struct ifinfo *ifi)
 {
        struct ra_opt *rao;
+       struct rainfo *rai;
        struct script_msg *smp1, *smp2, *smp3;
        struct timeval now;
        TAILQ_HEAD(, script_msg) sm_rdnss_head =
@@ -550,70 +577,87 @@ ra_opt_handler(struct ifinfo *ifi)
        dcount = 0;
        dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
        gettimeofday(&now, NULL);
-       TAILQ_FOREACH(rao, &ifi->ifi_ra_opt, rao_next) {
-               switch (rao->rao_type) {
-               case ND_OPT_RDNSS:
-                       if (timercmp(&now, &rao->rao_expire, >)) {
-                               warnmsg(LOG_INFO, __func__,
-                                       "expired rdnss entry: %s",
-                                       (char *)rao->rao_msg);
-                               break;
-                       }
-                       ELM_MALLOC(smp1, continue);
-                       ELM_MALLOC(smp2, goto free1);
-                       ELM_MALLOC(smp3, goto free2);
-                       smp1->sm_msg = resstr_ns_prefix;
-                       TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1, sm_next);
-                       smp2->sm_msg = rao->rao_msg;
-                       TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2, sm_next);
-                       smp3->sm_msg = resstr_nl;
-                       TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3, sm_next);
 
-                       break;
-               case ND_OPT_DNSSL:
-                       if (timercmp(&now, &rao->rao_expire, >)) {
-                               warnmsg(LOG_INFO, __func__,
-                                       "expired dnssl entry: %s",
-                                       (char *)rao->rao_msg);
+       /*
+        * All options from multiple RAs with the same or different
+        * source addresses on a single interface will be gathered and
+        * handled, not overridden.  [RFC 4861 6.3.4]
+        */
+       TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
+               TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
+                       switch (rao->rao_type) {
+                       case ND_OPT_RDNSS:
+                               if (timercmp(&now, &rao->rao_expire, >)) {
+                                       warnmsg(LOG_INFO, __func__,
+                                           "expired rdnss entry: %s",
+                                           (char *)rao->rao_msg);
+                                       break;
+                               }
+                               ELM_MALLOC(smp1, continue);
+                               ELM_MALLOC(smp2, goto free1);
+                               ELM_MALLOC(smp3, goto free2);
+                               smp1->sm_msg = resstr_ns_prefix;
+                               TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1,
+                                   sm_next);
+                               smp2->sm_msg = rao->rao_msg;
+                               TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2,
+                                   sm_next);
+                               smp3->sm_msg = resstr_nl;
+                               TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3,
+                                   sm_next);
+                               ifi->ifi_rdnss = IFI_DNSOPT_STATE_RECEIVED;
+
                                break;
-                       }
-                       dcount++;
-                       /* Check resolv.conf(5) restrictions. */
-                       if (dcount > 6) {
-                               warnmsg(LOG_INFO, __func__,
-                                   "dnssl entry exceeding maximum count (%d>6)"
-                                   ": %s", dcount, (char *)rao->rao_msg);
+                       case ND_OPT_DNSSL:
+                               if (timercmp(&now, &rao->rao_expire, >)) {
+                                       warnmsg(LOG_INFO, __func__,
+                                           "expired dnssl entry: %s",
+                                           (char *)rao->rao_msg);
+                                       break;
+                               }
+                               dcount++;
+                               /* Check resolv.conf(5) restrictions. */
+                               if (dcount > 6) {
+                                       warnmsg(LOG_INFO, __func__,
+                                           "dnssl entry exceeding maximum 
count (%d>6)"
+                                           ": %s", dcount, (char 
*)rao->rao_msg);
+                                       break;
+                               }
+                               if (256 < dlen + strlen(rao->rao_msg) +
+                                   strlen(resstr_sp)) {
+                                       warnmsg(LOG_INFO, __func__,
+                                           "dnssl entry exceeding maximum 
length "
+                                           "(>256): %s", (char *)rao->rao_msg);
+                                       break;
+                               }
+                               ELM_MALLOC(smp1, continue);
+                               ELM_MALLOC(smp2, goto free1);
+                               if (TAILQ_EMPTY(&sm_dnssl_head)) {
+                                       ELM_MALLOC(smp3, goto free2);
+                                       smp3->sm_msg = resstr_sh_prefix;
+                                       TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
+                                           sm_next);
+                               }
+                               smp1->sm_msg = rao->rao_msg;
+                               TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1,
+                                   sm_next);
+                               smp2->sm_msg = resstr_sp;
+                               TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2,
+                                   sm_next);
+                               dlen += strlen(rao->rao_msg) +
+                                   strlen(resstr_sp);
                                break;
-                       }
-                       if (256 < dlen + strlen(rao->rao_msg) +
-                           strlen(resstr_sp)) {
-                               warnmsg(LOG_INFO, __func__,
-                                   "dnssl entry exceeding maximum length "
-                                   "(>256): %s", (char *)rao->rao_msg);
+
+                               ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED;
+                       default:
                                break;
                        }
-                       ELM_MALLOC(smp1, continue);
-                       ELM_MALLOC(smp2, goto free1);
-                       if (TAILQ_EMPTY(&sm_dnssl_head)) {
-                               ELM_MALLOC(smp3, goto free2);
-                               smp3->sm_msg = resstr_sh_prefix;
-                               TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
-                                   sm_next);
-                       }
-                       smp1->sm_msg = rao->rao_msg;
-                       TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, sm_next);
-                       smp2->sm_msg = resstr_sp;
-                       TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2, sm_next);
-                       dlen += strlen(rao->rao_msg) + strlen(resstr_sp);
-                       break;
-               default:
-                       break;
-               }
-               continue;
+                       continue;
 free2:
-               free(smp2);
+                       free(smp2);
 free1:
-               free(smp1);
+                       free(smp1);
+               }
        }
        /* Add \n for DNSSL list. */
        if (!TAILQ_EMPTY(&sm_dnssl_head)) {
@@ -625,10 +669,12 @@ free1:
 
        if (!TAILQ_EMPTY(&sm_rdnss_head))
                CALL_SCRIPT(RESADD, &sm_rdnss_head);
-#if 0
-       else
+       else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
+           ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
                CALL_SCRIPT(RESDEL, NULL);
-#endif
+               ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
+               ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
+       }
 
 ra_opt_handler_freeit:
        /* Clear script message queue. */
@@ -638,9 +684,30 @@ ra_opt_handler_freeit:
                        free(smp1);
                }
        }
+       if (!TAILQ_EMPTY(&sm_dnssl_head)) {
+               while ((smp1 = TAILQ_FIRST(&sm_dnssl_head)) != NULL) {
+                       TAILQ_REMOVE(&sm_dnssl_head, smp1, sm_next);
+                       free(smp1);
+               }
+       }
        return (0);
 }
 
+static struct ra_opt *
+find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
+{
+       struct ra_opt *rao;
+
+       TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
+               if (rao->rao_type == type &&
+                   rao->rao_len == strlen(msg) &&
+                   memcmp(rao->rao_msg, msg, len) == 0)
+                       break;
+       }
+
+       return (rao);
+}
+
 static void
 call_script(const int argc, const char *const argv[], void *head)
 {

Modified: head/usr.sbin/rtsold/rtsold.c
==============================================================================
--- head/usr.sbin/rtsold/rtsold.c       Wed Jun  8 16:00:30 2011        
(r222860)
+++ head/usr.sbin/rtsold/rtsold.c       Wed Jun  8 16:03:29 2011        
(r222861)
@@ -44,6 +44,7 @@
 #include <netinet/in.h>
 #include <netinet/icmp6.h>
 #include <netinet/in_var.h>
+#include <arpa/inet.h>
 
 #include <netinet6/nd6.h>
 
@@ -408,7 +409,9 @@ ifconfig(char *ifname)
        }
        memset(ifi, 0, sizeof(*ifi));
        ifi->sdl = sdl;
-
+       ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
+       ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
+       TAILQ_INIT(&ifi->ifi_rainfo);
        strlcpy(ifi->ifname, ifname, sizeof(ifi->ifname));
 
        /* construct a router solicitation message */
@@ -500,6 +503,19 @@ ifreconfig(char *ifname)
 }
 #endif
 
+struct rainfo *
+find_rainfo(struct ifinfo *ifi, struct sockaddr_in6 *sin6)
+{
+       struct rainfo *rai;
+
+       TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next)
+               if (memcmp(&rai->rai_saddr.sin6_addr, &sin6->sin6_addr,
+                   sizeof(rai->rai_saddr.sin6_addr)) == 0)
+                       return (rai);
+
+       return (NULL);
+}
+
 struct ifinfo *
 find_ifinfo(int ifindex)
 {
@@ -556,6 +572,7 @@ rtsol_check_timer(void)
        static struct timeval returnval;
        struct timeval now, rtsol_timer;
        struct ifinfo *ifi;
+       struct rainfo *rai;
        struct ra_opt *rao;
        int flags;
 
@@ -565,18 +582,21 @@ rtsol_check_timer(void)
 
        TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
                if (timercmp(&ifi->expire, &now, <=)) {
-                       if (dflag > 1)
-                               warnmsg(LOG_DEBUG, __func__,
-                                   "timer expiration on %s, "
-                                   "state = %d", ifi->ifname,
-                                   ifi->state);
-
-                       /* Remove all RA options. */
-                       while ((rao = TAILQ_FIRST(&ifi->ifi_ra_opt)) != NULL) {
-                               if (rao->rao_msg != NULL)
-                                       free(rao->rao_msg);
-                               TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
-                               free(rao);
+                       warnmsg(LOG_DEBUG, __func__, "timer expiration on %s, "
+                           "state = %d", ifi->ifname, ifi->state);
+
+                       while((rai = TAILQ_FIRST(&ifi->ifi_rainfo)) != NULL) {
+                               /* Remove all RA options. */
+                               TAILQ_REMOVE(&ifi->ifi_rainfo, rai, rai_next);
+                               while ((rao = TAILQ_FIRST(&rai->rai_ra_opt)) !=
+                                   NULL) {
+                                       TAILQ_REMOVE(&rai->rai_ra_opt, rao,
+                                           rao_next);
+                                       if (rao->rao_msg != NULL)
+                                               free(rao->rao_msg);
+                                       free(rao);
+                               }
+                               free(rai);
                        }
                        switch (ifi->state) {
                        case IFS_DOWN:
@@ -645,21 +665,27 @@ rtsol_check_timer(void)
                        rtsol_timer_update(ifi);
                } else {
                        /* Expiration check for RA options. */
-                       struct ra_opt *rao_tmp;
                        int expire = 0;
 
-                       TAILQ_FOREACH_SAFE(rao, &ifi->ifi_ra_opt, rao_next, 
rao_tmp) {
-                               warnmsg(LOG_DEBUG, __func__,
-                                       "RA expiration timer: "
-                                       "type=%d, msg=%s, timer=%ld:%08ld",
-                                       rao->rao_type, (char *)rao->rao_msg,
-                                       (long)rao->rao_expire.tv_sec,
-                                       (long)rao->rao_expire.tv_usec);
-                               if (timercmp(&now, &rao->rao_expire, >=)) {
+                       TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
+                               TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
                                        warnmsg(LOG_DEBUG, __func__,
-                                               "RA expiration timer: 
expired.");
-                                       TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, 
rao_next);
-                                       expire = 1;
+                                           "RA expiration timer: "
+                                           "type=%d, msg=%s, expire=%s",
+                                           rao->rao_type, (char *)rao->rao_msg,
+                                               sec2str(&rao->rao_expire));
+                                       if (timercmp(&now, &rao->rao_expire,
+                                           >=)) {
+                                               warnmsg(LOG_DEBUG, __func__,
+                                                   "RA expiration timer: "
+                                                   "expired.");
+                                               TAILQ_REMOVE(&rai->rai_ra_opt,
+                                                   rao, rao_next);
+                                               if (rao->rao_msg != NULL)
+                                                       free(rao->rao_msg);
+                                               free(rao);
+                                               expire = 1;
+                                       }
                                }
                        }
                        if (expire)
@@ -678,9 +704,10 @@ rtsol_check_timer(void)
        else
                timersub(&rtsol_timer, &now, &returnval);
 
-       if (dflag > 1)
-               warnmsg(LOG_DEBUG, __func__, "New timer is %ld:%08ld",
-                   (long)returnval.tv_sec, (long)returnval.tv_usec);
+       now.tv_sec += returnval.tv_sec;
+       now.tv_usec += returnval.tv_usec;
+       warnmsg(LOG_DEBUG, __func__, "New timer is %s",
+           sec2str(&now));
 
        return (&returnval);
 }
@@ -751,11 +778,10 @@ rtsol_timer_update(struct ifinfo *ifi)
                gettimeofday(&now, NULL);
                timeradd(&now, &ifi->timer, &ifi->expire);
 
-               if (dflag > 1)
-                       warnmsg(LOG_DEBUG, __func__,
-                           "set timer for %s to %d:%d", ifi->ifname,
-                           (int)ifi->timer.tv_sec,
-                           (int)ifi->timer.tv_usec);
+               now.tv_sec += ifi->timer.tv_sec;
+               now.tv_usec += ifi->timer.tv_usec;
+               warnmsg(LOG_DEBUG, __func__, "set timer for %s to %s",
+                   ifi->ifname, sec2str(&now));
        }
 
 #undef MILLION

Modified: head/usr.sbin/rtsold/rtsold.h
==============================================================================
--- head/usr.sbin/rtsold/rtsold.h       Wed Jun  8 16:00:30 2011        
(r222860)
+++ head/usr.sbin/rtsold/rtsold.h       Wed Jun  8 16:03:29 2011        
(r222861)
@@ -46,6 +46,16 @@ struct ra_opt {
        void            *rao_msg;
 };
 
+TAILQ_HEAD(rainfo_head, ra_opt);
+
+struct rainfo {
+       TAILQ_ENTRY(rainfo)     rai_next;
+
+       struct ifinfo           *rai_ifinfo;
+       struct sockaddr_in6     rai_saddr;
+       TAILQ_HEAD(, ra_opt)    rai_ra_opt;
+};
+
 struct ifinfo {
        TAILQ_ENTRY(ifinfo)     ifi_next;       /* pointer to the next 
interface */
 
@@ -64,13 +74,16 @@ struct ifinfo {
        struct timeval timer;
        struct timeval expire;
        int errors;             /* # of errors we've got - detect wedge */
+#define IFI_DNSOPT_STATE_NOINFO                0
+#define IFI_DNSOPT_STATE_RECEIVED      1
+       int ifi_rdnss;          /* RDNSS option state */
+       int ifi_dnssl;          /* DNSSL option state */
 
        int racnt;              /* total # of valid RAs it have got */
+       TAILQ_HEAD(, rainfo)    ifi_rainfo;
 
        size_t rs_datalen;
        u_char *rs_data;
-
-       TAILQ_HEAD(, ra_opt)   ifi_ra_opt;
 };
 
 /* per interface status */
@@ -118,6 +131,7 @@ extern const char *resolvconf_script;
 extern int ifconfig(char *);
 extern void iflist_init(void);
 struct ifinfo *find_ifinfo(int);
+struct rainfo *find_rainfo(struct ifinfo *, struct sockaddr_in6 *);
 void rtsol_timer_update(struct ifinfo *);
 extern void warnmsg(int, const char *, const char *, ...)
      __attribute__((__format__(__printf__, 3, 4)));
@@ -145,6 +159,7 @@ extern void defrouter_probe(struct ifinf
 
 /* dump.c */
 extern void rtsold_dump_file(const char *);
+extern const char *sec2str(const struct timeval *);
 
 /* rtsock.c */
 extern int rtsock_open(void);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to