Beispiel #1
0
/**
 * Create the filter chain for this session.
 *
 * Filters must be setup in reverse order, starting with the last
 * filter in the chain and working back towards the client connection
 * Each filter is passed the current session head of the filter chain
 * this head becomes the destination for the filter. The newly created
 * filter becomes the new head of the filter chain.
 *
 * @param	session		The session that requires the chain
 * @return	0 if filter creation fails
 */
static int
session_setup_filters(SESSION *session)
{
SERVICE		*service = session->service;
DOWNSTREAM 	*head;
UPSTREAM	*tail;
int		i;

	if ((session->filters = calloc(service->n_filters,
				sizeof(SESSION_FILTER))) == NULL)
	{
                LOGIF(LE, (skygw_log_write_flush(
			LOGFILE_ERROR,
			"Insufficient memory to allocate session filter "
			"tracking.\n")));
			return 0;
	}
	session->n_filters = service->n_filters;
	for (i = service->n_filters - 1; i >= 0; i--)
	{
		if ((head = filterApply(service->filters[i], session,
						&session->head)) == NULL)
		{
                	LOGIF(LE, (skygw_log_write_flush(
				LOGFILE_ERROR,
				"Failed to create filter '%s' for service '%s'.\n",
					service->filters[i]->name,
					service->name)));
			return 0;
		}
		session->filters[i].filter = service->filters[i];
		session->filters[i].session = head->session;
		session->filters[i].instance = head->instance;
		session->head = *head;
	}

	for (i = 0; i < service->n_filters; i++)
	{
		if ((tail = filterUpstream(service->filters[i],
				session->filters[i].session,
						&session->tail)) == NULL)
		{
                	LOGIF(LE, (skygw_log_write_flush(
				LOGFILE_ERROR,
				"Failed to create filter '%s' for service '%s'.\n",
					service->filters[i]->name,
					service->name)));
			return 0;
		}
		session->tail = *tail;
	}

	return 1;
}
Beispiel #2
0
/**
 * Create the filter chain for this session.
 *
 * Filters must be setup in reverse order, starting with the last
 * filter in the chain and working back towards the client connection
 * Each filter is passed the current session head of the filter chain
 * this head becomes the destination for the filter. The newly created
 * filter becomes the new head of the filter chain.
 *
 * @param       session         The session that requires the chain
 * @return      0 if filter creation fails
 */
static int
session_setup_filters(SESSION *session)
{
    SERVICE *service = session->service;
    DOWNSTREAM *head;
    UPSTREAM *tail;
    int i;

    if ((session->filters = calloc(service->n_filters,
                                   sizeof(SESSION_FILTER))) == NULL)
    {
        MXS_ERROR("Insufficient memory to allocate session filter "
                  "tracking.\n");
        return 0;
    }
    session->n_filters = service->n_filters;
    for (i = service->n_filters - 1; i >= 0; i--)
    {
        if (service->filters[i] == NULL)
        {
            MXS_ERROR("Service '%s' contians an unresolved filter.", service->name);
            return 0;
        }
        if ((head = filterApply(service->filters[i], session,
                                &session->head)) == NULL)
        {
            MXS_ERROR("Failed to create filter '%s' for "
                      "service '%s'.\n",
                      service->filters[i]->name,
                      service->name);
            return 0;
        }
        session->filters[i].filter = service->filters[i];
        session->filters[i].session = head->session;
        session->filters[i].instance = head->instance;
        session->head = *head;
        free(head);
    }

    for (i = 0; i < service->n_filters; i++)
    {
        if ((tail = filterUpstream(service->filters[i],
                                   session->filters[i].session,
                                   &session->tail)) == NULL)
        {
            MXS_ERROR("Failed to create filter '%s' for service '%s'.",
                      service->filters[i]->name,
                      service->name);
            return 0;
        }

        /*
         * filterUpstream may simply return the 3 parameter if
         * the filter has no upstream entry point. So no need
         * to copy the contents or free tail in this case.
         */
        if (tail != &session->tail)
        {
            session->tail = *tail;
            free(tail);
        }
    }

    return 1;
}
Beispiel #3
0
/**
 * Associate a new session with this instance of the filter.
 *
 * Create the file to log to and open it.
 *
 * @param instance	The filter instance data
 * @param session	The session itself
 * @return Session specific data for this session
 */
static void *
newSession(FILTER *instance, SESSION *session)
{
    TEE_INSTANCE *my_instance = (TEE_INSTANCE *) instance;
    TEE_SESSION *my_session;
    char *remote, *userName;

    if (strcmp(my_instance->service->name, session->service->name) == 0)
    {
        MXS_ERROR("%s: Recursive use of tee filter in service.",
                  session->service->name);
        my_session = NULL;
        goto retblock;
    }

    HASHTABLE* ht = hashtable_alloc(100, simple_str_hash, strcmp);
    bool is_loop = detect_loops(my_instance, ht, session->service);
    hashtable_free(ht);

    if (is_loop)
    {
        MXS_ERROR("%s: Recursive use of tee filter in service.",
                  session->service->name);
        my_session = NULL;
        goto retblock;
    }

    if ((my_session = calloc(1, sizeof(TEE_SESSION))) != NULL)
    {
        my_session->active = 1;
        my_session->residual = 0;
        my_session->tee_replybuf = NULL;
        my_session->client_dcb = session->client;
        my_session->instance = my_instance;
        my_session->client_multistatement = false;
        my_session->queue = NULL;
        spinlock_init(&my_session->tee_lock);
        if (my_instance->source &&
            (remote = session_get_remote(session)) != NULL)
        {
            if (strcmp(remote, my_instance->source))
            {
                my_session->active = 0;

                MXS_WARNING("Tee filter is not active.");
            }
        }
        userName = session_getUser(session);

        if (my_instance->userName &&
            userName &&
            strcmp(userName, my_instance->userName))
        {
            my_session->active = 0;

            MXS_WARNING("Tee filter is not active.");
        }

        if (my_session->active)
        {
            DCB* dcb;
            SESSION* ses;
            FILTER_DEF* dummy;
            UPSTREAM* dummy_upstream;

            if ((dcb = dcb_clone(session->client)) == NULL)
            {
                freeSession(instance, (void *) my_session);
                my_session = NULL;

                MXS_ERROR("Creating client DCB for Tee "
                          "filter failed. Terminating session.");

                goto retblock;
            }

            if ((dummy = filter_alloc("tee_dummy", "tee_dummy")) == NULL)
            {
                dcb_close(dcb);
                freeSession(instance, (void *) my_session);
                my_session = NULL;
                MXS_ERROR("tee: Allocating memory for "
                          "dummy filter definition failed."
                          " Terminating session.");

                goto retblock;
            }



            if ((ses = session_alloc(my_instance->service, dcb)) == NULL)
            {
                filter_free(dummy);
                dcb_close(dcb);
                freeSession(instance, (void *) my_session);
                my_session = NULL;
                MXS_ERROR("Creating client session for Tee "
                          "filter failed. Terminating session.");

                goto retblock;
            }

            ss_dassert(ses->ses_is_child);

            dummy->obj = GetModuleObject();
            dummy->filter = NULL;
            my_session->branch_session = ses;
            my_session->branch_dcb = dcb;
            my_session->dummy_filterdef = dummy;

            if ((dummy_upstream = filterUpstream(
                                                 dummy, my_session, &ses->tail)) == NULL)
            {
                filter_free(dummy);
                closeSession(instance, (void*) my_session);
                dcb_close(dcb);
                free(my_session);
                MXS_ERROR("tee: Allocating memory for"
                          "dummy upstream failed."
                          " Terminating session.");

                return NULL;
            }

            ses->tail = *dummy_upstream;
            MySQLProtocol* protocol = (MySQLProtocol*) session->client->protocol;
            my_session->use_ok = protocol->client_capabilities & (1 << 6);
            free(dummy_upstream);
        }
    }
retblock:
    return my_session;
}