diff --git a/lib/actions_subscribe.c b/lib/actions_subscribe.c index aec454d041..03a5858ad3 100644 --- a/lib/actions_subscribe.c +++ b/lib/actions_subscribe.c @@ -90,6 +90,11 @@ int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count if(mosquitto_validate_utf8(sub[i], slen)){ return MOSQ_ERR_MALFORMED_UTF8; } + if(!mosq->wildcard_sub_available){ + if(strchr(sub[i], '+') || strchr(sub[i], '#')){ + return MOSQ_ERR_WILDCARD_SUBS_NOT_SUPPORTED; + } + } remaining_length += 2+(uint32_t)slen + 1; } diff --git a/lib/connect.c b/lib/connect.c index 2e714b22fe..d22289a663 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -94,6 +94,7 @@ static int mosquitto__connect_init(struct mosquitto *mosq, const char *host, int mosq->msgs_in.inflight_quota = mosq->msgs_in.inflight_maximum; mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum; mosq->retain_available = 1; + mosq->wildcard_sub_available = 1; mosquitto__set_request_disconnect(mosq, false); return MOSQ_ERR_SUCCESS; diff --git a/lib/handle_connack.c b/lib/handle_connack.c index 93ee81c6f1..d8aeabda10 100644 --- a/lib/handle_connack.c +++ b/lib/handle_connack.c @@ -102,6 +102,7 @@ int handle__connack(struct mosquitto *mosq) } mosquitto_property_read_byte(properties, MQTT_PROP_RETAIN_AVAILABLE, &mosq->retain_available, false); + mosquitto_property_read_byte(properties, MQTT_PROP_WILDCARD_SUB_AVAILABLE, &mosq->wildcard_sub_available, false); mosquitto_property_read_byte(properties, MQTT_PROP_MAXIMUM_QOS, &mosq->max_qos, false); mosquitto_property_read_int16(properties, MQTT_PROP_RECEIVE_MAXIMUM, &mosq->msgs_out.inflight_maximum, false); mosquitto_property_read_int16(properties, MQTT_PROP_SERVER_KEEP_ALIVE, &mosq->keepalive, false); diff --git a/lib/libmosquitto.c b/lib/libmosquitto.c index 559ac99cfc..91a53bab93 100644 --- a/lib/libmosquitto.c +++ b/lib/libmosquitto.c @@ -206,6 +206,7 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_st mosq->last_mid = 0; mosq->state = mosq_cs_new; mosq->max_qos = 2; + mosq->wildcard_sub_available = 1; mosq->msgs_in.inflight_maximum = 20; mosq->msgs_out.inflight_maximum = 20; mosq->msgs_in.inflight_quota = 20; diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index 0dd27b3158..fdfb579d80 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -451,6 +451,7 @@ struct mosquitto { #endif uint8_t max_qos; uint8_t retain_available; + uint8_t wildcard_sub_available; bool tcp_nodelay; #if defined(WITH_WEBSOCKETS) && WITH_WEBSOCKETS == WS_IS_BUILTIN char *http_request; diff --git a/test/lib/c/02-subscribe-wildcard-unavailable-v5.c b/test/lib/c/02-subscribe-wildcard-unavailable-v5.c new file mode 100644 index 0000000000..981a6a236a --- /dev/null +++ b/test/lib/c/02-subscribe-wildcard-unavailable-v5.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include + +static int run = -1; + + +static void on_connect(struct mosquitto *mosq, void *obj, int rc) +{ + (void)obj; + + if(rc){ + exit(1); + }else{ + /* Wildcard subscribe must be rejected client-side: CONNACK said = 0 */ + rc = mosquitto_subscribe(mosq, NULL, "wildcard/+/rejected", 0); + if(rc != MOSQ_ERR_WILDCARD_SUBS_NOT_SUPPORTED){ + run = 1; + return; + } + rc = mosquitto_subscribe(mosq, NULL, "wildcard/#", 0); + if(rc != MOSQ_ERR_WILDCARD_SUBS_NOT_SUPPORTED){ + run = 1; + return; + } + /* Plain topic must succeed */ + rc = mosquitto_subscribe(mosq, NULL, "plain/topic", 0); + if(rc != MOSQ_ERR_SUCCESS){ + run = 1; + } + } +} + + +static void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) +{ + (void)obj; + (void)mid; + (void)qos_count; + (void)granted_qos; + + mosquitto_disconnect(mosq); +} + + +static void on_disconnect(struct mosquitto *mosq, void *obj, int rc) +{ + (void)mosq; + (void)obj; + (void)rc; + + run = 0; +} + + +int main(int argc, char *argv[]) +{ + int rc; + struct mosquitto *mosq; + int port; + + if(argc < 2){ + return 1; + } + port = atoi(argv[1]); + + mosquitto_lib_init(); + + mosq = mosquitto_new("subscribe-wildcard-unavailable-test", true, NULL); + if(mosq == NULL){ + return 1; + } + mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, MQTT_PROTOCOL_V5); + mosquitto_connect_callback_set(mosq, on_connect); + mosquitto_subscribe_callback_set(mosq, on_subscribe); + mosquitto_disconnect_callback_set(mosq, on_disconnect); + + rc = mosquitto_connect(mosq, "localhost", port, 60); + if(rc != MOSQ_ERR_SUCCESS){ + return rc; + } + + while(run == -1){ + mosquitto_loop(mosq, 50, 1); + } + + mosquitto_destroy(mosq); + mosquitto_lib_cleanup(); + return run; +}