From 64720408e45d283eaaa5091957d949fab43087ef Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 27 Jul 2019 00:44:06 +0200 Subject: [PATCH] Close connections if the local address is no longer valid. When we detect that there are changes on the network interfaces, check for each active connection whether the local side of the connection has an address that exists on at least one network interface. If not, then communication via that connection is not possible. Instead of waiting for a timeout, immediately terminate those connections. --- configure.ac | 4 ++-- src/have.h | 4 ++++ src/net.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 48694a70..4028613f 100644 --- a/configure.ac +++ b/configure.ac @@ -118,7 +118,7 @@ AM_CONDITIONAL(INSTALL_TESTS, test "$install_tests" = true) dnl Checks for header files. dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies. -AC_CHECK_HEADERS([syslog.h sys/file.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h curses.h]) +AC_CHECK_HEADERS([syslog.h sys/file.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h curses.h ifaddrs.h]) dnl Checks for typedefs, structures, and compiler characteristics. MeshLink_ATTRIBUTE(__malloc__) @@ -134,7 +134,7 @@ AC_CHECK_TYPES([struct sockaddr_storage], ,AC_MSG_ERROR([System must support str dnl Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([asprintf fchmod fork gettimeofday random select setns strdup usleep], +AC_CHECK_FUNCS([asprintf fchmod fork gettimeofday random select setns strdup usleep getifaddrs], [], [], [#include "$srcdir/src/have.h"] ) diff --git a/src/have.h b/src/have.h index 536226d5..d4c62f48 100644 --- a/src/have.h +++ b/src/have.h @@ -115,6 +115,10 @@ #include #endif +#ifdef HAVE_IFADDRS_H +#include +#endif + #ifdef HAVE_MINGW #define SLASH "\\" #else diff --git a/src/net.c b/src/net.c index a42d933b..ddfd2cf0 100644 --- a/src/net.c +++ b/src/net.c @@ -625,13 +625,61 @@ void retry(meshlink_handle_t *mesh) { }); } - /* Check for outgoing connections that are in progress, and reset their ping timers */ +#ifdef HAVE_IFADDRS_H + struct ifaddrs *ifa = NULL; + getifaddrs(&ifa); +#endif + + /* For active connections, check if their addresses are still valid. + * If yes, reset their ping timers, otherwise terminate them. */ for list_each(connection_t, c, mesh->connections) { - if(c->outgoing && !c->node) { + if(!c->status.active) { + continue; + } + + if(!c->status.pinged) { c->last_ping_time = 0; } + +#ifdef HAVE_IFADDRS_H + + if(!ifa) { + continue; + } + + sockaddr_t sa; + socklen_t salen = sizeof(sa); + + if(getsockname(c->socket, &sa.sa, &salen)) { + continue; + } + + bool found = false; + + for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) { + if(ifap->ifa_addr && !sockaddrcmp_noport(&sa, (sockaddr_t *)ifap->ifa_addr)) { + found = true; + break; + } + + } + + if(!found) { + logger(mesh, MESHLINK_DEBUG, "Local address for connection to %s no longer valid, terminating", c->name); + terminate_connection(mesh, c, c->status.active); + } + +#endif + } + +#ifdef HAVE_IFADDRS_H + + if(ifa) { + freeifaddrs(ifa); } +#endif + /* Kick the ping timeout handler */ timeout_set(&mesh->loop, &mesh->pingtimer, &(struct timeval) { 0, 0 -- 2.39.5