/[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

Annotation of /trunk/net_io_filter.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * 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 dpavlin 8
30     #ifdef GEN_ETH
31 dpavlin 7 #include <pcap.h>
32 dpavlin 8 #endif
33 dpavlin 1
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 dpavlin 7 } else if (direction == NETIO_FILTER_DIR_TX) {
77 dpavlin 1 nio->tx_filter_data = NULL;
78     nio->tx_filter = pf;
79 dpavlin 7 } else {
80     nio->both_filter_data = NULL;
81     nio->both_filter = pf;
82 dpavlin 1 }
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 dpavlin 7 } else if (direction == NETIO_FILTER_DIR_TX) {
96 dpavlin 1 opt = &nio->tx_filter_data;
97     pf = nio->tx_filter;
98 dpavlin 7 } else {
99     opt = &nio->both_filter_data;
100     pf = nio->both_filter;
101 dpavlin 1 }
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 dpavlin 7 } else if (direction == NETIO_FILTER_DIR_TX) {
120 dpavlin 1 opt = &nio->tx_filter_data;
121     pf = nio->tx_filter;
122 dpavlin 7 } else {
123     opt = &nio->both_filter_data;
124     pf = nio->both_filter;
125 dpavlin 1 }
126    
127     if (!pf)
128     return(-1);
129    
130     return(pf->setup(nio,opt,argc,argv));
131     }
132    
133     /* ======================================================================== */
134 dpavlin 7 /* Packet Capture ("capture") */
135     /* GFA */
136     /* ======================================================================== */
137 dpavlin 8 #ifdef GEN_ETH
138 dpavlin 7
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 dpavlin 8 #endif
237    
238 dpavlin 7 /* ======================================================================== */
239 dpavlin 1 /* 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 dpavlin 8 #ifdef GEN_ETH
319 dpavlin 7 netio_filter_add(&pf_capture_def);
320 dpavlin 8 #endif
321 dpavlin 1 }

  ViewVC Help
Powered by ViewVC 1.1.26