diff options
author | Sam Roberts <sroberts@sroberts-desktop.(none)> | 2009-02-18 13:16:51 -0800 |
---|---|---|
committer | Sam Roberts <sroberts@sroberts-desktop.(none)> | 2009-02-18 13:16:51 -0800 |
commit | 4679d290c754e2ebd8299ef8abbd2b9e94e82abf (patch) | |
tree | 33ec442df1d6480da52961df7dd19cdd41d41fb5 /libnet/src/libnet_cq.c | |
parent | c35d5ad62a9b45153cf638272a3d590729728c12 (diff) | |
download | libnet-4679d290c754e2ebd8299ef8abbd2b9e94e82abf.tar.gz |
v1.1.2.1 from http://www.packetfactory.net/projects/libnet/
Diffstat (limited to 'libnet/src/libnet_cq.c')
-rw-r--r-- | libnet/src/libnet_cq.c | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/libnet/src/libnet_cq.c b/libnet/src/libnet_cq.c new file mode 100644 index 0000000..b5359f7 --- /dev/null +++ b/libnet/src/libnet_cq.c @@ -0,0 +1,395 @@ +/* + * $Id: libnet_cq.c,v 1.11 2004/01/28 19:45:00 mike Exp $ + * + * libnet + * libnet_cq.c - context queue management routines + * + * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com> + * Copyright (c) 2002 Frédéric Raynal <pappy@security-labs.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#if (HAVE_CONFIG_H) +#include "../include/config.h" +#endif +#if (!(_WIN32) || (__CYGWIN__)) +#include "../include/libnet.h" +#else +#include "../include/win32/libnet.h" +#endif + +/* private function prototypes */ +static libnet_cq_t *libnet_cq_find_internal(libnet_t *); +static int libnet_cq_dup_check(libnet_t *, char *); +static libnet_cq_t *libnet_cq_find_by_label_internal(char *label); + +/* global context queue */ +static libnet_cq_t *l_cq = NULL; +static libnet_cqd_t l_cqd = {0, CQ_LOCK_UNLOCKED, NULL}; + + +static inline int set_cq_lock(u_int x) +{ + if (check_cq_lock(x)) + { + return (0); + } + + l_cqd.cq_lock |= x; + return (1); +} + +static inline int clear_cq_lock(u_int x) +{ + if (!check_cq_lock(x)) + { + return (0); + } + + l_cqd.cq_lock &= ~x; + return (1); +} + +int +libnet_cq_add(libnet_t *l, char *label) +{ + libnet_cq_t *new; + + if (l == NULL) + { + return (-1); + } + + /* check for write lock on the context queue */ + if (cq_is_wlocked()) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): can't add, context queue is write locked\n", __func__); + return (-1); + } + + /* ensure there is a label */ + if (label == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): empty label\n", + __func__); + return (-1); + } + + /* check to see if we're the first node on the list */ + if (l_cq == NULL) + { + l_cq = (libnet_cq_t *)malloc(sizeof (libnet_cq_t)); + if (l_cq == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): can't malloc initial context queue: %s\n", + __func__, strerror(errno)); + return (-1); + } + + l_cq->context = l; + + /* label the context with the user specified string */ + strncpy(l->label, label, LIBNET_LABEL_SIZE); + l->label[LIBNET_LABEL_SIZE] = '\0'; + + l_cq->next = NULL; + l_cq->prev = NULL; + + /* track the number of nodes in the context queue */ + l_cqd.node = 1; + + return (1); + } + + /* check to see if the cq we're about to add is already in the list */ + if (libnet_cq_dup_check(l, label)) + { + /* error message set in libnet_cq_dup_check() */ + return (-1); + } + + new = (libnet_cq_t *)malloc(sizeof (libnet_cq_t)); + if (l_cq == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): can't malloc new context queue: %s\n", + __func__, strerror(errno)); + return (-1); + } + + new->context = l; + + /* label the context with the user specified string */ + strncpy(l->label, label, LIBNET_LABEL_SIZE); + l->label[LIBNET_LABEL_SIZE] = '\0'; + + new->next = l_cq; + new->prev = NULL; + + l_cq->prev = new; + l_cq = new; + + /* track the number of nodes in the context queue */ + l_cqd.node++; + + return (1); +} + +libnet_t * +libnet_cq_remove(libnet_t *l) +{ + libnet_cq_t *p; + libnet_t *ret; + + if (l_cq == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): can't remove from empty context queue\n", __func__); + return (NULL); + } + + if (l == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): can't remove empty libnet context\n", __func__); + return(NULL); + } + + /* check for write lock on the cq */ + if (cq_is_wlocked()) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): can't remove, context queue is write locked\n", + __func__); + return (NULL); + } + + if ((p = libnet_cq_find_internal(l)) == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): context not present in context queue\n", __func__); + return (NULL); + } + + if (p->prev) + { + p->prev->next = p->next; + } + else + { + l_cq = p->next; + } + if (p->next) + { + p->next->prev = p->prev; + } + + ret = p->context; + free(p); + + /* track the number of nodes in the cq */ + l_cqd.node--; + + return (ret); +} + +libnet_t * +libnet_cq_remove_by_label(char *label) +{ + libnet_cq_t *p; + libnet_t *ret; + + if ((p = libnet_cq_find_by_label_internal(label)) == NULL) + { + /* no context to write an error message */ + return (NULL); + } + + if (cq_is_wlocked()) + { + /* now we have a context, but the user can't see it */ + return (NULL); + } + + if (p->prev) + { + p->prev->next = p->next; + } + else + { + l_cq = p->next; + } + if (p->next) + { + p->next->prev = p->prev; + } + + ret = p->context; + free(p); + + /* track the number of nodes in the cq */ + l_cqd.node--; + + return (ret); +} + +libnet_cq_t * +libnet_cq_find_internal(libnet_t *l) +{ + libnet_cq_t *p; + + for (p = l_cq; p; p = p->next) + { + if (p->context == l) + { + return (p); + } + } + return (NULL); +} + +int +libnet_cq_dup_check(libnet_t *l, char *label) +{ + libnet_cq_t *p; + + for (p = l_cq; p; p = p->next) + { + if (p->context == l) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): context already in context queue\n", __func__); + return (1); + } + if (strncmp(p->context->label, label, LIBNET_LABEL_SIZE) == 0) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): duplicate label %s\n", __func__, label); + return (1); + } + } + /* no duplicate */ + return (0); +} + +libnet_cq_t * +libnet_cq_find_by_label_internal(char *label) +{ + libnet_cq_t *p; + + if (label == NULL) + { + return (NULL); + } + + for (p = l_cq; p; p = p->next) + { + if (!strncmp(p->context->label, label, LIBNET_LABEL_SIZE)) + { + return (p); + } + } + return (NULL); +} + +libnet_t * +libnet_cq_find_by_label(char *label) +{ + libnet_cq_t *p; + + p = libnet_cq_find_by_label_internal(label); + return (p ? p->context : NULL); +} + +int8_t * +libnet_cq_getlabel(libnet_t *l) +{ + return (l->label); +} + +void +libnet_cq_destroy() +{ + libnet_cq_t *p = l_cq; + libnet_cq_t *tmp; + + while (p) + { + tmp = p; + p = p->next; + libnet_destroy(tmp->context); + free(tmp); + } +} + +libnet_t * +libnet_cq_head() +{ + if (l_cq == NULL) + { + return (NULL); + } + + if (!set_cq_lock(CQ_LOCK_WRITE)) + { + return (NULL); + } + + l_cqd.current = l_cq; + return (l_cqd.current->context); +} + +int +libnet_cq_last() +{ + if (l_cqd.current) + { + return (1); + } + else + { + return (0); + } +} + +libnet_t * +libnet_cq_next() +{ + if (l_cqd.current == NULL) + { + return (NULL); + } + + l_cqd.current = l_cqd.current->next; + return (l_cqd.current ? l_cqd.current->context : NULL); +} + +u_int32_t +libnet_cq_size() +{ + return (l_cqd.node); +} |