/* * Mausezahn - A fast versatile traffic generator * Copyright (C) 2008 Herbert Haas * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html * */ #include "mz.h" #include "cli.h" int cmd_set(struct cli_def *cli, const char *command, char *argv[], int argc) { libnet_t *l; unsigned int time_factor; int i, cnt, found_dev; char *dum; unsigned char *x; if (argc < 2) { cli_print(cli, "Specify a variable to set:\r\n"); cli_print(cli, "device specify the primary network device\r"); cli_print(cli, "NOTE: The following options are non-MOPS and deprecated:\n"); cli_print(cli, "a|sa specify a MAC source address\r"); cli_print(cli, "b|da specify a MAC destination address\r"); cli_print(cli, "A|SA specify a IP source address\r"); cli_print(cli, "B|DA specify a IP destination address\r"); cli_print(cli, "c|count specify a packet count value\r"); cli_print(cli, "d|delay specify an interpacket delay (usec, msec, or sec)\r"); cli_print(cli, "P|payload specify an ASCII payload\r"); cli_print(cli, "H|hexload specify a hexadecimal payload\r"); cli_print(cli, "p|padding specify a number of padding bytes (total for raw, added otherwise)\r"); cli_print(cli, "Q|vlan specify one ore more 802.1Q vlan tags\r"); cli_print(cli, "M|mpls specify one ore more MPLS labels\r"); cli_print(cli, "\n"); return CLI_OK; } // set primary device if (strncmp(argv[0], "device", 2)==0) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify the primary network device (use 'show dev' for a list)\n"); } else { if (strlen(argv[1])) { found_dev = 0; for (i=0; i<device_list_entries; i++) { if (strncmp(device_list[i].dev, argv[1], 16)==0) { found_dev=1; break; } } if (found_dev) { strncpy(tx.device, argv[1], 16); } else cli_print(cli, "Unknown device, will stick on %s\n", tx.device); } else cli_print(cli, "Nothing specified, will stick on %s\n", tx.device); } } // set source MAC address else if ( (strncmp(argv[0], "a", 10)==0) || (strncmp(argv[0], "sa", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a source MAC address (format: XX:XX:XX:XX:XX:XX)\n"); } else { strncpy(tx.eth_src_txt, argv[1], 32); if (check_eth_mac_txt(ETH_SRC)) { cli_print(cli, "Invalid MAC address! Format: XX:XX:XX:XX:XX:XX\r"); cli_print(cli, "Current setting: sa = %02x:%02x:%02x:%02x:%02x:%02x\r", tx.eth_src[0], tx.eth_src[1], tx.eth_src[2], tx.eth_src[3], tx.eth_src[4], tx.eth_src[5]); } tx.packet_mode = 0; } } // set destination MAC address else if ( (strncmp(argv[0], "b", 10)==0) || (strncmp(argv[0], "da", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a destination MAC address (format: XX:XX:XX:XX:XX:XX)\n"); } else { strncpy(tx.eth_dst_txt, argv[1], 32); if (check_eth_mac_txt(ETH_DST)) { cli_print(cli, "Invalid MAC address! Format: XX:XX:XX:XX:XX:XX\r"); cli_print(cli, "Current setting: da = %02x:%02x:%02x:%02x:%02x:%02x\r", tx.eth_dst[0], tx.eth_dst[1], tx.eth_dst[2], tx.eth_dst[3], tx.eth_dst[4], tx.eth_dst[5]); } tx.packet_mode = 0; } } // set source IP address else if ( (strncmp(argv[0], "A", 10)==0) || (strncmp(argv[0], "SA", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a source IP address, a FQDN, 'rand', or a range\n"); } else { if (strcmp(argv[1], "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 // TODO: mops_hton32 (&tx.ip_src_h, &tx.ip_src); } else if (get_ip_range_src(argv[1])) // returns 1 when no range has been specified { l = libnet_init (LIBNET_LINK_ADV, tx.device, NULL); if (l == NULL) { cli_print(cli, "Error: could not access the network device!\n"); return CLI_OK; } // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN: tx.ip_src = libnet_name2addr4 (l, argv[1], LIBNET_RESOLVE); x = (unsigned char *) &tx.ip_src; cli_print(cli, "Set source IP address to %i.%i.%i.%i\n", *x,*(x+1),*(x+2),*(x+3)); // TODO: mops_hton32 (&tx.ip_src, &tx.ip_src_h); libnet_destroy(l); } } } // set destination IP address else if ( (strncmp(argv[0], "B", 10)==0) || (strncmp(argv[0], "DA", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a destination IP address, a FQDN, or a range\n"); } else { if (get_ip_range_dst(argv[1])) // returns 1 when no range has been specified { l = libnet_init (LIBNET_LINK_ADV, tx.device, NULL); if (l == NULL) { cli_print(cli, "Error: could not access the network device!\n"); return CLI_OK; } // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN: tx.ip_dst = libnet_name2addr4 (l, argv[1], LIBNET_RESOLVE); x = (unsigned char *) &tx.ip_src; cli_print(cli, "Set destination IP address to %i.%i.%i.%i\n", *x,*(x+1),*(x+2),*(x+3)); // TODO: mops_hton32 (&tx.ip_dst, &tx.ip_dst_h); libnet_destroy(l); } } } // set packet count else if ( (strncmp(argv[0], "c", 10)==0) || (strncmp(argv[0], "count", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a packet count value\n"); } else { cnt = (unsigned int) str2int (argv[1]); if (cnt==0) { cli_print(cli, "Warning: A packet count of zero means an infinite number of packets.\r"); cli_print(cli, "Infinite packets are only supported via MOPS (use the 'packet' command\r"); cli_print(cli, "in global configuration mode) or when running Mausezahn from the shell.\n"); cli_print(cli, "Note: The count value has NOT been changed.\n"); } else { tx.count = cnt; } } } // set interpacket delay else if ( (strncmp(argv[0], "d", 10)==0) || (strncmp(argv[0], "delay", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify an interpacket delay (usec, msec, or sec)\n"); } else { // determine whether seconds or msecs are used // default is usec!!! time_factor=1; if (exists(argv[1],"s") || exists(argv[1],"sec")) time_factor=1000000; if (exists(argv[1],"m") || exists(argv[1],"msec")) time_factor=1000; dum = strtok(argv[1],"ms"); tx.delay = strtol(dum, (char **)NULL, 10) * time_factor; if ((errno == ERANGE && (tx.delay == LONG_MAX || tx.delay == LONG_MIN)) || (errno != 0 && tx.delay == 0)) { cli_print(cli, "Value out of range!\n"); } if (tx.delay<0) tx.delay=0; // no delay cli_print(cli, "Set interpacket delay to %u usec\n", tx.delay); } } // set ASCII payload else if ( (strncmp(argv[0], "P", 10)==0) || (strncmp(argv[0], "payload", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify an ASCII payload enclosed in quotes\n"); } else { strncpy((char *)tx.ascii_payload, argv[1], MAX_PAYLOAD_SIZE); tx.ascii=1; } } // set HEX payload else if ( (strncmp(argv[0], "H", 10)==0) || (strncmp(argv[0], "hexload", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a hexadecimal payload (using ':' or '.' as delimiters)\n"); } else { tx.hex_payload_s = str2hex (argv[1], tx.hex_payload, 8192); if (tx.hex_payload_s==0) cli_print(cli, "Invalid hexadecimal string. Try something like aa:bb:cc:45:99:00:de:ad:be:ef: ...\n"); } } // set MPLS labels else if ( (strncmp(argv[0], "M", 10)==0) || (strncmp(argv[0], "mpls", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify one or more MPLS labels\n"); } else { if (strlen(argv[1])) // TODO: Better verification of 802.1Q syntax { strncpy(tx.mpls_txt, argv[1], 128); tx.mpls=1; } } } // set 802.1Q tags else if ( (strncmp(argv[0], "Q", 10)==0) || (strncmp(argv[0], "vlan", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify one or more 802.1Q VLAN tags (and optionally 801.1P values)\n"); } else { if (strlen(argv[1])) // TODO: Better verification of 802.1Q syntax { strncpy(tx.dot1Q_txt, argv[1], 32); tx.dot1Q=1; } } } // set padding else if ( (strncmp(argv[0], "p", 10)==0) || (strncmp(argv[0], "padding", 10)==0) ) { if (strncmp(argv[1],"?",1)==0) { cli_print(cli,"Specify a number of padding bytes\n"); } else { tx.padding = (unsigned int) str2int(argv[1]); if (tx.padding > MAX_PAYLOAD_SIZE) { cli_print(cli, "Note: Padding too big! However, let's try and see what happens...\n"); } } } // DEFAULT ANSWER: else { cli_print(cli, "Unknown variable '%s'\n",argv[0]); } return CLI_OK; }