On 2021-09-01 13:28 +02, Tobias Heider <tobias.hei...@stusta.de> wrote:
> 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?

the DNS bits look correct. There seem to be unrelated fixes in here?
One comment inline.

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

Why are you filtering RTM_GET? I don't think you need it.

> +     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
>

-- 
I'm not entirely sure you are real.

Reply via email to