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

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: 
                     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>