Annotation of embedaddon/libnet/src/libnet_cq.c, revision 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>