/* * Mausezahn - A fast versatile traffic generator * Copyright (C) 2008-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" int cmd_bpdu_id (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; char str[256]; if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) { mz_def16("0x0000", pd->id, str); cli_print(cli, "Specify the BPDU identifier (0..65535)\r"); cli_print(cli, "%s\n", str); cli_print(cli, "\n"); return CLI_OK; } if (mops_pdesc_2byte(&pd->id, argv[0], 0, 0, 65535)) { cli_print(cli, "Specify a value between 0 and 65535\n"); } return CLI_OK; } int cmd_bpdu_version (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) { cli_print(cli, "Specify the BPDU version (0..255)\r"); cli_print(cli, "\n"); return CLI_OK; } if (mops_pdesc_1byte(&pd->version, argv[0], 0, 0, 255)) { cli_print(cli, "Specify a value between 0 and 255\n"); } return CLI_OK; } int cmd_bpdu_type (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) { cli_print(cli, "Specify the BPDU type, either via keyword or number (0..255)\n"); cli_print(cli, "Keywords:\n"); cli_print(cli, " conf .... Configuration BPDU\r"); cli_print(cli, " tcn ..... Topology Change BPDU\r"); cli_print(cli, "\n"); return CLI_OK; } if (mz_strcmp(argv[0], "configuration", 1)==0) { pd->bpdu_type = 0x00; } else if (mz_strcmp(argv[0], "tcn", 1)==0) { pd->bpdu_type = 0x80; } else if (mops_pdesc_1byte(&pd->bpdu_type, argv[0], 0, 0, 255)) { cli_print(cli, "Specify a value between 0 and 255\n"); } return CLI_OK; } int cmd_bpdu_flags (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; int i; char str[16]; if ( (strcmp(argv[argc-1],"?")==0) || (argc>8) ) { cli_print(cli, "Specify the BPDU flags by keyword.\r"); cli_print(cli, "Note that not-mentioned flags will be set to zero!\n"); cli_print(cli, "General keywords:\n"); cli_print(cli, " ack .... Topology Change Acknowledgement\r"); cli_print(cli, " tcn .... Topology Change Notification\r"); cli_print(cli, "\r"); cli_print(cli, "RSTP-specific keywords:\n"); cli_print(cli, " agree .... Agreement\r"); cli_print(cli, " prop .... Proposal\r"); cli_print(cli, " fwd .... Forward State\r"); cli_print(cli, " learn .... Learn State\r"); cli_print(cli, "\r"); cli_print(cli, " Port roles:\n"); cli_print(cli, " unknown .... Unknown\r"); cli_print(cli, " alt .... Alternate or Backup\r"); cli_print(cli, " root .... Root\r"); cli_print(cli, " desg .... Designated\r"); cli_print(cli, "\n"); return CLI_OK; } // 7 6 5 4 3 2 1 0 // tcnack agree fwd learn X X proposal TCN // where XX is 00 unknown // 01 alternate or backup // 10 root // 11 designated if (argc) { pd->flags = 0x00; // always reset to zero (= normal Configuration BPDU) for (i=0; iflags |= 0x80; else if (mz_strcmp(argv[i], "tcn", 2)==0) pd->flags |= 0x01; else if (mz_strcmp(argv[i], "agree", 2)==0) pd->flags |= 0x40; else if (mz_strcmp(argv[i], "fwd", 2)==0) pd->flags |= 0x20; else if (mz_strcmp(argv[i], "learn", 2)==0) pd->flags |= 0x10; else if (mz_strcmp(argv[i], "proposal", 2)==0) pd->flags |= 0x02; else if (mz_strcmp(argv[i], "unknown", 2)==0) pd->flags &= 0xf3; else if (mz_strcmp(argv[i], "alt", 2)==0) { pd->flags &= 0xf7; pd->flags |= 0x04; } else if (mz_strcmp(argv[i], "root", 2)==0) { pd->flags &= 0xfb; pd->flags |= 0x08; } else if (mz_strcmp(argv[i], "desg", 2)==0) pd->flags |= 0x0c; } // Feedback char2bits(pd->flags, str); cli_print(cli, "Flags: %s\n", str); } else { cli_print(cli, "No flags configured (use '?')\n"); } return CLI_OK; } int cmd_bpdu_rid (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; char p[64], e[64]; int pri, esi, r; if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) ) { cli_print(cli, "Specify the BPDU root identifier, using the following format:\n"); cli_print(cli, " [:ext-sys-id] [interface | MAC-Address]\n"); cli_print(cli, " ....... priority (0-15)\r"); cli_print(cli, " ....... extended system-id (0-4095)\n"); cli_print(cli, "Optionally the MAC address of the root bridge can be given, either directly as arbitrary\r"); cli_print(cli, "address (format: XX:XX:XX:XX:XX:XX) or by referring to an existing interface.\n"); cli_print(cli, "Per default the MAC address of the default interface is used and a priority of zero.\n"); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Please specify at least the priority (use ?)\n"); return CLI_OK; } mz_tok(argv[0], ":", 2, p, e); pri = (int) str2int(p); if (e!=NULL) esi = (int) str2int(e); else esi = 0; if (argc==1) // no MAC given { r = mops_create_bpdu_bid (clipkt, pri, esi, NULL, 1); // 1 means RID (0 means BID) } else r = mops_create_bpdu_bid (clipkt, pri, esi, argv[1], 1); // 1 means RID (0 means BID) // Check return value switch (r) { case 1: cli_print(cli, "Priority must be within 0..15\n"); return CLI_OK; break; case 2: cli_print(cli, "Extended System-ID must be within 0..4095\n"); return CLI_OK; break; case 3: cli_print(cli, "Invalid MAC address or interface\n"); return CLI_OK; break; case 4: cli_print(cli, "Invalid format - use ?\n"); return CLI_OK; break; } //--------- // Verify: bs2str(pd->root_id, p, 8); cli_print(cli, "RID is now %s\n", p); // ------- // return CLI_OK; } int cmd_bpdu_pc (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; unsigned long long int i; if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) ) { cli_print(cli, "Specify the BPDU root path cost (0..4294967295)\r"); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = str2lint (argv[0]); if (i>0xffffffff) { cli_print(cli, "Range exceeded (0..4294967295)\n"); } else pd->root_pc = (u_int32_t) i; return CLI_OK; } int cmd_bpdu_bid (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; char p[64], e[64]; int pri, esi, r; if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) ) { cli_print(cli, "Specify the BPDU bridge identifier, using the following format:\n"); cli_print(cli, " [:ext-sys-id] [interface | MAC-Address]\n"); cli_print(cli, " ....... priority (0-15)\r"); cli_print(cli, " ....... extended system-id (0-4095)\n"); cli_print(cli, "Optionally the MAC address of the root bridge can be given, either directly as arbitrary\r"); cli_print(cli, "address (format: XX:XX:XX:XX:XX:XX) or by referring to an existing interface.\n"); cli_print(cli, "Per default the MAC address of the default interface is used and a priority of zero.\n"); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Please specify at least the priority (use ?)\n"); return CLI_OK; } mz_tok(argv[0], ":", 2, p, e); pri = (int) str2int(p); if (e!=NULL) esi = (int) str2int(e); else esi = 0; if (argc==1) // no MAC given { r = mops_create_bpdu_bid (clipkt, pri, esi, NULL, 0); // 0 means BID (1 means RID) } else r = mops_create_bpdu_bid (clipkt, pri, esi, argv[1], 0); // 0 means BID (1 means RID) // Check return value switch (r) { case 1: cli_print(cli, "Priority must be within 0..15\n"); return CLI_OK; break; case 2: cli_print(cli, "Extended System-ID must be within 0..4095\n"); return CLI_OK; break; case 3: cli_print(cli, "Invalid MAC address or interface\n"); return CLI_OK; break; case 4: cli_print(cli, "Invalid format - use ?\n"); return CLI_OK; break; } //--------- // Verify: bs2str(pd->bridge_id, p, 8); cli_print(cli, "BID is now %s\n", p); // ------- // return CLI_OK; } int cmd_bpdu_pid (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; u_int32_t i; if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) ) { cli_print(cli, "Specify the BPDU port identifier (0..65535)\r"); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = (u_int32_t) str2int (argv[0]); if (i>0xffff) { cli_print(cli, "The port identifier must be within 0..65535\n"); return CLI_OK; } pd->port_id = (u_int16_t) i; return CLI_OK; } // // // NOTE: // // All timers are multiples of 1/256 sec. Thus times range from 0 to 255 seconds. // // int cmd_bpdu_age (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; u_int32_t i; char str[256]; if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) ) { mz_def16("0", pd->message_age, str); cli_print(cli, "Specify the message age:\n"); cli_print(cli, " - either in seconds (0..256) e. g. '14 sec'\r"); cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n"); cli_print(cli, "%s\n", str); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = (u_int32_t) str2int (argv[0]); if (argc==1) // absolute { if (i>0xffff) cli_print(cli, "The age must be within 0..65535\n"); else pd->message_age = (u_int16_t) i; } else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds { if (i>256) cli_print(cli, "The age must be within 0..256 seconds\n"); else { if (i==256) i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996 else i = i * 256; pd->message_age = (u_int16_t) i; } } else cli_print(cli, "Invalid argument\n"); return CLI_OK; } int cmd_bpdu_maxage (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; u_int32_t i; char str[256]; if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) ) { mz_def16("20 seconds", pd->max_age, str); cli_print(cli, "Specify the maximum message age:\n"); cli_print(cli, " - either in seconds (0..256) e. g. '20 sec'\r"); cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n"); cli_print(cli, "%s\n", str); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = (u_int32_t) str2int (argv[0]); if (argc==1) // absolute { if (i>0xffff) cli_print(cli, "The max age must be within 0..65535\n"); else pd->max_age = (u_int16_t) i; } else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds { if (i>256) cli_print(cli, "The max age must be within 0..256 seconds\n"); else { if (i==256) i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996 else i = i * 256; pd->max_age = (u_int16_t) i; } } else cli_print(cli, "Invalid argument\n"); return CLI_OK; } int cmd_bpdu_hello (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; u_int32_t i; char str[256]; if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) ) { mz_def16("2 seconds", pd->hello_time, str); cli_print(cli, "Specify the hello interval:\n"); cli_print(cli, " - either in seconds (0..256) e. g. '2 sec'\r"); cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n"); cli_print(cli, "%s\n", str); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = (u_int32_t) str2int (argv[0]); if (argc==1) // absolute { if (i>0xffff) cli_print(cli, "The hello interval must be within 0..65535\n"); else pd->hello_time = (u_int16_t) i; } else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds { if (i>256) cli_print(cli, "The hello interval must be within 0..256 seconds\n"); else { if (i==256) i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996 else i = i * 256; pd->hello_time = (u_int16_t) i; } } else cli_print(cli, "Invalid argument\n"); return CLI_OK; } int cmd_bpdu_fwd (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; u_int32_t i; char str[256]; if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) ) { mz_def16("15 seconds", pd->f_delay, str); cli_print(cli, "Specify the forward delay:\n"); cli_print(cli, " - either in seconds (0..256) e. g. '15 sec'\r"); cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n"); cli_print(cli, "%s\n", str); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = (u_int32_t) str2int (argv[0]); if (argc==1) // absolute { if (i>0xffff) cli_print(cli, "The forward delay must be within 0..65535\n"); else pd->f_delay = (u_int16_t) i; } else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds { if (i>256) cli_print(cli, "The forward delay must be within 0..256 seconds\n"); else { if (i==256) i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996 else i = i * 256; pd->f_delay = (u_int16_t) i; } } else cli_print(cli, "Invalid argument\n"); return CLI_OK; } int cmd_bpdu_mode (struct cli_def *cli, const char *command, char *argv[], int argc) { struct mops_ext_bpdu * pd = clipkt->p_desc; if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) ) { cli_print(cli, "Specify the BPDU mode using the keywords:\n"); cli_print(cli, " stp ...... IEEE 802.1d (traditional CST)\r"); cli_print(cli, " rstp ...... IEEE 802.1w (Rapid STP)\r"); cli_print(cli, " mstp ...... IEEE 802.1s (Multiple STP)\r"); cli_print(cli, " pvst ...... Cisco Per-VLAN STP\r"); cli_print(cli, " rpvst ...... Cisco Per-VLAN RSTP\r"); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } if (mz_strcmp(argv[0], "stp", 1)==0) { pd->version=0; pd->rstp=0; pd->pvst=0; pd->mstp=0; } else if (mz_strcmp(argv[0], "rstp", 2)==0) { pd->version=2; pd->rstp=1; pd->mstp=0; } else if (mz_strcmp(argv[0], "mstp", 1)==0) { pd->version=3; pd->mstp=1; } else if (mz_strcmp(argv[0], "pvst", 1)==0) { pd->version=0; pd->pvst=1; pd->rstp=0; pd->mstp=0; } else if (mz_strcmp(argv[0], "rpvst", 2)==0) { pd->version=2; pd->rstp=1; pd->pvst=1; pd->mstp=0; } // TODO: also change version to 2 if RSTP, 0 if legacy return CLI_OK; } int cmd_bpdu_vlan(struct cli_def *cli, const char *command, char *argv[], int argc) { u_int32_t i; if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) ) { cli_print(cli, "Specify the VLAN number for PVST+ messages (0..4095)\n"); cli_print(cli, "\n"); return CLI_OK; } if (argc==0) { cli_print(cli, "Missing argument (use ?)\n"); return CLI_OK; } i = (u_int32_t) str2int(argv[0]); if (i>65535) { cli_print(cli, "VLAN number is definitely too large! (0..65535 at maximum)\n"); return CLI_OK; } if (i>4095) { cli_print(cli, "Warning: Invalid VLAN number (0..4095) - but let's try it...\n"); } mops_create_bpdu_trailer(clipkt, (u_int16_t) i); return CLI_OK; } int cmd_bpdu_end(struct cli_def *cli, const char *command, char *argv[], int argc) { char prompt[16]; sprintf(prompt, "pkt-%i",clipkt->id); cli_set_configmode(cli, MZ_MODE_PACKET, prompt); return CLI_OK; }