/[dynamips]/upstream/dynamips-0.2.7-RC1/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 /upstream/dynamips-0.2.7-RC1/net_io_filter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 7370 byte(s)
dynamips-0.2.7-RC1

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

  ViewVC Help
Powered by ViewVC 1.1.26