Annotation of embedaddon/libnet/src/libnet_cq.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:  *  $Id: libnet_cq.c,v 1.11 2004/01/28 19:45:00 mike 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: 
1.1.1.4 ! misho      34: #include "common.h"
1.1       misho      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: 
1.1.1.2   misho      46: static int
1.1.1.4 ! misho      47: set_cq_lock(uint32_t x) 
1.1       misho      48: {
                     49:     if (check_cq_lock(x))
                     50:     {
                     51:         return (0);
                     52:     }
                     53: 
                     54:     l_cqd.cq_lock |= x;
                     55:     return (1);
                     56: }
                     57: 
1.1.1.2   misho      58: static int
1.1.1.4 ! misho      59: clear_cq_lock(uint32_t x) 
1.1       misho      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,
1.1.1.4 ! misho      84:                 "%s(): can't add, context queue is write locked", __func__);
1.1       misho      85:         return (-1);
                     86:     }
                     87:   
                     88:     /* ensure there is a label */
                     89:     if (label == NULL)
                     90:     {
1.1.1.4 ! misho      91:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): empty label",
1.1       misho      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,
1.1.1.4 ! misho     103:                     "%s(): can't malloc initial context queue: %s",
1.1       misho     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);
1.1.1.2   misho     112:         l->label[LIBNET_LABEL_SIZE - 1] = '\0';
1.1       misho     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,
1.1.1.4 ! misho     134:                 "%s(): can't malloc new context queue: %s",
1.1       misho     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);
1.1.1.2   misho     143:     l->label[LIBNET_LABEL_SIZE -1] = '\0';
1.1       misho     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,
1.1.1.4 ! misho     166:                 "%s(): can't remove from empty context queue", __func__);
1.1       misho     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,
1.1.1.4 ! misho     179:                 "%s(): can't remove, context queue is write locked",
1.1       misho     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,
1.1.1.4 ! misho     187:                 "%s(): context not present in context queue", __func__);
1.1       misho     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,
1.1.1.4 ! misho     278:                 "%s(): context already in context queue", __func__);
1.1       misho     279:             return (1);
                    280:         }
                    281:         if (strncmp(p->context->label, label, LIBNET_LABEL_SIZE) == 0)
                    282:         {
                    283:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho     284:                     "%s(): duplicate label %s", __func__, label);
1.1       misho     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: 
1.1.1.2   misho     321: const char *
1.1       misho     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:     }
1.1.1.3   misho     340:     l_cq = NULL;
                    341:     memset(&l_cqd, 0, sizeof(l_cqd));
1.1       misho     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: 
1.1.1.2   misho     386: uint32_t
1.1       misho     387: libnet_cq_size()
                    388: {
                    389:     return (l_cqd.node);
                    390: }
1.1.1.2   misho     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: 
1.1.1.4 ! misho     403: /**
        !           404:  * Local Variables:
        !           405:  *  indent-tabs-mode: nil
        !           406:  *  c-file-style: "stroustrup"
        !           407:  * End:
        !           408:  */

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