From b07e0c08bffbda8428a869e4ee9eb145efd7a544 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 2 Aug 2018 13:01:02 +0100 Subject: [PATCH] Fix IPv6 addresses not being able to be used as bridge addresses. Closes #886. Signed-off-by: Roger A. Light --- ChangeLog.txt | 2 ++ man/mosquitto.conf.5.xml | 2 ++ mosquitto.conf | 10 +++++++++- src/conf.c | 43 ++++++++++++++++++++++++---------------- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 5225bf7f..d1edaccd 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,8 @@ Broker: - Use AF_UNSPEC etc. instead of PF_UNSPEC to comply with POSIX. Closes #863. - Remove use of AI_ADDRCONFIG, which means the broker can be used on systems where only the loopback interface is defined. Closes #869, Closes #901. +- Fix IPv6 addresses not being able to be used as bridge addresses. + Closes #886. 1.5 - 20180502 diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml index 9347cfc5..3d171e99 100644 --- a/man/mosquitto.conf.5.xml +++ b/man/mosquitto.conf.5.xml @@ -1030,6 +1030,8 @@ bridge to connect to. This must be given for each bridge connection. If the port is not specified, the default of 1883 is used. + If you use an IPv6 address, then the port is not + optional. Multiple host addresses can be specified on the address config. See the option for more details on the behaviour of bridges diff --git a/mosquitto.conf b/mosquitto.conf index 93f66f3d..96450050 100644 --- a/mosquitto.conf +++ b/mosquitto.conf @@ -658,21 +658,29 @@ # Create a new bridge using the "connection" option as described below. Set # options for the bridges using the remaining parameters. You must specify the # address and at least one topic to subscribe to. +# # Each connection must have a unique name. +# # The address line may have multiple host address and ports specified. See # below in the round_robin description for more details on bridge behaviour if -# multiple addresses are used. +# multiple addresses are used. Note that if you use an IPv6 address, then you +# are required to specify a port. +# # The direction that the topic will be shared can be chosen by # specifying out, in or both, where the default value is out. # The QoS level of the bridged communication can be specified with the next # topic option. The default QoS level is 0, to change the QoS the topic # direction must also be given. +# # The local and remote prefix options allow a topic to be remapped when it is # bridged to/from the remote broker. This provides the ability to place a topic # tree in an appropriate location. +# # For more details see the mosquitto.conf man page. +# # Multiple topics can be specified per connection, but be careful # not to create any loops. +# # If you are using bridges with cleansession set to false (the default), then # you may get unexpected behaviour from incoming topics if you change what # topics you are subscribing to. This is because the remote broker keeps the diff --git a/src/conf.c b/src/conf.c index 06513348..721207d5 100644 --- a/src/conf.c +++ b/src/conf.c @@ -714,6 +714,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct int tmp_int; char *saveptr = NULL; #ifdef WITH_BRIDGE + char *tmp_char; struct mosquitto__bridge *cur_bridge = NULL; struct mosquitto__bridge_topic *cur_topic; #endif @@ -732,10 +733,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct #endif int len; struct mosquitto__listener *cur_listener = &config->default_listener; -#ifdef WITH_BRIDGE - char *address; int i; -#endif int lineno_ext; struct mosquitto__security_options *cur_security_options = NULL; @@ -773,22 +771,33 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct cur_bridge->addresses[cur_bridge->address_count-1].address = token; } for(i=0; iaddress_count; i++){ - address = strtok_r(cur_bridge->addresses[i].address, ":", &saveptr); - if(address){ - token = strtok_r(NULL, ":", &saveptr); - if(token){ - tmp_int = atoi(token); - if(tmp_int < 1 || tmp_int > 65535){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port value (%d).", tmp_int); - return MOSQ_ERR_INVAL; - } - cur_bridge->addresses[i].port = tmp_int; - }else{ - cur_bridge->addresses[i].port = 1883; + /* cur_bridge->addresses[i].address is now + * "address[:port]". If address is an IPv6 address, + * then port is required. We must check for the : + * backwards. */ + tmp_char = strrchr(cur_bridge->addresses[i].address, ':'); + if(tmp_char){ + /* Remove ':', so cur_bridge->addresses[i].address + * now just looks like the address. */ + tmp_char[0] = '\0'; + + /* The remainder of the string */ + tmp_int = atoi(&tmp_char[1]); + if(tmp_int < 1 || tmp_int > 65535){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port value (%d).", tmp_int); + return MOSQ_ERR_INVAL; } - cur_bridge->addresses[i].address = mosquitto__strdup(address); - conf__attempt_resolve(address, "bridge address", MOSQ_LOG_WARNING, "Warning"); + cur_bridge->addresses[i].port = tmp_int; + }else{ + cur_bridge->addresses[i].port = 1883; } + /* This looks a bit weird, but isn't. Before this + * call, cur_bridge->addresses[i].address points + * to the tokenised part of the line, it will be + * reused in a future parse of a config line so we + * must duplicate it. */ + cur_bridge->addresses[i].address = mosquitto__strdup(cur_bridge->addresses[i].address); + conf__attempt_resolve(cur_bridge->addresses[i].address, "bridge address", MOSQ_LOG_WARNING, "Warning"); } if(cur_bridge->address_count == 0){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty address value in configuration.");