Fix some error handling related to the bind_interface option.

This commit is contained in:
Roger A. Light 2022-12-02 14:31:40 +00:00
parent c06599fab2
commit 8285a57bb9
3 changed files with 52 additions and 37 deletions

View File

@ -2,6 +2,7 @@ Broker:
- Fix $SYS messages being expired after 60 seconds and hence unchanged values - Fix $SYS messages being expired after 60 seconds and hence unchanged values
disappearing. disappearing.
- Fix some retained topic memory not being cleared immediately after used. - 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 2.0.15 - 2022-08-16
=================== ===================

View File

@ -622,6 +622,8 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr
* matching interface in the later bind(). * matching interface in the later bind().
*/ */
struct ifaddrs *ifaddr, *ifa; struct ifaddrs *ifaddr, *ifa;
bool have_interface = false;
if(getifaddrs(&ifaddr) < 0){ if(getifaddrs(&ifaddr) < 0){
net__print_error(MOSQ_LOG_ERR, "Error: %s"); net__print_error(MOSQ_LOG_ERR, "Error: %s");
return MOSQ_ERR_ERRNO; return MOSQ_ERR_ERRNO;
@ -632,49 +634,56 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr
continue; continue;
} }
if(!strcasecmp(listener->bind_interface, ifa->ifa_name) if(!strcasecmp(listener->bind_interface, ifa->ifa_name)){
&& ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){ have_interface = true;
if(rp->ai_addr->sa_family == AF_INET){ if(ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){
if(listener->host && if(rp->ai_addr->sa_family == AF_INET){
memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, if(listener->host &&
&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
sizeof(struct in_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).", log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface address for %s does not match specified listener address (%s).",
listener->bind_interface, listener->host); listener->bind_interface, listener->host);
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
}else{ }else{
memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
sizeof(struct in_addr)); sizeof(struct in_addr));
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
}else if(rp->ai_addr->sa_family == AF_INET6){ }else if(rp->ai_addr->sa_family == AF_INET6){
if(listener->host && if(listener->host &&
memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
sizeof(struct in6_addr))){ sizeof(struct in6_addr))){
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).", log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface address for %s does not match specified listener address (%s).",
listener->bind_interface, listener->host); listener->bind_interface, listener->host);
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
}else{ }else{
memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
}
} }
} }
} }
} }
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.", if(have_interface){
listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.",
return MOSQ_ERR_NOT_FOUND; 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 #endif
@ -756,10 +765,15 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)
if(listener->bind_interface){ if(listener->bind_interface){
/* It might be possible that an interface does not support all relevant sa_families. /* It might be possible that an interface does not support all relevant sa_families.
* We should successfully find at least one. */ * We should successfully find at least one. */
if(net__bind_interface(listener, rp)){ rc = net__bind_interface(listener, rp);
if(rc){
COMPAT_CLOSE(sock); COMPAT_CLOSE(sock);
listener->sock_count--; listener->sock_count--;
continue; if(rc == MOSQ_ERR_NOT_FOUND || rc == MOSQ_ERR_INVAL){
return rc;
}else{
continue;
}
} }
interface_bound = true; interface_bound = true;
} }

View File

@ -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) print("FAIL: unable to start broker: %s" % errs)
raise IOError raise IOError
else: else:
return None return broker
def start_client(filename, cmd, env, port=1888): def start_client(filename, cmd, env, port=1888):
if cmd is None: if cmd is None: