diff --git a/ChangeLog.txt b/ChangeLog.txt
index d6942a0d..cfe54fc2 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,6 +1,12 @@
1.5.5 - 201812xx
================
+Broker:
+- Add `socket_domain` option to allow listeners to disable IPv6 support.
+ This is required to work around a problem in libwebsockets that means
+ sockets only listen on IPv6 by default if IPv6 support is compiled in.
+ Closes #1004.
+
Client:
- Always print leading zeros in mosquitto_sub when output format is hex.
Closes #1066.
diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml
index a6bf0c99..d5dcc50b 100644
--- a/man/mosquitto.conf.5.xml
+++ b/man/mosquitto.conf.5.xml
@@ -813,6 +813,27 @@
Not reloaded on reload signal.
+
+ [ ipv4 | ipv6 ]
+
+ By default, a listener will attempt to listen on
+ all supported IP protocol versions. If you do not
+ have an IPv4 or IPv6 interface you may wish to
+ disable support for either of those protocol
+ versions. In particular, note that due to the
+ limitations of the websockets library, it will only
+ ever attempt to open IPv6 sockets if IPv6 support
+ is compiled in, and so will fail if IPv6 is not
+ available.
+ Set to to force the
+ listener to only use IPv4, or set to
+ to force the listener to only
+ use IPv6. If you want support for both IPv4 and
+ IPv6, then do not use the
+ option.
+ Not reloaded on reload signal.
+
+ [ true | false ]
diff --git a/src/conf.c b/src/conf.c
index 0b1d79cf..c6bd897c 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -446,6 +446,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
|| config->default_listener.max_connections != -1
|| config->default_listener.mount_point
|| config->default_listener.protocol != mp_mqtt
+ || config->default_listener.socket_domain
|| config->default_listener.security_options.password_file
|| config->default_listener.security_options.psk_file
|| config->default_listener.security_options.auth_plugin_config_count
@@ -476,6 +477,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
}
config->listeners[config->listener_count-1].max_connections = config->default_listener.max_connections;
config->listeners[config->listener_count-1].protocol = config->default_listener.protocol;
+ config->listeners[config->listener_count-1].socket_domain = config->default_listener.socket_domain;
config->listeners[config->listener_count-1].client_count = 0;
config->listeners[config->listener_count-1].socks = NULL;
config->listeners[config->listener_count-1].sock_count = 0;
@@ -1773,6 +1775,22 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
#endif
+ }else if(!strcmp(token, "socket_domain")){
+ if(reload) continue; // Listeners not valid for reloading.
+ token = strtok_r(NULL, " ", &saveptr);
+ if(token){
+ if(!strcmp(token, "ipv4")){
+ cur_listener->socket_domain = AF_INET;
+ }else if(!strcmp(token, "ipv6")){
+ cur_listener->socket_domain = AF_INET6;
+ }else{
+ log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid socket_domain value \"%s\" in configuration.", token);
+ return MOSQ_ERR_INVAL;
+ }
+ }else{
+ log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty socket_domain value in configuration.");
+ return MOSQ_ERR_INVAL;
+ }
}else if(!strcmp(token, "store_clean_interval")){
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: store_clean_interval is no longer needed.");
}else if(!strcmp(token, "sys_interval")){
diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h
index 67a2924c..bd6ad136 100644
--- a/src/mosquitto_broker_internal.h
+++ b/src/mosquitto_broker_internal.h
@@ -218,6 +218,7 @@ struct mosquitto__listener {
int sock_count;
int client_count;
enum mosquitto_protocol protocol;
+ int socket_domain;
bool use_username_as_clientid;
#ifdef WITH_TLS
char *cafile;
diff --git a/src/net.c b/src/net.c
index 08f2b824..21f5ec68 100644
--- a/src/net.c
+++ b/src/net.c
@@ -391,7 +391,11 @@ int net__socket_listen(struct mosquitto__listener *listener)
snprintf(service, 10, "%d", listener->port);
memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
+ if(listener->socket_domain){
+ hints.ai_family = listener->socket_domain;
+ }else{
+ hints.ai_family = AF_UNSPEC;
+ }
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
diff --git a/src/websockets.c b/src/websockets.c
index bf2804b8..a57330aa 100644
--- a/src/websockets.c
+++ b/src/websockets.c
@@ -729,6 +729,9 @@ struct libwebsocket_context *mosq_websockets_init(struct mosquitto__listener *li
#if LWS_LIBRARY_VERSION_MAJOR>1
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
#endif
+ if(listener->socket_domain == AF_INET){
+ info.options |= LWS_SERVER_OPTION_DISABLE_IPV6;
+ }
user = mosquitto__calloc(1, sizeof(struct libws_mqtt_hack));
if(!user){