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>