This commit is contained in:
VilhoRaatikka
2014-02-07 11:11:47 +02:00
29 changed files with 329 additions and 125 deletions

3
server/core/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
maxscale
depend.mk

View File

@ -63,7 +63,7 @@ HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \
../include/session.h ../include/spinlock.h ../include/thread.h \
../include/modules.h ../include/poll.h ../include/config.h \
../include/users.h ../include/hashtable.h ../include/gwbitmask.h \
../include/adminusers.h
../include/adminusers.h ../include/version.h ../include/maxscale.h
OBJ=$(SRCS:.c=.o)
@ -101,6 +101,10 @@ maxpasswd: $(POBJS)
.c.o:
$(CC) $(CFLAGS) $< -o $@
../include/version.h: ../../VERSION
echo '#define MAXSCALE_VERSION "'`cat ../../VERSION`'"' > ../include/version.h
clean:
rm -f $(OBJ) maxscale
- rm *.so
@ -108,7 +112,7 @@ clean:
tags:
ctags $(SRCS) $(HDRS)
depend:
depend: ../include/version.h
@rm -f depend.mk
cc -M $(CFLAGS) $(SRCS) > depend.mk

View File

@ -22,10 +22,11 @@
* @verbatim
* Revision History
*
* Date Who Description
* 21/06/13 Mark Riddoch Initial implementation
* 08/07/13 Mark Riddoch Addition on monitor module support
* 23/07/13 Mark Riddoch Addition on default monitor password
* Date Who Description
* 21/06/13 Mark Riddoch Initial implementation
* 08/07/13 Mark Riddoch Addition on monitor module support
* 23/07/13 Mark Riddoch Addition on default monitor password
* 06/02/14 Massimiliano Pinto Added support for enable/disable root user in services
*
* @endverbatim
*/
@ -197,6 +198,12 @@ int error_count = 0;
config_get_value(obj->parameters, "user");
char *auth =
config_get_value(obj->parameters, "passwd");
char *enable_root_user =
config_get_value(obj->parameters, "enable_root_user");
if (enable_root_user)
serviceEnableRootUser(obj->element, atoi(enable_root_user));
if (!auth)
auth = config_get_value(obj->parameters, "auth");
@ -333,11 +340,13 @@ int error_count = 0;
else if (!strcmp(type, "listener"))
{
char *service;
char *address;
char *port;
char *protocol;
service = config_get_value(obj->parameters, "service");
port = config_get_value(obj->parameters, "port");
address = config_get_value(obj->parameters, "address");
protocol = config_get_value(obj->parameters, "protocol");
if (service && port && protocol)
@ -349,6 +358,7 @@ int error_count = 0;
{
serviceAddProtocol(ptr->element,
protocol,
address,
atoi(port));
}
else
@ -587,21 +597,31 @@ SERVER *server;
{
char *user;
char *auth;
char *enable_root_user;
enable_root_user = config_get_value(obj->parameters, "enable_root_user");
user = config_get_value(obj->parameters,
"user");
auth = config_get_value(obj->parameters,
"passwd");
if (user && auth)
if (user && auth) {
service_update(service, router,
user,
auth);
if (enable_root_user)
serviceEnableRootUser(service, atoi(enable_root_user));
}
obj->element = service;
}
else
{
char *user;
char *auth;
char *enable_root_user;
enable_root_user = config_get_value(obj->parameters, "enable_root_user");
user = config_get_value(obj->parameters,
"user");
@ -615,6 +635,8 @@ SERVER *server;
serviceSetUser(obj->element,
user,
auth);
if (enable_root_user)
serviceEnableRootUser(service, atoi(enable_root_user));
}
}
}
@ -739,8 +761,10 @@ SERVER *server;
char *service;
char *port;
char *protocol;
char *address;
service = config_get_value(obj->parameters, "service");
address = config_get_value(obj->parameters, "address");
port = config_get_value(obj->parameters, "port");
protocol = config_get_value(obj->parameters, "protocol");
@ -758,6 +782,7 @@ SERVER *server;
{
serviceAddProtocol(ptr->element,
protocol,
address,
atoi(port));
serviceStartProtocol(ptr->element,
protocol,
@ -837,17 +862,19 @@ int i;
obj = context;
while (obj)
{
type = config_get_value(obj->parameters, "type");
if (!strcmp(type, "service"))
param_set = service_params;
else if (!strcmp(type, "server"))
param_set = server_params;
else if (!strcmp(type, "listener"))
param_set = listener_params;
else if (!strcmp(type, "monitor"))
param_set = monitor_params;
else
param_set = NULL;
param_set = NULL;
if (obj->parameters &&
(type = config_get_value(obj->parameters, "type")))
{
if (!strcmp(type, "service"))
param_set = service_params;
else if (!strcmp(type, "server"))
param_set = server_params;
else if (!strcmp(type, "listener"))
param_set = listener_params;
else if (!strcmp(type, "monitor"))
param_set = monitor_params;
}
if (param_set != NULL)
{
params = obj->parameters;

View File

@ -25,6 +25,7 @@
* Date Who Description
* 24/06/2013 Massimiliano Pinto Initial implementation
* 08/08/2013 Massimiliano Pinto Fixed bug for invalid memory access in row[1]+1 when row[1] is ""
* 06/02/2014 Massimiliano Pinto Mysql user root selected based on configuration flag
*
* @endverbatim
*/
@ -39,6 +40,9 @@
#include <log_manager.h>
#include <secrets.h>
#define USERS_QUERY_NO_ROOT " WHERE user NOT IN ('root')"
#define LOAD_MYSQL_USERS_QUERY "SELECT user, password FROM mysql.user"
extern int lm_enabled_logfiles_bitmask;
static int getUsers(SERVICE *service, struct users *users);
@ -101,7 +105,13 @@ getUsers(SERVICE *service, struct users *users)
char *dpwd;
int total_users = 0;
SERVER *server;
char *users_query;
if(service->enable_root)
users_query = LOAD_MYSQL_USERS_QUERY;
else
users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT;
serviceGetUser(service, &service_user, &service_passwd);
/** multi-thread environment requires that thread init succeeds. */
if (mysql_thread_init()) {
@ -159,7 +169,7 @@ getUsers(SERVICE *service, struct users *users)
return -1;
}
if (mysql_query(con, "SELECT user, password FROM mysql.user")) {
if (mysql_query(con, users_query)) {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Loading users for service %s encountered "

View File

@ -99,7 +99,7 @@ DCB * dcb_alloc(
{
DCB *rval;
if ((rval = calloc(1, sizeof(DCB))) == NULL)
if ((rval = calloc(1, sizeof(DCB))) == NULL)
{
return NULL;
}
@ -122,6 +122,7 @@ if ((rval = calloc(1, sizeof(DCB))) == NULL)
memset(&rval->stats, 0, sizeof(DCBSTATS)); // Zero the statistics
rval->state = DCB_STATE_ALLOC;
bitmask_init(&rval->memdata.bitmask);
rval->next = NULL;
spinlock_acquire(&dcbspin);
if (allDCBs == NULL)
@ -137,6 +138,26 @@ if ((rval = calloc(1, sizeof(DCB))) == NULL)
return rval;
}
/**
* Free a DCB that has not been associated with a decriptor.
*
* @param dcb The DCB to free
*/
void
dcb_free(DCB *dcb)
{
if (dcb->fd == -1)
dcb_final_free(dcb);
else
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Attempt to free a DCB via dcb_fee "
"that has been associated with a descriptor.")));
}
}
/**
* Add the DCB to the end of zombies list.
*

View File

@ -34,6 +34,7 @@
* 28/06/13 Vilho Raatikka Added necessary headers, example functions and
* calls to log manager and to query classifier.
* Put example code behind SS_DEBUG macros.
* 05/02/14 Mark Riddoch Addition of version string
*
* @endverbatim
*/
@ -53,6 +54,8 @@
#include <stdlib.h>
#include <mysql.h>
#include <monitor.h>
#include <version.h>
#include <maxscale.h>
#include <sys/stat.h>
#include <sys/types.h>
@ -313,7 +316,7 @@ static bool file_write_header(
*t = time(NULL);
*tm = *localtime(t);
header_buf1 = "\n\nSkySQL MaxScale\t";
header_buf1 = "\n\nSkySQL MaxScale " MAXSCALE_VERSION "\t";
header_buf2 = strdup(asctime(tm));
if (header_buf2 == NULL) {
@ -865,7 +868,7 @@ static void usage(void)
*/
int main(int argc, char **argv)
{
int rc = 0;
int rc = MAXSCALE_SHUTDOWN;
int l;
int i;
int n;
@ -914,7 +917,7 @@ int main(int argc, char **argv)
{
char* fprerr = "Failed to register exit functions for MaxScale";
print_log_n_stderr(false, true, NULL, fprerr, 0);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
}
@ -937,7 +940,23 @@ int main(int argc, char **argv)
*/
if (optarg[0] != '-')
{
get_expanded_pathname(&home_dir, optarg, NULL);
struct stat sb;
if (stat(optarg, &sb) != -1
&& (! S_ISDIR(sb.st_mode)))
{
char* logerr = "Home directory argument "
"identifier \'-c\' was specified but "
"the argument didn't specify a valid "
"a directory.";
print_log_n_stderr(true, true, logerr, logerr, 0);
usage();
succp = false;
}
else
{
get_expanded_pathname(&home_dir, optarg, NULL);
}
}
if (home_dir != NULL)
@ -992,7 +1011,7 @@ int main(int argc, char **argv)
if (!succp)
{
rc = 1;
rc = MAXSCALE_BADARG;
goto return_main;
}
}
@ -1024,7 +1043,7 @@ int main(int argc, char **argv)
eno = errno;
errno = 0;
print_log_n_stderr(true, true, fprerr, fprerr, eno);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
r = sigdelset(&sigset, SIGHUP);
@ -1036,7 +1055,7 @@ int main(int argc, char **argv)
eno = errno;
errno = 0;
print_log_n_stderr(true, true, fprerr, logerr, eno);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
r = sigdelset(&sigset, SIGTERM);
@ -1048,7 +1067,7 @@ int main(int argc, char **argv)
eno = errno;
errno = 0;
print_log_n_stderr(true, true, fprerr, logerr, eno);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
r = sigprocmask(SIG_SETMASK, &sigset, NULL);
@ -1059,7 +1078,7 @@ int main(int argc, char **argv)
eno = errno;
errno = 0;
print_log_n_stderr(true, true, fprerr, logerr, eno);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
gw_daemonize();
@ -1101,7 +1120,7 @@ int main(int argc, char **argv)
errno = 0;
print_log_n_stderr(true, !daemon_mode, logerr, fprerr, eno);
free(logerr);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
}
@ -1112,7 +1131,7 @@ int main(int argc, char **argv)
char* logerr = "Failed to initialise signal mask for MaxScale. "
"Exiting.";
print_log_n_stderr(true, true, logerr, logerr, eno);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
l = atexit(libmysqld_done);
@ -1123,7 +1142,7 @@ int main(int argc, char **argv)
char* logerr = "Failed to register exit function libmysql_done "
"for MaxScale. Exiting.";
print_log_n_stderr(true, true, logerr, fprerr, 0);
rc = 1;
rc = MAXSCALE_INTERNALERROR;
goto return_main;
}
/*<
@ -1136,7 +1155,7 @@ int main(int argc, char **argv)
if (!resolve_maxscale_homedir(&home_dir))
{
ss_dassert(home_dir == NULL);
rc = 1;
rc = MAXSCALE_HOMELESS;
goto return_main;
}
sprintf(mysql_home, "%s/mysql", home_dir);
@ -1174,7 +1193,7 @@ int main(int argc, char **argv)
if (!resolve_maxscale_conf_fname(&cnf_file_path, home_dir, cnf_file_arg))
{
ss_dassert(cnf_file_path == NULL);
rc = 1;
rc = MAXSCALE_BADCONFIG;
goto return_main;
}
@ -1274,7 +1293,7 @@ int main(int argc, char **argv)
mysql_error(NULL),
__FILE__,
__LINE__)));
rc = 1;
rc = MAXSCALE_NOLIBRARY;
goto return_main;
}
libmysqld_started = TRUE;
@ -1289,12 +1308,13 @@ int main(int argc, char **argv)
"Error : Failed to load MaxScale configuration file %s. "
"Exiting.",
cnf_file_path)));
rc = 1;
rc = MAXSCALE_BADCONFIG;
goto return_main;
}
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"SkySQL MaxScale (C) SkySQL Ab 2013")));
"SkySQL MaxScale %s (C) SkySQL Ab 2013,2014",
MAXSCALE_VERSION)));
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"MaxScale is running in process %i",
@ -1310,7 +1330,7 @@ int main(int argc, char **argv)
{
char* logerr = "Failed to start any MaxScale services. Exiting.";
print_log_n_stderr(true, !daemon_mode, logerr, logerr, 0);
rc = 1;
rc = MAXSCALE_NOSERVICES;
goto return_main;
}
/*<
@ -1367,7 +1387,7 @@ int main(int argc, char **argv)
"MaxScale shutdown completed.")));
return_main:
return 0;
return rc;
} /*< End of main */
/*<

View File

@ -32,6 +32,7 @@
* 01-07-2013 Massimiliano Pinto Removed session->backends
* from gw_read_gwbuff()
* 25-09-2013 Massimiliano Pinto setipaddress uses getaddrinfo
* 06-02-2014 Mark Riddoch Added parse_bindconfig
*
*@endverbatim
*/
@ -40,9 +41,14 @@
#include <dcb.h>
#include <session.h>
#include <skygw_utils.h>
#include <log_manager.h>
SPINLOCK tmplock = SPINLOCK_INIT;
/**
extern int lm_enabled_logfiles_bitmask;
/*
* Set IP address in socket structure in_addr
*
* @param a Pointer to a struct in_addr into which the address is written
@ -184,3 +190,64 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) {
return 0;
}
/**
* Parse the bind config data. This is passed in a string as address:port.
*
* The address may be either a . seperated IP address or a hostname to
* lookup. The address 0.0.0.0 is the wildcard address for SOCKADR_ANY.
* The ':' and port may be omitted, in which case the default port is
* used.
*
* @param config The bind address and port seperated by a ':'
* @param def_port The default port to use
* @param addr The sockaddr_in in which the data is written
* @return 0 on failure
*/
int
parse_bindconfig(char *config, unsigned short def_port, struct sockaddr_in *addr)
{
char *port, buf[1024];
short pnum;
struct hostent *hp;
strncpy(buf, config, 1024);
port = strrchr(buf, ':');
if (port)
{
*port = 0;
port++;
pnum = atoi(port);
}
else
{
pnum = def_port;
}
if (!strcmp(buf, "0.0.0.0"))
{
addr->sin_addr.s_addr = htonl(INADDR_ANY);
}
else
{
if (!inet_aton(buf, &addr->sin_addr))
{
if ((hp = gethostbyname(buf)) != NULL)
{
bcopy(hp->h_addr, &(addr->sin_addr.s_addr), hp->h_length);
}
else
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Failed to lookup host '%s'. ",
buf)));
return 0;
}
}
}
addr->sin_family = AF_INET;
addr->sin_port = htons(pnum);
return 1;
}

View File

@ -25,6 +25,7 @@
* Date Who Description
* 18/06/13 Mark Riddoch Initial implementation
* 24/06/13 Massimiliano Pinto Added: Loading users from mysql backend in serviceStart
* 06/02/14 Massimiliano Pinto Added: serviceEnableRootUser routine
* @endverbatim
*/
#include <stdio.h>
@ -78,6 +79,7 @@ SERVICE *service;
service->credentials.name = NULL;
service->credentials.authdata = NULL;
service->users = users_alloc();
service->enable_root = 0;
service->routerOptions = NULL;
service->databases = NULL;
spinlock_init(&service->spin);
@ -121,7 +123,7 @@ GWPROTOCOL *funcs;
if ((funcs =
(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL)
{
free(port->listener);
dcb_free(port->listener);
port->listener = NULL;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
@ -133,7 +135,10 @@ GWPROTOCOL *funcs;
}
memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
port->listener->session = NULL;
sprintf(config_bind, "0.0.0.0:%d", port->port);
if (port->address)
sprintf(config_bind, "%s:%d", port->address, port->port);
else
sprintf(config_bind, "0.0.0.0:%d", port->port);
if (port->listener->func.listen(port->listener, config_bind)) {
port->listener->session = session_alloc(service, port->listener);
@ -333,11 +338,12 @@ SERVICE *ptr;
*
* @param service The service
* @param protocol The name of the protocol module
* @param address The address to listen with
* @param port The port to listen on
* @return TRUE if the protocol/port could be added
*/
int
serviceAddProtocol(SERVICE *service, char *protocol, unsigned short port)
serviceAddProtocol(SERVICE *service, char *protocol, char *address, unsigned short port)
{
SERV_PROTOCOL *proto;
@ -346,6 +352,10 @@ SERV_PROTOCOL *proto;
return 0;
}
proto->protocol = strdup(protocol);
if (address)
proto->address = strdup(address);
else
proto->address = NULL;
proto->port = port;
spinlock_acquire(&service->spin);
proto->next = service->ports;
@ -356,7 +366,7 @@ SERV_PROTOCOL *proto;
}
/**
* Check if a protocol/port pair si part of the service
* Check if a protocol/port pair is part of the service
*
* @param service The service
* @param protocol The name of the protocol module
@ -496,7 +506,7 @@ serviceSetUser(SERVICE *service, char *user, char *auth)
* @param service The service we are setting the data for
* @param user The user name to use for connections
* @param auth The authentication data we need, e.g. MySQL SHA1 password
* @return 0 on failure
* @return 0 on failure
*/
int
serviceGetUser(SERVICE *service, char **user, char **auth)
@ -508,6 +518,26 @@ serviceGetUser(SERVICE *service, char **user, char **auth)
return 1;
}
/**
* Enable/Disable root user for this service
* associated with this service.
*
* @param service The service we are setting the data for
* @param action 1 for root enable, 0 for disable access
* @return 0 on failure
*/
int
serviceEnableRootUser(SERVICE *service, int action)
{
if (action != 0 && action != 1)
return 0;
service->enable_root = action;
return 1;
}
/**
* Return a named service
*