File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_cq.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (9 months, 2 weeks ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    1: /*
    2:  *  $Id: libnet_cq.c,v 1.1.1.4 2023/09/27 11:11:38 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: #include "common.h"
   35: 
   36: /* private function prototypes */
   37: static libnet_cq_t *libnet_cq_find_internal(libnet_t *);
   38: static int libnet_cq_dup_check(libnet_t *, char *);
   39: static libnet_cq_t *libnet_cq_find_by_label_internal(char *label);
   40: 
   41: /* global context queue */
   42: static libnet_cq_t *l_cq = NULL;
   43: static libnet_cqd_t l_cqd = {0, CQ_LOCK_UNLOCKED, NULL};
   44: 
   45: 
   46: static int
   47: set_cq_lock(uint32_t x) 
   48: {
   49:     if (check_cq_lock(x))
   50:     {
   51:         return (0);
   52:     }
   53: 
   54:     l_cqd.cq_lock |= x;
   55:     return (1);
   56: }
   57: 
   58: static int
   59: clear_cq_lock(uint32_t x) 
   60: {
   61:     if (!check_cq_lock(x))
   62:     {
   63:         return (0);
   64:     }
   65: 
   66:     l_cqd.cq_lock &= ~x;
   67:     return (1);
   68: }
   69: 
   70: int 
   71: libnet_cq_add(libnet_t *l, char *label)
   72: {
   73:     libnet_cq_t *new;
   74: 
   75:     if (l == NULL) 
   76:     {
   77:         return (-1);
   78:     }
   79: 
   80:     /* check for write lock on the context queue */
   81:     if (cq_is_wlocked()) 
   82:     {
   83:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
   84:                 "%s(): can't add, context queue is write locked", __func__);
   85:         return (-1);
   86:     }
   87:   
   88:     /* ensure there is a label */
   89:     if (label == NULL)
   90:     {
   91:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): empty label",
   92:                 __func__);
   93:         return (-1);
   94:     }
   95: 
   96:     /* check to see if we're the first node on the list */
   97:     if (l_cq == NULL)
   98:     {
   99:         l_cq = (libnet_cq_t *)malloc(sizeof (libnet_cq_t));
  100:         if (l_cq == NULL)
  101:         {
  102:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  103:                     "%s(): can't malloc initial context queue: %s",
  104:                     __func__, strerror(errno));
  105:             return (-1);
  106:         }
  107: 
  108:         l_cq->context = l;
  109: 
  110:         /* label the context with the user specified string */
  111:         strncpy(l->label, label, LIBNET_LABEL_SIZE);
  112:         l->label[LIBNET_LABEL_SIZE - 1] = '\0';
  113: 
  114:         l_cq->next = NULL;
  115:         l_cq->prev = NULL;
  116: 
  117:         /* track the number of nodes in the context queue */
  118:         l_cqd.node = 1;
  119: 
  120:         return (1);
  121:     }
  122: 
  123:     /* check to see if the cq we're about to add is already in the list */
  124:     if (libnet_cq_dup_check(l, label)) 
  125:     {
  126:         /* error message set in libnet_cq_dup_check() */
  127:         return (-1);
  128:     }
  129: 
  130:     new = (libnet_cq_t *)malloc(sizeof (libnet_cq_t));
  131:     if (l_cq == NULL)
  132:     {
  133:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  134:                 "%s(): can't malloc new context queue: %s",
  135:                 __func__, strerror(errno));
  136:         return (-1);
  137:     }
  138: 
  139:     new->context = l;
  140: 
  141:     /* label the context with the user specified string */
  142:     strncpy(l->label, label, LIBNET_LABEL_SIZE);
  143:     l->label[LIBNET_LABEL_SIZE -1] = '\0';
  144: 
  145:     new->next = l_cq;
  146:     new->prev = NULL;
  147: 
  148:     l_cq->prev = new;
  149:     l_cq = new;
  150: 
  151:     /* track the number of nodes in the context queue */
  152:     l_cqd.node++;
  153: 
  154:     return (1); 
  155: }
  156: 
  157: libnet_t *
  158: libnet_cq_remove(libnet_t *l) 
  159: {
  160:     libnet_cq_t *p;
  161:     libnet_t *ret;
  162: 
  163:     if (l_cq == NULL) 
  164:     {
  165:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  166:                 "%s(): can't remove from empty context queue", __func__);
  167:         return (NULL);
  168:     }
  169: 
  170:     if (l == NULL)
  171:     {
  172:         return(NULL);
  173:     }
  174: 
  175:     /* check for write lock on the cq */
  176:     if (cq_is_wlocked()) 
  177:     {
  178:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  179:                 "%s(): can't remove, context queue is write locked",
  180:                 __func__);
  181:         return (NULL);
  182:     }
  183:   
  184:     if ((p = libnet_cq_find_internal(l)) == NULL)
  185:     {
  186:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  187:                 "%s(): context not present in context queue", __func__);
  188:         return (NULL);
  189:     }
  190: 
  191:     if (p->prev) 
  192:     {
  193:         p->prev->next = p->next;
  194:     }
  195:     else
  196:     {
  197:         l_cq = p->next;
  198:     }
  199:     if (p->next)
  200:     {
  201:         p->next->prev = p->prev;
  202:     }
  203: 
  204:     ret = p->context;
  205:     free(p);
  206: 
  207:     /* track the number of nodes in the cq */
  208:     l_cqd.node--;
  209:   
  210:     return (ret);
  211: }
  212: 
  213: libnet_t *
  214: libnet_cq_remove_by_label(char *label) 
  215: {
  216:     libnet_cq_t *p;
  217:     libnet_t *ret;
  218: 
  219:     if ((p = libnet_cq_find_by_label_internal(label)) == NULL)
  220:     {
  221:         /* no context to write an error message */
  222:         return (NULL);
  223:     }
  224: 
  225:     if (cq_is_wlocked()) 
  226:     {
  227:         /* now we have a context, but the user can't see it */
  228:         return (NULL);
  229:     }
  230: 
  231:     if (p->prev) 
  232:     {
  233:         p->prev->next = p->next;
  234:     }
  235:     else
  236:     {
  237:         l_cq = p->next;
  238:     }
  239:     if (p->next)
  240:     {
  241:         p->next->prev = p->prev;
  242:     }
  243: 
  244:     ret = p->context;
  245:     free(p);
  246: 
  247:     /* track the number of nodes in the cq */
  248:     l_cqd.node--;
  249:   
  250:     return (ret);
  251: }
  252: 
  253: libnet_cq_t *
  254: libnet_cq_find_internal(libnet_t *l) 
  255: {
  256:     libnet_cq_t *p;
  257: 
  258:     for (p = l_cq; p; p = p->next)
  259:     {
  260:         if (p->context == l)
  261:         {
  262:             return (p);
  263:         }
  264:     }
  265:     return (NULL);
  266: }
  267: 
  268: int
  269: libnet_cq_dup_check(libnet_t *l, char *label)
  270: {
  271:     libnet_cq_t *p;
  272: 
  273:     for (p = l_cq; p; p = p->next)
  274:     {
  275:         if (p->context == l)
  276:         {
  277:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  278:                 "%s(): context already in context queue", __func__);
  279:             return (1);
  280:         }
  281:         if (strncmp(p->context->label, label, LIBNET_LABEL_SIZE) == 0)
  282:         {
  283:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  284:                     "%s(): duplicate label %s", __func__, label);
  285:             return (1);
  286:         }
  287:     }
  288:     /* no duplicate */
  289:     return (0);
  290: }
  291: 
  292: libnet_cq_t *
  293: libnet_cq_find_by_label_internal(char *label) 
  294: {
  295:     libnet_cq_t *p;
  296:   
  297:     if (label == NULL)
  298:     {
  299:         return (NULL);
  300:     }
  301: 
  302:     for (p = l_cq; p; p = p->next)
  303:     {
  304:         if (!strncmp(p->context->label, label, LIBNET_LABEL_SIZE))
  305:         {
  306:             return (p);
  307:         }
  308:     }
  309:     return (NULL);
  310: }
  311: 
  312: libnet_t *
  313: libnet_cq_find_by_label(char *label)
  314: {
  315:     libnet_cq_t *p;
  316:   
  317:     p = libnet_cq_find_by_label_internal(label);
  318:     return (p ? p->context : NULL);
  319: }
  320: 
  321: const char *
  322: libnet_cq_getlabel(libnet_t *l)
  323: {
  324:     return (l->label);
  325: }
  326: 
  327: void
  328: libnet_cq_destroy() 
  329: {
  330:     libnet_cq_t *p = l_cq;
  331:     libnet_cq_t *tmp;
  332: 
  333:     while (p)
  334:     {
  335:         tmp = p;
  336:         p = p->next;
  337:         libnet_destroy(tmp->context);
  338:         free(tmp);
  339:     }
  340:     l_cq = NULL;
  341:     memset(&l_cqd, 0, sizeof(l_cqd));
  342: }
  343: 
  344: libnet_t *
  345: libnet_cq_head()
  346: {
  347:     if (l_cq == NULL) 
  348:     {
  349:         return (NULL);
  350:     }
  351: 
  352:     if (!set_cq_lock(CQ_LOCK_WRITE)) 
  353:     {
  354:         return (NULL);
  355:     }
  356: 
  357:     l_cqd.current = l_cq;
  358:     return (l_cqd.current->context);
  359: }
  360: 
  361: int
  362: libnet_cq_last()
  363: {
  364:     if (l_cqd.current)
  365:     {
  366:         return (1);
  367:     }
  368:     else
  369:     {
  370:         return (0);
  371:     }
  372: }
  373: 
  374: libnet_t *
  375: libnet_cq_next()
  376: {
  377:     if (l_cqd.current == NULL)
  378:     {
  379:         return (NULL);
  380:     }
  381: 
  382:     l_cqd.current = l_cqd.current->next;
  383:     return (l_cqd.current ? l_cqd.current->context : NULL);
  384: }
  385: 
  386: uint32_t
  387: libnet_cq_size()
  388: {
  389:     return (l_cqd.node);
  390: }
  391: 
  392: uint32_t
  393: libnet_cq_end_loop()
  394: {
  395:     if (! clear_cq_lock(CQ_LOCK_WRITE))
  396:     {
  397:         return (0);
  398:     }
  399:     l_cqd.current = l_cq;
  400:     return (1);
  401: }
  402: 
  403: /**
  404:  * Local Variables:
  405:  *  indent-tabs-mode: nil
  406:  *  c-file-style: "stroustrup"
  407:  * End:
  408:  */

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