From d0009856814c13d13770db5aadd7b2fabf947776 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 13 May 2013 13:53:27 +0200 Subject: staging: add mausezahn staging directory After some back and forth, we decided that it is easier to maintain mausezahn in a staging directory until it is fully reworked and cleaned up to be ready to be fully integrated. This way, it is better than having it in a separate branch, and we can also accept patches from outside more easily. Also, while at it, fix up some function mismatches with libcli. Signed-off-by: Daniel Borkmann Signed-off-by: Tobias Klauser --- staging/mausezahn.c | 1013 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1013 insertions(+) create mode 100644 staging/mausezahn.c (limited to 'staging/mausezahn.c') diff --git a/staging/mausezahn.c b/staging/mausezahn.c new file mode 100644 index 0000000..7f712b7 --- /dev/null +++ b/staging/mausezahn.c @@ -0,0 +1,1013 @@ +/* + * netsniff-ng - the packet sniffing beast + * Mausezahn, a fast versatile traffic generator + * Copyright 2008, 2009, 2010 Herbert Haas. + * Subject to the GPL, version 2. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mz.h" +#include "cli.h" +#include "mops.h" +#include "llist.h" +#include "die.h" + +int verbose_level = 0; + +static const char *short_options = "46hqvVSxra:A:b:B:c:d:E:f:F:p:P:t:T:M:Q:X:"; + +static void signal_handler(int number) +{ + clean_up(number); +} + +void clean_up(int sig) +{ + int i; + struct arp_table_struct *cur, *next; + + if (!quiet) fprintf(stderr, "\nMausezahn cleans up...\n"); + + if (fp != NULL) { + verbose_l1(" close files (1) ...\n"); + + fflush(fp); + fclose(fp); + } + + if (fp2!=NULL) { + if (verbose) fprintf(stderr, " close files (2) ...\n"); + (void) fflush(fp2); + (void) fclose(fp2); + } + + // interactive mode? + if (mz_port) { + if (verbose) fprintf(stderr, " clear mops list...\n"); + mops_cleanup(mp_head); + if (verbose) fprintf(stderr, " clear automops list...\n"); + automops_cleanup(amp_head); + if (verbose) fprintf(stderr, " clear packet sequences...\n"); + mz_ll_delete_list(packet_sequences); + } + + for (i=0; inext; + if (cur!=NULL) free(cur); + cur=next; + } + } + + // close packet sockets + if (device_list[i].ps>=0) { + close(device_list[i].ps); + } + + } + + if (verbose) fprintf(stderr, "finished.\n"); + exit(sig); +} + + +static void help(void) +{ + printf("\nmausezahn %s, a fast versatile traffic generator\n", VERSION_STRING); + puts("http://www.netsniff-ng.org\n\n" + "Usage: mausezahn [options] [interface] ||\n" + "Options:\n" + " -x Interactive mode with telnet CLI, default port: 25542\n" + " -4 IPv4 mode (default)\n" + " -6 IPv6 mode\n" + " -c Send packet count times, default:1, infinite:0\n" + " -d Apply delay between transmissions. The delay value can be\n" + " specified in usec (default, no additional unit needed), or in\n" + " msec (e.g. 100m or 100msec), or in seconds (e.g. 100s or 100sec)\n" + " -r Multiplies the specified delay with a random value\n" + " -p Pad the raw frame to specified length (using random bytes)\n" + " -a Use specified source mac address, no matter what has\n" + " been specified with other arguments; keywords see below,\n" + " Default is own interface\n" + " -b Same with destination mac address; keywords:\n" + " rand Use a random MAC address\n" + " bc Use a broadcast MAC address\n" + " own Use own interface MAC address (default for source MAC)\n" + " stp Use IEEE 802.1d STP multicast address\n" + " cisco Use Cisco multicast address as used for CDP, VTP, or PVST+\n" + " -A Use specified source IP address (default is own interface IP)\n" + " -B Send packet to specified destination IP or domain name\n" + " -P Use the specified ASCII payload\n" + " -f Read the ASCII payload from a file\n" + " -F Read the hexadecimal payload from a file\n" + " -Q <[CoS:]vlan> Specify 802.1Q VLAN tag and optional Class of Service, you can\n" + " specify multiple 802.1Q VLAN tags (QinQ...) by separating them\n" + " via a comma or a period (e.g. '5:10,20,2:30')\n" + " -t Specify packet type for autobuild (you don't need to care for\n" + " encapsulations in lower layers, most packet types allow/require\n" + " additional packet-specific arguments in an ;\n" + " Currently supported types: arp, bpdu, cdp, ip, icmp, udp, tcp,\n" + " dns, rtp, syslog, lldp and more;\n" + " For context-help use 'help' as !\n" + " -T Specify packet type for server mode, currently only rtp is supported;\n" + " Enter -T help or -T rtp help for further information\n" + " -M Insert a MPLS label, enter '-M help' for a syntax description\n" + " -V|VV|... Verbose and more verbose mode\n" + " -q Quiet mode, even omit 'important' standard short messages\n" + " -S Simulation mode: DOES NOT put anything on the wire, this is\n" + " typically combined with one of the verbose modes (v or V)\n" + " -v Show version\n" + " -h Print this help\n\n" + "Examples:\n" + " mausezahn -x 99\n" + " mausezahn -c 0 -d 2s -t bpdu conf\n" + " mausezahn -t cdp change -c 0\n" + " mausezahn -t syslog sev=3 -P \"You have been mausezahned.\" -A 10.1.1.109 -B 192.168.7.7\n" + " mausezahn eth0 -A rand -B 1.1.1.1 -c 0 -t tcp \"dp=1-1023, flags=syn\"\n\n" + "Note:\n" + " This tool is targeted for network developers! You should\n" + " be aware of what you are doing and what these options above\n" + " mean! Only use this tool in an isolated LAN that you own!\n\n" + "Please report bugs to \n" + "Copyright (C) 2008-2010 Herbert Haas ,\n" + "Copyright (C) 2011 Daniel Borkmann ,\n" + "Swiss federal institute of technology (ETH Zurich)\n" + "License: GNU GPL version 2.0\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n"); + die(); +} + +static void version(void) +{ + printf("\nmausezahn %s, a fast versatile traffic generator\n", VERSION_STRING); + puts("http://www.netsniff-ng.org\n\n" + "Please report bugs to \n" + "Copyright (C) 2008-2010 Herbert Haas ,\n" + "Copyright (C) 2011 Daniel Borkmann ,\n" + "Swiss federal institute of technology (ETH Zurich)\n" + "License: GNU GPL version 2.0\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n"); + die(); +} + +int reset() +{ + int i; + time_t t; + + // Determine platform type sizes: + MZ_SIZE_LONG_INT = sizeof(long int); + + mz_default_config_path[0] = 0x00; + mz_default_log_path[0] = 0x00; + + // Reset globals: + quiet = 0; + ipv6_mode = 0; + verbose = 0; + simulate = 0; + filename[0] = '\0'; + path[0] = '\0'; + gind=0; + gind_max = TIME_COUNT; + fp = NULL; + fp2 = NULL; + mz_port = 0; + mz_rand = 0; + mp_head = NULL; + + for (i=0;i10000) { + fprintf(stderr, " Warning: Padding must not exceed 10000!\n"); + return -1; + } + break; + case 't': + packet_type = optarg; // analyzed below + break; + case 'X': + mops_type = optarg; // MOPS TRANSITION STRATEGY -- analyzed below + break; + case 'T': + packet_type = optarg; + RX = 1; + break; + case 'r': + mz_rand = 1; + break; + case 'M': + if (strncmp(optarg,"help",4)==0) { + (void) get_mpls_params("help "); + } + else { + strncpy (tx.mpls_txt, optarg, 128); + tx.eth_type = ETHERTYPE_MPLS; + tx.packet_mode = 0; + tx.mpls=1; + } + break; + case 'P': // ASCII payload + strncpy((char*)tx.ascii_payload, optarg, MAX_PAYLOAD_SIZE); + tx.ascii = 1; + break; + case 'f': // ASCII payload in FILE + afp = fopen(optarg, "r"); + if (fgets((char*)tx.ascii_payload, MAX_PAYLOAD_SIZE, afp) == NULL) + fprintf(stderr, " mz/getopts: File empty?\n"); + fclose(afp); + tx.ascii = 1; + break; + case 'F': // HEX payload in FILE + afp = fopen(optarg, "r"); + i=0; + while ( (hexpld[i]=fgetc(afp))!=EOF ) { + if (isspace(hexpld[i])) { + hexpld[i]=':'; + } + i++; + } + hexpld[i]='\0'; + fclose(afp); + hexpld_specified=1; + break; + case 'Q': // VLAN TAG + if (strncmp(optarg,"help",4)==0) { + print_dot1Q_help(); // ugly but most simple and safe solution + } + else { + strncpy (tx.dot1Q_txt, optarg, 32); + tx.dot1Q=1; + // determine number of VLAN tags + for (i=0; i2) { // number of remaining arguments + fprintf(stderr," mz/getopts: Too many arguments!\n"); + return -1; + } + + + // There can be 0-2 additional arguments + switch (rargs) { + case 0: + if (lookupdev()) { // no device found + if (verbose) fprintf(stderr, " mz: no active interfaces found!\n"); + strcpy(tx.device, "lo"); + } + if (verbose) // device found + fprintf(stderr," mz: device not given, will use %s\n",tx.device); + break; + case 1: // arg_string OR device given => find out! + if ( (strncmp(argv[optind],"eth",3)==0) + || (strncmp(argv[optind],"ath",3)==0) + || ((strncmp(argv[optind],"lo",2)==0)&&(strncmp(argv[optind],"log",3)!=0)) + || (strncmp(argv[optind],"vmnet",5)==0) + || (strncmp(argv[optind],"wifi",4)==0) ) { + // device has been specified! + strncpy (tx.device, argv[optind], 16); + } + else { /// arg_string given => no device has been specified -- let's find one! + strncpy (tx.arg_string, argv[optind], MAX_PAYLOAD_SIZE); + if (lookupdev()) { // no device found + if (verbose) fprintf(stderr, " mz: no active interfaces found!\n"); + strcpy(tx.device, "lo"); + } + if (verbose) + fprintf(stderr," mz: device not given, will use %s\n",tx.device); + } + break; + case 2: // both device and arg_string given + strncpy (tx.device, argv[optind], 16); + strncpy (tx.arg_string, argv[optind+1], MAX_PAYLOAD_SIZE); + break; + default: + fprintf(stderr," mz/getopts: Unknown argument problem!\n"); + return 1; + } + + if (hexpld_specified) { + strcat(tx.arg_string, ",p="); + strcat(tx.arg_string, hexpld); + } + + + ////////////////////////////////////////////////////////////////////////// + // + // Initialize MAC and IP Addresses. + // + // - tx.eth_src = own interface MAC + // - tx.ip_src = own interface IP or user specified + // - tx.ip_dst = 255.255.255.255 or user specified (can be a range) + // - tx.ip_src_rand ... is set if needed. + // + + // Get own device MAC address: + // Don't open context if only a help text is requested + if (getarg(tx.arg_string,"help", NULL)!=1) { + l = libnet_init (LIBNET_LINK_ADV, tx.device, err_buf ); + if (l == NULL) { + fprintf(stderr, " mz/getopts: libnet_init() failed (%s)", err_buf); + return -1; + } + mymac = libnet_get_hwaddr(l); + for (i=0; i<6; i++) { + tx.eth_src[i] = mymac->ether_addr_octet[i]; + tx.eth_mac_own[i] = mymac->ether_addr_octet[i]; + } + + // Set source IP address: + if (strlen(tx.ip_src_txt)) { // option -A has been specified + if (mz_strcmp(tx.ip_src_txt, "bcast", 2)==0) { + tx.ip_src = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE); + } else if (strcmp(tx.ip_src_txt, "rand") == 0) { + tx.ip_src_rand = 1; + tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0 + } + else if (get_ip_range_src(tx.ip_src_txt)) { // returns 1 when no range has been specified + // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN: + if (ipv6_mode) + tx.ip6_src = libnet_name2addr6 (l, tx.ip_src_txt, LIBNET_RESOLVE); + else + tx.ip_src = libnet_name2addr4 (l, tx.ip_src_txt, LIBNET_RESOLVE); + } + } + else { // no source IP specified: by default use own IP address + if (ipv6_mode) { + tx.ip6_src = libnet_get_ipaddr6(l); + if (strncmp((char*)&tx.ip6_src,(char*)&in6addr_error,sizeof(in6addr_error))==0) + printf("Failed to set source IPv6 address: %s", l->err_buf); + } + else + tx.ip_src = libnet_get_ipaddr4(l); + } + + // Set destination IP address: + if (strlen(tx.ip_dst_txt)) { // option -B has been specified + if (mz_strcmp(tx.ip_dst_txt, "rand", 2)==0) { + fprintf(stderr, "Option -B does not support random destination IP addresses currently.\n"); + return 1; + } + + if (mz_strcmp(tx.ip_dst_txt, "bcast", 2)==0) { + tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE); + } else if (get_ip_range_dst(tx.ip_dst_txt)) { // returns 1 when no range has been specified + // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN: + if (ipv6_mode) + tx.ip6_dst = libnet_name2addr6 (l, tx.ip_dst_txt, LIBNET_RESOLVE); + else + tx.ip_dst = libnet_name2addr4 (l, tx.ip_dst_txt, LIBNET_RESOLVE); + } + } + else { // no destination IP specified: by default use broadcast + tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE); + } + + // Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()' + // in verbose mode. See 'modifications.c'. + + if (tx.ip_src_rand) { // ip_src_h already given, convert to ip_src + dum1 = (unsigned char*) &tx.ip_src_h; + dum2 = (unsigned char*) &tx.ip_src; + } + else { // ip_src already given, convert to ip_src_h + dum1 = (unsigned char*) &tx.ip_src; + dum2 = (unsigned char*) &tx.ip_src_h; + } + + *dum2 = *(dum1+3); + dum2++; + *dum2 = *(dum1+2); + dum2++; + *dum2 = *(dum1+1); + dum2++; + *dum2 = *dum1; + + dum1 = (unsigned char*) &tx.ip_dst; + dum2 = (unsigned char*) &tx.ip_dst_h; + + *dum2 = *(dum1+3); + dum2++; + *dum2 = *(dum1+2); + dum2++; + *dum2 = *(dum1+1); + dum2++; + *dum2 = *dum1; + + libnet_destroy(l); + } + + // + // END OF ADDRESS INITIALIZATION + // + ////////////////////////////////////////////////////////////////////////// + + + ////// retrieve interface parameters /////// + + for (i=0; i special packet types, stateless + // + // If -t not present then evaluate arg_string which must + // contain a byte-string in hexadecimal notation. + // + // + + // ***** NEW: MOPS TRANSITION STRATEGY ***** + if (mops_type != NULL) { + + if (mz_strcmp(mops_type,"lldp",4)==0) { + mops_direct(tx.device, MOPS_LLDP, tx.arg_string); + } + } + + + if (packet_type == NULL) { // raw hex string given + mode = BYTE_STREAM; + } + else if (strcmp(packet_type,"arp")==0) { + mode = ARP; + } + else if (strcmp(packet_type,"bpdu")==0) { + mode = BPDU; + } + else if (strcmp(packet_type,"ip")==0) { + mode = IP; + } + else if (strcmp(packet_type,"udp")==0) { + mode = UDP; + } + else if (strcmp(packet_type,"icmp")==0) { + mode = ICMP; + } + else if (strcmp(packet_type,"icmp6")==0) { + mode = ICMP6; + } + else if (strcmp(packet_type,"tcp")==0) { + mode = TCP; + } + else if (strcmp(packet_type,"dns")==0) { + mode = DNS; + } + else if (strcmp(packet_type,"cdp")==0) { + mode = CDP; + } + else if (strcmp(packet_type,"syslog")==0) { + mode = SYSLOG; + } + else if (strcmp(packet_type,"lldp")==0) { + mode = LLDP; + tx.packet_mode=0; // create whole frame by ourself + } + else if (strcmp(packet_type,"rtp")==0) { + if (RX) { + mode = RX_RTP; + } + else { + mode = RTP; + if (!count_set) tx.count = 0; + if (!delay_set) tx.delay = 20000; // 20 msec inter-packet delay for RTP + } + } + else if (strcmp(packet_type,"help")==0) { + fprintf(stderr, "\n" + MAUSEZAHN_VERSION + "\n" + "| The following packet types are currently implemented:\n" + "|\n" + "| arp ... sends ARP packets\n" + "| bpdu ... sends BPDU packets (STP or PVST+)\n" + "| cdp ... sends CDP messages\n" + "| ip ... sends IPv4 packets\n" + "| udp ... sends UDP datagrams\n" + "| tcp ... sends TCP segments\n" + "| icmp ... sends ICMP messages\n" + "| dns ... sends DNS messages\n" + "| rtp ... sends RTP datagrams\n" + "| syslog ... sends Syslog messages\n" + "|\n" + "| Of course you can build any other packet type 'manually' using the direct layer 2 mode.\n" + "| FYI: The interactive mode supports additional protocols. (Try mz -x )\n" + "\n" + ); + exit(1); + } + else { + fprintf(stderr, " mz: you must specify a valid packet type!\n"); + } + + + ////////////////////////////////////////////////////////////////////////// + + // TODO: Implement macro support + // Check macro types here + + return 0; +} + +int main(int argc, char **argv) +{ + // These handles are only used when creating L3 and above packets. + libnet_t *l; // the context + libnet_ptag_t t2=0, t3=0, t4=0; // handles to layers + double cpu_time_used; + + reset(); + + if ( getopts(argc, argv) ) + { + (void) fprintf(stderr, " Invalid command line parameters!\n"); + help(); + } + + // Check whether hires timers are supported or not: + (void) check_timer(); + + signal(SIGINT, signal_handler); // to close all file pointers etc upon SIGINT + + switch (mode) + { + case BYTE_STREAM: + send_eth(); + break; + + case ARP: + (void) send_arp(); + break; + + case BPDU: + (void) send_bpdu(); + break; + + case CDP: + (void) send_cdp(); + break; + + case IP: // From now on a new much more modular method is used: + l = get_link_context(); + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case ICMP: + tx.ip_proto = 1; + l = get_link_context(); + t4 = create_icmp_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case ICMP6: + tx.ip_proto = 58; + l = get_link_context(); + t4 = create_icmp6_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (ipv6_mode) + update_ISUM(l, t4); + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case UDP: + tx.ip_proto = 17; + l = get_link_context(); + t4 = create_udp_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (ipv6_mode) + update_USUM(l, t4); + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case TCP: + tx.ip_proto = 6; + l = get_link_context(); + t4 = create_tcp_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (ipv6_mode) + update_TSUM(l, t4); + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case DNS: + tx.ip_proto = 17; + l = get_link_context(); + (void) create_dns_packet(); + t4 = create_udp_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case RTP: + tx.ip_proto = 17; + l = get_link_context(); + if (!quiet) fprintf(stderr, " mz: RTP mode! (count=%u, delay=%u usec)\n\n", tx.count, tx.delay); + (void) create_rtp_packet(); + t4 = create_udp_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (!quiet) complexity(); + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case RX_RTP: // Receive RTP packets + rcv_rtp_init(); + rcv_rtp(); + break; + + case SYSLOG: + tx.ip_proto = 17; + l = get_link_context(); + (void) create_syslog_packet(); + t4 = create_udp_packet(l); // t4 can be used for later header changes + t3 = create_ip_packet(l); // t3 can be used for later header changes + if (!quiet) complexity(); + + if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + + case LLDP: // start with a new concept here + //l = get_link_context(); + //(void) create_lldp_packet(); + // // // printf("SIZE=%lu\n",sizeof(struct tx_struct)); + fprintf(stderr, "LLDP is currently only supported via the interactive mode\n"); + exit(1); + break; + + + default: + (void) fprintf(stderr," mz/main: unknown mode! Stop.\n"); + return (1); + } + + if (!quiet) + { + mz_stop = clock(); + cpu_time_used = ((double) (mz_stop - mz_start)) / CLOCKS_PER_SEC; + if (cpu_time_used > 0) + { + total_d /= cpu_time_used; + fprintf(stderr, "%.2f seconds (%.Lf packets per second)\n",cpu_time_used,total_d); + } + else + { + fprintf(stderr, "\n"); + } + } + + return(0); +} -- cgit v1.2.3-54-g00ecf