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); } }