Annotation of embedaddon/libnet/src/libnet_cq.c, revision 1.1.1.3
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:
1.1.1.2 misho 53: static int
54: set_cq_lock(uint x)
1.1 misho 55: {
56: if (check_cq_lock(x))
57: {
58: return (0);
59: }
60:
61: l_cqd.cq_lock |= x;
62: return (1);
63: }
64:
1.1.1.2 misho 65: static int
66: clear_cq_lock(uint x)
1.1 misho 67: {
68: if (!check_cq_lock(x))
69: {
70: return (0);
71: }
72:
73: l_cqd.cq_lock &= ~x;
74: return (1);
75: }
76:
77: int
78: libnet_cq_add(libnet_t *l, char *label)
79: {
80: libnet_cq_t *new;
81:
82: if (l == NULL)
83: {
84: return (-1);
85: }
86:
87: /* check for write lock on the context queue */
88: if (cq_is_wlocked())
89: {
90: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
91: "%s(): can't add, context queue is write locked\n", __func__);
92: return (-1);
93: }
94:
95: /* ensure there is a label */
96: if (label == NULL)
97: {
98: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): empty label\n",
99: __func__);
100: return (-1);
101: }
102:
103: /* check to see if we're the first node on the list */
104: if (l_cq == NULL)
105: {
106: l_cq = (libnet_cq_t *)malloc(sizeof (libnet_cq_t));
107: if (l_cq == NULL)
108: {
109: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
110: "%s(): can't malloc initial context queue: %s\n",
111: __func__, strerror(errno));
112: return (-1);
113: }
114:
115: l_cq->context = l;
116:
117: /* label the context with the user specified string */
118: strncpy(l->label, label, LIBNET_LABEL_SIZE);
1.1.1.2 misho 119: l->label[LIBNET_LABEL_SIZE - 1] = '\0';
1.1 misho 120:
121: l_cq->next = NULL;
122: l_cq->prev = NULL;
123:
124: /* track the number of nodes in the context queue */
125: l_cqd.node = 1;
126:
127: return (1);
128: }
129:
130: /* check to see if the cq we're about to add is already in the list */
131: if (libnet_cq_dup_check(l, label))
132: {
133: /* error message set in libnet_cq_dup_check() */
134: return (-1);
135: }
136:
137: new = (libnet_cq_t *)malloc(sizeof (libnet_cq_t));
138: if (l_cq == NULL)
139: {
140: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
141: "%s(): can't malloc new context queue: %s\n",
142: __func__, strerror(errno));
143: return (-1);
144: }
145:
146: new->context = l;
147:
148: /* label the context with the user specified string */
149: strncpy(l->label, label, LIBNET_LABEL_SIZE);
1.1.1.2 misho 150: l->label[LIBNET_LABEL_SIZE -1] = '\0';
1.1 misho 151:
152: new->next = l_cq;
153: new->prev = NULL;
154:
155: l_cq->prev = new;
156: l_cq = new;
157:
158: /* track the number of nodes in the context queue */
159: l_cqd.node++;
160:
161: return (1);
162: }
163:
164: libnet_t *
165: libnet_cq_remove(libnet_t *l)
166: {
167: libnet_cq_t *p;
168: libnet_t *ret;
169:
170: if (l_cq == NULL)
171: {
172: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
173: "%s(): can't remove from empty context queue\n", __func__);
174: return (NULL);
175: }
176:
177: if (l == NULL)
178: {
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:
1.1.1.2 misho 328: const char *
1.1 misho 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: }
1.1.1.3 ! misho 347: l_cq = NULL;
! 348: memset(&l_cqd, 0, sizeof(l_cqd));
1.1 misho 349: }
350:
351: libnet_t *
352: libnet_cq_head()
353: {
354: if (l_cq == NULL)
355: {
356: return (NULL);
357: }
358:
359: if (!set_cq_lock(CQ_LOCK_WRITE))
360: {
361: return (NULL);
362: }
363:
364: l_cqd.current = l_cq;
365: return (l_cqd.current->context);
366: }
367:
368: int
369: libnet_cq_last()
370: {
371: if (l_cqd.current)
372: {
373: return (1);
374: }
375: else
376: {
377: return (0);
378: }
379: }
380:
381: libnet_t *
382: libnet_cq_next()
383: {
384: if (l_cqd.current == NULL)
385: {
386: return (NULL);
387: }
388:
389: l_cqd.current = l_cqd.current->next;
390: return (l_cqd.current ? l_cqd.current->context : NULL);
391: }
392:
1.1.1.2 misho 393: uint32_t
1.1 misho 394: libnet_cq_size()
395: {
396: return (l_cqd.node);
397: }
1.1.1.2 misho 398:
399: uint32_t
400: libnet_cq_end_loop()
401: {
402: if (! clear_cq_lock(CQ_LOCK_WRITE))
403: {
404: return (0);
405: }
406: l_cqd.current = l_cq;
407: return (1);
408: }
409:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>