Skip to content

Commit

Permalink
Allow binding a listener to a specific network interface
Browse files Browse the repository at this point in the history
Signed-off-by: Steven Lawrance <[email protected]>
  • Loading branch information
stlawrance authored and ralight committed Feb 27, 2019
1 parent b2c0c3d commit 208c3d3
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 0 deletions.
10 changes: 10 additions & 0 deletions man/mosquitto.conf.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,16 @@
<para>Not reloaded on reload signal.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>bind_interface</option> <replaceable>device</replaceable></term>
<listitem>
<para>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.</para>
<para>Not reloaded on reload signal.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>http_dir</option> <replaceable>directory</replaceable></term>
<listitem>
Expand Down
5 changes: 5 additions & 0 deletions mosquitto.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 9 additions & 0 deletions src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ void config__cleanup(struct mosquitto__config *config)
if(config->listeners){
for(i=0; i<config->listener_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);
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/mosquitto_broker_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 18 additions & 0 deletions src/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and the Eclipse Distribution License is available at
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <net/if.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 208c3d3

Please sign in to comment.