Пример #1
0
/**
 * Handler for the EPOLLIN event when the DCB refers to the listening
 * socket for the protocol.
 *
 * @param dcb	The descriptor control block
 * @return The number of new connections created
 */
static int
telnetd_accept(DCB *dcb)
{
int	n_connect = 0;

	while (1)
	{
		int			so;
		struct sockaddr_in	addr;
		socklen_t		addrlen = sizeof(struct sockaddr);
		DCB			*client_dcb;
                TELNETD*                telnetd_pr = NULL;
                dcb_state_t             old_state = DCB_STATE_UNDEFINED;
                bool                    succp = FALSE;

                so = accept(dcb->fd, (struct sockaddr *)&addr, &addrlen);
                
		if (so == -1)
			return n_connect;
		else
		{
			atomic_add(&dcb->stats.n_accepts, 1);
                        client_dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);

			if (client_dcb == NULL)

			{
				return n_connect;
			}
                        client_dcb->fd = so;
			client_dcb->remote = strdup(inet_ntoa(addr.sin_addr));
			memcpy(&client_dcb->func, &MyObject, sizeof(GWPROTOCOL));
			client_dcb->session =
                                session_alloc(dcb->session->service, client_dcb);
                        telnetd_pr = (TELNETD *)malloc(sizeof(TELNETD));
                        client_dcb->protocol = (void *)telnetd_pr;

                        if (telnetd_pr == NULL)
                        {
                                dcb_add_to_zombieslist(client_dcb);
				return n_connect;
			}

			if (poll_add_dcb(client_dcb) == -1)
			{
                                dcb_add_to_zombieslist(dcb);
				return n_connect;
			}
			n_connect++;
			telnetd_pr->state = TELNETD_STATE_LOGIN;
			telnetd_pr->username = NULL;
			dcb_printf(client_dcb, "MaxScale login: ");
		}
	}
	return n_connect;
}
Пример #2
0
static int
test1()
{
DCB     *dcb;
int     result;
	int eno = 0;

        /* Poll tests */  
        ss_dfprintf(stderr,
                    "testpoll : Initialise the polling system."); 
        init_test_env(NULL);
        poll_init();
        ss_dfprintf(stderr, "\t..done\nAdd a DCB");
        dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);

		if(dcb == NULL){
			ss_dfprintf(stderr, "\nError on function call: dcb_alloc() returned NULL.\n");
			return 1;
		}

        dcb->fd = socket(AF_UNIX, SOCK_STREAM, 0);

        if(dcb->fd < 0){
                        char errbuf[STRERROR_BUFLEN];
			ss_dfprintf(stderr, "\nError on function call: socket() returned %d: %s\n",errno,strerror_r(errno,errbuf,sizeof(errbuf)));
				    return 1;
		}


        if((eno = poll_add_dcb(dcb)) != 0){
			ss_dfprintf(stderr, "\nError on function call: poll_add_dcb() returned %d.\n",eno);
				    return 1;
		}

        if((eno = poll_remove_dcb(dcb)) != 0){
			ss_dfprintf(stderr, "\nError on function call: poll_remove_dcb() returned %d.\n",eno);
				    return 1;
		}

        if((eno = poll_add_dcb(dcb)) != 0){
			ss_dfprintf(stderr, "\nError on function call: poll_add_dcb() returned %d.\n",eno);
				    return 1;
		}

        ss_dfprintf(stderr, "\t..done\nStart wait for events.");
        sleep(10);
        poll_shutdown();
        ss_dfprintf(stderr, "\t..done\nTidy up.");
        dcb_close(dcb);
        ss_dfprintf(stderr, "\t..done\n");
		
	return 0;
        
}
Пример #3
0
/**
 * Handler for the EPOLLIN event when the DCB refers to the listening
 * socket for the protocol.
 *
 * @param dcb   The descriptor control block
 */
static int httpd_accept(DCB *dcb)
{
    int n_connect = 0;

    while (1)
    {
        int so = -1;
        struct sockaddr_in addr;
        socklen_t addrlen;
        DCB *client = NULL;
        HTTPD_session *client_data = NULL;

        if ((so = accept(dcb->fd, (struct sockaddr *)&addr, &addrlen)) == -1)
        {
            return n_connect;
        }
        else
        {
            atomic_add(&dcb->stats.n_accepts, 1);

            if ((client = dcb_alloc(DCB_ROLE_REQUEST_HANDLER)))
            {
                client->listen_ssl = dcb->listen_ssl;
                client->fd = so;
                client->remote = strdup(inet_ntoa(addr.sin_addr));
                memcpy(&client->func, &MyObject, sizeof(GWPROTOCOL));

                /* create the session data for HTTPD */
                client_data = (HTTPD_session *)calloc(1, sizeof(HTTPD_session));
                client->data = client_data;

                client->session = session_alloc(dcb->session->service, client);

                if (NULL == client->session || poll_add_dcb(client) == -1)
                {
                    close(so);
                    dcb_close(client);
                    return n_connect;
                }
                n_connect++;
            }
            else
            {
                close(so);
            }
        }
    }

    return n_connect;
}
Пример #4
0
/**
 * test1	Allocate a dcb and do lots of other things
 *
  */
static int
test1()
{
DCB   *dcb, *extra, *clone;
int     size = 100;
int     bite1 = 35;
int     bite2 = 60;
int     bite3 = 10;
int     buflen;

        /* Single buffer tests */
        ss_dfprintf(stderr,
                    "testdcb : creating buffer with type DCB_ROLE_SERVICE_LISTENER"); 
        dcb = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);
        printDCB(dcb);
        ss_info_dassert(dcb_isvalid(dcb), "New DCB must be valid");
        ss_dfprintf(stderr, "\t..done\nAllocated dcb.");
        clone = dcb_clone(dcb);
        ss_dfprintf(stderr, "\t..done\nCloned dcb");
        printAllDCBs();
        ss_info_dassert(true, "Something is true");
        ss_dfprintf(stderr, "\t..done\n");
        dcb_close(dcb);
        ss_dfprintf(stderr, "Freed original dcb");
        ss_info_dassert(!dcb_isvalid(dcb), "Freed DCB must not be valid");
        ss_dfprintf(stderr, "\t..done\nMake clone DCB a zombie");
        clone->state = DCB_STATE_NOPOLLING;
        dcb_close(clone);
        ss_info_dassert(dcb_get_zombies() == clone, "Clone DCB must be start of zombie list now");
        ss_dfprintf(stderr, "\t..done\nProcess the zombies list");
        dcb_process_zombies(0);
        ss_dfprintf(stderr, "\t..done\nCheck clone no longer valid");
        ss_info_dassert(!dcb_isvalid(clone), "After zombie processing, clone DCB must not be valid");
        ss_dfprintf(stderr, "\t..done\n");
		
	return 0;
}
Пример #5
0
/**
 * Start an individual port/protocol pair
 *
 * @param service	The service
 * @param port		The port to start
 * @return		The number of listeners started
 */
static int
serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
{
int		listeners = 0;
char		config_bind[40];
GWPROTOCOL	*funcs;

        port->listener = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);

        if (port->listener == NULL)
	{
		return 0;
	}
	if (strcmp(port->protocol, "MySQLClient") == 0) {
		int loaded;
		/* Allocate specific data for MySQL users */
		service->users = mysql_users_alloc();
		loaded = load_mysql_users(service);
		/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
 		 * This way MaxScale could try reloading users' just after startup
 		 */

		service->rate_limit.last=time(NULL) - USERS_REFRESH_TIME;
		service->rate_limit.nloads=1;

		LOGIF(LM, (skygw_log_write(
                        LOGFILE_MESSAGE,
                        "Loaded %d MySQL Users.",
                        loaded)));
	} else {
		/* Generic users table */
		service->users = users_alloc();
	}

	if ((funcs =
             (GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL)
	{
		dcb_free(port->listener);
		port->listener = NULL;
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to load protocol module %s. Listener "
                        "for service %s not started.",
			port->protocol,
                        service->name)));
		return 0;
	}
	memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
	port->listener->session = NULL;
	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);

                if (port->listener->session != NULL) {
                        port->listener->session->state = SESSION_STATE_LISTENER;
                        listeners += 1;
                } else {
                        dcb_close(port->listener);
                }
        } else {
                dcb_close(port->listener);
                
                LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to start to listen port %d for %s %s.",
			port->port,
                        port->protocol,
                        service->name)));
        }
	return listeners;
}
Пример #6
0
/**
 * Start an individual port/protocol pair
 *
 * @param service	The service
 * @param port		The port to start
 * @return		The number of listeners started
 */
static int
serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
{
int		listeners = 0;
char		config_bind[40];
GWPROTOCOL	*funcs;

        port->listener = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);

        if (port->listener == NULL)
	{
		return 0;
	}
	if (strcmp(port->protocol, "MySQLClient") == 0) {
		int loaded = load_mysql_users(service);
		LOGIF(LM, (skygw_log_write(
                        LOGFILE_MESSAGE,
                        "Loaded %d MySQL Users.",
                        loaded)));
	}

	if ((funcs =
             (GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL)
	{
		dcb_free(port->listener);
		port->listener = NULL;
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to load protocol module %s. Listener "
                        "for service %s not started.",
			port->protocol,
                        service->name)));
		return 0;
	}
	memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
	port->listener->session = NULL;
	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);
                
                if (port->listener->session != NULL) {
                        port->listener->session->state = SESSION_STATE_LISTENER;
                        listeners += 1;
                } else {
                        dcb_close(port->listener);
                }
        } else {
                dcb_close(port->listener);
                
                LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to start to listen port %d for %s %s.",
			port->port,
                        port->protocol,
                        service->name)));
        }
	return listeners;
}
Пример #7
0
/**
 * Start an individual port/protocol pair
 *
 * @param service	The service
 * @param port		The port to start
 * @return		The number of listeners started
 */
static int
serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
{
int		listeners = 0;
char		config_bind[40];
GWPROTOCOL	*funcs;

        port->listener = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);

        if (port->listener == NULL)
	{
		LOGIF(LE, (skygw_log_write_flush(
			LOGFILE_ERROR,
			"Error : Failed to create listener for service %s.",
			service->name)));
		goto retblock;
	}
	
	if (strcmp(port->protocol, "MySQLClient") == 0) {
		int loaded;

		if (service->users == NULL) {
			/*
			 * Allocate specific data for MySQL users
			 * including hosts and db names
			 */
			service->users = mysql_users_alloc();
	
			if ((loaded = load_mysql_users(service)) < 0)
			{
				LOGIF(LE, (skygw_log_write_flush(
					LOGFILE_ERROR,
					"Error : Unable to load users from %s:%d for "
					"service %s.",
					(port->address == NULL ? "0.0.0.0" : port->address),
					port->port,
					service->name)));
				
				{
					/* Try loading authentication data from file cache */
					char	*ptr, path[4097];
					strcpy(path, "/usr/local/mariadb-maxscale");
					if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
					{
						strncpy(path, ptr, 4096);
					}
					strncat(path, "/", 4096);
					strncat(path, service->name, 4096);
					strncat(path, "/.cache/dbusers", 4096);
					loaded = dbusers_load(service->users, path);
					if (loaded != -1)
					{
						LOGIF(LE, (skygw_log_write_flush(
							LOGFILE_ERROR,
							"Using cached credential information.")));
					}
				}
				if (loaded == -1)
				{
					hashtable_free(service->users->data);
					free(service->users);
					dcb_free(port->listener);
					port->listener = NULL;
					goto retblock;
				}
			}
			else
			{
				/* Save authentication data to file cache */
				char	*ptr, path[4097];
                                int mkdir_rval = 0;
				strcpy(path, "/usr/local/mariadb-maxscale");
				if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
				{
					strncpy(path, ptr, 4096);
				}
				strncat(path, "/", 4096);
				strncat(path, service->name, 4096);
				if (access(path, R_OK) == -1)
                                {
					mkdir_rval = mkdir(path, 0777);
                                }

                                if(mkdir_rval)
                                {
                                    skygw_log_write(LOGFILE_ERROR,"Error : Failed to create directory '%s': [%d] %s",
                                                    path,
                                                    errno,
                                                    strerror(errno));
                                    mkdir_rval = 0;
                                }

				strncat(path, "/.cache", 4096);
				if (access(path, R_OK) == -1)
                                {
					mkdir_rval = mkdir(path, 0777);
                                }

                                if(mkdir_rval)
                                {
                                    skygw_log_write(LOGFILE_ERROR,"Error : Failed to create directory '%s': [%d] %s",
                                                    path,
                                                    errno,
                                                    strerror(errno));
                                    mkdir_rval = 0;
                                }
				strncat(path, "/dbusers", 4096);
				dbusers_save(service->users, path);
			}
			if (loaded == 0)
			{
				LOGIF(LE, (skygw_log_write_flush(
					LOGFILE_ERROR,
					"Service %s: failed to load any user "
					"information. Authentication will "
					"probably fail as a result.",
					service->name)));
			}

			/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
 			 * This way MaxScale could try reloading users' just after startup
 			 */
			service->rate_limit.last=time(NULL) - USERS_REFRESH_TIME;
			service->rate_limit.nloads=1;

			LOGIF(LM, (skygw_log_write(
				LOGFILE_MESSAGE,
				"Loaded %d MySQL Users for service [%s].",
				loaded, service->name)));
		}
	} 
	else 
	{
		if (service->users == NULL) {
			/* Generic users table */
			service->users = users_alloc();
		}
	}

	if ((funcs=(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) 
		== NULL)
	{
		if (service->users->data)
		{
			hashtable_free(service->users->data);
		}
		free(service->users);
		dcb_free(port->listener);
		port->listener = NULL;
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to load protocol module %s. Listener "
                        "for service %s not started.",
			port->protocol,
                        service->name)));
		goto retblock;
	}
	memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
	port->listener->session = NULL;
	
	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);

                if (port->listener->session != NULL) 
		{
                        port->listener->session->state = SESSION_STATE_LISTENER;
                        listeners += 1;
                } 
                else 
		{
			LOGIF(LE, (skygw_log_write_flush(
				LOGFILE_ERROR,
				"Error : Failed to create session to service %s.",
				service->name)));
			
			if (service->users->data)
			{
				hashtable_free(service->users->data);
			}
			free(service->users);
                        dcb_close(port->listener);
			port->listener = NULL;
			goto retblock;
                }
        } 
        else 
	{       
                LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to start to listen port %d for %s %s.",
			port->port,
                        port->protocol,
                        service->name)));
		if (service->users->data)
		{
			hashtable_free(service->users->data);
		}
		free(service->users);
		dcb_close(port->listener);
		port->listener = NULL;
        }
        
retblock:
	return listeners;
}
Пример #8
0
int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char *password) {
        struct sockaddr_in serv_addr;
        MYSQL_USER_HOST key;
        MYSQL_USER_HOST find_key;
	USERS *mysql_users;
	char ret_ip[200]="";
	char *fetch_data;
	char *db="";
	DCB *dcb;
	SERVICE *service;

	unsigned long fix_ipv4;

        dcb = dcb_alloc(DCB_ROLE_INTERNAL);

        if (dcb == NULL) {
                fprintf(stderr, "dcb_alloc() failed\n");
                return 1;
        }
        if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
                fprintf(stderr, "service_alloc() failed\n");
                dcb_free(dcb);
                return 1;
        }

	if (ipv4 > UINT_MAX) {
		fix_ipv4 = UINT_MAX;
	} else {
		fix_ipv4 = ipv4;
	}	
	
	mysql_users = mysql_users_alloc();
        /* prepare the user@host data struct */
	memset(&key, 0, sizeof(key));
	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	memcpy(&(serv_addr).sin_addr.s_addr, &fix_ipv4, sizeof(ipv4));

	key.user = username;
	memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
	key.resource = db;

	inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);

	fprintf(stderr, "IPv4 passed/fixed [%lu/%lu] is [%s]\n", ipv4,fix_ipv4, ret_ip);

	/* add user@host as key and passwd as value in the MySQL users hash table */
	if (!mysql_users_add(mysql_users, &key, password)) {
		fprintf(stderr, "Failed adding %s@%s(%lu)\n", username, ret_ip, fix_ipv4);
		users_free(mysql_users);
		free(service);
		dcb_free(dcb);
		return 1;
	}

	memset(&serv_addr, 0, sizeof(serv_addr));
	memset(&find_key, 0, sizeof(find_key));

	find_key.user = username;
	memcpy(&(serv_addr).sin_addr.s_addr, &ipv4, sizeof(ipv4));
	find_key.resource = db;

	memcpy(&find_key.ipv4, &serv_addr, sizeof(serv_addr));

	fetch_data = mysql_users_fetch(mysql_users, &find_key);

	users_free(mysql_users);
	free(service);
	dcb_free(dcb);

	if (!fetch_data)
		return 1;
	
	return 0;
}
Пример #9
0
int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *password, char *from, char *anydb, char *db, char *db_from) {
	USERS *mysql_users;
	int ret = -1;
	struct sockaddr_in client_addr;
	DCB	*dcb;
	SERVICE *service;
	MYSQL_session *data;

	dcb = dcb_alloc(DCB_ROLE_INTERNAL);

	if (dcb == NULL) {
		fprintf(stderr, "dcb_alloc() failed\n");
		return ret;
	}
        if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
		fprintf(stderr, "service_alloc() failed\n");
		dcb_free(dcb);
		return ret;
	}

        memset(&client_addr, 0, sizeof(client_addr));

        if (hostname) {
		if(!setipaddress(&client_addr.sin_addr, from)) {
			fprintf(stderr, "setipaddress failed for host [%s]\n", from);
			free(service);
			dcb_free(dcb);
			return ret;
		}
	}

	if ((data = (MYSQL_session *) calloc(1, sizeof(MYSQL_session))) == NULL) {
		fprintf(stderr, "MYSQL_session alloc failed\n");
		free(service);
		dcb_free(dcb);
		return ret;
	}

	
	/* client IPv4 in raw data*/
	memcpy(&dcb->ipv4, (struct sockaddr_in *)&client_addr, sizeof(struct sockaddr_in));

	dcb->service = service;

	mysql_users = mysql_users_alloc();

	service->users = mysql_users;

	if (db_from != NULL)
		strncpy(data->db, db_from,MYSQL_DATABASE_MAXLEN);
	else
		strncpy(data->db, "",MYSQL_DATABASE_MAXLEN);

	/* freed by dcb_free(dcb) */
	dcb->data = data;

	// the routine returns 1 on success
	if (anydb != NULL) {
		if (strcmp(anydb, "N") == 0) {
			ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, anydb, db);
		} else if (strcmp(anydb, "Y") == 0) {
			ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "Y", "");
		} else {
			ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL);
		}
	} else {
		ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL);
	}
	
	if (ret == 0) {
		fprintf(stderr, "add_mysql_users_with_host_ipv4 (%s@%s, %s) FAILED\n", username, hostname, password);
	} else {
		unsigned char db_passwd[100]="";

		dcb->remote=strdup(from);

		// returns 0 on success
		ret = gw_find_mysql_user_password_sha1(username, db_passwd, dcb);
	}

	users_free(mysql_users);
	free(service);
	dcb_free(dcb);

	return ret;
}