Set RTF_GATEWAY for host route based on RTM_GET response.
authortobhe <tobhe@openbsd.org>
Sat, 27 Feb 2021 17:07:04 +0000 (17:07 +0000)
committertobhe <tobhe@openbsd.org>
Sat, 27 Feb 2021 17:07:04 +0000 (17:07 +0000)
sbin/iked/vroute.c

index ebba6b9..fe839fc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vroute.c,v 1.4 2021/02/26 21:06:02 tobhe Exp $        */
+/*     $OpenBSD: vroute.c,v 1.5 2021/02/27 17:07:04 tobhe Exp $        */
 
 /*
  * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
@@ -43,7 +43,7 @@
 int vroute_setroute(struct iked *, uint8_t, struct sockaddr *, uint8_t,
     struct sockaddr *, int);
 int vroute_doroute(struct iked *, int, int, int, uint8_t, struct sockaddr *,
-    struct sockaddr *, struct sockaddr *);
+    struct sockaddr *, struct sockaddr *, int *);
 int vroute_doaddr(struct iked *, char *, struct sockaddr *, struct sockaddr *, int);
 
 struct iked_vroute_sc {
@@ -60,7 +60,7 @@ struct vroute_msg {
 };
 
 int vroute_process(struct iked *, int msglen, struct vroute_msg *,
-    struct sockaddr *, struct sockaddr *, struct sockaddr *);
+    struct sockaddr *, struct sockaddr *, struct sockaddr *, int *);
 
 void
 vroute_init(struct iked *env)
@@ -273,7 +273,7 @@ vroute_getroute(struct iked *env, struct imsg *imsg)
        }
 
        return (vroute_doroute(env, flags, addrs, rdomain, type,
-           dest, mask, addr));
+           dest, mask, addr, NULL));
 }
 
 int
@@ -288,6 +288,7 @@ vroute_getcloneroute(struct iked *env, struct imsg *imsg)
        uint8_t                  rdomain;
        int                      flags;
        int                      addrs;
+       int                      need_gw;
 
        ptr = (uint8_t *)imsg->data;
        left = IMSG_DATA_SIZE(imsg);
@@ -315,18 +316,21 @@ vroute_getcloneroute(struct iked *env, struct imsg *imsg)
        flags = RTF_UP | RTF_HOST | RTF_STATIC;
        if (vroute_doroute(env, flags, RTA_DST, rdomain, RTM_GET,
            (struct sockaddr *)&dest, (struct sockaddr *)&mask,
-           (struct sockaddr *)&addr))
+           (struct sockaddr *)&addr, &need_gw))
                return (-1);
 
+       if (need_gw)
+               flags |= RTF_GATEWAY;
+
        /* Set explicit route to peer with gateway addr*/
        addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
        return (vroute_doroute(env, flags, addrs, rdomain, RTM_ADD,
-           dst, (struct sockaddr *)&mask, (struct sockaddr *)&addr));
+           dst, (struct sockaddr *)&mask, (struct sockaddr *)&addr, NULL));
 }
 
 int
 vroute_doroute(struct iked *env, int flags, int addrs, int rdomain, uint8_t type,
-    struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr)
+    struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr, int *need_gw)
 {
        struct vroute_msg        m_rtmsg;
        struct iovec             iov[7];
@@ -399,7 +403,7 @@ vroute_doroute(struct iked *env, int flags, int addrs, int rdomain, uint8_t type
                if ((type == RTM_ADD && errno != EEXIST) ||
                    (type == RTM_DELETE && errno != ESRCH)) {
                        log_warn("%s: write %d", __func__, rtm.rtm_errno);
-                       return (-1);
+                       return (0);
                }
        }
 
@@ -408,7 +412,7 @@ vroute_doroute(struct iked *env, int flags, int addrs, int rdomain, uint8_t type
                        len = read(ivr->ivr_rtsock, &m_rtmsg, sizeof(m_rtmsg));
                } while(len > 0 && (rtm.rtm_version != RTM_VERSION ||
                    rtm.rtm_seq != ivr->ivr_rtseq || rtm.rtm_pid != ivr->ivr_pid));
-               return (vroute_process(env, len, &m_rtmsg, dest, mask, addr));
+               return (vroute_process(env, len, &m_rtmsg, dest, mask, addr, need_gw));
        }
 #undef rtm
 
@@ -417,7 +421,7 @@ vroute_doroute(struct iked *env, int flags, int addrs, int rdomain, uint8_t type
 
 int
 vroute_process(struct iked *env, int msglen, struct vroute_msg *m_rtmsg,
-    struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr)
+    struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr, int *need_gw)
 {
        struct sockaddr *sa;
        char *cp;
@@ -440,6 +444,7 @@ vroute_process(struct iked *env, int msglen, struct vroute_msg *m_rtmsg,
                return (-1);
        }
        cp = m_rtmsg->vm_space;
+       *need_gw = rtm.rtm_flags & RTF_GATEWAY;
        if(rtm.rtm_addrs) {
                for (i = 1; i; i <<= 1) {
                        if (i & rtm.rtm_addrs) {
@@ -508,7 +513,6 @@ vroute_doaddr(struct iked *env, char *ifname, struct sockaddr *addr,
                        memcpy(&req6.ifra_prefixmask, mask,
                            sizeof(req6.ifra_prefixmask));
 
-
                inet_ntop(af, &((struct sockaddr_in6 *)addr)->sin6_addr,
                    addr_buf, sizeof(addr_buf));
                inet_ntop(af, &((struct sockaddr_in6 *)mask)->sin6_addr,