File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_cq.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:14:23 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /*
    2:  *  $Id: libnet_cq.c,v 1.1 2012/02/21 22:14:23 misho Exp $
    3:  *
    4:  *  libnet
    5:  *  libnet_cq.c - context queue management routines
    6:  *
    7:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
    8:  *  Copyright (c) 2002 Frédéric Raynal <pappy@security-labs.org>
    9:  *  All rights reserved.
   10:  *
   11:  * Redistribution and use in source and binary forms, with or without
   12:  * modification, are permitted provided that the following conditions
   13:  * are met:
   14:  * 1. Redistributions of source code must retain the above copyright
   15:  *    notice, this list of conditions and the following disclaimer.
   16:  * 2. Redistributions in binary form must reproduce the above copyright
   17:  *    notice, this list of conditions and the following disclaimer in the
   18:  *    documentation and/or other materials provided with the distribution.
   19:  *
   20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30:  * SUCH DAMAGE.
   31:  *
   32:  */
   33: 
   34: #if (HAVE_CONFIG_H)
   35: #include "../include/config.h"
   36: #endif
   37: #if (!(_WIN32) || (__CYGWIN__)) 
   38: #include "../include/libnet.h"
   39: #else
   40: #include "../include/win32/libnet.h"
   41: #endif
   42: 
   43: /* private function prototypes */
   44: static libnet_cq_t *libnet_cq_find_internal(libnet_t *);
   45: static int libnet_cq_dup_check(libnet_t *, char *);
   46: static libnet_cq_t *libnet_cq_find_by_label_internal(char *label);
   47: 
   48: /* global context queue */
   49: static libnet_cq_t *l_cq = NULL;
   50: static libnet_cqd_t l_cqd = {0, CQ_LOCK_UNLOCKED, NULL};
   51: 
   52: 
   53: static inline int set_cq_lock(u_int x) 
   54: {
   55:     if (check_cq_lock(x))
   56:     {
   57:         return (0);
   58:     }
   59: 
   60:     l_cqd.cq_lock |= x;
   61:     return (1);
   62: }
   63: 
   64: static inline int clear_cq_lock(u_int x) 
   65: {
   66:     if (!check_cq_lock(x))
   67:     {
   68:         return (0);
   69:     }
   70: 
   71:     l_cqd.cq_lock &= ~x;
   72:     return (1);
   73: }
   74: 
   75: int 
   76: libnet_cq_add(libnet_t *l, char *label)
   77: {
   78:     libnet_cq_t *new;
   79: 
   80:     if (l == NULL) 
   81:     {
   82:         return (-1);
   83:     }
   84: 
   85:     /* check for write lock on the context queue */
   86:     if (cq_is_wlocked()) 
   87:     {
   88:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
   89:                 "%s(): can't add, context queue is write locked\n", __func__);
   90:         return (-1);
   91:     }
   92:   
   93:     /* ensure there is a label */
   94:     if (label == NULL)
   95:     {
   96:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): empty label\n",
   97:                 __func__);
   98:         return (-1);
   99:     }
  100: 
  101:     /* check to see if we're the first node on the list */
  102:     if (l_cq == NULL)
  103:     {
  104:         l_cq = (libnet_cq_t *)malloc(sizeof (libnet_cq_t));
  105:         if (l_cq == NULL)
  106:         {
  107:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  108:                     "%s(): can't malloc initial context queue: %s\n",
  109:                     __func__, strerror(errno));
  110:             return (-1);
  111:         }
  112: 
  113:         l_cq->context = l;
  114: 
  115:         /* label the context with the user specified string */
  116:         strncpy(l->label, label, LIBNET_LABEL_SIZE);
  117:         l->label[LIBNET_LABEL_SIZE] = '\0';
  118: 
  119:         l_cq->next = NULL;
  120:         l_cq->prev = NULL;
  121: 
  122:         /* track the number of nodes in the context queue */
  123:         l_cqd.node = 1;
  124: 
  125:         return (1);
  126:     }
  127: 
  128:     /* check to see if the cq we're about to add is already in the list */
  129:     if (libnet_cq_dup_check(l, label)) 
  130:     {
  131:         /* error message set in libnet_cq_dup_check() */
  132:         return (-1);
  133:     }
  134: 
  135:     new = (libnet_cq_t *)malloc(sizeof (libnet_cq_t));
  136:     if (l_cq == NULL)
  137:     {
  138:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  139:                 "%s(): can't malloc new context queue: %s\n",
  140:                 __func__, strerror(errno));
  141:         return (-1);
  142:     }
  143: 
  144:     new->context = l;
  145: 
  146:     /* label the context with the user specified string */
  147:     strncpy(l->label, label, LIBNET_LABEL_SIZE);
  148:     l->label[LIBNET_LABEL_SIZE] = '\0';
  149: 
  150:     new->next = l_cq;
  151:     new->prev = NULL;
  152: 
  153:     l_cq->prev = new;
  154:     l_cq = new;
  155: 
  156:     /* track the number of nodes in the context queue */
  157:     l_cqd.node++;
  158: 
  159:     return (1); 
  160: }
  161: 
  162: libnet_t *
  163: libnet_cq_remove(libnet_t *l) 
  164: {
  165:     libnet_cq_t *p;
  166:     libnet_t *ret;
  167: 
  168:     if (l_cq == NULL) 
  169:     {
  170:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  171:                 "%s(): can't remove from empty context queue\n", __func__);
  172:         return (NULL);
  173:     }
  174: 
  175:     if (l == NULL)
  176:     {
  177:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  178:                 "%s(): can't remove empty libnet context\n", __func__);
  179:         return(NULL);
  180:     }
  181: 
  182:     /* check for write lock on the cq */
  183:     if (cq_is_wlocked()) 
  184:     {
  185:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  186:                 "%s(): can't remove, context queue is write locked\n",
  187:                 __func__);
  188:         return (NULL);
  189:     }
  190:   
  191:     if ((p = libnet_cq_find_internal(l)) == NULL)
  192:     {
  193:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  194:                 "%s(): context not present in context queue\n", __func__);
  195:         return (NULL);
  196:     }
  197: 
  198:     if (p->prev) 
  199:     {
  200:         p->prev->next = p->next;
  201:     }
  202:     else
  203:     {
  204:         l_cq = p->next;
  205:     }
  206:     if (p->next)
  207:     {
  208:         p->next->prev = p->prev;
  209:     }
  210: 
  211:     ret = p->context;
  212:     free(p);
  213: 
  214:     /* track the number of nodes in the cq */
  215:     l_cqd.node--;
  216:   
  217:     return (ret);
  218: }
  219: 
  220: libnet_t *
  221: libnet_cq_remove_by_label(char *label) 
  222: {
  223:     libnet_cq_t *p;
  224:     libnet_t *ret;
  225: 
  226:     if ((p = libnet_cq_find_by_label_internal(label)) == NULL)
  227:     {
  228:         /* no context to write an error message */
  229:         return (NULL);
  230:     }
  231: 
  232:     if (cq_is_wlocked()) 
  233:     {
  234:         /* now we have a context, but the user can't see it */
  235:         return (NULL);
  236:     }
  237: 
  238:     if (p->prev) 
  239:     {
  240:         p->prev->next = p->next;
  241:     }
  242:     else
  243:     {
  244:         l_cq = p->next;
  245:     }
  246:     if (p->next)
  247:     {
  248:         p->next->prev = p->prev;
  249:     }
  250: 
  251:     ret = p->context;
  252:     free(p);
  253: 
  254:     /* track the number of nodes in the cq */
  255:     l_cqd.node--;
  256:   
  257:     return (ret);
  258: }
  259: 
  260: libnet_cq_t *
  261: libnet_cq_find_internal(libnet_t *l) 
  262: {
  263:     libnet_cq_t *p;
  264: 
  265:     for (p = l_cq; p; p = p->next)
  266:     {
  267:         if (p->context == l)
  268:         {
  269:             return (p);
  270:         }
  271:     }
  272:     return (NULL);
  273: }
  274: 
  275: int
  276: libnet_cq_dup_check(libnet_t *l, char *label)
  277: {
  278:     libnet_cq_t *p;
  279: 
  280:     for (p = l_cq; p; p = p->next)
  281:     {
  282:         if (p->context == l)
  283:         {
  284:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  285:                 "%s(): context already in context queue\n", __func__);
  286:             return (1);
  287:         }
  288:         if (strncmp(p->context->label, label, LIBNET_LABEL_SIZE) == 0)
  289:         {
  290:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  291:                     "%s(): duplicate label %s\n", __func__, label);
  292:             return (1);
  293:         }
  294:     }
  295:     /* no duplicate */
  296:     return (0);
  297: }
  298: 
  299: libnet_cq_t *
  300: libnet_cq_find_by_label_internal(char *label) 
  301: {
  302:     libnet_cq_t *p;
  303:   
  304:     if (label == NULL)
  305:     {
  306:         return (NULL);
  307:     }
  308: 
  309:     for (p = l_cq; p; p = p->next)
  310:     {
  311:         if (!strncmp(p->context->label, label, LIBNET_LABEL_SIZE))
  312:         {
  313:             return (p);
  314:         }
  315:     }
  316:     return (NULL);
  317: }
  318: 
  319: libnet_t *
  320: libnet_cq_find_by_label(char *label)
  321: {
  322:     libnet_cq_t *p;
  323:   
  324:     p = libnet_cq_find_by_label_internal(label);
  325:     return (p ? p->context : NULL);
  326: }
  327: 
  328: int8_t *
  329: libnet_cq_getlabel(libnet_t *l)
  330: {
  331:     return (l->label);
  332: }
  333: 
  334: void
  335: libnet_cq_destroy() 
  336: {
  337:     libnet_cq_t *p = l_cq;
  338:     libnet_cq_t *tmp;
  339: 
  340:     while (p)
  341:     {
  342:         tmp = p;
  343:         p = p->next;
  344:         libnet_destroy(tmp->context);
  345:         free(tmp);
  346:     }
  347: }
  348: 
  349: libnet_t *
  350: libnet_cq_head()
  351: {
  352:     if (l_cq == NULL) 
  353:     {
  354:         return (NULL);
  355:     }
  356: 
  357:     if (!set_cq_lock(CQ_LOCK_WRITE)) 
  358:     {
  359:         return (NULL);
  360:     }
  361: 
  362:     l_cqd.current = l_cq;
  363:     return (l_cqd.current->context);
  364: }
  365: 
  366: int
  367: libnet_cq_last()
  368: {
  369:     if (l_cqd.current)
  370:     {
  371:         return (1);
  372:     }
  373:     else
  374:     {
  375:         return (0);
  376:     }
  377: }
  378: 
  379: libnet_t *
  380: libnet_cq_next()
  381: {
  382:     if (l_cqd.current == NULL)
  383:     {
  384:         return (NULL);
  385:     }
  386: 
  387:     l_cqd.current = l_cqd.current->next;
  388:     return (l_cqd.current ? l_cqd.current->context : NULL);
  389: }
  390: 
  391: u_int32_t
  392: libnet_cq_size()
  393: {
  394:     return (l_cqd.node);
  395: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>