/* * Mausezahn - A fast versatile traffic generator * Copyright (C) 2010 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" #include "mops.h" #include "llist.h" // PURPOSE: Enter sequence configuration mode // either a) create new or b) edit old or c) delete old sequence // // # sequence MY_SEQUENCE // # sequence OLD_SEQUENCE delete // int conf_sequence (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mz_ll *cur; char str[512]; int ret=0; if ( (strcmp(argv[argc-1],"?")==0) || (argc<1) || (argc>2)) { cli_print(cli, "Configure a sequence of packets.\n"); cli_print(cli, "ARGUMENTS: [delete]\n"); cli_print(cli, "Current list of packet sequences:\n"); while (mops_dump_sequence(str)) cli_print(cli, "%s\r", str); return CLI_OK; } switch (argc) { case 1: cur = mz_ll_search_name (packet_sequences, argv[0]); if (cur==NULL) { // create NEW sequence cli_print(cli, "Sequence does not exist; creating new sequence named '%s'\n", argv[0]); cur = mops_create_sequence(argv[0]); if (cur==NULL) { cli_print(cli, "ERROR: Cannot allocate another sequence!\n"); return CLI_OK; } } // else ENTER EXISTING (cur already points to it) cli_seq = cur; cli_set_configmode(cli, MZ_MODE_SEQUENCE, "config-seq"); break; case 2: // otherwise DELETE? if (mz_strcmp(argv[1], "delete", 3)==0) { ret = mops_delete_sequence(argv[0]); switch (ret) { case 1: cli_print(cli, "Sequence '%s' does not exist\n", argv[0]); break; case 2: cli_print(cli, "Sequence '%s' is currently active! Cannot delete it.\n", argv[0]); break; default: cli_print(cli, "Sequence '%s' deleted.\n", argv[0]); } } break; default: // nothing break; } return CLI_OK; } // add packet to current sequence int sequence_add (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops *mp; int ret=0; if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) { cli_print(cli, "Add a packet to the current sequence.\n"); cli_print(cli, "ARGUMENT: OR \n"); return CLI_OK; } // first assume argument is a name mp = mops_search_name (mp_head, argv[0]); if (mp==NULL) { // but packet name does not exist if (mz_strisnum(argv[0])!=0) // arg is really a number? mp = mops_search_id (mp_head, (int) str2int(argv[0])); if (mp==NULL) { // also packet ID not found cli_print(cli, "Packet does not exist!\n"); return CLI_OK; } } // packet found, so add to current sequence ret = mops_add_packet_to_sequence (cli_seq, mp); if (ret==1) cli_print(cli, "Cannot add packet (unknown error, maybe report this)!\n"); if (ret==-1) cli_print(cli, "Cannot add packet: sequence already full!\n"); if (ret==-2) cli_print(cli, "Cannot add packet with infinite count!\n"); return CLI_OK; } // add a delay int sequence_delay (struct cli_def *cli, const char *command, char *argv[], int argc) { int ret=0, ret2=0; struct timespec t; char str[128]; if ( (strcmp(argv[argc-1],"?")==0) || (argc<1) || (argc>2)) { cli_print(cli, "Add a delay to the current sequence.\n"); cli_print(cli, "ARGUMENTS: [hour | min | sec | msec | usec | nsec]\n"); cli_print(cli, "The default unit is milliseconds (i. e. when no unit is given).\n"); return CLI_OK; } switch (argc) { case 1: // only one argument, but may contain an unit (such as '314sec') ret = delay_parse(&t, argv[0], NULL); break; case 2: // user specified two arguments such as '100 msec' ret = delay_parse(&t, argv[0], argv[1]); break; default: cli_print(cli, "Too many arguments! Expected delay value and unit, such as '10 msec'\n"); return CLI_OK; } switch (ret) { case 1: cli_print(cli, "Invalid unit! Use one of {nsec, usec, msec, sec, min, hours}\n"); return CLI_OK; break; case 2: cli_print(cli, "Value too large! Supported range is from 0 to 999999999\n"); return CLI_OK; break; } ret2 = mops_add_delay_to_sequence (cli_seq, &t); if (ret2==-1) { cli_print(cli, "You must add a packet first.\n"); return CLI_OK; } if (ret2==-2) { cli_print(cli, "Cannot add delay (array full).\n"); return CLI_OK; } sprintf(str, "Delay set to %lu sec and %lu nsec", ((struct pseq*) cli_seq->data)->gap[ret2].tv_sec, ((struct pseq*) cli_seq->data)->gap[ret2].tv_nsec); cli_print(cli, "%s\n", str); return CLI_OK; } // remove one packet int sequence_remove (struct cli_def *cli, const char *command, char *argv[], int argc) { int ret=0; int i=0; if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1)) { cli_print(cli, "Remove a packet (and any associated pause configuration) from the current sequence.\n"); cli_print(cli, "ARGUMENT: | last | all\n"); cli_print(cli, "FYI: Use the 'show' command to see the current packet list with indexes.\n"); return CLI_OK; } if (mz_strcmp(argv[0], "last", 1)==0) { ret = mops_delete_packet_from_pseq (cli_seq, -1); } else if (mz_strcmp(argv[0], "all", 1)==0) { ret = mops_delete_all_packets_from_pseq (cli_seq); i=1; } else { // index number given if (mz_strisnum(argv[0])==0) { cli_print(cli, "Invalid parameter. Please specify a packet index number or 'last'\n"); return CLI_OK; } ret = mops_delete_packet_from_pseq (cli_seq, (int) str2int(argv[0])); } switch (ret) { case 0: if (i) cli_print(cli, "Removed all entries.\n"); else cli_print(cli, "Removed one entry.\n"); break; case 1: cli_print(cli, "List empty or invalid packet index.\n"); break; case 2: cli_print(cli, "Packet index too large.\n"); break; } return CLI_OK; } // show packet list of that sequence int sequence_show (struct cli_def *cli, const char *command, char *argv[], int argc) { char str[512], name[32], layers[16], proto[16]; struct pseq *seq; int i; if (strcmp(argv[argc-1],"?")==0) { cli_print(cli, "Shows all packets of the current sequence.\n"); return CLI_OK; } if (argc>0) { cli_print(cli, "This command has currently no arguments!\n"); return CLI_OK; } seq = (struct pseq*) cli_seq->data; if (seq->count==0) { cli_print(cli, "Current sequence '%s' has no entries.\n", cli_seq->name); } else { // show all packets in this sequence cli_print(cli, "%i sequence(s) defined.\r", packet_sequences->refcount-1); // total info snprintf(str,512, "Current sequence '%s' has %i entries:", cli_seq->name, seq->count); // num entries here cli_print(cli, "%s\n", str); cli_print(cli, "Nr PId PktName Layers Protocol Device"); for (i=0; icount; i++) { strncpy (name, seq->packet[i]->packet_name, 13); // only show first 13 chars if (strnlen(seq->packet[i]->packet_name, MAX_MOPS_PACKET_NAME_LEN)>13) { name[13]=0x00; strcat(name, "..."); } mops_get_proto_info(seq->packet[i], layers, proto); snprintf(str,512, "%2i %4i %-16s %s %-8s %-6s", i+1, seq->packet[i]->id, name, layers, proto, seq->packet[i]->device); cli_print(cli, "%s\r", str); if ((seq->gap[i].tv_sec !=0) || (seq->gap[i].tv_nsec !=0)) { // gap also defined? timespec2str(&seq->gap[i], str); cli_print(cli, " \\___ %s pause ___/\r", str); } } } return CLI_OK; }