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
25 // Catch SIGINT and clean up, close everything...
26 void clean_up(int sig
)
29 struct arp_table_struct
*cur
, *next
;
31 if (!quiet
) fprintf(stderr
, "\nMausezahn cleans up...\n");
34 if (verbose
) fprintf(stderr
, " close files (1) ...\n");
40 if (verbose
) fprintf(stderr
, " close files (2) ...\n");
47 if (verbose
) fprintf(stderr
, " clear mops list...\n");
48 mops_cleanup (mp_head
);
49 if (verbose
) fprintf(stderr
, " clear automops list...\n");
50 automops_cleanup (amp_head
);
51 if (verbose
) fprintf(stderr
, " clear packet sequences...\n");
52 mz_ll_delete_list (packet_sequences
);
55 for (i
=0; i
<device_list_entries
; i
++) {
56 if (device_list
[i
].p_arp
!=NULL
) {
57 pcap_close(device_list
[i
].p_arp
);
58 fprintf(stderr
, " stopped ARP process for device %s\n", device_list
[i
].dev
);
60 if (device_list
[i
].arprx_thread
!=0) {
61 pthread_cancel(device_list
[i
].arprx_thread
);
63 fprintf(stderr
, " (ARP thread for device %s done)\n", device_list
[i
].dev
);
66 if (device_list
[i
].arp_table
!=NULL
) {
67 cur
=device_list
[i
].arp_table
;
70 if (cur
!=NULL
) free(cur
);
75 // close packet sockets
76 if (device_list
[i
].ps
>=0) {
77 close(device_list
[i
].ps
);
84 if (verbose
) fprintf(stderr
, "finished.\n");
92 (void) fprintf (stderr
,"\n"
96 "| USAGE: mz [options] [interface] keyword | arg_string | hex_string\n"
98 "| Short option description (see doc or manpage for more information):\n"
99 "| -h Prints this information.\n"
100 "| -4 IPv4 mode (default)\n"
102 "| -c <count> Send the packet count times (default: 1, infinite: 0).\n"
103 "| -d <delay> Apply delay between transmissions. The delay value can be\n"
104 "| specified in usec (default, no additional unit needed), or in\n"
105 "| msec (e. g. 100m or 100msec), or in seconds (e. g. 100s or 100sec).\n"
106 "| -r Multiplies the specified delay with a random value.\n"
107 "| -p <length> Pad the raw frame to specified length (using random bytes).\n"
108 "| -a <Src_MAC|keyword> Use specified source mac address, no matter what has\n"
109 "| been specified with other arguments. Keywords see below.\n"
110 "| Default is own interface MAC.\n"
111 "| -b <Dst_MAC|keyword> Same with destination mac address.\n"
113 "| rand use a random MAC address\n"
114 "| bc use a broadcast MAC address\n"
115 "| own use own interface MAC address (default for source MAC)\n"
116 "| stp use IEEE 802.1d STP multicast address\n"
117 "| cisco use Cisco multicast address as used for CDP, VTP, or PVST+\n"
118 "| -A <Src_IP> Use specified source IP address (default is own interface IP).\n"
119 "| -B <Dst_IP|DNS_name> Send packet to specified destination IP or domain name.\n"
120 "| -P <ASCII Payload> Use the specified ASCII payload.\n"
121 "| -f <filename> Read the ASCII payload from a file.\n"
122 "| -F <filename> Read the hexadecimal payload from a file.\n"
123 "| -Q <[CoS:]vlan> Specify 802.1Q VLAN tag and optional Class of Service. You can\n"
124 "| specify multiple 802.1Q VLAN tags (QinQ...) by separating them\n"
125 "| via a comma or a period (e. g. '5:10,20,2:30').\n"
126 "| -t <packet_type> Specify packet type for autobuild (you don't need to care for\n"
127 "| encapsulations in lower layers. Most packet types allow/require\n"
128 "| additional packet-specific arguments in an arg_string.\n"
129 "| Currently supported types: arp, bpdu, cdp, ip, icmp, udp, tcp,\n"
130 "| dns, rtp, syslog, lldp.\n"
131 "| For context-help use 'help' as arg_string!\n"
132 "| -T <packet_type> Specify packet type for server mode. Currently only rtp is supported.\n"
133 "| Enter -T help or -T rtp help for further information.\n"
134 "| -M <MPLS label> Insert a MPLS label. Enter '-M help' for a syntax description.\n"
135 "| -v|V Verbose and more verbose mode\n"
136 "| -q Quiet mode, i. e. even omit 'important standard short messages'.\n"
137 "| -S Simulation mode: DOES NOT put anything on the wire. This is\n"
138 "| typically combined with one of the verbose modes (v or V).\n"
148 int main(int argc
, char *argv
[])
152 // These handles are only used when creating L3 and above packets.
153 libnet_t
*l
; // the context
154 libnet_ptag_t t2
=0, t3
=0, t4
=0; // handles to layers
156 double cpu_time_used
;
158 // Check if we have root priviliges
159 if ( (getuid()!=0) && (geteuid()!=0) )
161 fprintf(stderr
, " Mausezahn requires root privileges.\n Exit.\n");
169 // Get all CLI options (sets globals, see mz.h)
170 if ( getopts(argc
, argv
) )
172 (void) fprintf(stderr
, " Invalid command line parameters!\n");
176 // Check whether hires timers are supported or not:
177 (void) check_timer();
181 // *********************************************************************
182 // First prefer data in a mausezahn description file!
183 // *********************************************************************
188 // Note that argument 'device' is also used here!
190 // Must end in state machine!
194 // *********************************************************************
195 // If no MDF given, then send packet according CLI specifications
196 // *********************************************************************
199 (void) signal(SIGINT
, clean_up
); // to close all file pointers etc upon SIGINT
219 case IP
: // From now on a new much more modular method is used:
220 l
= get_link_context();
221 t3
= create_ip_packet(l
); // t3 can be used for later header changes
222 if (!quiet
) complexity();
223 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
224 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
226 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
231 l
= get_link_context();
232 t4
= create_icmp_packet(l
); // t4 can be used for later header changes
233 t3
= create_ip_packet(l
); // t3 can be used for later header changes
234 if (!quiet
) complexity();
235 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
236 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
238 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
243 l
= get_link_context();
244 t4
= create_icmp6_packet(l
); // t4 can be used for later header changes
245 t3
= create_ip_packet(l
); // t3 can be used for later header changes
248 if (!quiet
) complexity();
249 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
250 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
252 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
257 l
= get_link_context();
258 t4
= create_udp_packet(l
); // t4 can be used for later header changes
259 t3
= create_ip_packet(l
); // t3 can be used for later header changes
262 if (!quiet
) complexity();
263 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
264 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
266 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
271 l
= get_link_context();
272 t4
= create_tcp_packet(l
); // t4 can be used for later header changes
273 t3
= create_ip_packet(l
); // t3 can be used for later header changes
276 if (!quiet
) complexity();
277 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
278 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
280 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
285 l
= get_link_context();
286 (void) create_dns_packet();
287 t4
= create_udp_packet(l
); // t4 can be used for later header changes
288 t3
= create_ip_packet(l
); // t3 can be used for later header changes
289 if (!quiet
) complexity();
290 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
291 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
293 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
298 l
= get_link_context();
299 if (!quiet
) fprintf(stderr
, " mz: RTP mode! (count=%u, delay=%u usec)\n\n", tx
.count
, tx
.delay
);
300 (void) create_rtp_packet();
301 t4
= create_udp_packet(l
); // t4 can be used for later header changes
302 t3
= create_ip_packet(l
); // t3 can be used for later header changes
303 if (!quiet
) complexity();
304 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
305 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
307 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
310 case RX_RTP
: // Receive RTP packets
317 l
= get_link_context();
318 (void) create_syslog_packet();
319 t4
= create_udp_packet(l
); // t4 can be used for later header changes
320 t3
= create_ip_packet(l
); // t3 can be used for later header changes
321 if (!quiet
) complexity();
323 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
324 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
326 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
329 case LLDP
: // start with a new concept here
330 //l = get_link_context();
331 //(void) create_lldp_packet();
332 // // // printf("SIZE=%lu\n",sizeof(struct tx_struct));
333 fprintf(stderr
, "LLDP is currently only supported via the interactive mode\n");
339 (void) fprintf(stderr
," mz/main: unknown mode! Stop.\n");
346 cpu_time_used
= ((double) (mz_stop
- mz_start
)) / CLOCKS_PER_SEC
;
347 if (cpu_time_used
> 0)
349 total_d
/= cpu_time_used
;
350 fprintf(stderr
, "%.2f seconds (%.Lf packets per second)\n",cpu_time_used
,total_d
);
354 fprintf(stderr
, "\n");