/** * 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_free(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_add_to_zombieslist(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; }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
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; }