diff --git a/ChangeLog.txt b/ChangeLog.txt index a9b46ee4..041ed9ac 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -2,6 +2,7 @@ Broker: - Fix $SYS messages being expired after 60 seconds and hence unchanged values disappearing. - Fix some retained topic memory not being cleared immediately after used. +- Fix error handling related to the `bind_interface` option. 2.0.15 - 2022-08-16 =================== diff --git a/src/net.c b/src/net.c index 80d2c8d6..b9a27685 100644 --- a/src/net.c +++ b/src/net.c @@ -622,6 +622,8 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr * matching interface in the later bind(). */ struct ifaddrs *ifaddr, *ifa; + bool have_interface = false; + if(getifaddrs(&ifaddr) < 0){ net__print_error(MOSQ_LOG_ERR, "Error: %s"); return MOSQ_ERR_ERRNO; @@ -632,49 +634,56 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr continue; } - if(!strcasecmp(listener->bind_interface, ifa->ifa_name) - && ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){ + if(!strcasecmp(listener->bind_interface, ifa->ifa_name)){ + have_interface = true; - if(rp->ai_addr->sa_family == AF_INET){ - if(listener->host && - memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, - &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, - sizeof(struct in_addr))){ + if(ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){ + if(rp->ai_addr->sa_family == AF_INET){ + if(listener->host && + memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, + &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, + sizeof(struct in_addr))){ - log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).", - listener->bind_interface, listener->host); - return MOSQ_ERR_INVAL; - }else{ - memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, - &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, - sizeof(struct in_addr)); + log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface address for %s does not match specified listener address (%s).", + listener->bind_interface, listener->host); + return MOSQ_ERR_INVAL; + }else{ + memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, + &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, + sizeof(struct in_addr)); - freeifaddrs(ifaddr); - return MOSQ_ERR_SUCCESS; - } - }else if(rp->ai_addr->sa_family == AF_INET6){ - if(listener->host && - memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, - &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, - sizeof(struct in6_addr))){ + freeifaddrs(ifaddr); + return MOSQ_ERR_SUCCESS; + } + }else if(rp->ai_addr->sa_family == AF_INET6){ + if(listener->host && + memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, + &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, + sizeof(struct in6_addr))){ - log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).", - listener->bind_interface, listener->host); - return MOSQ_ERR_INVAL; - }else{ - memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, - &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, - sizeof(struct in6_addr)); - freeifaddrs(ifaddr); - return MOSQ_ERR_SUCCESS; + log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface address for %s does not match specified listener address (%s).", + listener->bind_interface, listener->host); + return MOSQ_ERR_INVAL; + }else{ + memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, + &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, + sizeof(struct in6_addr)); + freeifaddrs(ifaddr); + return MOSQ_ERR_SUCCESS; + } } } } } freeifaddrs(ifaddr); - log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.", - listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); - return MOSQ_ERR_NOT_FOUND; + if(have_interface){ + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.", + listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); + return MOSQ_ERR_NOT_SUPPORTED; + }else{ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface %s does not exist.", listener->bind_interface); + return MOSQ_ERR_NOT_FOUND; + } } #endif @@ -756,10 +765,15 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener) if(listener->bind_interface){ /* It might be possible that an interface does not support all relevant sa_families. * We should successfully find at least one. */ - if(net__bind_interface(listener, rp)){ + rc = net__bind_interface(listener, rp); + if(rc){ COMPAT_CLOSE(sock); listener->sock_count--; - continue; + if(rc == MOSQ_ERR_NOT_FOUND || rc == MOSQ_ERR_INVAL){ + return rc; + }else{ + continue; + } } interface_bound = true; } diff --git a/test/mosq_test.py b/test/mosq_test.py index d9fe6970..98fd3ac9 100644 --- a/test/mosq_test.py +++ b/test/mosq_test.py @@ -70,7 +70,7 @@ def start_broker(filename, cmd=None, port=0, use_conf=False, expect_fail=False, print("FAIL: unable to start broker: %s" % errs) raise IOError else: - return None + return broker def start_client(filename, cmd, env, port=1888): if cmd is None: