/[dynamips]/trunk/net_io_filter.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/net_io_filter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 7438 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * NetIO Filtering.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <signal.h>
15 #include <fcntl.h>
16 #include <ctype.h>
17 #include <time.h>
18 #include <sys/time.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <sys/wait.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <netdb.h>
28 #include <pthread.h>
29
30 #ifdef GEN_ETH
31 #include <pcap.h>
32 #endif
33
34 #include "registry.h"
35 #include "net.h"
36 #include "net_io.h"
37 #include "net_io_filter.h"
38
39 /* Filter list */
40 static netio_pktfilter_t *pf_list = NULL;
41
42 /* Find a filter */
43 netio_pktfilter_t *netio_filter_find(char *name)
44 {
45 netio_pktfilter_t *pf;
46
47 for(pf=pf_list;pf;pf=pf->next)
48 if (!strcmp(pf->name,name))
49 return pf;
50
51 return NULL;
52 }
53
54 /* Add a new filter */
55 int netio_filter_add(netio_pktfilter_t *pf)
56 {
57 if (netio_filter_find(pf->name) != NULL)
58 return(-1);
59
60 pf->next = pf_list;
61 pf_list = pf;
62 return(0);
63 }
64
65 /* Bind a filter to a NIO */
66 int netio_filter_bind(netio_desc_t *nio,int direction,char *pf_name)
67 {
68 netio_pktfilter_t *pf;
69
70 if (!(pf = netio_filter_find(pf_name)))
71 return(-1);
72
73 if (direction == NETIO_FILTER_DIR_RX) {
74 nio->rx_filter_data = NULL;
75 nio->rx_filter = pf;
76 } else if (direction == NETIO_FILTER_DIR_TX) {
77 nio->tx_filter_data = NULL;
78 nio->tx_filter = pf;
79 } else {
80 nio->both_filter_data = NULL;
81 nio->both_filter = pf;
82 }
83 return(0);
84 }
85
86 /* Unbind a filter from a NIO */
87 int netio_filter_unbind(netio_desc_t *nio,int direction)
88 {
89 netio_pktfilter_t *pf;
90 void **opt;
91
92 if (direction == NETIO_FILTER_DIR_RX) {
93 opt = &nio->rx_filter_data;
94 pf = nio->rx_filter;
95 } else if (direction == NETIO_FILTER_DIR_TX) {
96 opt = &nio->tx_filter_data;
97 pf = nio->tx_filter;
98 } else {
99 opt = &nio->both_filter_data;
100 pf = nio->both_filter;
101 }
102
103 if (!pf)
104 return(-1);
105
106 pf->free(nio,opt);
107 return(0);
108 }
109
110 /* Setup a filter */
111 int netio_filter_setup(netio_desc_t *nio,int direction,int argc,char *argv[])
112 {
113 netio_pktfilter_t *pf;
114 void **opt;
115
116 if (direction == NETIO_FILTER_DIR_RX) {
117 opt = &nio->rx_filter_data;
118 pf = nio->rx_filter;
119 } else if (direction == NETIO_FILTER_DIR_TX) {
120 opt = &nio->tx_filter_data;
121 pf = nio->tx_filter;
122 } else {
123 opt = &nio->both_filter_data;
124 pf = nio->both_filter;
125 }
126
127 if (!pf)
128 return(-1);
129
130 return(pf->setup(nio,opt,argc,argv));
131 }
132
133 /* ======================================================================== */
134 /* Packet Capture ("capture") */
135 /* GFA */
136 /* ======================================================================== */
137 #ifdef GEN_ETH
138
139 /* Free resources used by filter */
140 static void pf_capture_free(netio_desc_t *nio,void **opt)
141 {
142 struct netio_filter_capture *c = *opt;
143
144 if (c != NULL) {
145 printf("NIO %s: ending packet capture.\n",nio->name);
146
147 /* Close dumper */
148 if (c->dumper)
149 pcap_dump_close(c->dumper);
150
151 /* Close PCAP descriptor */
152 if (c->desc)
153 pcap_close(c->desc);
154
155 free(c);
156 *opt = NULL;
157 }
158 }
159
160 /* Setup filter resources */
161 static int pf_capture_setup(netio_desc_t *nio,void **opt,
162 int argc,char *argv[])
163 {
164 struct netio_filter_capture *c;
165 int link_type;
166
167 /* We must have a link type and a filename */
168 if (argc != 2)
169 return(-1);
170
171 /* Free resources if something has already been done */
172 pf_capture_free(nio,opt);
173
174 /* Allocate structure to hold PCAP info */
175 if (!(c = malloc(sizeof(*c))))
176 return(-1);
177
178 if ((link_type = pcap_datalink_name_to_val(argv[0])) == -1) {
179 fprintf(stderr,"NIO %s: unknown link type %s, assuming Ethernet.\n",
180 nio->name,argv[0]);
181 link_type = DLT_EN10MB;
182 }
183
184 /* Open a dead pcap descriptor */
185 if (!(c->desc = pcap_open_dead(link_type,8192))) {
186 fprintf(stderr,"NIO %s: pcap_open_dead failure\n",nio->name);
187 goto pcap_open_err;
188 }
189
190 /* Open the output file */
191 if (!(c->dumper = pcap_dump_open(c->desc,argv[1]))) {
192 fprintf(stderr,"NIO %s: pcap_dump_open failure (file %s)\n",
193 nio->name,argv[0]);
194 goto pcap_dump_err;
195 }
196
197 printf("NIO %s: capturing to file '%s'\n",nio->name,argv[1]);
198 *opt = c;
199 return(0);
200
201 pcap_dump_err:
202 pcap_close(c->desc);
203 pcap_open_err:
204 free(c);
205 return(-1);
206 }
207
208 /* Packet handler: write packets to a file in CAP format */
209 static int pf_capture_pkt_handler(netio_desc_t *nio,void *pkt,size_t len,
210 void *opt)
211 {
212 struct netio_filter_capture *c = opt;
213 struct pcap_pkthdr pkt_hdr;
214
215 if (c != NULL) {
216 gettimeofday(&pkt_hdr.ts,0);
217 pkt_hdr.caplen = len;
218 pkt_hdr.len = len;
219
220 pcap_dump((u_char *)c->dumper,&pkt_hdr,pkt);
221 pcap_dump_flush(c->dumper);
222 }
223
224 return(NETIO_FILTER_ACTION_PASS);
225 }
226
227 /* Packet capture */
228 static netio_pktfilter_t pf_capture_def = {
229 "capture",
230 pf_capture_setup,
231 pf_capture_free,
232 pf_capture_pkt_handler,
233 NULL,
234 };
235
236 #endif
237
238 /* ======================================================================== */
239 /* Frequency Dropping ("freq_drop"). */
240 /* ======================================================================== */
241
242 struct pf_freqdrop_data {
243 int frequency;
244 int current;
245 };
246
247 /* Setup filter ressources */
248 static int pf_freqdrop_setup(netio_desc_t *nio,void **opt,
249 int argc,char *argv[])
250 {
251 struct pf_freqdrop_data *data = *opt;
252
253 if (argc != 1)
254 return(-1);
255
256 if (!data) {
257 if (!(data = malloc(sizeof(*data))))
258 return(-1);
259
260 *opt = data;
261 }
262
263 data->current = 0;
264 data->frequency = atoi(argv[0]);
265 return(0);
266 }
267
268 /* Free ressources used by filter */
269 static void pf_freqdrop_free(netio_desc_t *nio,void **opt)
270 {
271 if (*opt)
272 free(*opt);
273
274 *opt = NULL;
275 }
276
277 /* Packet handler: drop 1 out of n packets */
278 static int pf_freqdrop_pkt_handler(netio_desc_t *nio,void *pkt,size_t len,
279 void *opt)
280 {
281 struct pf_freqdrop_data *data = opt;
282
283 if (data != NULL) {
284 switch(data->frequency) {
285 case -1:
286 return(NETIO_FILTER_ACTION_DROP);
287 case 0:
288 return(NETIO_FILTER_ACTION_PASS);
289 default:
290 data->current++;
291
292 if (data->current == data->frequency) {
293 data->current = 0;
294 return(NETIO_FILTER_ACTION_DROP);
295 }
296 }
297 }
298
299 return(NETIO_FILTER_ACTION_PASS);
300 }
301
302 /* Packet dropping at 1/n frequency */
303 static netio_pktfilter_t pf_freqdrop_def = {
304 "freq_drop",
305 pf_freqdrop_setup,
306 pf_freqdrop_free,
307 pf_freqdrop_pkt_handler,
308 NULL,
309 };
310
311 /* ======================================================================== */
312 /* Initialization of packet filters. */
313 /* ======================================================================== */
314
315 void netio_filter_load_all(void)
316 {
317 netio_filter_add(&pf_freqdrop_def);
318 #ifdef GEN_ETH
319 netio_filter_add(&pf_capture_def);
320 #endif
321 }

  ViewVC Help
Powered by ViewVC 1.1.26