]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Merge multiple options together as per RFC4861 section 6.3.4
authorRoy Marples <roy@marples.name>
Wed, 14 Nov 2012 10:30:30 +0000 (10:30 +0000)
committerRoy Marples <roy@marples.name>
Wed, 14 Nov 2012 10:30:30 +0000 (10:30 +0000)
ipv6rs.c

index d5112f9ed962834483c87d7ae299c714fcc36243..7449de7e123f9a58d62fac1136317d831979dc78 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -756,6 +756,8 @@ handle_flag:
                if (new_data)
                        syslog(LOG_WARNING, "%s: no support for DHCPv6 management",
                            ifp->name);
+               if (options & DHCPCD_TEST)
+                       exit(EXIT_SUCCESS);
 //             if (dhcp6_start(ifp, 1) == -1)
 //                     syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
        } else if (rap->flags & ND_RA_FLAG_OTHER) {
@@ -765,11 +767,12 @@ handle_flag:
                if (new_data)
                        syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA",
                            ifp->name);
+               if (options & DHCPCD_TEST)
+                       exit(EXIT_SUCCESS);
        }
 
        /* Expire should be called last as the rap object could be destroyed */
-       if (!(options & DHCPCD_TEST))
-               ipv6rs_expire(ifp);
+       ipv6rs_expire(ifp);
 }
 
 int
@@ -793,9 +796,11 @@ ipv6rs_env(char **env, const char *prefix, const struct interface *ifp)
        int i;
        char buffer[32];
        const char *optn;
+       char **pref, **mtu, **rdnss, **dnssl, ***var, *new;
 
        i = 0;
        l = 0;
+       pref = rdnss = dnssl = NULL;
        get_monotonic(&now);
        TAILQ_FOREACH(rap, &ipv6_routers, next) {
                i++;
@@ -811,27 +816,46 @@ ipv6rs_env(char **env, const char *prefix, const struct interface *ifp)
                TAILQ_FOREACH(rao, &rap->options, next) {
                        if (rao->option == NULL)
                                continue;
-                       l++;
-                       if (env == NULL)
-                               continue;
                        switch (rao->type) {
                        case ND_OPT_PREFIX_INFORMATION:
                                optn = "prefix";
+                               var = &pref;
                                break;
                        case ND_OPT_MTU:
                                optn = "mtu";
+                               var = &mtu;
                                break;
                        case ND_OPT_RDNSS:
                                optn = "rdnss";
+                               var = &rdnss;   
                                break;
                        case ND_OPT_DNSSL:
                                optn = "dnssl";
+                               var = &dnssl;
                                break;
                        default:
                                continue;
                        }
-                       snprintf(buffer, sizeof(buffer), "ra%d_%s", i, optn);
-                       setvar(&env, prefix, buffer, rao->option);
+                       if (*var == NULL) {
+                               *var = env ? env : &new;
+                               l++;
+                       } else if (env) {
+                               new = realloc(**var,
+                                   strlen(**var) + 1 +
+                                   strlen(rao->option) + 1);
+                               if (new) {
+                                       **var = new;
+                                       new += strlen(new);
+                                       *new++ = ' ';
+                                       strcpy(new, rao->option);
+                                       continue;
+                               }
+                       }
+                       if (env) {
+                               snprintf(buffer, sizeof(buffer),
+                                   "ra%d_%s", i, optn);
+                               setvar(&env, prefix, buffer, rao->option);
+                       }
                }
        }
 
@@ -865,7 +889,7 @@ ipv6rs_expire(void *arg)
        struct ipv6_addr *ap, *apn;
        struct ra_opt *rao, *raon;
        struct timeval now, lt, expire, next;
-       int expired;
+       int expired, valid;
 
        ifp = arg;
        get_monotonic(&now);
@@ -879,6 +903,7 @@ ipv6rs_expire(void *arg)
                lt.tv_usec = 0;
                timeradd(&rap->received, &lt, &expire);
                if (timercmp(&now, &expire, >)) {
+                       valid = 0;
                        if (!rap->expired) {
                                syslog(LOG_INFO,
                                    "%s: %s: expired default Router",
@@ -886,6 +911,7 @@ ipv6rs_expire(void *arg)
                                rap->expired = expired = 1;
                        }
                } else {
+                       valid = 1;
                        timersub(&expire, &now, &lt);
                        if (!timerisset(&next) || timercmp(&next, &lt, >))
                                next = lt;
@@ -925,10 +951,16 @@ ipv6rs_expire(void *arg)
                                free(rao);
                                continue;
                        }
+                       valid = 1;
                        timersub(&rao->expire, &now, &lt);
                        if (!timerisset(&next) || timercmp(&next, &lt, >))
                                next = lt;
                }
+
+               /* No valid lifetimes are left on the RA, so we might
+                * as well punt it. */
+               if (!valid)
+                       ipv6rs_free_ra(rap);
        }
 
        if (timerisset(&next))