2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
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.
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
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 // ***************************************************************************
22 // This sections contains functions to send various L2-based PDUs such as
25 // ***************************************************************************
33 "| ARP type: Send arbitrary ARP packets.\n" \
35 "| - The Ethernet dst and src MAC addresses can be specified but can be also 'rand'.\n" \
36 "| - If dst and src are NOT specified then practical defaults are used (src=own MAC, dst=bc).\n" \
38 "| ARGUMENT SYNTAX: <command> [<parameters>]\n" \
40 "| help, request, reply --+ |\n" \
41 "| +-- sendermac, senderip, targetmac, targetip\n" \
42 "| smac sip tmac tip\n" \
45 "| 1. Legitimate ARP response to broadcast:\n" \
46 "| # mz eth0 -t arp \"reply\"\n" \
47 "| 2. ARP cache poisoning, claiming to be 192.168.0.1, telling a target PC:\n" \
48 "| # mz eth0 -t arp \"reply, senderip=192.168.0.1, targetmac=00:00:0c:01:02:03, targetip=172.16.1.50\"\n" \
52 #define MZ_BPDU_HELP \
53 "| BPDU type: Send arbitrary BPDU packets (spanning tree).\n" \
55 "| ARGUMENT SYNTAX: <command> [<parameters>]\n" \
57 "| conf, tcn --+ \n" \
61 "| id = 0-65535 ..... default: 0, identifies 'Spanning Tree Protocol'\n" \
62 "| version = 0-255 ..... default: 0\n" \
63 "| type = 0-255 ..... BPDU Type: 0=CONF, 1=TCN (default: CONF)\n" \
64 "| flags = 0-255 ..... 1=TC, 128=ACK (default: 0 = No TC, No ACK)\n" \
65 "| rootid = <pri>:<mac> ..... 8 byte Root-ID (default: 00:00:<own-mac>)\n" \
66 "| rootpc = 0-4294967295 ..... root path cost (default: 0)\n" \
67 "| bid = <mac> ..... 6 byte MAC address (default: own-mac)\n" \
68 "| pid = 0-65535 ..... port identifier (default: 0)\n" \
69 "| age = 0-65535 ..... message age (default: 0)\n" \
70 "| maxage = 0-65535 ..... max age (default: 20)\n" \
71 "| hello = 0-65535 ..... hello time (default: 2)\n" \
72 "| fwd = 0-65535 ..... forward delay (default: 15)\n" \
73 "| tag - ..... Keyword to enforce 802.1Q VLAN tag; use this\n" \
74 "| together with the 'vlan' parameter below.\n" \
76 "| PVST+ extensions:\n" \
78 "| vlan ..... VLAN number (default: 0)\n" \
79 "| pri ..... 802.1P-Priority (0-7, default: 0)\n" \
80 "| notag ..... Omit 802.1Q VLAN tag\n" \
83 "| DEFAULTS: mz sends standard IEEE 802.1d (CST) BPDUs and assumes that your computer\n" \
84 "| wants to become the root bridge (rid=bid). Configuration BPDUs are the default but\n" \
85 "| can be changed using the 'tcn' keyword. Optionally the 802.3 source and destination\n" \
86 "| MAC addresses can be specified using the -a and -b options. Per default, the correct\n" \
87 "| STP or PVST+ destination addresses are used (same as '-b stp' or '-b pvst', \n" \
88 "| respectively).\n" \
90 "| Note that the parameter 'vlan' only selects the PVST+ mode if the parameter 'tag' is\n" \
96 // Send arbitrary ARP packets.
98 // - The Ethernet dst and src MAC addresses can be specified,
99 // the eth_src_txt can be 'rand'
100 // - If eth_dst and eth_src are NOT specified then practical defaults are used
102 // arg_string syntax: <command>, <param>, ... , <param>
103 // - commands: 'request' OR 'reply'
104 // - params: 'sendermac', 'senderip', 'targetmac', 'targetip'
106 // Example arg_string for ARP cache poisoning:
107 // "reply, senderip=192.168.0.1, targetmac=00:00:0c:01:02:03, targetip=172.16.1.50"
108 // where sendermac will be automatically replaced by own mac,
109 // senderip is the spoofed IP,
110 // targetmac and targetip identifies the receiver.
123 errbuf
[LIBNET_ERRBUF_SIZE
];
147 fprintf(stderr
," Note: ARP mode does not support 802.1Q builder.\n");
153 fprintf(stderr
," Note: ARP mode does not support MPLS builder.\n");
157 if (getarg(tx
.arg_string
,"help", NULL
)==1)
161 cli_print(gcli
, "%s", MZ_ARP_HELP
);
168 "\n%s", MZ_ARP_HELP
);
174 // Set the flags to shorten subsequent decisions:
175 src
= strlen(tx
.eth_src_txt
);
176 dst
= strlen(tx
.eth_dst_txt
);
178 l
= libnet_init(LIBNET_LINK_ADV
, tx
.device
, errbuf
);
182 fprintf(stderr
, "%s", errbuf
);
188 if (getarg(tx
.arg_string
,"request", NULL
)==1)
191 arpop
= ARPOP_REQUEST
;
194 if (getarg(tx
.arg_string
, "reply", NULL
)==1)
207 if ( (getarg(tx
.arg_string
,"sendermac", argval
)==1) || (getarg(tx
.arg_string
,"smac", argval
)==1) )
209 //TODO: Allow 'rand' as sendermac
210 str2hex(argval
,sendermac
,6);
214 // sendermac is usually ALWAYS own MAC:
215 getbytes(tx
.eth_src
, sendermac
,1,6);
219 if ( (getarg(tx
.arg_string
,"targetmac", argval
)==1) || (getarg(tx
.arg_string
,"tmac", argval
)==1) )
221 str2hex(argval
,targetmac
,6);
226 // targetmac is either zero (request) or bcast (reply=>gratitious ARP)
227 if (arpmode
==1) //request
228 str2hex("00:00:00:00:00:00",targetmac
, 6);
230 str2hex("ff:ff:ff:ff:ff:ff",targetmac
, 6);
234 if ( (getarg(tx
.arg_string
,"senderip", argval
)==1) || (getarg(tx
.arg_string
,"sip", argval
)==1) )
236 senderip
= str2ip32_rev(argval
);
240 // senderip is usually ALWAYS the own IP
241 senderip
= libnet_get_ipaddr4(l
); // TODO - use tx.ip_src
246 if ( (getarg(tx
.arg_string
,"targetip", argval
)==1) || (getarg(tx
.arg_string
,"tip", argval
)==1) )
248 targetip
= str2ip32_rev(argval
);
252 // if targetip is missing also use own IP because it may be used for duplicate IP detection
253 targetip
= libnet_get_ipaddr4(l
);
258 // NOTE: Now all ARP parameters are set (possibly defaults used!)
260 bs2str(sendermac
,t1
,6);
261 bs2str(targetmac
,t2
,6);
263 //printf("-- sendermac=%s targetmac=%s senderip=%u targetip=%u\n",t1,t2,senderip,targetip);
267 // Build the ARP header
269 t
= libnet_autobuild_arp(arpop
, /* operation type */
270 sendermac
, /* sender hardware addr */
271 (u_int8_t
*)&senderip
, /* sender protocol addr */
272 targetmac
, /* target hardware addr */
273 (u_int8_t
*)&targetip
, /* target protocol addr */
274 l
); /* libnet context */
278 fprintf(stderr
, " mz/send_arp: Can't build ARP header: %s\n", libnet_geterror(l
));
283 // Finally build the Ethernet header
285 if ((!dst
) && (!src
)) // ... user does not care about addresses (both eth_dst and eth_src NOT specified)
288 str2hex("ff:ff:ff:ff:ff:ff", tx
.eth_dst
, 6);
290 getbytes(targetmac
, tx
.eth_dst
, 1, 6); // either also bcast or specific MAC
292 t
= libnet_autobuild_ethernet(tx
.eth_dst
, /* ethernet destination */
293 ETHERTYPE_ARP
, /* protocol type */
294 l
); /* libnet handle */
298 fprintf(stderr
, " mz/send_arp: Can't build ethernet header: %s\n",
303 else // EITHER eth_dst OR eth_src OR BOTH specified:
308 str2hex("ff:ff:ff:ff:ff:ff", tx
.eth_dst
, 6);
310 getbytes(targetmac
, tx
.eth_dst
, 1, 6); // either also bcast when reply or specific MAC
312 else // eth_dst specified
314 if (check_eth_mac_txt(ETH_DST
)) // if true then problem!
316 str2hex("ff:ff:ff:ff:ff:ff",tx
.eth_dst
, 6); // the default
323 // tx.eth_src contains own MAC by default!
325 else // use specified source MAC address
327 if (check_eth_mac_txt(ETH_SRC
)) // if true then problem!
329 str2hex("ff:ff:ff:ff:ff:ff",tx
.eth_src
, 6); // the default
333 t
= libnet_build_ethernet (tx
.eth_dst
, tx
.eth_src
, ETHERTYPE_ARP
, NULL
, 0, l
, 0); // Note: payload=NULL, payload_s=0
336 if (libnet_adv_cull_packet(l
, &packet
, &packet_s
) == -1)
338 fprintf(stderr
, "%s", libnet_geterror(l
));
342 libnet_adv_free_packet(l
, packet
);
345 // this is for the statistics:
357 for (i
=1; i
<=loop
; i
++)
360 if (!simulate
) libnet_write(l
);
364 fprintf(stderr
," sent ARP: %s smac=%s sip=%s tmac=%s tip=%s\n",
365 (arpmode
==1) ? "request" : "reply",
367 libnet_addr2name4(senderip
,LIBNET_DONT_RESOLVE
),
369 libnet_addr2name4(targetip
,LIBNET_DONT_RESOLVE
));
373 if (tx
.delay
) SLEEP (tx
.delay
);
401 ///////////////////////////////////////////////////////////////////////////////////////
402 // Send arbitrary BPDU frames.
405 // conf|tcn ...when specifying everything yourself
408 // id, version, type, flags, rootid, rootpc, bid, pid, age, maxage, hello, fwd,
412 // mz assumes you want to become root bridge! (rid=bid)
422 bpdu_type
=0, // 0=conf, 1=topology change (actually in big endian!)
423 flags
=0, // 1=TC, 128=TCAck
424 root_id
[8], // Root BID
425 bridge_id
[8]; // Own BID
427 root_pc
=0; // Root Path Cost
429 port_id
=0, // Port Identifier
430 message_age
=0, // All timers are multiples of 1/256 sec. Thus times range from 0 to 256 seconds.
441 // Optional payload (needed for PVST+)
456 // Standard libnet variables:
459 char errbuf
[LIBNET_ERRBUF_SIZE
];
462 unsigned int i
, loop
;
465 char dum1
[32], dum2
[32];
470 fprintf(stderr
," Note: BPDU mode does not support 802.1Q builder.\n");
476 fprintf(stderr
," Note: BPDU mode does not support MPLS builder.\n");
482 if (getarg(tx
.arg_string
,"help", NULL
)==1)
486 cli_print(gcli
, "%s", MZ_BPDU_HELP
);
493 "\n%s", MZ_BPDU_HELP
);
498 /////////////////////////////////////////////////////////
499 // Default Destination Address
500 if (check_eth_mac_txt(ETH_DST
)) // if true then problem!
502 str2hex("01:80:C2:00:00:00",tx
.eth_dst
, 6); // if '1' then user did not set MAC address (or problem occurred)
508 for (i
=0; i
<6; i
++) bridge_id
[2+i
]=tx
.eth_src
[i
];
509 for (i
=0; i
<8; i
++) root_id
[i
]=bridge_id
[i
];
510 /////////////////////////////////////////////////////////
515 // determine BPDU type:
516 if (getarg(tx
.arg_string
,"conf", NULL
)==1)
519 tx
.eth_len
= LIBNET_802_2_H
+ LIBNET_STP_CONF_H
;
522 if (getarg(tx
.arg_string
, "tcn", NULL
)==1)
525 tx
.eth_len
= LIBNET_802_2_H
+ LIBNET_STP_TCN_H
;
531 tx
.eth_len
= LIBNET_802_2_H
+ LIBNET_STP_CONF_H
;
536 // id, version, type, flags, rid, rootpc, bid, pid, age, maxage, hello, fwd
538 if (getarg(tx
.arg_string
,"id", argval
)==1)
540 id
= (u_int16_t
) str2int(argval
);
543 if (getarg(tx
.arg_string
,"version", argval
)==1)
545 version
= (u_int8_t
) str2int(argval
);
548 if (getarg(tx
.arg_string
,"bpdu_type", argval
)==1)
550 bpdu_type
= (u_int8_t
) str2int(argval
);
553 if (getarg(tx
.arg_string
,"flags", argval
)==1)
555 flags
= (u_int8_t
) str2int(argval
);
558 if (getarg(tx
.arg_string
,"rid", argval
)==1)
560 if (str2hex(argval
,root_id
, 8)!=8)
562 fprintf(stderr
," mz/send_bpdu: [ERROR] The root-id must be exactly 8 bytes!\n");
567 if (getarg(tx
.arg_string
,"rootpc", argval
)==1)
569 root_pc
= (u_int32_t
) str2int(argval
);
572 if (getarg(tx
.arg_string
,"bid", argval
)==1)
574 if (str2hex(argval
,bridge_id
, 6)!=6)
576 fprintf(stderr
," mz/send_bpdu: [ERROR] The bridge-id must be exactly 6 bytes!\n");
581 if (getarg(tx
.arg_string
,"pid", argval
)==1)
583 port_id
= (u_int16_t
) str2int(argval
);
586 if (getarg(tx
.arg_string
,"age", argval
)==1)
588 message_age
= (u_int16_t
) str2int(argval
);
591 if (getarg(tx
.arg_string
,"maxage", argval
)==1)
593 max_age
= (u_int16_t
) str2int(argval
);
596 if (getarg(tx
.arg_string
,"hello", argval
)==1)
598 hello_time
= (u_int16_t
) str2int(argval
);
601 if (getarg(tx
.arg_string
,"fwd", argval
)==1)
603 f_delay
= (u_int16_t
) str2int(argval
);
608 if (getarg(tx
.arg_string
,"vlan", argval
)==1)
610 // PVST+ uses TLVs of type=0x00, len=0x02, and Value=0xVV which is the VLAN ID
611 // The DA must be 0100.0ccc.cccd instead of the standard 0180.c200.0000
613 if (check_eth_mac_txt(ETH_DST
)) // if '1' then user did not set MAC address (or problem occurred)
615 str2hex("01:00:0C:CC:CC:CD",tx
.eth_dst
, 6); // Cisco PVST+ address
618 /* // OLD TLV, maybe wrong, maybe obsolete, I don't know.
620 bpdu_payload[0] = 0x34;
621 bpdu_payload[1] = 0x00;
622 bpdu_payload[2] = 0x02;
623 vlan = (u_int16_t) str2int(argval);
625 x = (u_int8_t*) &vlan;
626 bpdu_payload[3] = *(x+1);
627 bpdu_payload[4] = *(x);
628 bpdu_payload[5] = 0x00;
629 bpdu_payload[6] = 0x00;
632 // Updated PVST+ TLV:
633 bpdu_payload
[0] = 0x00;
634 bpdu_payload
[1] = 0x00;
635 bpdu_payload
[2] = 0x00;
636 bpdu_payload
[3] = 0x00;
637 bpdu_payload
[4] = 0x02;
638 vlan
= (u_int16_t
) str2int(argval
);
639 x
= (u_int8_t
*) &vlan
;
640 bpdu_payload
[5] = *(x
+1);
641 bpdu_payload
[6] = *(x
);
644 tag
=1; // set the default: Use 802.1Q tag !!!
646 else // even a normal BPDU must be padded to 60 bytes (total)
648 bpdu_payload
[0] = 0x00;
649 bpdu_payload
[1] = 0x00;
650 bpdu_payload
[2] = 0x00;
651 bpdu_payload
[3] = 0x00;
652 bpdu_payload
[4] = 0x00;
653 bpdu_payload
[5] = 0x00;
654 bpdu_payload
[6] = 0x00;
655 bpdu_payload
[7] = 0x00;
658 tag
=0; // set the default: send untagged !!!
662 // Note: The order is important because above the defaults for 'tag' has been set.
664 if (getarg(tx
.arg_string
,"notag", NULL
)==1)
670 // Send normal BPDU with VLAN tag
671 if (getarg(tx
.arg_string
,"tag", NULL
)==1)
674 bpdu_payload
[0] = 0x00;
675 bpdu_payload
[1] = 0x00;
676 bpdu_payload
[2] = 0x00;
677 bpdu_payload
[3] = 0x00;
678 bpdu_payload
[4] = 0x00;
679 bpdu_payload
[5] = 0x00;
680 bpdu_payload
[6] = 0x00;
681 bpdu_payload
[7] = 0x00;
684 // Rewrite to standard 0180.c200.0000
686 if (check_eth_mac_txt(ETH_DST
)) // if '1' then user did not set MAC address (or problem occurred)
688 str2hex("01:80:C2:00:00:00",tx
.eth_dst
, 6);
690 vlan
= (u_int16_t
) str2int(argval
);
694 if (getarg(tx
.arg_string
,"pri", argval
)==1)
696 priority
= (u_int8_t
) str2int(argval
);
699 fprintf(stderr
, " mz/send_bpdu: Priority must be between 0 and 7.\n");
705 fprintf(stderr
, " mz/send_bpdu: Priority cannot be used together with the 'notag' keyword.\n");
711 // Open the link - get libnet handle
712 l
= libnet_init(LIBNET_LINK_ADV
, tx
.device
, errbuf
);
716 fprintf(stderr
, "%s", errbuf
);
721 if (bpdumode
==1) // Prepare CONFIGURATION BPDU:
724 t
= libnet_build_stp_conf (id
,
736 (bpdu_payload_s
) ? bpdu_payload
: NULL
,
743 fprintf(stderr
, " mz/send_bpdu: Can't build BPDU header: %s\n",
748 else // Topology Change BPDU
750 t
= libnet_build_stp_tcn(id
,
753 (bpdu_payload_s
) ? bpdu_payload
: NULL
,
760 fprintf(stderr
, " mz/send_bpdu: Can't build BPDU header: %s\n",
768 if ( (vlan
==0) || (tag
==2) ) // normal BPDU
770 // normal LLC without SNAP
771 t
= libnet_build_802_2 (dsap
,
781 fprintf(stderr
, " mz/send_bpdu: Can't build LLC header: %s\n",
786 else // PVST+ => LLC with SNAP
792 // requires a SNAP header with oui=0x00000c and type=0x010b
793 t
= libnet_build_802_2snap(0xAA,
805 fprintf(stderr
, " mz/send_bpdu: Can't build SNAP header: %s\n",
814 // Normal 802.3 header without VLAN tag
815 t
= libnet_build_802_3 (tx
.eth_dst
,
817 (vlan
) ? 0x36 : tx
.eth_len
, // NOTE the LENGTH field => 802.3 header!
824 else // PVST+ => 802.3 with 802.1Q
826 t
= libnet_build_802_1q(tx
.eth_dst
,
842 fprintf(stderr
, " mz/send_bpdu: Can't build 802.3 header: %s\n",
848 // This is ugly but it works good ;-)
854 // this is for the statistics:
861 for (i
=1; i
<=loop
; i
++)
863 if (!simulate
) libnet_write(l
);
867 bs2str(root_id
,dum1
,8);
868 bs2str(bridge_id
,dum2
,8);
869 fprintf(stderr
," sent BPDU: ");
870 fprintf(stderr
,"%s ", (bpdumode
==1) ? "conf" : "tcn ");
871 fprintf(stderr
," id=%u ver=%u flags=%x rid=%s bid=%s\n"
872 " rpc=%u pid=%u age=%u maxage=%u hello=%u fwd_delay=%u\n",
885 fprintf(stderr
,"\n");
889 if (tx
.delay
) SLEEP (tx
.delay
);