From 03d4b8c27029da25dd350df3ca86dd7a6f1393fe Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Thu, 8 Sep 2016 11:24:29 +0000 Subject: [PATCH 01/46] websockets: fix compatibility with older lws versions (#260) In 1.3, 1.4 and 1.5, the function was "libwebsockets_get_protocol" not "libwebsocket_get_protocol" While the #define name doesn't matter on newer libwebsockets, where it redirects to lws_get_protocol, the naming is critical for older versions. Fixes: 477cd3e39911 (Fix missing context->listener for websocket client) Signed-off-by: Karl Palsson --- src/mosquitto_broker.h | 2 +- src/websockets.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mosquitto_broker.h b/src/mosquitto_broker.h index 7d29e927a5..bd6a0ef7da 100644 --- a/src/mosquitto_broker.h +++ b/src/mosquitto_broker.h @@ -31,7 +31,7 @@ and the Eclipse Distribution License is available at # define libwebsocket_write(A, B, C, D) lws_write((A), (B), (C), (D)) # define libwebsocket_get_socket_fd(A) lws_get_socket_fd((A)) # define libwebsockets_return_http_status(A, B, C, D) lws_return_http_status((B), (C), (D)) -# define libwebsocket_get_protocol(A) lws_get_protocol((A)) +# define libwebsockets_get_protocol(A) lws_get_protocol((A)) # define libwebsocket_context lws_context # define libwebsocket_protocols lws_protocols diff --git a/src/websockets.c b/src/websockets.c index c16bde7a9b..231cb72b8d 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -182,7 +182,7 @@ static int callback_mqtt(struct libwebsocket_context *context, case LWS_CALLBACK_ESTABLISHED: mosq = mqtt3_context_init(db, WEBSOCKET_CLIENT); if(mosq){ - p = libwebsocket_get_protocol(wsi); + p = libwebsockets_get_protocol(wsi); for (i=0; iconfig->listener_count; i++){ if (db->config->listeners[i].protocol == mp_websockets) { for (j=0; db->config->listeners[i].ws_protocol[j].name; j++){ From 762126064c1b1240e976742dfb79ff3a71925b98 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 20 Sep 2016 23:26:14 +0100 Subject: [PATCH 02/46] [259] Fix crash when "lazy" type bridge attempts to reconnect. Thanks to hakofugu41. Bug: https://github.com/eclipse/mosquitto/issues/259 --- ChangeLog.txt | 3 +++ src/loop.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index bec39d776e..0899f8a74e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,6 @@ +Broker: +- Fix crash when "lazy" type bridge attempts to reconnect. Closes #259. + 1.4.10 - 20160816 ================= diff --git a/src/loop.c b/src/loop.c index 4470323d56..07e02c5b39 100644 --- a/src/loop.c +++ b/src/loop.c @@ -246,7 +246,16 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li }else{ if(context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect){ rc = mqtt3_bridge_connect(db, context); - if(rc){ + if(rc == MOSQ_ERR_SUCCESS){ + pollfds[pollfd_index].fd = context->sock; + pollfds[pollfd_index].events = POLLIN; + pollfds[pollfd_index].revents = 0; + if(context->current_out_packet){ + pollfds[pollfd_index].events |= POLLOUT; + } + context->pollfd_index = pollfd_index; + pollfd_index++; + }else{ context->bridge->cur_address++; if(context->bridge->cur_address == context->bridge->address_count){ context->bridge->cur_address = 0; From f272e2e047b3c06a1471c3e1270b046e6c72d819 Mon Sep 17 00:00:00 2001 From: tucic Date: Thu, 29 Sep 2016 19:51:31 +0200 Subject: [PATCH 03/46] Maximum connections for websockets listener (#271) Check current number of connections before accepting new websockets clients. Signed-off-by: tucic --- src/websockets.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/websockets.c b/src/websockets.c index 231cb72b8d..975a10c063 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -193,7 +193,10 @@ static int callback_mqtt(struct libwebsocket_context *context, } } } - + if(!mosq->listener){ + _mosquitto_free(mosq); + return -1; + } #if !defined(LWS_LIBRARY_VERSION_NUMBER) mosq->ws_context = context; #endif @@ -209,6 +212,12 @@ static int callback_mqtt(struct libwebsocket_context *context, u->mosq = NULL; return -1; } + if(mosq->listener->max_connections > 0 && mosq->listener->client_count > mosq->listener->max_connections){ + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied: max_connections exceeded.", mosq->address); + _mosquitto_free(mosq); + u->mosq = NULL; + return -1; + } break; case LWS_CALLBACK_CLOSED: From b3a1604646694a9790cd4322a2068f7abb02d41f Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 29 Sep 2016 21:08:02 +0100 Subject: [PATCH 04/46] Update changelog. --- ChangeLog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 0899f8a74e..57eb6af177 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,5 +1,6 @@ Broker: - Fix crash when "lazy" type bridge attempts to reconnect. Closes #259. +- maximum_connections now applies to websockets listeners. Closes #271. 1.4.10 - 20160816 ================= From 1abd089afb958b469f0410148e8a245fd308b4f0 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 20 Oct 2016 13:47:41 +0100 Subject: [PATCH 05/46] [295] Usage should say we support 3.1.1 as well as 3.1. Closes #295. Bug: https://github.com/eclipse/mosquitto/issues/295 --- src/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf.c b/src/conf.c index 587e970bdd..4f4732f2fa 100644 --- a/src/conf.c +++ b/src/conf.c @@ -309,7 +309,7 @@ void mqtt3_config_cleanup(struct mqtt3_config *config) static void print_usage(void) { printf("mosquitto version %s (build date %s)\n\n", VERSION, TIMESTAMP); - printf("mosquitto is an MQTT v3.1 broker.\n\n"); + printf("mosquitto is an MQTT v3.1.1/v3.1 broker.\n\n"); printf("Usage: mosquitto [-c config_file] [-d] [-h] [-p port]\n\n"); printf(" -c : specify the broker config file.\n"); printf(" -d : put the broker into the background after starting.\n"); From 6f7a0bff4b51c0409a8506afb142a0c9c822cc91 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 30 Nov 2016 11:31:30 +0000 Subject: [PATCH 06/46] [323] Allow outgoing IPv6 connections to use TLS. Bug: https://github.com/eclipse/mosquitto/issues/323 --- ChangeLog.txt | 5 +++++ lib/net_mosq.c | 10 ++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 57eb6af177..7cb1a5fb58 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,11 @@ Broker: - Fix crash when "lazy" type bridge attempts to reconnect. Closes #259. - maximum_connections now applies to websockets listeners. Closes #271. +- Allow bridges to use TLS with IPv6. + +Client library: +- Clients can now use TLS with IPv6. + 1.4.10 - 20160816 ================= diff --git a/lib/net_mosq.c b/lib/net_mosq.c index f18d41b2a1..26f98554bf 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -281,14 +281,7 @@ int _mosquitto_try_connect(struct mosquitto *mosq, const char *host, uint16_t po *sock = INVALID_SOCKET; memset(&hints, 0, sizeof(struct addrinfo)); -#ifdef WITH_TLS - if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ - hints.ai_family = PF_INET; - }else -#endif - { - hints.ai_family = PF_UNSPEC; - } + hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; @@ -542,6 +535,7 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } + SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq); bio = BIO_new_socket(sock, BIO_NOCLOSE); if(!bio){ From dac29a5a5f87efa853961c2fa94287ff2a6abcea Mon Sep 17 00:00:00 2001 From: Teun Lassche Date: Mon, 7 Nov 2016 20:28:17 +0100 Subject: [PATCH 07/46] Fix #304 Socket leakage Signed-off-by: Teun Lassche --- lib/mosquitto.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/mosquitto.c b/lib/mosquitto.c index 880657df05..732e18f346 100644 --- a/lib/mosquitto.c +++ b/lib/mosquitto.c @@ -520,6 +520,10 @@ static int _mosquitto_reconnect(struct mosquitto *mosq, bool blocking) _mosquitto_messages_reconnect_reset(mosq); + if(mosq->sock != INVALID_SOCKET){ + _mosquitto_socket_close(mosq); //close socket + } + #ifdef WITH_SOCKS if(mosq->socks5_host){ rc = _mosquitto_socket_connect(mosq, mosq->socks5_host, mosq->socks5_port, mosq->bind_address, blocking); From b55b47efd30e9551f47cb22e94a2ef4c954afa1c Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Sun, 4 Dec 2016 22:01:20 +0000 Subject: [PATCH 08/46] Fix potential socket leakage when reconnecting. Bug: https://github.com/eclipse/mosquitto/issues/304 --- ChangeLog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 7cb1a5fb58..d7cdf92ce5 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -5,6 +5,7 @@ Broker: Client library: - Clients can now use TLS with IPv6. +- Fix potential socket leakage when reconnecting. Closes #304. 1.4.10 - 20160816 From 2c2ba2cf10fa5ea7a98b1b6f7149d1a269c5e540 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 8 Dec 2016 21:06:45 +0000 Subject: [PATCH 09/46] [329] Fix potential negative timeout being passed to pselect. Thanks to Dollars. Bug: https://github.com/eclipse/mosquitto/issues/329 --- ChangeLog.txt | 1 + lib/mosquitto.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index d7cdf92ce5..45fbd33ddd 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -6,6 +6,7 @@ Broker: Client library: - Clients can now use TLS with IPv6. - Fix potential socket leakage when reconnecting. Closes #304. +- Fix potential negative timeout being passed to pselect. Closes #329. 1.4.10 - 20160816 diff --git a/lib/mosquitto.c b/lib/mosquitto.c index 732e18f346..afd7e37590 100644 --- a/lib/mosquitto.c +++ b/lib/mosquitto.c @@ -916,6 +916,12 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets) timeout = (mosq->next_msg_out - now)*1000; } + if(timeout < 0){ + /* There has been a delay somewhere which means we should have already + * sent a message. */ + timeout = 0; + } + local_timeout.tv_sec = timeout/1000; #ifdef HAVE_PSELECT local_timeout.tv_nsec = (timeout-local_timeout.tv_sec*1000)*1e6; From fbb60d67a769c364df336d8266422e4e98f66fed Mon Sep 17 00:00:00 2001 From: Jens Breitbart Date: Sat, 10 Dec 2016 19:41:38 +0100 Subject: [PATCH 10/46] Fix compiler warnings (unused parameter, additional semicolon). A modern version of the clang compiler complained about: * unused parameters * additional semicolon . This commit fixes these warnings. Signed-off-by: Jens Breitbart --- lib/cpp/mosquittopp.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/cpp/mosquittopp.h b/lib/cpp/mosquittopp.h index d3d6f13ef0..e54805d358 100644 --- a/lib/cpp/mosquittopp.h +++ b/lib/cpp/mosquittopp.h @@ -4,12 +4,12 @@ Copyright (c) 2010-2013 Roger Light All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 and Eclipse Distribution License v1.0 which accompany this distribution. - + The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License is available at http://www.eclipse.org/org/documents/edl-v10.php. - + Contributors: Roger Light - initial implementation and documentation. */ @@ -28,8 +28,8 @@ and the Eclipse Distribution License is available at #endif #include -#include #include +#include namespace mosqpp { @@ -90,15 +90,16 @@ class mosqpp_EXPORT mosquittopp { bool want_write(); int threaded_set(bool threaded=true); int socks5_set(const char *host, int port=1080, const char *username=NULL, const char *password=NULL); - - virtual void on_connect(int rc) {return;}; - virtual void on_disconnect(int rc) {return;}; - virtual void on_publish(int mid) {return;}; - virtual void on_message(const struct mosquitto_message *message) {return;}; - virtual void on_subscribe(int mid, int qos_count, const int *granted_qos) {return;}; - virtual void on_unsubscribe(int mid) {return;}; - virtual void on_log(int level, const char *str) {return;}; - virtual void on_error() {return;}; + + // names in the functions commented to prevent unused parameter warning + virtual void on_connect(int /*rc*/) {return;} + virtual void on_disconnect(int /*rc*/) {return;} + virtual void on_publish(int /*mid*/) {return;} + virtual void on_message(const struct mosquitto_message * /*message*/) {return;} + virtual void on_subscribe(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/) {return;} + virtual void on_unsubscribe(int /*mid*/) {return;} + virtual void on_log(int /*level*/, const char * /*str*/) {return;} + virtual void on_error() {return;} }; } From ef417a6688e91fb3974a69ae6cbd1e2b42173b76 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 5 Jan 2017 21:42:24 +0000 Subject: [PATCH 11/46] Don't use reserved identifiers in public headers. --- lib/cpp/mosquittopp.h | 4 ++-- lib/mosquitto.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cpp/mosquittopp.h b/lib/cpp/mosquittopp.h index e54805d358..9b0cb69445 100644 --- a/lib/cpp/mosquittopp.h +++ b/lib/cpp/mosquittopp.h @@ -14,8 +14,8 @@ and the Eclipse Distribution License is available at Roger Light - initial implementation and documentation. */ -#ifndef _MOSQUITTOPP_H_ -#define _MOSQUITTOPP_H_ +#ifndef MOSQUITTOPP_H +#define MOSQUITTOPP_H #ifdef _WIN32 # ifdef mosquittopp_EXPORTS diff --git a/lib/mosquitto.h b/lib/mosquitto.h index a7de292295..2058d59afb 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -14,8 +14,8 @@ and the Eclipse Distribution License is available at Roger Light - initial implementation and documentation. */ -#ifndef _MOSQUITTO_H_ -#define _MOSQUITTO_H_ +#ifndef MOSQUITTO_H +#define MOSQUITTO_H #ifdef __cplusplus extern "C" { From 7f66bf1f65161fe979a056a165dabb614e7a99a1 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 6 Jan 2017 00:44:17 +0000 Subject: [PATCH 12/46] [316] Don't error on zero length persistence files. Closes #316. Bug: https://github.com/eclipse/mosquitto/issues/316 --- ChangeLog.txt | 1 + src/persist.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 45fbd33ddd..c1d6cbfc84 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -2,6 +2,7 @@ Broker: - Fix crash when "lazy" type bridge attempts to reconnect. Closes #259. - maximum_connections now applies to websockets listeners. Closes #271. - Allow bridges to use TLS with IPv6. +- Don't error on zero length persistence files. Closes #316. Client library: - Clients can now use TLS with IPv6. diff --git a/src/persist.c b/src/persist.c index 47c27ae70c..dad6830f99 100644 --- a/src/persist.c +++ b/src/persist.c @@ -813,7 +813,14 @@ int mqtt3_db_restore(struct mosquitto_db *db) fptr = _mosquitto_fopen(db->config->persistence_filepath, "rb"); if(fptr == NULL) return MOSQ_ERR_SUCCESS; - read_e(fptr, &header, 15); + rlen = fread(&header, 1, 15, fptr); + if(rlen == 0){ + fclose(fptr); + _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Persistence file is empty."); + return 0; + }else if(rlen != 15){ + goto error; + } if(!memcmp(header, magic, 15)){ // Restore DB as normal read_e(fptr, &crc, sizeof(uint32_t)); From 8171a975ae9c8a188975af62a2d8ff7345a82d65 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 20 Jan 2017 18:25:04 +0000 Subject: [PATCH 13/46] [354] Close http files even on bad clients. Thanks to jbwdevries. Bug: https://github.com/eclipse/mosquitto/issues/354 --- ChangeLog.txt | 2 ++ src/websockets.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index c1d6cbfc84..9c9f6cd8c6 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -3,6 +3,8 @@ Broker: - maximum_connections now applies to websockets listeners. Closes #271. - Allow bridges to use TLS with IPv6. - Don't error on zero length persistence files. Closes #316. +- For http only websockets clients, close files served over http in all cases + when the client disconnects. Closes #354. Client library: - Clients can now use TLS with IPv6. diff --git a/src/websockets.c b/src/websockets.c index 975a10c063..529aaff4c7 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -521,6 +521,7 @@ static int callback_http(struct libwebsocket_context *context, (unsigned int)filestat.st_size); if(libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP) < 0){ fclose(u->fptr); + u->fptr = NULL; return -1; } libwebsocket_callback_on_writable(context, wsi); @@ -546,6 +547,7 @@ static int callback_http(struct libwebsocket_context *context, buflen = fread(buf, 1, sizeof(buf), u->fptr); if(buflen < 1){ fclose(u->fptr); + u->fptr = NULL; return -1; } wlen = libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP); @@ -566,6 +568,15 @@ static int callback_http(struct libwebsocket_context *context, }else{ return -1; } + + case LWS_CALLBACK_CLOSED: + case LWS_CALLBACK_CLOSED_HTTP: + case LWS_CALLBACK_HTTP_FILE_COMPLETION: + if(u && u->fptr){ + fclose(u->fptr); + u->fptr = NULL; + } + break; #endif default: From a2a2099fa1bcbb5e53a4b6beb751e36dce012c2e Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 20 Jan 2017 21:18:18 +0000 Subject: [PATCH 14/46] Fix error message when websockets http_dir directory does not exist. --- ChangeLog.txt | 1 + src/websockets.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 9c9f6cd8c6..00dd0704ba 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -5,6 +5,7 @@ Broker: - Don't error on zero length persistence files. Closes #316. - For http only websockets clients, close files served over http in all cases when the client disconnects. Closes #354. +- Fix error message when websockets http_dir directory does not exist. Client library: - Clients can now use TLS with IPv6. diff --git a/src/websockets.c b/src/websockets.c index 529aaff4c7..bae69e0348 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -656,7 +656,7 @@ struct libwebsocket_context *mosq_websockets_init(struct _mqtt3_listener *listen if(!user->http_dir){ _mosquitto_free(user); _mosquitto_free(p); - _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open http dir \"%s\".", user->http_dir); + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open http dir \"%s\".", listener->http_dir); return NULL; } } From 9b05b12039ef8e2083c858ae46994a9bd0c0a35d Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Sat, 21 Jan 2017 07:50:07 +0000 Subject: [PATCH 15/46] More file closing fixes. --- src/websockets.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/websockets.c b/src/websockets.c index bae69e0348..b44943d308 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -504,6 +504,7 @@ static int callback_http(struct libwebsocket_context *context, if(fstat(fileno(u->fptr), &filestat) < 0){ libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL); fclose(u->fptr); + u->fptr = NULL; return -1; } #ifdef WIN32 @@ -512,6 +513,8 @@ static int callback_http(struct libwebsocket_context *context, if(!S_ISREG(filestat.st_mode)){ #endif libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL); + fclose(u->fptr); + u->fptr = NULL; return -1; } @@ -568,6 +571,7 @@ static int callback_http(struct libwebsocket_context *context, }else{ return -1; } + break; case LWS_CALLBACK_CLOSED: case LWS_CALLBACK_CLOSED_HTTP: From 532273250c98568ad086807880a3f4a7e204a7d7 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 24 Jan 2017 23:01:16 +0100 Subject: [PATCH 16/46] Check for rt and pthread libraries before linking This fixes building on Android which does not have separate librt or libpthread libraries. Signed-off-by: Fredrik Fornwall --- lib/CMakeLists.txt | 12 ++++++++++-- src/CMakeLists.txt | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d9163991b6..07be5d93bd 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,7 +7,12 @@ if (${WITH_THREADING} STREQUAL ON) set (PTHREAD_LIBRARIES C:\\pthreads\\Pre-built.2\\lib\\x86\\pthreadVC2.lib) set (PTHREAD_INCLUDE_DIR C:\\pthreads\\Pre-built.2\\include) else (WIN32) - set (PTHREAD_LIBRARIES pthread) + find_library(LIBPTHREAD pthread) + if (LIBPTHREAD) + set (PTHREAD_LIBRARIES pthread) + else (LIBPTHREAD) + set (PTHREAD_LIBRARIES "") + endif() set (PTHREAD_INCLUDE_DIR "") endif (WIN32) else (${WITH_THREADING} STREQUAL ON) @@ -44,7 +49,10 @@ add_library(libmosquitto SHARED set (LIBRARIES ${OPENSSL_LIBRARIES} ${PTHREAD_LIBRARIES}) if (UNIX AND NOT APPLE) - set (LIBRARIES ${LIBRARIES} rt) + find_library(LIBRT rt) + if (LIBRT) + set (LIBRARIES ${LIBRARIES} rt) + endif (LIBRT) endif (UNIX AND NOT APPLE) if (WIN32) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0008e5551b..9d615636f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,7 +86,11 @@ if (UNIX) if (APPLE) set (MOSQ_LIBS ${MOSQ_LIBS} dl m) else (APPLE) - set (MOSQ_LIBS ${MOSQ_LIBS} rt dl m) + set (MOSQ_LIBS ${MOSQ_LIBS} dl m) + find_library(LIBRT rt) + if (LIBRT) + set (MOSQ_LIBS ${MOSQ_LIBS} rt) + endif (LIBRT) endif (APPLE) endif (UNIX) From 23b0891048ea017aded192da74df624b785392ce Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 24 Jan 2017 23:24:22 +0100 Subject: [PATCH 17/46] Include instead of Using the standard header instead of makes it consistent with other source files and fixes compilation on Android. Signed-off-by: Fredrik Fornwall --- src/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf.c b/src/conf.c index 4f4732f2fa..9792b2eacb 100644 --- a/src/conf.c +++ b/src/conf.c @@ -36,7 +36,7 @@ and the Eclipse Distribution License is available at #endif #if !defined(WIN32) && !defined(__CYGWIN__) -# include +# include #endif #include From 96a9d445c914534208435c6349ffcce0683fc7ef Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 2 Feb 2017 14:12:59 +0000 Subject: [PATCH 18/46] Fix build dep typo. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a00fe0d4ca..9515380dff 100644 --- a/readme.md +++ b/readme.md @@ -65,7 +65,7 @@ already be built. Use `make binary` to skip building the man pages, or install ### Build Dependencies -* c-ares (libc-ares2-dev on Debian based systems) - disable with `make WITH_DNS_SRV=no` +* c-ares (libc-ares-dev on Debian based systems) - disable with `make WITH_DNS_SRV=no` * libuuid (uuid-dev) - disable with `make WITH_UUID=no` * libwebsockets (libwebsockets-dev) - enable with `make WITH_LIBWEBSOCKETS=yes` * openssl (libssl-dev on Debian based systems) - disable with `make WITH_TLS=no` From ef7a2303657c17da93f06525e94e5e4e526dd171 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 6 Feb 2017 22:39:39 +0000 Subject: [PATCH 19/46] Start of fix for [344]. --- config.mk | 4 ++ lib/mosquitto_internal.h | 6 ++ lib/net_mosq.c | 140 ++++++++++++++++++++++++++++++++------- lib/net_mosq.h | 2 + src/bridge.c | 44 +++++++++++- src/loop.c | 78 +++++++++++++--------- src/mosquitto_broker.h | 2 + 7 files changed, 217 insertions(+), 59 deletions(-) diff --git a/config.mk b/config.mk index 087766c544..3d2aa499dd 100644 --- a/config.mk +++ b/config.mk @@ -156,6 +156,10 @@ ifeq ($(UNAME),QNX) LIB_LIBS:=$(LIB_LIBS) -lsocket endif +ifeq ($(UNAME),Linux) + BROKER_LIBS:=$(BROKER_LIBS) -lanl +endif + ifeq ($(WITH_WRAP),yes) BROKER_LIBS:=$(BROKER_LIBS) -lwrap BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_WRAP diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index 4b4cf85807..640de160c4 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -56,6 +56,9 @@ and the Eclipse Distribution License is available at #include "mosquitto.h" #include "time_mosq.h" #ifdef WITH_BROKER +# ifdef __linux__ +# include +# endif # include "uthash.h" struct mosquitto_client_msg; #endif @@ -151,6 +154,9 @@ struct mosquitto { mosq_sock_t sock; #ifndef WITH_BROKER mosq_sock_t sockpairR, sockpairW; +#endif +#ifdef __linux__ + struct gaicb *adns; /* For getaddrinfo_a */ #endif enum _mosquitto_protocol protocol; char *address; diff --git a/lib/net_mosq.c b/lib/net_mosq.c index 26f98554bf..24174f096d 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -14,12 +14,15 @@ and the Eclipse Distribution License is available at Roger Light - initial implementation and documentation. */ +#define _GNU_SOURCE + #include #include #include #include #include #ifndef WIN32 +#define _GNU_SOURCE #include #include #include @@ -268,6 +271,88 @@ static unsigned int psk_client_callback(SSL *ssl, const char *hint, } #endif +#if defined(WITH_BROKER) && defined(__linux__) +/* Async connect, part 1 (dns lookup) */ +int _mosquitto_try_connect_step1(struct mosquitto *mosq, const char *host) +{ + int s; + void *sevp = NULL; + + if(mosq->adns){ + _mosquitto_free(mosq->adns); + } + mosq->adns = _mosquitto_calloc(1, sizeof(struct gaicb)); + if(!mosq->adns){ + return MOSQ_ERR_NOMEM; + } + mosq->adns->ar_name = host; + + s = getaddrinfo_a(GAI_NOWAIT, &mosq->adns, 1, sevp); + if(s){ + errno = s; + return MOSQ_ERR_EAI; + } + + return MOSQ_ERR_SUCCESS; +} + +/* Async connect part 2, the connection. */ +int _mosquitto_try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_sock_t *sock) +{ + struct addrinfo *ainfo, *rp; + int rc; + + ainfo = mosq->adns->ar_result; + + for(rp = ainfo; rp != NULL; rp = rp->ai_next){ + *sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if(*sock == INVALID_SOCKET) continue; + + if(rp->ai_family == PF_INET){ + ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); + }else if(rp->ai_family == PF_INET6){ + ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); + }else{ + COMPAT_CLOSE(*sock); + continue; + } + + /* Set non-blocking */ + if(_mosquitto_socket_nonblock(*sock)){ + COMPAT_CLOSE(*sock); + continue; + } + + rc = connect(*sock, rp->ai_addr, rp->ai_addrlen); +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if(rc == 0 || errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK){ + if(rc < 0 && (errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK)){ + rc = MOSQ_ERR_CONN_PENDING; + } + + /* Set non-blocking */ + if(_mosquitto_socket_nonblock(*sock)){ + COMPAT_CLOSE(*sock); + continue; + } + break; + } + + COMPAT_CLOSE(*sock); + *sock = INVALID_SOCKET; + } + freeaddrinfo(ainfo); + if(!rp){ + return MOSQ_ERR_ERRNO; + } + return rc; +} + +#endif + + int _mosquitto_try_connect(struct mosquitto *mosq, const char *host, uint16_t port, mosq_sock_t *sock, const char *bind_address, bool blocking) { struct addrinfo hints; @@ -303,7 +388,7 @@ int _mosquitto_try_connect(struct mosquitto *mosq, const char *host, uint16_t po for(rp = ainfo; rp != NULL; rp = rp->ai_next){ *sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(*sock == INVALID_SOCKET) continue; - + if(rp->ai_family == PF_INET){ ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); }else if(rp->ai_family == PF_INET6){ @@ -396,24 +481,13 @@ int mosquitto__socket_connect_tls(struct mosquitto *mosq) } #endif -/* Create a socket and connect it to 'ip' on port 'port'. - * Returns -1 on failure (ip is NULL, socket creation/connection error) - * Returns sock number on success. - */ -int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking) +int _mosquitto_socket_connect_step3(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking) { - mosq_sock_t sock = INVALID_SOCKET; - int rc; #ifdef WITH_TLS int ret; BIO *bio; #endif - if(!mosq || !host || !port) return MOSQ_ERR_INVAL; - - rc = _mosquitto_try_connect(mosq, host, port, &sock, bind_address, blocking); - if(rc > 0) return rc; - #ifdef WITH_TLS if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ #if OPENSSL_VERSION_NUMBER >= 0x10001000L @@ -425,7 +499,7 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version); - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_INVAL; } #else @@ -433,13 +507,13 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version); - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_INVAL; } #endif if(!mosq->ssl_ctx){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } @@ -456,7 +530,7 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers); if(ret == 0){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers); - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } } @@ -480,7 +554,7 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath); } #endif - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } if(mosq->tls_cert_reqs == 0){ @@ -502,7 +576,7 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t #else _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile); #endif - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } } @@ -514,13 +588,13 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t #else _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile); #endif - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } ret = SSL_CTX_check_private_key(mosq->ssl_ctx); if(ret != 1){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent."); - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } } @@ -532,27 +606,43 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t mosq->ssl = SSL_new(mosq->ssl_ctx); if(!mosq->ssl){ - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq); - bio = BIO_new_socket(sock, BIO_NOCLOSE); + bio = BIO_new_socket(mosq->sock, BIO_NOCLOSE); if(!bio){ - COMPAT_CLOSE(sock); + COMPAT_CLOSE(mosq->sock); return MOSQ_ERR_TLS; } SSL_set_bio(mosq->ssl, bio, bio); - mosq->sock = sock; if(mosquitto__socket_connect_tls(mosq)){ return MOSQ_ERR_TLS; } } #endif + return MOSQ_ERR_SUCCESS; +} + +/* Create a socket and connect it to 'ip' on port 'port'. + * Returns -1 on failure (ip is NULL, socket creation/connection error) + * Returns sock number on success. + */ +int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking) +{ + mosq_sock_t sock = INVALID_SOCKET; + int rc; + + if(!mosq || !host || !port) return MOSQ_ERR_INVAL; + + rc = _mosquitto_try_connect(mosq, host, port, &sock, bind_address, blocking); + if(rc > 0) return rc; mosq->sock = sock; + rc = _mosquitto_socket_connect_step3(mosq, host, port, bind_address, blocking); return rc; } diff --git a/lib/net_mosq.h b/lib/net_mosq.h index b101746d61..569e9452c7 100644 --- a/lib/net_mosq.h +++ b/lib/net_mosq.h @@ -61,6 +61,8 @@ int _mosquitto_socket_close(struct mosquitto_db *db, struct mosquitto *mosq); int _mosquitto_socket_close(struct mosquitto *mosq); #endif int _mosquitto_try_connect(struct mosquitto *mosq, const char *host, uint16_t port, mosq_sock_t *sock, const char *bind_address, bool blocking); +int _mosquitto_try_connect_step1(struct mosquitto *mosq, const char *host); +int _mosquitto_try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_sock_t *sock); int _mosquitto_socket_nonblock(mosq_sock_t sock); int _mosquitto_socketpair(mosq_sock_t *sp1, mosq_sock_t *sp2); diff --git a/src/bridge.c b/src/bridge.c index a7d5ad096e..e9a3d0eefc 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -131,10 +131,15 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) return MOSQ_ERR_NOMEM; } +#ifdef __linux__ + new_context->bridge->restart_t = 1; /* force quick restart of bridge */ + return mqtt3_bridge_connect_step1(db, new_context); +#else return mqtt3_bridge_connect(db, new_context); +#endif } -int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) +int mqtt3_bridge_connect_step1(struct mosquitto_db *db, struct mosquitto *context) { int rc; int i; @@ -207,6 +212,31 @@ int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) } } + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); + rc = _mosquitto_try_connect_step1(context, context->bridge->addresses[context->bridge->cur_address].address); + if(rc > 0 ){ + if(rc == MOSQ_ERR_TLS){ + _mosquitto_socket_close(db, context); + return rc; /* Error already printed */ + }else if(rc == MOSQ_ERR_ERRNO){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); + }else if(rc == MOSQ_ERR_EAI){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); + } + + return rc; + } + + return MOSQ_ERR_SUCCESS; +} + + +int mqtt3_bridge_connect_step2(struct mosquitto_db *db, struct mosquitto *context) +{ + int rc; + + if(!context || !context->bridge) return MOSQ_ERR_INVAL; + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, false); if(rc > 0 ){ @@ -245,6 +275,18 @@ int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) } } + +int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) +{ + int rc; + + rc = mqtt3_bridge_connect_step1(db, context); + if(rc) return rc; + + return mqtt3_bridge_connect_step2(db, context); +} + + void mqtt3_bridge_packet_cleanup(struct mosquitto *context) { struct _mosquitto_packet *packet; diff --git a/src/loop.c b/src/loop.c index 07e02c5b39..d3d5e6a86c 100644 --- a/src/loop.c +++ b/src/loop.c @@ -244,45 +244,57 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li context->bridge->primary_retry = now + 5; } }else{ - if(context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect){ - rc = mqtt3_bridge_connect(db, context); - if(rc == MOSQ_ERR_SUCCESS){ - pollfds[pollfd_index].fd = context->sock; - pollfds[pollfd_index].events = POLLIN; - pollfds[pollfd_index].revents = 0; - if(context->current_out_packet){ - pollfds[pollfd_index].events |= POLLOUT; + if((context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect) + || (context->bridge->start_type == bst_automatic && now > context->bridge->restart_t)){ + +#ifdef __linux__ + if(context->adns){ + /* Waiting on DNS lookup */ + rc = mqtt3_bridge_connect_step2(db, context); + if(rc == MOSQ_ERR_SUCCESS){ + pollfds[pollfd_index].fd = context->sock; + pollfds[pollfd_index].events = POLLIN; + pollfds[pollfd_index].revents = 0; + if(context->current_out_packet){ + pollfds[pollfd_index].events |= POLLOUT; + } + context->pollfd_index = pollfd_index; + pollfd_index++; + }else{ + context->bridge->cur_address++; + if(context->bridge->cur_address == context->bridge->address_count){ + context->bridge->cur_address = 0; + } } - context->pollfd_index = pollfd_index; - pollfd_index++; }else{ - context->bridge->cur_address++; - if(context->bridge->cur_address == context->bridge->address_count){ - context->bridge->cur_address = 0; + rc = mqtt3_bridge_connect_step1(db, context); + if(rc){ + context->bridge->cur_address++; + if(context->bridge->cur_address == context->bridge->address_count){ + context->bridge->cur_address = 0; + } } } - } - if(context->bridge->start_type == bst_automatic && now > context->bridge->restart_t){ - context->bridge->restart_t = 0; - rc = mqtt3_bridge_connect(db, context); - if(rc == MOSQ_ERR_SUCCESS){ - pollfds[pollfd_index].fd = context->sock; - pollfds[pollfd_index].events = POLLIN; - pollfds[pollfd_index].revents = 0; - if(context->current_out_packet){ - pollfds[pollfd_index].events |= POLLOUT; - } - context->pollfd_index = pollfd_index; - pollfd_index++; - }else{ - /* Retry later. */ - context->bridge->restart_t = now+context->bridge->restart_timeout; - - context->bridge->cur_address++; - if(context->bridge->cur_address == context->bridge->address_count){ - context->bridge->cur_address = 0; +#else + { + rc = mqtt3_bridge_connect(db, context); + if(rc == MOSQ_ERR_SUCCESS){ + pollfds[pollfd_index].fd = context->sock; + pollfds[pollfd_index].events = POLLIN; + pollfds[pollfd_index].revents = 0; + if(context->current_out_packet){ + pollfds[pollfd_index].events |= POLLOUT; + } + context->pollfd_index = pollfd_index; + pollfd_index++; + }else{ + context->bridge->cur_address++; + if(context->bridge->cur_address == context->bridge->address_count){ + context->bridge->cur_address = 0; + } } } +#endif } } } diff --git a/src/mosquitto_broker.h b/src/mosquitto_broker.h index bd6a0ef7da..c89489b6f6 100644 --- a/src/mosquitto_broker.h +++ b/src/mosquitto_broker.h @@ -466,6 +466,8 @@ int _mosquitto_log_printf(struct mosquitto *mosq, int level, const char *fmt, .. #ifdef WITH_BRIDGE int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge); int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context); +int mqtt3_bridge_connect_step1(struct mosquitto_db *db, struct mosquitto *context); +int mqtt3_bridge_connect_step2(struct mosquitto_db *db, struct mosquitto *context); void mqtt3_bridge_packet_cleanup(struct mosquitto *context); #endif From f464970fcffad41844c691bd5229e4749b9c10b4 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 6 Feb 2017 23:10:43 +0000 Subject: [PATCH 20/46] [344] Fix leaks and incorrect connect call. --- lib/net_mosq.h | 1 + src/bridge.c | 16 +++++++++++++++- src/loop.c | 36 ++++++++++++++++++++++++------------ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/net_mosq.h b/lib/net_mosq.h index 569e9452c7..b504ebc03c 100644 --- a/lib/net_mosq.h +++ b/lib/net_mosq.h @@ -63,6 +63,7 @@ int _mosquitto_socket_close(struct mosquitto *mosq); int _mosquitto_try_connect(struct mosquitto *mosq, const char *host, uint16_t port, mosq_sock_t *sock, const char *bind_address, bool blocking); int _mosquitto_try_connect_step1(struct mosquitto *mosq, const char *host); int _mosquitto_try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_sock_t *sock); +int _mosquitto_socket_connect_step3(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking); int _mosquitto_socket_nonblock(mosq_sock_t sock); int _mosquitto_socketpair(mosq_sock_t *sp1, mosq_sock_t *sp2); diff --git a/src/bridge.c b/src/bridge.c index e9a3d0eefc..5f5eb1b3d8 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -238,7 +238,21 @@ int mqtt3_bridge_connect_step2(struct mosquitto_db *db, struct mosquitto *contex if(!context || !context->bridge) return MOSQ_ERR_INVAL; _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); - rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, false); + rc = _mosquitto_try_connect_step2(context, context->bridge->addresses[context->bridge->cur_address].port, &context->sock); + if(rc > 0 ){ + if(rc == MOSQ_ERR_TLS){ + _mosquitto_socket_close(db, context); + return rc; /* Error already printed */ + }else if(rc == MOSQ_ERR_ERRNO){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); + }else if(rc == MOSQ_ERR_EAI){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); + } + + return rc; + } + + rc = _mosquitto_socket_connect_step3(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, false); if(rc > 0 ){ if(rc == MOSQ_ERR_TLS){ _mosquitto_socket_close(db, context); diff --git a/src/loop.c b/src/loop.c index d3d5e6a86c..a4014f0ccd 100644 --- a/src/loop.c +++ b/src/loop.c @@ -250,21 +250,33 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li #ifdef __linux__ if(context->adns){ /* Waiting on DNS lookup */ - rc = mqtt3_bridge_connect_step2(db, context); - if(rc == MOSQ_ERR_SUCCESS){ - pollfds[pollfd_index].fd = context->sock; - pollfds[pollfd_index].events = POLLIN; - pollfds[pollfd_index].revents = 0; - if(context->current_out_packet){ - pollfds[pollfd_index].events |= POLLOUT; + rc = gai_error(context->adns); + if(rc == EAI_INPROGRESS){ + /* Just keep on waiting */ + }else if(rc == 0){ + rc = mqtt3_bridge_connect_step2(db, context); + if(rc == MOSQ_ERR_SUCCESS){ + pollfds[pollfd_index].fd = context->sock; + pollfds[pollfd_index].events = POLLIN; + pollfds[pollfd_index].revents = 0; + if(context->current_out_packet){ + pollfds[pollfd_index].events |= POLLOUT; + } + context->pollfd_index = pollfd_index; + pollfd_index++; + }else{ + context->bridge->cur_address++; + if(context->bridge->cur_address == context->bridge->address_count){ + context->bridge->cur_address = 0; + } } - context->pollfd_index = pollfd_index; - pollfd_index++; }else{ - context->bridge->cur_address++; - if(context->bridge->cur_address == context->bridge->address_count){ - context->bridge->cur_address = 0; + /* Need to retry */ + if(context->adns->ar_result){ + freeaddrinfo(context->adns->ar_result); } + _mosquitto_free(context->adns); + context->adns = NULL; } }else{ rc = mqtt3_bridge_connect_step1(db, context); From ee543a25f5deaa42b62a5b39a205a3c4a4531a81 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 7 Feb 2017 16:11:57 +0000 Subject: [PATCH 21/46] [344] More leak fixes. --- lib/net_mosq.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/net_mosq.c b/lib/net_mosq.c index 24174f096d..c8776c1aca 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -290,6 +290,8 @@ int _mosquitto_try_connect_step1(struct mosquitto *mosq, const char *host) s = getaddrinfo_a(GAI_NOWAIT, &mosq->adns, 1, sevp); if(s){ errno = s; + _mosquitto_free(mosq->adns); + mosq->adns = NULL; return MOSQ_ERR_EAI; } @@ -343,10 +345,16 @@ int _mosquitto_try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_soc COMPAT_CLOSE(*sock); *sock = INVALID_SOCKET; } - freeaddrinfo(ainfo); + freeaddrinfo(mosq->adns->ar_result); + mosq->adns->ar_result = NULL; + + _mosquitto_free(mosq->adns); + mosq->adns = NULL; + if(!rp){ return MOSQ_ERR_ERRNO; } + return rc; } From 3d40ffe18b3fed0a652778d9702b3c4fe71e12ae Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 8 Feb 2017 15:40:44 +0000 Subject: [PATCH 22/46] [344] Only do async dns on glibc. --- lib/mosquitto_internal.h | 2 +- lib/net_mosq.c | 2 +- src/bridge.c | 2 +- src/loop.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index 640de160c4..e401a2fb6d 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -155,7 +155,7 @@ struct mosquitto { #ifndef WITH_BROKER mosq_sock_t sockpairR, sockpairW; #endif -#ifdef __linux__ +#ifdef __GLIBC__ struct gaicb *adns; /* For getaddrinfo_a */ #endif enum _mosquitto_protocol protocol; diff --git a/lib/net_mosq.c b/lib/net_mosq.c index c8776c1aca..c98b274679 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -271,7 +271,7 @@ static unsigned int psk_client_callback(SSL *ssl, const char *hint, } #endif -#if defined(WITH_BROKER) && defined(__linux__) +#if defined(WITH_BROKER) && defined(__GLIBC__) /* Async connect, part 1 (dns lookup) */ int _mosquitto_try_connect_step1(struct mosquitto *mosq, const char *host) { diff --git a/src/bridge.c b/src/bridge.c index 5f5eb1b3d8..ad9ef1d86f 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -131,7 +131,7 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) return MOSQ_ERR_NOMEM; } -#ifdef __linux__ +#ifdef __GLIBC__ new_context->bridge->restart_t = 1; /* force quick restart of bridge */ return mqtt3_bridge_connect_step1(db, new_context); #else diff --git a/src/loop.c b/src/loop.c index a4014f0ccd..dba3c5ea24 100644 --- a/src/loop.c +++ b/src/loop.c @@ -247,7 +247,7 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li if((context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect) || (context->bridge->start_type == bst_automatic && now > context->bridge->restart_t)){ -#ifdef __linux__ +#ifdef __GLIBC__ if(context->adns){ /* Waiting on DNS lookup */ rc = gai_error(context->adns); From fb824e7f1ea608263eb59890f04f3169a4f22239 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 8 Feb 2017 16:24:50 +0000 Subject: [PATCH 23/46] [344] Detect libanl in cmake. --- src/CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d615636f6..6918ac26ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -82,6 +82,16 @@ add_executable(mosquitto ${MOSQ_SRCS}) set (MOSQ_LIBS ${MOSQ_LIBS} ${OPENSSL_LIBRARIES}) +# Check for getaddrinfo_a +include(CheckLibraryExists) +check_library_exists(anl getaddrinfo_a "" HAVE_GETADDRINFO_A) +if (HAVE_GETADDRINFO_A) + add_definitions(-DHAVE_GETADDRINFO_A) + set (MOSQ_LIBS ${MOSQ_LIBS} anl) +endif (HAVE_GETADDRINFO_A) + + + if (UNIX) if (APPLE) set (MOSQ_LIBS ${MOSQ_LIBS} dl m) From f0485d139848da64dd76fff57ef32c20b7b1c6f0 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 8 Feb 2017 22:30:00 +0000 Subject: [PATCH 24/46] [344] Don't compile in async dns support by default for makefiles. --- config.mk | 8 ++++++++ lib/mosquitto_internal.h | 2 +- lib/net_mosq.c | 2 +- src/bridge.c | 2 +- src/loop.c | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/config.mk b/config.mk index 3d2aa499dd..02df80b214 100644 --- a/config.mk +++ b/config.mk @@ -76,6 +76,9 @@ WITH_DOCS:=yes # Build with client support for SOCK5 proxy. WITH_SOCKS:=yes +# Build with async dns lookup support for bridges (temporary). Requires glibc. +#WITH_ADNS:=yes + # ============================================================================= # End of user configuration # ============================================================================= @@ -239,6 +242,11 @@ ifeq ($(WITH_EC),yes) BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_EC endif +ifeq ($(WITH_ADNS),yes) + BROKER_LIBS:=$(BROKER_LIBS) -lanl + BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_ADNS +endif + MAKE_ALL:=mosquitto ifeq ($(WITH_DOCS),yes) MAKE_ALL:=$(MAKE_ALL) docs diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index e401a2fb6d..ac9257380e 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -155,7 +155,7 @@ struct mosquitto { #ifndef WITH_BROKER mosq_sock_t sockpairR, sockpairW; #endif -#ifdef __GLIBC__ +#if defined(__GLIBC__) && defined(WITH_ADNS) struct gaicb *adns; /* For getaddrinfo_a */ #endif enum _mosquitto_protocol protocol; diff --git a/lib/net_mosq.c b/lib/net_mosq.c index c98b274679..06c9bce2e9 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -271,7 +271,7 @@ static unsigned int psk_client_callback(SSL *ssl, const char *hint, } #endif -#if defined(WITH_BROKER) && defined(__GLIBC__) +#if defined(WITH_BROKER) && defined(__GLIBC__) && defined(WITH_ADNS) /* Async connect, part 1 (dns lookup) */ int _mosquitto_try_connect_step1(struct mosquitto *mosq, const char *host) { diff --git a/src/bridge.c b/src/bridge.c index ad9ef1d86f..869b3db18e 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -131,7 +131,7 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) return MOSQ_ERR_NOMEM; } -#ifdef __GLIBC__ +#if defined(__GLIBC__) && defined(WITH_ADNS) new_context->bridge->restart_t = 1; /* force quick restart of bridge */ return mqtt3_bridge_connect_step1(db, new_context); #else diff --git a/src/loop.c b/src/loop.c index dba3c5ea24..b7e8b752bc 100644 --- a/src/loop.c +++ b/src/loop.c @@ -247,7 +247,7 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li if((context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect) || (context->bridge->start_type == bst_automatic && now > context->bridge->restart_t)){ -#ifdef __GLIBC__ +#if defined(__GLIBC__) && defined(WITH_ADNS) if(context->adns){ /* Waiting on DNS lookup */ rc = gai_error(context->adns); From 565c9c34321e5d82815b4fc83156543f59b73a08 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 9 Feb 2017 16:41:48 +0000 Subject: [PATCH 25/46] [344] Fix non-async case. --- src/bridge.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 4 deletions(-) diff --git a/src/bridge.c b/src/bridge.c index 869b3db18e..dc5f9c4472 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -139,6 +139,7 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge) #endif } +#if defined(__GLIBC__) && defined(WITH_ADNS) int mqtt3_bridge_connect_step1(struct mosquitto_db *db, struct mosquitto *context) { int rc; @@ -288,17 +289,119 @@ int mqtt3_bridge_connect_step2(struct mosquitto_db *db, struct mosquitto *contex return rc; } } - +#else int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) { int rc; + int i; + char *notification_topic; + int notification_topic_len; + uint8_t notification_payload; + + if(!context || !context->bridge) return MOSQ_ERR_INVAL; + + context->state = mosq_cs_new; + context->sock = INVALID_SOCKET; + context->last_msg_in = mosquitto_time(); + context->next_msg_out = mosquitto_time() + context->bridge->keepalive; + context->keepalive = context->bridge->keepalive; + context->clean_session = context->bridge->clean_session; + context->in_packet.payload = NULL; + context->ping_t = 0; + context->bridge->lazy_reconnect = false; + mqtt3_bridge_packet_cleanup(context); + mqtt3_db_message_reconnect_reset(db, context); + + if(context->clean_session){ + mqtt3_db_messages_delete(db, context); + } + + /* Delete all local subscriptions even for clean_session==false. We don't + * remove any messages and the next loop carries out the resubscription + * anyway. This means any unwanted subs will be removed. + */ + mqtt3_subs_clean_session(db, context); + + for(i=0; ibridge->topic_count; i++){ + if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){ + _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic); + if(mqtt3_sub_add(db, context, context->bridge->topics[i].local_topic, context->bridge->topics[i].qos, &db->subs)) return 1; + } + } - rc = mqtt3_bridge_connect_step1(db, context); - if(rc) return rc; + if(context->bridge->notifications){ + if(context->bridge->notification_topic){ + if(!context->bridge->initial_notification_done){ + notification_payload = '0'; + mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); + context->bridge->initial_notification_done = true; + } + notification_payload = '0'; + rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, ¬ification_payload, 1, true); + if(rc != MOSQ_ERR_SUCCESS){ + return rc; + } + }else{ + notification_topic_len = strlen(context->bridge->remote_clientid)+strlen("$SYS/broker/connection//state"); + notification_topic = _mosquitto_malloc(sizeof(char)*(notification_topic_len+1)); + if(!notification_topic) return MOSQ_ERR_NOMEM; - return mqtt3_bridge_connect_step2(db, context); + snprintf(notification_topic, notification_topic_len+1, "$SYS/broker/connection/%s/state", context->bridge->remote_clientid); + + if(!context->bridge->initial_notification_done){ + notification_payload = '0'; + mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); + context->bridge->initial_notification_done = true; + } + + notification_payload = '0'; + rc = _mosquitto_will_set(context, notification_topic, 1, ¬ification_payload, 1, true); + _mosquitto_free(notification_topic); + if(rc != MOSQ_ERR_SUCCESS){ + return rc; + } + } + } + + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); + rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, false); + if(rc > 0 ){ + if(rc == MOSQ_ERR_TLS){ + _mosquitto_socket_close(db, context); + return rc; /* Error already printed */ + }else if(rc == MOSQ_ERR_ERRNO){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); + }else if(rc == MOSQ_ERR_EAI){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); + } + + return rc; + } + + HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(context->sock), context); + + if(rc == MOSQ_ERR_CONN_PENDING){ + context->state = mosq_cs_connect_pending; + } + rc = _mosquitto_send_connect(context, context->keepalive, context->clean_session); + if(rc == MOSQ_ERR_SUCCESS){ + return MOSQ_ERR_SUCCESS; + }else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){ + return MOSQ_ERR_SUCCESS; + }else{ + if(rc == MOSQ_ERR_TLS){ + return rc; /* Error already printed */ + }else if(rc == MOSQ_ERR_ERRNO){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); + }else if(rc == MOSQ_ERR_EAI){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); + } + _mosquitto_socket_close(db, context); + return rc; + } } +#endif void mqtt3_bridge_packet_cleanup(struct mosquitto *context) From ebad302119b5406d2a134345cc5a596163868c23 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Sun, 12 Feb 2017 21:22:58 +0000 Subject: [PATCH 26/46] [379] Improve mosquitto_passwd error messages. Thanks to Jaimyn Mayer. Closes #379. Bug: https://github.com/eclipse/mosquitto/issues/379 --- ChangeLog.txt | 1 + src/mosquitto_passwd.c | 57 ++++++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 00dd0704ba..c03ad2bc29 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -6,6 +6,7 @@ Broker: - For http only websockets clients, close files served over http in all cases when the client disconnects. Closes #354. - Fix error message when websockets http_dir directory does not exist. +- Improve password utility error message. Closes #379. Client library: - Clients can now use TLS with IPv6. diff --git a/src/mosquitto_passwd.c b/src/mosquitto_passwd.c index de9a719ae8..aa7a81011a 100644 --- a/src/mosquitto_passwd.c +++ b/src/mosquitto_passwd.c @@ -377,35 +377,50 @@ int main(int argc, char *argv[]) OpenSSL_add_all_digests(); - if(argc == 5){ - if(!strcmp(argv[1], "-b")){ - batch_mode = true; - }else{ - fprintf(stderr, "Error: Unknown option '%s'\n", argv[1]); + if(argc == 1){ + print_usage(); + return 1; + } + + if(!strcmp(argv[1], "-c")){ + create_new = true; + if(argc != 4){ + fprintf(stderr, "Error: -c argument given but password file or username missing.\n"); return 1; + }else{ + password_file_tmp = argv[2]; + username = argv[3]; } - password_file_tmp = argv[2]; - username = argv[3]; - password_cmd = argv[4]; - }else if(argc == 4){ - if(!strcmp(argv[1], "-c")){ - create_new = true; - }else if(!strcmp(argv[1], "-D")){ - delete_user = true; + }else if(!strcmp(argv[1], "-D")){ + delete_user = true; + if(argc != 4){ + fprintf(stderr, "Error: -D argument given but password file or username missing.\n"); + return 1; }else{ - fprintf(stderr, "Error: Unknown option '%s'\n", argv[1]); + password_file_tmp = argv[2]; + username = argv[3]; + } + }else if(!strcmp(argv[1], "-b")){ + batch_mode = true; + if(argc != 5){ + fprintf(stderr, "Error: -b argument given but password file, username or password missing.\n"); return 1; + }else{ + password_file_tmp = argv[2]; + username = argv[3]; + password_cmd = argv[4]; } - password_file_tmp = argv[2]; - username = argv[3]; - }else if(argc == 3){ - if(!strcmp(argv[1], "-U")){ + }else if(!strcmp(argv[1], "-U")){ + if(argc != 3){ + fprintf(stderr, "Error: -U argument given but password file missing.\n"); + return 1; + }else{ do_update_file = true; password_file_tmp = argv[2]; - }else{ - password_file_tmp = argv[1]; - username = argv[2]; } + }else if(argc == 3){ + password_file_tmp = argv[1]; + username = argv[2]; }else{ print_usage(); return 1; From 10c89751fa9a51aad423e7eb2df66df13ae2355b Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 15 Feb 2017 21:01:49 +0000 Subject: [PATCH 27/46] Use of --ciphers no longer requires you to also pass --tls-version. Closes #380. Bug: https://github.com/eclipse/mosquitto/issues/380 --- ChangeLog.txt | 4 ++++ client/client_shared.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index c03ad2bc29..c3e05be7e9 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,10 @@ Broker: - Fix error message when websockets http_dir directory does not exist. - Improve password utility error message. Closes #379. +Clients: +- Use of --ciphers no longer requires you to also pass --tls-version. + Closes #380. + Client library: - Clients can now use TLS with IPv6. - Fix potential socket leakage when reconnecting. Closes #304. diff --git a/client/client_shared.c b/client/client_shared.c index cecc5ab5c1..b82d6c2400 100644 --- a/client/client_shared.c +++ b/client/client_shared.c @@ -690,7 +690,7 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg) return 1; } # endif - if(cfg->tls_version && mosquitto_tls_opts_set(mosq, 1, cfg->tls_version, cfg->ciphers)){ + if((cfg->tls_version || cfg->ciphers) && mosquitto_tls_opts_set(mosq, 1, cfg->tls_version, cfg->ciphers)){ if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS options.\n"); mosquitto_lib_cleanup(); return 1; From ce7f60e45f0952400232da053c5707cb3b013477 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 20 Feb 2017 21:20:00 +0000 Subject: [PATCH 28/46] EPROTO is defined on MSVC 2015. --- config.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/config.h b/config.h index fbe4babb23..6af5c2833d 100644 --- a/config.h +++ b/config.h @@ -13,6 +13,7 @@ * ============================================================ */ #if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf sprintf_s +# define EPROTO ECONNABORTED #endif #ifdef WIN32 @@ -27,6 +28,3 @@ #define uthash_malloc(sz) _mosquitto_malloc(sz) #define uthash_free(ptr,sz) _mosquitto_free(ptr) -#ifndef EPROTO -# define EPROTO ECONNABORTED -#endif From 55f4a17a69aae83480be524515b5c5fd0ce4703e Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 20 Feb 2017 21:48:25 +0000 Subject: [PATCH 29/46] Missing malloc check. --- client/client_shared.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/client_shared.c b/client/client_shared.c index b82d6c2400..caa33e1855 100644 --- a/client/client_shared.c +++ b/client/client_shared.c @@ -924,6 +924,10 @@ static int mosquitto__parse_socks_url(struct mosq_config *cfg, char *url) port[len] = '\0'; }else{ host = malloc(len + 1); + if(!host){ + fprintf(stderr, "Error: Out of memory.\n"); + goto cleanup; + } memcpy(host, &(str[start]), len); host[len] = '\0'; } From 9f32d5c0ac17fb760838581bdcc302ab970e02a2 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 20 Feb 2017 21:57:45 +0000 Subject: [PATCH 30/46] Version bump. --- CMakeLists.txt | 2 +- ChangeLog.txt | 3 +++ config.mk | 2 +- installer/mosquitto-cygwin.nsi | 2 +- installer/mosquitto.nsi | 2 +- lib/mosquitto.h | 2 +- set-version.sh | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29fb4b4523..b0f29a2d3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ project(mosquitto) cmake_minimum_required(VERSION 2.8) # Only for version 3 and up. cmake_policy(SET CMP0042 NEW) -set (VERSION 1.4.10) +set (VERSION 1.4.11) if (WIN32) execute_process(COMMAND cmd /c echo %DATE% %TIME% OUTPUT_VARIABLE TIMESTAMP diff --git a/ChangeLog.txt b/ChangeLog.txt index c3e05be7e9..57f9ee2c75 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,6 @@ +1.4.11 - 20170220 +================= + Broker: - Fix crash when "lazy" type bridge attempts to reconnect. Closes #259. - maximum_connections now applies to websockets listeners. Closes #271. diff --git a/config.mk b/config.mk index 02df80b214..6e369c2349 100644 --- a/config.mk +++ b/config.mk @@ -86,7 +86,7 @@ WITH_SOCKS:=yes # Also bump lib/mosquitto.h, CMakeLists.txt, # installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi -VERSION=1.4.10 +VERSION=1.4.11 TIMESTAMP:=$(shell date "+%F %T%z") # Client library SO version. Bump if incompatible API/ABI changes are made. diff --git a/installer/mosquitto-cygwin.nsi b/installer/mosquitto-cygwin.nsi index eea6ae421d..1567c73b7b 100644 --- a/installer/mosquitto-cygwin.nsi +++ b/installer/mosquitto-cygwin.nsi @@ -7,7 +7,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "mosquitto" -!define VERSION 1.4.10 +!define VERSION 1.4.11 OutFile "mosquitto-${VERSION}-install-cygwin.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi index 7dc4d1f8fa..4afe737be4 100644 --- a/installer/mosquitto.nsi +++ b/installer/mosquitto.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "mosquitto" -!define VERSION 1.4.10 +!define VERSION 1.4.11 OutFile "mosquitto-${VERSION}-install-win32.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 2058d59afb..43e1f15fe3 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -45,7 +45,7 @@ extern "C" { #define LIBMOSQUITTO_MAJOR 1 #define LIBMOSQUITTO_MINOR 4 -#define LIBMOSQUITTO_REVISION 10 +#define LIBMOSQUITTO_REVISION 11 /* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */ #define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION) diff --git a/set-version.sh b/set-version.sh index 71631010cd..75c0b5299c 100755 --- a/set-version.sh +++ b/set-version.sh @@ -2,7 +2,7 @@ MAJOR=1 MINOR=4 -REVISION=9 +REVISION=11 sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk From a93a0c9bb1cb2481dba5da89391c607ddbab9220 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 13 Apr 2017 13:40:12 +0100 Subject: [PATCH 31/46] [424] Fix mosquitto.db from becoming corrupted due to client messages being persisted with no stored message. Thanks to codami. Bug: https://github.com/eclipse/mosquitto/issues/424 --- ChangeLog.txt | 7 +++++++ src/persist.c | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 57f9ee2c75..36a0ba5828 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,10 @@ +1.4.12 - 201703xx +================= + +Broker: +- Fix mosquitto.db from becoming corrupted due to client messages being + persisted with no stored message. Closes #424. + 1.4.11 - 20170220 ================= diff --git a/src/persist.c b/src/persist.c index dad6830f99..024317a290 100644 --- a/src/persist.c +++ b/src/persist.c @@ -79,6 +79,16 @@ static int mqtt3_db_client_messages_write(struct mosquitto_db *db, FILE *db_fptr cmsg = context->msgs; while(cmsg){ + if(!strncmp(cmsg->store->topic, "$SYS", 4) + && cmsg->store->ref_count <= 1 + && cmsg->store->dest_id_count == 0){ + + /* This $SYS message won't have been persisted, so we can't persist + * this client message. */ + cmsg = cmsg->next; + continue; + } + slen = strlen(context->id); length = htonl(sizeof(dbid_t) + sizeof(uint16_t) + sizeof(uint8_t) + From 97572610c07955ffa8496cf1527023ad3f9e80ad Mon Sep 17 00:00:00 2001 From: YuLun Shih Date: Fri, 21 Apr 2017 16:31:44 +0800 Subject: [PATCH 32/46] Fix bridge->restart_t won't be reset Signed-off-by: YuLun Shih --- src/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loop.c b/src/loop.c index b7e8b752bc..6e9de59fa2 100644 --- a/src/loop.c +++ b/src/loop.c @@ -246,7 +246,7 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li }else{ if((context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect) || (context->bridge->start_type == bst_automatic && now > context->bridge->restart_t)){ - + context->bridge->restart_t = 0; #if defined(__GLIBC__) && defined(WITH_ADNS) if(context->adns){ /* Waiting on DNS lookup */ From 3c8581a3ea90c4bbc5891295509b3849c04c4782 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 5 May 2017 22:09:29 +0100 Subject: [PATCH 33/46] Update changelog. --- ChangeLog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 36a0ba5828..1926302d53 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -4,6 +4,7 @@ Broker: - Fix mosquitto.db from becoming corrupted due to client messages being persisted with no stored message. Closes #424. +- Fix bridge not restarting properly. Closes #428. 1.4.11 - 20170220 ================= From 059ba5f00b18cfa4fe92ed739832c6e97b71802f Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Mon, 17 Apr 2017 13:30:43 +0200 Subject: [PATCH 34/46] Fix use of unitialized memory in gets_quiet Spotted by cppcheck Signed-off-by: Riccardo Magliocchetti --- src/mosquitto_passwd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mosquitto_passwd.c b/src/mosquitto_passwd.c index aa7a81011a..c3dd05ab1c 100644 --- a/src/mosquitto_passwd.c +++ b/src/mosquitto_passwd.c @@ -230,6 +230,7 @@ int gets_quiet(char *s, int len) memset(s, 0, len); h = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(h, &con_orig); + con_quiet = con_orig; con_quiet &= ~ENABLE_ECHO_INPUT; con_quiet |= ENABLE_LINE_INPUT; SetConsoleMode(h, con_quiet); From 5115c84501609cccb9982a1b3f1ee5b4f2ef4be5 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 5 May 2017 22:12:00 +0100 Subject: [PATCH 35/46] Update changelog. --- ChangeLog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 1926302d53..88f221dd7e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -5,6 +5,7 @@ Broker: - Fix mosquitto.db from becoming corrupted due to client messages being persisted with no stored message. Closes #424. - Fix bridge not restarting properly. Closes #428. +- Fix unitialized memory in gets_quiet on Windows. Closes #426. 1.4.11 - 20170220 ================= From 623f082615d66d9837b75dc019054ee7bd250343 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 5 May 2017 22:14:46 +0100 Subject: [PATCH 36/46] Fix typo in readme. Thanks to Ali Utku Selen. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 9515380dff..ec69f8300a 100644 --- a/readme.md +++ b/readme.md @@ -67,7 +67,7 @@ already be built. Use `make binary` to skip building the man pages, or install * c-ares (libc-ares-dev on Debian based systems) - disable with `make WITH_DNS_SRV=no` * libuuid (uuid-dev) - disable with `make WITH_UUID=no` -* libwebsockets (libwebsockets-dev) - enable with `make WITH_LIBWEBSOCKETS=yes` +* libwebsockets (libwebsockets-dev) - enable with `make WITH_WEBSOCKETS=yes` * openssl (libssl-dev on Debian based systems) - disable with `make WITH_TLS=no` ## Credits From 439f39b5daba0de131cc0c28feacea851cf2c08e Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Mon, 3 Apr 2017 20:34:07 +0200 Subject: [PATCH 37/46] Remove -lanl when WITH_ADNS is unset Do not add -lanl to BROKER_LIBS for all Linux builds. Indeed, -lanl is only needed for getaddrinfo_a which is only used in _mosquitto_try_connect_step1 when WITH_ADNS is set Signed-off-by: Fabrice Fontaine --- config.mk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config.mk b/config.mk index 6e369c2349..44639d2391 100644 --- a/config.mk +++ b/config.mk @@ -159,10 +159,6 @@ ifeq ($(UNAME),QNX) LIB_LIBS:=$(LIB_LIBS) -lsocket endif -ifeq ($(UNAME),Linux) - BROKER_LIBS:=$(BROKER_LIBS) -lanl -endif - ifeq ($(WITH_WRAP),yes) BROKER_LIBS:=$(BROKER_LIBS) -lwrap BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_WRAP From 7c0e8fde81875ff257d5fd92a0b08bf7c85f4ef3 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 5 May 2017 22:30:08 +0100 Subject: [PATCH 38/46] Update changelog. --- ChangeLog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 88f221dd7e..dd9de07878 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -6,6 +6,8 @@ Broker: persisted with no stored message. Closes #424. - Fix bridge not restarting properly. Closes #428. - Fix unitialized memory in gets_quiet on Windows. Closes #426. +- Fix building with WITH_ADNS=no for systems that don't use glibc. Closes + #415. 1.4.11 - 20170220 ================= From b92ffec74edbf976a3682e766983cc3bd8ceae0a Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 5 May 2017 22:45:13 +0100 Subject: [PATCH 39/46] Fix documentation type WITH_DNS_SRV. --- ChangeLog.txt | 1 + readme.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index dd9de07878..0fe47b6b06 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,7 @@ Broker: - Fix unitialized memory in gets_quiet on Windows. Closes #426. - Fix building with WITH_ADNS=no for systems that don't use glibc. Closes #415. +- Fixes to readme.md. 1.4.11 - 20170220 ================= diff --git a/readme.md b/readme.md index ec69f8300a..0ae7587f70 100644 --- a/readme.md +++ b/readme.md @@ -65,7 +65,7 @@ already be built. Use `make binary` to skip building the man pages, or install ### Build Dependencies -* c-ares (libc-ares-dev on Debian based systems) - disable with `make WITH_DNS_SRV=no` +* c-ares (libc-ares-dev on Debian based systems) - disable with `make WITH_SRV=no` * libuuid (uuid-dev) - disable with `make WITH_UUID=no` * libwebsockets (libwebsockets-dev) - enable with `make WITH_WEBSOCKETS=yes` * openssl (libssl-dev on Debian based systems) - disable with `make WITH_TLS=no` From ab266e7f5f09ce3140eb7c9628e85cbd1e13d80e Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 3 Apr 2017 21:45:42 +0200 Subject: [PATCH 40/46] lib: fix OpenSSL 1.1 deprecation warning for ERR_remove_state ERR_remove_state has been marked deprecated in OpenSSL 1.1.0 and do nothing, as the OpenSSL libraries now normally do all thread initialization and deinitialisation automatically. Signed-off-by: Jelle van der Waa --- lib/net_mosq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/net_mosq.c b/lib/net_mosq.c index 06c9bce2e9..88160abecc 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -114,7 +114,9 @@ void _mosquitto_net_init(void) void _mosquitto_net_cleanup(void) { #ifdef WITH_TLS - ERR_remove_state(0); + #if OPENSSL_VERSION_NUMBER < 0x10100000L + ERR_remove_state(0); + #endif ENGINE_cleanup(); CONF_modules_unload(1); ERR_free_strings(); From a421d40d42c9edb31ce88579ebb02e264c231f30 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 5 May 2017 22:50:21 +0100 Subject: [PATCH 41/46] Update changelog. --- ChangeLog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 0fe47b6b06..2d5315bc0d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -9,6 +9,8 @@ Broker: - Fix building with WITH_ADNS=no for systems that don't use glibc. Closes #415. - Fixes to readme.md. +- Fix deprecation warning for OpenSSL 1.1. PR #416. + 1.4.11 - 20170220 ================= From ca8a50760714e2f23a5e43536351619d35165afb Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 12 May 2017 22:29:54 +0100 Subject: [PATCH 42/46] [446] Don't segfault on duplicate bridge names. Thanks to Tifaifai Maupiti. Bug: https://github.com/eclipse/mosquitto/issues/446 --- ChangeLog.txt | 1 + src/conf.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 2d5315bc0d..f708d66cc3 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,7 @@ Broker: #415. - Fixes to readme.md. - Fix deprecation warning for OpenSSL 1.1. PR #416. +- Don't segfault on duplicate bridge names. Closes #446. 1.4.11 - 20170220 diff --git a/src/conf.c b/src/conf.c index 9792b2eacb..56ea9ace17 100644 --- a/src/conf.c +++ b/src/conf.c @@ -916,6 +916,14 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char if(reload) continue; // FIXME token = strtok_r(NULL, " ", &saveptr); if(token){ + /* Check for existing bridge name. */ + for(i=0; ibridge_count; i++){ + if(!strcmp(config->bridges[i].name, token)){ + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate bridge name \"%s\".", token); + return MOSQ_ERR_INVAL; + } + } + config->bridge_count++; config->bridges = _mosquitto_realloc(config->bridges, config->bridge_count*sizeof(struct _mqtt3_bridge)); if(!config->bridges){ From c79d48c0c36beb66b3148f38a23caab39e7058a2 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 17 May 2017 14:56:28 +0100 Subject: [PATCH 43/46] JOSS paper. --- doc/joss-paper/codemeta.json | 23 +++++++++++ doc/joss-paper/paper.bib | 77 ++++++++++++++++++++++++++++++++++++ doc/joss-paper/paper.md | 49 +++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 doc/joss-paper/codemeta.json create mode 100644 doc/joss-paper/paper.bib create mode 100644 doc/joss-paper/paper.md diff --git a/doc/joss-paper/codemeta.json b/doc/joss-paper/codemeta.json new file mode 100644 index 0000000000..d23c57f059 --- /dev/null +++ b/doc/joss-paper/codemeta.json @@ -0,0 +1,23 @@ +{ + "@context": "https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld", + "@type": "Code", + "author": [ + { + "@id": "http://orcid.org/0000-0001-9218-7797", + "@type": "Person", + "email": "", + "name": "Roger A. Light", + "affiliation": "" + } + ], + "identifier": "", + "codeRepository": "https://github.com/eclipse/mosquitto", + "datePublished": "2017-05-17", + "dateModified": "2017-05-17", + "dateCreated": "2017-05-17", + "description": "Broker and client implementation of the MQTT protocol.", + "keywords": "IoT, MQTT, messaging, pubsub", + "license": "EPL 2.0 / EDL 2.0", + "title": "Mosquitto", + "version": "v1.4.11" +} \ No newline at end of file diff --git a/doc/joss-paper/paper.bib b/doc/joss-paper/paper.bib new file mode 100644 index 0000000000..9bdb921cf4 --- /dev/null +++ b/doc/joss-paper/paper.bib @@ -0,0 +1,77 @@ +@inproceedings{Schulz_2014, + title = {Real-time animation of equipment in a remote laboratory}, + doi = {10.1109/REV.2014.6784247}, + booktitle = {2014 11th {International} {Conference} on {Remote} {Engineering} and {Virtual} {Instrumentation} ({REV})}, + author = {Schulz, M. and Chen, F. and Payne, L.}, + month = feb, + year = {2014}, + keywords = {Animation, cameras, client-server systems, computer aided instruction, computer animation, Computer architecture, data path, data streaming, Electron tubes, Engines, equipment animation, Hardware, message server, MIT iLabs shared architecture, MQTT, real-time animation, real-time systems, remote laboratory, servers, software architecture, student experiments, webcam}, + pages = {172--176} +} + +@inproceedings{Antonic_2015, + title = {Comparison of the {CUPUS} middleware and {MQTT} protocol for smart city services}, + doi = {10.1109/ConTEL.2015.7231225}, + booktitle = {2015 13th {International} {Conference} on {Telecommunications} ({Con}TEL)}, + author = {Antonić, A. and Marjanović, M. and Skočir, P. and Žarko, I. P.}, + month = jul, + year = {2015}, + keywords = {cloud-based publish-subscribe middleware, cloud computing, CUPUS middleware, Engines, FP7 project OpenIoT platform, Internet of Things, IoT services, message passing, message queue telemetry transport protocol, message queuing solutions, middleware, Mobile communication, mobile computing, mobile devices, Mobile handsets, MQTT protocol, open-source cloud platform, Protocols, public domain software, sensors, smart cities, smart city services, telemetry, transport protocols, wearable sensors, wireless sensor networks, WSNs}, + pages = {1--8} +} + +@inproceedings{Thangavel_2014, + title = {Performance evaluation of {MQTT} and {CoAP} via a common middleware}, + doi = {10.1109/ISSNIP.2014.6827678}, + booktitle = {2014 {IEEE} {Ninth} {International} {Conference} on {Intelligent} {Sensors}, {Sensor} {Networks} and {Information} {Processing} ({ISSNIP})}, + author = {Thangavel, D. and Ma, X. and Valera, A. and Tan, H. X. and Tan, C. K. Y.}, + month = apr, + year = {2014}, + keywords = {bandwidth consumption, CoAP, constrained application protocol, data transmission, delays, end-to-end delay, gateways, internetworking, Logic gates, message queue telemetry transport, middleware, MQTT, Packet loss, Protocols, Quality of service, queueing theory, sensor nodes, servers, wireless sensor networks}, + pages = {1--6} +} + +@inproceedings{Kang_2017, + title = {Room {Temperature} {Control} and {Fire} {Alarm} \#x002F;{Suppression} {IoT} {Service} {Using} {MQTT} on {AWS}}, + doi = {10.1109/PlatCon.2017.7883724}, + abstract = {In this paper we build an MQTT(Message Queue Telemetry Transportation) broker on Amazon Web Service(AWS). The MQTT broker has been utilized as a platform to provide the Internet of Things(IoT) services which monitor and control room temperatures, and sense, alarm, and suppress fire. Arduino was used as the IoT end device connecting sensors and actuators to the platform via Wi-Fi channel. We created smart home scenario and designed IoT massages satisfying the scenario requirement. We also implemented the smart some system in hardware and software, and verified the system operation. We show that MQTT and AWS are good technical candidates for small IoT business applications.}, + booktitle = {2017 {International} {Conference} on {Platform} {Technology} and {Service} ({PlatCon})}, + author = {Kang, D. H. and Park, M. S. and Kim, H. S. and Kim, D. y and Kim, S. H. and Son, H. J. and Lee, S. G.}, + month = feb, + year = {2017}, + note = {00000}, + keywords = {Actuators, Amazon web service, AWS, electronic messaging, fire alarm-suppression IoT service, fires, Internet of Things, Internet of Things services, message queue telemetry transportation, MQTT broker, queueing theory, room temperature control, room temperature monitoring, sensors, small IoT business applications, smart home scenario, smart some system, telemetry, temperature 293 K to 298 K, Web services, Wi-Fi channel, wireless LAN}, + pages = {1--5} +} + +@inproceedings{Fremantle_2014, + title = {Federated {Identity} and {Access} {Management} for the {Internet} of {Things}}, + doi = {10.1109/SIoT.2014.8}, + abstract = {We examine the use of Federated Identity and Access Management (FIAM) approaches for the Internet of Things (IoT). We look at specific challenges that devices, sensors and actuators have, and look for approaches to address them. OAuth is a widely deployed protocol – built on top of HTTP – for applying FIAM to Web systems. We explore the use of OAuth for IoT systems that instead use the lightweight MQTT 3.1 protocol. In order to evaluate this area, we built a prototype that uses OAuth 2.0 to enable access control to information distributed via MQTT. We evaluate the results of this prototyping activity, and assess the strengths and weaknesses of this approach, and the benefits of using the FIAM approaches with IoT and Machine to Machine (M2M) scenarios. Finally we outline areas for further research.}, + booktitle = {2014 {International} {Workshop} on {Secure} {Internet} of {Things}}, + author = {Fremantle, P. and Aziz, B. and Kopecký, J. and Scott, P.}, + month = sep, + year = {2014}, + note = {00026}, + keywords = {access control, Authentication, authorisation, Authorization, federated identity and access management, FIAM, Hip, Internet of Things, IoT, M2M scenarios, machine to machine scenarios, MQTT 3.1 protocol, OAuth 2.0, Protocols, servers}, + pages = {10--17} +} + +@article{Bellavista_2017, + title = {The {PeRvasive} {Environment} {Sensing} and {Sharing} {Solution}}, + volume = {9}, + copyright = {http://creativecommons.org/licenses/by/3.0/}, + url = {http://www.mdpi.com/2071-1050/9/4/585}, + doi = {10.3390/su9040585}, + abstract = {to stimulate better user behavior and improve environmental and economic sustainability, it is of paramount importance to make citizens effectively aware of the quality of the environment in which they live every day. in particular, we claim that users could significantly benefit from cost-effective efficient internet-of-things (iot) solutions that provide them with up-to-date live information about air pollution in the areas where they live, suitably adapted to different situations and with different levels of dynamically selected granularities (e.g., at home/district/city levels). our pervasive environment sensing and sharing (press) project has the ambition of increasing users’ awareness of the natural environment they live in, as a first step towards improved sustainability; the primary target is the efficient provisioning of real-time user-centric information about environmental conditions in the surroundings, and in particular about air pollution. to this purpose, we have designed, implemented, and thoroughly evaluated the press framework, which is capable of achieving good flexibility and scalability while integrating heterogeneous monitoring data, ranging from sensed air pollution to user-provided quality perceptions. among the elements of technical originality, press exploits extended kura iot gateways with novel congestion detection and recovery mechanisms that allow us to optimize bandwidth allocation between in-the-field press components and the cloud. the reported performance results show the feasibility of the proposed solution, by pointing out not only the scalability and efficiency of the adopted message-based solution that uses message queue telemetry transport (mqtt) and websockets, but also the capability of press to quickly identify and manage traffic congestions, thus, ensuring good quality levels to final users.}, + language = {en}, + number = {4}, + urldate = {2017-05-17}, + journal = {sustainability}, + author = {Bellavista, Paolo and Giannelli, Carlo and Zamagna, Riccardo}, + month = apr, + year = {2017}, + note = {00000}, + keywords = {dynamic extensibility, environmental monitoring, heterogeneous monitoring data, mqtt, scalability, traffic congestion management, websockets}, + pages = {585} +} diff --git a/doc/joss-paper/paper.md b/doc/joss-paper/paper.md new file mode 100644 index 0000000000..ce08ced3bc --- /dev/null +++ b/doc/joss-paper/paper.md @@ -0,0 +1,49 @@ +--- +title: 'Mosquitto: server and client implementation of the MQTT protocol' +tags: + - Internet of Things + - MQTT + - Pubsub + - Messaging +authors: + - name: Roger A Light + orcid: 0000-0001-9218-7797 +date: 17 May 2017 +bibliography: paper.bib +--- + +# Summary + +Mosquitto provides standards compliant server and client implementations of the +[MQTT](http://mqtt.org/) messaging protocol. MQTT uses a publish/subscribe +model, has low network overhead and can be implemented on low power devices +such microcontrollers that might be used in remote Internet of Things sensors. +As such, Mosquitto is intended for use in all situations where there is a need +for lightweight messaging, particularly on constrained devices with limited +resources. + +The Mosquitto project is a member of the [Eclipse Foundation](http://eclipse.org/) + +There are three parts to the project. + +* The main `mosquitto` server +* The `mosquitto_pub` and `mosquitto_sub` client utilities that are one method of communicating with an MQTT server +* An MQTT client library written in C, with a C++ wrapper + +Mosquitto allows research directly related to the MQTT protocol itself, such as +comparing the performance of MQTT and the Constrained Application Protocol +(CoAP) [@Thangavel_2014] or investigating the use of OAuth in MQTT +[@Fremantle_2014]. Mosquitto supports other research activities as a useful +block for building larger systems and has been used to evaluate MQTT for use in +Smart City Services [@Antonic_2015], and in the development of an environmental +monitoring system [@Bellavista_2017]. Mosquitto has also been used to support +research less directly as part of a scheme for remote control of an experiment +[@Schulz_2014]. + +Outside of academia, Mosquitto is used in other open source projects such as +the [openHAB](http://www.openhab.org/) home automation project and +[OwnTracks](http://owntracks.org/), the personal location tracking project, and +has been integrated into commercial products. + +# References + From 15b8140f900efecaea617441d7880f4c642b1097 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 23 May 2017 16:46:41 +0100 Subject: [PATCH 44/46] Update openssl for appveyor. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 65683db286..d2cdc5e15d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,7 @@ os: Visual Studio 2013 environment: CMAKE_ARGS: -DCMAKE_BUILD_TYPE=Release NSIS_ROOT: C:\nsis - SSL_VER: 1_0_2h + SSL_VER: 1_0_2k configuration: - Release From 9af3c6958fe1b2c653a7952f6f144bcf6ecfbc0d Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 25 May 2017 21:56:06 +0100 Subject: [PATCH 45/46] Fix for CVE-2017-7650. --- ChangeLog.txt | 10 ++++++++++ src/security.c | 15 +++++++++++++++ src/security_default.c | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index f708d66cc3..eb4f98898d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,15 @@ 1.4.12 - 201703xx ================= +Security: +- Fix CVE-2017-7650, which allows clients with username or client id set to + '#' or '+' to bypass pattern based ACLs or third party plugins. The fix + denies message sending or receiving of messages for clients with a '#' or + '+' in their username or client id and if the message is subject to a + pattern ACL check or plugin check. + Patches for other versions are available at + https://mosquitto.org/files/cve/2017-7650/ + Broker: - Fix mosquitto.db from becoming corrupted due to client messages being persisted with no stored message. Closes #424. @@ -11,6 +20,7 @@ Broker: - Fixes to readme.md. - Fix deprecation warning for OpenSSL 1.1. PR #416. - Don't segfault on duplicate bridge names. Closes #446. +- Fix CVE-2017-7650. 1.4.11 - 20170220 diff --git a/src/security.c b/src/security.c index 6ae9fb9c5d..d0c376bd56 100644 --- a/src/security.c +++ b/src/security.c @@ -233,6 +233,21 @@ int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, cons { username = context->username; } + + /* Check whether the client id or username contains a +, # or / and if + * so deny access. + * + * Do this check for every message regardless, we have to protect the + * plugins against possible pattern based attacks. + */ + if(username && strpbrk(username, "+#/")){ + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous username \"%s\"", username); + return MOSQ_ERR_ACL_DENIED; + } + if(context->id && strpbrk(context->id, "+#/")){ + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous client id \"%s\"", context->id); + return MOSQ_ERR_ACL_DENIED; + } return db->auth_plugin.acl_check(db->auth_plugin.user_data, context->id, username, topic, access); } } diff --git a/src/security_default.c b/src/security_default.c index 64ca846b26..a41c21f47a 100644 --- a/src/security_default.c +++ b/src/security_default.c @@ -261,6 +261,26 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte } acl_root = db->acl_patterns; + + if(acl_root){ + /* We are using pattern based acls. Check whether the username or + * client id contains a +, # or / and if so deny access. + * + * Without this, a malicious client may configure its username/client + * id to bypass ACL checks (or have a username/client id that cannot + * publish or receive messages to its own place in the hierarchy). + */ + if(context->username && strpbrk(context->username, "+#/")){ + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous username \"%s\"", context->username); + return MOSQ_ERR_ACL_DENIED; + } + + if(context->id && strpbrk(context->id, "+#/")){ + _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous client id \"%s\"", context->id); + return MOSQ_ERR_ACL_DENIED; + } + } + /* Loop through all pattern ACLs. */ clen = strlen(context->id); while(acl_root){ From 2897f71aba79a082accc5583d9dcb3b50ec5dda6 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Sun, 28 May 2017 21:53:19 +0100 Subject: [PATCH 46/46] Bump version number. --- CMakeLists.txt | 2 +- ChangeLog.txt | 2 +- config.mk | 2 +- installer/mosquitto-cygwin.nsi | 2 +- installer/mosquitto.nsi | 2 +- lib/mosquitto.h | 2 +- set-version.sh | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b0f29a2d3f..f8eac48a96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ project(mosquitto) cmake_minimum_required(VERSION 2.8) # Only for version 3 and up. cmake_policy(SET CMP0042 NEW) -set (VERSION 1.4.11) +set (VERSION 1.4.12) if (WIN32) execute_process(COMMAND cmd /c echo %DATE% %TIME% OUTPUT_VARIABLE TIMESTAMP diff --git a/ChangeLog.txt b/ChangeLog.txt index eb4f98898d..75ca22f0b2 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,4 +1,4 @@ -1.4.12 - 201703xx +1.4.12 - 20170528 ================= Security: diff --git a/config.mk b/config.mk index 44639d2391..7f7491bed5 100644 --- a/config.mk +++ b/config.mk @@ -86,7 +86,7 @@ WITH_SOCKS:=yes # Also bump lib/mosquitto.h, CMakeLists.txt, # installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi -VERSION=1.4.11 +VERSION=1.4.12 TIMESTAMP:=$(shell date "+%F %T%z") # Client library SO version. Bump if incompatible API/ABI changes are made. diff --git a/installer/mosquitto-cygwin.nsi b/installer/mosquitto-cygwin.nsi index 1567c73b7b..9860230d16 100644 --- a/installer/mosquitto-cygwin.nsi +++ b/installer/mosquitto-cygwin.nsi @@ -7,7 +7,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "mosquitto" -!define VERSION 1.4.11 +!define VERSION 1.4.12 OutFile "mosquitto-${VERSION}-install-cygwin.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi index 4afe737be4..a599dba620 100644 --- a/installer/mosquitto.nsi +++ b/installer/mosquitto.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "mosquitto" -!define VERSION 1.4.11 +!define VERSION 1.4.12 OutFile "mosquitto-${VERSION}-install-win32.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 43e1f15fe3..c106618da0 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -45,7 +45,7 @@ extern "C" { #define LIBMOSQUITTO_MAJOR 1 #define LIBMOSQUITTO_MINOR 4 -#define LIBMOSQUITTO_REVISION 11 +#define LIBMOSQUITTO_REVISION 12 /* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */ #define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION) diff --git a/set-version.sh b/set-version.sh index 75c0b5299c..ee81183d3e 100755 --- a/set-version.sh +++ b/set-version.sh @@ -2,7 +2,7 @@ MAJOR=1 MINOR=4 -REVISION=11 +REVISION=12 sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk