mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / staging / cli_bpdu.c
blob8cc2a69d9c1984e316739c549c47a27e9403b4a8
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
21 #include "mz.h"
22 #include "cli.h"
23 #include "mops.h"
27 int cmd_bpdu_id (struct cli_def *cli, const char *command, char *argv[], int argc)
29 struct mops_ext_bpdu * pd = clipkt->p_desc;
30 char str[256];
32 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) )
34 mz_def16("0x0000", pd->id, str);
35 cli_print(cli, "Specify the BPDU identifier (0..65535)\r");
36 cli_print(cli, "%s\n", str);
37 cli_print(cli, "\n");
38 return CLI_OK;
41 if (mops_pdesc_2byte(&pd->id, argv[0], 0, 0, 65535))
43 cli_print(cli, "Specify a value between 0 and 65535\n");
46 return CLI_OK;
50 int cmd_bpdu_version (struct cli_def *cli, const char *command, char *argv[], int argc)
52 struct mops_ext_bpdu * pd = clipkt->p_desc;
54 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) )
56 cli_print(cli, "Specify the BPDU version (0..255)\r");
57 cli_print(cli, "\n");
58 return CLI_OK;
61 if (mops_pdesc_1byte(&pd->version, argv[0], 0, 0, 255))
63 cli_print(cli, "Specify a value between 0 and 255\n");
67 return CLI_OK;
72 int cmd_bpdu_type (struct cli_def *cli, const char *command, char *argv[], int argc)
74 struct mops_ext_bpdu * pd = clipkt->p_desc;
76 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) {
77 cli_print(cli, "Specify the BPDU type, either via keyword or number (0..255)\n");
78 cli_print(cli, "Keywords:\n");
79 cli_print(cli, " conf .... Configuration BPDU\r");
80 cli_print(cli, " tcn ..... Topology Change BPDU\r");
81 cli_print(cli, "\n");
82 return CLI_OK;
85 if (mz_strcmp(argv[0], "configuration", 1)==0) {
86 pd->bpdu_type = 0x00;
87 } else if (mz_strcmp(argv[0], "tcn", 1)==0) {
88 pd->bpdu_type = 0x80;
89 } else if (mops_pdesc_1byte(&pd->bpdu_type, argv[0], 0, 0, 255)) {
90 cli_print(cli, "Specify a value between 0 and 255\n");
93 return CLI_OK;
97 int cmd_bpdu_flags (struct cli_def *cli, const char *command, char *argv[], int argc)
99 struct mops_ext_bpdu * pd = clipkt->p_desc;
100 int i;
101 char str[16];
103 if ( (strcmp(argv[argc-1],"?")==0) || (argc>8) )
105 cli_print(cli, "Specify the BPDU flags by keyword.\r");
106 cli_print(cli, "Note that not-mentioned flags will be set to zero!\n");
107 cli_print(cli, "General keywords:\n");
108 cli_print(cli, " ack .... Topology Change Acknowledgement\r");
109 cli_print(cli, " tcn .... Topology Change Notification\r");
110 cli_print(cli, "\r");
111 cli_print(cli, "RSTP-specific keywords:\n");
112 cli_print(cli, " agree .... Agreement\r");
113 cli_print(cli, " prop .... Proposal\r");
114 cli_print(cli, " fwd .... Forward State\r");
115 cli_print(cli, " learn .... Learn State\r");
116 cli_print(cli, "\r");
117 cli_print(cli, " Port roles:\n");
118 cli_print(cli, " unknown .... Unknown\r");
119 cli_print(cli, " alt .... Alternate or Backup\r");
120 cli_print(cli, " root .... Root\r");
121 cli_print(cli, " desg .... Designated\r");
122 cli_print(cli, "\n");
123 return CLI_OK;
126 // 7 6 5 4 3 2 1 0
127 // tcnack agree fwd learn X X proposal TCN
128 // where XX is 00 unknown
129 // 01 alternate or backup
130 // 10 root
131 // 11 designated
133 if (argc)
135 pd->flags = 0x00; // always reset to zero (= normal Configuration BPDU)
137 for (i=0; i<argc; i++)
139 if (mz_strcmp(argv[i], "ack", 2)==0) pd->flags |= 0x80;
140 else
141 if (mz_strcmp(argv[i], "tcn", 2)==0) pd->flags |= 0x01;
142 else
143 if (mz_strcmp(argv[i], "agree", 2)==0) pd->flags |= 0x40;
144 else
145 if (mz_strcmp(argv[i], "fwd", 2)==0) pd->flags |= 0x20;
146 else
147 if (mz_strcmp(argv[i], "learn", 2)==0) pd->flags |= 0x10;
148 else
149 if (mz_strcmp(argv[i], "proposal", 2)==0) pd->flags |= 0x02;
150 else
151 if (mz_strcmp(argv[i], "unknown", 2)==0) pd->flags &= 0xf3;
152 else
153 if (mz_strcmp(argv[i], "alt", 2)==0) { pd->flags &= 0xf7; pd->flags |= 0x04; }
154 else
155 if (mz_strcmp(argv[i], "root", 2)==0) { pd->flags &= 0xfb; pd->flags |= 0x08; }
156 else
157 if (mz_strcmp(argv[i], "desg", 2)==0) pd->flags |= 0x0c;
159 // Feedback
160 char2bits(pd->flags, str);
161 cli_print(cli, "Flags: %s\n", str);
163 else
165 cli_print(cli, "No flags configured (use '?')\n");
168 return CLI_OK;
179 int cmd_bpdu_rid (struct cli_def *cli, const char *command, char *argv[], int argc)
182 struct mops_ext_bpdu * pd = clipkt->p_desc;
183 char p[64], e[64];
184 int pri, esi, r;
186 if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) )
188 cli_print(cli, "Specify the BPDU root identifier, using the following format:\n");
189 cli_print(cli, " <priority>[:ext-sys-id] [interface | MAC-Address]\n");
190 cli_print(cli, " <priority> ....... priority (0-15)\r");
191 cli_print(cli, " <ext-sys-id> ....... extended system-id (0-4095)\n");
192 cli_print(cli, "Optionally the MAC address of the root bridge can be given, either directly as arbitrary\r");
193 cli_print(cli, "address (format: XX:XX:XX:XX:XX:XX) or by referring to an existing interface.\n");
194 cli_print(cli, "Per default the MAC address of the default interface is used and a priority of zero.\n");
195 cli_print(cli, "\n");
196 return CLI_OK;
199 if (argc==0) {
200 cli_print(cli, "Please specify at least the priority (use ?)\n");
201 return CLI_OK;
204 mz_tok(argv[0], ":", 2, p, e);
206 pri = (int) str2int(p);
207 if (e!=NULL)
208 esi = (int) str2int(e);
209 else
210 esi = 0;
212 if (argc==1) // no MAC given
214 r = mops_create_bpdu_bid (clipkt, pri, esi, NULL, 1); // 1 means RID (0 means BID)
216 else
217 r = mops_create_bpdu_bid (clipkt, pri, esi, argv[1], 1); // 1 means RID (0 means BID)
220 // Check return value
221 switch (r)
223 case 1:
224 cli_print(cli, "Priority must be within 0..15\n");
225 return CLI_OK;
226 break;
227 case 2:
228 cli_print(cli, "Extended System-ID must be within 0..4095\n");
229 return CLI_OK;
230 break;
231 case 3:
232 cli_print(cli, "Invalid MAC address or interface\n");
233 return CLI_OK;
234 break;
235 case 4:
236 cli_print(cli, "Invalid format - use ?\n");
237 return CLI_OK;
238 break;
243 //---------
244 // Verify:
245 bs2str(pd->root_id, p, 8);
246 cli_print(cli, "RID is now %s\n", p);
247 // -------
249 return CLI_OK;
257 int cmd_bpdu_pc (struct cli_def *cli, const char *command, char *argv[], int argc)
259 struct mops_ext_bpdu * pd = clipkt->p_desc;
260 unsigned long long int i;
262 if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) )
264 cli_print(cli, "Specify the BPDU root path cost (0..4294967295)\r");
265 cli_print(cli, "\n");
266 return CLI_OK;
269 if (argc==0)
271 cli_print(cli, "Missing argument (use ?)\n");
272 return CLI_OK;
275 i = str2lint (argv[0]);
276 if (i>0xffffffff)
278 cli_print(cli, "Range exceeded (0..4294967295)\n");
280 else
281 pd->root_pc = (u_int32_t) i;
283 return CLI_OK;
289 int cmd_bpdu_bid (struct cli_def *cli, const char *command, char *argv[], int argc)
292 struct mops_ext_bpdu * pd = clipkt->p_desc;
293 char p[64], e[64];
294 int pri, esi, r;
296 if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) )
298 cli_print(cli, "Specify the BPDU bridge identifier, using the following format:\n");
299 cli_print(cli, " <priority>[:ext-sys-id] [interface | MAC-Address]\n");
300 cli_print(cli, " <priority> ....... priority (0-15)\r");
301 cli_print(cli, " <ext-sys-id> ....... extended system-id (0-4095)\n");
302 cli_print(cli, "Optionally the MAC address of the root bridge can be given, either directly as arbitrary\r");
303 cli_print(cli, "address (format: XX:XX:XX:XX:XX:XX) or by referring to an existing interface.\n");
304 cli_print(cli, "Per default the MAC address of the default interface is used and a priority of zero.\n");
305 cli_print(cli, "\n");
306 return CLI_OK;
310 if (argc==0)
312 cli_print(cli, "Please specify at least the priority (use ?)\n");
313 return CLI_OK;
316 mz_tok(argv[0], ":", 2, p, e);
318 pri = (int) str2int(p);
319 if (e!=NULL)
320 esi = (int) str2int(e);
321 else
322 esi = 0;
324 if (argc==1) // no MAC given
326 r = mops_create_bpdu_bid (clipkt, pri, esi, NULL, 0); // 0 means BID (1 means RID)
328 else
329 r = mops_create_bpdu_bid (clipkt, pri, esi, argv[1], 0); // 0 means BID (1 means RID)
332 // Check return value
333 switch (r)
335 case 1:
336 cli_print(cli, "Priority must be within 0..15\n");
337 return CLI_OK;
338 break;
339 case 2:
340 cli_print(cli, "Extended System-ID must be within 0..4095\n");
341 return CLI_OK;
342 break;
343 case 3:
344 cli_print(cli, "Invalid MAC address or interface\n");
345 return CLI_OK;
346 break;
347 case 4:
348 cli_print(cli, "Invalid format - use ?\n");
349 return CLI_OK;
350 break;
355 //---------
356 // Verify:
357 bs2str(pd->bridge_id, p, 8);
358 cli_print(cli, "BID is now %s\n", p);
359 // -------
361 return CLI_OK;
368 int cmd_bpdu_pid (struct cli_def *cli, const char *command, char *argv[], int argc)
370 struct mops_ext_bpdu * pd = clipkt->p_desc;
371 u_int32_t i;
373 if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) )
375 cli_print(cli, "Specify the BPDU port identifier (0..65535)\r");
376 cli_print(cli, "\n");
377 return CLI_OK;
380 if (argc==0)
382 cli_print(cli, "Missing argument (use ?)\n");
383 return CLI_OK;
386 i = (u_int32_t) str2int (argv[0]);
388 if (i>0xffff)
390 cli_print(cli, "The port identifier must be within 0..65535\n");
391 return CLI_OK;
394 pd->port_id = (u_int16_t) i;
396 return CLI_OK;
401 // NOTE:
403 // All timers are multiples of 1/256 sec. Thus times range from 0 to 255 seconds.
407 int cmd_bpdu_age (struct cli_def *cli, const char *command, char *argv[], int argc)
409 struct mops_ext_bpdu * pd = clipkt->p_desc;
410 u_int32_t i;
411 char str[256];
413 if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) )
415 mz_def16("0", pd->message_age, str);
417 cli_print(cli, "Specify the message age:\n");
418 cli_print(cli, " - either in seconds (0..256) e. g. '14 sec'\r");
419 cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n");
420 cli_print(cli, "%s\n", str);
421 cli_print(cli, "\n");
422 return CLI_OK;
425 if (argc==0)
427 cli_print(cli, "Missing argument (use ?)\n");
428 return CLI_OK;
431 i = (u_int32_t) str2int (argv[0]);
433 if (argc==1) // absolute
435 if (i>0xffff)
436 cli_print(cli, "The age must be within 0..65535\n");
437 else
438 pd->message_age = (u_int16_t) i;
440 else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds
442 if (i>256)
443 cli_print(cli, "The age must be within 0..256 seconds\n");
444 else
446 if (i==256)
447 i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996
448 else
449 i = i * 256;
451 pd->message_age = (u_int16_t) i;
455 else
456 cli_print(cli, "Invalid argument\n");
458 return CLI_OK;
468 int cmd_bpdu_maxage (struct cli_def *cli, const char *command, char *argv[], int argc)
470 struct mops_ext_bpdu * pd = clipkt->p_desc;
471 u_int32_t i;
472 char str[256];
474 if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) )
476 mz_def16("20 seconds", pd->max_age, str);
478 cli_print(cli, "Specify the maximum message age:\n");
479 cli_print(cli, " - either in seconds (0..256) e. g. '20 sec'\r");
480 cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n");
481 cli_print(cli, "%s\n", str);
482 cli_print(cli, "\n");
483 return CLI_OK;
486 if (argc==0)
488 cli_print(cli, "Missing argument (use ?)\n");
489 return CLI_OK;
492 i = (u_int32_t) str2int (argv[0]);
494 if (argc==1) // absolute
496 if (i>0xffff)
497 cli_print(cli, "The max age must be within 0..65535\n");
498 else
499 pd->max_age = (u_int16_t) i;
501 else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds
503 if (i>256)
504 cli_print(cli, "The max age must be within 0..256 seconds\n");
505 else
507 if (i==256)
508 i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996
509 else
510 i = i * 256;
512 pd->max_age = (u_int16_t) i;
516 else
517 cli_print(cli, "Invalid argument\n");
519 return CLI_OK;
527 int cmd_bpdu_hello (struct cli_def *cli, const char *command, char *argv[], int argc)
529 struct mops_ext_bpdu * pd = clipkt->p_desc;
530 u_int32_t i;
531 char str[256];
533 if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) )
535 mz_def16("2 seconds", pd->hello_time, str);
537 cli_print(cli, "Specify the hello interval:\n");
538 cli_print(cli, " - either in seconds (0..256) e. g. '2 sec'\r");
539 cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n");
540 cli_print(cli, "%s\n", str); cli_print(cli, "\n");
541 return CLI_OK;
544 if (argc==0)
546 cli_print(cli, "Missing argument (use ?)\n");
547 return CLI_OK;
551 i = (u_int32_t) str2int (argv[0]);
553 if (argc==1) // absolute
555 if (i>0xffff)
556 cli_print(cli, "The hello interval must be within 0..65535\n");
557 else
558 pd->hello_time = (u_int16_t) i;
560 else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds
562 if (i>256)
563 cli_print(cli, "The hello interval must be within 0..256 seconds\n");
564 else
566 if (i==256)
567 i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996
568 else
569 i = i * 256;
571 pd->hello_time = (u_int16_t) i;
575 else
576 cli_print(cli, "Invalid argument\n");
578 return CLI_OK;
582 int cmd_bpdu_fwd (struct cli_def *cli, const char *command, char *argv[], int argc)
584 struct mops_ext_bpdu * pd = clipkt->p_desc;
585 u_int32_t i;
586 char str[256];
588 if ( (strcmp(argv[argc-1],"?")==0) || (argc>2) )
590 mz_def16("15 seconds", pd->f_delay, str);
592 cli_print(cli, "Specify the forward delay:\n");
593 cli_print(cli, " - either in seconds (0..256) e. g. '15 sec'\r");
594 cli_print(cli, " - or as multiples of 1/256 seconds (0..65535)\n");
595 cli_print(cli, "%s\n", str);
596 cli_print(cli, "\n");
597 return CLI_OK;
600 if (argc==0)
602 cli_print(cli, "Missing argument (use ?)\n");
603 return CLI_OK;
607 i = (u_int32_t) str2int (argv[0]);
609 if (argc==1) // absolute
611 if (i>0xffff)
612 cli_print(cli, "The forward delay must be within 0..65535\n");
613 else
614 pd->f_delay = (u_int16_t) i;
616 else if (mz_strcmp(argv[1], "seconds", 1)==0) // in seconds
618 if (i>256)
619 cli_print(cli, "The forward delay must be within 0..256 seconds\n");
620 else
622 if (i==256)
623 i = 0xffff; // since 256*256=65536 which exceeds 0xffff but 65535/256 = 255.996
624 else
625 i = i * 256;
627 pd->f_delay = (u_int16_t) i;
631 else
632 cli_print(cli, "Invalid argument\n");
634 return CLI_OK;
640 int cmd_bpdu_mode (struct cli_def *cli, const char *command, char *argv[], int argc)
642 struct mops_ext_bpdu * pd = clipkt->p_desc;
644 if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) )
646 cli_print(cli, "Specify the BPDU mode using the keywords:\n");
647 cli_print(cli, " stp ...... IEEE 802.1d (traditional CST)\r");
648 cli_print(cli, " rstp ...... IEEE 802.1w (Rapid STP)\r");
649 cli_print(cli, " mstp ...... IEEE 802.1s (Multiple STP)\r");
650 cli_print(cli, " pvst ...... Cisco Per-VLAN STP\r");
651 cli_print(cli, " rpvst ...... Cisco Per-VLAN RSTP\r");
652 cli_print(cli, "\n");
653 return CLI_OK;
656 if (argc==0)
658 cli_print(cli, "Missing argument (use ?)\n");
659 return CLI_OK;
663 if (mz_strcmp(argv[0], "stp", 1)==0)
665 pd->version=0;
666 pd->rstp=0;
667 pd->pvst=0;
668 pd->mstp=0;
670 else if (mz_strcmp(argv[0], "rstp", 2)==0)
672 pd->version=2;
673 pd->rstp=1;
674 pd->mstp=0;
676 else if (mz_strcmp(argv[0], "mstp", 1)==0)
678 pd->version=3;
679 pd->mstp=1;
681 else if (mz_strcmp(argv[0], "pvst", 1)==0)
683 pd->version=0;
684 pd->pvst=1;
685 pd->rstp=0;
686 pd->mstp=0;
688 else if (mz_strcmp(argv[0], "rpvst", 2)==0)
690 pd->version=2;
691 pd->rstp=1;
692 pd->pvst=1;
693 pd->mstp=0;
697 // TODO: also change version to 2 if RSTP, 0 if legacy
700 return CLI_OK;
706 int cmd_bpdu_vlan(struct cli_def *cli, const char *command, char *argv[], int argc)
708 u_int32_t i;
710 if ( (strcmp(argv[argc-1],"?")==0) || (argc>1) )
712 cli_print(cli, "Specify the VLAN number for PVST+ messages (0..4095)\n");
713 cli_print(cli, "\n");
714 return CLI_OK;
717 if (argc==0)
719 cli_print(cli, "Missing argument (use ?)\n");
720 return CLI_OK;
723 i = (u_int32_t) str2int(argv[0]);
725 if (i>65535)
727 cli_print(cli, "VLAN number is definitely too large! (0..65535 at maximum)\n");
728 return CLI_OK;
731 if (i>4095)
733 cli_print(cli, "Warning: Invalid VLAN number (0..4095) - but let's try it...\n");
736 mops_create_bpdu_trailer(clipkt, (u_int16_t) i);
738 return CLI_OK;
743 int cmd_bpdu_end(struct cli_def *cli, const char *command, char *argv[], int argc)
745 char prompt[16];
746 sprintf(prompt, "pkt-%i",clipkt->id);
747 cli_set_configmode(cli, MZ_MODE_PACKET, prompt);
748 return CLI_OK;