OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / Libnet / src / libnet_port_list.c
1 /*
2  *  $Id: libnet_port_list.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
3  *
4  *  libnet
5  *  libnet_port_list.c - transport layer port list chaining code
6  *
7  *  Copyright (c) 1998 - 2001 Mike D. Schiffman <mike@infonexus.com>
8  *  All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  */
32
33 #if (HAVE_CONFIG_H)
34 #include "../include/config.h"
35 #endif
36 #include "../include/libnet.h"
37
38 u_short *all_lists;
39
40 int
41 libnet_plist_chain_new(struct libnet_plist_chain **head, char *tok_list)
42 {
43     char libnet_plist_legal_tokens[] = "0123456789,- ";
44     struct libnet_plist_chain *tmp;
45     char *tok;
46     int i, j, valid_token, cur_node;
47     static u_char cur_id;
48
49     if (!tok_list)
50     {
51         return (-1);
52     }
53
54     /*
55      *  Make sure we have legal tokens.
56      */
57     for (i = 0; tok_list[i]; i++)
58     {
59         for (j = 0, valid_token = 0; libnet_plist_legal_tokens[j]; j++)
60         {
61             if (libnet_plist_legal_tokens[j] == tok_list[i])
62             {
63                 valid_token = 1;
64                 break;
65             }
66         }
67         if (!valid_token)
68         {
69 #if (__DEBUG)
70             libnet_error(LIBNET_ERR_CRITICAL,
71                     "libnet_build_plist_chain: illegal token # %d (%c)\n",
72                     i + 1,
73                     tok_list[i]);
74 #endif
75             *head = NULL;
76             return (-1);
77         }
78     }
79
80     /*
81      *  Head node.
82      */
83     *head = 
84         (struct libnet_plist_chain *)malloc(sizeof(struct libnet_plist_chain));
85
86     if (!(*head))
87     {
88 #if (__DEBUG)
89         perror("libnet_build_plist_chain: malloc");
90 #endif
91         *head = NULL;
92         return(-1);
93     }
94
95     tmp = *head;
96     tmp->node = cur_node = 0;
97     tmp->next = NULL;
98     tmp->id = cur_id;
99     all_lists = realloc(all_lists, (sizeof(u_short) * (cur_id + 1)));
100     if (!all_lists)
101     {
102 #if (__DEBUG)
103         perror("libnet_build_plist_chain: realloc");
104 #endif
105         *head = NULL;
106         return(-1);
107     }
108
109     all_lists[cur_id++] = 0;
110
111     /*
112      *  Using strtok successively proved problematic.  We solve this by
113      *  calling it once, then manually extracting the elements from the token.
114      *  In the case of bport > eport, we swap them.
115      */
116     for (i = 0; (tok = strtok(!i ? tok_list : NULL, ",")); i = 1, cur_node++)
117     {
118         /*
119          *  The first iteration we will have a head node allocated so we don't
120          *  need to malloc().
121          */
122         if (i)
123         {
124             tmp->next = (struct libnet_plist_chain *)
125                         malloc(sizeof(struct libnet_plist_chain));
126             if (!tmp)
127             {
128 #if (__DEBUG)
129                 perror("libnet_build_plist_chain: malloc");
130 #endif
131                 /*
132                  *  XXX - potential memory leak if other nodes are allocated
133                  *  but not freed.
134                  */
135                 *head = NULL;
136                 return(-1);
137             }
138             tmp = tmp->next;
139             tmp->node = cur_node;
140             tmp->next = NULL;
141         }
142         tmp->bport = atoi(tok);
143
144         /*
145          *  Step past this port number.
146          */
147         j = 0;
148         while (isdigit((int)tok[j]))
149         {
150             j++;
151         }
152
153         /*
154          *  If we have a delimiting dash and are NOT at the end of the token
155          *  array, we can assume it's the end port, otherwise if we just have
156          *  a dash, we consider it shorthand for `inclusive of all ports up to
157          *  65535.  Finally, if we have no dash, we assume this token is a
158          *  single port only.
159          */
160         if (tok[j] == '-')
161         {
162             tmp->eport = (++j != strlen(tok)) ? atoi(&tok[j]) : 65535;
163         }
164         else
165         {
166             tmp->eport = tmp->bport;
167         }
168
169         /*
170          *  Do we need to swap the values?
171          */
172         if (tmp->bport > tmp->eport)
173         {
174             tmp->bport ^= tmp->eport;
175             tmp->eport ^= tmp->bport;
176             tmp->bport ^= tmp->eport;
177         }
178     }
179
180     /*
181      *  The head node needs to hold the total node count.
182      */
183     (*head)->node = cur_node;
184     return (1);
185 }
186
187
188 int
189 libnet_plist_chain_next_pair(struct libnet_plist_chain *p, u_short *bport,
190         u_short *eport)
191 {
192     u_short *node_cnt;
193     u_short tmp_cnt;
194
195     node_cnt = &(all_lists[p->id]);
196     if (!p)
197     {
198         return (-1);
199     }
200
201     /*
202      *  We are at the end of the list.
203      */
204     if (*node_cnt == p->node)
205     {
206         *node_cnt = 0;
207         *bport = 0;
208         *eport = 0;
209         return (0);
210     }
211
212     for (tmp_cnt = *node_cnt; tmp_cnt; tmp_cnt--, p = p->next) ;
213     *bport = p->bport;
214     *eport = p->eport;
215     *node_cnt += 1;
216     return (1);
217 }
218
219
220 int
221 libnet_plist_chain_dump(struct libnet_plist_chain *p)
222 {
223     if (!p)
224     {
225         return (-1);
226     }
227
228     for (; p; p = p->next)
229     {
230         if (p->bport == p->eport)
231         {
232             fprintf(stdout, "%d ", p->bport);
233         }
234         else
235         {
236             fprintf(stdout, "%d-%d ", p->bport, p->eport);
237         }
238     }
239     fprintf(stdout, "\n");
240     return (1);
241 }
242
243
244 u_char *
245 libnet_plist_chain_dump_string(struct libnet_plist_chain *p)
246 {
247     u_char buf[BUFSIZ] = {0};
248     int i, j;
249
250     if (!p)
251     {
252         return (NULL);
253     }
254
255     for (i = 0, j = 0; p; p = p->next)
256     {
257         if (p->bport == p->eport)
258         {
259             i = sprintf(&buf[j], "%d", p->bport);
260         }
261         else
262         {
263             i = sprintf(&buf[j], "%d-%d", p->bport, p->eport);
264         }
265         j += i;
266         if (p->next)
267         {
268             sprintf(&buf[j++], ",");
269         }
270     }
271     return (strdup(buf));       /* XXX - reentrancy == no */
272 }
273
274
275 int
276 libnet_plist_chain_free(struct libnet_plist_chain *p)
277 {
278     u_short i;
279     struct libnet_plist_chain *tmp;
280
281     if (!p)
282     {
283         return (-1);
284     }
285
286     for (i = p->node; i; i--)
287     {
288         tmp = p;
289         p = p->next;
290         free(tmp);
291     }
292     p = NULL;
293     return (1);
294 }
295
296
297 /* EOF */