diff --git a/ChangeLog.txt b/ChangeLog.txt index 8938ff7e..5bfb045c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -6,6 +6,7 @@ Broker: Closes #821. - Don't quit with an error if opening the log file isn't possible. Closes #821. +- Fix bridge topic remapping when using "" as the topic. Closes #1749. Client library: - Improved documentation around connect callback return codes. Close #1730. diff --git a/src/conf.c b/src/conf.c index 42614956..6ec461ed 100644 --- a/src/conf.c +++ b/src/conf.c @@ -653,7 +653,7 @@ int config__read(struct mosquitto_db *db, struct mosquitto__config *config, bool } /* Check plugins loaded to see if they have username/password checks enabled */ - for(j=0; jlisteners[i].security_options.auth_plugin_config_count; j++){ + for(j=0; jlisteners[i].security_options.auth_plugin_config_count; j++){ plugin = &config->listeners[i].security_options.auth_plugin_configs[j].plugin; if(plugin->version == 3 || plugin->version == 2){ @@ -685,7 +685,7 @@ int config__read(struct mosquitto_db *db, struct mosquitto__config *config, bool } /* Check plugins loaded to see if they have username/password checks enabled */ - for(j=0; jsecurity_options.auth_plugin_config_count; j++){ + for(j=0; jsecurity_options.auth_plugin_config_count; j++){ plugin = &config->security_options.auth_plugin_configs[j].plugin; if(plugin->version == 3 || plugin->version == 2){ @@ -759,6 +759,76 @@ int config__read(struct mosquitto_db *db, struct mosquitto__config *config, bool return MOSQ_ERR_SUCCESS; } + +static int config__create_bridge_remap_topic(const char *prefix, const char *topic, char **remap_topic) +{ + int len; + + if(prefix){ + if(topic){ + len = strlen(topic) + strlen(prefix)+1; + *remap_topic = mosquitto__malloc(len+1); + if(!(*remap_topic)){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); + return MOSQ_ERR_NOMEM; + } + snprintf(*remap_topic, len+1, "%s%s", prefix, topic); + (*remap_topic)[len] = '\0'; + }else{ + *remap_topic = mosquitto__strdup(prefix); + if(!(*remap_topic)){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); + return MOSQ_ERR_NOMEM; + } + } + }else{ + *remap_topic = mosquitto__strdup(topic); + if(!(*remap_topic)){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); + return MOSQ_ERR_NOMEM; + } + } + return MOSQ_ERR_SUCCESS; +} + + +static int config__create_bridge_prefix(char **prefix, const char *topic, const char *token, const char *direction) +{ + int len; + + if(topic){ + len = strlen(topic) + strlen(token) + 1; + }else{ + len = strlen(token) + 1; + } + *prefix = malloc(len); + if(*prefix == NULL){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); + return MOSQ_ERR_NOMEM; + } + + if(topic){ + /* Print prefix+pattern to check for validity */ + snprintf(*prefix, len, "%s%s", token, topic); + }else{ + snprintf(*prefix, len, "%s", token); + } + + if(mosquitto_sub_topic_check(*prefix) != MOSQ_ERR_SUCCESS){ + log__printf(NULL, MOSQ_LOG_ERR, + "Error: Invalid bridge topic %s prefix and pattern combination '%s'.", + direction, *prefix); + + return MOSQ_ERR_INVAL; + } + + /* Print just the prefix for storage */ + snprintf(*prefix, len, "%s", token); + + return MOSQ_ERR_SUCCESS; +} + + int config__read_file_core(struct mosquitto__config *config, bool reload, struct config_recurse *cr, int level, int *lineno, FILE *fptr, char **buf, int *buflen) { int rc; @@ -769,7 +839,6 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct char *tmp_char; struct mosquitto__bridge *cur_bridge = NULL; struct mosquitto__bridge_topic *cur_topic; - int len; #endif struct mosquitto__auth_plugin_config *cur_auth_plugin_config = NULL; @@ -2021,22 +2090,12 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic local prefix '%s'.", token); return MOSQ_ERR_INVAL; } - cur_topic->local_prefix = malloc(strlen(cur_topic->topic) + strlen(token) + 1); - if(cur_topic->local_prefix == NULL){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } - /* Print prefix+pattern to check for validity */ - snprintf(cur_topic->local_prefix, strlen(cur_topic->topic) + strlen(token)+1, - "%s%s", token, cur_topic->topic); - if(mosquitto_sub_topic_check(cur_topic->local_prefix) != MOSQ_ERR_SUCCESS){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic local prefix and pattern combination '%s'.", cur_topic->local_prefix); + + if(config__create_bridge_prefix(&cur_topic->local_prefix, + cur_topic->topic, token, "local")){ + return MOSQ_ERR_INVAL; } - - /* Print just the prefix for storage */ - snprintf(cur_topic->local_prefix, strlen(cur_topic->topic) + strlen(token)+1, - "%s", token); } token = strtok_r(NULL, " ", &saveptr); @@ -2048,24 +2107,11 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic remote prefix '%s'.", token); return MOSQ_ERR_INVAL; } - cur_topic->remote_prefix = malloc(strlen(cur_topic->topic) + strlen(token) + 1); - if(cur_topic == NULL){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } - /* Print prefix+pattern to check for validity */ - snprintf(cur_topic->remote_prefix, strlen(cur_topic->topic) + strlen(token)+1, - "%s%s", token, cur_topic->topic); - if(mosquitto_sub_topic_check(cur_topic->remote_prefix) != MOSQ_ERR_SUCCESS){ - log__printf(NULL, MOSQ_LOG_ERR, - "Error: Invalid bridge topic remote prefix and pattern combination '%s'.", - cur_topic->remote_prefix); + if(config__create_bridge_prefix(&cur_topic->remote_prefix, + cur_topic->topic, token, "remote")){ + return MOSQ_ERR_INVAL; } - - /* Print just the prefix for storage */ - snprintf(cur_topic->remote_prefix, strlen(cur_topic->topic) + strlen(token)+1, - "%s", token); } } } @@ -2077,54 +2123,16 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge remapping."); return MOSQ_ERR_INVAL; } - if(cur_topic->local_prefix){ - if(cur_topic->topic){ - len = strlen(cur_topic->topic) + strlen(cur_topic->local_prefix)+1; - cur_topic->local_topic = mosquitto__malloc(len+1); - if(!cur_topic->local_topic){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } - snprintf(cur_topic->local_topic, len+1, "%s%s", cur_topic->local_prefix, cur_topic->topic); - cur_topic->local_topic[len] = '\0'; - }else{ - cur_topic->local_topic = mosquitto__strdup(cur_topic->local_prefix); - if(!cur_topic->local_topic){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } - } - }else{ - cur_topic->local_topic = mosquitto__strdup(cur_topic->topic); - if(!cur_topic->local_topic){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } + if(config__create_bridge_remap_topic(cur_topic->local_prefix, + cur_topic->topic, &cur_topic->local_topic)){ + + return MOSQ_ERR_INVAL; } - if(cur_topic->remote_prefix){ - if(cur_topic->topic){ - len = strlen(cur_topic->topic) + strlen(cur_topic->remote_prefix)+1; - cur_topic->remote_topic = mosquitto__malloc(len+1); - if(!cur_topic->remote_topic){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } - snprintf(cur_topic->remote_topic, len, "%s%s", cur_topic->remote_prefix, cur_topic->topic); - cur_topic->remote_topic[len] = '\0'; - }else{ - cur_topic->remote_topic = mosquitto__strdup(cur_topic->remote_prefix); - if(!cur_topic->remote_topic){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } - } - }else{ - cur_topic->remote_topic = mosquitto__strdup(cur_topic->topic); - if(!cur_topic->remote_topic){ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); - return MOSQ_ERR_NOMEM; - } + if(config__create_bridge_remap_topic(cur_topic->remote_prefix, + cur_topic->topic, &cur_topic->remote_topic)){ + + return MOSQ_ERR_INVAL; } #else log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");