diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml
index c14aa907..a7a1069d 100644
--- a/man/mosquitto.conf.5.xml
+++ b/man/mosquitto.conf.5.xml
@@ -803,6 +803,16 @@
Not reloaded on reload signal.
+
+ device
+
+ Listen for incoming network connections only on
+ the specified interface. This is similar to the
+ preceding option but useful when an interface has
+ multiple addresses or the address may change.
+ Not reloaded on reload signal.
+
+
directory
diff --git a/mosquitto.conf b/mosquitto.conf
index 248417b7..5d1bef9e 100644
--- a/mosquitto.conf
+++ b/mosquitto.conf
@@ -207,6 +207,11 @@
# Port to use for the default listener.
#port 1883
+# Bind the listener to a specific interface. This is similar to
+# bind_address above but useful when an interface has multiple
+# addresses or the address may change. Only available on Linux.
+#bind_interface eth0
+
# The maximum number of client connections to allow. This is
# a per listener setting.
# Default is -1, which means unlimited connections.
diff --git a/src/conf.c b/src/conf.c
index d92dd2bb..ca8dd879 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -291,6 +291,7 @@ void config__cleanup(struct mosquitto__config *config)
if(config->listeners){
for(i=0; ilistener_count; i++){
mosquitto__free(config->listeners[i].host);
+ mosquitto__free(config->listeners[i].bind_interface);
mosquitto__free(config->listeners[i].mount_point);
mosquitto__free(config->listeners[i].socks);
mosquitto__free(config->listeners[i].security_options.auto_id_prefix);
@@ -915,6 +916,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__attempt_resolve(config->default_listener.host, "bind_address", MOSQ_LOG_ERR, "Error")){
return MOSQ_ERR_INVAL;
}
+ }else if(!strcmp(token, "bind_interface")){
+#ifdef SO_BINDTODEVICE
+ if(reload) continue; // Listeners not valid for reloading.
+ if(conf__parse_string(&token, "bind_interface", &cur_listener->bind_interface, saveptr)) return MOSQ_ERR_INVAL;
+#else
+ log__printf(NULL, MOSQ_LOG_ERR, "Error: bind_interface specified but socket option not available.");
+ return MOSQ_ERR_INVAL;
+#endif
}else if(!strcmp(token, "bridge_attempt_unsubscribe")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h
index 22d84c1b..24f194fa 100644
--- a/src/mosquitto_broker_internal.h
+++ b/src/mosquitto_broker_internal.h
@@ -212,6 +212,7 @@ struct mosquitto__listener {
int fd;
uint16_t port;
char *host;
+ char *bind_interface;
int max_connections;
char *mount_point;
mosq_sock_t *socks;
diff --git a/src/net.c b/src/net.c
index ec71fd77..63516ab7 100644
--- a/src/net.c
+++ b/src/net.c
@@ -22,6 +22,7 @@ Contributors:
#include
#include
#include
+#include
#else
#include
#include
@@ -395,6 +396,9 @@ int net__socket_listen(struct mosquitto__listener *listener)
X509_LOOKUP *lookup;
ENGINE *engine = NULL;
#endif
+#ifdef SO_BINDTODEVICE
+ struct ifreq ifr;
+#endif
if(!listener) return MOSQ_ERR_INVAL;
@@ -446,6 +450,20 @@ int net__socket_listen(struct mosquitto__listener *listener)
return 1;
}
+#ifdef SO_BINDTODEVICE
+ if(listener->bind_interface){
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, listener->bind_interface, sizeof(ifr.ifr_name)-1);
+ ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
+ log__printf(NULL, MOSQ_LOG_INFO, "Binding listener to interface \"%s\".", ifr.ifr_name);
+ if(setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
+ net__print_error(MOSQ_LOG_ERR, "Error: %s");
+ COMPAT_CLOSE(sock);
+ return 1;
+ }
+ }
+#endif
+
if(bind(sock, rp->ai_addr, rp->ai_addrlen) == -1){
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);