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){