mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
5.0 KiB
C
195 lines
5.0 KiB
C
/*
|
|
* LibHTP (http://www.libhtp.org)
|
|
* Copyright 2009,2010 Ivan Ristic <ivanr@webkreator.com>
|
|
*
|
|
* LibHTP is an open source product, released under terms of the General Public Licence
|
|
* version 2 (GPLv2). Please refer to the file LICENSE, which contains the complete text
|
|
* of the license.
|
|
*
|
|
* In addition, there is a special exception that allows LibHTP to be freely
|
|
* used with any OSI-approved open source licence. Please refer to the file
|
|
* LIBHTP_LICENSING_EXCEPTION for the full text of the exception.
|
|
*
|
|
*/
|
|
|
|
#include "hooks.h"
|
|
|
|
/**
|
|
* Creates a new hook.
|
|
*
|
|
* @return New htp_hook_t structure on success, NULL on failure
|
|
*/
|
|
htp_hook_t *hook_create() {
|
|
htp_hook_t *hook = calloc(1, sizeof (htp_hook_t));
|
|
if (hook == NULL) return NULL;
|
|
|
|
hook->callbacks = list_array_create(4);
|
|
if (hook->callbacks == NULL) {
|
|
free(hook);
|
|
return NULL;
|
|
}
|
|
|
|
return hook;
|
|
}
|
|
|
|
/**
|
|
* Creates a copy of the provided hook. The hook is allowed to be NULL,
|
|
* in which case this function simply returns a NULL.
|
|
*
|
|
* @param hook
|
|
* @return A copy of the hook, or NULL (if the provided hook was NULL
|
|
* or, if it wasn't, if there was a memory allocation problem while
|
|
* constructing a copy).
|
|
*/
|
|
htp_hook_t * hook_copy(htp_hook_t *hook) {
|
|
if (hook == NULL) return NULL;
|
|
|
|
htp_hook_t *copy = hook_create();
|
|
if (copy == NULL) return NULL;
|
|
|
|
htp_callback_t *callback = NULL;
|
|
list_iterator_reset(hook->callbacks);
|
|
while ((callback = list_iterator_next(hook->callbacks)) != NULL) {
|
|
if (hook_register(©, callback->fn) < 0) {
|
|
hook_destroy(copy);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return copy;
|
|
}
|
|
|
|
/**
|
|
* Destroys an existing hook. It is all right to send a NULL
|
|
* to this method because it will simply return straight away.
|
|
*
|
|
* @param hook
|
|
*/
|
|
void hook_destroy(htp_hook_t *hook) {
|
|
if (hook == NULL) return;
|
|
|
|
htp_callback_t *callback = NULL;
|
|
list_iterator_reset(hook->callbacks);
|
|
while ((callback = list_iterator_next(hook->callbacks)) != NULL) {
|
|
free(callback);
|
|
}
|
|
|
|
list_destroy(hook->callbacks);
|
|
|
|
free(hook);
|
|
}
|
|
|
|
/**
|
|
* Registers a new callback with the hook.
|
|
*
|
|
* @param hook
|
|
* @param callback_fn
|
|
* @return 1 on success, -1 on memory allocation error
|
|
*/
|
|
int hook_register(htp_hook_t **hook, int (*callback_fn)()) {
|
|
int hook_created = 0;
|
|
htp_callback_t *callback = calloc(1, sizeof (htp_callback_t));
|
|
if (callback == NULL) return -1;
|
|
|
|
callback->fn = callback_fn;
|
|
|
|
// Create a new hook if one does not exist
|
|
if (*hook == NULL) {
|
|
*hook = hook_create();
|
|
if (*hook == NULL) {
|
|
free(callback);
|
|
return -1;
|
|
}
|
|
|
|
hook_created = 1;
|
|
}
|
|
|
|
// Add callback
|
|
if (list_add((*hook)->callbacks, callback) < 0) {
|
|
if (hook_created) {
|
|
free(*hook);
|
|
}
|
|
|
|
free(callback);
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Runs all the callbacks associated with a given hook. Only stops if
|
|
* one of the callbacks returns an error (HOOK_ERROR).
|
|
*
|
|
* @param hook
|
|
* @param data
|
|
* @return HOOK_OK or HOOK_ERROR
|
|
*/
|
|
int hook_run_all(htp_hook_t *hook, void *data) {
|
|
if (hook == NULL) {
|
|
return HOOK_OK;
|
|
}
|
|
|
|
/* HACK https://redmine.openinfosecfoundation.org/issues/601 */
|
|
size_t i = 0;
|
|
for (i = 0; i < ((list_array_t *)hook->callbacks)->current_size; i++) {
|
|
void *r = ((list_array_t *)hook->callbacks)->elements[i];
|
|
if (r == NULL)
|
|
continue;
|
|
|
|
htp_callback_t *callback = r;
|
|
if (callback->fn(data) == HOOK_ERROR) {
|
|
return HOOK_ERROR;
|
|
}
|
|
}
|
|
#if 0
|
|
htp_callback_t *callback = NULL;
|
|
list_iterator_reset(hook->callbacks);
|
|
while ((callback = list_iterator_next(hook->callbacks)) != NULL) {
|
|
if (callback->fn(data) == HOOK_ERROR) {
|
|
return HOOK_ERROR;
|
|
}
|
|
}
|
|
#endif
|
|
return HOOK_OK;
|
|
}
|
|
|
|
/**
|
|
* Run callbacks until one of them accepts to service the hook.
|
|
*
|
|
* @param hook
|
|
* @param data
|
|
* @return HOOK_OK on success, HOOK_DECLINED if no callback wanted to run and HOOK_ERROR on error.
|
|
*/
|
|
int hook_run_one(htp_hook_t *hook, void *data) {
|
|
if (hook == NULL) {
|
|
return HOOK_DECLINED;
|
|
}
|
|
|
|
/* HACK https://redmine.openinfosecfoundation.org/issues/601 */
|
|
size_t i = 0;
|
|
for (i = 0; i < ((list_array_t *)hook->callbacks)->current_size; i++) {
|
|
void *r = ((list_array_t *)hook->callbacks)->elements[i];
|
|
if (r == NULL)
|
|
continue;
|
|
|
|
htp_callback_t *callback = r;
|
|
int status = callback->fn(data);
|
|
if (status != HOOK_DECLINED) {
|
|
return status;
|
|
}
|
|
}
|
|
#if 0
|
|
htp_callback_t *callback = NULL;
|
|
list_iterator_reset(hook->callbacks);
|
|
while ((callback = list_iterator_next(hook->callbacks)) != NULL) {
|
|
int status = callback->fn(data);
|
|
// Both HOOK_OK and HOOK_ERROR will stop hook processing
|
|
if (status != HOOK_DECLINED) {
|
|
return status;
|
|
}
|
|
}
|
|
#endif
|
|
return HOOK_DECLINED;
|
|
}
|