Merge remote-tracking branch 'origin/fixes' into develop

pull/1865/head
Roger A. Light 5 years ago
commit c90e49af1b

@ -1,8 +1,18 @@
Thank you for contributing your time to the Mosquitto project!
Before you go any further, please note that we cannot accept contributions if
you haven't signed the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/ECA.php).
If you aren't able to do that, or just don't want to, please describe your bug
fix/feature change in an issue. For simple bug fixes it is can be just as easy
for us to be told about the problem and then go fix it directly.
Then please check the following list of things we ask for in your pull request:
- [ ] Have you signed the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/ECA.php), using the same email address as you used in your commits?
- [ ] Do each of your commits have a "Signed-off-by" line, with the correct email address? Use "git commit -s" to generate this line for you.
- [ ] If you are contributing a new feature, is your work based off the develop branch?
- [ ] If you are contributing a bugfix, is your work based off the fixes branch?
- [ ] Have you added an explanation of what your changes do and why you'd like us to include them?
- [ ] Have you successfully run `make test` with your changes locally?
- [ ] Have you signed the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/ECA.php), using the same email address as you used in your commits?
- [ ] Do each of your commits have a "Signed-off-by" line, with the correct email address? Use "git commit -s" to generate this line for you.
-----

@ -0,0 +1,19 @@
name: "Synchronise Coverity Scan branches on a weekly basis"
on:
workflow_dispatch:
schedule:
- cron: "7 3 * * 0"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- run: |
git checkout -b coverity-fixes origin/fixes
git push origin coverity-fixes
git checkout -b coverity-develop origin/develop
git push origin coverity-develop

@ -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.6.9)
set (VERSION 1.6.12)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
@ -24,6 +24,7 @@ endif (WIN32)
include(GNUInstallDirs)
option(WITH_BUNDLED_DEPS "Build with bundled dependencies?" ON)
option(WITH_TLS
"Include SSL/TLS support?" ON)
option(WITH_TLS_PSK

@ -67,6 +67,9 @@ Client library:
sockets. Closes #1526.
- Add `mosquitto_ssl_get()` to allow clients to access their SSL structure and
perform additional verification.
- Fix send quota being incorrecly reset on reconnect. Closes #1822.
- Don't use logging until log mutex is initialised. Closes #1819.
- Fix missing mach/mach_time.h header on OS X. Closes #1831.
Clients:
- Add timeout return code (27) for `mosquitto_sub -W <secs>` and
@ -94,6 +97,105 @@ Clients:
- Add `--version` for all clients.
1.6.12 - 2020-08-19
===================
Security:
- In some circumstances, Mosquitto could leak memory when handling PUBLISH
messages. This is limited to incoming QoS 2 messages, and is related
to the combination of the broker having persistence enabled, a clean
session=false client, which was connected prior to the broker restarting,
then has reconnected and has now sent messages at a sufficiently high rate
that the incoming queue at the broker has filled up and hence messages are
being dropped. This is more likely to have an effect where
max_queued_messages is a small value. This has now been fixed. Closes #1793.
Broker:
- Build warning fixes when building with WITH_BRIDGE=no and WITH_TLS=no.
Clients:
- All clients exit with an error exit code on CONNACK failure. Closes #1778.
- Don't busy loop with `mosquitto_pub -l` on a slow connection.
1.6.11 - 2020-08-11
===================
Security:
- On Windows the Mosquitto service was being installed without appropriate
path quoting, this has been fixed.
Broker:
- Fix usage message only mentioning v3.1.1. Closes #1713.
- Fix broker refusing to start if only websockets listeners were defined.
Closes #1740.
- Change systemd unit files to create /var/log/mosquitto before starting.
Closes #821.
- Don't quit with an error if opening the log file isn't possible.
Closes #821.
- Fix bridge topic remapping when using "" as the topic. Closes #1749.
- Fix messages being queued for disconnected bridges when clean start was
set to true. Closes #1729.
- Fix `autosave_interval` not being triggered by messages being delivered.
Closes #1726.
- Fix websockets clients sometimes not being disconnected promptly.
Closes #1718.
- Fix "slow" file based logging by switching to line based buffering.
Closes #1689. Closes #1741.
- Log protocol error message where appropriate from a bad UNSUBSCRIBE, rather
than the generic "socket error".
- Don't try to start DLT logging if DLT unavailable, to avoid a long delay
when shutting down the broker. Closes #1735.
- Fix potential memory leaks. Closes #1773. Closes #1774.
- Fix clients not receiving messages after a previous client with the same
client ID and positive will delay interval quit. Closes #1752.
- Fix overly broad HAVE_PTHREAD_CANCEL compile guard. Closes #1547.
Client library:
- Improved documentation around connect callback return codes. Close #1730.
- Fix `mosquitto_publish*()` no longer returning `MOSQ_ERR_NO_CONN` when not
connected. Closes #1725.
- `mosquitto_loop_start()` now sets a thread name on Linux, FreeBSD, NetBSD,
and OpenBSD. Closes #1777.
- Fix `mosquitto_loop_stop()` not stopping on Windows. Closes #1748. Closes #117.
1.6.10 - 2020-05-25
===================
Broker:
- Report invalid bridge prefix+pattern combinations at config parsing time
rather than letting the bridge fail later. Issue #1635.
- Fix `mosquitto_passwd -b` not updating passwords for existing users
correctly. Creating a new user with `-b` worked without problem.
Closes #1664.
- Fix memory leak when connecting clients rejected.
- Don't disconnect clients that are already disconnected. This prevents the
session expiry being extended on SIGHUP. Closes #1521.
- Fix support for openssl 3.0.
- Fix check when loading persistence file of a different version than the
native version. Closes #1684.
- Fix possible assert crash associated with bridge reconnecting when compiled
without epoll support. Closes #1700.
Client library:
- Don't treat an unexpected PUBACK, PUBREL, or PUBCOMP as a fatal error.
Issue #1629.
- Fix support for openssl 3.0.
- Fix memory leaks from multiple calls to
`mosquitto_lib_init()`/`mosquitto_lib_cleanup()`. Closes #1691.
- Fix documentation on return code of `mosquitto_lib_init()` for Windows.
Closes #1690.
Clients:
- Fix mosquitto_sub %j or %J not working on Windows. Closes #1674.
Build:
- Various fixes for building with <C99 support. Closes #1622.
- Fix use of sed on BSD. Closes #1614.
>>>>>>> fixes
1.6.9 - 20200227
================

@ -110,7 +110,6 @@ sign : dist
copy : sign
cd dist; scp mosquitto-${VERSION}.tar.gz mosquitto-${VERSION}.tar.gz.asc mosquitto:site/mosquitto.org/files/source/
cd dist; scp *.html mosquitto:site/mosquitto.org/man/
scp ChangeLog.txt mosquitto:site/mosquitto.org/
coverage :

@ -65,6 +65,8 @@ int cfg_parse_property(struct mosq_config *cfg, int argc, char *argv[], int *idx
int cmd, identifier, type;
mosquitto_property **proplist;
int rc;
long tmpl;
size_t szt;
/* idx now points to "command" */
if((*idx)+2 > argc-1){
@ -161,19 +163,44 @@ int cfg_parse_property(struct mosq_config *cfg, int argc, char *argv[], int *idx
switch(type){
case MQTT_PROP_TYPE_BYTE:
rc = mosquitto_property_add_byte(proplist, identifier, atoi(value));
tmpl = atol(value);
if(tmpl < 0 || tmpl > UINT8_MAX){
fprintf(stderr, "Error: Property value (%ld) out of range for property %s.\n\n", tmpl, propname);
return MOSQ_ERR_INVAL;
}
rc = mosquitto_property_add_byte(proplist, identifier, (uint8_t )tmpl);
break;
case MQTT_PROP_TYPE_INT16:
rc = mosquitto_property_add_int16(proplist, identifier, atoi(value));
tmpl = atol(value);
if(tmpl < 0 || tmpl > UINT16_MAX){
fprintf(stderr, "Error: Property value (%ld) out of range for property %s.\n\n", tmpl, propname);
return MOSQ_ERR_INVAL;
}
rc = mosquitto_property_add_int16(proplist, identifier, (uint16_t )tmpl);
break;
case MQTT_PROP_TYPE_INT32:
rc = mosquitto_property_add_int32(proplist, identifier, atoi(value));
tmpl = atol(value);
if(tmpl < 0 || tmpl > UINT32_MAX){
fprintf(stderr, "Error: Property value (%ld) out of range for property %s.\n\n", tmpl, propname);
return MOSQ_ERR_INVAL;
}
rc = mosquitto_property_add_int32(proplist, identifier, (uint32_t )tmpl);
break;
case MQTT_PROP_TYPE_VARINT:
rc = mosquitto_property_add_varint(proplist, identifier, atoi(value));
tmpl = atol(value);
if(tmpl < 0 || tmpl > UINT32_MAX){
fprintf(stderr, "Error: Property value (%ld) out of range for property %s.\n\n", tmpl, propname);
return MOSQ_ERR_INVAL;
}
rc = mosquitto_property_add_varint(proplist, identifier, (uint32_t )tmpl);
break;
case MQTT_PROP_TYPE_BINARY:
rc = mosquitto_property_add_binary(proplist, identifier, value, strlen(value));
szt = strlen(value);
if(szt > UINT16_MAX){
fprintf(stderr, "Error: Property value too long for property %s.\n\n", propname);
return MOSQ_ERR_INVAL;
}
rc = mosquitto_property_add_binary(proplist, identifier, value, (uint16_t )szt);
break;
case MQTT_PROP_TYPE_STRING:
rc = mosquitto_property_add_string(proplist, identifier, value);

@ -45,7 +45,7 @@ static int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int
static int check_format(const char *str)
{
int i;
int len;
size_t len;
len = strlen(str);
for(i=0; i<len; i++){
@ -268,7 +268,7 @@ int client_config_load(struct mosq_config *cfg, int pub_or_sub, int argc, char *
char line[1024];
int count;
char *loc = NULL;
int len;
size_t len;
char *args[3];
#ifndef WIN32
@ -418,7 +418,7 @@ int client_config_load(struct mosq_config *cfg, int pub_or_sub, int argc, char *
fprintf(stderr, "Error: You must provide a client id if you are using an infinite session expiry interval.\n");
return 1;
}
rc = mosquitto_property_add_int32(&cfg->connect_props, MQTT_PROP_SESSION_EXPIRY_INTERVAL, cfg->session_expiry_interval);
rc = mosquitto_property_add_int32(&cfg->connect_props, MQTT_PROP_SESSION_EXPIRY_INTERVAL, (uint32_t )cfg->session_expiry_interval);
if(rc){
fprintf(stderr, "Error adding property session-expiry-interval\n");
}
@ -481,7 +481,7 @@ int client_config_load(struct mosq_config *cfg, int pub_or_sub, int argc, char *
int cfg_add_topic(struct mosq_config *cfg, int type, char *topic, const char *arg)
{
if(mosquitto_validate_utf8(topic, strlen(topic))){
if(mosquitto_validate_utf8(topic, (int )strlen(topic))){
fprintf(stderr, "Error: Malformed UTF-8 in %s argument.\n\n", arg);
return 1;
}
@ -503,7 +503,7 @@ int cfg_add_topic(struct mosq_config *cfg, int type, char *topic, const char *ar
return 1;
}
cfg->topic_count++;
cfg->topics = realloc(cfg->topics, cfg->topic_count*sizeof(char *));
cfg->topics = realloc(cfg->topics, (size_t )cfg->topic_count*sizeof(char *));
if(!cfg->topics){
err_printf(cfg, "Error: Out of memory.\n");
return 1;
@ -517,7 +517,9 @@ int cfg_add_topic(struct mosq_config *cfg, int type, char *topic, const char *ar
int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, char *argv[])
{
int i;
int tmpi;
float f;
size_t szt;
for(i=1; i<argc; i++){
if(!strcmp(argv[i], "-A")){
@ -784,7 +786,16 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
return 1;
}else{
cfg->message = strdup(argv[i+1]);
cfg->msglen = strlen(cfg->message);
if(cfg->message == NULL){
fprintf(stderr, "Error: Out of memory.\n\n");
return 1;
}
szt = strlen(cfg->message);
if(szt > MQTT_MAX_PAYLOAD){
fprintf(stderr, "Error: Message length must be less than %u bytes.\n\n", MQTT_MAX_PAYLOAD);
return 1;
}
cfg->msglen = (int )szt;
cfg->pub_mode = MSGMODE_CMD;
}
i++;
@ -793,7 +804,12 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
fprintf(stderr, "Error: -M argument given but max_inflight not specified.\n\n");
return 1;
}else{
cfg->max_inflight = atoi(argv[i+1]);
tmpi = atoi(argv[i+1]);
if(tmpi < 1){
fprintf(stderr, "Error: Maximum inflight messages must be greater than 0.\n\n");
return 1;
}
cfg->max_inflight = (unsigned int )tmpi;
}
i++;
}else if(!strcmp(argv[i], "--nodelay")){
@ -936,13 +952,13 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
fprintf(stderr, "Error: --repeat-delay argument given but no time specified.\n\n");
return 1;
}else{
f = atof(argv[i+1]);
f = (float )atof(argv[i+1]);
if(f < 0.0f){
fprintf(stderr, "Error: --repeat-delay argument must be >=0.0.\n\n");
return 1;
}
f *= 1.0e6;
cfg->repeat_delay.tv_sec = (int)f/1e6;
f *= 1.0e6f;
cfg->repeat_delay.tv_sec = (int)f/1000000;
cfg->repeat_delay.tv_usec = (int)f%1000000;
}
i++;
@ -987,7 +1003,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
fprintf(stderr, "Error: -T argument given but no topic filter specified.\n\n");
return 1;
}else{
if(mosquitto_validate_utf8(argv[i+1], strlen(argv[i+1]))){
if(mosquitto_validate_utf8(argv[i+1], (int )strlen(argv[i+1]))){
fprintf(stderr, "Error: Malformed UTF-8 in -T argument.\n\n");
return 1;
}
@ -996,7 +1012,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
return 1;
}
cfg->filter_out_count++;
cfg->filter_outs = realloc(cfg->filter_outs, cfg->filter_out_count*sizeof(char *));
cfg->filter_outs = realloc(cfg->filter_outs, (size_t )cfg->filter_out_count*sizeof(char *));
if(!cfg->filter_outs){
fprintf(stderr, "Error: Out of memory.\n");
return 1;
@ -1046,7 +1062,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
fprintf(stderr, "Error: -U argument given but no unsubscribe topic specified.\n\n");
return 1;
}else{
if(mosquitto_validate_utf8(argv[i+1], strlen(argv[i+1]))){
if(mosquitto_validate_utf8(argv[i+1], (int )strlen(argv[i+1]))){
fprintf(stderr, "Error: Malformed UTF-8 in -U argument.\n\n");
return 1;
}
@ -1055,7 +1071,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
return 1;
}
cfg->unsub_topic_count++;
cfg->unsub_topics = realloc(cfg->unsub_topics, cfg->unsub_topic_count*sizeof(char *));
cfg->unsub_topics = realloc(cfg->unsub_topics, (size_t )cfg->unsub_topic_count*sizeof(char *));
if(!cfg->unsub_topics){
fprintf(stderr, "Error: Out of memory.\n");
return 1;
@ -1112,11 +1128,12 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
fprintf(stderr, "Error: -W argument given but no timeout specified.\n\n");
return 1;
}else{
cfg->timeout = atoi(argv[i+1]);
if(cfg->timeout < 1){
fprintf(stderr, "Error: Invalid timeout \"%d\".\n\n", cfg->msg_count);
tmpi = atoi(argv[i+1]);
if(tmpi < 1){
fprintf(stderr, "Error: Invalid timeout \"%d\".\n\n", tmpi);
return 1;
}
cfg->timeout = (unsigned int )tmpi;
}
i++;
}
@ -1126,7 +1143,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
return 1;
}else{
cfg->will_payload = strdup(argv[i+1]);
cfg->will_payloadlen = strlen(cfg->will_payload);
cfg->will_payloadlen = (int )strlen(cfg->will_payload);
}
i++;
}else if(!strcmp(argv[i], "--will-qos")){
@ -1148,7 +1165,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
return 1;
}else{
if(mosquitto_validate_utf8(argv[i+1], strlen(argv[i+1]))){
if(mosquitto_validate_utf8(argv[i+1], (int )strlen(argv[i+1]))){
fprintf(stderr, "Error: Malformed UTF-8 in --will-topic argument.\n\n");
return 1;
}
@ -1359,7 +1376,7 @@ int client_connect(struct mosquitto *mosq, struct mosq_config *cfg)
static int mosquitto__urldecode(char *str)
{
int i, j;
int len;
size_t len;
if(!str) return 0;
if(!strchr(str, '%')) return 0;

@ -53,7 +53,7 @@ struct mosq_config {
int pub_mode; /* pub, rr */
char *file_input; /* pub, rr */
char *message; /* pub, rr */
long msglen; /* pub, rr */
int msglen; /* pub, rr */
char *topic; /* pub, rr */
char *bind_address;
int repeat_count; /* pub */
@ -68,7 +68,7 @@ struct mosq_config {
char *password;
char *will_topic;
char *will_payload;
long will_payloadlen;
int will_payloadlen;
int will_qos;
bool will_retain;
#ifdef WITH_TLS
@ -104,7 +104,7 @@ struct mosq_config {
int msg_count; /* sub */
char *format; /* sub, rr */
bool pretty; /* sub, rr */
int timeout; /* sub */
unsigned int timeout; /* sub */
int sub_opts; /* sub */
long session_expiry_interval;
int random_filter; /* sub */

@ -46,6 +46,7 @@ static bool disconnect_sent = false;
static int publish_count = 0;
static bool ready_for_repeat = false;
static volatile int status = STATUS_CONNECTING;
static int connack_result = 0;
#ifdef WIN32
static uint64_t next_publish_tv;
@ -76,7 +77,7 @@ static void set_repeat_time(void)
next_publish_tv.tv_sec += cfg.repeat_delay.tv_sec;
next_publish_tv.tv_usec += cfg.repeat_delay.tv_usec;
next_publish_tv.tv_sec += next_publish_tv.tv_usec/1e6;
next_publish_tv.tv_sec += next_publish_tv.tv_usec/1000000;
next_publish_tv.tv_usec = next_publish_tv.tv_usec%1000000;
}
@ -129,6 +130,8 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag
UNUSED(flags);
UNUSED(properties);
connack_result = result;
if(!result){
switch(cfg.pub_mode){
case MSGMODE_CMD:
@ -217,7 +220,7 @@ void my_publish_callback(struct mosquitto *mosq, void *obj, int mid, int reason_
int pub_shared_init(void)
{
line_buf = malloc(line_buf_len);
line_buf = malloc((size_t )line_buf_len);
if(!line_buf){
err_printf(&cfg, "Error: Out of memory.\n");
return 1;
@ -238,11 +241,22 @@ int pub_stdin_line_loop(struct mosquitto *mosq)
mosquitto_loop_start(mosq);
stdin_finished = false;
do{
if(status == STATUS_CONNECTING){
#ifdef WIN32
Sleep(100);
#else
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 100000000;
nanosleep(&ts, NULL);
#endif
}
if(status == STATUS_CONNACK_RECVD){
pos = 0;
read_len = line_buf_len;
while(status == STATUS_CONNACK_RECVD && fgets(&line_buf[pos], read_len, stdin)){
buf_len_actual = strlen(line_buf);
buf_len_actual = (int )strlen(line_buf);
if(line_buf[buf_len_actual-1] == '\n'){
line_buf[buf_len_actual-1] = '\0';
rc = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain);
@ -256,7 +270,7 @@ int pub_stdin_line_loop(struct mosquitto *mosq)
line_buf_len += 1024;
pos += 1023;
read_len = 1024;
buf2 = realloc(line_buf, line_buf_len);
buf2 = realloc(line_buf, (size_t )line_buf_len);
if(!buf2){
err_printf(&cfg, "Error: Out of memory.\n");
return MOSQ_ERR_NOMEM;
@ -319,7 +333,7 @@ int pub_other_loop(struct mosquitto *mosq)
int loop_delay = 1000;
if(cfg.repeat_count > 1 && (cfg.repeat_delay.tv_sec == 0 || cfg.repeat_delay.tv_usec != 0)){
loop_delay = cfg.repeat_delay.tv_usec / 2000;
loop_delay = (int )cfg.repeat_delay.tv_usec / 2000;
}
do{
@ -584,7 +598,11 @@ int main(int argc, char *argv[])
if(rc){
err_printf(&cfg, "Error: %s\n", mosquitto_strerror(rc));
}
return rc;
if(connack_result){
return connack_result;
}else{
return rc;
}
cleanup:
mosquitto_lib_cleanup();

@ -50,7 +50,7 @@ void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *s
int load_stdin(void)
{
long pos = 0, rlen;
size_t pos = 0, rlen;
char buf[1024];
char *aux_message = NULL;
@ -70,7 +70,12 @@ int load_stdin(void)
memcpy(&(cfg.message[pos]), buf, rlen);
pos += rlen;
}
cfg.msglen = pos;
if(pos > MQTT_MAX_PAYLOAD){
err_printf(&cfg, "Error: Message length must be less than %u bytes.\n\n", MQTT_MAX_PAYLOAD);
free(cfg.message);
return 1;
}
cfg.msglen = (int )pos;
if(!cfg.msglen){
err_printf(&cfg, "Error: Zero length input.\n");
@ -82,8 +87,9 @@ int load_stdin(void)
int load_file(const char *filename)
{
long pos, rlen;
size_t pos, rlen;
FILE *fptr = NULL;
long flen;
fptr = fopen(filename, "rb");
if(!fptr){
@ -92,12 +98,13 @@ int load_file(const char *filename)
}
cfg.pub_mode = MSGMODE_FILE;
fseek(fptr, 0, SEEK_END);
cfg.msglen = ftell(fptr);
if(cfg.msglen > 268435455){
flen = ftell(fptr);
if(flen > MQTT_MAX_PAYLOAD){
fclose(fptr);
err_printf(&cfg, "Error: File \"%s\" is too large (>268,435,455 bytes).\n", filename);
err_printf(&cfg, "Error: File must be less than %u bytes.\n\n", MQTT_MAX_PAYLOAD);
free(cfg.message);
return 1;
}else if(cfg.msglen == 0){
}else if(flen == 0){
fclose(fptr);
cfg.message = NULL;
cfg.msglen = 0;
@ -107,8 +114,9 @@ int load_file(const char *filename)
err_printf(&cfg, "Error: Unable to determine size of file \"%s\".\n", filename);
return 1;
}
cfg.msglen = (int )flen;
fseek(fptr, 0, SEEK_SET);
cfg.message = malloc(cfg.msglen);
cfg.message = malloc((size_t )cfg.msglen);
if(!cfg.message){
fclose(fptr);
err_printf(&cfg, "Error: Out of memory.\n");
@ -116,7 +124,7 @@ int load_file(const char *filename)
}
pos = 0;
while(pos < cfg.msglen){
rlen = fread(&(cfg.message[pos]), sizeof(char), cfg.msglen-pos, fptr);
rlen = fread(&(cfg.message[pos]), sizeof(char), (size_t )cfg.msglen-pos, fptr);
pos += rlen;
}
fclose(fptr);

@ -54,6 +54,7 @@ bool process_messages = true;
int msg_count = 0;
struct mosquitto *mosq = NULL;
static bool timed_out = false;
static int connack_result = 0;
#ifndef WIN32
void my_signal_handler(int signum)
@ -118,6 +119,7 @@ void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquit
void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flags, const mosquitto_property *properties)
{
connack_result = result;
if(!result){
client_state = rr_s_connected;
mosquitto_subscribe_v5(mosq, NULL, cfg.response_topic, cfg.qos, 0, cfg.subscribe_props);
@ -392,7 +394,11 @@ int main(int argc, char *argv[])
}else if(rc){
err_printf(&cfg, "Error: %s\n", mosquitto_strerror(rc));
}
return rc;
if(connack_result){
return connack_result;
}else{
return rc;
}
cleanup:
mosquitto_lib_cleanup();

@ -42,6 +42,7 @@ int msg_count = 0;
struct mosquitto *mosq = NULL;
int last_mid = 0;
static bool timed_out = false;
static int connack_result = 0;
#ifndef WIN32
void my_signal_handler(int signum)
@ -120,6 +121,7 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag
UNUSED(flags);
UNUSED(properties);
connack_result = result;
if(!result){
mosquitto_subscribe_multiple(mosq, NULL, cfg.topic_count, cfg.topics, cfg.qos, cfg.sub_opts, cfg.subscribe_props);
@ -412,7 +414,11 @@ int main(int argc, char *argv[])
}else if(rc){
err_printf(&cfg, "Error: %s\n", mosquitto_strerror(rc));
}
return rc;
if(connack_result){
return connack_result;
}else{
return rc;
}
cleanup:
mosquitto_destroy(mosq);

@ -110,7 +110,7 @@ static void write_payload(const unsigned char *payload, int payloadlen, int hex,
}
if(hex == 0){
(void)fwrite(payload, 1, payloadlen, stdout);
(void)fwrite(payload, 1, (size_t )payloadlen, stdout);
}else if(hex == 1){
for(i=0; i<payloadlen; i++){
fprintf(stdout, "%02x", payload[i]);

@ -118,7 +118,7 @@ WITH_CONTROL:=yes
# Also bump lib/mosquitto.h, CMakeLists.txt,
# installer/mosquitto.nsi, installer/mosquitto64.nsi
VERSION=1.6.9
VERSION=1.6.12
# Client library SO version. Bump if incompatible API/ABI changes are made.
SOVERSION=1
@ -167,8 +167,10 @@ PASSWD_LDADD:=
ifneq ($(or $(findstring $(UNAME),FreeBSD), $(findstring $(UNAME),OpenBSD), $(findstring $(UNAME),NetBSD)),)
BROKER_LDADD:=$(BROKER_LDADD) -lm
SEDINPLACE:=-i ""
else
BROKER_LDADD:=$(BROKER_LDADD) -ldl -lm
SEDINPLACE:=-i
endif
ifeq ($(UNAME),Linux)

@ -1,14 +0,0 @@
FROM alpine:3.6
MAINTAINER David Audet <david.audet@ca.com>
LABEL Description="Eclipse Mosquitto MQTT Broker"
RUN apk --no-cache add mosquitto=1.4.12-r0 ca-certificates && \
mkdir -p /mosquitto/config /mosquitto/data /mosquitto/log && \
cp /etc/mosquitto/mosquitto.conf /mosquitto/config && \
chown -R mosquitto:mosquitto /mosquitto
COPY docker-entrypoint.sh /
EXPOSE 1883
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"]

@ -1,49 +0,0 @@
#Eclipse Mosquitto v1.4.12 Docker Image
##Mount Points
Three mount points have been created in the image to be used for configuration, persistent storage and logs.
```
/mosquitto/config
/mosquitto/data
/mosquitto/log
```
##Configuration
When running the image, the default configuration values are used.
To use a custom configuration file, mount a **local** configuration file to `/mosquitto/config/mosquitto.conf`
```
docker run -it -p 1883:1883 -p 9001:9001 -v <path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:1.4.12
```
Configuration can be changed to:
* persist data to `/mosquitto/data`
* log to `/mosquitto/log/mosquitto.log`
i.e. add the following to `mosquitto.conf`:
```
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
```
**Note**: If a volume is used, the data will persist between containers.
##Build
Build the image:
```
docker build -t eclipse-mosquitto:1.4.12 .
```
##Run
Run a container using the new image:
```
docker run -it -p 1883:1883 -p 9001:9001 -v <path-to-configuration-file>:/mosquitto/config/mosquitto.conf -v /mosquitto/data -v /mosquitto/log eclipse-mosquitto:1.4.12
```
:boom: if the mosquitto configuration (mosquitto.conf) was modified
to use non-default ports, the docker run command will need to be updated
to expose the ports that have been configured.

@ -1,5 +0,0 @@
#!/bin/ash
set -e
exec "$@"

@ -0,0 +1,90 @@
FROM alpine:3.12
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=1.5.9 \
DOWNLOAD_SHA256=d7b62aa0ca680b0d869d6883373903362f98326a6465fc6cd01a0b9e0e8f0333 \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=2.4.2
RUN set -x && \
apk --no-cache add --virtual build-deps \
build-base \
cmake \
gnupg \
openssl-dev \
util-linux-dev && \
wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \
mkdir -p /build/lws && \
tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \
rm /tmp/lws.tar.gz && \
cd /build/lws && \
cmake . \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX=/usr \
-DLWS_IPV6=ON \
-DLWS_WITHOUT_BUILTIN_GETIFADDRS=ON \
-DLWS_WITHOUT_CLIENT=ON \
-DLWS_WITHOUT_EXTENSIONS=ON \
-DLWS_WITHOUT_TESTAPPS=ON \
-DLWS_WITH_SHARED=OFF \
-DLWS_WITH_ZIP_FOPS=OFF \
-DLWS_WITH_ZLIB=OFF && \
make -j "$(nproc)" && \
rm -rf /root/.cmake && \
wget https://mosquitto.org/files/source/mosquitto-${VERSION}.tar.gz -O /tmp/mosq.tar.gz && \
echo "$DOWNLOAD_SHA256 /tmp/mosq.tar.gz" | sha256sum -c - && \
wget https://mosquitto.org/files/source/mosquitto-${VERSION}.tar.gz.asc -O /tmp/mosq.tar.gz.asc && \
export GNUPGHOME="$(mktemp -d)" && \
found=''; \
for server in \
ha.pool.sks-keyservers.net \
hkp://keyserver.ubuntu.com:80 \
hkp://p80.pool.sks-keyservers.net:80 \
pgp.mit.edu \
; do \
echo "Fetching GPG key $GPG_KEYS from $server"; \
gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$GPG_KEYS" && found=yes && break; \
done; \
test -z "$found" && echo >&2 "error: failed to fetch GPG key $GPG_KEYS" && exit 1; \
gpg --batch --verify /tmp/mosq.tar.gz.asc /tmp/mosq.tar.gz && \
gpgconf --kill all && \
rm -rf "$GNUPGHOME" /tmp/mosq.tar.gz.asc && \
mkdir -p /build/mosq && \
tar --strip=1 -xf /tmp/mosq.tar.gz -C /build/mosq && \
rm /tmp/mosq.tar.gz && \
make -C /build/mosq -j "$(nproc)" \
CFLAGS="-Wall -O2 -I/build/lws/include -flto" \
LDFLAGS="-L/build/lws/lib -flto" \
WITH_ADNS=no \
WITH_DOCS=no \
WITH_SHARED_LIBRARIES=yes \
WITH_SRV=no \
WITH_STRIP=yes \
WITH_WEBSOCKETS=yes \
prefix=/usr \
binary && \
addgroup -S -g 1883 mosquitto 2>/dev/null && \
adduser -S -u 1883 -D -H -h /var/empty -s /sbin/nologin -G mosquitto -g mosquitto mosquitto 2>/dev/null && \
mkdir -p /mosquitto/config /mosquitto/data /mosquitto/log && \
install -d /usr/sbin/ && \
install -s -m755 /build/mosq/client/mosquitto_pub /usr/bin/mosquitto_pub && \
install -s -m755 /build/mosq/client/mosquitto_sub /usr/bin/mosquitto_sub && \
install -s -m644 /build/mosq/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1 && \
install -s -m755 /build/mosq/src/mosquitto /usr/sbin/mosquitto && \
install -s -m755 /build/mosq/src/mosquitto_passwd /usr/bin/mosquitto_passwd && \
install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \
chown -R mosquitto:mosquitto /mosquitto && \
apk --no-cache add \
ca-certificates libuuid && \
apk del build-deps && \
rm -rf /build
VOLUME ["/mosquitto/data", "/mosquitto/log"]
# Set up the entry point script and default command
COPY docker-entrypoint.sh /
EXPOSE 1883
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"]

@ -0,0 +1,49 @@
# Eclipse Mosquitto Docker Image
Containers built with this Dockerfile build as source from published tarballs.
## Mount Points
A docker mount point has been created in the image to be used for configuration.
```
/mosquitto/config
```
Two docker volumes have been created in the image to be used for persistent storage and logs.
```
/mosquitto/data
/mosquitto/log
```
## User/Group
The image runs mosquitto under the mosquitto user and group, which are created
with a uid and gid of 1883.
## Configuration
When creating a container from the image, the default configuration values are used.
To use a custom configuration file, mount a **local** configuration file to `/mosquitto/config/mosquitto.conf`
```
docker run -it -p 1883:1883 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
:boom: if the mosquitto configuration (mosquitto.conf) was modified
to use non-default ports, the docker run command will need to be updated
to expose the ports that have been configured, for example:
```
docker run -it -p 1883:1883 -p 8080:8080 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
Configuration can be changed to:
* persist data to `/mosquitto/data`
* log to `/mosquitto/log/mosquitto.log`
i.e. add the following to `mosquitto.conf`:
```
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
```
**Note**: For any volume used, the data will be persistent between containers.

@ -0,0 +1,10 @@
#!/bin/ash
set -e
# Set permissions
user="$(id -u)"
if [ "$user" = '0' ]; then
[ -d "/mosquitto" ] && chown -R mosquitto:mosquitto /mosquitto || true
fi
exec "$@"

@ -1,4 +1,4 @@
FROM alpine:3.8
FROM alpine:3.12
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
@ -62,7 +62,7 @@ RUN set -x && \
WITH_SHARED_LIBRARIES=yes \
WITH_SRV=no \
WITH_STRIP=yes \
WITH_TLS_PSK=no \
WITH_TLS_PSK=no \
WITH_WEBSOCKETS=yes \
prefix=/usr \
binary && \
@ -78,7 +78,9 @@ RUN set -x && \
install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \
chown -R mosquitto:mosquitto /mosquitto && \
apk --no-cache add \
ca-certificates libuuid && \
ca-certificates \
libressl \
libuuid && \
apk del build-deps && \
rm -rf /build

@ -30,7 +30,7 @@ to use non-default ports, the docker run command will need to be updated
to expose the ports that have been configured, for example:
```
docker run -it -p 1883:1883 -p 9001:9001 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
docker run -it -p 1883:1883 -p 8080:8080 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
Configuration can be changed to:

@ -1,4 +1,10 @@
#!/bin/ash
set -e
# Set permissions
user="$(id -u)"
if [ "$user" = '0' ]; then
[ -d "/mosquitto" ] && chown -R mosquitto:mosquitto /mosquitto || true
fi
exec "$@"

@ -0,0 +1,91 @@
FROM alpine:3.12
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=1.6.11 \
DOWNLOAD_SHA256=b02d8f1368c40d5779ee125c37daf9003608eb47d7fbb04c5b938c76c1230a1f \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=2.4.2
RUN set -x && \
apk --no-cache add --virtual build-deps \
build-base \
cmake \
gnupg \
openssl-dev \
util-linux-dev && \
wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \
mkdir -p /build/lws && \
tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \
rm /tmp/lws.tar.gz && \
cd /build/lws && \
cmake . \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX=/usr \
-DLWS_IPV6=ON \
-DLWS_WITHOUT_BUILTIN_GETIFADDRS=ON \
-DLWS_WITHOUT_CLIENT=ON \
-DLWS_WITHOUT_EXTENSIONS=ON \
-DLWS_WITHOUT_TESTAPPS=ON \
-DLWS_WITH_SHARED=OFF \
-DLWS_WITH_ZIP_FOPS=OFF \
-DLWS_WITH_ZLIB=OFF && \
make -j "$(nproc)" && \
rm -rf /root/.cmake && \
wget https://mosquitto.org/files/source/mosquitto-${VERSION}.tar.gz -O /tmp/mosq.tar.gz && \
echo "$DOWNLOAD_SHA256 /tmp/mosq.tar.gz" | sha256sum -c - && \
wget https://mosquitto.org/files/source/mosquitto-${VERSION}.tar.gz.asc -O /tmp/mosq.tar.gz.asc && \
export GNUPGHOME="$(mktemp -d)" && \
found=''; \
for server in \
ha.pool.sks-keyservers.net \
hkp://keyserver.ubuntu.com:80 \
hkp://p80.pool.sks-keyservers.net:80 \
pgp.mit.edu \
; do \
echo "Fetching GPG key $GPG_KEYS from $server"; \
gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$GPG_KEYS" && found=yes && break; \
done; \
test -z "$found" && echo >&2 "error: failed to fetch GPG key $GPG_KEYS" && exit 1; \
gpg --batch --verify /tmp/mosq.tar.gz.asc /tmp/mosq.tar.gz && \
gpgconf --kill all && \
rm -rf "$GNUPGHOME" /tmp/mosq.tar.gz.asc && \
mkdir -p /build/mosq && \
tar --strip=1 -xf /tmp/mosq.tar.gz -C /build/mosq && \
rm /tmp/mosq.tar.gz && \
make -C /build/mosq -j "$(nproc)" \
CFLAGS="-Wall -O2 -I/build/lws/include" \
LDFLAGS="-L/build/lws/lib" \
WITH_ADNS=no \
WITH_DOCS=no \
WITH_SHARED_LIBRARIES=yes \
WITH_SRV=no \
WITH_STRIP=yes \
WITH_WEBSOCKETS=yes \
prefix=/usr \
binary && \
addgroup -S -g 1883 mosquitto 2>/dev/null && \
adduser -S -u 1883 -D -H -h /var/empty -s /sbin/nologin -G mosquitto -g mosquitto mosquitto 2>/dev/null && \
mkdir -p /mosquitto/config /mosquitto/data /mosquitto/log && \
install -d /usr/sbin/ && \
install -s -m755 /build/mosq/client/mosquitto_pub /usr/bin/mosquitto_pub && \
install -s -m755 /build/mosq/client/mosquitto_rr /usr/bin/mosquitto_rr && \
install -s -m755 /build/mosq/client/mosquitto_sub /usr/bin/mosquitto_sub && \
install -s -m644 /build/mosq/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1 && \
install -s -m755 /build/mosq/src/mosquitto /usr/sbin/mosquitto && \
install -s -m755 /build/mosq/src/mosquitto_passwd /usr/bin/mosquitto_passwd && \
install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \
chown -R mosquitto:mosquitto /mosquitto && \
apk --no-cache add \
ca-certificates && \
apk del build-deps && \
rm -rf /build
VOLUME ["/mosquitto/data", "/mosquitto/log"]
# Set up the entry point script and default command
COPY docker-entrypoint.sh /
EXPOSE 1883
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"]

@ -0,0 +1,49 @@
# Eclipse Mosquitto Docker Image
Containers built with this Dockerfile build as source from published tarballs.
## Mount Points
A docker mount point has been created in the image to be used for configuration.
```
/mosquitto/config
```
Two docker volumes have been created in the image to be used for persistent storage and logs.
```
/mosquitto/data
/mosquitto/log
```
## User/Group
The image runs mosquitto under the mosquitto user and group, which are created
with a uid and gid of 1883.
## Configuration
When creating a container from the image, the default configuration values are used.
To use a custom configuration file, mount a **local** configuration file to `/mosquitto/config/mosquitto.conf`
```
docker run -it -p 1883:1883 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
:boom: if the mosquitto configuration (mosquitto.conf) was modified
to use non-default ports, the docker run command will need to be updated
to expose the ports that have been configured, for example:
```
docker run -it -p 1883:1883 -p 8080:8080 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
Configuration can be changed to:
* persist data to `/mosquitto/data`
* log to `/mosquitto/log/mosquitto.log`
i.e. add the following to `mosquitto.conf`:
```
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
```
**Note**: For any volume used, the data will be persistent between containers.

@ -0,0 +1,10 @@
#!/bin/ash
set -e
# Set permissions
user="$(id -u)"
if [ "$user" = '0' ]; then
[ -d "/mosquitto" ] && chown -R mosquitto:mosquitto /mosquitto || true
fi
exec "$@"

@ -1,10 +1,10 @@
FROM alpine:3.8
FROM alpine:3.12
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=1.6.8 \
DOWNLOAD_SHA256=7df23c81ca37f0e070574fe74414403cf25183016433d07add6134366fb45df6 \
ENV VERSION=1.6.11 \
DOWNLOAD_SHA256=b02d8f1368c40d5779ee125c37daf9003608eb47d7fbb04c5b938c76c1230a1f \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=2.4.2
@ -79,7 +79,8 @@ RUN set -x && \
install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \
chown -R mosquitto:mosquitto /mosquitto && \
apk --no-cache add \
ca-certificates && \
ca-certificates \
libressl && \
apk del build-deps && \
rm -rf /build

@ -30,7 +30,7 @@ to use non-default ports, the docker run command will need to be updated
to expose the ports that have been configured, for example:
```
docker run -it -p 1883:1883 -p 9001:9001 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
docker run -it -p 1883:1883 -p 8080:8080 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
Configuration can be changed to:

@ -1,4 +1,10 @@
#!/bin/ash
set -e
# Set permissions
user="$(id -u)"
if [ "$user" = '0' ]; then
[ -d "/mosquitto" ] && chown -R mosquitto:mosquitto /mosquitto || true
fi
exec "$@"

@ -2,11 +2,14 @@
This directory contains Docker files for Mosquitto.
The `1.5` directory contains the latest version of Mosquitto for
that series, and provide the basis of the official image.
The `1.6` directory contains the latest version of Mosquitto for
that series, and provide the basis of the official image. It uses libressl. The
`1.6-openssl` directory is identical except that it uses openssl instead of
libressl, and enables TLS-PSK support.
`1.4.12` is the version using Alpine packaged Mosquitto, which will be removed
at the next minor release.
The `1.5` directory contains the version of Mosquitto based on the 1.5 branch.
It uses libressl. The `1.5-openssl` directory is identical except that it uses
openssl instead of libressl, and enables TLS-PSK support.
The `generic` directory contains a generic Dockerfile that can be used to build
arbitrary versions of Mosquitto based on the released tarballs as follows:

@ -6,7 +6,7 @@ RUN test -n "${VERSION}"
RUN apk --no-cache add \
build-base \
libressl-dev \
openssl-dev \
c-ares-dev \
curl \
util-linux-dev \
@ -48,8 +48,7 @@ LABEL maintainer="Jonathan Hanson <jonathan@jonathan-hanson.org>" \
RUN apk --no-cache add \
busybox \
ca-certificates \
libcrypto1.0 \
libssl1.0 \
openssl \
libuuid \
libwebsockets \
musl

@ -13,7 +13,7 @@ Three docker volumes have been created in the image to be used for configuration
When creating a container from the image, the default configuration values are used.
To use a custom configuration file, mount a **local** configuration file to `/mosquitto/config/mosquitto.conf`
```
docker run -it -p 1883:1883 -p 9001:9001 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
docker run -it -p 1883:1883 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
Configuration can be changed to:
@ -40,7 +40,7 @@ docker build -t eclipse-mosquitto:<version> --build-arg VERSION="<version>" .
## Run
Run a container using the new image:
```
docker run -it -p 1883:1883 -p 9001:9001 -v <path-to-configuration-file>:/mosquitto/config/mosquitto.conf -v /mosquitto/data -v /mosquitto/log eclipse-mosquitto:<version>
docker run -it -p 1883:1883 -v <path-to-configuration-file>:/mosquitto/config/mosquitto.conf -v /mosquitto/data -v /mosquitto/log eclipse-mosquitto:<version>
```
:boom: if the mosquitto configuration (mosquitto.conf) was modified
to use non-default ports, the docker run command will need to be updated

@ -1,4 +1,10 @@
#!/bin/ash
set -e
# Set permissions
user="$(id -u)"
if [ "$user" = '0' ]; then
[ -d "/mosquitto" ] && chown -R mosquitto:mosquitto /mosquitto || true
fi
exec "$@"

@ -1,4 +1,4 @@
FROM alpine:3.8
FROM alpine:3.12
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
@ -12,7 +12,7 @@ RUN set -x && \
build-base \
cmake \
gnupg \
libressl-dev \
openssl-dev \
util-linux-dev && \
wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \
mkdir -p /build/lws && \
@ -43,7 +43,6 @@ RUN set -x && \
WITH_SHARED_LIBRARIES=yes \
WITH_SRV=no \
WITH_STRIP=yes \
WITH_TLS_PSK=no \
WITH_WEBSOCKETS=yes \
prefix=/usr \
binary && \

@ -29,10 +29,11 @@ docker run -it -p 1883:1883 -v <absolute-path-to-configuration-file>:/mosquitto/
:boom: if the mosquitto configuration (mosquitto.conf) was modified
to use non-default ports, the docker run command will need to be updated
to expose the ports that have been configured, for example:
to expose the ports that have been configured, for example if you use port 8080
for websockets as well as port 1883:
```
docker run -it -p 1883:1883 -p 9001:9001 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
docker run -it -p 1883:1883 -p 8080:8080 -v <absolute-path-to-configuration-file>:/mosquitto/config/mosquitto.conf eclipse-mosquitto:<version>
```
Configuration can be changed to:

@ -1,4 +1,10 @@
#!/bin/ash
set -e
# Set permissions
user="$(id -u)"
if [ "$user" = '0' ]; then
[ -d "/mosquitto" ] && chown -R mosquitto:mosquitto /mosquitto || true
fi
exec "$@"

@ -2,5 +2,5 @@ This is a simple example of the C++ library mosquittopp.
It is a client that subscribes to the topic temperature/celsius which should
have temperature data in text form being published to it. It reads this data as
a Celsius temperature, converts to Farenheit and republishes on
temperature/farenheit.
a Celsius temperature, converts to Fahrenheit and republishes on
temperature/fahrenheit.

@ -28,7 +28,7 @@ void mqtt_tempconv::on_connect(int rc)
void mqtt_tempconv::on_message(const struct mosquitto_message *message)
{
double temp_celsius, temp_farenheit;
double temp_celsius, temp_fahrenheit;
char buf[51];
if(!strcmp(message->topic, "temperature/celsius")){
@ -36,9 +36,9 @@ void mqtt_tempconv::on_message(const struct mosquitto_message *message)
/* Copy N-1 bytes to ensure always 0 terminated. */
memcpy(buf, message->payload, 50*sizeof(char));
temp_celsius = atof(buf);
temp_farenheit = temp_celsius*9.0/5.0 + 32.0;
snprintf(buf, 50, "%f", temp_farenheit);
publish(NULL, "temperature/farenheit", strlen(buf), buf);
temp_fahrenheit = temp_celsius*9.0/5.0 + 32.0;
snprintf(buf, 50, "%f", temp_fahrenheit);
publish(NULL, "temperature/fahrenheit", strlen(buf), buf);
}
}

@ -9,7 +9,7 @@
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
Name "Eclipse Mosquitto"
!define VERSION 1.6.9
!define VERSION 1.6.12
OutFile "mosquitto-${VERSION}-install-windows-x86.exe"
InstallDir "$PROGRAMFILES\mosquitto"

@ -9,7 +9,7 @@
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
Name "Eclipse Mosquitto"
!define VERSION 1.6.9
!define VERSION 1.6.12
OutFile "mosquitto-${VERSION}-install-windows-x64.exe"
!include "x64.nsh"

@ -74,7 +74,7 @@ endif
$(INSTALL) mqtt_protocol.h "${DESTDIR}${incdir}/mqtt_protocol.h"
$(INSTALL) -d "${DESTDIR}${libdir}/pkgconfig"
$(INSTALL) -m644 ../libmosquitto.pc.in "${DESTDIR}${libdir}/pkgconfig/libmosquitto.pc"
sed -i -e "s#@CMAKE_INSTALL_PREFIX@#${prefix}#" -e "s#@VERSION@#${VERSION}#" "${DESTDIR}${libdir}/pkgconfig/libmosquitto.pc"
sed ${SEDINPLACE} -e "s#@CMAKE_INSTALL_PREFIX@#${prefix}#" -e "s#@VERSION@#${VERSION}#" "${DESTDIR}${libdir}/pkgconfig/libmosquitto.pc"
ifeq ($(WITH_SHARED_LIBRARIES),yes)
$(MAKE) -C cpp install
endif

@ -155,9 +155,9 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
pthread_mutex_lock(&mosq->msgs_out.mutex);
message->state = mosq_ms_invalid;
message__queue(mosq, message, mosq_md_out);
rc = message__queue(mosq, message, mosq_md_out);
pthread_mutex_unlock(&mosq->msgs_out.mutex);
return MOSQ_ERR_SUCCESS;
return rc;
}
}

@ -81,20 +81,6 @@ static int mosquitto__connect_init(struct mosquitto *mosq, const char *host, int
mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum;
mosq->retain_available = 1;
if(mosq->sockpairR != INVALID_SOCKET){
COMPAT_CLOSE(mosq->sockpairR);
mosq->sockpairR = INVALID_SOCKET;
}
if(mosq->sockpairW != INVALID_SOCKET){
COMPAT_CLOSE(mosq->sockpairW);
mosq->sockpairW = INVALID_SOCKET;
}
if(net__socketpair(&mosq->sockpairR, &mosq->sockpairW)){
log__printf(mosq, MOSQ_LOG_WARNING,
"Warning: Unable to open socket pair, outgoing publish commands may be delayed.");
}
return MOSQ_ERR_SUCCESS;
}

@ -26,7 +26,7 @@ endif
$(INSTALL) mosquittopp.h "${DESTDIR}${incdir}/mosquittopp.h"
$(INSTALL) -d "${DESTDIR}${libdir}/pkgconfig/"
$(INSTALL) -m644 ../../libmosquittopp.pc.in "${DESTDIR}${libdir}/pkgconfig/libmosquittopp.pc"
sed -i -e "s#@CMAKE_INSTALL_PREFIX@#${prefix}#" -e "s#@VERSION@#${VERSION}#" "${DESTDIR}${libdir}/pkgconfig/libmosquittopp.pc"
sed ${SEDINPLACE} -e "s#@CMAKE_INSTALL_PREFIX@#${prefix}#" -e "s#@VERSION@#${VERSION}#" "${DESTDIR}${libdir}/pkgconfig/libmosquittopp.pc"
uninstall :
-rm -f "${DESTDIR}${libdir}/libmosquittopp.so.${SOVERSION}"

@ -4,6 +4,7 @@
#define pthread_create(A, B, C, D)
#define pthread_join(A, B)
#define pthread_cancel(A)
#define pthread_testcancel()
#define pthread_mutex_init(A, B)
#define pthread_mutex_destroy(A)

@ -104,6 +104,7 @@ int handle__connack(struct mosquitto *mosq)
mosquitto_property_read_int32(properties, MQTT_PROP_MAXIMUM_PACKET_SIZE, &mosq->maximum_packet_size, false);
mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum;
message__reconnect_reset(mosq);
connack_callback(mosq, reason_code, connect_flags, properties);
mosquitto_property_free_all(&properties);

@ -92,9 +92,7 @@ int handle__pubackcomp(struct mosquitto *mosq, const char *type)
log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d, RC:%d)", mosq->id, type, mid, reason_code);
rc = message__delete(mosq, mid, mosq_md_out, qos);
if(rc){
return rc;
}else{
if(rc == MOSQ_ERR_SUCCESS){
/* Only inform the client the message has been sent once. */
pthread_mutex_lock(&mosq->callback_mutex);
if(mosq->on_publish){
@ -109,6 +107,8 @@ int handle__pubackcomp(struct mosquitto *mosq, const char *type)
}
pthread_mutex_unlock(&mosq->callback_mutex);
mosquitto_property_free_all(&properties);
}else if(rc != MOSQ_ERR_NOT_FOUND){
return rc;
}
pthread_mutex_lock(&mosq->msgs_out.mutex);
message__release_to_inflight(mosq, mosq_md_out);

@ -101,9 +101,7 @@ int handle__pubrel(struct mosquitto_db *db, struct mosquitto *mosq)
}
rc = message__remove(mosq, mid, mosq_md_in, &message, 2);
if(rc){
return rc;
}else{
if(rc == MOSQ_ERR_SUCCESS){
/* Only pass the message on if we have removed it from the queue - this
* prevents multiple callbacks for the same message. */
pthread_mutex_lock(&mosq->callback_mutex);
@ -120,6 +118,10 @@ int handle__pubrel(struct mosquitto_db *db, struct mosquitto *mosq)
pthread_mutex_unlock(&mosq->callback_mutex);
mosquitto_property_free_all(&properties);
message__cleanup(&message);
}else if(rc == MOSQ_ERR_NOT_FOUND){
return MOSQ_ERR_SUCCESS;
}else{
return rc;
}
#endif

@ -109,6 +109,7 @@ MOSQ_1.6 {
mosquitto_property_add_varint;
mosquitto_property_check_all;
mosquitto_property_check_command;
mosquitto_property_copy_all;
mosquitto_property_free_all;
mosquitto_property_read_binary;
mosquitto_property_read_byte;

@ -191,14 +191,63 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets)
}
static int interruptible_sleep(struct mosquitto *mosq, unsigned long reconnect_delay)
{
#ifdef HAVE_PSELECT
struct timespec local_timeout;
#else
struct timeval local_timeout;
#endif
fd_set readfds;
int fdcount;
char pairbuf;
int maxfd = 0;
local_timeout.tv_sec = reconnect_delay;
#ifdef HAVE_PSELECT
local_timeout.tv_nsec = 0;
#else
local_timeout.tv_usec = 0;
#endif
FD_ZERO(&readfds);
maxfd = 0;
if(mosq->sockpairR != INVALID_SOCKET){
/* sockpairR is used to break out of select() before the
* timeout, when mosquitto_loop_stop() is called */
FD_SET(mosq->sockpairR, &readfds);
maxfd = mosq->sockpairR;
}
#ifdef HAVE_PSELECT
fdcount = pselect(maxfd+1, &readfds, NULL, NULL, &local_timeout, NULL);
#else
fdcount = select(maxfd+1, &readfds, NULL, NULL, &local_timeout);
#endif
if(fdcount == -1){
#ifdef WIN32
errno = WSAGetLastError();
#endif
if(errno == EINTR){
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_ERRNO;
}
}else if(mosq->sockpairR != INVALID_SOCKET && FD_ISSET(mosq->sockpairR, &readfds)){
#ifndef WIN32
if(read(mosq->sockpairR, &pairbuf, 1) == 0){
}
#else
recv(mosq->sockpairR, &pairbuf, 1, 0);
#endif
}
return MOSQ_ERR_SUCCESS;
}
int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
{
int run = 1;
int rc;
unsigned long reconnect_delay;
#ifndef WIN32
struct timespec req, rem;
#endif
int state;
if(!mosq) return MOSQ_ERR_INVAL;
@ -207,6 +256,9 @@ int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
while(run){
do{
#ifdef HAVE_PTHREAD_CANCEL
pthread_testcancel();
#endif
rc = mosquitto_loop(mosq, timeout, max_packets);
}while(run && rc == MOSQ_ERR_SUCCESS);
/* Quit after fatal errors. */
@ -231,6 +283,9 @@ int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
return rc;
}
do{
#ifdef HAVE_PTHREAD_CANCEL
pthread_testcancel();
#endif
rc = MOSQ_ERR_SUCCESS;
state = mosquitto__get_state(mosq);
if(state == mosq_cs_disconnecting || state == mosq_cs_disconnected){
@ -252,15 +307,8 @@ int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
mosq->reconnects++;
}
#ifdef WIN32
Sleep(reconnect_delay*1000);
#else
req.tv_sec = reconnect_delay;
req.tv_nsec = 0;
while(nanosleep(&req, &rem) == -1 && errno == EINTR){
req = rem;
}
#endif
rc = interruptible_sleep(mosq, reconnect_delay);
if(rc) return rc;
state = mosquitto__get_state(mosq);
if(state == mosq_cs_disconnecting || state == mosq_cs_disconnected){

@ -47,12 +47,13 @@ void memory__set_limit(size_t lim)
void *mosquitto__calloc(size_t nmemb, size_t size)
{
void *mem;
#ifdef REAL_WITH_MEMORY_TRACKING
if(mem_limit && memcount + size > mem_limit){
return NULL;
}
#endif
void *mem = calloc(nmemb, size);
mem = calloc(nmemb, size);
#ifdef REAL_WITH_MEMORY_TRACKING
if(mem){
@ -79,12 +80,15 @@ void mosquitto__free(void *mem)
void *mosquitto__malloc(size_t size)
{
void *mem;
#ifdef REAL_WITH_MEMORY_TRACKING
if(mem_limit && memcount + size > mem_limit){
return NULL;
}
#endif
void *mem = malloc(size);
mem = malloc(size);
#ifdef REAL_WITH_MEMORY_TRACKING
if(mem){
@ -112,13 +116,11 @@ unsigned long mosquitto__max_memory_used(void)
void *mosquitto__realloc(void *ptr, size_t size)
{
void *mem;
#ifdef REAL_WITH_MEMORY_TRACKING
if(mem_limit && memcount + size > mem_limit){
return NULL;
}
#endif
void *mem;
#ifdef REAL_WITH_MEMORY_TRACKING
if(ptr){
memcount -= malloc_usable_size(ptr);
}
@ -139,12 +141,13 @@ void *mosquitto__realloc(void *ptr, size_t size)
char *mosquitto__strdup(const char *s)
{
char *str;
#ifdef REAL_WITH_MEMORY_TRACKING
if(mem_limit && memcount + strlen(s) > mem_limit){
return NULL;
}
#endif
char *str = strdup(s);
str = strdup(s);
#ifdef REAL_WITH_MEMORY_TRACKING
if(str){
@ -157,4 +160,3 @@ char *mosquitto__strdup(const char *s)
return str;
}

@ -24,6 +24,11 @@ Contributors:
#include <strings.h>
#endif
#if defined(__APPLE__)
# include <mach/mach_time.h>
#endif
#include "logging_mosq.h"
#include "mosquitto.h"
#include "mosquitto_internal.h"
#include "memory_mosq.h"
@ -109,11 +114,11 @@ struct mosquitto *mosquitto_new(const char *id, bool clean_start, void *userdata
mosq = (struct mosquitto *)mosquitto__calloc(1, sizeof(struct mosquitto));
if(mosq){
mosq->sock = INVALID_SOCKET;
mosq->sockpairR = INVALID_SOCKET;
mosq->sockpairW = INVALID_SOCKET;
#ifdef WITH_THREADING
mosq->thread_id = pthread_self();
#endif
mosq->sockpairR = INVALID_SOCKET;
mosq->sockpairW = INVALID_SOCKET;
rc = mosquitto_reinitialise(mosq, id, clean_start, userdata);
if(rc){
mosquitto_destroy(mosq);
@ -148,8 +153,6 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_st
}
mosq->protocol = mosq_p_mqtt311;
mosq->sock = INVALID_SOCKET;
mosq->sockpairR = INVALID_SOCKET;
mosq->sockpairW = INVALID_SOCKET;
mosq->keepalive = 60;
mosq->clean_start = clean_start;
if(id){
@ -208,6 +211,12 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_st
pthread_mutex_init(&mosq->mid_mutex, NULL);
mosq->thread_id = pthread_self();
#endif
/* This must be after pthread_mutex_init(), otherwise the log mutex may be
* used before being initialised. */
if(net__socketpair(&mosq->sockpairR, &mosq->sockpairW)){
log__printf(mosq, MOSQ_LOG_WARNING,
"Warning: Unable to open socket pair, outgoing publish commands may be delayed.");
}
return MOSQ_ERR_SUCCESS;
}

@ -48,7 +48,7 @@ extern "C" {
#define LIBMOSQUITTO_MAJOR 1
#define LIBMOSQUITTO_MINOR 6
#define LIBMOSQUITTO_REVISION 9
#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)
@ -208,7 +208,8 @@ libmosq_EXPORT int mosquitto_lib_version(int *major, int *minor, int *revision);
* This function is *not* thread safe.
*
* Returns:
* MOSQ_ERR_SUCCESS - always
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_UNKNOWN - on Windows, if sockets couldn't be initialized.
*
* See Also:
* <mosquitto_lib_cleanup>, <mosquitto_lib_version>
@ -439,7 +440,11 @@ libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_INVAL - if the input parameters were invalid, which could be any of:
* * mosq == NULL
* * host == NULL
* * port < 0
* * keepalive < 5
* MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
* contains the error code, even on Windows.
* Use strerror_r() where available or FormatMessage() on
@ -505,7 +510,11 @@ libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *ho
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_INVAL - if the input parameters were invalid, which could be any of:
* * mosq == NULL
* * host == NULL
* * port < 0
* * keepalive < 5
* MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
* contains the error code, even on Windows.
* Use strerror_r() where available or FormatMessage() on
@ -575,7 +584,11 @@ libmosq_EXPORT int mosquitto_connect_async(struct mosquitto *mosq, const char *h
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_INVAL - if the input parameters were invalid, which could be any of:
* * mosq == NULL
* * host == NULL
* * port < 0
* * keepalive < 5
* MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
* contains the error code, even on Windows.
* Use strerror_r() where available or FormatMessage() on
@ -609,7 +622,11 @@ libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const ch
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_INVAL - if the input parameters were invalid, which could be any of:
* * mosq == NULL
* * host == NULL
* * port < 0
* * keepalive < 5
* MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
* contains the error code, even on Windows.
* Use strerror_r() where available or FormatMessage() on
@ -1494,6 +1511,39 @@ libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt
*/
libmosq_EXPORT int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value);
/*
* Function: mosquitto_string_option
*
* Used to set const char* options for the client.
*
* Parameters:
* mosq - a valid mosquitto instance.
* option - the option to set.
* value - the option specific value.
*
* Options:
* MOSQ_OPT_TLS_ENGINE
* Configure the client for TLS Engine support. Pass a TLS Engine ID
* to be used when creating TLS connections.
* Must be set before <mosquitto_connect>.
* MOSQ_OPT_TLS_KEYFORM
* Configure the client to treat the keyfile differently depending
* on its type. Must be set before <mosquitto_connect>.
* Set as either "pem" or "engine", to determine from where the
* private key for a TLS connection will be obtained. Defaults to
* "pem", a normal private key file.
* MOSQ_OPT_TLS_KPASS_SHA1
* Where the TLS Engine requires the use of a password to be
* accessed, this option allows a hex encoded SHA1 hash of the
* private key password to be passed to the engine directly.
* Must be set before <mosquitto_connect>.
* MOSQ_OPT_TLS_ALPN
* If the broker being connected to has multiple services available
* on a single TLS port, such as both MQTT and WebSockets, use this
* option to configure the ALPN option for the connection.
*/
libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value);
/*
* Function: mosquitto_reconnect_delay_set
@ -1779,13 +1829,10 @@ libmosq_EXPORT void *mosquitto_ssl_get(struct mosquitto *mosq);
* Callback Parameters:
* mosq - the mosquitto instance making the callback.
* obj - the user data provided in <mosquitto_new>
* rc - the return code of the connection response, one of:
*
* * 0 - success
* * 1 - connection refused (unacceptable protocol version)
* * 2 - connection refused (identifier rejected)
* * 3 - connection refused (broker unavailable)
* * 4-255 - reserved for future use
* rc - the return code of the connection response. The values are defined by
* the MQTT protocol version in use.
* For MQTT v5.0, look at section 3.2.2.2 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html
* For MQTT v3.1.1, look at section 3.2.2.3 Connect Return code: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
*/
libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int));
@ -1803,14 +1850,11 @@ libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, void
* Callback Parameters:
* mosq - the mosquitto instance making the callback.
* obj - the user data provided in <mosquitto_new>
* rc - the return code of the connection response, one of:
* rc - the return code of the connection response. The values are defined by
* the MQTT protocol version in use.
* For MQTT v5.0, look at section 3.2.2.2 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html
* For MQTT v3.1.1, look at section 3.2.2.3 Connect Return code: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
* flags - the connect flags.
*
* * 0 - success
* * 1 - connection refused (unacceptable protocol version)
* * 2 - connection refused (identifier rejected)
* * 3 - connection refused (broker unavailable)
* * 4-255 - reserved for future use
*/
libmosq_EXPORT void mosquitto_connect_with_flags_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int));
@ -1828,12 +1872,10 @@ libmosq_EXPORT void mosquitto_connect_with_flags_callback_set(struct mosquitto *
* Callback Parameters:
* mosq - the mosquitto instance making the callback.
* obj - the user data provided in <mosquitto_new>
* rc - the return code of the connection response, one of:
* * 0 - success
* * 1 - connection refused (unacceptable protocol version)
* * 2 - connection refused (identifier rejected)
* * 3 - connection refused (broker unavailable)
* * 4-255 - reserved for future use
* rc - the return code of the connection response. The values are defined by
* the MQTT protocol version in use.
* For MQTT v5.0, look at section 3.2.2.2 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html
* For MQTT v3.1.1, look at section 3.2.2.3 Connect Return code: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
* flags - the connect flags.
* props - list of MQTT 5 properties, or NULL
*
@ -2072,44 +2114,6 @@ libmosq_EXPORT void mosquitto_unsubscribe_v5_callback_set(struct mosquitto *mosq
libmosq_EXPORT void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *));
/*
* Function: mosquitto_reconnect_delay_set
*
* Control the behaviour of the client when it has unexpectedly disconnected in
* <mosquitto_loop_forever> or after <mosquitto_loop_start>. The default
* behaviour if this function is not used is to repeatedly attempt to reconnect
* with a delay of 1 second until the connection succeeds.
*
* Use reconnect_delay parameter to change the delay between successive
* reconnection attempts. You may also enable exponential backoff of the time
* between reconnections by setting reconnect_exponential_backoff to true and
* set an upper bound on the delay with reconnect_delay_max.
*
* Example 1:
* delay=2, delay_max=10, exponential_backoff=False
* Delays would be: 2, 4, 6, 8, 10, 10, ...
*
* Example 2:
* delay=3, delay_max=30, exponential_backoff=True
* Delays would be: 3, 6, 12, 24, 30, 30, ...
*
* Parameters:
* mosq - a valid mosquitto instance.
* reconnect_delay - the number of seconds to wait between
* reconnects.
* reconnect_delay_max - the maximum number of seconds to wait
* between reconnects.
* reconnect_exponential_backoff - use exponential backoff between
* reconnect attempts. Set to true to enable
* exponential backoff.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
*/
libmosq_EXPORT int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
/* =============================================================================
*
* Section: SOCKS5 proxy functions

@ -165,7 +165,6 @@ struct mosquitto_message_all{
struct mosquitto_message_all *prev;
mosquitto_property *properties;
time_t timestamp;
//enum mosquitto_msg_direction direction;
enum mosquitto_msg_state state;
bool dup;
struct mosquitto_message msg;
@ -321,7 +320,7 @@ struct mosquitto {
void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid);
void (*on_unsubscribe_v5)(struct mosquitto *, void *userdata, int mid, const mosquitto_property *props);
void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str);
//void (*on_error)();
/*void (*on_error)();*/
char *host;
int port;
char *bind_address;

@ -547,11 +547,11 @@ void net__print_ssl_error(struct mosquitto *mosq)
int net__socket_connect_tls(struct mosquitto *mosq)
{
int ret, err;
long res;
ERR_clear_error();
long res;
if (mosq->tls_ocsp_required) {
// Note: OCSP is available in all currently supported OpenSSL versions.
/* Note: OCSP is available in all currently supported OpenSSL versions. */
if ((res=SSL_set_tlsext_status_type(mosq->ssl, TLSEXT_STATUSTYPE_ocsp)) != 1) {
log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res);
return MOSQ_ERR_OCSP;
@ -596,12 +596,69 @@ int net__socket_connect_tls(struct mosquitto *mosq)
#ifdef WITH_TLS
static int net__tls_load_ca(struct mosquitto *mosq)
{
int ret;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
if(ret == 0){
# ifdef WITH_BROKER
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
}
# else
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
}
# endif
return MOSQ_ERR_TLS;
}
#else
if(mosq->tls_cafile){
ret = SSL_CTX_load_verify_file(mosq->ssl_ctx, mosq->tls_cafile);
if(ret == 0){
# ifdef WITH_BROKER
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
# else
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
# endif
return MOSQ_ERR_TLS;
}
}
if(mosq->tls_capath){
ret = SSL_CTX_load_verify_dir(mosq->ssl_ctx, mosq->tls_capath);
if(ret == 0){
# ifdef WITH_BROKER
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
# else
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
# endif
return MOSQ_ERR_TLS;
}
}
#endif
return MOSQ_ERR_SUCCESS;
}
static int net__init_ssl_ctx(struct mosquitto *mosq)
{
int ret;
ENGINE *engine = NULL;
uint8_t tls_alpn_wire[256];
uint8_t tls_alpn_len;
#if !defined(OPENSSL_NO_ENGINE)
EVP_PKEY *pkey;
#endif
if(mosq->ssl_ctx){
if(!mosq->ssl_ctx_defaults){
@ -662,7 +719,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
/* Set ALPN */
if(mosq->tls_alpn) {
tls_alpn_len = (uint8_t) strnlen(mosq->tls_alpn, 254);
tls_alpn_wire[0] = tls_alpn_len; // first byte is length of string
tls_alpn_wire[0] = tls_alpn_len; /* first byte is length of string */
memcpy(tls_alpn_wire + 1, mosq->tls_alpn, tls_alpn_len);
SSL_CTX_set_alpn_protos(mosq->ssl_ctx, tls_alpn_wire, tls_alpn_len + 1);
}
@ -707,28 +764,11 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
}
}
if(mosq->tls_cafile || mosq->tls_capath){
ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
if(ret == 0){
#ifdef WITH_BROKER
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
}
#else
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
}
#endif
#if !defined(OPENSSL_NO_ENGINE)
ret = net__tls_load_ca(mosq);
if(ret != MOSQ_ERR_SUCCESS){
# if !defined(OPENSSL_NO_ENGINE)
ENGINE_FINISH(engine);
#endif
# endif
COMPAT_CLOSE(mosq->sock);
mosq->sock = INVALID_SOCKET;
net__print_ssl_error(mosq);
@ -785,7 +825,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
}
ui_method = NULL;
}
EVP_PKEY *pkey = ENGINE_load_private_key(engine, mosq->tls_keyfile, ui_method, NULL);
pkey = ENGINE_load_private_key(engine, mosq->tls_keyfile, ui_method, NULL);
if(!pkey){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load engine private key file \"%s\".", mosq->tls_keyfile);
ENGINE_FINISH(engine);
@ -1157,6 +1197,9 @@ int net__socketpair(mosq_sock_t *pairR, mosq_sock_t *pairW)
#else
int sv[2];
*pairR = INVALID_SOCKET;
*pairW = INVALID_SOCKET;
if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1){
return MOSQ_ERR_ERRNO;
}

@ -64,7 +64,7 @@ int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg)
long len = SSL_get_tlsext_status_ocsp_resp(mosq->ssl, &p);
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL_get_tlsext_status_ocsp_resp returned %ld bytes", len);
// the following functions expect a const pointer
/* the following functions expect a const pointer */
cp = (const unsigned char *)p;
if (!cp || len <= 0) {
@ -100,9 +100,10 @@ int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg)
st = SSL_CTX_get_cert_store(mosq->ssl_ctx);
// Note:
// Other checkers often fix problems in OpenSSL before 1.0.2a (e.g. libcurl).
// For all currently supported versions of the OpenSSL project, this is not needed anymore.
/* Note:
* Other checkers often fix problems in OpenSSL before 1.0.2a (e.g. libcurl).
* For all currently supported versions of the OpenSSL project, this is not needed anymore.
*/
if ((result2=OCSP_basic_verify(br, ch, st, 0)) <= 0) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: response verification failed (error: %d)", result2);
@ -126,7 +127,7 @@ int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg)
switch(cert_status) {
case V_OCSP_CERTSTATUS_GOOD:
// Note: A OCSP stapling result will be accepted up to 5 minutes after it expired!
/* Note: A OCSP stapling result will be accepted up to 5 minutes after it expired! */
if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: OCSP response has expired");
goto end;
@ -149,11 +150,11 @@ int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg)
if (br!=NULL) OCSP_BASICRESP_free(br);
if (rsp!=NULL) OCSP_RESPONSE_free(rsp);
return 1; // OK
return 1; /* OK */
end:
if (br!=NULL) OCSP_BASICRESP_free(br);
if (rsp!=NULL) OCSP_RESPONSE_free(rsp);
return 0; // Not OK
return 0; /* Not OK */
}
#endif

@ -27,7 +27,7 @@ Contributors:
#else
# include <arpa/inet.h>
#endif
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__OpenBSD__)
# include <sys/socket.h>
# include <netinet/in.h>
#endif

@ -20,6 +20,14 @@ Contributors:
#include <time.h>
#endif
#if defined(WITH_THREADING)
#if defined(__linux__) || defined(__NetBSD__)
# include <pthread.h>
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
# include <pthread_np.h>
#endif
#endif
#include "mosquitto_internal.h"
#include "net_mosq.h"
#include "util_mosq.h"
@ -28,11 +36,18 @@ void *mosquitto__thread_main(void *obj);
int mosquitto_loop_start(struct mosquitto *mosq)
{
#if defined(WITH_THREADING) && defined(HAVE_PTHREAD_CANCEL)
#if defined(WITH_THREADING)
if(!mosq || mosq->threaded != mosq_ts_none) return MOSQ_ERR_INVAL;
mosq->threaded = mosq_ts_self;
if(!pthread_create(&mosq->thread_id, NULL, mosquitto__thread_main, mosq)){
#if defined(__linux__)
pthread_setname_np(mosq->thread_id, "mosquitto loop");
#elif defined(__NetBSD__)
pthread_setname_np(mosq->thread_id, "%s", "mosquitto loop");
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
pthread_set_name_np(mosq->thread_id, "mosquitto loop");
#endif
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_ERRNO;
@ -44,7 +59,7 @@ int mosquitto_loop_start(struct mosquitto *mosq)
int mosquitto_loop_stop(struct mosquitto *mosq, bool force)
{
#if defined(WITH_THREADING) && defined(HAVE_PTHREAD_CANCEL)
#if defined(WITH_THREADING)
# ifndef WITH_BROKER
char sockpair_data = 0;
# endif
@ -63,9 +78,11 @@ int mosquitto_loop_stop(struct mosquitto *mosq, bool force)
#endif
}
#ifdef HAVE_PTHREAD_CANCEL
if(force){
pthread_cancel(mosq->thread_id);
}
#endif
pthread_join(mosq->thread_id, NULL);
mosq->thread_id = pthread_self();
mosq->threaded = mosq_ts_none;

@ -45,11 +45,11 @@ int mosquitto_validate_utf8(const char *str, int len)
codelen = 2;
codepoint = (ustr[i] & 0x1F);
}else if((ustr[i] & 0xF0) == 0xE0){
// 1110xxxx - 3 byte sequence
/* 1110xxxx - 3 byte sequence */
codelen = 3;
codepoint = (ustr[i] & 0x0F);
}else if((ustr[i] & 0xF8) == 0xF0){
// 11110xxx - 4 byte sequence
/* 11110xxx - 4 byte sequence */
if(ustr[i] > 0xF4){
/* Invalid, this would produce values > 0x10FFFF. */
return MOSQ_ERR_MALFORMED_UTF8;

@ -120,6 +120,7 @@ int will__clear(struct mosquitto *mosq)
mosquitto__free(mosq->will);
mosq->will = NULL;
mosq->will_delay_interval = 0;
return MOSQ_ERR_SUCCESS;
}

@ -1197,7 +1197,7 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
<listitem>
<para>Set <option>use_username_as_clientid</option> to
true to replace the clientid that a client
connected with with its username. This allows
connected with its username. This allows
authentication to be tied to the clientid, which
means that it is possible to prevent one client
disconnecting another by using the same
@ -1877,7 +1877,7 @@ topic # both 2 local/topic/ remote/topic/</programlisting>
connection test-mosquitto-org
address test.mosquitto.org
cleansession true
topic clients/total in 0 test/mosquitto/org $SYS/broker/
topic clients/total in 0 test/mosquitto/org/ $SYS/broker/
</programlisting></example>
</listitem>
@ -1973,7 +1973,7 @@ topic clients/total in 0 test/mosquitto/org $SYS/broker/
disable the hostname verification.</para>
<para>Setting this option to
<replaceable>true</replaceable> means that a
malicious third party could potentially inpersonate
malicious third party could potentially impersonate
your server, so it should always be set to
<replaceable>false</replaceable> in production
environments.</para>

@ -127,6 +127,64 @@
</refsect1>
<refsect1>
<title>Exit Status</title>
<para>
mosquitto_sub returns zero on success, or non-zero on error. If
the connection is refused by the broker at the MQTT level, then
the exit code is the CONNACK reason code. If another error
occurs, the exit code is a libmosquitto return value.
</para>
<para>MQTT v3.1.1 CONNACK codes:</para>
<itemizedlist mark="circle">
<listitem><para><option>0</option> Success</para></listitem>
<listitem><para><option>1</option> Connection refused: Bad protocol version</para></listitem>
<listitem><para><option>2</option> Connection refused: Identifier rejected</para></listitem>
<listitem><para><option>3</option> Connection refused: Server unavailable</para></listitem>
<listitem><para><option>4</option> Connection refused: Bad username/password</para></listitem>
<listitem><para><option>5</option> Connection refused: Not authorized</para></listitem>
</itemizedlist>
<para>MQTT v5 CONNACK codes:</para>
<itemizedlist>
<listitem><para><option>0</option> Success</para></listitem>
<listitem><para><option>128</option> Unspecified error</para></listitem>
<listitem><para><option>129</option> Malformed packet</para></listitem>
<listitem><para><option>130</option> Protocol error</para></listitem>
<listitem><para><option>131</option> Implementation specific error</para></listitem>
<listitem><para><option>132</option> Unsupported protocol version</para></listitem>
<listitem><para><option>133</option> Client ID not valid</para></listitem>
<listitem><para><option>134</option> Bad username or password</para></listitem>
<listitem><para><option>135</option> Not authorized</para></listitem>
<listitem><para><option>136</option> Server unavailable</para></listitem>
<listitem><para><option>137</option> Server busy</para></listitem>
<listitem><para><option>138</option> Banned</para></listitem>
<listitem><para><option>139</option> Server shutting down</para></listitem>
<listitem><para><option>140</option> Bad authentication method</para></listitem>
<listitem><para><option>141</option> Keep alive timeout</para></listitem>
<listitem><para><option>142</option> Session taken over</para></listitem>
<listitem><para><option>143</option> Topic filter invalid</para></listitem>
<listitem><para><option>144</option> Topic name invalid</para></listitem>
<listitem><para><option>147</option> Receive maximum exceeded</para></listitem>
<listitem><para><option>148</option> Topic alias invalid</para></listitem>
<listitem><para><option>149</option> Packet too large</para></listitem>
<listitem><para><option>148</option> Message rate too high</para></listitem>
<listitem><para><option>151</option> Quota exceeded</para></listitem>
<listitem><para><option>152</option> Administrative action</para></listitem>
<listitem><para><option>153</option> Payload format invalid</para></listitem>
<listitem><para><option>154</option> Retain not supported</para></listitem>
<listitem><para><option>155</option> QoS not supported</para></listitem>
<listitem><para><option>156</option> Use another server</para></listitem>
<listitem><para><option>157</option> Server moved</para></listitem>
<listitem><para><option>158</option> Shared subscriptions not supported</para></listitem>
<listitem><para><option>159</option> Connection rate exceeded</para></listitem>
<listitem><para><option>160</option> Maximum connect time</para></listitem>
<listitem><para><option>161</option> Subscription IDs not supported</para></listitem>
<listitem><para><option>162</option> Wildcard subscriptions not supported</para></listitem>
</itemizedlist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>Add a user to a new password file:</para>

@ -702,6 +702,64 @@
</refsect2>
</refsect1>
<refsect1>
<title>Exit Status</title>
<para>
mosquitto_sub returns zero on success, or non-zero on error. If
the connection is refused by the broker at the MQTT level, then
the exit code is the CONNACK reason code. If another error
occurs, the exit code is a libmosquitto return value.
</para>
<para>MQTT v3.1.1 CONNACK codes:</para>
<itemizedlist mark="circle">
<listitem><para><option>0</option> Success</para></listitem>
<listitem><para><option>1</option> Connection refused: Bad protocol version</para></listitem>
<listitem><para><option>2</option> Connection refused: Identifier rejected</para></listitem>
<listitem><para><option>3</option> Connection refused: Server unavailable</para></listitem>
<listitem><para><option>4</option> Connection refused: Bad username/password</para></listitem>
<listitem><para><option>5</option> Connection refused: Not authorized</para></listitem>
</itemizedlist>
<para>MQTT v5 CONNACK codes:</para>
<itemizedlist>
<listitem><para><option>0</option> Success</para></listitem>
<listitem><para><option>128</option> Unspecified error</para></listitem>
<listitem><para><option>129</option> Malformed packet</para></listitem>
<listitem><para><option>130</option> Protocol error</para></listitem>
<listitem><para><option>131</option> Implementation specific error</para></listitem>
<listitem><para><option>132</option> Unsupported protocol version</para></listitem>
<listitem><para><option>133</option> Client ID not valid</para></listitem>
<listitem><para><option>134</option> Bad username or password</para></listitem>
<listitem><para><option>135</option> Not authorized</para></listitem>
<listitem><para><option>136</option> Server unavailable</para></listitem>
<listitem><para><option>137</option> Server busy</para></listitem>
<listitem><para><option>138</option> Banned</para></listitem>
<listitem><para><option>139</option> Server shutting down</para></listitem>
<listitem><para><option>140</option> Bad authentication method</para></listitem>
<listitem><para><option>141</option> Keep alive timeout</para></listitem>
<listitem><para><option>142</option> Session taken over</para></listitem>
<listitem><para><option>143</option> Topic filter invalid</para></listitem>
<listitem><para><option>144</option> Topic name invalid</para></listitem>
<listitem><para><option>147</option> Receive maximum exceeded</para></listitem>
<listitem><para><option>148</option> Topic alias invalid</para></listitem>
<listitem><para><option>149</option> Packet too large</para></listitem>
<listitem><para><option>148</option> Message rate too high</para></listitem>
<listitem><para><option>151</option> Quota exceeded</para></listitem>
<listitem><para><option>152</option> Administrative action</para></listitem>
<listitem><para><option>153</option> Payload format invalid</para></listitem>
<listitem><para><option>154</option> Retain not supported</para></listitem>
<listitem><para><option>155</option> QoS not supported</para></listitem>
<listitem><para><option>156</option> Use another server</para></listitem>
<listitem><para><option>157</option> Server moved</para></listitem>
<listitem><para><option>158</option> Shared subscriptions not supported</para></listitem>
<listitem><para><option>159</option> Connection rate exceeded</para></listitem>
<listitem><para><option>160</option> Maximum connect time</para></listitem>
<listitem><para><option>161</option> Subscription IDs not supported</para></listitem>
<listitem><para><option>162</option> Wildcard subscriptions not supported</para></listitem>
</itemizedlist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>Publish temperature information to localhost with QoS 1:</para>

@ -983,7 +983,7 @@ mosquitto_sub -t 'bbc/#' -T bbc/bbc1 --remove-retained</programlisting>
<title>Connect</title>
<itemizedlist>
<listitem><para><option>authentication-data</option> (binary data - note treated as a string in mosquitto_sub)</para></listitem>
<listitem><para><option>authentication-method</option> (UTF-8 string pair)</para></listitem>
<listitem><para><option>authentication-method</option> (UTF-8 string)</para></listitem>
<listitem><para><option>maximum-packet-size</option> (32-bit unsigned integer)</para></listitem>
<listitem><para><option>receive-maximum</option> (16-bit unsigned integer)</para></listitem>
<listitem><para><option>request-problem-information</option> (8-bit unsigned integer)</para></listitem>
@ -1030,6 +1030,64 @@ mosquitto_sub -t 'bbc/#' -T bbc/bbc1 --remove-retained</programlisting>
</refsect2>
</refsect1>
<refsect1>
<title>Exit Status</title>
<para>
mosquitto_sub returns zero on success, or non-zero on error. If
the connection is refused by the broker at the MQTT level, then
the exit code is the CONNACK reason code. If another error
occurs, the exit code is a libmosquitto return value.
</para>
<para>MQTT v3.1.1 CONNACK codes:</para>
<itemizedlist mark="circle">
<listitem><para><option>0</option> Success</para></listitem>
<listitem><para><option>1</option> Connection refused: Bad protocol version</para></listitem>
<listitem><para><option>2</option> Connection refused: Identifier rejected</para></listitem>
<listitem><para><option>3</option> Connection refused: Server unavailable</para></listitem>
<listitem><para><option>4</option> Connection refused: Bad username/password</para></listitem>
<listitem><para><option>5</option> Connection refused: Not authorized</para></listitem>
</itemizedlist>
<para>MQTT v5 CONNACK codes:</para>
<itemizedlist>
<listitem><para><option>0</option> Success</para></listitem>
<listitem><para><option>128</option> Unspecified error</para></listitem>
<listitem><para><option>129</option> Malformed packet</para></listitem>
<listitem><para><option>130</option> Protocol error</para></listitem>
<listitem><para><option>131</option> Implementation specific error</para></listitem>
<listitem><para><option>132</option> Unsupported protocol version</para></listitem>
<listitem><para><option>133</option> Client ID not valid</para></listitem>
<listitem><para><option>134</option> Bad username or password</para></listitem>
<listitem><para><option>135</option> Not authorized</para></listitem>
<listitem><para><option>136</option> Server unavailable</para></listitem>
<listitem><para><option>137</option> Server busy</para></listitem>
<listitem><para><option>138</option> Banned</para></listitem>
<listitem><para><option>139</option> Server shutting down</para></listitem>
<listitem><para><option>140</option> Bad authentication method</para></listitem>
<listitem><para><option>141</option> Keep alive timeout</para></listitem>
<listitem><para><option>142</option> Session taken over</para></listitem>
<listitem><para><option>143</option> Topic filter invalid</para></listitem>
<listitem><para><option>144</option> Topic name invalid</para></listitem>
<listitem><para><option>147</option> Receive maximum exceeded</para></listitem>
<listitem><para><option>148</option> Topic alias invalid</para></listitem>
<listitem><para><option>149</option> Packet too large</para></listitem>
<listitem><para><option>148</option> Message rate too high</para></listitem>
<listitem><para><option>151</option> Quota exceeded</para></listitem>
<listitem><para><option>152</option> Administrative action</para></listitem>
<listitem><para><option>153</option> Payload format invalid</para></listitem>
<listitem><para><option>154</option> Retain not supported</para></listitem>
<listitem><para><option>155</option> QoS not supported</para></listitem>
<listitem><para><option>156</option> Use another server</para></listitem>
<listitem><para><option>157</option> Server moved</para></listitem>
<listitem><para><option>158</option> Shared subscriptions not supported</para></listitem>
<listitem><para><option>159</option> Connection rate exceeded</para></listitem>
<listitem><para><option>160</option> Maximum connect time</para></listitem>
<listitem><para><option>161</option> Subscription IDs not supported</para></listitem>
<listitem><para><option>162</option> Wildcard subscriptions not supported</para></listitem>
</itemizedlist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>Note that these really are examples - the subscriptions will work

@ -230,8 +230,10 @@
# a per listener setting.
# Default is -1, which means unlimited connections.
# Note that other process limits mean that unlimited connections
# are not really possible. Typically the default maximum number of
# connections possible is around 1024.
# are not really possible. Typically operating systems such as Linux set a
# default maximum number of connections possible at around 1024. If you require
# more connections than this, the operating system limit must be increased with
# something like `ulimit`.
#max_connections -1
# Choose the protocol to use when listening.

@ -1,8 +1,8 @@
[Unit]
Description=Mosquitto MQTT v3.1/v3.1.1 Broker
Description=Mosquitto MQTT Broker
Documentation=man:mosquitto.conf(5) man:mosquitto(8)
After=network-online.target
Wants=network-online.target
After=network.target
Wants=network.target
[Service]
Type=notify
@ -10,6 +10,8 @@ NotifyAccess=main
ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
ExecStartPre=/bin/mkdir -m 740 -p /var/log/mosquitto
ExecStartPre=/bin/chown mosquitto: /var/log/mosquitto
[Install]
WantedBy=multi-user.target

@ -1,13 +1,15 @@
[Unit]
Description=Mosquitto MQTT v3.1/v3.1.1 Broker
Description=Mosquitto MQTT Broker
Documentation=man:mosquitto.conf(5) man:mosquitto(8)
After=network-online.target
Wants=network-online.target
After=network.target
Wants=network.target
[Service]
ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
ExecStartPre=/bin/mkdir -m 740 -p /var/log/mosquitto
ExecStartPre=/bin/chown mosquitto: /var/log/mosquitto
[Install]
WantedBy=multi-user.target

@ -2,7 +2,7 @@
MAJOR=1
MINOR=6
REVISION=9
REVISION=12
sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk

@ -1,7 +1,7 @@
name: mosquitto
version: 1.6.9
version: 1.6.12
summary: Eclipse Mosquitto MQTT broker
description: This is a message broker that supports version 3.1 and 3.1.1 of the MQTT
description: This is a message broker that supports version 5.0, 3.1.1, and 3.1 of the MQTT
protocol.
MQTT provides a method of carrying out messaging using a publish/subscribe
model. It is lightweight, both in terms of bandwidth usage and ease of
@ -10,6 +10,7 @@ description: This is a message broker that supports version 3.1 and 3.1.1 of the
example.
confinement: strict
grade: stable
base: core18
apps:
mosquitto:

@ -71,7 +71,6 @@ set (MOSQ_SRCS
../lib/will_mosq.c ../lib/will_mosq.h)
option(WITH_BUNDLED_DEPS "Build with bundled dependencies?" ON)
if (WITH_BUNDLED_DEPS)
include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/src/deps)
endif (WITH_BUNDLED_DEPS)
@ -158,6 +157,10 @@ endif (HAVE_GETADDRINFO_A AND WITH_ADNS)
if (UNIX)
if (APPLE)
set (MOSQ_LIBS ${MOSQ_LIBS} dl m)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
set (MOSQ_LIBS ${MOSQ_LIBS} m)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
set (MOSQ_LIBS ${MOSQ_LIBS} m)
elseif(QNX)
set(MOSQ_LIBS ${MOSQ_LIBS} m socket)
else(APPLE)

@ -21,6 +21,78 @@ Contributors:
#include "memory_mosq.h"
#ifdef WITH_BRIDGE
static int bridge__create_remap_topic(const char *prefix, const char *topic, char **remap_topic)
{
int len;
if(prefix){
if(topic){
len = strlen(topic) + strlen(prefix)+1;
*remap_topic = mosquitto__malloc(len+1);
if(!(*remap_topic)){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
snprintf(*remap_topic, len+1, "%s%s", prefix, topic);
(*remap_topic)[len] = '\0';
}else{
*remap_topic = mosquitto__strdup(prefix);
if(!(*remap_topic)){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
}
}else{
*remap_topic = mosquitto__strdup(topic);
if(!(*remap_topic)){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
}
return MOSQ_ERR_SUCCESS;
}
static int bridge__create_prefix(char **full_prefix, const char *topic, const char *prefix, const char *direction)
{
int len;
if(mosquitto_pub_topic_check(prefix) != MOSQ_ERR_SUCCESS){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic local prefix '%s'.", prefix);
return MOSQ_ERR_INVAL;
}
if(topic){
len = strlen(topic) + strlen(prefix) + 1;
}else{
len = strlen(prefix) + 1;
}
*full_prefix = mosquitto__malloc(len);
if(*full_prefix == NULL){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
if(topic){
/* Print full_prefix+pattern to check for validity */
snprintf(*full_prefix, len, "%s%s", prefix, topic);
}else{
snprintf(*full_prefix, len, "%s", prefix);
}
if(mosquitto_sub_topic_check(*full_prefix) != MOSQ_ERR_SUCCESS){
log__printf(NULL, MOSQ_LOG_ERR,
"Error: Invalid bridge topic %s prefix and pattern combination '%s'.",
direction, *full_prefix);
return MOSQ_ERR_INVAL;
}
/* Print just the prefix for storage */
snprintf(*full_prefix, len, "%s", prefix);
return MOSQ_ERR_SUCCESS;
}
/* topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix] */
@ -28,7 +100,6 @@ int bridge__add_topic(struct mosquitto__bridge *bridge, const char *topic, enum
{
struct mosquitto__bridge_topic *topics;
struct mosquitto__bridge_topic *cur_topic;
int len;
if(bridge == NULL) return MOSQ_ERR_INVAL;
@ -83,69 +154,29 @@ int bridge__add_topic(struct mosquitto__bridge *bridge, const char *topic, enum
if(local_prefix || remote_prefix){
bridge->topic_remapping = true;
if(local_prefix){
cur_topic->local_prefix = mosquitto__strdup(local_prefix);
if(cur_topic->local_prefix == NULL){
if(bridge__create_prefix(&cur_topic->local_prefix, cur_topic->topic, local_prefix, "local")){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
}
if(remote_prefix){
cur_topic->remote_prefix = mosquitto__strdup(remote_prefix);
if(cur_topic->remote_prefix == NULL){
if(bridge__create_prefix(&cur_topic->remote_prefix, cur_topic->topic, remote_prefix, "local")){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
}
}
if(cur_topic->local_prefix){
if(cur_topic->topic){
len = strlen(cur_topic->topic) + strlen(cur_topic->local_prefix)+1;
cur_topic->local_topic = mosquitto__malloc(len+1);
if(!cur_topic->local_topic){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
snprintf(cur_topic->local_topic, len+1, "%s%s", cur_topic->local_prefix, cur_topic->topic);
cur_topic->local_topic[len] = '\0';
}else{
cur_topic->local_topic = mosquitto__strdup(cur_topic->local_prefix);
if(!cur_topic->local_topic){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
}
}else{
cur_topic->local_topic = mosquitto__strdup(cur_topic->topic);
if(!cur_topic->local_topic){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
if(bridge__create_remap_topic(cur_topic->local_prefix,
cur_topic->topic, &cur_topic->local_topic)){
return MOSQ_ERR_INVAL;
}
if(cur_topic->remote_prefix){
if(cur_topic->topic){
len = strlen(cur_topic->topic) + strlen(cur_topic->remote_prefix)+1;
cur_topic->remote_topic = mosquitto__malloc(len+1);
if(!cur_topic->remote_topic){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
snprintf(cur_topic->remote_topic, len, "%s%s", cur_topic->remote_prefix, cur_topic->topic);
cur_topic->remote_topic[len] = '\0';
}else{
cur_topic->remote_topic = mosquitto__strdup(cur_topic->remote_prefix);
if(!cur_topic->remote_topic){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
}
}else{
cur_topic->remote_topic = mosquitto__strdup(cur_topic->topic);
if(!cur_topic->remote_topic){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
if(bridge__create_remap_topic(cur_topic->remote_prefix,
cur_topic->topic, &cur_topic->remote_topic)){
return MOSQ_ERR_INVAL;
}
return MOSQ_ERR_SUCCESS;

@ -355,7 +355,7 @@ void config__cleanup(struct mosquitto__config *config)
static void print_usage(void)
{
printf("mosquitto version %s\n\n", VERSION);
printf("mosquitto is an MQTT v3.1.1 broker.\n\n");
printf("mosquitto is an MQTT v5.0/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");
@ -364,7 +364,7 @@ static void print_usage(void)
printf(" Not recommended in conjunction with the -c option.\n");
printf(" -v : verbose mode - enable all logging types. This overrides\n");
printf(" any logging options given in the config file.\n");
printf("\nSee http://mosquitto.org/ for more information.\n\n");
printf("\nSee https://mosquitto.org/ for more information.\n\n");
}
int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config, int argc, char *argv[])
@ -716,6 +716,7 @@ int config__read(struct mosquitto_db *db, struct mosquitto__config *config, bool
return MOSQ_ERR_SUCCESS;
}
int config__read_file_core(struct mosquitto__config *config, bool reload, struct config_recurse *cr, int level, int *lineno, FILE *fptr, char **buf, int *buflen)
{
int rc;
@ -734,6 +735,12 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
int i;
int lineno_ext = 0;
int prefix_len;
char **files;
int file_count;
#ifdef WITH_TLS
char *kpass_sha = NULL, *kpass_sha_bin = NULL;
char *keyform ;
#endif
*lineno = 0;
@ -754,7 +761,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_string(&token, "acl_file", &cur_security_options->acl_file, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "address") || !strcmp(token, "addresses")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge || cur_bridge->addresses){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -816,7 +823,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
conf__set_cur_security_options(config, cur_listener, &cur_security_options);
if(conf__parse_bool(&token, "allow_zero_length_clientid", &cur_security_options->allow_zero_length_clientid, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strncmp(token, "auth_opt_", strlen("auth_opt_")) || !strncmp(token, "plugin_opt_", strlen("plugin_opt_"))){
if(reload) continue; // Auth plugin not currently valid for reloading.
if(reload) continue; /* Auth plugin not currently valid for reloading. */
if(!cur_auth_plugin_config){
log__printf(NULL, MOSQ_LOG_ERR, "Error: An auth_opt_ option exists in the config file without an auth_plugin.");
return MOSQ_ERR_INVAL;
@ -880,7 +887,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
cur_security_options->auth_plugin_config_count++;
if(conf__parse_string(&token, "auth_plugin", &cur_auth_plugin_config->path, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "auth_plugin_deny_special_chars")){
if(reload) continue; // Auth plugin not currently valid for reloading.
if(reload) continue; /* Auth plugin not currently valid for reloading. */
if(!cur_auth_plugin_config){
log__printf(NULL, MOSQ_LOG_ERR, "Error: An auth_plugin_deny_special_chars option exists in the config file without an auth_plugin.");
return MOSQ_ERR_INVAL;
@ -901,14 +908,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_bool(&token, "autosave_on_changes", &config->autosave_on_changes, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "bind_address")){
config->local_only = false;
if(reload) continue; // Listener not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "default listener bind_address", &config->default_listener.host, saveptr)) return MOSQ_ERR_INVAL;
if(conf__attempt_resolve(config->default_listener.host, "bind_address", MOSQ_LOG_ERR, "Error")){
return MOSQ_ERR_INVAL;
}
}else if(!strcmp(token, "bind_interface")){
#ifdef SO_BINDTODEVICE
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "bind_interface", &cur_listener->bind_interface, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_ERR, "Error: bind_interface specified but socket option not available.");
@ -916,7 +923,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_attempt_unsubscribe")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -927,7 +934,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_cafile")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -944,7 +951,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_alpn")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -955,7 +962,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_capath")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -972,7 +979,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_certfile")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -989,7 +996,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_identity")){
#if defined(WITH_BRIDGE) && defined(FINAL_WITH_TLS_PSK)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1004,7 +1011,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_insecure")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1018,7 +1025,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_require_ocsp")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1040,7 +1047,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_keyfile")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1057,7 +1064,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_protocol_version")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1083,7 +1090,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_psk")){
#if defined(WITH_BRIDGE) && defined(FINAL_WITH_TLS_PSK)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1098,7 +1105,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "bridge_tls_version")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1109,7 +1116,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "cafile")){
#if defined(WITH_TLS)
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(cur_listener->psk_hint){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Cannot use both certificate and psk encryption in a single listener.");
return MOSQ_ERR_INVAL;
@ -1120,14 +1127,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "capath")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "capath", &cur_listener->capath, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "certfile")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(cur_listener->psk_hint){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Cannot use both certificate and psk encryption in a single listener.");
return MOSQ_ERR_INVAL;
@ -1141,14 +1148,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_bool(&token, "check_retain_source", &config->check_retain_source, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "ciphers")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "ciphers", &cur_listener->ciphers, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "clientid") || !strcmp(token, "remote_clientid")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1159,7 +1166,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "cleansession")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1187,7 +1194,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_string(&token, "clientid_prefixes", &config->clientid_prefixes, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "connection")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
token = strtok_r(NULL, " ", &saveptr);
if(token){
/* Check for existing bridge name. */
@ -1237,28 +1244,28 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_bool(&token, token, &config->connection_messages, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "crlfile")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "crlfile", &cur_listener->crlfile, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "dhparamfile")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "dhparamfile", &cur_listener->dhparamfile, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "http_dir")){
#ifdef WITH_WEBSOCKETS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "http_dir", &cur_listener->http_dir, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Websockets support not available.");
#endif
}else if(!strcmp(token, "idle_timeout")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1280,8 +1287,6 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
return 1;
}
char **files;
int file_count;
rc = config__get_dir_files(token, &files, &file_count);
if(rc) return rc;
@ -1305,7 +1310,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
}else if(!strcmp(token, "keepalive_interval")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1320,7 +1325,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "keyfile")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "keyfile", &cur_listener->keyfile, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
@ -1416,7 +1421,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
}else if(!strcmp(token, "local_clientid")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1427,7 +1432,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "local_password")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1438,7 +1443,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "local_username")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1575,7 +1580,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty log_type value in configuration.");
}
}else if(!strcmp(token, "max_connections")){
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
token = strtok_r(NULL, " ", &saveptr);
if(token){
cur_listener->max_connections = atoi(token);
@ -1584,7 +1589,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty max_connections value in configuration.");
}
}else if(!strcmp(token, "maximum_qos")){
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_int(&token, "maximum_qos", &tmp_int, saveptr)) return MOSQ_ERR_INVAL;
if(tmp_int < 0 || tmp_int > 2){
log__printf(NULL, MOSQ_LOG_ERR, "Error: maximum_qos must be between 0 and 2 inclusive.");
@ -1651,7 +1656,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
return MOSQ_ERR_INVAL;
}
}else if(!strcmp(token, "mount_point")){
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(config->listener_count == 0){
log__printf(NULL, MOSQ_LOG_ERR, "Error: You must use create a listener before using the mount_point option in the configuration file.");
return MOSQ_ERR_INVAL;
@ -1665,7 +1670,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
}else if(!strcmp(token, "notifications")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1676,7 +1681,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "notifications_local_only")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration");
return MOSQ_ERR_INVAL;
@ -1687,7 +1692,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "notification_topic")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1698,7 +1703,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "password") || !strcmp(token, "remote_password")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1759,11 +1764,11 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty persistent_client_expiration value in configuration.");
}
}else if(!strcmp(token, "pid_file")){
if(reload) continue; // pid file not valid for reloading.
if(reload) continue; /* pid file not valid for reloading. */
if(conf__parse_string(&token, "pid_file", &config->pid_file, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "port")){
config->local_only = false;
if(reload) continue; // Listener not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(config->default_listener.port){
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Default listener port specified multiple times. Only the latest will be used.");
}
@ -1810,7 +1815,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "psk_hint")){
#ifdef FINAL_WITH_TLS_PSK
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "psk_hint", &cur_listener->psk_hint, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS/TLS-PSK support not available.");
@ -1819,14 +1824,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_bool(&token, token, &config->queue_qos0_messages, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "require_certificate")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_bool(&token, "require_certificate", &cur_listener->require_certificate, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "restart_timeout")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1859,7 +1864,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: The retry_interval option is no longer available.");
}else if(!strcmp(token, "round_robin")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1872,7 +1877,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_bool(&token, "set_tcp_nodelay", &config->set_tcp_nodelay, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "start_type")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1900,7 +1905,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
#endif
}else if(!strcmp(token, "socket_domain")){
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
token = strtok_r(NULL, " ", &saveptr);
if(token){
if(!strcmp(token, "ipv4")){
@ -1925,7 +1930,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
}else if(!strcmp(token, "threshold")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -1940,15 +1945,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "tls_engine")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "tls_engine", &cur_listener->tls_engine, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "tls_engine_kpass_sha1")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
char *kpass_sha = NULL, *kpass_sha_bin = NULL;
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "tls_engine_kpass_sha1", &kpass_sha, saveptr)) return MOSQ_ERR_INVAL;
if(mosquitto__hex2bin_sha1(kpass_sha, (unsigned char**)&kpass_sha_bin) != MOSQ_ERR_SUCCESS){
mosquitto__free(kpass_sha);
@ -1961,8 +1965,8 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "tls_keyform")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
char *keyform = NULL;
if(reload) continue; /* Listeners not valid for reloading. */
keyform = NULL;
if(conf__parse_string(&token, "tls_keyform", &keyform, saveptr)) return MOSQ_ERR_INVAL;
cur_listener->tls_keyform = mosq_k_pem;
if(!strcmp(keyform, "engine")) cur_listener->tls_keyform = mosq_k_engine;
@ -1972,14 +1976,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#endif
}else if(!strcmp(token, "tls_version")){
#if defined(WITH_TLS)
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_string(&token, "tls_version", &cur_listener->tls_version, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "topic")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -2041,6 +2045,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
}
}
if(bridge__add_topic(cur_bridge, topic, direction, qos, local_prefix, remote_prefix)){
return MOSQ_ERR_INVAL;
}
@ -2048,7 +2053,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
#endif
}else if(!strcmp(token, "max_topic_alias")){
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
token = strtok_r(NULL, " ", &saveptr);
if(token){
cur_listener->max_topic_alias = atoi(token);
@ -2057,7 +2062,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
}else if(!strcmp(token, "try_private")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
@ -2070,28 +2075,28 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_bool(&token, token, &config->upgrade_outgoing_qos, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "use_identity_as_username")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_bool(&token, "use_identity_as_username", &cur_listener->use_identity_as_username, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "use_subject_as_username")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_bool(&token, "use_subject_as_username", &cur_listener->use_subject_as_username, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "user")){
if(reload) continue; // Drop privileges user not valid for reloading.
if(reload) continue; /* Drop privileges user not valid for reloading. */
mosquitto__free(config->user);
if(conf__parse_string(&token, "user", &config->user, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "use_username_as_clientid")){
if(reload) continue; // Listeners not valid for reloading.
if(reload) continue; /* Listeners not valid for reloading. */
if(conf__parse_bool(&token, "use_username_as_clientid", &cur_listener->use_username_as_clientid, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "username") || !strcmp(token, "remote_username")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(reload) continue; /* FIXME */
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;

@ -198,6 +198,10 @@ void context__send_will(struct mosquitto_db *db, struct mosquitto *ctxt)
void context__disconnect(struct mosquitto_db *db, struct mosquitto *context)
{
if(mosquitto__get_state(context) == mosq_cs_disconnected){
return;
}
net__socket_close(db, context);
context__send_will(db, context);
@ -231,12 +235,8 @@ void context__add_to_disused(struct mosquitto_db *db, struct mosquitto *context)
context->id = NULL;
}
if(db->ll_for_free){
context->for_free_next = db->ll_for_free;
db->ll_for_free = context;
}else{
db->ll_for_free = context;
}
context->for_free_next = db->ll_for_free;
db->ll_for_free = context;
}
void context__free_disused(struct mosquitto_db *db)
@ -248,6 +248,7 @@ void context__free_disused(struct mosquitto_db *db)
assert(db);
context = db->ll_for_free;
db->ll_for_free = NULL;
while(context){
#ifdef WITH_WEBSOCKETS
if(context->wsi){
@ -269,7 +270,6 @@ void context__free_disused(struct mosquitto_db *db)
context = next;
}
}
db->ll_for_free = NULL;
}

@ -37,7 +37,7 @@ static unsigned long max_queued_bytes = 0;
* @param qos qos for the packet of interest
* @return true if more in flight are allowed.
*/
static bool db__ready_for_flight(struct mosquitto_msg_data *msgs, int qos)
bool db__ready_for_flight(struct mosquitto_msg_data *msgs, int qos)
{
bool valid_bytes;
bool valid_count;
@ -68,12 +68,14 @@ static bool db__ready_for_flight(struct mosquitto_msg_data *msgs, int qos)
* @param qos destination qos for the packet of interest
* @return true if queuing is allowed, false if should be dropped
*/
static bool db__ready_for_queue(struct mosquitto *context, int qos, struct mosquitto_msg_data *msg_data)
bool db__ready_for_queue(struct mosquitto *context, int qos, struct mosquitto_msg_data *msg_data)
{
int source_count;
int adjust_count;
unsigned long source_bytes;
unsigned long adjust_bytes = max_inflight_bytes;
bool valid_bytes;
bool valid_count;
if(max_queued == 0 && max_queued_bytes == 0){
return true;
@ -94,8 +96,8 @@ static bool db__ready_for_queue(struct mosquitto *context, int qos, struct mosqu
adjust_count = 0;
}
bool valid_bytes = source_bytes - adjust_bytes < max_queued_bytes;
bool valid_count = source_count - adjust_count < max_queued;
valid_bytes = source_bytes - adjust_bytes < max_queued_bytes;
valid_count = source_count - adjust_count < max_queued;
if(max_queued_bytes == 0){
return valid_count;
@ -343,6 +345,9 @@ int db__message_delete_outgoing(struct mosquitto_db *db, struct mosquitto *conte
}
db__message_dequeue_first(context, &context->msgs_out);
}
#ifdef WITH_PERSISTENCE
db->persistence_changes++;
#endif
return db__message_write_inflight_out_latest(db, context);
}
@ -398,6 +403,10 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
}
}
}
if(context->bridge && context->bridge->clean_start_local == true){
mosquitto_property_free_all(&properties);
return 2;
}
}
if(context->sock != INVALID_SOCKET){

@ -110,8 +110,8 @@ static int dump__cfg_chunk_process(struct mosquitto_db *db, FILE *db_fd, uint32_
memset(&chunk, 0, sizeof(struct PF_cfg));
if(db_version == 5){
rc = persist__chunk_cfg_read_v5(db_fd, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_cfg_read_v56(db_fd, &chunk);
}else{
rc = persist__chunk_cfg_read_v234(db_fd, &chunk);
}
@ -147,8 +147,8 @@ static int dump__client_chunk_process(struct mosquitto_db *db, FILE *db_fd, uint
memset(&chunk, 0, sizeof(struct P_client));
if(db_version == 5){
rc = persist__chunk_client_read_v5(db_fd, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_client_read_v56(db_fd, &chunk, db_version);
}else{
rc = persist__chunk_client_read_v234(db_fd, &chunk, db_version);
}
@ -189,8 +189,8 @@ static int dump__client_msg_chunk_process(struct mosquitto_db *db, FILE *db_fd,
client_msg_count++;
memset(&chunk, 0, sizeof(struct P_client_msg));
if(db_version == 5){
rc = persist__chunk_client_msg_read_v5(db_fd, &chunk, length);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_client_msg_read_v56(db_fd, &chunk, length);
}else{
rc = persist__chunk_client_msg_read_v234(db_fd, &chunk);
}
@ -234,8 +234,8 @@ static int dump__msg_store_chunk_process(struct mosquitto_db *db, FILE *db_fptr,
msg_store_count++;
memset(&chunk, 0, sizeof(struct P_msg_store));
if(db_version == 5){
rc = persist__chunk_msg_store_read_v5(db_fptr, &chunk, length);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_msg_store_read_v56(db_fptr, &chunk, length);
}else{
rc = persist__chunk_msg_store_read_v234(db_fptr, &chunk, db_version);
}
@ -328,8 +328,8 @@ static int dump__retain_chunk_process(struct mosquitto_db *db, FILE *db_fd, uint
if(do_print) printf("DB_CHUNK_RETAIN:\n");
if(do_print) printf("\tLength: %d\n", length);
if(db_version == 5){
rc = persist__chunk_retain_read_v5(db_fd, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_retain_read_v56(db_fd, &chunk);
}else{
rc = persist__chunk_retain_read_v234(db_fd, &chunk);
}
@ -352,8 +352,8 @@ static int dump__sub_chunk_process(struct mosquitto_db *db, FILE *db_fd, uint32_
sub_count++;
memset(&chunk, 0, sizeof(struct P_sub));
if(db_version == 5){
rc = persist__chunk_sub_read_v5(db_fd, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_sub_read_v56(db_fd, &chunk);
}else{
rc = persist__chunk_sub_read_v234(db_fd, &chunk);
}

@ -145,6 +145,12 @@ void print__client(struct P_client *chunk, int length)
printf("DB_CHUNK_CLIENT:\n");
printf("\tLength: %d\n", length);
printf("\tClient ID: %s\n", chunk->client_id);
if(chunk->username){
printf("\tUsername: %s\n", chunk->username);
}
if(chunk->F.listener_port > 0){
printf("\tListener port: %u\n", chunk->F.listener_port);
}
printf("\tLast MID: %d\n", chunk->F.last_mid);
printf("\tSession expiry time: %" PRIu64 "\n", chunk->F.session_expiry_time);
printf("\tSession expiry interval: %u\n", chunk->F.session_expiry_interval);

@ -384,12 +384,17 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
uint16_t auth_data_len = 0;
void *auth_data_out = NULL;
uint16_t auth_data_out_len = 0;
bool allow_zero_length_clientid;
#ifdef WITH_TLS
int i;
X509 *client_cert = NULL;
X509_NAME *name;
X509_NAME_ENTRY *name_entry;
ASN1_STRING *name_asn1 = NULL;
BIO *subject_bio;
char *data_start;
long name_length;
char *subject;
#endif
G_CONNECTION_COUNT_INC();
@ -500,7 +505,7 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
rc = MOSQ_ERR_PROTOCOL;
goto handle_connect_error;
}
will_retain = ((connect_flags & 0x20) == 0x20); // Temporary hack because MSVC<1800 doesn't have stdbool.h.
will_retain = ((connect_flags & 0x20) == 0x20);
password_flag = connect_flags & 0x40;
username_flag = connect_flags & 0x80;
@ -543,7 +548,6 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
mosquitto__free(client_id);
client_id = NULL;
bool allow_zero_length_clientid;
if(db->config->per_listener_settings){
allow_zero_length_clientid = context->listener->security_options.allow_zero_length_clientid;
}else{
@ -699,7 +703,7 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
rc = 1;
goto handle_connect_error;
}
if (context->listener->use_identity_as_username) { //use_identity_as_username
if (context->listener->use_identity_as_username) { /* use_identity_as_username */
i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
if(i == -1){
if(context->protocol == mosq_p_mqtt5){
@ -747,12 +751,12 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
goto handle_connect_error;
}
}
} else { // use_subject_as_username
BIO *subject_bio = BIO_new(BIO_s_mem());
} else { /* use_subject_as_username */
subject_bio = BIO_new(BIO_s_mem());
X509_NAME_print_ex(subject_bio, X509_get_subject_name(client_cert), 0, XN_FLAG_RFC2253);
char *data_start = NULL;
long name_length = BIO_get_mem_data(subject_bio, &data_start);
char *subject = mosquitto__malloc(sizeof(char)*name_length+1);
data_start = NULL;
name_length = BIO_get_mem_data(subject_bio, &data_start);
subject = mosquitto__malloc(sizeof(char)*name_length+1);
if(!subject){
BIO_free(subject_bio);
rc = MOSQ_ERR_NOMEM;

@ -272,9 +272,18 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
db__message_store_find(context, msg->source_mid, &stored);
}
if(!stored){
dup = 0;
if(db__message_store(db, context, msg, message_expiry_interval, 0, mosq_mo_client)){
return 1;
if(msg->qos == 0
|| db__ready_for_flight(&context->msgs_in, msg->qos)
|| db__ready_for_queue(context, msg->qos, &context->msgs_in)){
dup = 0;
if(db__message_store(db, context, msg, message_expiry_interval, 0, mosq_mo_client)){
return 1;
}
}else{
/* Client isn't allowed any more incoming messages, so fail early */
reason_code = MQTT_RC_QUOTA_EXCEEDED;
goto process_bad_message;
}
stored = msg;
msg = NULL;
@ -309,6 +318,7 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
}
/* db__message_insert() returns 2 to indicate dropped message
* due to queue. This isn't an error so don't disconnect them. */
/* FIXME - this is no longer necessary due to failing early above */
if(!res){
if(send__pubrec(context, stored->source_mid, 0, NULL)) rc = 1;
}else if(res == 1){

@ -24,6 +24,7 @@ Contributors:
#include <time.h>
#ifdef WITH_DLT
#include <sys/stat.h>
#include <dlt/dlt.h>
#endif
@ -55,6 +56,29 @@ static int log_priorities = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE |
#ifdef WITH_DLT
static DltContext dltContext;
static bool dlt_allowed = false;
void dlt_fifo_check(void)
{
struct stat statbuf;
int fd;
/* If we start DLT but the /tmp/dlt fifo doesn't exist, or isn't available
* for writing then there is a big delay when we try and close the log
* later, so check for it first. This has the side effect of not letting
* people using DLT create the fifo after Mosquitto has started, but at the
* benefit of not having a massive delay for everybody else. */
memset(&statbuf, 0, sizeof(statbuf));
if(stat("/tmp/dlt", &statbuf) == 0){
if(S_ISFIFO(statbuf.st_mode)){
fd = open("/tmp/dlt", O_NONBLOCK | O_WRONLY);
if(fd != -1){
dlt_allowed = true;
close(fd);
}
}
}
}
#endif
static int get_time(struct tm **ti)
@ -110,16 +134,18 @@ int log__init(struct mosquitto__config *config)
return 1;
}
config->log_fptr = mosquitto__fopen(config->log_file, "at", true);
if(!config->log_fptr){
if(config->log_fptr){
setvbuf(config->log_fptr, NULL, _IOLBF, 0);
}else{
log_destinations = MQTT3_LOG_STDERR;
log_priorities = MOSQ_LOG_ERR;
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open log file %s for writing.", config->log_file);
return MOSQ_ERR_INVAL;
}
restore_privileges();
}
#ifdef WITH_DLT
if(log_destinations & MQTT3_LOG_DLT){
dlt_fifo_check();
if(dlt_allowed){
DLT_REGISTER_APP("MQTT","mosquitto log");
dlt_register_context(&dltContext, "MQTT", "mosquitto DLT context");
}
@ -144,7 +170,7 @@ int log__close(struct mosquitto__config *config)
}
#ifdef WITH_DLT
if(log_destinations & MQTT3_LOG_DLT){
if(dlt_allowed){
dlt_unregister_context(&dltContext);
DLT_UNREGISTER_APP();
}
@ -186,7 +212,6 @@ int log__vprintf(int priority, const char *fmt, va_list va)
const char *topic;
int syslog_priority;
time_t now = time(NULL);
static time_t last_flush = 0;
char time_buf[50];
bool log_timestamp = true;
char *log_timestamp_format = NULL;
@ -298,7 +323,6 @@ int log__vprintf(int priority, const char *fmt, va_list va)
}else{
fprintf(stdout, "%s\n", s);
}
fflush(stdout);
}
if(log_destinations & MQTT3_LOG_STDERR){
if(log_timestamp){
@ -310,7 +334,6 @@ int log__vprintf(int priority, const char *fmt, va_list va)
}else{
fprintf(stderr, "%s\n", s);
}
fflush(stderr);
}
if(log_destinations & MQTT3_LOG_FILE && log_fptr){
if(log_timestamp){
@ -322,10 +345,6 @@ int log__vprintf(int priority, const char *fmt, va_list va)
}else{
fprintf(log_fptr, "%s\n", s);
}
if(now - last_flush > 1){
fflush(log_fptr);
last_flush = now;
}
}
if(log_destinations & MQTT3_LOG_SYSLOG){
#ifndef WIN32

@ -490,6 +490,18 @@ int main(int argc, char *argv[])
rc = mosquitto_security_init(&int_db, false);
if(rc) return rc;
/* After loading persisted clients and ACLs, try to associate them,
* so persisted subscriptions can start storing messages */
HASH_ITER(hh_id, int_db.contexts_by_id, ctxt, ctxt_tmp){
if(ctxt && !ctxt->clean_start && ctxt->username){
rc = acl__find_acls(&int_db, ctxt);
if(rc){
log__printf(NULL, MOSQ_LOG_WARNING, "Failed to associate persisted user %s with ACLs, "
"likely due to changed ports while using a per_listener_settings configuration.", ctxt->username);
}
}
}
#ifdef WITH_SYS_TREE
sys_tree__init(&int_db);
#endif
@ -505,6 +517,7 @@ int main(int argc, char *argv[])
bridge__start_all(&int_db);
#endif
log__printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s running", VERSION);
#ifdef WITH_SYSTEMD
sd_notify(0, "READY=1");
#endif

@ -706,6 +706,8 @@ void db__msg_store_clean(struct mosquitto_db *db);
void db__msg_store_compact(struct mosquitto_db *db);
void db__msg_store_free(struct mosquitto_msg_store *store);
int db__message_reconnect_reset(struct mosquitto_db *db, struct mosquitto *context);
bool db__ready_for_flight(struct mosquitto_msg_data *msgs, int qos);
bool db__ready_for_queue(struct mosquitto *context, int qos, struct mosquitto_msg_data *msg_data);
void sys_tree__init(struct mosquitto_db *db);
void sys_tree__update(struct mosquitto_db *db, int interval, time_t start_time);
int db__message_write_inflight_out_all(struct mosquitto_db *db, struct mosquitto *context);

@ -139,7 +139,7 @@ void print_usage(void)
{
printf("mosquitto_passwd is a tool for managing password files for mosquitto.\n\n");
printf("Usage: mosquitto_passwd [-H sha512 | -H sha512-pbkdf2] [-c | -D] passwordfile username\n");
printf(" mosquitto_passwd [-H sha512 | -H sha512-pbkdf2] -b passwordfile username password\n");
printf(" mosquitto_passwd [-H sha512 | -H sha512-pbkdf2] [-c] -b passwordfile username password\n");
printf(" mosquitto_passwd -U passwordfile\n");
printf(" -b : run in batch mode to allow passing passwords on the command line.\n");
printf(" -c : create a new password file. This will overwrite existing files.\n");
@ -352,7 +352,7 @@ static int update_pwuser_cb(FILE *fptr, FILE *ftmp, const char *username, const
}else{
/* Write out a new line for our matching username */
helper->found = true;
rc = output_new_password(ftmp, username, password);
rc = output_new_password(ftmp, username, helper->password);
}
return rc;
}
@ -364,6 +364,7 @@ int update_pwuser(FILE *fptr, FILE *ftmp, const char *username, const char *pass
memset(&helper, 0, sizeof(helper));
helper.username = username;
helper.password = password;
rc = pwfile_iterate(fptr, ftmp, update_pwuser_cb, &helper);
if(helper.found){
@ -552,66 +553,97 @@ int main(int argc, char *argv[])
}
idx = 1;
if(!strcmp(argv[1], "-H")){
if(argc < 5){
fprintf(stderr, "Error: -H argument given but not enough other arguments.\n");
return 1;
}
if(!strcmp(argv[2], "sha512")){
hashtype = pw_sha512;
}else if(!strcmp(argv[2], "sha512-pbkdf2")){
hashtype = pw_sha512_pbkdf2;
for(idx = 1; idx < argc; idx++){
if(!strcmp(argv[idx], "-H")){
if(idx+1 == argc){
fprintf(stderr, "Error: -H argument given but not enough other arguments.\n");
return 1;
}
if(!strcmp(argv[idx+1], "sha512")){
hashtype = pw_sha512;
}else if(!strcmp(argv[idx+1], "sha512-pbkdf2")){
hashtype = pw_sha512_pbkdf2;
}else{
fprintf(stderr, "Error: Unknown hash type '%s'\n", argv[idx+1]);
return 1;
}
idx++;
}else if(!strcmp(argv[idx], "-b")){
batch_mode = true;
}else if(!strcmp(argv[idx], "-c")){
create_new = true;
}else if(!strcmp(argv[idx], "-D")){
delete_user = true;
}else if(!strcmp(argv[idx], "-U")){
do_update_file = true;
}else{
fprintf(stderr, "Error: Unknown hash type '%s'\n", argv[2]);
return 1;
break;
}
idx += 2;
argc -= 2;
}
if(!strcmp(argv[idx], "-c")){
create_new = true;
if(argc != 4){
fprintf(stderr, "Error: -c argument given but password file or username missing.\n");
return 1;
if(create_new && delete_user){
fprintf(stderr, "Error: -c and -D cannot be used together.\n");
return 1;
}
if(create_new && do_update_file){
fprintf(stderr, "Error: -c and -U cannot be used together.\n");
return 1;
}
if(delete_user && do_update_file){
fprintf(stderr, "Error: -D and -U cannot be used together.\n");
return 1;
}
if(delete_user && batch_mode){
fprintf(stderr, "Error: -b and -D cannot be used together.\n");
return 1;
}
if(create_new){
if(batch_mode){
if(idx+2 >= argc){
fprintf(stderr, "Error: -c argument given but password file, username, or password missing.\n");
return 1;
}else{
password_file_tmp = argv[idx];
username = argv[idx+1];
password_cmd = argv[idx+2];
}
}else{
password_file_tmp = argv[idx+1];
username = argv[idx+2];
if(idx+1 >= argc){
fprintf(stderr, "Error: -c argument given but password file or username missing.\n");
return 1;
}else{
password_file_tmp = argv[idx];
username = argv[idx+1];
}
}
}else if(!strcmp(argv[idx], "-D")){
delete_user = true;
if(argc != 4){
}else if(delete_user){
if(idx+1 >= argc){
fprintf(stderr, "Error: -D argument given but password file or username missing.\n");
return 1;
}else{
password_file_tmp = argv[idx+1];
username = argv[idx+2];
password_file_tmp = argv[idx];
username = argv[idx+1];
}
}else if(!strcmp(argv[idx], "-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[idx+1];
username = argv[idx+2];
password_cmd = argv[idx+3];
}
}else if(!strcmp(argv[idx], "-U")){
if(argc != 3){
}else if(do_update_file){
if(idx+1 != argc){
fprintf(stderr, "Error: -U argument given but password file missing.\n");
return 1;
}else{
do_update_file = true;
password_file_tmp = argv[idx+1];
password_file_tmp = argv[idx];
}
}else if(argc == 3){
}else if(batch_mode == true && idx+3 == argc){
password_file_tmp = argv[idx];
username = argv[idx+1];
password_cmd = argv[idx+1];
}else if(batch_mode == false && idx+2 == argc){
password_file_tmp = argv[idx];
username = argv[idx+1];
}else{
print_usage();
return 1;
}
if(username && strlen(username) > 65535){
fprintf(stderr, "Error: Username must be less than 65536 characters long.\n");
return 1;
@ -644,10 +676,13 @@ int main(int argc, char *argv[])
#endif
if(create_new){
rc = get_password(password, MAX_BUFFER_LEN);
if(rc){
free(password_file);
return rc;
if(batch_mode == false){
rc = get_password(password, MAX_BUFFER_LEN);
if(rc){
free(password_file);
return rc;
}
password_cmd = password;
}
fptr = fopen(password_file, "wt");
if(!fptr){
@ -656,7 +691,7 @@ int main(int argc, char *argv[])
return 1;
}
free(password_file);
rc = output_new_password(fptr, username, password);
rc = output_new_password(fptr, username, password_cmd);
fclose(fptr);
return rc;
}else{

@ -94,7 +94,7 @@ static void net__print_error(int log, const char *format_str)
#ifdef WIN32
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(), LANG_NEUTRAL, &buf, 0, NULL);
NULL, WSAGetLastError(), LANG_NEUTRAL, (LPTSTR)&buf, 0, NULL);
log__printf(NULL, log, format_str, buf);
LocalFree(buf);
@ -173,7 +173,11 @@ int net__socket_accept(struct mosquitto_db *db, mosq_sock_t listensock)
if(db->config->set_tcp_nodelay){
int flag = 1;
#ifdef WIN32
if (setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) != 0) {
#else
if(setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)) != 0){
#endif
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Unable to set TCP_NODELAY.");
}
}
@ -207,43 +211,37 @@ int net__socket_accept(struct mosquitto_db *db, mosq_sock_t listensock)
#ifdef WITH_TLS
/* TLS init */
for(i=0; i<db->config->listener_count; i++){
for(j=0; j<db->config->listeners[i].sock_count; j++){
if(db->config->listeners[i].socks[j] == listensock){
if(db->config->listeners[i].ssl_ctx){
new_context->ssl = SSL_new(db->config->listeners[i].ssl_ctx);
if(!new_context->ssl){
context__cleanup(db, new_context, true);
return -1;
}
SSL_set_ex_data(new_context->ssl, tls_ex_index_context, new_context);
SSL_set_ex_data(new_context->ssl, tls_ex_index_listener, &db->config->listeners[i]);
new_context->want_write = true;
bio = BIO_new_socket(new_sock, BIO_NOCLOSE);
SSL_set_bio(new_context->ssl, bio, bio);
ERR_clear_error();
rc = SSL_accept(new_context->ssl);
if(rc != 1){
rc = SSL_get_error(new_context->ssl, rc);
if(rc == SSL_ERROR_WANT_READ){
/* We always want to read. */
}else if(rc == SSL_ERROR_WANT_WRITE){
new_context->want_write = true;
}else{
if(db->config->connection_messages == true){
e = ERR_get_error();
while(e){
log__printf(NULL, MOSQ_LOG_NOTICE,
"Client connection from %s failed: %s.",
new_context->address, ERR_error_string(e, ebuf));
e = ERR_get_error();
}
}
context__cleanup(db, new_context, true);
return -1;
}
if(new_context->listener->ssl_ctx){
new_context->ssl = SSL_new(new_context->listener->ssl_ctx);
if(!new_context->ssl){
context__cleanup(db, new_context, true);
return -1;
}
SSL_set_ex_data(new_context->ssl, tls_ex_index_context, new_context);
SSL_set_ex_data(new_context->ssl, tls_ex_index_listener, new_context->listener);
new_context->want_write = true;
bio = BIO_new_socket(new_sock, BIO_NOCLOSE);
SSL_set_bio(new_context->ssl, bio, bio);
ERR_clear_error();
rc = SSL_accept(new_context->ssl);
if(rc != 1){
rc = SSL_get_error(new_context->ssl, rc);
if(rc == SSL_ERROR_WANT_READ){
/* We always want to read. */
}else if(rc == SSL_ERROR_WANT_WRITE){
new_context->want_write = true;
}else{
if(db->config->connection_messages == true){
e = ERR_get_error();
while(e){
log__printf(NULL, MOSQ_LOG_NOTICE,
"Client connection from %s failed: %s.",
new_context->address, ERR_error_string(e, ebuf));
e = ERR_get_error();
}
}
context__cleanup(db, new_context, true);
return -1;
}
}
}
@ -452,8 +450,13 @@ int net__tls_load_verify(struct mosquitto__listener *listener)
{
#ifdef WITH_TLS
ENGINE *engine = NULL;
# if !defined(OPENSSL_NO_ENGINE)
UI_METHOD *ui_method;
EVP_PKEY *pkey;
# endif
int rc;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
if(listener->cafile || listener->capath){
rc = SSL_CTX_load_verify_locations(listener->ssl_ctx, listener->cafile, listener->capath);
if(rc == 0){
@ -464,10 +467,27 @@ int net__tls_load_verify(struct mosquitto__listener *listener)
}else{
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check capath \"%s\".", listener->capath);
}
}
}
#else
if(listener->cafile){
rc = SSL_CTX_load_verify_file(listener->ssl_ctx, listener->cafile);
if(rc == 0){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check cafile \"%s\".", listener->cafile);
net__print_ssl_error(NULL);
return 1;
return MOSQ_ERR_TLS;
}
}
if(listener->capath){
rc = SSL_CTX_load_verify_dir(listener->ssl_ctx, listener->capath);
if(rc == 0){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check capath \"%s\".", listener->capath);
net__print_ssl_error(NULL);
return MOSQ_ERR_TLS;
}
}
#endif
if(listener->tls_engine){
#if !defined(OPENSSL_NO_ENGINE)
engine = ENGINE_by_id(listener->tls_engine);
@ -503,7 +523,7 @@ int net__tls_load_verify(struct mosquitto__listener *listener)
}
if(listener->tls_engine && listener->tls_keyform == mosq_k_engine){
#if !defined(OPENSSL_NO_ENGINE)
UI_METHOD *ui_method = net__get_ui_method();
ui_method = net__get_ui_method();
if(listener->tls_engine_kpass_sha1){
if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha");
@ -519,7 +539,7 @@ int net__tls_load_verify(struct mosquitto__listener *listener)
}
ui_method = NULL;
}
EVP_PKEY *pkey = ENGINE_load_private_key(engine, listener->keyfile, ui_method, NULL);
pkey = ENGINE_load_private_key(engine, listener->keyfile, ui_method, NULL);
if(!pkey){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load engine private key file \"%s\".", listener->keyfile);
net__print_ssl_error(NULL);
@ -537,6 +557,7 @@ int net__tls_load_verify(struct mosquitto__listener *listener)
rc = SSL_CTX_use_PrivateKey_file(listener->ssl_ctx, listener->keyfile, SSL_FILETYPE_PEM);
if(rc != 1){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server key file \"%s\". Check keyfile.", listener->keyfile);
net__print_ssl_error(NULL);
#if !defined(OPENSSL_NO_ENGINE)
ENGINE_FINISH(engine);
#endif
@ -575,11 +596,7 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)
struct addrinfo *ainfo, *rp;
char service[10];
int rc;
#ifndef WIN32
int ss_opt = 1;
#else
char ss_opt = 1;
#endif
#ifdef SO_BINDTODEVICE
struct ifreq ifr;
#endif

@ -17,7 +17,7 @@ Contributors:
#ifndef PERSIST_H
#define PERSIST_H
#define MOSQ_DB_VERSION 5
#define MOSQ_DB_VERSION 6
/* DB read/write */
extern const unsigned char magic[15];
@ -57,15 +57,28 @@ struct PF_cfg{
uint8_t dbid_size;
};
struct PF_client_v5{
int64_t session_expiry_time;
uint32_t session_expiry_interval;
uint16_t last_mid;
uint16_t id_len;
};
struct PF_client{
/* struct PF_client_v5; */
int64_t session_expiry_time;
uint32_t session_expiry_interval;
uint16_t last_mid;
uint16_t id_len;
uint16_t listener_port;
uint16_t username_len;
/* tail: 4 byte padding, because 64bit member
* forces multiple of 8 for struct size */
};
struct P_client{
struct PF_client F;
char *client_id;
char *username;
};
@ -141,19 +154,19 @@ int persist__chunk_msg_store_read_v234(FILE *db_fptr, struct P_msg_store *chunk,
int persist__chunk_retain_read_v234(FILE *db_fptr, struct P_retain *chunk);
int persist__chunk_sub_read_v234(FILE *db_fptr, struct P_sub *chunk);
int persist__chunk_header_read_v5(FILE *db_fptr, int *chunk, int *length);
int persist__chunk_cfg_read_v5(FILE *db_fptr, struct PF_cfg *chunk);
int persist__chunk_client_read_v5(FILE *db_fptr, struct P_client *chunk);
int persist__chunk_client_msg_read_v5(FILE *db_fptr, struct P_client_msg *chunk, uint32_t length);
int persist__chunk_msg_store_read_v5(FILE *db_fptr, struct P_msg_store *chunk, uint32_t length);
int persist__chunk_retain_read_v5(FILE *db_fptr, struct P_retain *chunk);
int persist__chunk_sub_read_v5(FILE *db_fptr, struct P_sub *chunk);
int persist__chunk_cfg_write_v5(FILE *db_fptr, struct PF_cfg *chunk);
int persist__chunk_client_write_v5(FILE *db_fptr, struct P_client *chunk);
int persist__chunk_client_msg_write_v5(FILE *db_fptr, struct P_client_msg *chunk);
int persist__chunk_message_store_write_v5(FILE *db_fptr, struct P_msg_store *chunk);
int persist__chunk_retain_write_v5(FILE *db_fptr, struct P_retain *chunk);
int persist__chunk_sub_write_v5(FILE *db_fptr, struct P_sub *chunk);
int persist__chunk_header_read_v56(FILE *db_fptr, int *chunk, int *length);
int persist__chunk_cfg_read_v56(FILE *db_fptr, struct PF_cfg *chunk);
int persist__chunk_client_read_v56(FILE *db_fptr, struct P_client *chunk, int db_version);
int persist__chunk_client_msg_read_v56(FILE *db_fptr, struct P_client_msg *chunk, uint32_t length);
int persist__chunk_msg_store_read_v56(FILE *db_fptr, struct P_msg_store *chunk, uint32_t length);
int persist__chunk_retain_read_v56(FILE *db_fptr, struct P_retain *chunk);
int persist__chunk_sub_read_v56(FILE *db_fptr, struct P_sub *chunk);
int persist__chunk_cfg_write_v6(FILE *db_fptr, struct PF_cfg *chunk);
int persist__chunk_client_write_v6(FILE *db_fptr, struct P_client *chunk);
int persist__chunk_client_msg_write_v6(FILE *db_fptr, struct P_client_msg *chunk);
int persist__chunk_message_store_write_v6(FILE *db_fptr, struct P_msg_store *chunk);
int persist__chunk_retain_write_v6(FILE *db_fptr, struct P_retain *chunk);
int persist__chunk_sub_write_v6(FILE *db_fptr, struct P_sub *chunk);
#endif

@ -174,14 +174,14 @@ static int persist__client_msg_restore(struct mosquitto_db *db, struct P_client_
static int persist__client_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
{
int rc = 0;
int i, rc = 0;
struct mosquitto *context;
struct P_client chunk;
memset(&chunk, 0, sizeof(struct P_client));
if(db_version == 5){
rc = persist__chunk_client_read_v5(db_fptr, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_client_read_v56(db_fptr, &chunk, db_version);
}else{
rc = persist__chunk_client_read_v234(db_fptr, &chunk, db_version);
}
@ -198,13 +198,29 @@ static int persist__client_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
if(context){
context->session_expiry_time = chunk.F.session_expiry_time;
context->session_expiry_interval = chunk.F.session_expiry_interval;
if(chunk.username && !context->username){
/* username is not freed here, it is now owned by context */
context->username = chunk.username;
chunk.username = NULL;
/* in per_listener_settings mode, try to find the listener by persisted port */
if(db->config->per_listener_settings && !context->listener && chunk.F.listener_port > 0){
for(i=0; i < db->config->listener_count; i++){
if(db->config->listeners[i].port == chunk.F.listener_port){
context->listener = &db->config->listeners[i];
break;
}
}
}
}
/* FIXME - we should expire clients here if they have exceeded their time */
}else{
rc = 1;
}
mosquitto__free(chunk.client_id);
if(chunk.username){
mosquitto__free(chunk.username);
}
return rc;
}
@ -216,8 +232,8 @@ static int persist__client_msg_chunk_restore(struct mosquitto_db *db, FILE *db_f
memset(&chunk, 0, sizeof(struct P_client_msg));
if(db_version == 5){
rc = persist__chunk_client_msg_read_v5(db_fptr, &chunk, length);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_client_msg_read_v56(db_fptr, &chunk, length);
}else{
rc = persist__chunk_client_msg_read_v234(db_fptr, &chunk);
}
@ -245,8 +261,8 @@ static int persist__msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fp
memset(&chunk, 0, sizeof(struct P_msg_store));
if(db_version == 5){
rc = persist__chunk_msg_store_read_v5(db_fptr, &chunk, length);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_msg_store_read_v56(db_fptr, &chunk, length);
}else{
rc = persist__chunk_msg_store_read_v234(db_fptr, &chunk, db_version);
}
@ -342,8 +358,8 @@ static int persist__retain_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
memset(&chunk, 0, sizeof(struct P_retain));
if(db_version == 5){
rc = persist__chunk_retain_read_v5(db_fptr, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_retain_read_v56(db_fptr, &chunk);
}else{
rc = persist__chunk_retain_read_v234(db_fptr, &chunk);
}
@ -371,8 +387,8 @@ static int persist__sub_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
memset(&chunk, 0, sizeof(struct P_sub));
if(db_version == 5){
rc = persist__chunk_sub_read_v5(db_fptr, &chunk);
if(db_version == 6 || db_version == 5){
rc = persist__chunk_sub_read_v56(db_fptr, &chunk);
}else{
rc = persist__chunk_sub_read_v234(db_fptr, &chunk);
}
@ -392,8 +408,8 @@ static int persist__sub_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
int persist__chunk_header_read(FILE *db_fptr, int *chunk, int *length)
{
if(db_version == 5){
return persist__chunk_header_read_v5(db_fptr, chunk, length);
if(db_version == 6 || db_version == 5){
return persist__chunk_header_read_v56(db_fptr, chunk, length);
}else{
return persist__chunk_header_read_v234(db_fptr, chunk, length);
}
@ -433,15 +449,17 @@ int persist__restore(struct mosquitto_db *db)
goto error;
}
if(!memcmp(header, magic, 15)){
// Restore DB as normal
/* Restore DB as normal */
read_e(fptr, &crc, sizeof(uint32_t));
read_e(fptr, &i32temp, sizeof(uint32_t));
db_version = ntohl(i32temp);
/* IMPORTANT - this is where compatibility checks are made.
* Is your DB change still compatible with previous versions?
*/
if(db_version > MOSQ_DB_VERSION && db_version != 0){
if(db_version == 4){
if(db_version != MOSQ_DB_VERSION){
if(db_version == 5){
/* Addition of username and listener_port to client chunk in v6 */
}else if(db_version == 4){
}else if(db_version == 3){
/* Addition of source_username and source_port to msg_store chunk in v4, v1.5.6 */
}else if(db_version == 2){
@ -456,8 +474,8 @@ int persist__restore(struct mosquitto_db *db)
while(persist__chunk_header_read(fptr, &chunk, &length) == MOSQ_ERR_SUCCESS){
switch(chunk){
case DB_CHUNK_CFG:
if(db_version == 5){
if(persist__chunk_cfg_read_v5(fptr, &cfg_chunk)){
if(db_version == 6 || db_version == 5){
if(persist__chunk_cfg_read_v56(fptr, &cfg_chunk)){
fclose(fptr);
return 1;
}

@ -57,8 +57,8 @@ int persist__chunk_header_read_v234(FILE *db_fptr, int *chunk, int *length)
int persist__chunk_cfg_read_v234(FILE *db_fptr, struct PF_cfg *chunk)
{
read_e(db_fptr, &chunk->shutdown, sizeof(uint8_t)); // shutdown
read_e(db_fptr, &chunk->dbid_size, sizeof(uint8_t)); // sizeof(dbid_t)
read_e(db_fptr, &chunk->shutdown, sizeof(uint8_t)); /* shutdown */
read_e(db_fptr, &chunk->dbid_size, sizeof(uint8_t)); /* sizeof(dbid_t) */
read_e(db_fptr, &chunk->last_db_id, sizeof(dbid_t));
return MOSQ_ERR_SUCCESS;

@ -38,7 +38,7 @@ Contributors:
#include "util_mosq.h"
int persist__chunk_header_read_v5(FILE *db_fptr, int *chunk, int *length)
int persist__chunk_header_read_v56(FILE *db_fptr, int *chunk, int *length)
{
size_t rlen;
struct PF_header header;
@ -53,7 +53,7 @@ int persist__chunk_header_read_v5(FILE *db_fptr, int *chunk, int *length)
}
int persist__chunk_cfg_read_v5(FILE *db_fptr, struct PF_cfg *chunk)
int persist__chunk_cfg_read_v56(FILE *db_fptr, struct PF_cfg *chunk)
{
if(fread(chunk, sizeof(struct PF_cfg), 1, db_fptr) != 1){
log__printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno));
@ -64,30 +64,48 @@ int persist__chunk_cfg_read_v5(FILE *db_fptr, struct PF_cfg *chunk)
}
int persist__chunk_client_read_v5(FILE *db_fptr, struct P_client *chunk)
int persist__chunk_client_read_v56(FILE *db_fptr, struct P_client *chunk, int db_version)
{
int rc;
read_e(db_fptr, &chunk->F, sizeof(struct PF_client));
if(db_version == 6){
read_e(db_fptr, &chunk->F, sizeof(struct PF_client));
chunk->F.username_len = ntohs(chunk->F.username_len);
chunk->F.listener_port = ntohs(chunk->F.listener_port);
}else if(db_version == 5){
read_e(db_fptr, &chunk->F, sizeof(struct PF_client_v5));
}else{
return 1;
}
chunk->F.session_expiry_interval = ntohl(chunk->F.session_expiry_interval);
chunk->F.last_mid = ntohs(chunk->F.last_mid);
chunk->F.id_len = ntohs(chunk->F.id_len);
rc = persist__read_string_len(db_fptr, &chunk->client_id, chunk->F.id_len);
if(rc){
return 1;
}else if(chunk->client_id == NULL){
return -1;
}else{
return MOSQ_ERR_SUCCESS;
}
if(chunk->F.username_len > 0){
rc = persist__read_string_len(db_fptr, &chunk->username, chunk->F.username_len);
if(rc || !chunk->username){
mosquitto__free(chunk->client_id);
return 1;
}
}
return MOSQ_ERR_SUCCESS;
error:
log__printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno));
return 1;
}
int persist__chunk_client_msg_read_v5(FILE *db_fptr, struct P_client_msg *chunk, uint32_t length)
int persist__chunk_client_msg_read_v56(FILE *db_fptr, struct P_client_msg *chunk, uint32_t length)
{
mosquitto_property *properties = NULL;
struct mosquitto__packet prop_packet;
@ -127,7 +145,7 @@ error:
}
int persist__chunk_msg_store_read_v5(FILE *db_fptr, struct P_msg_store *chunk, uint32_t length)
int persist__chunk_msg_store_read_v56(FILE *db_fptr, struct P_msg_store *chunk, uint32_t length)
{
int rc = 0;
mosquitto_property *properties = NULL;
@ -217,7 +235,7 @@ error:
}
int persist__chunk_retain_read_v5(FILE *db_fptr, struct P_retain *chunk)
int persist__chunk_retain_read_v56(FILE *db_fptr, struct P_retain *chunk)
{
if(fread(&chunk->F, sizeof(struct P_retain), 1, db_fptr) != 1){
log__printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno));
@ -227,7 +245,7 @@ int persist__chunk_retain_read_v5(FILE *db_fptr, struct P_retain *chunk)
}
int persist__chunk_sub_read_v5(FILE *db_fptr, struct P_sub *chunk)
int persist__chunk_sub_read_v56(FILE *db_fptr, struct P_sub *chunk)
{
int rc;

@ -70,7 +70,7 @@ static int persist__client_messages_save(struct mosquitto_db *db, FILE *db_fptr,
chunk.client_id = context->id;
chunk.properties = cmsg->properties;
rc = persist__chunk_client_msg_write_v5(db_fptr, &chunk);
rc = persist__chunk_client_msg_write_v6(db_fptr, &chunk);
if(rc){
return rc;
}
@ -146,7 +146,7 @@ static int persist__message_store_save(struct mosquitto_db *db, FILE *db_fptr)
chunk.payload = stored->payload;
chunk.properties = stored->properties;
rc = persist__chunk_message_store_write_v5(db_fptr, &chunk);
rc = persist__chunk_message_store_write_v6(db_fptr, &chunk);
if(rc){
return rc;
}
@ -174,6 +174,13 @@ static int persist__client_save(struct mosquitto_db *db, FILE *db_fptr)
chunk.F.last_mid = context->last_mid;
chunk.F.id_len = strlen(context->id);
chunk.client_id = context->id;
if(context->username){
chunk.F.username_len = strlen(context->username);
chunk.username = context->username;
if(context->listener){
chunk.F.listener_port = context->listener->port;
}
}
if(chunk.F.id_len == 0){
/* This should never happen, but in case we have a client with
@ -181,7 +188,7 @@ static int persist__client_save(struct mosquitto_db *db, FILE *db_fptr)
continue;
}
rc = persist__chunk_client_write_v5(db_fptr, &chunk);
rc = persist__chunk_client_write_v6(db_fptr, &chunk);
if(rc){
return rc;
}
@ -228,7 +235,7 @@ static int persist__subs_save(struct mosquitto_db *db, FILE *db_fptr, struct mos
sub_chunk.client_id = sub->context->id;
sub_chunk.topic = thistopic;
rc = persist__chunk_sub_write_v5(db_fptr, &sub_chunk);
rc = persist__chunk_sub_write_v6(db_fptr, &sub_chunk);
if(rc){
mosquitto__free(thistopic);
return rc;
@ -268,7 +275,7 @@ static int persist__retain_save(struct mosquitto_db *db, FILE *db_fptr, struct m
if(node->retained && strncmp(node->retained->topic, "$SYS", 4)){
/* Don't save $SYS messages. */
retain_chunk.F.store_id = node->retained->db_id;
rc = persist__chunk_retain_write_v5(db_fptr, &retain_chunk);
rc = persist__chunk_retain_write_v6(db_fptr, &retain_chunk);
if(rc){
return rc;
}
@ -364,7 +371,7 @@ int persist__backup(struct mosquitto_db *db, bool shutdown)
cfg_chunk.last_db_id = db->last_db_id;
cfg_chunk.shutdown = shutdown;
cfg_chunk.dbid_size = sizeof(dbid_t);
if(persist__chunk_cfg_write_v5(db_fptr, &cfg_chunk)){
if(persist__chunk_cfg_write_v6(db_fptr, &cfg_chunk)){
goto error;
}

@ -37,7 +37,7 @@ Contributors:
#include "time_mosq.h"
#include "util_mosq.h"
int persist__chunk_cfg_write_v5(FILE *db_fptr, struct PF_cfg *chunk)
int persist__chunk_cfg_write_v6(FILE *db_fptr, struct PF_cfg *chunk)
{
struct PF_header header;
@ -53,22 +53,28 @@ error:
}
int persist__chunk_client_write_v5(FILE *db_fptr, struct P_client *chunk)
int persist__chunk_client_write_v6(FILE *db_fptr, struct P_client *chunk)
{
struct PF_header header;
uint16_t id_len = chunk->F.id_len;
uint16_t username_len = chunk->F.username_len;
chunk->F.session_expiry_interval = htonl(chunk->F.session_expiry_interval);
chunk->F.last_mid = htons(chunk->F.last_mid);
chunk->F.id_len = htons(chunk->F.id_len);
chunk->F.username_len = htons(chunk->F.username_len);
chunk->F.listener_port = htons(chunk->F.listener_port);
header.chunk = htonl(DB_CHUNK_CLIENT);
header.length = htonl(sizeof(struct PF_client)+id_len);
header.length = htonl(sizeof(struct PF_client)+id_len+username_len);
write_e(db_fptr, &header, sizeof(struct PF_header));
write_e(db_fptr, &chunk->F, sizeof(struct PF_client));
write_e(db_fptr, chunk->client_id, id_len);
if(username_len > 0){
write_e(db_fptr, chunk->username, username_len);
}
return MOSQ_ERR_SUCCESS;
error:
@ -77,7 +83,7 @@ error:
}
int persist__chunk_client_msg_write_v5(FILE *db_fptr, struct P_client_msg *chunk)
int persist__chunk_client_msg_write_v6(FILE *db_fptr, struct P_client_msg *chunk)
{
struct PF_header header;
struct mosquitto__packet prop_packet;
@ -108,7 +114,10 @@ int persist__chunk_client_msg_write_v5(FILE *db_fptr, struct P_client_msg *chunk
return MOSQ_ERR_NOMEM;
}
rc = property__write_all(&prop_packet, chunk->properties, true);
if(rc) return rc;
if(rc){
mosquitto__free(prop_packet.payload);
return rc;
}
write_e(db_fptr, prop_packet.payload, proplen);
mosquitto__free(prop_packet.payload);
@ -122,7 +131,7 @@ error:
}
int persist__chunk_message_store_write_v5(FILE *db_fptr, struct P_msg_store *chunk)
int persist__chunk_message_store_write_v6(FILE *db_fptr, struct P_msg_store *chunk)
{
struct PF_header header;
uint32_t payloadlen = chunk->F.payloadlen;
@ -171,7 +180,10 @@ int persist__chunk_message_store_write_v5(FILE *db_fptr, struct P_msg_store *chu
return MOSQ_ERR_NOMEM;
}
rc = property__write_all(&prop_packet, chunk->properties, true);
if(rc) return rc;
if(rc){
mosquitto__free(prop_packet.payload);
return rc;
}
write_e(db_fptr, prop_packet.payload, proplen);
mosquitto__free(prop_packet.payload);
@ -186,7 +198,7 @@ error:
}
int persist__chunk_retain_write_v5(FILE *db_fptr, struct P_retain *chunk)
int persist__chunk_retain_write_v6(FILE *db_fptr, struct P_retain *chunk)
{
struct PF_header header;
@ -203,7 +215,7 @@ error:
}
int persist__chunk_sub_write_v5(FILE *db_fptr, struct P_sub *chunk)
int persist__chunk_sub_write_v6(FILE *db_fptr, struct P_sub *chunk)
{
struct PF_header header;
uint16_t id_len = chunk->F.id_len;

@ -35,7 +35,7 @@ void LIB_ERROR(void)
#ifdef WIN32
char *buf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
NULL, GetLastError(), LANG_NEUTRAL, &buf, 0, NULL);
NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&buf, 0, NULL);
log__printf(NULL, MOSQ_LOG_ERR, "Load error: %s", buf);
LocalFree(buf);
#else
@ -589,7 +589,7 @@ int mosquitto_security_cleanup(struct mosquitto_db *db, bool reload)
}
//int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, int access)
/* int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, int access) */
static int acl__check_single(struct mosquitto__auth_plugin_config *auth_plugin, struct mosquitto *context, struct mosquitto_acl_msg *msg, int access)
{
const char *username;
@ -650,7 +650,7 @@ static int acl__check_dollar(const char *topic, int access)
}else if(!strncmp(topic, "$share", 6)){
/* Only allow sub/unsub to shared subscriptions */
if(access == MOSQ_ACL_SUBSCRIBE){
//FIXME if(access == MOSQ_ACL_SUBSCRIBE || access == MOSQ_ACL_UNSUBSCRIBE){
/* FIXME if(access == MOSQ_ACL_SUBSCRIBE || access == MOSQ_ACL_UNSUBSCRIBE){ */
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_ACL_DENIED;

@ -396,7 +396,7 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
len = tlen + acl_root->ccount*(clen-2);
}
local_acl = mosquitto__malloc(len+1);
if(!local_acl) return 1; // FIXME
if(!local_acl) return 1; /* FIXME */
s = local_acl;
for(i=0; i<tlen; i++){
if(i<tlen-1 && acl_root->topic[i] == '%'){
@ -465,8 +465,9 @@ static int aclfile__parse(struct mosquitto_db *db, struct mosquitto__security_op
return 1;
}
// topic [read|write] <topic>
// user <user>
/* topic [read|write] <topic>
* user <user>
*/
while(fgets_extending(&buf, &buflen, aclfptr)){
slen = strlen(buf);
@ -1044,6 +1045,10 @@ int mosquitto_security_apply_default(struct mosquitto_db *db)
X509_NAME_ENTRY *name_entry;
ASN1_STRING *name_asn1 = NULL;
struct mosquitto__listener *listener;
BIO *subject_bio;
char *data_start;
long name_length;
char *subject;
#endif
if(!db) return MOSQ_ERR_INVAL;
@ -1122,7 +1127,7 @@ int mosquitto_security_apply_default(struct mosquitto_db *db)
security__disconnect_auth(db, context);
continue;
}
if (context->listener->use_identity_as_username) { //use_identity_as_username
if (context->listener->use_identity_as_username) { /* use_identity_as_username */
i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
if(i == -1){
X509_free(client_cert);
@ -1158,12 +1163,12 @@ int mosquitto_security_apply_default(struct mosquitto_db *db)
continue;
}
}
} else { // use_subject_as_username
BIO *subject_bio = BIO_new(BIO_s_mem());
} else { /* use_subject_as_username */
subject_bio = BIO_new(BIO_s_mem());
X509_NAME_print_ex(subject_bio, X509_get_subject_name(client_cert), 0, XN_FLAG_RFC2253);
char *data_start = NULL;
long name_length = BIO_get_mem_data(subject_bio, &data_start);
char *subject = mosquitto__malloc(sizeof(char)*name_length+1);
data_start = NULL;
name_length = BIO_get_mem_data(subject_bio, &data_start);
subject = mosquitto__malloc(sizeof(char)*name_length+1);
if(!subject){
BIO_free(subject_bio);
X509_free(client_cert);
@ -1272,7 +1277,7 @@ int pw__digest(const char *password, const unsigned char *salt, unsigned int sal
digest = EVP_get_digestbyname("sha512");
if(!digest){
// FIXME fprintf(stderr, "Error: Unable to create openssl digest.\n");
/* FIXME fprintf(stderr, "Error: Unable to create openssl digest.\n"); */
return 1;
}

@ -32,7 +32,7 @@ static void print_error(void)
char *buf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(), LANG_NEUTRAL, &buf, 0, NULL);
NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&buf, 0, NULL);
fprintf(stderr, "Error: %s\n", buf);
LocalFree(buf);
@ -70,7 +70,7 @@ void __stdcall service_main(DWORD dwArgc, LPTSTR *lpszArgv)
service_handle = RegisterServiceCtrlHandler("mosquitto", service_handler);
if(service_handle){
memset(conf_path, 0, MAX_PATH + 20);
memset(conf_path, 0, sizeof(conf_path));
rc = GetEnvironmentVariable("MOSQUITTO_DIR", conf_path, MAX_PATH);
if(!rc || rc == MAX_PATH){
service_status.dwCurrentState = SERVICE_STOPPED;
@ -103,25 +103,26 @@ void __stdcall service_main(DWORD dwArgc, LPTSTR *lpszArgv)
void service_install(void)
{
SC_HANDLE sc_manager, svc_handle;
char exe_path[MAX_PATH + 5];
char service_string[MAX_PATH + 20];
char exe_path[MAX_PATH + 1];
SERVICE_DESCRIPTION svc_desc;
memset(exe_path, 0, MAX_PATH+5);
memset(exe_path, 0, sizeof(exe_path));
if(GetModuleFileName(NULL, exe_path, MAX_PATH) == MAX_PATH){
fprintf(stderr, "Error: Path too long.\n");
return;
}
strcat(exe_path, " run");
snprintf(service_string, sizeof(service_string), "\"%s\" run", exe_path);
sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if(sc_manager){
svc_handle = CreateService(sc_manager, "mosquitto", "Mosquitto Broker",
SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG,
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
exe_path, NULL, NULL, NULL, NULL, NULL);
service_string, NULL, NULL, NULL, NULL, NULL);
if(svc_handle){
svc_desc.lpDescription = "MQTT v3.1.1 broker";
svc_desc.lpDescription = "Eclipse Mosquitto MQTT v5/v3.1.1 broker";
ChangeServiceConfig2(svc_handle, SERVICE_CONFIG_DESCRIPTION, &svc_desc);
CloseServiceHandle(svc_handle);
}else{

@ -218,6 +218,7 @@ void sys_tree__update(struct mosquitto_db *db, int interval, time_t start_time)
double exponent;
double i_mult;
int len;
bool initial_publish;
now = mosquitto_time();
@ -227,7 +228,7 @@ void sys_tree__update(struct mosquitto_db *db, int interval, time_t start_time)
db__messages_easy_queue(db, NULL, "$SYS/broker/uptime", SYS_TREE_QOS, len, buf, 1, 60, NULL);
sys_tree__update_clients(db, buf);
bool initial_publish = false;
initial_publish = false;
if(last_update == 0){
initial_publish = true;
last_update = 1;

@ -54,10 +54,10 @@ extern unsigned int g_connection_count;
#define G_MSGS_SENT_INC(A)
#define G_PUB_MSGS_RECEIVED_INC(A)
#define G_PUB_MSGS_SENT_INC(A)
#define G_MSGS_DROPPED_INC(A)
#define G_CLIENTS_EXPIRED_INC(A)
#define G_SOCKET_CONNECTIONS_INC(A)
#define G_CONNECTION_COUNT_INC(A)
#define G_MSGS_DROPPED_INC()
#define G_CLIENTS_EXPIRED_INC()
#define G_SOCKET_CONNECTIONS_INC()
#define G_CONNECTION_COUNT_INC()
#endif

@ -307,7 +307,10 @@ static int callback_mqtt(struct libwebsocket_context *context,
}
count = libwebsocket_write(wsi, &packet->payload[packet->pos], txlen, LWS_WRITE_BINARY);
if(count < 0){
if (mosq->state == mosq_cs_disconnect_ws || mosq->state == mosq_cs_disconnecting){
if (mosq->state == mosq_cs_disconnect_ws
|| mosq->state == mosq_cs_disconnecting
|| mosq->state == mosq_cs_disused){
return -1;
}
return 0;
@ -318,7 +321,10 @@ static int callback_mqtt(struct libwebsocket_context *context,
packet->to_process -= count;
packet->pos += count;
if(packet->to_process > 0){
if (mosq->state == mosq_cs_disconnect_ws || mosq->state == mosq_cs_disconnecting){
if (mosq->state == mosq_cs_disconnect_ws
|| mosq->state == mosq_cs_disconnecting
|| mosq->state == mosq_cs_disused){
return -1;
}
break;
@ -345,7 +351,10 @@ static int callback_mqtt(struct libwebsocket_context *context,
mosq->next_msg_out = mosquitto_time() + mosq->keepalive;
}
if (mosq->state == mosq_cs_disconnect_ws || mosq->state == mosq_cs_disconnecting){
if (mosq->state == mosq_cs_disconnect_ws
|| mosq->state == mosq_cs_disconnecting
|| mosq->state == mosq_cs_disused){
return -1;
}
if(mosq->current_out_packet){
@ -704,7 +713,7 @@ static int callback_http(struct libwebsocket_context *context,
static void log_wrap(int level, const char *line)
{
char *l = (char *)line;
l[strlen(line)-1] = '\0'; // Remove \n
l[strlen(line)-1] = '\0'; /* Remove \n */
log__printf(NULL, MOSQ_LOG_WEBSOCKETS, "%s", l);
}

@ -9,10 +9,12 @@ check : test
test : utest
$(MAKE) -C broker test
$(MAKE) -C lib test
$(MAKE) -C client test
ptest : utest
$(MAKE) -C broker ptest
$(MAKE) -C lib ptest
$(MAKE) -C client test
utest :
$(MAKE) -C unit test

@ -16,8 +16,6 @@ def write_config(filename, port1, port2, protocol_version):
f.write("topic prefix/# out 0 local2/topic/ remote2/topic/\n")
f.write("topic +/value out 0 local3/topic/ remote3/topic/\n")
f.write("topic ic/+ out 0 local4/top remote4/tip\n")
f.write("# this one is invalid\n")
f.write("topic +/value out 0 local5/top remote5/tip\n")
f.write("notifications false\n")
f.write("restart_timeout 5\n")
f.write("bridge_protocol_version %s\n" % (protocol_version))

@ -0,0 +1,46 @@
#!/bin/bash
# Very basic client testing.
set -e
export LD_LIBRARY_PATH=../lib
export PORT=1888
export SUB_TIMEOUT=1
# Start broker
../src/mosquitto -p ${PORT} 2>/dev/null &
export MOSQ_PID=$!
sleep 0.5
# Kill broker on exit
trap "kill $MOSQ_PID" EXIT
# Simple subscribe test - single message from $SYS
./mosquitto_sub -p ${PORT} -W ${SUB_TIMEOUT} -C 1 -t '$SYS/broker/uptime' >/dev/null
echo "Simple subscribe ok"
# Simple publish/subscribe test - single message from mosquitto_pub
./mosquitto_sub -p ${PORT} -W ${SUB_TIMEOUT} -C 1 -t 'single/test' >/dev/null &
export SUB_PID=$!
./mosquitto_pub -p ${PORT} -t 'single/test' -m 'single-test'
kill ${SUB_PID} 2>/dev/null || true
echo "Simple publish/subscribe ok"
# Publish a file and subscribe, do we get at least that many lines?
export TEST_LINES=$(wc -l test.sh | cut -d' ' -f1)
./mosquitto_sub -p ${PORT} -W ${SUB_TIMEOUT} -C ${TEST_LINES} -t 'file-publish' >/dev/null &
export SUB_PID=$!
./mosquitto_pub -p ${PORT} -t 'file-publish' -f ./test.sh
kill ${SUB_PID} 2>/dev/null || true
echo "File publish ok"
# Publish a file from stdin and subscribe, do we get at least that many lines?
export TEST_LINES=$(wc -l test.sh | cut -d' ' -f1)
./mosquitto_sub -p ${PORT} -W ${SUB_TIMEOUT} -C ${TEST_LINES} -t 'file-publish' >/dev/null &
export SUB_PID=$!
./mosquitto_pub -p ${PORT} -t 'file-publish' -l < ./test.sh
kill ${SUB_PID} 2>/dev/null || true
echo "stdin publish ok"

@ -0,0 +1,62 @@
#!/usr/bin/env python3
from mosq_test_helper import *
port = mosq_test.get_lib_port()
rc = 1
keepalive = 5
connect_packet = mosq_test.gen_connect("publish-qos1-test", keepalive=keepalive)
connack_packet = mosq_test.gen_connack(rc=0)
disconnect_packet = mosq_test.gen_disconnect()
mid = 13423
puback_packet = mosq_test.gen_puback(mid)
pingreq_packet = mosq_test.gen_pingreq()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(10)
sock.bind(('', port))
sock.listen(5)
client_args = sys.argv[1:]
env = dict(os.environ)
env['LD_LIBRARY_PATH'] = '../../lib:../../lib/cpp'
try:
pp = env['PYTHONPATH']
except KeyError:
pp = ''
env['PYTHONPATH'] = '../../lib/python:'+pp
client = mosq_test.start_client(filename=sys.argv[1].replace('/', '-'), cmd=client_args, env=env, port=port)
try:
(conn, address) = sock.accept()
conn.settimeout(10)
if mosq_test.expect_packet(conn, "connect", connect_packet):
conn.send(connack_packet)
conn.send(puback_packet)
if mosq_test.expect_packet(conn, "pingreq", pingreq_packet):
rc = 0
conn.close()
finally:
for i in range(0, 5):
if client.returncode != None:
break
time.sleep(0.1)
try:
client.terminate()
except OSError:
pass
client.wait()
sock.close()
if rc != 0 or client.returncode != 0:
exit(1)
exit(rc)

@ -0,0 +1,62 @@
#!/usr/bin/env python3
from mosq_test_helper import *
port = mosq_test.get_lib_port()
rc = 1
keepalive = 5
connect_packet = mosq_test.gen_connect("publish-qos2-test", keepalive=keepalive)
connack_packet = mosq_test.gen_connack(rc=0)
disconnect_packet = mosq_test.gen_disconnect()
mid = 13423
pubcomp_packet = mosq_test.gen_pubcomp(mid)
pingreq_packet = mosq_test.gen_pingreq()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(10)
sock.bind(('', port))
sock.listen(5)
client_args = sys.argv[1:]
env = dict(os.environ)
env['LD_LIBRARY_PATH'] = '../../lib:../../lib/cpp'
try:
pp = env['PYTHONPATH']
except KeyError:
pp = ''
env['PYTHONPATH'] = '../../lib/python:'+pp
client = mosq_test.start_client(filename=sys.argv[1].replace('/', '-'), cmd=client_args, env=env, port=port)
try:
(conn, address) = sock.accept()
conn.settimeout(10)
if mosq_test.expect_packet(conn, "connect", connect_packet):
conn.send(connack_packet)
conn.send(pubcomp_packet)
if mosq_test.expect_packet(conn, "pingreq", pingreq_packet):
rc = 0
conn.close()
finally:
for i in range(0, 5):
if client.returncode != None:
break
time.sleep(0.1)
try:
client.terminate()
except OSError:
pass
client.wait()
sock.close()
if rc != 0 or client.returncode != 0:
exit(1)
exit(rc)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save