From 4d3679613179637df5ef999073aba2d187540a57 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Sun, 14 Jan 2018 14:30:38 +0100 Subject: [PATCH] KRT: Fix direct routes for BSD Old way to set direct routes is to use local IP as gateway, but that does not work properly on newer FreeBSDs. Now we use sockaddr_dl containing interface index as gateway. --- sysdep/bsd/krt-sock.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 0a52cfbd..e56dd616 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -186,6 +186,16 @@ struct ks_msg memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\ body += l;} +static inline void +sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa) +{ + uint len = OFFSETOF(struct sockaddr_dl, sdl_data); + memset(sa, 0, len); + sa->sdl_len = len; + sa->sdl_family = AF_LINK; + sa->sdl_index = ifa->index; +} + static int krt_send_route(struct krt_proto *p, int cmd, rte *e) { @@ -291,11 +301,8 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) { /* Fallback for all other valid cases */ -#ifdef RTF_CLONING - if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ - msg.rtm.rtm_flags |= RTF_CLONING; -#endif - +#if __OpenBSD__ + /* Keeping temporarily old code for OpenBSD */ struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6); if (!addr) @@ -304,7 +311,16 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) return -1; } - sockaddr_fill(&gate, af, addr->ip, i, 0); + /* Embed interface ID to link-local address */ + ip_addr gw = addr->ip; + if (ipa_is_link_local(gw)) + _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); + + sockaddr_fill(&gate, af, gw, i, 0); +#else + sockaddr_fill_dl(&gate, i); +#endif + msg.rtm.rtm_addrs |= RTA_GATEWAY; break; }