Hi,

iked currently enforces an arbitrary limit of only a single remote name
server.  As we have found out, a good reason to support more than one
is to have a backup when the connection to that server fails for some
reason.

With the diff below we can support all the name servers we get and
fall back to the next one if one connection dies.

ok?

Index: vroute.c
===================================================================
RCS file: /cvs/src/sbin/iked/vroute.c,v
retrieving revision 1.17
diff -u -p -r1.17 vroute.c
--- vroute.c    18 Jul 2022 19:32:16 -0000      1.17
+++ vroute.c    8 Feb 2023 20:46:13 -0000
@@ -76,12 +76,14 @@ TAILQ_HEAD(vroute_routes, vroute_route);
 struct vroute_dns {
        struct  sockaddr_storage        vd_addr;
        int                             vd_ifidx;
+       TAILQ_ENTRY(vroute_dns)         vd_entry;
 };
+TAILQ_HEAD(vroute_dnss, vroute_dns);
 
 struct iked_vroute_sc {
        struct vroute_addrs      ivr_addrs;
        struct vroute_routes     ivr_routes;
-       struct vroute_dns       *ivr_dns;
+       struct vroute_dnss       ivr_dnss;
        struct event             ivr_routeev;
        int                      ivr_iosock;
        int                      ivr_iosock6;
@@ -103,6 +105,7 @@ vroute_rtmsg_cb(int fd, short events, vo
 {
        struct iked             *env = (struct iked *) arg;
        struct iked_vroute_sc   *ivr = env->sc_vroute;
+       struct vroute_dns       *dns;
        static uint8_t          *buf;
        struct rt_msghdr        *rtm;
        ssize_t                  n;
@@ -133,11 +136,12 @@ vroute_rtmsg_cb(int fd, short events, vo
 
        switch(rtm->rtm_type) {
        case RTM_PROPOSAL:
-               if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT &&
-                   ivr->ivr_dns) {
-                       log_debug("%s: got solicit", __func__);
-                       vroute_dodns(env, (struct sockaddr 
*)&ivr->ivr_dns->vd_addr, 1,
-                           ivr->ivr_dns->vd_ifidx);
+               if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) {
+                       TAILQ_FOREACH(dns, &ivr->ivr_dnss, vd_entry) {
+                               log_debug("%s: got solicit", __func__);
+                               vroute_dodns(env, (struct sockaddr *) 
&dns->vd_addr,
+                                   1, dns->vd_ifidx);
+                       }
                }
                break;
        default:
@@ -171,6 +175,7 @@ vroute_init(struct iked *env)
                fatal("%s: setsockopt(ROUTE_MSGFILTER)", __func__);
 
        TAILQ_INIT(&ivr->ivr_addrs);
+       TAILQ_INIT(&ivr->ivr_dnss);
        TAILQ_INIT(&ivr->ivr_routes);
 
        ivr->ivr_pid = getpid();
@@ -189,6 +194,7 @@ vroute_cleanup(struct iked *env)
        struct iked_vroute_sc   *ivr = env->sc_vroute;
        struct vroute_addr      *addr;
        struct vroute_route     *route;
+       struct vroute_dns       *dns;
 
        while ((addr = TAILQ_FIRST(&ivr->ivr_addrs))) {
                if_indextoname(addr->va_ifidx, ifname);
@@ -209,10 +215,11 @@ vroute_cleanup(struct iked *env)
                free(route);
        }
 
-       if (ivr->ivr_dns) {
-               vroute_dodns(env, (struct sockaddr *)&ivr->ivr_dns->vd_addr, 0,
-                   ivr->ivr_dns->vd_ifidx);
-               free(ivr->ivr_dns);
+       while ((dns = TAILQ_FIRST(&ivr->ivr_dnss))) {
+               vroute_dodns(env, (struct sockaddr *)&dns->vd_addr, 0,
+                   dns->vd_ifidx);
+               TAILQ_REMOVE(&ivr->ivr_dnss, dns, vd_entry);
+               free(dns);
        }
 }
 
@@ -334,7 +341,6 @@ vroute_setdns(struct iked *env, int add,
 int
 vroute_getdns(struct iked *env, struct imsg *imsg)
 {
-       struct iked_vroute_sc   *ivr = env->sc_vroute;
        struct sockaddr         *dns;
        uint8_t                 *ptr;
        size_t                   left;
@@ -361,12 +367,8 @@ vroute_getdns(struct iked *env, struct i
 
        add = (imsg->hdr.type == IMSG_VDNS_ADD);
        if (add) {
-               if (ivr->ivr_dns != NULL)
-                       return (0);
                vroute_insertdns(env, ifidx, dns);
        } else {
-               if (ivr->ivr_dns == NULL)
-                       return (0);
                vroute_removedns(env, ifidx, dns);
        }
 
@@ -432,19 +434,23 @@ vroute_insertdns(struct iked *env, int i
        memcpy(&dns->vd_addr, addr, addr->sa_len);
        dns->vd_ifidx = ifidx;
 
-       ivr->ivr_dns = dns;
+       TAILQ_INSERT_TAIL(&ivr->ivr_dnss, dns, vd_entry);
 }
 
 void
 vroute_removedns(struct iked *env, int ifidx, struct sockaddr *addr)
 {
        struct iked_vroute_sc   *ivr = env->sc_vroute;
+       struct vroute_dns       *dns, *tdns;
+
+       TAILQ_FOREACH_SAFE(dns, &ivr->ivr_dnss, vd_entry, tdns) {
+               if (ifidx != dns->vd_ifidx)
+                       continue;
+               if (sockaddr_cmp(addr, (struct sockaddr *) &dns->vd_addr, -1))
+                       continue;
 
-       if (ifidx == ivr->ivr_dns->vd_ifidx &&
-           sockaddr_cmp(addr, (struct sockaddr *)
-           &ivr->ivr_dns->vd_addr, -1) == 0) {
-               free(ivr->ivr_dns);
-               ivr->ivr_dns = NULL;
+               TAILQ_REMOVE(&ivr->ivr_dnss, dns, vd_entry);
+               free(dns);
        }
 }
 

Reply via email to