--- upstream/dynamips-0.2.6-RC5/net_io_filter.c 2007/10/06 16:09:07 6 +++ upstream/dynamips-0.2.7-RC2/net_io_filter.c 2007/10/06 16:24:54 8 @@ -1,5 +1,5 @@ /* - * Cisco 7200 (Predator) simulation platform. + * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * NetIO Filtering. @@ -27,6 +27,10 @@ #include #include +#ifdef GEN_ETH +#include +#endif + #include "registry.h" #include "net.h" #include "net_io.h" @@ -69,11 +73,13 @@ if (direction == NETIO_FILTER_DIR_RX) { nio->rx_filter_data = NULL; nio->rx_filter = pf; - } else { + } else if (direction == NETIO_FILTER_DIR_TX) { nio->tx_filter_data = NULL; nio->tx_filter = pf; + } else { + nio->both_filter_data = NULL; + nio->both_filter = pf; } - return(0); } @@ -86,9 +92,12 @@ if (direction == NETIO_FILTER_DIR_RX) { opt = &nio->rx_filter_data; pf = nio->rx_filter; - } else { + } else if (direction == NETIO_FILTER_DIR_TX) { opt = &nio->tx_filter_data; pf = nio->tx_filter; + } else { + opt = &nio->both_filter_data; + pf = nio->both_filter; } if (!pf) @@ -107,9 +116,12 @@ if (direction == NETIO_FILTER_DIR_RX) { opt = &nio->rx_filter_data; pf = nio->rx_filter; - } else { + } else if (direction == NETIO_FILTER_DIR_TX) { opt = &nio->tx_filter_data; pf = nio->tx_filter; + } else { + opt = &nio->both_filter_data; + pf = nio->both_filter; } if (!pf) @@ -119,6 +131,111 @@ } /* ======================================================================== */ +/* Packet Capture ("capture") */ +/* GFA */ +/* ======================================================================== */ +#ifdef GEN_ETH + +/* Free resources used by filter */ +static void pf_capture_free(netio_desc_t *nio,void **opt) +{ + struct netio_filter_capture *c = *opt; + + if (c != NULL) { + printf("NIO %s: ending packet capture.\n",nio->name); + + /* Close dumper */ + if (c->dumper) + pcap_dump_close(c->dumper); + + /* Close PCAP descriptor */ + if (c->desc) + pcap_close(c->desc); + + free(c); + *opt = NULL; + } +} + +/* Setup filter resources */ +static int pf_capture_setup(netio_desc_t *nio,void **opt, + int argc,char *argv[]) +{ + struct netio_filter_capture *c; + int link_type; + + /* We must have a link type and a filename */ + if (argc != 2) + return(-1); + + /* Free resources if something has already been done */ + pf_capture_free(nio,opt); + + /* Allocate structure to hold PCAP info */ + if (!(c = malloc(sizeof(*c)))) + return(-1); + + if ((link_type = pcap_datalink_name_to_val(argv[0])) == -1) { + fprintf(stderr,"NIO %s: unknown link type %s, assuming Ethernet.\n", + nio->name,argv[0]); + link_type = DLT_EN10MB; + } + + /* Open a dead pcap descriptor */ + if (!(c->desc = pcap_open_dead(link_type,8192))) { + fprintf(stderr,"NIO %s: pcap_open_dead failure\n",nio->name); + goto pcap_open_err; + } + + /* Open the output file */ + if (!(c->dumper = pcap_dump_open(c->desc,argv[1]))) { + fprintf(stderr,"NIO %s: pcap_dump_open failure (file %s)\n", + nio->name,argv[0]); + goto pcap_dump_err; + } + + printf("NIO %s: capturing to file '%s'\n",nio->name,argv[1]); + *opt = c; + return(0); + + pcap_dump_err: + pcap_close(c->desc); + pcap_open_err: + free(c); + return(-1); +} + +/* Packet handler: write packets to a file in CAP format */ +static int pf_capture_pkt_handler(netio_desc_t *nio,void *pkt,size_t len, + void *opt) +{ + struct netio_filter_capture *c = opt; + struct pcap_pkthdr pkt_hdr; + + if (c != NULL) { + gettimeofday(&pkt_hdr.ts,0); + pkt_hdr.caplen = len; + pkt_hdr.len = len; + + pcap_dump((u_char *)c->dumper,&pkt_hdr,pkt); + pcap_dump_flush(c->dumper); + } + + return(NETIO_FILTER_ACTION_PASS); +} + +/* Packet capture */ +static netio_pktfilter_t pf_capture_def = { + "capture", + pf_capture_setup, + pf_capture_free, + pf_capture_pkt_handler, + NULL, +}; + +#endif + +/* ======================================================================== */ /* Frequency Dropping ("freq_drop"). */ /* ======================================================================== */ @@ -198,4 +315,7 @@ void netio_filter_load_all(void) { netio_filter_add(&pf_freqdrop_def); +#ifdef GEN_ETH + netio_filter_add(&pf_capture_def); +#endif }