From 3413001d47dd26f55fee7db0f36528a961ebbad5 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 7 Sep 2021 22:03:24 +0100 Subject: [PATCH] Add `mosquitto_plugin_set_info()` This allows plugins to tell the broker their name and version. --- ChangeLog.txt | 2 ++ include/mosquitto_broker.h | 12 +++++++++ plugins/dynamic-security/plugin.c | 1 + .../add-properties/mosquitto_add_properties.c | 3 +++ .../auth-by-ip/mosquitto_auth_by_ip.c | 4 +++ .../mosquitto_client_properties.c | 4 +++ .../mosquitto_connection_state.c | 4 +++ .../delayed-auth/mosquitto_delayed_auth.c | 4 +++ .../force-retain/mosquitto_force_retain.c | 4 +++ .../mosquitto_message_timestamp.c | 4 +++ .../mosquitto_payload_modification.c | 4 +++ .../mosquitto_print_ip_on_publish.c | 4 +++ src/control.c | 27 ++++++++++++++++--- src/linker-macosx.syms | 1 + src/linker.syms | 1 + src/mosquitto_broker_internal.h | 12 +++++++-- src/plugin.c | 27 +++++++++++++++++-- src/plugin_public.c | 19 +++++++++++++ src/security.c | 7 +++++ 19 files changed, 137 insertions(+), 7 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index eeae1027..a99200ac 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -49,6 +49,8 @@ Broker: when a connection attempts an upgrade to WebSockets. - Allow mosquitto_ctrl dynsec module to update passwords in files rather than having to connect to a broker. +- Add `mosquitto_plugin_set_info()` to allow plugins to tell the broker their + name and version. Client library: - Add MOSQ_OPT_DISABLE_SOCKETPAIR to allow the disabling of the socketpair diff --git a/include/mosquitto_broker.h b/include/mosquitto_broker.h index 6f818a96..f5e52a34 100644 --- a/include/mosquitto_broker.h +++ b/include/mosquitto_broker.h @@ -185,6 +185,18 @@ typedef int (*MOSQ_FUNC_generic_callback)(int, void *, void *); typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t; +/* + * Function: mosquitto_plugin_set_info + * + * Set plugin name and version information for the broker to report. It is + * recommended this is used in the mosquitto_plugin_init() call. + */ +mosq_EXPORT int mosquitto_plugin_set_info( + mosquitto_plugin_id_t *identifier, + const char *plugin_name, + const char *plugin_version); + + /* * Function: mosquitto_callback_register * diff --git a/plugins/dynamic-security/plugin.c b/plugins/dynamic-security/plugin.c index e022d013..664e1941 100644 --- a/plugins/dynamic-security/plugin.c +++ b/plugins/dynamic-security/plugin.c @@ -500,6 +500,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s } plg_id = identifier; + mosquitto_plugin_set_info(identifier, "dynamic-security", NULL); dynsec__config_load(); mosquitto_callback_register(plg_id, MOSQ_EVT_CONTROL, dynsec_control_callback, "$CONTROL/dynamic-security/v1", NULL); diff --git a/plugins/examples/add-properties/mosquitto_add_properties.c b/plugins/examples/add-properties/mosquitto_add_properties.c index a458dcfd..8747f13f 100644 --- a/plugins/examples/add-properties/mosquitto_add_properties.c +++ b/plugins/examples/add-properties/mosquitto_add_properties.c @@ -43,6 +43,8 @@ Contributors: #include "mqtt_protocol.h" #define TS_BUF_LEN (14+1) // 14 characters in unix epoch (ms) is ≈16 Nov 5138 +#define PLUGIN_NAME "add-properties" +#define PLUGIN_VERSION "1.0" static mosquitto_plugin_id_t *mosq_pid = NULL; @@ -106,6 +108,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL, NULL); } diff --git a/plugins/examples/auth-by-ip/mosquitto_auth_by_ip.c b/plugins/examples/auth-by-ip/mosquitto_auth_by_ip.c index 49cc0178..955c88db 100644 --- a/plugins/examples/auth-by-ip/mosquitto_auth_by_ip.c +++ b/plugins/examples/auth-by-ip/mosquitto_auth_by_ip.c @@ -42,6 +42,9 @@ Contributors: #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "auth-by-ip" +#define PLUGIN_VERSION "1.0" + static mosquitto_plugin_id_t *mosq_pid = NULL; static int basic_auth_callback(int event, void *event_data, void *userdata) @@ -80,6 +83,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_BASIC_AUTH, basic_auth_callback, NULL, NULL); } diff --git a/plugins/examples/client-properties/mosquitto_client_properties.c b/plugins/examples/client-properties/mosquitto_client_properties.c index 2d9cc2c5..b2ccafd9 100644 --- a/plugins/examples/client-properties/mosquitto_client_properties.c +++ b/plugins/examples/client-properties/mosquitto_client_properties.c @@ -19,6 +19,9 @@ #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "client-properties" +#define PLUGIN_VERSION "1.0" + #define UNUSED(A) (void)(A) static mosquitto_plugin_id_t *mosq_pid = NULL; @@ -57,6 +60,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL, NULL); } diff --git a/plugins/examples/connection-state/mosquitto_connection_state.c b/plugins/examples/connection-state/mosquitto_connection_state.c index 62a922b8..de8b9ea9 100644 --- a/plugins/examples/connection-state/mosquitto_connection_state.c +++ b/plugins/examples/connection-state/mosquitto_connection_state.c @@ -40,6 +40,9 @@ Contributors: #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "connection-state" +#define PLUGIN_VERSION "1.0" + #define UNUSED(A) (void)(A) static mosquitto_plugin_id_t *mosq_pid = NULL; @@ -115,6 +118,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); rc = mosquitto_callback_register(mosq_pid, MOSQ_EVT_CONNECT, connect_callback, NULL, NULL); if(rc) return rc; diff --git a/plugins/examples/delayed-auth/mosquitto_delayed_auth.c b/plugins/examples/delayed-auth/mosquitto_delayed_auth.c index 92c26265..16c3dd3a 100644 --- a/plugins/examples/delayed-auth/mosquitto_delayed_auth.c +++ b/plugins/examples/delayed-auth/mosquitto_delayed_auth.c @@ -44,6 +44,9 @@ Contributors: #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "delayed-auth" +#define PLUGIN_VERSION "1.0" + #ifndef UNUSED # define UNUSED(A) (void)(A) #endif @@ -156,6 +159,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); rc = mosquitto_callback_register(mosq_pid, MOSQ_EVT_BASIC_AUTH, basic_auth_callback, NULL, NULL); if(rc) return rc; diff --git a/plugins/examples/force-retain/mosquitto_force_retain.c b/plugins/examples/force-retain/mosquitto_force_retain.c index 8ae01b8f..176f1355 100644 --- a/plugins/examples/force-retain/mosquitto_force_retain.c +++ b/plugins/examples/force-retain/mosquitto_force_retain.c @@ -37,6 +37,9 @@ Contributors: #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "force-retain" +#define PLUGIN_VERSION "1.0" + #define UNUSED(A) (void)(A) static mosquitto_plugin_id_t *mosq_pid = NULL; @@ -72,6 +75,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL, NULL); } diff --git a/plugins/examples/message-timestamp/mosquitto_message_timestamp.c b/plugins/examples/message-timestamp/mosquitto_message_timestamp.c index ae35ff87..2a446267 100644 --- a/plugins/examples/message-timestamp/mosquitto_message_timestamp.c +++ b/plugins/examples/message-timestamp/mosquitto_message_timestamp.c @@ -38,6 +38,9 @@ Contributors: #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "message-timestamp" +#define PLUGIN_VERSION "1.0" + static mosquitto_plugin_id_t *mosq_pid = NULL; static int callback_message(int event, void *event_data, void *userdata) @@ -76,6 +79,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL, NULL); } diff --git a/plugins/examples/payload-modification/mosquitto_payload_modification.c b/plugins/examples/payload-modification/mosquitto_payload_modification.c index 6af83ef5..9bc37229 100644 --- a/plugins/examples/payload-modification/mosquitto_payload_modification.c +++ b/plugins/examples/payload-modification/mosquitto_payload_modification.c @@ -40,6 +40,9 @@ Contributors: #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "payload-modification" +#define PLUGIN_VERSION "1.0" + #define UNUSED(A) (void)(A) static mosquitto_plugin_id_t *mosq_pid = NULL; @@ -99,6 +102,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL, NULL); } diff --git a/plugins/examples/print-ip-on-publish/mosquitto_print_ip_on_publish.c b/plugins/examples/print-ip-on-publish/mosquitto_print_ip_on_publish.c index 75b56eb0..f62dca35 100644 --- a/plugins/examples/print-ip-on-publish/mosquitto_print_ip_on_publish.c +++ b/plugins/examples/print-ip-on-publish/mosquitto_print_ip_on_publish.c @@ -10,6 +10,9 @@ #include "mosquitto.h" #include "mqtt_protocol.h" +#define PLUGIN_NAME "print-ip-on-publish" +#define PLUGIN_VERSION "1.0" + static mosquitto_plugin_id_t *mosq_pid = NULL; static char my_topic[] = "troublesome/topic"; @@ -46,6 +49,7 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s UNUSED(opt_count); mosq_pid = identifier; + mosquitto_plugin_set_info(identifier, PLUGIN_NAME, PLUGIN_VERSION); return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, message_callback, NULL, NULL); } diff --git a/src/control.c b/src/control.c index 4daaaae5..3750dbd4 100644 --- a/src/control.c +++ b/src/control.c @@ -19,6 +19,7 @@ Contributors: #include "config.h" #include +#include #include "mqtt_protocol.h" #include "mosquitto_broker_internal.h" @@ -78,7 +79,7 @@ int control__process(struct mosquitto *context, struct mosquitto_msg_store *stor } #endif -int control__register_callback(MOSQ_FUNC_generic_callback cb_func, const char *topic, void *userdata) +int control__register_callback(mosquitto_plugin_id_t *pid, MOSQ_FUNC_generic_callback cb_func, const char *topic, void *userdata) { #ifdef WITH_CONTROL struct mosquitto__security_options *opts; @@ -112,19 +113,32 @@ int control__register_callback(MOSQ_FUNC_generic_callback cb_func, const char *t cb_new->userdata = userdata; HASH_ADD_KEYPTR(hh, opts->plugin_callbacks.control, cb_new->data, strlen(cb_new->data), cb_new); + if(pid->plugin_name){ + struct control_endpoint *ep; + ep = mosquitto_malloc(sizeof(struct control_endpoint) + topic_len + 2); + if(ep){ + ep->next = NULL; + ep->prev = NULL; + snprintf(ep->topic, topic_len+1, "%s", topic); + DL_APPEND(pid->control_endpoints, ep); + } + log__printf(NULL, MOSQ_LOG_INFO, "Plugin %s has registered to receive 'control' events on topic %s.", + pid->plugin_name, topic); + } return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif } -int control__unregister_callback(MOSQ_FUNC_generic_callback cb_func, const char *topic) +int control__unregister_callback(mosquitto_plugin_id_t *identifier, MOSQ_FUNC_generic_callback cb_func, const char *topic) { #ifdef WITH_CONTROL struct mosquitto__security_options *opts; struct mosquitto__callback *cb_found; size_t topic_len; + struct control_endpoint *ep; if(topic == NULL) return MOSQ_ERR_INVAL; topic_len = strlen(topic); @@ -139,7 +153,14 @@ int control__unregister_callback(MOSQ_FUNC_generic_callback cb_func, const char mosquitto__free(cb_found->data); mosquitto__free(cb_found); - return MOSQ_ERR_SUCCESS;; + DL_FOREACH(identifier->control_endpoints, ep){ + if(!strcmp(topic, ep->topic)){ + DL_DELETE(identifier->control_endpoints, ep); + mosquitto__free(ep); + break; + } + } + return MOSQ_ERR_SUCCESS; } return MOSQ_ERR_NOT_FOUND; #else diff --git a/src/linker-macosx.syms b/src/linker-macosx.syms index 40481bca..6f176cc2 100644 --- a/src/linker-macosx.syms +++ b/src/linker-macosx.syms @@ -18,6 +18,7 @@ _mosquitto_kick_client_by_clientid _mosquitto_kick_client_by_username _mosquitto_log_printf _mosquitto_malloc +_mosquitto_plugin_set_info _mosquitto_property_add_binary _mosquitto_property_add_byte _mosquitto_property_add_int16 diff --git a/src/linker.syms b/src/linker.syms index f1b8deb1..bad455c8 100644 --- a/src/linker.syms +++ b/src/linker.syms @@ -19,6 +19,7 @@ mosquitto_kick_client_by_username; mosquitto_log_printf; mosquitto_malloc; + mosquitto_plugin_set_info; mosquitto_property_add_binary; mosquitto_property_add_byte; mosquitto_property_add_int16; diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 9937ca60..e20465ad 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -257,6 +257,9 @@ struct mosquitto__listener_sock{ typedef struct mosquitto_plugin_id_t{ struct mosquitto__listener *listener; + char *plugin_name; + char *plugin_version; + struct control_endpoint *control_endpoints; } mosquitto_plugin_id_t; struct mosquitto__config { @@ -601,6 +604,11 @@ struct libws_mqtt_data { #include +struct control_endpoint { + struct control_endpoint *next, *prev; + char topic[]; +}; + extern struct mosquitto_db db; /* ============================================================ @@ -733,8 +741,8 @@ int connect__on_authorised(struct mosquitto *context, void *auth_data_out, uint1 int control__process(struct mosquitto *context, struct mosquitto_msg_store *stored); void control__cleanup(void); #endif -int control__register_callback(MOSQ_FUNC_generic_callback cb_func, const char *topic, void *userdata); -int control__unregister_callback(MOSQ_FUNC_generic_callback cb_func, const char *topic); +int control__register_callback(mosquitto_plugin_id_t *pid, MOSQ_FUNC_generic_callback cb_func, const char *topic, void *userdata); +int control__unregister_callback(mosquitto_plugin_id_t *pid, MOSQ_FUNC_generic_callback cb_func, const char *topic); /* ============================================================ diff --git a/src/plugin.c b/src/plugin.c index 07f4214a..d15964d6 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -99,6 +99,13 @@ int plugin__load_v5(struct mosquitto__listener *listener, struct mosquitto__auth return rc; } } + if(pid->plugin_name && pid->plugin_version){ + log__printf(NULL, MOSQ_LOG_INFO, + "Plugin %s version %s loaded.", pid->plugin_name, pid->plugin_version); + }else if(pid->plugin_name){ + log__printf(NULL, MOSQ_LOG_INFO, + "Plugin %s loaded.", pid->plugin_name); + } return 0; } @@ -249,6 +256,7 @@ int mosquitto_callback_register( { struct mosquitto__callback **cb_base = NULL, *cb_new; struct mosquitto__security_options *security_options; + const char *event_name; if(cb_func == NULL) return MOSQ_ERR_INVAL; @@ -261,36 +269,46 @@ int mosquitto_callback_register( switch(event){ case MOSQ_EVT_RELOAD: cb_base = &security_options->plugin_callbacks.reload; + event_name = "reload"; break; case MOSQ_EVT_ACL_CHECK: cb_base = &security_options->plugin_callbacks.acl_check; + event_name = "acl-check"; break; case MOSQ_EVT_BASIC_AUTH: cb_base = &security_options->plugin_callbacks.basic_auth; + event_name = "basic-auth"; break; case MOSQ_EVT_PSK_KEY: cb_base = &security_options->plugin_callbacks.psk_key; + event_name = "psk-key"; break; case MOSQ_EVT_EXT_AUTH_START: cb_base = &security_options->plugin_callbacks.ext_auth_start; + event_name = "auth-start"; break; case MOSQ_EVT_EXT_AUTH_CONTINUE: cb_base = &security_options->plugin_callbacks.ext_auth_continue; + event_name = "auth-continue"; break; case MOSQ_EVT_CONTROL: - return control__register_callback(cb_func, event_data, userdata); + return control__register_callback(identifier, cb_func, event_data, userdata); break; case MOSQ_EVT_MESSAGE: cb_base = &security_options->plugin_callbacks.message; + event_name = "message"; break; case MOSQ_EVT_TICK: cb_base = &security_options->plugin_callbacks.tick; + event_name = "tick"; break; case MOSQ_EVT_DISCONNECT: cb_base = &security_options->plugin_callbacks.disconnect; + event_name = "disconnect"; break; case MOSQ_EVT_CONNECT: cb_base = &security_options->plugin_callbacks.connect; + event_name = "connect"; break; default: return MOSQ_ERR_NOT_SUPPORTED; @@ -309,6 +327,11 @@ int mosquitto_callback_register( cb_new->cb = cb_func; cb_new->userdata = userdata; + if(identifier->plugin_name){ + log__printf(NULL, MOSQ_LOG_INFO, "Plugin %s has registered to receive '%s' events.", + identifier->plugin_name, event_name); + } + return MOSQ_ERR_SUCCESS; } @@ -351,7 +374,7 @@ int mosquitto_callback_unregister( cb_base = &security_options->plugin_callbacks.ext_auth_continue; break; case MOSQ_EVT_CONTROL: - return control__unregister_callback(cb_func, event_data); + return control__unregister_callback(identifier, cb_func, event_data); break; case MOSQ_EVT_MESSAGE: cb_base = &security_options->plugin_callbacks.message; diff --git a/src/plugin_public.c b/src/plugin_public.c index 111f48f3..33f8fbeb 100644 --- a/src/plugin_public.c +++ b/src/plugin_public.c @@ -31,6 +31,25 @@ Contributors: # include #endif +int mosquitto_plugin_set_info(mosquitto_plugin_id_t *identifier, + const char *plugin_name, + const char *plugin_version) +{ + if(identifier == NULL || plugin_name == NULL){ + return MOSQ_ERR_INVAL; + } + + identifier->plugin_name = mosquitto_strdup(plugin_name); + if(plugin_version){ + identifier->plugin_version = mosquitto_strdup(plugin_version); + }else{ + identifier->plugin_version = NULL; + } + + return MOSQ_ERR_SUCCESS; +} + + const char *mosquitto_client_address(const struct mosquitto *client) { if(client){ diff --git a/src/security.c b/src/security.c index 239c9974..e4db8536 100644 --- a/src/security.c +++ b/src/security.c @@ -405,6 +405,7 @@ int mosquitto_security_module_init(void) static void security__module_cleanup_single(struct mosquitto__security_options *opts) { int i; + struct control_endpoint *ep, *tmp; for(i=0; iauth_plugin_config_count; i++){ /* Run plugin cleanup function */ @@ -413,6 +414,12 @@ static void security__module_cleanup_single(struct mosquitto__security_options * opts->auth_plugin_configs[i].plugin.user_data, opts->auth_plugin_configs[i].options, opts->auth_plugin_configs[i].option_count); + mosquitto__free(opts->auth_plugin_configs[i].plugin.identifier->plugin_name); + mosquitto__free(opts->auth_plugin_configs[i].plugin.identifier->plugin_version); + DL_FOREACH_SAFE(opts->auth_plugin_configs[i].plugin.identifier->control_endpoints, ep, tmp){ + DL_DELETE(opts->auth_plugin_configs[i].plugin.identifier->control_endpoints, ep); + mosquitto__free(ep); + } mosquitto__free(opts->auth_plugin_configs[i].plugin.identifier); opts->auth_plugin_configs[i].plugin.identifier = NULL;