From 11631d8d9285db12a7fd8fac682737edf10de251 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 10 Jun 2014 23:30:15 +0100 Subject: [PATCH] Add local_clientid for bridges. --- ChangeLog.txt | 15 +++++++++++++-- lib/send_client_mosq.c | 19 +++++++++++++++---- man/mosquitto.conf.5.xml | 10 ++++++++++ mosquitto.conf | 11 ++++++++--- src/bridge.c | 28 +++++++++++++++------------- src/conf.c | 25 +++++++++++++++++++++++++ src/mosquitto_broker.h | 1 + 7 files changed, 87 insertions(+), 22 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index c4cac71d..c1b957da 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,9 +1,20 @@ 1.4 - xxxxxxxx ============== +Important changes: +- Bridge behaviour on the local broker has changed due to the introduction of + the local_* options. This may affect you if you are using authentication + and/or ACLs with bridges. +- The default TLS behaviour has changed to accept all of TLS v1.2, v1.1 and + v1.0, rather than only only one version of the protocol. It is still + possible to restrict a listener to a single version of TLS. +- The Python client has been removed now that the Eclipse Paho Python client + has had a release. + + Broker: -- Add local_username, local_password for bridge connections to authenticate to - the local broker. +- Add local_clientid, local_username, local_password for bridge connections to + authenticate to the local broker. - Default TLS mode now accepts TLS v1.2, v1.1 and v1.0. - Support for ECDHE-ECDSA family ciphers. - Fix bug #1324411, which could have had unexpected consequences for delayed diff --git a/lib/send_client_mosq.c b/lib/send_client_mosq.c index 5c883c99..35cac447 100644 --- a/lib/send_client_mosq.c +++ b/lib/send_client_mosq.c @@ -37,14 +37,25 @@ int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool cle uint8_t byte; int rc; uint8_t version = PROTOCOL_VERSION_v31; + char *clientid; assert(mosq); assert(mosq->id); +#if defined(WITH_BROKER) && defined(WITH_BRIDGE) + if(mosq->bridge){ + clientid = mosq->bridge->clientid; + }else{ + clientid = mosq->id; + } +#else + clientid = mosq->id; +#endif + packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); if(!packet) return MOSQ_ERR_NOMEM; - payloadlen = 2+strlen(mosq->id); + payloadlen = 2+strlen(clientid); if(mosq->will){ will = 1; assert(mosq->will->topic); @@ -89,7 +100,7 @@ int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool cle _mosquitto_write_uint16(packet, keepalive); /* Payload */ - _mosquitto_write_string(packet, mosq->id, strlen(mosq->id)); + _mosquitto_write_string(packet, clientid, strlen(clientid)); if(will){ _mosquitto_write_string(packet, mosq->will->topic, strlen(mosq->will->topic)); _mosquitto_write_string(packet, (const char *)mosq->will->payload, mosq->will->payloadlen); @@ -104,10 +115,10 @@ int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool cle mosq->keepalive = keepalive; #ifdef WITH_BROKER # ifdef WITH_BRIDGE - _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", mosq->id); + _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", clientid); # endif #else - _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", mosq->id); + _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", clientid); #endif return _mosquitto_packet_queue(mosq, packet); } diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml index d362b95f..f7b711ab 100644 --- a/man/mosquitto.conf.5.xml +++ b/man/mosquitto.conf.5.xml @@ -918,6 +918,16 @@ to 60 seconds. + + password + + Set the clientid to use on the local broker. If not + defined, this defaults to + . If you are + bridging a broker to itself, it is important that + local_clientid and clientid do not match. + + password diff --git a/mosquitto.conf b/mosquitto.conf index 9020ab16..84f5f57b 100644 --- a/mosquitto.conf +++ b/mosquitto.conf @@ -603,11 +603,16 @@ # remain connected until it fails #round_robin false -# Set the client id for this bridge connection. If not defined, -# this defaults to 'name.hostname' where name is the connection -# name and hostname is the hostname of this computer. +# Set the client id to use on the remote end of this bridge connection. If not +# defined, this defaults to 'name.hostname' where name is the connection name +# and hostname is the hostname of this computer. #clientid +# Set the clientid to use on the local broker. If not defined, this defaults to +# 'local.'. If you are bridging a broker to itself, it is important +# that local_clientid and clientid do not match. +#local_clientid + # Set the clean session variable for this bridge. # When set to true, when the bridge disconnects for any reason, all # messages and subscriptions will be cleaned up on the remote diff --git a/src/bridge.c b/src/bridge.c index 6209bf46..9ab6ebc1 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -50,14 +50,12 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) struct mosquitto **tmp_contexts; char hostname[256]; int len; - char *id; + char *id, *local_id; assert(db); assert(bridge); - if(bridge->clientid){ - id = _mosquitto_strdup(bridge->clientid); - }else{ + if(!bridge->clientid){ if(!gethostname(hostname, 256)){ len = strlen(hostname) + strlen(bridge->name) + 2; id = _mosquitto_malloc(len); @@ -68,16 +66,25 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) }else{ return 1; } + bridge->clientid = id; } - if(!id){ - return MOSQ_ERR_NOMEM; + if(bridge->local_clientid){ + local_id = bridge->local_clientid; + }else{ + len = strlen(bridge->clientid) + strlen("local.") + 2; + local_id = _mosquitto_malloc(len); + if(!local_id){ + return MOSQ_ERR_NOMEM; + } + snprintf(local_id, len, "local.%s", bridge->clientid); + bridge->local_clientid = local_id; } /* Search for existing id (possible from persistent db) and also look for a * gap in the db->contexts[] array in case the id isn't found. */ for(i=0; icontext_count; i++){ if(db->contexts[i]){ - if(!strcmp(db->contexts[i]->id, id)){ + if(!strcmp(db->contexts[i]->id, local_id)){ new_context = db->contexts[i]; break; } @@ -90,7 +97,6 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) /* id wasn't found, so generate a new context */ new_context = mqtt3_context_init(-1); if(!new_context){ - _mosquitto_free(id); return MOSQ_ERR_NOMEM; } if(null_index == -1){ @@ -101,17 +107,13 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) db->contexts = tmp_contexts; db->contexts[db->context_count-1] = new_context; }else{ - _mosquitto_free(id); _mosquitto_free(new_context); return MOSQ_ERR_NOMEM; } }else{ db->contexts[null_index] = new_context; } - new_context->id = id; - }else{ - /* id was found, so context->id already in memory. */ - _mosquitto_free(id); + new_context->id = local_id; } new_context->bridge = bridge; new_context->is_bridge = true; diff --git a/src/conf.c b/src/conf.c index 7a1db2fb..9c713d96 100644 --- a/src/conf.c +++ b/src/conf.c @@ -251,6 +251,7 @@ void mqtt3_config_cleanup(struct mqtt3_config *config) if(config->bridges[i].clientid) _mosquitto_free(config->bridges[i].clientid); if(config->bridges[i].username) _mosquitto_free(config->bridges[i].username); if(config->bridges[i].password) _mosquitto_free(config->bridges[i].password); + if(config->bridges[i].local_clientid) _mosquitto_free(config->bridges[i].local_clientid); if(config->bridges[i].local_username) _mosquitto_free(config->bridges[i].local_username); if(config->bridges[i].local_password) _mosquitto_free(config->bridges[i].local_password); if(config->bridges[i].topics){ @@ -1140,6 +1141,30 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty listener value in configuration."); return MOSQ_ERR_INVAL; } + }else if(!strcmp(token, "local_clientid")){ +#ifdef WITH_BRIDGE + if(reload) continue; // FIXME + if(!cur_bridge){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); + return MOSQ_ERR_INVAL; + } + token = strtok_r(NULL, " ", &saveptr); + if(token){ + if(cur_bridge->local_clientid){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate local_clientid value in bridge configuration."); + return MOSQ_ERR_INVAL; + } + cur_bridge->local_clientid = _mosquitto_strdup(token); + if(!cur_bridge->local_clientid){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); + return MOSQ_ERR_NOMEM; + } + }else{ + cur_bridge->local_clientid = NULL; + } +#else + _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); +#endif }else if(!strcmp(token, "local_password")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME diff --git a/src/mosquitto_broker.h b/src/mosquitto_broker.h index a0312c4f..6a2cb305 100644 --- a/src/mosquitto_broker.h +++ b/src/mosquitto_broker.h @@ -272,6 +272,7 @@ struct _mqtt3_bridge{ time_t restart_t; char *username; char *password; + char *local_clientid; char *local_username; char *local_password; bool notifications;