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>