On Thu, Jan 09, 2020 at 02:45:46PM +0100, Claudio Jeker wrote:
> The RDE needs to know the local v4 and v6 address of a session so that
> nexthop self works. Until now the lookup for the other AF address was done
> in the RDE when the session got established. This diff moves this code
> over to the SE where it fits better. Especially this allows to remove the
> route pledge from the RDE.
> 
> This diff works for me but I would like more tests especially on link
> local IPv6 sessions (the KAME embedded scope curse haunts me again).

ping...

-- 
:wq Claudio

? obj
Index: bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.397
diff -u -p -r1.397 bgpd.h
--- bgpd.h      9 Jan 2020 11:55:25 -0000       1.397
+++ bgpd.h      9 Jan 2020 13:37:19 -0000
@@ -656,7 +656,8 @@ struct kif {
 };
 
 struct session_up {
-       struct bgpd_addr        local_addr;
+       struct bgpd_addr        local_v4_addr;
+       struct bgpd_addr        local_v6_addr;
        struct bgpd_addr        remote_addr;
        struct capabilities     capa;
        u_int32_t               remote_bgpid;
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.498
diff -u -p -r1.498 rde.c
--- rde.c       9 Jan 2020 13:31:52 -0000       1.498
+++ rde.c       9 Jan 2020 13:37:19 -0000
@@ -177,7 +177,7 @@ rde_main(int debug, int verbose)
            setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
                fatal("can't drop privileges");
 
-       if (pledge("stdio route recvfd", NULL) == -1)
+       if (pledge("stdio recvfd", NULL) == -1)
                fatal("pledge");
 
        signal(SIGTERM, rde_sighdlr);
Index: rde_peer.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_peer.c,v
retrieving revision 1.2
diff -u -p -r1.2 rde_peer.c
--- rde_peer.c  9 Jan 2020 13:31:52 -0000       1.2
+++ rde_peer.c  9 Jan 2020 13:37:19 -0000
@@ -17,9 +17,7 @@
  */
 #include <sys/types.h>
 #include <sys/queue.h>
-#include <sys/socket.h>
 
-#include <ifaddrs.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -306,102 +304,6 @@ rde_up_dump_done(void *ptr, u_int8_t aid
                fatal("%s: prefix_dump_new", __func__);
 }
 
-static int
-sa_cmp(struct bgpd_addr *a, struct sockaddr *b)
-{
-       struct sockaddr_in      *in_b;
-       struct sockaddr_in6     *in6_b;
-
-       if (aid2af(a->aid) != b->sa_family)
-               return (1);
-
-       switch (b->sa_family) {
-       case AF_INET:
-               in_b = (struct sockaddr_in *)b;
-               if (a->v4.s_addr != in_b->sin_addr.s_addr)
-                       return (1);
-               break;
-       case AF_INET6:
-               in6_b = (struct sockaddr_in6 *)b;
-#ifdef __KAME__
-               /* directly stolen from sbin/ifconfig/ifconfig.c */
-               if (IN6_IS_ADDR_LINKLOCAL(&in6_b->sin6_addr)) {
-                       in6_b->sin6_scope_id =
-                           ntohs(*(u_int16_t *)&in6_b->sin6_addr.s6_addr[2]);
-                       in6_b->sin6_addr.s6_addr[2] =
-                           in6_b->sin6_addr.s6_addr[3] = 0;
-               }
-#endif
-               if (bcmp(&a->v6, &in6_b->sin6_addr,
-                   sizeof(struct in6_addr)))
-                       return (1);
-               break;
-       default:
-               fatal("king bula sez: unknown address family");
-               /* NOTREACHED */
-       }
-
-       return (0);
-}
-
-/*
- * Figure out the local IP addresses most suitable for this session.
- * This looks up the local address of other address family based on
- * the address of the TCP session.
- */
-static int
-peer_localaddrs(struct rde_peer *peer, struct bgpd_addr *laddr)
-{
-       struct ifaddrs  *ifap, *ifa, *match;
-
-       if (getifaddrs(&ifap) == -1)
-               fatal("getifaddrs");
-
-       for (match = ifap; match != NULL; match = match->ifa_next)
-               if (sa_cmp(laddr, match->ifa_addr) == 0)
-                       break;
-
-       if (match == NULL) {
-               log_warnx("peer_localaddrs: local address not found");
-               return (-1);
-       }
-
-       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
-               if (ifa->ifa_addr->sa_family == AF_INET &&
-                   strcmp(ifa->ifa_name, match->ifa_name) == 0) {
-                       if (ifa->ifa_addr->sa_family ==
-                           match->ifa_addr->sa_family)
-                               ifa = match;
-                       sa2addr(ifa->ifa_addr, &peer->local_v4_addr, NULL);
-                       break;
-               }
-       }
-       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
-               if (ifa->ifa_addr->sa_family == AF_INET6 &&
-                   strcmp(ifa->ifa_name, match->ifa_name) == 0) {
-                       /*
-                        * only accept global scope addresses except explicitly
-                        * specified.
-                        */
-                       if (ifa->ifa_addr->sa_family ==
-                           match->ifa_addr->sa_family)
-                               ifa = match;
-                       else if (IN6_IS_ADDR_LINKLOCAL(
-                           &((struct sockaddr_in6 *)ifa->
-                           ifa_addr)->sin6_addr) ||
-                           IN6_IS_ADDR_SITELOCAL(
-                           &((struct sockaddr_in6 *)ifa->
-                           ifa_addr)->sin6_addr))
-                               continue;
-                       sa2addr(ifa->ifa_addr, &peer->local_v6_addr, NULL);
-                       break;
-               }
-       }
-
-       freeifaddrs(ifap);
-       return (0);
-}
-
 /*
  * Session got established, bring peer up, load RIBs do initial table dump.
  */
@@ -424,12 +326,10 @@ peer_up(struct rde_peer *peer, struct se
        }
        peer->remote_bgpid = ntohl(sup->remote_bgpid);
        peer->short_as = sup->short_as;
-       memcpy(&peer->remote_addr, &sup->remote_addr,
-           sizeof(peer->remote_addr));
+       peer->remote_addr = sup->remote_addr;
+       peer->local_v4_addr = sup->local_v4_addr;
+       peer->local_v6_addr = sup->local_v6_addr;
        memcpy(&peer->capa, &sup->capa, sizeof(peer->capa));
-
-       if (peer_localaddrs(peer, &sup->local_addr))
-               return (-1);
 
        peer->state = PEER_UP;
 
Index: session.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
retrieving revision 1.396
diff -u -p -r1.396 session.c
--- session.c   9 Jan 2020 11:51:18 -0000       1.396
+++ session.c   9 Jan 2020 13:37:19 -0000
@@ -33,6 +33,7 @@
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <ifaddrs.h>
 #include <poll.h>
 #include <pwd.h>
 #include <signal.h>
@@ -1189,6 +1190,69 @@ session_setup_socket(struct peer *p)
        return (0);
 }
 
+/* compare two sockaddrs by converting them into bgpd_addr */
+static int
+sa_cmp(struct sockaddr *a, struct sockaddr *b)
+{
+       struct bgpd_addr ba, bb;
+
+       sa2addr(a, &ba, NULL);
+       sa2addr(b, &bb, NULL);
+
+       return (memcmp(&ba, &bb, sizeof(ba)) == 0);
+}
+
+static void
+get_alternate_addr(struct sockaddr *sa, struct bgpd_addr *alt)
+{
+       struct ifaddrs  *ifap, *ifa, *match;
+
+       if (getifaddrs(&ifap) == -1)
+               fatal("getifaddrs");
+
+       for (match = ifap; match != NULL; match = match->ifa_next)
+               if (sa_cmp(sa, match->ifa_addr) == 0)
+                       break;
+
+       if (match == NULL) {
+               log_warnx("%s: local address not found", __func__);
+               return;
+       }
+
+       switch (sa->sa_family) {
+       case AF_INET6:
+               for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+                       if (ifa->ifa_addr->sa_family == AF_INET &&
+                           strcmp(ifa->ifa_name, match->ifa_name) == 0) {
+                               sa2addr(ifa->ifa_addr, alt, NULL);
+                               break;
+                       }
+               }
+               break;
+       case AF_INET:
+               for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+                       struct sockaddr_in6 *s =
+                           (struct sockaddr_in6 *)ifa->ifa_addr;
+                       if (ifa->ifa_addr->sa_family == AF_INET6 &&
+                           strcmp(ifa->ifa_name, match->ifa_name) == 0) {
+                               /* only accept global scope addresses */
+                               if (IN6_IS_ADDR_LINKLOCAL(&s->sin6_addr) ||
+                                   IN6_IS_ADDR_SITELOCAL(&s->sin6_addr))
+                                       continue;
+                               sa2addr(ifa->ifa_addr, alt, NULL);
+                               break;
+                       }
+               }
+               break;
+       default:
+               log_warnx("%s: unsupported address family %d", __func__,
+                   sa->sa_family);
+               break;
+       }
+
+       freeifaddrs(ifap);
+}
+
 void
 session_tcp_established(struct peer *peer)
 {
@@ -1199,6 +1263,7 @@ session_tcp_established(struct peer *pee
        if (getsockname(peer->fd, (struct sockaddr *)&ss, &len) == -1)
                log_warn("getsockname");
        sa2addr((struct sockaddr *)&ss, &peer->local, &peer->local_port);
+       get_alternate_addr((struct sockaddr *)&ss, &peer->local_alt);
        len = sizeof(ss);
        if (getpeername(peer->fd, (struct sockaddr *)&ss, &len) == -1)
                log_warn("getpeername");
@@ -3070,7 +3135,13 @@ session_up(struct peer *p)
            &p->conf, sizeof(p->conf)) == -1)
                fatalx("imsg_compose error");
 
-       sup.local_addr = p->local;
+       if (p->local.aid == AID_INET) {
+               sup.local_v4_addr = p->local;
+               sup.local_v6_addr = p->local_alt;
+       } else {
+               sup.local_v6_addr = p->local;
+               sup.local_v4_addr = p->local_alt;
+       }
        sup.remote_addr = p->remote;
 
        sup.remote_bgpid = p->remote_bgpid;
Index: session.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.h,v
retrieving revision 1.142
diff -u -p -r1.142 session.h
--- session.h   9 Jan 2020 11:51:18 -0000       1.142
+++ session.h   9 Jan 2020 13:37:19 -0000
@@ -211,6 +211,7 @@ struct peer {
                u_int8_t                established;
        }                        auth;
        struct bgpd_addr         local;
+       struct bgpd_addr         local_alt;
        struct bgpd_addr         remote;
        struct peer_timer_head   timers;
        struct msgbuf            wbuf;
Index: util.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
retrieving revision 1.51
diff -u -p -r1.51 util.c
--- util.c      3 Jul 2019 03:24:02 -0000       1.51
+++ util.c      9 Jan 2020 13:37:19 -0000
@@ -75,6 +75,7 @@ log_in6addr(const struct in6_addr *addr)
        sa_in6.sin6_family = AF_INET6;
        memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr));
 
+#ifdef __KAME__
        /* XXX thanks, KAME, for this ugliness... adopted from route/show.c */
        if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) ||
            IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) {
@@ -83,6 +84,7 @@ log_in6addr(const struct in6_addr *addr)
                sa_in6.sin6_addr.s6_addr[2] = 0;
                sa_in6.sin6_addr.s6_addr[3] = 0;
        }
+#endif
 
        return (log_sockaddr((struct sockaddr *)&sa_in6, sizeof(sa_in6)));
 }
@@ -883,6 +885,23 @@ sa2addr(struct sockaddr *sa, struct bgpd
        case AF_INET6:
                addr->aid = AID_INET6;
                memcpy(&addr->v6, &sa_in6->sin6_addr, sizeof(addr->v6));
+#ifdef __KAME__
+               /*
+                * XXX thanks, KAME, for this ugliness...
+                * adopted from route/show.c
+                */
+               if (IN6_IS_ADDR_LINKLOCAL(&sa_in6->sin6_addr) ||
+                   IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6->sin6_addr)) {
+                       uint16_t tmp16;
+                       memcpy(&tmp16, &sa_in6->sin6_addr.s6_addr[2],
+                           sizeof(tmp16));
+                       if (tmp16 != 0) {
+                               sa_in6->sin6_scope_id = ntohs(tmp16);
+                               sa_in6->sin6_addr.s6_addr[2] = 0;
+                               sa_in6->sin6_addr.s6_addr[3] = 0;
+                       }
+               }
+#endif
                addr->scope_id = sa_in6->sin6_scope_id; /* I hate v6 */
                if (port)
                        *port = ntohs(sa_in6->sin6_port);

Reply via email to