Here's an updated diff with the following changes:

- Send the ifidx of the configured 'iface' instead of ifidx 0 to prevent
  name collisions
- Cache the first received DNS server locally for cleanup/resending.
- Handle RTP_PROPOSAL_SOLICIT by resending the cached server.
- Remove the cached server from resolvd on cleanup.

There is no easy way to support multiple DNS servers from different peers
at the moment.  For now, iked will always propose the first DNS server it
receives and simply ignore the rest.  There is room for improvement here,
but i would rather do this in a follow-up diff.

ok?

Index: config.c
===================================================================
RCS file: /cvs/src/sbin/iked/config.c,v
retrieving revision 1.79
diff -u -p -r1.79 config.c
--- config.c    13 May 2021 15:20:48 -0000      1.79
+++ config.c    1 Sep 2021 11:26:51 -0000
@@ -174,6 +174,7 @@ config_free_sa(struct iked *env, struct 
 
        free(sa->sa_cp_addr);
        free(sa->sa_cp_addr6);
+       free(sa->sa_cp_dns);
 
        free(sa->sa_tag);
        free(sa);
Index: iked.c
===================================================================
RCS file: /cvs/src/sbin/iked/iked.c,v
retrieving revision 1.57
diff -u -p -r1.57 iked.c
--- iked.c      13 May 2021 15:20:48 -0000      1.57
+++ iked.c      1 Sep 2021 11:26:51 -0000
@@ -459,6 +459,9 @@ parent_dispatch_ikev2(int fd, struct pri
        case IMSG_IF_ADDADDR:
        case IMSG_IF_DELADDR:
                return (vroute_getaddr(env, imsg));
+       case IMSG_VDNS_ADD:
+       case IMSG_VDNS_DEL:
+               return (vroute_getdns(env, imsg));
        case IMSG_VROUTE_ADD:
        case IMSG_VROUTE_DEL:
                return (vroute_getroute(env, imsg));
Index: iked.h
===================================================================
RCS file: /cvs/src/sbin/iked/iked.h,v
retrieving revision 1.192
diff -u -p -r1.192 iked.h
--- iked.h      23 Jun 2021 12:11:40 -0000      1.192
+++ iked.h      1 Sep 2021 11:26:51 -0000
@@ -429,6 +429,7 @@ struct iked_sa {
        int                              sa_cp;         /* XXX */
        struct iked_addr                *sa_cp_addr;    /* requested address */
        struct iked_addr                *sa_cp_addr6;   /* requested address */
+       struct iked_addr                *sa_cp_dns;     /* requested dns */
 
        struct iked_policy              *sa_policy;
        struct timeval                   sa_timecreated;
@@ -611,6 +612,7 @@ struct iked_message {
        int                      msg_cp;
        struct iked_addr        *msg_cp_addr;   /* requested address */
        struct iked_addr        *msg_cp_addr6;  /* requested address */
+       struct iked_addr        *msg_cp_dns;    /* requested dns */
 
        /* MOBIKE */
        int                      msg_update_sa_addresses;
@@ -752,6 +754,7 @@ struct iked {
 
        int                              sc_pfkey;      /* ike process */
        struct event                     sc_pfkeyev;
+       struct event                     sc_routeev;
        uint8_t                          sc_certreqtype;
        struct ibuf                     *sc_certreq;
        void                            *sc_vroute;
@@ -975,6 +978,8 @@ void vroute_init(struct iked *);
 int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
 void vroute_cleanup(struct iked *);
 int vroute_getaddr(struct iked *, struct imsg *);
+int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
+int vroute_getdns(struct iked *, struct imsg *);
 int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
     uint8_t, struct sockaddr *);
 int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
Index: ikev2.c
===================================================================
RCS file: /cvs/src/sbin/iked/ikev2.c,v
retrieving revision 1.325
diff -u -p -r1.325 ikev2.c
--- ikev2.c     29 Jun 2021 15:39:20 -0000      1.325
+++ ikev2.c     1 Sep 2021 11:26:51 -0000
@@ -998,6 +998,13 @@ ikev2_ike_auth_recv(struct iked *env, st
                        log_info("%s: obtained lease: %s", SPI_SA(sa, __func__),
                            print_host((struct sockaddr 
*)&sa->sa_cp_addr6->addr, NULL, 0));
                }
+               if (msg->msg_cp_dns) {
+                       sa->sa_cp_dns = msg->msg_cp_dns;
+                       msg->msg_cp_dns = NULL;
+                       log_debug("%s: DNS: %s", __func__,
+                           print_host((struct sockaddr *)&sa->sa_cp_dns->addr,
+                           NULL, 0));
+               }
                sa->sa_cp = msg->msg_cp;
        }
 
@@ -4508,6 +4515,8 @@ ikev2_ikesa_enable(struct iked *env, str
        sa->sa_cp_addr = NULL;
        nsa->sa_cp_addr6 = sa->sa_cp_addr6;
        sa->sa_cp_addr6 = NULL;
+       nsa->sa_cp_dns = sa->sa_cp_dns;
+       sa->sa_cp_dns = NULL;
        /* Transfer other attributes */
         if (sa->sa_dstid_entry_valid) {
                sa_dstid_remove(env, sa);
Index: ikev2_msg.c
===================================================================
RCS file: /cvs/src/sbin/iked/ikev2_msg.c,v
retrieving revision 1.77
diff -u -p -r1.77 ikev2_msg.c
--- ikev2_msg.c 29 Oct 2020 21:49:58 -0000      1.77
+++ ikev2_msg.c 1 Sep 2021 11:26:51 -0000
@@ -197,6 +197,7 @@ ikev2_msg_cleanup(struct iked *env, stru
                free(msg->msg_eap.eam_user);
                free(msg->msg_cp_addr);
                free(msg->msg_cp_addr6);
+               free(msg->msg_cp_dns);
 
                msg->msg_nonce = NULL;
                msg->msg_ke = NULL;
@@ -209,6 +210,7 @@ ikev2_msg_cleanup(struct iked *env, stru
                msg->msg_eap.eam_user = NULL;
                msg->msg_cp_addr = NULL;
                msg->msg_cp_addr6 = NULL;
+               msg->msg_cp_dns = NULL;
 
                config_free_proposals(&msg->msg_proposals, 0);
                while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs))) {
Index: ikev2_pld.c
===================================================================
RCS file: /cvs/src/sbin/iked/ikev2_pld.c,v
retrieving revision 1.117
diff -u -p -r1.117 ikev2_pld.c
--- ikev2_pld.c 19 Feb 2021 21:52:53 -0000      1.117
+++ ikev2_pld.c 1 Sep 2021 11:26:51 -0000
@@ -1842,6 +1842,7 @@ ikev2_pld_cp(struct iked *env, struct ik
        uint8_t                 *ptr;
        size_t                   len;
        uint8_t                  buf[128];
+       int                      cfg_type;
 
        if (ikev2_validate_cp(msg, offset, left, &cp))
                return (-1);
@@ -1878,8 +1879,10 @@ ikev2_pld_cp(struct iked *env, struct ik
 
                print_hex(ptr, sizeof(*cfg), betoh16(cfg->cfg_length));
 
-               switch (betoh16(cfg->cfg_type)) {
+               cfg_type = betoh16(cfg->cfg_type);
+               switch (cfg_type) {
                case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
+               case IKEV2_CFG_INTERNAL_IP4_DNS:
                        if (!ikev2_msg_frompeer(msg))
                                break;
                        if (betoh16(cfg->cfg_length) == 0)
@@ -1891,8 +1894,20 @@ ikev2_pld_cp(struct iked *env, struct ik
                                    __func__, betoh16(cfg->cfg_length), 4);
                                return (-1);
                        }
-                       if (msg->msg_parent->msg_cp_addr != NULL) {
-                               log_debug("%s: address already set", __func__);
+                       switch(cfg_type) {
+                       case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
+                               if (msg->msg_parent->msg_cp_addr != NULL) {
+                                       log_debug("%s: address already set", 
__func__);
+                                       goto skip;
+                               }
+                               break;
+                       case IKEV2_CFG_INTERNAL_IP4_DNS:
+                               if (msg->msg_parent->msg_cp_dns != NULL) {
+                                       log_debug("%s: dns already set", 
__func__);
+                                       goto skip;
+                               }
+                               break;
+                       default:
                                break;
                        }
                        if ((addr = calloc(1, sizeof(*addr))) == NULL) {
@@ -1907,22 +1922,42 @@ ikev2_pld_cp(struct iked *env, struct ik
                        print_host((struct sockaddr *)in4, (char *)buf,
                            sizeof(buf));
                        log_debug("%s: cfg %s", __func__, buf);
-                       msg->msg_parent->msg_cp_addr = addr;
+                       switch(cfg_type) {
+                       case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
+                               msg->msg_parent->msg_cp_addr = addr;
+                               log_debug("%s: IP4_ADDRESS %s", __func__, buf);
+                               break;
+                       case IKEV2_CFG_INTERNAL_IP4_DNS:
+                               msg->msg_parent->msg_cp_dns = addr;
+                               log_debug("%s: IP4_DNS %s", __func__, buf);
+                               break;
+                       }
                        break;
                case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
+               case IKEV2_CFG_INTERNAL_IP6_DNS:
                        if (!ikev2_msg_frompeer(msg))
                                break;
                        if (betoh16(cfg->cfg_length) == 0)
                                break;
                        /* XXX multiple-valued */
-                       if (betoh16(cfg->cfg_length) < 16 + 1) {
+                       if (betoh16(cfg->cfg_length) < 16) {
                                log_debug("%s: malformed payload: too short "
                                    "for ipv6 addr w/prefixlen (%u < %u)",
-                                   __func__, betoh16(cfg->cfg_length), 16 + 1);
+                                   __func__, betoh16(cfg->cfg_length), 16);
                                return (-1);
                        }
-                       if (msg->msg_parent->msg_cp_addr6 != NULL) {
-                               log_debug("%s: address already set", __func__);
+                       switch(cfg_type) {
+                       case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
+                               if (msg->msg_parent->msg_cp_addr6 != NULL) {
+                                       log_debug("%s: address6 already set", 
__func__);
+                                       goto skip;
+                               }
+                               break;
+                       case IKEV2_CFG_INTERNAL_IP6_DNS:
+                               if (msg->msg_parent->msg_cp_dns != NULL) {
+                                       log_debug("%s: dns already set", 
__func__);
+                                       goto skip;
+                               }
                                break;
                        }
                        if ((addr = calloc(1, sizeof(*addr))) == NULL) {
@@ -1937,10 +1972,20 @@ ikev2_pld_cp(struct iked *env, struct ik
                        print_host((struct sockaddr *)in6, (char *)buf,
                            sizeof(buf));
                        log_debug("%s: cfg %s/%d", __func__, buf, ptr[16]);
-                       msg->msg_parent->msg_cp_addr6 = addr;
+                       switch(cfg_type) {
+                       case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
+                               msg->msg_parent->msg_cp_addr6 = addr;
+                               log_debug("%s: IP6_ADDRESS %s", __func__, buf);
+                               break;
+                       case IKEV2_CFG_INTERNAL_IP6_DNS:
+                               msg->msg_parent->msg_cp_dns = addr;
+                               log_debug("%s: IP6_DNS %s", __func__, buf);
+                               break;
+                       }
                        break;
                }
 
+ skip:
                ptr += betoh16(cfg->cfg_length);
                len -= betoh16(cfg->cfg_length);
        }
Index: policy.c
===================================================================
RCS file: /cvs/src/sbin/iked/policy.c,v
retrieving revision 1.82
diff -u -p -r1.82 policy.c
--- policy.c    23 Jun 2021 12:11:40 -0000      1.82
+++ policy.c    1 Sep 2021 11:26:51 -0000
@@ -680,6 +680,13 @@ sa_configure_iface(struct iked *env, str
        if (sa->sa_policy == NULL || sa->sa_policy->pol_iface == 0)
                return (0);
 
+       if (sa->sa_cp_dns) {
+               if (vroute_setdns(env, add,
+                   (struct sockaddr *)&sa->sa_cp_dns->addr,
+                   sa->sa_policy->pol_iface) != 0)
+                       return (-1);
+       }
+
        if (!sa->sa_cp_addr && !sa->sa_cp_addr6)
                return (0);
 
Index: types.h
===================================================================
RCS file: /cvs/src/sbin/iked/types.h,v
retrieving revision 1.44
diff -u -p -r1.44 types.h
--- types.h     3 Aug 2021 12:46:30 -0000       1.44
+++ types.h     1 Sep 2021 11:26:51 -0000
@@ -119,6 +119,8 @@ enum imsg_type {
        IMSG_VROUTE_ADD,
        IMSG_VROUTE_DEL,
        IMSG_VROUTE_CLONE,
+       IMSG_VDNS_ADD,
+       IMSG_VDNS_DEL,
        IMSG_OCSP_FD,
        IMSG_OCSP_CFG,
        IMSG_AUTH,
Index: vroute.c
===================================================================
RCS file: /cvs/src/sbin/iked/vroute.c,v
retrieving revision 1.12
diff -u -p -r1.12 vroute.c
--- vroute.c    23 Jun 2021 12:21:23 -0000      1.12
+++ vroute.c    1 Sep 2021 11:26:51 -0000
@@ -35,6 +35,7 @@
 
 #include <iked.h>
 
+#define ROUTE_SOCKET_BUF_SIZE  16384
 #define IKED_VROUTE_PRIO       6
 
 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : 
sizeof(long))
@@ -44,10 +45,14 @@ int vroute_setroute(struct iked *, uint8
 int vroute_doroute(struct iked *, int, int, int, uint8_t, struct sockaddr *,
     struct sockaddr *, struct sockaddr *, int *);
 int vroute_doaddr(struct iked *, char *, struct sockaddr *, struct sockaddr *, 
int);
+int vroute_dodns(struct iked *, struct sockaddr *, int, unsigned int);
 void vroute_cleanup(struct iked *);
+void vroute_rtmsg_cb(int, short, void *);
 
 void vroute_insertaddr(struct iked *, int, struct sockaddr *, struct sockaddr 
*);
 void vroute_removeaddr(struct iked *, int, struct sockaddr *, struct sockaddr 
*);
+void vroute_insertdns(struct iked *, int, struct sockaddr *);
+void vroute_removedns(struct iked *, int, struct sockaddr *);
 void vroute_insertroute(struct iked *, int, struct sockaddr *, struct sockaddr 
*);
 void vroute_removeroute(struct iked *, int, struct sockaddr *, struct sockaddr 
*);
 
@@ -68,14 +73,21 @@ struct vroute_route {
 };
 TAILQ_HEAD(vroute_routes, vroute_route);
 
+struct vroute_dns {
+       struct  sockaddr_storage        vd_addr;
+       int                             vd_ifidx;
+};
+
 struct iked_vroute_sc {
-       struct vroute_addrs     ivr_addrs;
-       struct vroute_routes    ivr_routes;
-       int                     ivr_iosock;
-       int                     ivr_iosock6;
-       int                     ivr_rtsock;
-       int                     ivr_rtseq;
-       pid_t                   ivr_pid;
+       struct vroute_addrs      ivr_addrs;
+       struct vroute_routes     ivr_routes;
+       struct vroute_dns       *ivr_dns;
+       struct event             ivr_routeev;
+       int                      ivr_iosock;
+       int                      ivr_iosock6;
+       int                      ivr_rtsock;
+       int                      ivr_rtseq;
+       pid_t                    ivr_pid;
 };
 
 struct vroute_msg {
@@ -87,9 +99,57 @@ int vroute_process(struct iked *, int ms
     struct sockaddr *, struct sockaddr *, struct sockaddr *, int *);
 
 void
+vroute_rtmsg_cb(int fd, short events, void *arg)
+{
+       struct iked             *env = (struct iked *) arg;
+       struct iked_vroute_sc   *ivr = env->sc_vroute;
+       static uint8_t          *buf;
+       struct rt_msghdr        *rtm;
+       ssize_t                  n;
+
+       if (buf == NULL) {
+               buf = malloc(ROUTE_SOCKET_BUF_SIZE);
+               if (buf == NULL)
+                       fatal("malloc");
+       }
+       rtm = (struct rt_msghdr *)buf;
+       if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) {
+               if (errno == EAGAIN || errno == EINTR)
+                       return;
+               log_warn("%s: read error", __func__);
+               return;
+       }
+
+       if (n == 0)
+               fatal("routing socket closed");
+
+       if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
+               log_warnx("partial rtm of %zd in buffer", n);
+               return;
+       }
+
+       if (rtm->rtm_version != RTM_VERSION)
+               return;
+
+       switch(rtm->rtm_type) {
+       case RTM_PROPOSAL:
+               if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) {
+                       log_debug("%s: got solicit", __func__);
+                       vroute_dodns(env, (struct sockaddr *) 
&ivr->ivr_dns->vd_addr, 1,
+                           ivr->ivr_dns->vd_ifidx);
+               }
+               break;
+       default:
+               log_debug("%s: unexpected RTM: %d", __func__, rtm->rtm_type);
+               break;
+       }
+}
+
+void
 vroute_init(struct iked *env)
 {
        struct iked_vroute_sc   *ivr;
+       int                      rtfilter;
 
        ivr = calloc(1, sizeof(*ivr));
        if (ivr == NULL)
@@ -104,12 +164,21 @@ vroute_init(struct iked *env)
        if ((ivr->ivr_rtsock = socket(AF_ROUTE, SOCK_RAW, AF_UNSPEC)) == -1)
                fatal("%s: failed to create routing socket", __func__);
 
+       rtfilter = ROUTE_FILTER(RTM_GET) | ROUTE_FILTER(RTM_PROPOSAL);
+       if (setsockopt(ivr->ivr_rtsock, AF_ROUTE, ROUTE_MSGFILTER, &rtfilter,
+           sizeof(rtfilter)) == -1)
+               fatal("%s: setsockopt(ROUTE_MSGFILTER)", __func__);
+
        TAILQ_INIT(&ivr->ivr_addrs);
        TAILQ_INIT(&ivr->ivr_routes);
 
        ivr->ivr_pid = getpid();
 
        env->sc_vroute = ivr;
+
+       event_set(&ivr->ivr_routeev, ivr->ivr_rtsock, EV_READ | EV_PERSIST,
+           vroute_rtmsg_cb, env);
+       event_add(&ivr->ivr_routeev, NULL);
 }
 
 void
@@ -138,6 +207,12 @@ vroute_cleanup(struct iked *env)
                TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry);
                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);
+       }
 }
 
 int
@@ -239,6 +314,64 @@ vroute_getaddr(struct iked *env, struct 
        return (vroute_doaddr(env, ifname, addr, mask, add));
 }
 
+int
+vroute_setdns(struct iked *env, int add, struct sockaddr *addr,
+    unsigned int ifidx)
+{
+       struct iovec             iov[2];
+
+       iov[0].iov_base = addr;
+       iov[0].iov_len = addr->sa_len;
+
+       iov[1].iov_base = &ifidx;
+       iov[1].iov_len = sizeof(ifidx);
+
+       return (proc_composev(&env->sc_ps, PROC_PARENT,
+           add ? IMSG_VDNS_ADD: IMSG_VDNS_DEL, iov, 2));
+}
+
+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;
+       int                      add;
+       unsigned int             ifidx;
+
+       ptr = imsg->data;
+       left = IMSG_DATA_SIZE(imsg);
+
+       if (left < sizeof(*dns))
+               fatalx("bad length imsg received");
+
+       dns = (struct sockaddr *) ptr;
+       if (left < dns->sa_len)
+               fatalx("bad length imsg received");
+       ptr += dns->sa_len;
+       left -= dns->sa_len;
+
+       if (left != sizeof(ifidx))
+               fatalx("bad length imsg received");
+       memcpy(&ifidx, ptr, sizeof(ifidx));
+       ptr += sizeof(ifidx);
+       left -= sizeof(ifidx);
+
+       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);
+       }
+
+       return (vroute_dodns(env, dns, add, ifidx));
+}
+
 void
 vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest,
     struct sockaddr *mask)
@@ -285,6 +418,35 @@ vroute_removeroute(struct iked *env, int
 }
 
 void
+vroute_insertdns(struct iked *env, int ifidx, struct sockaddr *addr)
+{
+       struct iked_vroute_sc   *ivr = env->sc_vroute;
+       struct vroute_dns       *dns;
+       
+       dns = calloc(1, sizeof(*dns));
+       if (dns == NULL)
+               fatalx("%s: calloc.", __func__);
+
+       memcpy(&dns->vd_addr, addr, addr->sa_len);
+       dns->vd_ifidx = ifidx;
+       
+       ivr->ivr_dns = dns;
+}
+
+void
+vroute_removedns(struct iked *env, int ifidx, struct sockaddr *addr)
+{
+       struct iked_vroute_sc   *ivr = env->sc_vroute;
+
+       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;
+       }
+}
+
+void
 vroute_insertaddr(struct iked *env, int ifidx, struct sockaddr *addr,
     struct sockaddr *mask)
 {
@@ -525,6 +687,73 @@ vroute_getcloneroute(struct iked *env, s
        return (vroute_doroute(env, flags, addrs, rdomain, RTM_ADD,
            (struct sockaddr *)&dest, (struct sockaddr *)&mask,
            (struct sockaddr *)&addr, NULL));
+}
+
+int
+vroute_dodns(struct iked *env, struct sockaddr *dns, int add,
+    unsigned int ifidx)
+{
+       struct vroute_msg        m_rtmsg;
+       struct sockaddr_in       *in;
+       struct sockaddr_in6      *in6;
+       struct sockaddr_rtdns    rtdns;
+       struct iked_vroute_sc   *ivr = env->sc_vroute;
+       struct iovec             iov[3];
+       int                      i;
+       long                     pad = 0;
+       int                      iovcnt = 0, padlen;
+
+       bzero(&m_rtmsg, sizeof(m_rtmsg));
+#define rtm m_rtmsg.vm_rtm
+       rtm.rtm_version = RTM_VERSION;
+       rtm.rtm_type = RTM_PROPOSAL;
+       rtm.rtm_seq = ++ivr->ivr_rtseq;
+       rtm.rtm_priority = RTP_PROPOSAL_STATIC;
+       rtm.rtm_flags = RTF_UP;
+       rtm.rtm_addrs = RTA_DNS;
+       rtm.rtm_index = ifidx;
+
+       iov[iovcnt].iov_base = &rtm;
+       iov[iovcnt].iov_len = sizeof(rtm);
+       iovcnt++;
+
+       bzero(&rtdns, sizeof(rtdns));
+       rtdns.sr_family = dns->sa_family;
+       rtdns.sr_len = 2;
+       if (add) {
+               switch(dns->sa_family) {
+               case AF_INET:
+                       rtdns.sr_family = AF_INET;
+                       rtdns.sr_len += sizeof(struct in_addr);
+                       in = (struct sockaddr_in *)dns;
+                       memcpy(rtdns.sr_dns, &in->sin_addr, sizeof(struct 
in_addr));
+                       break;
+               case AF_INET6:
+                       rtdns.sr_family = AF_INET6;
+                       rtdns.sr_len += sizeof(struct in6_addr);
+                       in6 = (struct sockaddr_in6 *)dns;
+                       memcpy(rtdns.sr_dns, &in6->sin6_addr, sizeof(struct 
in6_addr));
+                       break;
+               default:
+                       return (-1);
+               }
+       }
+       iov[iovcnt].iov_base = &rtdns;
+       iov[iovcnt++].iov_len = sizeof(rtdns);
+       padlen = ROUNDUP(sizeof(rtdns)) - sizeof(rtdns);
+       if (padlen > 0) {
+               iov[iovcnt].iov_base = &pad;
+               iov[iovcnt++].iov_len = padlen;
+       }
+
+       for (i = 0; i < iovcnt; i++)
+               rtm.rtm_msglen += iov[i].iov_len;
+#undef rtm
+
+       if (writev(ivr->ivr_rtsock, iov, iovcnt) == -1)
+               log_warn("failed to send route message");
+
+       return (0);
 }
 
 int

Reply via email to