Merge branch 'develop' into firewall
This commit is contained in:
		@ -161,3 +161,16 @@ configure_file(
 | 
			
		||||
 | 
			
		||||
add_custom_target(uninstall
 | 
			
		||||
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
 | 
			
		||||
 | 
			
		||||
find_package(Doxygen)
 | 
			
		||||
 | 
			
		||||
if(DOXYGEN_FOUND)
 | 
			
		||||
  configure_file(
 | 
			
		||||
    "${CMAKE_CURRENT_SOURCE_DIR}/doxygate.in"
 | 
			
		||||
    "${CMAKE_CURRENT_BINARY_DIR}/doxygate"
 | 
			
		||||
    IMMEDIATE @ONLY)
 | 
			
		||||
 | 
			
		||||
  add_custom_target(documentation
 | 
			
		||||
    COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygate)
 | 
			
		||||
  
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1520
									
								
								doxygate.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1520
									
								
								doxygate.in
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -338,6 +338,12 @@ static bool logmanager_init_nomutex(
 | 
			
		||||
        bool           succp = false;
 | 
			
		||||
 | 
			
		||||
        lm = (logmanager_t *)calloc(1, sizeof(logmanager_t));
 | 
			
		||||
	
 | 
			
		||||
	if (lm == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		err = 1;
 | 
			
		||||
		goto return_succp;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(SS_DEBUG)
 | 
			
		||||
        lm->lm_chk_top   = CHK_NUM_LOGMANAGER;
 | 
			
		||||
        lm->lm_chk_tail  = CHK_NUM_LOGMANAGER;
 | 
			
		||||
@ -347,7 +353,15 @@ static bool logmanager_init_nomutex(
 | 
			
		||||
	simple_mutex_init(&msg_mutex, "Message mutex");
 | 
			
		||||
#endif
 | 
			
		||||
        lm->lm_clientmes = skygw_message_init();
 | 
			
		||||
        lm->lm_logmes    = skygw_message_init();
 | 
			
		||||
	lm->lm_logmes    = skygw_message_init();
 | 
			
		||||
	
 | 
			
		||||
	if (lm->lm_clientmes == NULL || 
 | 
			
		||||
		lm->lm_logmes == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		err = 1;
 | 
			
		||||
		goto return_succp;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
        lm->lm_enabled_logfiles |= LOGFILE_ERROR;
 | 
			
		||||
        lm->lm_enabled_logfiles |= LOGFILE_MESSAGE;
 | 
			
		||||
#if defined(SS_DEBUG)
 | 
			
		||||
@ -360,8 +374,10 @@ static bool logmanager_init_nomutex(
 | 
			
		||||
        fw->fwr_state = UNINIT;
 | 
			
		||||
        
 | 
			
		||||
        /** Initialize configuration including log file naming info */
 | 
			
		||||
        if (!fnames_conf_init(fn, argc, argv)) {
 | 
			
		||||
            goto return_succp;
 | 
			
		||||
        if (!fnames_conf_init(fn, argc, argv)) 
 | 
			
		||||
	{
 | 
			
		||||
		err = 1;
 | 
			
		||||
		goto return_succp;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** Initialize logfiles */
 | 
			
		||||
@ -389,6 +405,12 @@ static bool logmanager_init_nomutex(
 | 
			
		||||
                                           thr_filewriter_fun,
 | 
			
		||||
                                           (void *)fw);
 | 
			
		||||
 | 
			
		||||
	if (fw->fwr_thread == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		err = 1;
 | 
			
		||||
		goto return_succp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if ((err = skygw_thread_start(fw->fwr_thread)) != 0) 
 | 
			
		||||
	{
 | 
			
		||||
		goto return_succp;
 | 
			
		||||
@ -402,9 +424,12 @@ static bool logmanager_init_nomutex(
 | 
			
		||||
return_succp:
 | 
			
		||||
        if (err != 0) 
 | 
			
		||||
	{
 | 
			
		||||
            /** This releases memory of all created objects */
 | 
			
		||||
            logmanager_done_nomutex();
 | 
			
		||||
            fprintf(stderr, "*\n* Error : Initializing log manager failed.\n*\n");
 | 
			
		||||
		skygw_message_done(lm->lm_clientmes);
 | 
			
		||||
		skygw_message_done(lm->lm_logmes);
 | 
			
		||||
		
 | 
			
		||||
		/** This releases memory of all created objects */
 | 
			
		||||
		logmanager_done_nomutex();
 | 
			
		||||
		fprintf(stderr, "*\n* Error : Initializing log manager failed.\n*\n");
 | 
			
		||||
        }
 | 
			
		||||
        return succp;
 | 
			
		||||
}
 | 
			
		||||
@ -2076,8 +2101,8 @@ static bool logfile_init(
 | 
			
		||||
        fnames_conf_t* fn = &logmanager->lm_fnames_conf;
 | 
			
		||||
        /** string parts of which the file is composed of */
 | 
			
		||||
        strpart_t      strparts[3];
 | 
			
		||||
        bool           namecreatefail;
 | 
			
		||||
        bool           nameconflicts;
 | 
			
		||||
        bool           namecreatefail = false;
 | 
			
		||||
        bool           nameconflicts  = false;
 | 
			
		||||
        bool           writable;
 | 
			
		||||
 | 
			
		||||
        logfile->lf_state = INIT;
 | 
			
		||||
@ -2406,9 +2431,16 @@ static bool filewriter_init(
 | 
			
		||||
                                                           NULL);
 | 
			
		||||
                }
 | 
			
		||||
            
 | 
			
		||||
                if (fw->fwr_file[id] == NULL) {
 | 
			
		||||
                if (fw->fwr_file[id] == NULL) 
 | 
			
		||||
		{
 | 
			
		||||
			fprintf(stderr, 
 | 
			
		||||
				"Error : opening %s failed, %s. Exiting "
 | 
			
		||||
				"MaxScale\n",
 | 
			
		||||
				lf->lf_full_file_name,
 | 
			
		||||
				strerror(errno));
 | 
			
		||||
                        goto return_succp;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                if (lf->lf_enabled) {
 | 
			
		||||
                        start_msg_str = strdup("---\tLogging is enabled.\n");
 | 
			
		||||
                } else {
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,8 @@
 | 
			
		||||
#include <log_manager.h>
 | 
			
		||||
#include <secrets.h>
 | 
			
		||||
#include <mysql_client_server_protocol.h>
 | 
			
		||||
#include <mysqld_error.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
 | 
			
		||||
#define LOAD_MYSQL_USERS_QUERY "SELECT user, host, password, concat(user,host,password,Select_priv) AS userdata, Select_priv AS anydb FROM mysql.user WHERE user IS NOT NULL AND user <> ''"
 | 
			
		||||
@ -494,7 +496,7 @@ getUsers(SERVICE *service, USERS *users)
 | 
			
		||||
 | 
			
		||||
	/* start with users and db grants for users */
 | 
			
		||||
	if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
 | 
			
		||||
		if (1142 != mysql_errno(con)) {
 | 
			
		||||
		if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
 | 
			
		||||
                        /* This is an error we cannot handle, return */
 | 
			
		||||
			LOGIF(LE, (skygw_log_write_flush(
 | 
			
		||||
				LOGFILE_ERROR,
 | 
			
		||||
@ -897,13 +899,19 @@ static void *uh_keydup(void* key) {
 | 
			
		||||
	MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *)key;
 | 
			
		||||
 | 
			
		||||
	if (key == NULL || rval == NULL || current_key == NULL || current_key->user == NULL) {
 | 
			
		||||
		if (rval) {
 | 
			
		||||
			free(rval);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rval->user = strdup(current_key->user);
 | 
			
		||||
 | 
			
		||||
	if (rval->user == NULL)
 | 
			
		||||
	if (rval->user == NULL) {
 | 
			
		||||
		free(rval);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in));
 | 
			
		||||
	memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int));
 | 
			
		||||
 | 
			
		||||
@ -175,7 +175,7 @@ void gw_daemonize(void) {
 | 
			
		||||
int
 | 
			
		||||
parse_bindconfig(char *config, unsigned short def_port, struct sockaddr_in *addr)
 | 
			
		||||
{
 | 
			
		||||
char			*port, buf[1024];
 | 
			
		||||
char			*port, buf[1024 + 1];
 | 
			
		||||
short			pnum;
 | 
			
		||||
struct hostent		*hp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -258,7 +258,9 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
 | 
			
		||||
 | 
			
		||||
		/* check succesfull key copy */
 | 
			
		||||
		if ( ptr->key  == NULL) {
 | 
			
		||||
			free(ptr);
 | 
			
		||||
			hashtable_write_unlock(table);
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -269,9 +271,11 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
 | 
			
		||||
		if  ( ptr->value == NULL) {
 | 
			
		||||
			/* remove the key ! */
 | 
			
		||||
			table->kfreefn(ptr->key);
 | 
			
		||||
			free(ptr);
 | 
			
		||||
 | 
			
		||||
			/* value not copied, return */
 | 
			
		||||
			hashtable_write_unlock(table);
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -279,6 +283,7 @@ hashtable_add(HASHTABLE *table, void *key, void *value)
 | 
			
		||||
		table->entries[hashkey % table->hashsize] = ptr;
 | 
			
		||||
	}
 | 
			
		||||
	hashtable_write_unlock(table);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,7 @@ static  simple_mutex_t  epoll_wait_mutex; /*< serializes calls to epoll_wait */
 | 
			
		||||
#endif
 | 
			
		||||
static	int		n_waiting = 0;	  /*< No. of threads in epoll_wait */
 | 
			
		||||
static	int		process_pollq(int thread_id);
 | 
			
		||||
static	void		poll_add_event_to_dcb(DCB* dcb, GWBUF* buf, __uint32_t ev);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DCB		*eventq = NULL;
 | 
			
		||||
@ -1110,3 +1111,68 @@ int		new_samples, new_nfds;
 | 
			
		||||
	if (next_sample >= n_avg_samples)
 | 
			
		||||
		next_sample = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add given GWBUF to DCB's readqueue and add a pending EPOLLIN event for DCB.
 | 
			
		||||
 * The event pretends that there is something to read for the DCB. Actually
 | 
			
		||||
 * the incoming data is stored in the DCB's readqueue where it is read.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param dcb	DCB where the event and data are added
 | 
			
		||||
 * @param buf	GWBUF including the data
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
void poll_add_epollin_event_to_dcb(
 | 
			
		||||
	DCB*   dcb,
 | 
			
		||||
	GWBUF* buf)
 | 
			
		||||
{
 | 
			
		||||
	__uint32_t ev;
 | 
			
		||||
	
 | 
			
		||||
	ev = EPOLLIN;
 | 
			
		||||
 | 
			
		||||
	poll_add_event_to_dcb(dcb, buf, ev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void poll_add_event_to_dcb(
 | 
			
		||||
	DCB*       dcb,
 | 
			
		||||
	GWBUF*     buf,
 | 
			
		||||
	__uint32_t ev)
 | 
			
		||||
{	
 | 
			
		||||
	/** Add buf to readqueue */
 | 
			
		||||
	spinlock_acquire(&dcb->authlock);
 | 
			
		||||
	dcb->dcb_readqueue = gwbuf_append(dcb->dcb_readqueue, buf);
 | 
			
		||||
	spinlock_release(&dcb->authlock);
 | 
			
		||||
		
 | 
			
		||||
	spinlock_acquire(&pollqlock);
 | 
			
		||||
	
 | 
			
		||||
	/** Set event to DCB */
 | 
			
		||||
	if (DCB_POLL_BUSY(dcb))
 | 
			
		||||
	{
 | 
			
		||||
		dcb->evq.pending_events |= ev;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		dcb->evq.pending_events = ev;
 | 
			
		||||
		/** Add DCB to eventqueue if it isn't already there */
 | 
			
		||||
		if (eventq)
 | 
			
		||||
		{
 | 
			
		||||
			dcb->evq.prev = eventq->evq.prev;
 | 
			
		||||
			eventq->evq.prev->evq.next = dcb;
 | 
			
		||||
			eventq->evq.prev = dcb;
 | 
			
		||||
			dcb->evq.next = eventq;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			eventq = dcb;
 | 
			
		||||
			dcb->evq.prev = dcb;
 | 
			
		||||
			dcb->evq.next = dcb;
 | 
			
		||||
		}
 | 
			
		||||
		pollStats.evq_length++;
 | 
			
		||||
		if (pollStats.evq_length > pollStats.evq_max)
 | 
			
		||||
		{
 | 
			
		||||
			pollStats.evq_max = pollStats.evq_length;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	spinlock_release(&pollqlock);
 | 
			
		||||
}
 | 
			
		||||
@ -41,4 +41,11 @@ extern GWBUF	*modutil_replace_SQL(GWBUF *, char *);
 | 
			
		||||
extern char	*modutil_get_query(GWBUF* buf);
 | 
			
		||||
extern int	modutil_send_mysql_err_packet(DCB *, int, int, int, const char *, const char *);
 | 
			
		||||
 | 
			
		||||
GWBUF *modutil_create_mysql_err_msg(
 | 
			
		||||
	int		packet_number,
 | 
			
		||||
	int		affected_rows,
 | 
			
		||||
	int		merrno,
 | 
			
		||||
	const char	*statemsg,
 | 
			
		||||
	const char	*msg);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -42,4 +42,6 @@ extern	void		poll_shutdown();
 | 
			
		||||
extern	GWBITMASK	*poll_bitmask();
 | 
			
		||||
extern	void		dprintPollStats(DCB *);
 | 
			
		||||
extern	void		dShowThreads(DCB *dcb);
 | 
			
		||||
void 			poll_add_epollin_event_to_dcb(DCB* dcb, GWBUF* buf);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -74,6 +74,7 @@ typedef enum backend_type_t {
 | 
			
		||||
struct router_instance;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	TARGET_UNDEFINED    = 0x00,
 | 
			
		||||
        TARGET_MASTER       = 0x01,
 | 
			
		||||
        TARGET_SLAVE        = 0x02,
 | 
			
		||||
        TARGET_NAMED_SERVER = 0x04,
 | 
			
		||||
 | 
			
		||||
@ -71,6 +71,7 @@ static int gw_change_user(DCB *backend_dcb, SERVER *server, SESSION *in_session,
 | 
			
		||||
static GWBUF* process_response_data (DCB* dcb, GWBUF* readbuf, int nbytes_to_process); 
 | 
			
		||||
extern char* create_auth_failed_msg( GWBUF* readbuf, char*  hostaddr, uint8_t*  sha1);
 | 
			
		||||
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db);
 | 
			
		||||
static bool sescmd_response_complete(DCB* dcb);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(NOT_USED)
 | 
			
		||||
@ -471,19 +472,26 @@ static int gw_read_backend_event(DCB *dcb) {
 | 
			
		||||
                }
 | 
			
		||||
                nbytes_read = gwbuf_length(read_buffer);
 | 
			
		||||
 | 
			
		||||
                if (nbytes_read == 0)
 | 
			
		||||
                if (nbytes_read == 0 && dcb->dcb_readqueue == NULL)
 | 
			
		||||
                {
 | 
			
		||||
                        goto return_rc;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                        ss_dassert(read_buffer != NULL);
 | 
			
		||||
                        ss_dassert(read_buffer != NULL || dcb->dcb_readqueue != NULL);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /** Packet prefix was read earlier */
 | 
			
		||||
                if (dcb->dcb_readqueue)
 | 
			
		||||
                {
 | 
			
		||||
                        read_buffer = gwbuf_append(dcb->dcb_readqueue, read_buffer);
 | 
			
		||||
			if (read_buffer != NULL)
 | 
			
		||||
			{
 | 
			
		||||
				read_buffer = gwbuf_append(dcb->dcb_readqueue, read_buffer);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				read_buffer = dcb->dcb_readqueue;
 | 
			
		||||
			}
 | 
			
		||||
                        nbytes_read = gwbuf_length(read_buffer);
 | 
			
		||||
                        
 | 
			
		||||
                        if (nbytes_read < 5) /*< read at least command type */
 | 
			
		||||
@ -494,7 +502,6 @@ static int gw_read_backend_event(DCB *dcb) {
 | 
			
		||||
                        /** There is at least length and command type. */
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                                read_buffer = dcb->dcb_readqueue;
 | 
			
		||||
                                dcb->dcb_readqueue = NULL;                        
 | 
			
		||||
                        }
 | 
			
		||||
                }
 | 
			
		||||
@ -516,6 +523,15 @@ static int gw_read_backend_event(DCB *dcb) {
 | 
			
		||||
                        MYSQL_COM_UNDEFINED)
 | 
			
		||||
                {
 | 
			
		||||
                        read_buffer = process_response_data(dcb, read_buffer, nbytes_read);
 | 
			
		||||
			/** 
 | 
			
		||||
			 * Received incomplete response to session command.
 | 
			
		||||
			 * Store it to readqueue and return.
 | 
			
		||||
			 */
 | 
			
		||||
			if (!sescmd_response_complete(dcb))
 | 
			
		||||
			{
 | 
			
		||||
				rc = 0;
 | 
			
		||||
				goto return_rc;
 | 
			
		||||
			}
 | 
			
		||||
                }
 | 
			
		||||
                /*<
 | 
			
		||||
                 * If dcb->session->client is freed already it may be NULL.
 | 
			
		||||
@ -723,9 +739,6 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
 | 
			
		||||
                
 | 
			
		||||
                default:
 | 
			
		||||
                {
 | 
			
		||||
                        uint8_t* ptr = GWBUF_DATA(queue);
 | 
			
		||||
                        int      cmd = MYSQL_GET_COMMAND(ptr);
 | 
			
		||||
 | 
			
		||||
                        LOGIF(LD, (skygw_log_write(
 | 
			
		||||
                                LOGFILE_DEBUG,
 | 
			
		||||
                                "%lu [gw_MySQLWrite_backend] delayed write to "
 | 
			
		||||
@ -741,6 +754,9 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
 | 
			
		||||
                        if (GWBUF_IS_TYPE_SINGLE_STMT(queue) &&
 | 
			
		||||
                                GWBUF_IS_TYPE_SESCMD(queue))
 | 
			
		||||
                        {
 | 
			
		||||
				uint8_t* ptr = GWBUF_DATA(queue);
 | 
			
		||||
				int      cmd = MYSQL_GET_COMMAND(ptr);
 | 
			
		||||
				
 | 
			
		||||
                                /** Record the command to backend's protocol */
 | 
			
		||||
                                protocol_add_srv_command(backend_protocol, cmd);
 | 
			
		||||
                        }
 | 
			
		||||
@ -1183,7 +1199,7 @@ static int backend_write_delayqueue(DCB *dcb)
 | 
			
		||||
 * @param server	The backend server pointer
 | 
			
		||||
 * @param in_session	The current session data (MYSQL_session)
 | 
			
		||||
 * @param queue		The GWBUF containing the COM_CHANGE_USER receveid
 | 
			
		||||
 * @return 0 on success and 1 on failure
 | 
			
		||||
 * @return 1 on success and 0 on failure
 | 
			
		||||
 */
 | 
			
		||||
static int gw_change_user(
 | 
			
		||||
        DCB     *backend, 
 | 
			
		||||
@ -1266,26 +1282,35 @@ static int gw_change_user(
 | 
			
		||||
        if (auth_ret != 0) {
 | 
			
		||||
		char *password_set = NULL;
 | 
			
		||||
		char *message = NULL;
 | 
			
		||||
		GWBUF* 		buf;
 | 
			
		||||
 | 
			
		||||
		if (auth_token_len > 0)
 | 
			
		||||
			password_set = (char *)client_sha1;
 | 
			
		||||
		else
 | 
			
		||||
			password_set = "";
 | 
			
		||||
 | 
			
		||||
		message=create_auth_fail_str(username,
 | 
			
		||||
		/** 
 | 
			
		||||
		 * Create an error message and make it look like legit reply
 | 
			
		||||
		 * from backend server. Then make it look like an incoming event
 | 
			
		||||
		 * so that thread gets new task of it, calls clientReply
 | 
			
		||||
		 * which filters out duplicate errors from same cause and forward
 | 
			
		||||
		 * reply to the client.
 | 
			
		||||
		 */
 | 
			
		||||
		message = create_auth_fail_str(username,
 | 
			
		||||
						backend->session->client->remote,
 | 
			
		||||
						password_set,
 | 
			
		||||
						"");
 | 
			
		||||
		/* send the error packet */
 | 
			
		||||
		modutil_send_mysql_err_packet(backend->session->client, 1, 0, 1045, "28000", message);
 | 
			
		||||
 | 
			
		||||
		free(message);
 | 
			
		||||
 | 
			
		||||
		rv = 1;
 | 
			
		||||
		/** TODO: Add custom message indicating that retry would probably help */
 | 
			
		||||
		buf = modutil_create_mysql_err_msg(1, 0, 1045, "28000", message);
 | 
			
		||||
		/** Set flags that help router to identify session commans reply */
 | 
			
		||||
		gwbuf_set_type(buf, GWBUF_TYPE_MYSQL);
 | 
			
		||||
		gwbuf_set_type(buf, GWBUF_TYPE_SESCMD_RESPONSE);
 | 
			
		||||
		gwbuf_set_type(buf, GWBUF_TYPE_RESPONSE_END);
 | 
			
		||||
		/** Create an incoming event for backend DCB */
 | 
			
		||||
		poll_add_epollin_event_to_dcb(backend, buf);
 | 
			
		||||
		rv = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
		rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Now copy new data into user session
 | 
			
		||||
		 */		
 | 
			
		||||
@ -1298,29 +1323,9 @@ static int gw_change_user(
 | 
			
		||||
	return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Session Change wrapper for func.write
 | 
			
		||||
 * The reply packet will be back routed to the right server
 | 
			
		||||
 * in the gw_read_backend_event checking the ROUTER_CHANGE_SESSION command in dcb->command
 | 
			
		||||
 * 
 | 
			
		||||
 * @param
 | 
			
		||||
 * @return always 1
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
static int gw_session(DCB *backend_dcb, void *data) {
 | 
			
		||||
 | 
			
		||||
	GWBUF *queue = NULL;
 | 
			
		||||
 | 
			
		||||
	queue = (GWBUF *) data;
 | 
			
		||||
	backend_dcb->func.write(backend_dcb, queue);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
 * Move packets or parts of packets from redbuf to outbuf as the packet headers
 | 
			
		||||
 * Move packets or parts of packets from readbuf to outbuf as the packet headers
 | 
			
		||||
 * and lengths have been noticed and counted.
 | 
			
		||||
 * Session commands need to be marked so that they can be handled properly in 
 | 
			
		||||
 * the router's clientReply.
 | 
			
		||||
@ -1452,3 +1457,28 @@ static GWBUF* process_response_data (
 | 
			
		||||
        }
 | 
			
		||||
        return outbuf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static bool sescmd_response_complete(
 | 
			
		||||
	DCB* dcb)
 | 
			
		||||
{
 | 
			
		||||
	int 		npackets_left;
 | 
			
		||||
	size_t 		nbytes_left;
 | 
			
		||||
	MySQLProtocol* 	p;
 | 
			
		||||
	bool		succp;
 | 
			
		||||
	
 | 
			
		||||
	p = DCB_PROTOCOL(dcb, MySQLProtocol);
 | 
			
		||||
	CHK_PROTOCOL(p);
 | 
			
		||||
	
 | 
			
		||||
	protocol_get_response_status(p, &npackets_left, &nbytes_left);
 | 
			
		||||
	
 | 
			
		||||
	if (npackets_left == 0)
 | 
			
		||||
	{
 | 
			
		||||
		succp = true;
 | 
			
		||||
	}
 | 
			
		||||
	else 
 | 
			
		||||
	{
 | 
			
		||||
		succp = false;
 | 
			
		||||
	}
 | 
			
		||||
	return succp;
 | 
			
		||||
}
 | 
			
		||||
@ -1221,7 +1221,7 @@ int gw_send_change_user_to_backend(
 | 
			
		||||
 * @param scramble_len 	The scrable size in bytes
 | 
			
		||||
 * @param username	The current username in the authentication request
 | 
			
		||||
 * @param stage1_hash	The SHA1(candidate_password) decoded by this routine
 | 
			
		||||
 * @return 0 on succesful check or != 0 on failure
 | 
			
		||||
 * @return 0 on succesful check or 1 on failure
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_len, uint8_t *scramble, unsigned int scramble_len, char *username, uint8_t *stage1_hash) {
 | 
			
		||||
@ -1321,7 +1321,12 @@ int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_le
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* now compare SHA1(SHA1(gateway_password)) and check_hash: return 0 is MYSQL_AUTH_OK */
 | 
			
		||||
	return memcmp(password, check_hash, SHA_DIGEST_LENGTH);
 | 
			
		||||
	ret_val = memcmp(password, check_hash, SHA_DIGEST_LENGTH);
 | 
			
		||||
 | 
			
		||||
	if (ret_val != 0)
 | 
			
		||||
		return 1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -1241,7 +1241,7 @@ static route_target_t get_route_target (
 | 
			
		||||
	target_t           use_sql_variables_in,
 | 
			
		||||
        HINT*              hint)
 | 
			
		||||
{
 | 
			
		||||
        route_target_t target;
 | 
			
		||||
        route_target_t target = TARGET_UNDEFINED;
 | 
			
		||||
	/**
 | 
			
		||||
	 * These queries are not affected by hints
 | 
			
		||||
	 */
 | 
			
		||||
@ -1355,6 +1355,11 @@ static route_target_t get_route_target (
 | 
			
		||||
			}
 | 
			
		||||
			hint = hint->next;
 | 
			
		||||
		} /*< while (hint != NULL) */
 | 
			
		||||
		/** If nothing matches then choose the master */
 | 
			
		||||
		if ((target & (TARGET_ALL|TARGET_SLAVE|TARGET_MASTER)) == target)
 | 
			
		||||
		{
 | 
			
		||||
			target = TARGET_MASTER;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -224,17 +224,27 @@ int skygw_rwlock_init(
 | 
			
		||||
        int             err;
 | 
			
		||||
        
 | 
			
		||||
        rwl = (skygw_rwlock_t *)calloc(1, sizeof(skygw_rwlock_t));
 | 
			
		||||
        rwl->srw_chk_top = CHK_NUM_RWLOCK;
 | 
			
		||||
        rwl->srw_chk_tail = CHK_NUM_RWLOCK;
 | 
			
		||||
        err = pthread_rwlock_init(rwl->srw_rwlock, NULL);
 | 
			
		||||
        ss_dassert(err == 0);
 | 
			
		||||
	
 | 
			
		||||
        if (err != 0) {
 | 
			
		||||
	if (rwl == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		err = 1;
 | 
			
		||||
		goto return_err;
 | 
			
		||||
	}
 | 
			
		||||
	rwl->srw_chk_top = CHK_NUM_RWLOCK;
 | 
			
		||||
	rwl->srw_chk_tail = CHK_NUM_RWLOCK;
 | 
			
		||||
	err = pthread_rwlock_init(rwl->srw_rwlock, NULL);
 | 
			
		||||
	ss_dassert(err == 0);
 | 
			
		||||
        
 | 
			
		||||
        if (err != 0) 
 | 
			
		||||
	{
 | 
			
		||||
		free(rwl);
 | 
			
		||||
                ss_dfprintf(stderr,
 | 
			
		||||
                            "* Creating pthread_rwlock failed : %s\n",
 | 
			
		||||
                            strerror(err));
 | 
			
		||||
                goto return_err;
 | 
			
		||||
        }
 | 
			
		||||
        *rwlock = rwl;
 | 
			
		||||
	
 | 
			
		||||
return_err:
 | 
			
		||||
        return err;
 | 
			
		||||
}
 | 
			
		||||
@ -1013,6 +1023,7 @@ skygw_thread_t* skygw_thread_init(
 | 
			
		||||
 | 
			
		||||
        if (th->sth_mutex == NULL) {
 | 
			
		||||
                thread_free_memory(th, th->sth_name);
 | 
			
		||||
		th = NULL;
 | 
			
		||||
                goto return_th;
 | 
			
		||||
        }
 | 
			
		||||
        th->sth_thrfun = sth_thrfun;
 | 
			
		||||
@ -1396,6 +1407,12 @@ skygw_message_t* skygw_message_init(void)
 | 
			
		||||
        skygw_message_t* mes;
 | 
			
		||||
 | 
			
		||||
        mes = (skygw_message_t*)calloc(1, sizeof(skygw_message_t));
 | 
			
		||||
	
 | 
			
		||||
	if (mes == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		err = 1;
 | 
			
		||||
		goto return_mes;
 | 
			
		||||
	}
 | 
			
		||||
        mes->mes_chk_top = CHK_NUM_MESSAGE;
 | 
			
		||||
        mes->mes_chk_tail = CHK_NUM_MESSAGE;
 | 
			
		||||
        err = pthread_mutex_init(&(mes->mes_mutex), NULL);
 | 
			
		||||
@ -1406,6 +1423,7 @@ skygw_message_t* skygw_message_init(void)
 | 
			
		||||
                        "%d, %s\n",
 | 
			
		||||
                        err,
 | 
			
		||||
                        strerror(errno));
 | 
			
		||||
		free(mes);
 | 
			
		||||
                mes = NULL;
 | 
			
		||||
                goto return_mes;
 | 
			
		||||
        }
 | 
			
		||||
@ -1417,6 +1435,8 @@ skygw_message_t* skygw_message_init(void)
 | 
			
		||||
                        "due error %d, %s\n",
 | 
			
		||||
                        err,
 | 
			
		||||
                        strerror(errno));
 | 
			
		||||
		pthread_mutex_destroy(&mes->mes_mutex);
 | 
			
		||||
		free(mes);
 | 
			
		||||
                mes = NULL;
 | 
			
		||||
                goto return_mes;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user