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 <mbrown@fensystems.co.uk>
This commit is contained in:
Michael Brown
2020-05-10 13:11:23 +01:00
committed by Nikos Mavrogiannopoulos
parent 03b05526c3
commit a227d6d66d

View File

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