Allow creation of listener at runtime
Listeners can now be created and started at runtime. If SSL is to be used, the required parameters must be present.
This commit is contained in:
parent
b24a28285c
commit
e8af6908c1
@ -118,3 +118,29 @@ bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert
|
||||
* @return True if @c key was one of the supported parameters
|
||||
*/
|
||||
bool runtime_alter_monitor(MONITOR *monitor, char *key, char *value);
|
||||
|
||||
/**
|
||||
* @brief Create a new listener for a service
|
||||
*
|
||||
* This function adds a new listener to a service and starts it.
|
||||
*
|
||||
* @param service Service where the listener is added
|
||||
* @param name Name of the listener
|
||||
* @param addr Listening address, NULL for default of 0.0.0.0
|
||||
* @param port Listening port, NULL for default of 3306
|
||||
* @param proto Listener protocol, NULL for default of "MySQLClient"
|
||||
* @param auth Listener authenticator, NULL for protocol default authenticator
|
||||
* @param auth_opt Options for the authenticator, NULL for no options
|
||||
* @param ssl_key SSL key, NULL for no key
|
||||
* @param ssl_cert SSL cert, NULL for no cert
|
||||
* @param ssl_ca SSL CA cert, NULL for no CA cert
|
||||
* @param ssl_version SSL version, NULL for default of "MAX"
|
||||
* @param ssl_depth SSL cert verification depth, NULL for default
|
||||
*
|
||||
* @return True if the listener was successfully created and started
|
||||
*/
|
||||
bool runtime_create_listener(SERVICE *service, const char *name, const char *addr,
|
||||
const char *port, const char *proto, const char *auth,
|
||||
const char *auth_opt, const char *ssl_key,
|
||||
const char *ssl_cert, const char *ssl_ca,
|
||||
const char *ssl_version, const char *ssl_depth);
|
||||
|
@ -204,7 +204,7 @@ extern void serviceAddRouterOption(SERVICE *, char *);
|
||||
extern void serviceClearRouterOptions(SERVICE *);
|
||||
extern int serviceStart(SERVICE *);
|
||||
extern int serviceStartAll();
|
||||
extern void serviceStartProtocol(SERVICE *, char *, int);
|
||||
extern bool serviceListen(SERVICE *service, unsigned short port);
|
||||
extern int serviceStop(SERVICE *);
|
||||
extern int serviceRestart(SERVICE *);
|
||||
extern int serviceSetUser(SERVICE *, char *, char *);
|
||||
|
@ -98,7 +98,7 @@ bool config_has_duplicate_sections(const char* config, DUPLICATE_CONTEXT* contex
|
||||
int create_new_service(CONFIG_CONTEXT *obj);
|
||||
int create_new_server(CONFIG_CONTEXT *obj);
|
||||
int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE* monitorhash);
|
||||
int create_new_listener(CONFIG_CONTEXT *obj, bool startnow);
|
||||
int create_new_listener(CONFIG_CONTEXT *obj);
|
||||
int create_new_filter(CONFIG_CONTEXT *obj);
|
||||
int configure_new_service(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj);
|
||||
|
||||
@ -815,7 +815,7 @@ process_config_context(CONFIG_CONTEXT *context)
|
||||
}
|
||||
else if (!strcmp(type, "listener"))
|
||||
{
|
||||
error_count += create_new_listener(obj, false);
|
||||
error_count += create_new_listener(obj);
|
||||
}
|
||||
else if (!strcmp(type, "monitor"))
|
||||
{
|
||||
@ -3094,7 +3094,7 @@ int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE*
|
||||
* @param startnow If true, start the listener now
|
||||
* @return Number of errors
|
||||
*/
|
||||
int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
|
||||
int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
{
|
||||
int error_count = 0;
|
||||
char *service_name = config_get_value(obj->parameters, "service");
|
||||
@ -3123,10 +3123,6 @@ int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
|
||||
{
|
||||
serviceAddProtocol(service, obj->object, protocol, socket, 0,
|
||||
authenticator, authenticator_options, ssl_info);
|
||||
if (startnow)
|
||||
{
|
||||
serviceStartProtocol(service, protocol, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3144,10 +3140,6 @@ int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
|
||||
{
|
||||
serviceAddProtocol(service, obj->object, protocol, address, atoi(port),
|
||||
authenticator, authenticator_options, ssl_info);
|
||||
if (startnow)
|
||||
{
|
||||
serviceStartProtocol(service, protocol, atoi(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
#include <maxscale/atomic.h>
|
||||
#include <maxscale/config_runtime.h>
|
||||
#include <maxscale/gwdirs.h>
|
||||
@ -190,17 +191,16 @@ bool runtime_destroy_server(SERVER *server)
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert,
|
||||
const char *ca, const char *version, const char *depth)
|
||||
static SSL_LISTENER* create_ssl(const char *name, const char *key, const char *cert,
|
||||
const char *ca, const char *version, const char *depth)
|
||||
{
|
||||
spinlock_acquire(&crt_lock);
|
||||
bool rval = false;
|
||||
SSL_LISTENER *rval = NULL;
|
||||
CONFIG_CONTEXT *obj = config_context_create(name);
|
||||
|
||||
if (key && cert && ca)
|
||||
if (obj)
|
||||
{
|
||||
CONFIG_CONTEXT *obj = config_context_create(server->unique_name);
|
||||
|
||||
if (obj && config_add_param(obj, "ssl_key", key) &&
|
||||
if (config_add_param(obj, "ssl", "required") &&
|
||||
config_add_param(obj, "ssl_key", key) &&
|
||||
config_add_param(obj, "ssl_cert", cert) &&
|
||||
config_add_param(obj, "ssl_ca_cert", ca) &&
|
||||
(!version || config_add_param(obj, "ssl_version", version)) &&
|
||||
@ -211,27 +211,44 @@ bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert
|
||||
|
||||
if (err == 0 && ssl && listener_init_SSL(ssl) == 0)
|
||||
{
|
||||
/** TODO: Properly discard old SSL configurations
|
||||
*
|
||||
* This could cause the loss of a pointer if two update
|
||||
* operations are done at the same time.*/
|
||||
ssl->next = server->server_ssl;
|
||||
|
||||
/** Sync to prevent reads on partially initialized server_ssl */
|
||||
atomic_synchronize();
|
||||
|
||||
server->server_ssl = ssl;
|
||||
if (server_serialize(server))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
rval = ssl;
|
||||
}
|
||||
}
|
||||
|
||||
config_context_free(obj);
|
||||
}
|
||||
|
||||
spinlock_release(&crt_lock);
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert,
|
||||
const char *ca, const char *version, const char *depth)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (key && cert && ca)
|
||||
{
|
||||
spinlock_acquire(&crt_lock);
|
||||
SSL_LISTENER *ssl = create_ssl(server->unique_name, key, cert, ca, version, depth);
|
||||
|
||||
if (ssl)
|
||||
{
|
||||
/** TODO: Properly discard old SSL configurations.This could cause the
|
||||
* loss of a pointer if two update operations are done at the same time.*/
|
||||
ssl->next = server->server_ssl;
|
||||
|
||||
/** Sync to prevent reads on partially initialized server_ssl */
|
||||
atomic_synchronize();
|
||||
server->server_ssl = ssl;
|
||||
|
||||
if (server_serialize(server))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
}
|
||||
spinlock_release(&crt_lock);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -341,3 +358,73 @@ bool runtime_alter_monitor(MONITOR *monitor, char *key, char *value)
|
||||
spinlock_release(&crt_lock);
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool runtime_create_listener(SERVICE *service, const char *name, const char *addr,
|
||||
const char *port, const char *proto, const char *auth,
|
||||
const char *auth_opt, const char *ssl_key,
|
||||
const char *ssl_cert, const char *ssl_ca,
|
||||
const char *ssl_version, const char *ssl_depth)
|
||||
{
|
||||
SSL_LISTENER *ssl = NULL;
|
||||
bool rval = true;
|
||||
|
||||
if (addr == NULL || strcasecmp(addr, "default") == 0)
|
||||
{
|
||||
addr = "0.0.0.0";
|
||||
}
|
||||
if (port == NULL || strcasecmp(port, "default") == 0)
|
||||
{
|
||||
port = "3306";
|
||||
}
|
||||
if (proto == NULL || strcasecmp(proto, "default") == 0)
|
||||
{
|
||||
proto = "MySQLClient";
|
||||
}
|
||||
|
||||
if (auth && strcasecmp(auth, "default") == 0)
|
||||
{
|
||||
/** Set auth to NULL so the protocol default authenticator is used */
|
||||
auth = NULL;
|
||||
}
|
||||
|
||||
if (auth_opt && strcasecmp(auth_opt, "default") == 0)
|
||||
{
|
||||
/** Don't pass options to the authenticator */
|
||||
auth_opt = NULL;
|
||||
}
|
||||
|
||||
unsigned short u_port = atoi(port);
|
||||
|
||||
if (ssl_key && ssl_cert && ssl_ca)
|
||||
{
|
||||
ssl = create_ssl(name, ssl_key, ssl_cert, ssl_ca, ssl_version, ssl_depth);
|
||||
|
||||
if (ssl == NULL)
|
||||
{
|
||||
MXS_ERROR("SSL initialization for listener '%s' failed.", name);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
|
||||
spinlock_acquire(&crt_lock);
|
||||
|
||||
if (rval)
|
||||
{
|
||||
const char *print_addr = addr ? addr : "0.0.0.0";
|
||||
|
||||
if (serviceAddProtocol(service, name, proto, addr, u_port, auth, auth_opt, ssl) &&
|
||||
serviceListen(service, u_port))
|
||||
{
|
||||
MXS_NOTICE("Listener '%s' at %s:%s for service '%s' created",
|
||||
name, print_addr, port, service->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Failed to start listener '%s' at %s:%s.", name, print_addr, port);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
|
||||
spinlock_release(&crt_lock);
|
||||
return rval;
|
||||
}
|
||||
|
@ -506,25 +506,25 @@ serviceStart(SERVICE *service)
|
||||
* Start an individual listener
|
||||
*
|
||||
* @param service The service to start the listener for
|
||||
* @param protocol The name of the protocol
|
||||
* @param port The port number
|
||||
*/
|
||||
void
|
||||
serviceStartProtocol(SERVICE *service, char *protocol, int port)
|
||||
bool serviceListen(SERVICE *service, unsigned short port)
|
||||
{
|
||||
SERV_LISTENER *ptr;
|
||||
|
||||
ptr = service->ports;
|
||||
while (ptr)
|
||||
bool rval = false;
|
||||
for (SERV_LISTENER *ptr = service->ports; ptr; ptr = ptr->next)
|
||||
{
|
||||
if (strcmp(ptr->protocol, protocol) == 0 && ptr->port == port)
|
||||
if (ptr->port == port)
|
||||
{
|
||||
serviceStartPort(service, ptr);
|
||||
if (serviceStartPort(service, ptr))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start all the services
|
||||
|
Loading…
x
Reference in New Issue
Block a user