2014-05-07 22:27:00 +00:00
|
|
|
/*
|
2020-02-27 23:26:58 +00:00
|
|
|
Copyright (c) 2009-2020 Roger Light <roger@atchoo.org>
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
All rights reserved. This program and the accompanying materials
|
|
|
|
are made available under the terms of the Eclipse Public License v1.0
|
|
|
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
|
|
|
|
|
|
The Eclipse Public License is available at
|
|
|
|
http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
and the Eclipse Distribution License is available at
|
|
|
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
|
|
|
|
|
|
|
Contributors:
|
|
|
|
Roger Light - initial implementation and documentation.
|
|
|
|
*/
|
|
|
|
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "config.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
/* For initgroups() */
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <grp.h>
|
2016-02-11 21:49:55 +00:00
|
|
|
# include <assert.h>
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <pwd.h>
|
|
|
|
#else
|
|
|
|
#include <process.h>
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#endif
|
|
|
|
|
2014-06-02 00:01:29 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
# include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2015-06-22 18:11:17 +00:00
|
|
|
#ifdef WITH_SYSTEMD
|
|
|
|
# include <systemd/sd-daemon.h>
|
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_WRAP
|
|
|
|
#include <tcpd.h>
|
|
|
|
#endif
|
2014-06-30 22:30:43 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
# include <libwebsockets.h>
|
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2016-07-08 09:10:04 +00:00
|
|
|
#include "mosquitto_broker_internal.h"
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "memory_mosq.h"
|
2020-02-04 16:05:58 +00:00
|
|
|
#include "misc_mosq.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
#include "util_mosq.h"
|
|
|
|
|
|
|
|
struct mosquitto_db int_db;
|
|
|
|
|
|
|
|
bool flag_reload = false;
|
|
|
|
#ifdef WITH_PERSISTENCE
|
|
|
|
bool flag_db_backup = false;
|
|
|
|
#endif
|
|
|
|
bool flag_tree_print = false;
|
|
|
|
int run;
|
|
|
|
#ifdef WITH_WRAP
|
|
|
|
#include <syslog.h>
|
|
|
|
int allow_severity = LOG_INFO;
|
|
|
|
int deny_severity = LOG_INFO;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void handle_sigint(int signal);
|
|
|
|
void handle_sigusr1(int signal);
|
|
|
|
void handle_sigusr2(int signal);
|
2016-07-03 21:40:27 +00:00
|
|
|
#ifdef SIGHUP
|
|
|
|
void handle_sighup(int signal);
|
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
struct mosquitto_db *mosquitto__get_db(void)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
|
|
|
return &int_db;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mosquitto shouldn't run as root.
|
|
|
|
* This function will attempt to change to an unprivileged user and group if
|
|
|
|
* running as root. The user is given in config->user.
|
|
|
|
* Returns 1 on failure (unknown user, setuid/setgid failure)
|
|
|
|
* Returns 0 on success.
|
|
|
|
* Note that setting config->user to "root" does not produce an error, but it
|
|
|
|
* strongly discouraged.
|
|
|
|
*/
|
2020-11-05 12:05:07 +00:00
|
|
|
int drop_privileges(struct mosquitto__config *config)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
|
|
|
#if !defined(__CYGWIN__) && !defined(WIN32)
|
|
|
|
struct passwd *pwd;
|
2018-11-07 17:43:21 +00:00
|
|
|
char *err;
|
2015-02-08 22:06:11 +00:00
|
|
|
int rc;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-09-20 11:05:02 +00:00
|
|
|
const char *snap = getenv("SNAP_NAME");
|
|
|
|
if(snap && !strcmp(snap, "mosquitto")){
|
|
|
|
/* Don't attempt to drop privileges if running as a snap */
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
if(geteuid() == 0){
|
|
|
|
if(config->user && strcmp(config->user, "root")){
|
|
|
|
pwd = getpwnam(config->user);
|
|
|
|
if(!pwd){
|
2019-08-07 09:42:03 +00:00
|
|
|
if(strcmp(config->user, "mosquitto")){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to drop privileges to '%s' because this user does not exist.", config->user);
|
|
|
|
return 1;
|
|
|
|
}else{
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Warning: Unable to drop privileges to '%s' because this user does not exist. Trying 'nobody' instead.", config->user);
|
|
|
|
pwd = getpwnam("nobody");
|
|
|
|
if(!pwd){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to drop privileges to 'nobody'.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
if(initgroups(config->user, pwd->pw_gid) == -1){
|
2018-11-07 17:43:21 +00:00
|
|
|
err = strerror(errno);
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error setting groups whilst dropping privileges: %s.", err);
|
2014-05-07 22:27:00 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2020-11-05 12:05:07 +00:00
|
|
|
rc = setgid(pwd->pw_gid);
|
2015-02-08 22:06:11 +00:00
|
|
|
if(rc == -1){
|
2018-11-07 17:43:21 +00:00
|
|
|
err = strerror(errno);
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error setting gid whilst dropping privileges: %s.", err);
|
2014-05-07 22:27:00 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2020-11-05 12:05:07 +00:00
|
|
|
rc = setuid(pwd->pw_uid);
|
2015-02-08 22:06:11 +00:00
|
|
|
if(rc == -1){
|
2018-11-07 17:43:21 +00:00
|
|
|
err = strerror(errno);
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error setting uid whilst dropping privileges: %s.", err);
|
2014-05-07 22:27:00 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(geteuid() == 0 || getegid() == 0){
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Mosquitto should not be run as root/administrator.");
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2016-02-11 21:49:55 +00:00
|
|
|
void mosquitto__daemonise(void)
|
|
|
|
{
|
|
|
|
#ifndef WIN32
|
2018-11-07 17:43:21 +00:00
|
|
|
char *err;
|
2016-02-11 21:49:55 +00:00
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
pid = fork();
|
|
|
|
if(pid < 0){
|
2018-11-07 17:43:21 +00:00
|
|
|
err = strerror(errno);
|
2016-06-21 22:33:58 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in fork: %s", err);
|
2016-02-11 21:49:55 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(pid > 0){
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
if(setsid() < 0){
|
2018-11-07 17:43:21 +00:00
|
|
|
err = strerror(errno);
|
2016-06-21 22:33:58 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in setsid: %s", err);
|
2016-02-11 21:49:55 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(freopen("/dev/null", "r", stdin));
|
|
|
|
assert(freopen("/dev/null", "w", stdout));
|
|
|
|
assert(freopen("/dev/null", "w", stderr));
|
|
|
|
#else
|
2016-06-21 22:33:58 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows.");
|
2016-02-11 21:49:55 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2020-09-16 13:33:32 +00:00
|
|
|
void listener__set_defaults(struct mosquitto__listener *listener)
|
|
|
|
{
|
|
|
|
listener->security_options.allow_anonymous = -1;
|
|
|
|
listener->security_options.allow_zero_length_clientid = true;
|
|
|
|
listener->protocol = mp_mqtt;
|
|
|
|
listener->max_connections = -1;
|
|
|
|
listener->maximum_qos = 2;
|
|
|
|
listener->max_topic_alias = 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-04 22:33:01 +00:00
|
|
|
void listeners__reload_all_certificates(struct mosquitto_db *db)
|
|
|
|
{
|
2020-11-05 10:23:01 +00:00
|
|
|
#ifdef WITH_TLS
|
2020-11-04 22:33:01 +00:00
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
struct mosquitto__listener *listener;
|
|
|
|
|
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
listener = &db->config->listeners[i];
|
|
|
|
if(listener->ssl_ctx && listener->certfile && listener->keyfile){
|
|
|
|
rc = net__load_certificates(listener);
|
|
|
|
if(rc){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error when reloading certificate '%s' or key '%s'.",
|
|
|
|
listener->certfile, listener->keyfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-05 10:23:01 +00:00
|
|
|
#endif
|
2020-11-04 22:33:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-16 10:41:35 +00:00
|
|
|
int listeners__start_single_mqtt(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count, int *listensock_index, struct mosquitto__listener *listener)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
mosq_sock_t *listensock_new;
|
|
|
|
|
|
|
|
if(net__socket_listen(listener)){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
(*listensock_count) += listener->sock_count;
|
2020-10-17 00:23:08 +00:00
|
|
|
listensock_new = mosquitto__realloc(*listensock, sizeof(mosq_sock_t)*(size_t)(*listensock_count));
|
2020-09-16 10:41:35 +00:00
|
|
|
if(!listensock_new){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
*listensock = listensock_new;
|
|
|
|
|
|
|
|
for(i=0; i<listener->sock_count; i++){
|
|
|
|
if(listener->socks[i] == INVALID_SOCKET){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
(*listensock)[*listensock_index] = listener->socks[i];
|
|
|
|
(*listensock_index)++;
|
|
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int listeners__add_local(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count, int *listensock_index, const char *host, uint16_t port)
|
|
|
|
{
|
|
|
|
struct mosquitto__listener *listeners;
|
|
|
|
|
2020-10-17 00:23:08 +00:00
|
|
|
listeners = mosquitto__realloc(db->config->listeners, (size_t)(db->config->listener_count+1)*sizeof(struct mosquitto__listener));
|
2020-09-16 10:41:35 +00:00
|
|
|
if(listeners == NULL){
|
|
|
|
return MOSQ_ERR_NOMEM;
|
|
|
|
}
|
|
|
|
db->config->listener_count++;
|
|
|
|
db->config->listeners = listeners;
|
|
|
|
memset(&listeners[db->config->listener_count-1], 0, sizeof(struct mosquitto__listener));
|
|
|
|
|
2020-09-16 13:33:32 +00:00
|
|
|
listener__set_defaults(&listeners[db->config->listener_count-1]);
|
|
|
|
listeners[db->config->listener_count-1].security_options.allow_anonymous = true;
|
2020-09-16 10:41:35 +00:00
|
|
|
listeners[db->config->listener_count-1].port = port;
|
|
|
|
listeners[db->config->listener_count-1].host = mosquitto__strdup(host);
|
|
|
|
if(listeners[db->config->listener_count-1].host == NULL){
|
|
|
|
return MOSQ_ERR_NOMEM;
|
|
|
|
}
|
|
|
|
if(listeners__start_single_mqtt(db, listensock, listensock_count, listensock_index, &listeners[db->config->listener_count-1])){
|
|
|
|
mosquitto__free(listeners[db->config->listener_count-1].host);
|
|
|
|
listeners[db->config->listener_count-1].host = NULL;
|
|
|
|
db->config->listener_count--;
|
|
|
|
return MOSQ_ERR_UNKNOWN;
|
|
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int listeners__start_local_only(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count)
|
|
|
|
{
|
|
|
|
/* Attempt to open listeners bound to 127.0.0.1 and ::1 only */
|
|
|
|
int i;
|
|
|
|
int listensock_index = 0;
|
|
|
|
int rc;
|
|
|
|
|
2020-10-21 12:27:39 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_WARNING, "Starting in local only mode. Connections will only be possible from clients running on this machine.");
|
|
|
|
log__printf(NULL, MOSQ_LOG_WARNING, "Create a configuration file which defines a listener to allow remote access.");
|
2020-09-16 10:41:35 +00:00
|
|
|
if(db->config->cmd_port_count == 0){
|
|
|
|
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "127.0.0.1", 1883);
|
|
|
|
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
|
|
|
|
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "::1", 1883);
|
|
|
|
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
|
|
|
|
}else{
|
|
|
|
for(i=0; i<db->config->cmd_port_count; i++){
|
|
|
|
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "127.0.0.1", db->config->cmd_port[i]);
|
|
|
|
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
|
|
|
|
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "::1", db->config->cmd_port[i]);
|
|
|
|
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(db->config->listener_count > 0){
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}else{
|
|
|
|
return MOSQ_ERR_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-08 10:34:31 +00:00
|
|
|
int listeners__start(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count)
|
|
|
|
{
|
2020-09-16 10:41:35 +00:00
|
|
|
int i;
|
2020-04-08 10:34:31 +00:00
|
|
|
int listensock_index = 0;
|
|
|
|
|
|
|
|
listensock_index = 0;
|
|
|
|
(*listensock_count) = 0;
|
2020-09-16 10:41:35 +00:00
|
|
|
|
|
|
|
if(db->config->listener_count == 0){
|
|
|
|
if(listeners__start_local_only(db, listensock, listensock_count)){
|
|
|
|
db__close(db);
|
|
|
|
if(db->config->pid_file){
|
|
|
|
remove(db->config->pid_file);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-04-08 10:34:31 +00:00
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
if(db->config->listeners[i].protocol == mp_mqtt){
|
2020-09-16 10:41:35 +00:00
|
|
|
if(listeners__start_single_mqtt(db, listensock, listensock_count, &listensock_index, &db->config->listeners[i])){
|
2020-04-08 10:34:31 +00:00
|
|
|
db__close(db);
|
|
|
|
if(db->config->pid_file){
|
|
|
|
remove(db->config->pid_file);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}else if(db->config->listeners[i].protocol == mp_websockets){
|
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
db->config->listeners[i].ws_context = mosq_websockets_init(&db->config->listeners[i], db->config);
|
|
|
|
if(!db->config->listeners[i].ws_context){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to create websockets listener on port %d.", db->config->listeners[i].port);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if((*listensock) == NULL){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to start any listening sockets, exiting.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void listeners__stop(struct mosquitto_db *db, mosq_sock_t *listensock, int listensock_count)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
if(db->config->listeners[i].ws_context){
|
|
|
|
libwebsocket_context_destroy(db->config->listeners[i].ws_context);
|
|
|
|
}
|
|
|
|
mosquitto__free(db->config->listeners[i].ws_protocol);
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_UNIX_SOCKETS
|
|
|
|
if(db->config->listeners[i].unix_socket_path != NULL){
|
|
|
|
unlink(db->config->listeners[i].unix_socket_path);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<listensock_count; i++){
|
|
|
|
if(listensock[i] != INVALID_SOCKET){
|
|
|
|
COMPAT_CLOSE(listensock[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mosquitto__free(listensock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void signal__setup(void)
|
|
|
|
{
|
|
|
|
signal(SIGINT, handle_sigint);
|
|
|
|
signal(SIGTERM, handle_sigint);
|
|
|
|
#ifdef SIGHUP
|
|
|
|
signal(SIGHUP, handle_sighup);
|
|
|
|
#endif
|
|
|
|
#ifndef WIN32
|
|
|
|
signal(SIGUSR1, handle_sigusr1);
|
|
|
|
signal(SIGUSR2, handle_sigusr2);
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
|
|
CreateThread(NULL, 0, SigThreadProc, NULL, 0, NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int pid__write(struct mosquitto_db *db)
|
|
|
|
{
|
|
|
|
FILE *pid;
|
|
|
|
|
2020-10-13 20:14:48 +00:00
|
|
|
if(db->config->pid_file){
|
2020-04-08 10:34:31 +00:00
|
|
|
pid = mosquitto__fopen(db->config->pid_file, "wt", false);
|
|
|
|
if(pid){
|
|
|
|
fprintf(pid, "%d", getpid());
|
|
|
|
fclose(pid);
|
|
|
|
}else{
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to write pid file.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2015-03-29 09:43:08 +00:00
|
|
|
mosq_sock_t *listensock = NULL;
|
2014-05-07 22:27:00 +00:00
|
|
|
int listensock_count = 0;
|
2015-05-16 18:03:12 +00:00
|
|
|
struct mosquitto__config config;
|
2020-11-05 10:23:01 +00:00
|
|
|
#ifdef WITH_BRIDGE
|
2020-04-08 10:34:31 +00:00
|
|
|
int i;
|
2020-11-05 10:23:01 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
int rc;
|
|
|
|
#ifdef WIN32
|
|
|
|
SYSTEMTIME st;
|
|
|
|
#else
|
|
|
|
struct timeval tv;
|
|
|
|
#endif
|
2014-06-23 16:57:35 +00:00
|
|
|
struct mosquitto *ctxt, *ctxt_tmp;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
#if defined(WIN32) || defined(__CYGWIN__)
|
|
|
|
if(argc == 2){
|
|
|
|
if(!strcmp(argv[1], "run")){
|
|
|
|
service_run();
|
|
|
|
return 0;
|
|
|
|
}else if(!strcmp(argv[1], "install")){
|
|
|
|
service_install();
|
|
|
|
return 0;
|
|
|
|
}else if(!strcmp(argv[1], "uninstall")){
|
|
|
|
service_uninstall();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
GetSystemTime(&st);
|
|
|
|
srand(st.wSecond + st.wMilliseconds);
|
|
|
|
#else
|
|
|
|
gettimeofday(&tv, NULL);
|
2020-10-17 00:23:08 +00:00
|
|
|
srand((unsigned int)(tv.tv_sec + tv.tv_usec));
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2018-03-14 10:01:47 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
_setmaxstdio(2048);
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
memset(&int_db, 0, sizeof(struct mosquitto_db));
|
|
|
|
|
2018-09-18 11:08:49 +00:00
|
|
|
net__broker_init();
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-05-02 22:56:11 +00:00
|
|
|
config__init(&int_db, &config);
|
|
|
|
rc = config__parse_args(&int_db, &config, argc, argv);
|
2014-05-07 22:27:00 +00:00
|
|
|
if(rc != MOSQ_ERR_SUCCESS) return rc;
|
|
|
|
int_db.config = &config;
|
|
|
|
|
2020-11-05 12:05:07 +00:00
|
|
|
/* Drop privileges permanently immediately after the config is loaded.
|
|
|
|
* This requires the user to ensure that all certificates, log locations,
|
|
|
|
* etc. are accessible my the `mosquitto` or other unprivileged user.
|
|
|
|
*/
|
|
|
|
rc = drop_privileges(&config);
|
|
|
|
if(rc != MOSQ_ERR_SUCCESS) return rc;
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
if(config.daemon){
|
2016-02-11 21:49:55 +00:00
|
|
|
mosquitto__daemonise();
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
2020-04-08 10:34:31 +00:00
|
|
|
if(pid__write(&int_db)) return 1;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2015-05-16 14:24:24 +00:00
|
|
|
rc = db__open(&config, &int_db);
|
2014-05-07 22:27:00 +00:00
|
|
|
if(rc != MOSQ_ERR_SUCCESS){
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Couldn't open database.");
|
2014-05-07 22:27:00 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialise logging only after initialising the database in case we're
|
|
|
|
* logging to topics */
|
2017-03-06 21:19:53 +00:00
|
|
|
if(log__init(&config)){
|
2016-08-16 21:31:36 +00:00
|
|
|
rc = 1;
|
|
|
|
return rc;
|
|
|
|
}
|
2018-01-12 13:41:09 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s starting", VERSION);
|
2018-02-24 21:44:38 +00:00
|
|
|
if(int_db.config_file){
|
2018-05-02 22:56:11 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Config loaded from %s.", int_db.config_file);
|
2014-05-07 22:27:00 +00:00
|
|
|
}else{
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Using default config.");
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = mosquitto_security_module_init(&int_db);
|
|
|
|
if(rc) return rc;
|
|
|
|
rc = mosquitto_security_init(&int_db, false);
|
|
|
|
if(rc) return rc;
|
|
|
|
|
2020-08-07 06:32:14 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_SYS_TREE
|
2016-07-08 08:14:11 +00:00
|
|
|
sys_tree__init(&int_db);
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2020-04-08 10:34:31 +00:00
|
|
|
if(listeners__start(&int_db, &listensock, &listensock_count)) return 1;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2020-04-08 10:34:31 +00:00
|
|
|
signal__setup();
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
#ifdef WITH_BRIDGE
|
2020-04-08 10:34:31 +00:00
|
|
|
bridge__start_all(&int_db);
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2020-07-10 14:36:17 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s running", VERSION);
|
2015-06-22 18:11:17 +00:00
|
|
|
#ifdef WITH_SYSTEMD
|
|
|
|
sd_notify(0, "READY=1");
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
run = 1;
|
2019-03-13 14:11:50 +00:00
|
|
|
rc = mosquitto_main_loop(&int_db, listensock, listensock_count);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s terminating", VERSION);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2019-02-25 22:28:51 +00:00
|
|
|
/* FIXME - this isn't quite right, all wills with will delay zero should be
|
|
|
|
* sent now, but those with positive will delay should be persisted and
|
|
|
|
* restored, pending the client reconnecting in time. */
|
2017-07-10 22:43:42 +00:00
|
|
|
HASH_ITER(hh_id, int_db.contexts_by_id, ctxt, ctxt_tmp){
|
2017-07-19 13:49:49 +00:00
|
|
|
context__send_will(&int_db, ctxt);
|
2017-07-10 22:43:42 +00:00
|
|
|
}
|
2019-02-25 22:28:51 +00:00
|
|
|
will_delay__send_all(&int_db);
|
2017-07-10 22:43:42 +00:00
|
|
|
|
|
|
|
#ifdef WITH_PERSISTENCE
|
2020-04-08 10:34:31 +00:00
|
|
|
persist__backup(&int_db, true);
|
2017-07-10 22:43:42 +00:00
|
|
|
#endif
|
2019-03-25 06:55:45 +00:00
|
|
|
session_expiry__remove_all(&int_db);
|
2017-07-10 22:43:42 +00:00
|
|
|
|
2014-06-23 16:57:35 +00:00
|
|
|
HASH_ITER(hh_id, int_db.contexts_by_id, ctxt, ctxt_tmp){
|
2014-06-30 22:30:43 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
if(!ctxt->wsi){
|
2015-05-16 14:24:24 +00:00
|
|
|
context__cleanup(&int_db, ctxt, true);
|
2014-06-30 22:30:43 +00:00
|
|
|
}
|
|
|
|
#else
|
2015-05-16 14:24:24 +00:00
|
|
|
context__cleanup(&int_db, ctxt, true);
|
2014-06-30 22:30:43 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2014-06-28 00:38:58 +00:00
|
|
|
HASH_ITER(hh_sock, int_db.contexts_by_sock, ctxt, ctxt_tmp){
|
2015-05-16 14:24:24 +00:00
|
|
|
context__cleanup(&int_db, ctxt, true);
|
2014-06-28 00:38:58 +00:00
|
|
|
}
|
2014-06-30 22:37:03 +00:00
|
|
|
#ifdef WITH_BRIDGE
|
2014-11-18 23:34:54 +00:00
|
|
|
for(i=0; i<int_db.bridge_count; i++){
|
|
|
|
if(int_db.bridges[i]){
|
2015-05-16 14:24:24 +00:00
|
|
|
context__cleanup(&int_db, int_db.bridges[i], true);
|
2014-11-18 23:34:54 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-22 13:42:56 +00:00
|
|
|
mosquitto__free(int_db.bridges);
|
2014-06-30 22:37:03 +00:00
|
|
|
#endif
|
2015-05-16 14:24:24 +00:00
|
|
|
context__free_disused(&int_db);
|
2014-06-30 22:30:43 +00:00
|
|
|
|
2015-05-16 14:24:24 +00:00
|
|
|
db__close(&int_db);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2020-04-08 10:34:31 +00:00
|
|
|
listeners__stop(&int_db, listensock, listensock_count);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
mosquitto_security_module_cleanup(&int_db);
|
|
|
|
|
|
|
|
if(config.pid_file){
|
|
|
|
remove(config.pid_file);
|
|
|
|
}
|
|
|
|
|
2019-03-18 23:04:34 +00:00
|
|
|
log__close(&config);
|
2015-05-16 14:24:24 +00:00
|
|
|
config__cleanup(int_db.config);
|
2018-09-19 12:01:13 +00:00
|
|
|
net__broker_cleanup();
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WIN32
|
2015-09-22 09:03:57 +00:00
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
|
|
|
char **argv;
|
|
|
|
int argc = 1;
|
|
|
|
char *token;
|
|
|
|
char *saveptr = NULL;
|
|
|
|
int rc;
|
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
argv = mosquitto__malloc(sizeof(char *)*1);
|
2014-05-07 22:27:00 +00:00
|
|
|
argv[0] = "mosquitto";
|
|
|
|
token = strtok_r(lpCmdLine, " ", &saveptr);
|
|
|
|
while(token){
|
|
|
|
argc++;
|
2015-04-19 21:10:59 +00:00
|
|
|
argv = mosquitto__realloc(argv, sizeof(char *)*argc);
|
2014-05-07 22:27:00 +00:00
|
|
|
if(!argv){
|
|
|
|
fprintf(stderr, "Error: Out of memory.\n");
|
|
|
|
return MOSQ_ERR_NOMEM;
|
|
|
|
}
|
|
|
|
argv[argc-1] = token;
|
|
|
|
token = strtok_r(NULL, " ", &saveptr);
|
|
|
|
}
|
|
|
|
rc = main(argc, argv);
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__free(argv);
|
2014-05-07 22:27:00 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif
|