From a227d6d66d645186b68617d8df53a8652279e835 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 10 May 2020 13:11:23 +0100 Subject: [PATCH] tun: Bring up interface before setting IPv6 route on Linux Linux kernel commit 955ec4c ("net/ipv6: Do not allow route add with a device that is down") rejects attempts to install an IPv6 route on an interface that is not yet up. This commit is first included in kernel 4.16. The current code in os_set_ipv6_addr brings up the interface only after attempting to install the IPv6 route. On kernel 4.16 or later, this fails with the error "Error setting route to remote IPv6: Network is down". Fix by switching the order of code blocks to bring the interface up before attempting to configure the route. Resolves: #301 Signed-off-by: Michael Brown --- src/tun.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tun.c b/src/tun.c index 3cc571b0..2da47226 100644 --- a/src/tun.c +++ b/src/tun.c @@ -118,6 +118,21 @@ int os_set_ipv6_addr(main_server_st * s, struct proc_st *proc) goto cleanup; } + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_addr.sa_family = AF_INET6; + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); + + ret = ioctl(fd, SIOCSIFFLAGS, &ifr); + if (ret != 0) { + e = errno; + mslog(s, NULL, LOG_ERR, + "%s: Could not bring up IPv6 interface: %s\n", + proc->tun_lease.name, strerror(e)); + ret = -1; + goto cleanup; + } + /* route to our remote address */ memset(&rt6, 0, sizeof(rt6)); memcpy(&rt6.rtmsg_dst, SA_IN6_P(&proc->ipv6->rip), @@ -138,21 +153,6 @@ int os_set_ipv6_addr(main_server_st * s, struct proc_st *proc) goto cleanup; } - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_addr.sa_family = AF_INET6; - ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); - - ret = ioctl(fd, SIOCSIFFLAGS, &ifr); - if (ret != 0) { - e = errno; - mslog(s, NULL, LOG_ERR, - "%s: Could not bring up IPv6 interface: %s\n", - proc->tun_lease.name, strerror(e)); - ret = -1; - goto cleanup; - } - ret = 0; cleanup: close(fd);