Add support for configuring multiple name servers as roadwarrior
authortobhe <tobhe@openbsd.org>
Fri, 10 Feb 2023 19:51:08 +0000 (19:51 +0000)
committertobhe <tobhe@openbsd.org>
Fri, 10 Feb 2023 19:51:08 +0000 (19:51 +0000)
client.  This allows us to have a fallback in case one connection
fails.

Tested by Ryan Kavanagh
ok patrick@

sbin/iked/vroute.c

index 89a7f01..7f900e7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vroute.c,v 1.17 2022/07/18 19:32:16 tobhe Exp $       */
+/*     $OpenBSD: vroute.c,v 1.18 2023/02/10 19:51:08 tobhe Exp $       */
 
 /*
  * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
@@ -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, void *arg)
 {
        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, void *arg)
 
        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, struct sockaddr *addr,
 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 imsg *imsg)
 
        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 ifidx, struct sockaddr *addr)
        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);
        }
 }