dev: mark paths likely/unlikely
[netsniff-ng.git] / staging / mausezahn.c
blob7831b90f81bd1a65c140057ed3d5101b80085a51
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Mausezahn, a fast versatile traffic generator
4 * Copyright 2008, 2009, 2010 Herbert Haas.
5 * Subject to the GPL, version 2.
6 */
8 #define _GNU_SOURCE
9 #include <libnet.h>
10 #include <pcap/pcap.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <limits.h>
17 #include <sys/time.h>
18 #include <time.h>
19 #include <signal.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <arpa/inet.h>
23 #include <sys/ioctl.h>
24 #include <netinet/in.h>
25 #include <stdarg.h>
27 #include "mz.h"
28 #include "cli.h"
29 #include "mops.h"
30 #include "llist.h"
31 #include "die.h"
33 int verbose_level = 0;
35 static const char *short_options = "46hqvVSxra:A:b:B:c:d:E:f:F:p:P:t:T:M:Q:X:";
37 static void signal_handler(int number)
39 clean_up(number);
42 void clean_up(int sig)
44 int i;
45 struct arp_table_struct *cur, *next;
47 if (!quiet) fprintf(stderr, "\nMausezahn cleans up...\n");
49 if (fp != NULL) {
50 verbose_l1(" close files (1) ...\n");
52 fflush(fp);
53 fclose(fp);
56 if (fp2!=NULL) {
57 if (verbose) fprintf(stderr, " close files (2) ...\n");
58 (void) fflush(fp2);
59 (void) fclose(fp2);
62 // interactive mode?
63 if (mz_port) {
64 if (verbose) fprintf(stderr, " clear mops list...\n");
65 mops_cleanup(mp_head);
66 if (verbose) fprintf(stderr, " clear automops list...\n");
67 automops_cleanup(amp_head);
68 if (verbose) fprintf(stderr, " clear packet sequences...\n");
69 mz_ll_delete_list(packet_sequences);
72 for (i=0; i<device_list_entries; i++) {
73 if (device_list[i].p_arp!=NULL) {
74 pcap_close(device_list[i].p_arp);
75 fprintf(stderr, " stopped ARP process for device %s\n", device_list[i].dev);
77 if (device_list[i].arprx_thread!=0) {
78 pthread_cancel(device_list[i].arprx_thread);
79 if (verbose)
80 fprintf(stderr, " (ARP thread for device %s done)\n", device_list[i].dev);
83 if (device_list[i].arp_table!=NULL) {
84 cur=device_list[i].arp_table;
85 while (cur!=NULL) {
86 next = cur->next;
87 if (cur!=NULL) free(cur);
88 cur=next;
92 // close packet sockets
93 if (device_list[i].ps>=0) {
94 close(device_list[i].ps);
99 if (verbose) fprintf(stderr, "finished.\n");
100 exit(sig);
104 static void help(void)
106 printf("\nmausezahn %s, a fast versatile traffic generator\n", VERSION_STRING);
107 puts("http://www.netsniff-ng.org\n\n"
108 "Usage: mausezahn [options] [interface] <keyword>|<arg-string>|<hex-string>\n"
109 "Options:\n"
110 " -x <port> Interactive mode with telnet CLI, default port: 25542\n"
111 " -4 IPv4 mode (default)\n"
112 " -6 IPv6 mode\n"
113 " -c <count> Send packet count times, default:1, infinite:0\n"
114 " -d <delay> Apply delay between transmissions. The delay value can be\n"
115 " specified in usec (default, no additional unit needed), or in\n"
116 " msec (e.g. 100m or 100msec), or in seconds (e.g. 100s or 100sec)\n"
117 " -r Multiplies the specified delay with a random value\n"
118 " -p <length> Pad the raw frame to specified length (using random bytes)\n"
119 " -a <srcmac|keyword> Use specified source mac address, no matter what has\n"
120 " been specified with other arguments; keywords see below,\n"
121 " Default is own interface\n"
122 " -b <dstmac|keyword> Same with destination mac address; keywords:\n"
123 " rand Use a random MAC address\n"
124 " bc Use a broadcast MAC address\n"
125 " own Use own interface MAC address (default for source MAC)\n"
126 " stp Use IEEE 802.1d STP multicast address\n"
127 " cisco Use Cisco multicast address as used for CDP, VTP, or PVST+\n"
128 " -A <srcip> Use specified source IP address (default is own interface IP)\n"
129 " -B <dstip|dnsname> Send packet to specified destination IP or domain name\n"
130 " -P <ascii payload> Use the specified ASCII payload\n"
131 " -f <filename> Read the ASCII payload from a file\n"
132 " -F <filename> Read the hexadecimal payload from a file\n"
133 " -Q <[CoS:]vlan> Specify 802.1Q VLAN tag and optional Class of Service, you can\n"
134 " specify multiple 802.1Q VLAN tags (QinQ...) by separating them\n"
135 " via a comma or a period (e.g. '5:10,20,2:30')\n"
136 " -t <packet-type> Specify packet type for autobuild (you don't need to care for\n"
137 " encapsulations in lower layers, most packet types allow/require\n"
138 " additional packet-specific arguments in an <arg-string>;\n"
139 " Currently supported types: arp, bpdu, cdp, ip, icmp, udp, tcp,\n"
140 " dns, rtp, syslog, lldp and more;\n"
141 " For context-help use 'help' as <arg-string>!\n"
142 " -T <packet-type> Specify packet type for server mode, currently only rtp is supported;\n"
143 " Enter -T help or -T rtp help for further information\n"
144 " -M <MPLS-label> Insert a MPLS label, enter '-M help' for a syntax description\n"
145 " -V|VV|... Verbose and more verbose mode\n"
146 " -q Quiet mode, even omit 'important' standard short messages\n"
147 " -S Simulation mode: DOES NOT put anything on the wire, this is\n"
148 " typically combined with one of the verbose modes (v or V)\n"
149 " -v Show version\n"
150 " -h Print this help\n\n"
151 "Examples:\n"
152 " mausezahn -x 99\n"
153 " mausezahn -c 0 -d 2s -t bpdu conf\n"
154 " mausezahn -t cdp change -c 0\n"
155 " mausezahn -t syslog sev=3 -P \"You have been mausezahned.\" -A 10.1.1.109 -B 192.168.7.7\n"
156 " mausezahn eth0 -A rand -B 1.1.1.1 -c 0 -t tcp \"dp=1-1023, flags=syn\"\n\n"
157 "Note:\n"
158 " This tool is targeted for network developers! You should\n"
159 " be aware of what you are doing and what these options above\n"
160 " mean! Only use this tool in an isolated LAN that you own!\n\n"
161 "Please report bugs to <bugs@netsniff-ng.org>\n"
162 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
163 "Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
164 "Swiss federal institute of technology (ETH Zurich)\n"
165 "License: GNU GPL version 2.0\n"
166 "This is free software: you are free to change and redistribute it.\n"
167 "There is NO WARRANTY, to the extent permitted by law.\n");
168 die();
171 static void version(void)
173 printf("\nmausezahn %s, a fast versatile traffic generator\n", VERSION_LONG);
174 puts("http://www.netsniff-ng.org\n\n"
175 "Please report bugs to <bugs@netsniff-ng.org>\n"
176 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
177 "Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
178 "Swiss federal institute of technology (ETH Zurich)\n"
179 "License: GNU GPL version 2.0\n"
180 "This is free software: you are free to change and redistribute it.\n"
181 "There is NO WARRANTY, to the extent permitted by law.\n");
182 die();
185 int reset()
187 int i;
188 time_t t;
190 // Determine platform type sizes:
191 MZ_SIZE_LONG_INT = sizeof(long int);
193 mz_default_config_path[0] = 0x00;
194 mz_default_log_path[0] = 0x00;
196 // Reset globals:
197 quiet = 0;
198 ipv6_mode = 0;
199 verbose = 0;
200 simulate = 0;
201 filename[0] = '\0';
202 path[0] = '\0';
203 gind=0;
204 gind_max = TIME_COUNT;
205 fp = NULL;
206 fp2 = NULL;
207 mz_port = 0;
208 mz_rand = 0;
209 mp_head = NULL;
211 for (i=0;i<TIME_COUNT_MAX;i++) jitter[i] = 0;
213 time0_flag = 0; // If set then time0 has valid data
214 sqnr0_flag = 0; // If set then sqnr_last and sqnr_next has valid data
215 rtp_log = 0;
216 mz_ssrc[0]=0; mz_ssrc[1]=0; mz_ssrc[2]=0; mz_ssrc[3]=0;
218 // Reset mgmt parameters of TX:
219 tx.packet_mode = 1; // assume we don't care about L2
220 tx.count = 1;
221 tx.delay = DEFAULT_DELAY;
222 tx.arg_string[0] = '\0';
224 // Reset Ethernet parameters of TX:
225 tx.eth_params_already_set = 0;
226 for (i=0; i<6; i++) tx.eth_dst[i] = 0xff;
227 for (i=0; i<6; i++) tx.eth_src[i] = 0; // TODO: Get own MAC !!!
228 tx.eth_dst_txt[0] = '\0';
229 tx.eth_src_txt[0] = '\0';
230 tx.eth_dst_rand = 0;
231 tx.eth_src_rand = 0;
233 tx.eth_type = 0x800;
234 tx.eth_len = 0;
235 tx.eth_payload[0] = '\0';
236 tx.eth_payload_s = 0;
237 tx.padding = 0;
239 // Reset CDP parameters for TX:
240 tx.cdp_sum = 0;
241 tx.cdp_version = 0;
242 tx.cdp_ttl = 0;
243 tx.cdp_payload[0] = '\0';
244 tx.cdp_payload_s = 0;
245 tx.cdp_tlv_id[0] = '\0';
246 tx.cdp_tlv_id_len = 0;
248 // Reset 802.1Q parameters of TX:
249 tx.dot1Q=0;
250 tx.dot1Q_txt[0] = '\0';
252 // ASCII Payload:
253 tx.ascii = 0; // 1 if specified
254 tx.ascii_payload[0]= '\0';
256 // HEX Payload:
257 tx.hex_payload_s = 0;
259 // Reset MPLS parameters of TX:
260 tx.mpls = 0;
261 tx.mpls_txt[0] = '\0';
262 tx.mpls_label = 0;
263 tx.mpls_exp = 0;
264 tx.mpls_bos = 1;
265 tx.mpls_ttl = 255;
266 tx.mpls_verbose_string[0] = '\0';
268 // Reset IP parameters of TX:
269 tx.ip_src_txt[0] = '\0';
270 tx.ip_src_rand = 0;
271 tx.ip_dst_txt[0] = '\0';
272 tx.ip_src_isrange = 0;
273 tx.ip_src_start = 0;
274 tx.ip_src_stop = 0;
276 tx.ip_dst_start = 0;
277 tx.ip_dst_stop = 0;
278 tx.ip_dst_isrange = 0;
280 tx.ip_len = 0;
281 tx.ip_payload[0]= '\0';
282 tx.ip_payload_s = 0;
283 tx.ip_option[0]= '\0';
284 tx.ip_option_s = 0;
286 // Reset ICMP parameters:
287 tx.icmp_type=0;
288 tx.icmp_code=0;
289 tx.icmp_chksum=0; // 0=autofill
290 tx.icmp_ident=0x42;
291 tx.icmp_sqnr=0x1;
292 tx.icmp_payload_s=0;
294 // Reset general L4 parameters:
295 tx.sp = 0;
296 tx.dp = 0;
297 tx.sp_start = 0;
298 tx.sp_stop = 0;
299 tx.dp_start = 0;
300 tx.dp_stop = 0;
301 tx.sp_isrange = 0;
302 tx.dp_isrange = 0;
304 // Reset UDP parameters of TX:
306 tx.udp_len = 0; // If set to zero then create_udp_packet will calculate it
307 tx.udp_sum = 0;
308 tx.udp_payload[0] = '\0';
309 tx.udp_payload_s = 0;
311 // Reset TCP parameters of TX:
313 tx.tcp_seq = 42;
314 tx.tcp_seq_stop = 42;
315 tx.tcp_seq_delta = 0; // also used as 'isrange' meaning
316 tx.tcp_ack = 42;
317 tx.tcp_control = 0;
318 tx.tcp_win = 10000;
319 tx.tcp_sum = 0;
320 tx.tcp_urg = 0;
321 tx.tcp_len = 20; // Least size (TCP header only)
322 tx.tcp_payload[0] = '\0';
323 tx.tcp_payload_s = 0;
325 // Reset RTP parameters of TX:
326 tx.rtp_sqnr = 0;
327 tx.rtp_stmp = 0;
329 // Initialize random generator
330 time(&t);
331 srand((unsigned int)t);
333 // Reset device_list
334 for (i=0; i<MZ_MAX_DEVICES; i++) {
335 device_list[i].arprx_thread = 0;
336 device_list[i].p_arp = NULL;
337 device_list[i].arp_table = NULL;
338 device_list[i].ps=-1;
339 device_list[i].cli=0;
340 device_list[i].mgmt_only=0;
343 return 0;
348 // Purpose: Properly handle arguments and configure global structs (tx)
349 int getopts (int argc, char *argv[])
351 int i, c, rargs, RX=0, count_set=0, delay_set=0;
352 unsigned int time_factor;
353 char *packet_type=NULL, *mops_type=NULL;
354 char *dum;
355 unsigned char *dum1, *dum2;
357 libnet_t *l;
358 char err_buf[LIBNET_ERRBUF_SIZE];
359 struct libnet_ether_addr *mymac;
361 FILE *afp;
362 char hexpld[MAX_PAYLOAD_SIZE*2];
363 int hexpld_specified=0;
365 opterr = 1; // let getopt print error message if necessary
368 while ((c = getopt(argc, argv, short_options)) != -1)
369 switch (c) {
370 case '4':
371 tx.eth_type = 0x0800;
372 ipv6_mode=0;
373 break;
374 case '6':
375 tx.eth_type = 0x86dd;
376 ipv6_mode=1;
377 break;
378 case 'h':
379 help();
380 break;
381 case 'q':
382 quiet=1;
383 break;
384 case 'v':
385 version();
386 break;
387 case 'V':
388 verbose++;
389 break;
390 case 'S':
391 simulate=1;
392 break;
393 case 'x':
394 mz_port = MZ_DEFAULT_PORT;
395 break;
396 case 'a':
397 strncpy (tx.eth_src_txt, optarg, 32);
398 tx.packet_mode = 0;
399 break;
400 case 'A':
401 strncpy (tx.ip_src_txt, optarg, sizeof(tx.ip_src_txt));
402 break;
403 case 'b':
404 strncpy (tx.eth_dst_txt, optarg, 32);
405 tx.packet_mode = 0;
406 break;
407 case 'B':
408 strncpy (tx.ip_dst_txt, optarg, sizeof(tx.ip_dst_txt));
409 break;
410 case 'c':
411 errno=0;
412 tx.count = strtol(optarg, (char **)NULL, 10);
413 if ((errno == ERANGE && (tx.count == LONG_MAX || tx.count == LONG_MIN))
414 || (errno != 0 && tx.count == 0)) {
415 perror("strtol");
416 return (-1);
418 if (tx.count<0) tx.count=1; //TODO: Allow count=0 which means infinity (need to update all send_functions)
419 count_set=1;
420 break;
421 case 'd':
422 errno=0;
423 // determine whether seconds or msecs are used
424 // default is usec!!!
425 time_factor=1;
426 if (exists(optarg,"s") || exists(optarg,"sec")) time_factor=1000000;
427 if (exists(optarg,"m") || exists(optarg,"msec")) time_factor=1000;
428 dum = strtok(optarg,"ms");
429 tx.delay = strtol(dum, (char **)NULL, 10) * time_factor;
430 if ((errno == ERANGE && (tx.delay == LONG_MAX || tx.delay == LONG_MIN))
431 || (errno != 0 && tx.delay == 0)) {
432 perror("strtol");
433 return (-1);
435 if (tx.delay<0) tx.delay=0; // no delay
436 delay_set=1;
437 break;
438 case 'p':
439 errno=0;
440 tx.padding = strtol(optarg, (char **)NULL, 10);
441 if ((errno == ERANGE && (tx.padding == LONG_MAX || tx.padding == LONG_MIN))
442 || (errno != 0 && tx.padding == 0)) {
443 perror("strtol");
444 return (-1);
446 if (tx.padding>10000) {
447 fprintf(stderr, " Warning: Padding must not exceed 10000!\n");
448 return -1;
450 break;
451 case 't':
452 packet_type = optarg; // analyzed below
453 break;
454 case 'X':
455 mops_type = optarg; // MOPS TRANSITION STRATEGY -- analyzed below
456 break;
457 case 'T':
458 packet_type = optarg;
459 RX = 1;
460 break;
461 case 'r':
462 mz_rand = 1;
463 break;
464 case 'M':
465 if (strncmp(optarg,"help",4)==0) {
466 (void) get_mpls_params("help ");
468 else {
469 strncpy (tx.mpls_txt, optarg, 128);
470 tx.eth_type = ETHERTYPE_MPLS;
471 tx.packet_mode = 0;
472 tx.mpls=1;
474 break;
475 case 'P': // ASCII payload
476 strncpy((char*)tx.ascii_payload, optarg, MAX_PAYLOAD_SIZE);
477 tx.ascii = 1;
478 break;
479 case 'f': // ASCII payload in FILE
480 afp = fopen(optarg, "r");
481 if (fgets((char*)tx.ascii_payload, MAX_PAYLOAD_SIZE, afp) == NULL)
482 fprintf(stderr, " mz/getopts: File empty?\n");
483 fclose(afp);
484 tx.ascii = 1;
485 break;
486 case 'F': // HEX payload in FILE
487 afp = fopen(optarg, "r");
488 i=0;
489 while ( (hexpld[i]=fgetc(afp))!=EOF ) {
490 if (isspace(hexpld[i])) {
491 hexpld[i]=':';
493 i++;
495 hexpld[i]='\0';
496 fclose(afp);
497 hexpld_specified=1;
498 break;
499 case 'Q': // VLAN TAG
500 if (strncmp(optarg,"help",4)==0) {
501 print_dot1Q_help(); // ugly but most simple and safe solution
503 else {
504 strncpy (tx.dot1Q_txt, optarg, 32);
505 tx.dot1Q=1;
506 // determine number of VLAN tags
507 for (i=0; i<strlen(tx.dot1Q_txt); i++) {
508 if (tx.dot1Q_txt[i]==',') tx.dot1Q++;
510 tx.packet_mode = 0;
512 break;
513 case '?':
514 if ((optopt == 'a') || (optopt == 'b') || (optopt = 'c') ||
515 (optopt == 'd') || (optopt == 'f') || (optopt = 'p') ||
516 (optopt == 't') || (optopt == 'm'))
517 fprintf (stderr, " mz/getopts: Option -%c requires an argument.\n", optopt);
518 else if (isprint (optopt))
519 fprintf (stderr, " mz/getopts: Unknown option -%c'.\n", optopt);
520 else
521 fprintf (stderr, " mz/getopts: Unknown option character \\x%x'.\n", optopt);
522 return 1;
523 default:
524 fprintf (stderr," mz/getopts: Could not handle arguments properly!\n");
525 return 1;
528 // ********************************************
529 // Handle additional arguments
530 // ********************************************
532 // Greeting text
533 if (verbose) {
534 fprintf(stderr,"\n"
535 MAUSEZAHN_VERSION
536 "\n"
537 "Use at your own risk and responsibility!\n"
538 "-- Verbose mode --\n"
539 "\n");
542 if (argc<2) {
543 help();
546 if ((rargs=argc-optind)>2) { // number of remaining arguments
547 fprintf(stderr," mz/getopts: Too many arguments!\n");
548 return -1;
552 // There can be 0-2 additional arguments
553 switch (rargs) {
554 case 0:
555 if (lookupdev()) { // no device found
556 if (verbose) fprintf(stderr, " mz: no active interfaces found!\n");
557 strcpy(tx.device, "lo");
559 if (verbose) // device found
560 fprintf(stderr," mz: device not given, will use %s\n",tx.device);
561 break;
562 case 1: // arg_string OR device given => find out!
563 if ( (strncmp(argv[optind],"eth",3)==0)
564 || (strncmp(argv[optind],"ath",3)==0)
565 || ((strncmp(argv[optind],"lo",2)==0)&&(strncmp(argv[optind],"log",3)!=0))
566 || (strncmp(argv[optind],"vmnet",5)==0)
567 || (strncmp(argv[optind],"wifi",4)==0) ) {
568 // device has been specified!
569 strncpy (tx.device, argv[optind], 16);
571 else { /// arg_string given => no device has been specified -- let's find one!
572 strncpy (tx.arg_string, argv[optind], MAX_PAYLOAD_SIZE);
573 if (lookupdev()) { // no device found
574 if (verbose) fprintf(stderr, " mz: no active interfaces found!\n");
575 strcpy(tx.device, "lo");
577 if (verbose)
578 fprintf(stderr," mz: device not given, will use %s\n",tx.device);
580 break;
581 case 2: // both device and arg_string given
582 strncpy (tx.device, argv[optind], 16);
583 strncpy (tx.arg_string, argv[optind+1], MAX_PAYLOAD_SIZE);
584 break;
585 default:
586 fprintf(stderr," mz/getopts: Unknown argument problem!\n");
587 return 1;
590 if (hexpld_specified) {
591 strcat(tx.arg_string, ",p=");
592 strcat(tx.arg_string, hexpld);
596 //////////////////////////////////////////////////////////////////////////
598 // Initialize MAC and IP Addresses.
600 // - tx.eth_src = own interface MAC
601 // - tx.ip_src = own interface IP or user specified
602 // - tx.ip_dst = 255.255.255.255 or user specified (can be a range)
603 // - tx.ip_src_rand ... is set if needed.
606 // Get own device MAC address:
607 // Don't open context if only a help text is requested
608 if (getarg(tx.arg_string,"help", NULL)!=1) {
609 l = libnet_init (LIBNET_LINK_ADV, tx.device, err_buf );
610 if (l == NULL) {
611 fprintf(stderr, " mz/getopts: libnet_init() failed (%s)", err_buf);
612 return -1;
614 mymac = libnet_get_hwaddr(l);
615 for (i=0; i<6; i++) {
616 tx.eth_src[i] = mymac->ether_addr_octet[i];
617 tx.eth_mac_own[i] = mymac->ether_addr_octet[i];
620 // Set source IP address:
621 if (strlen(tx.ip_src_txt)) { // option -A has been specified
622 if (mz_strcmp(tx.ip_src_txt, "bcast", 2)==0) {
623 tx.ip_src = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
624 } else if (strcmp(tx.ip_src_txt, "rand") == 0) {
625 tx.ip_src_rand = 1;
626 tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0
628 else if (get_ip_range_src(tx.ip_src_txt)) { // returns 1 when no range has been specified
629 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
630 if (ipv6_mode)
631 tx.ip6_src = libnet_name2addr6 (l, tx.ip_src_txt, LIBNET_RESOLVE);
632 else
633 tx.ip_src = libnet_name2addr4 (l, tx.ip_src_txt, LIBNET_RESOLVE);
636 else { // no source IP specified: by default use own IP address
637 if (ipv6_mode) {
638 tx.ip6_src = libnet_get_ipaddr6(l);
639 if (strncmp((char*)&tx.ip6_src,(char*)&in6addr_error,sizeof(in6addr_error))==0)
640 printf("Failed to set source IPv6 address: %s", l->err_buf);
642 else
643 tx.ip_src = libnet_get_ipaddr4(l);
646 // Set destination IP address:
647 if (strlen(tx.ip_dst_txt)) { // option -B has been specified
648 if (mz_strcmp(tx.ip_dst_txt, "rand", 2)==0) {
649 fprintf(stderr, "Option -B does not support random destination IP addresses currently.\n");
650 return 1;
653 if (mz_strcmp(tx.ip_dst_txt, "bcast", 2)==0) {
654 tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
655 } else if (get_ip_range_dst(tx.ip_dst_txt)) { // returns 1 when no range has been specified
656 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
657 if (ipv6_mode)
658 tx.ip6_dst = libnet_name2addr6 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
659 else
660 tx.ip_dst = libnet_name2addr4 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
663 else { // no destination IP specified: by default use broadcast
664 tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
667 // Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()'
668 // in verbose mode. See 'modifications.c'.
670 if (tx.ip_src_rand) { // ip_src_h already given, convert to ip_src
671 dum1 = (unsigned char*) &tx.ip_src_h;
672 dum2 = (unsigned char*) &tx.ip_src;
674 else { // ip_src already given, convert to ip_src_h
675 dum1 = (unsigned char*) &tx.ip_src;
676 dum2 = (unsigned char*) &tx.ip_src_h;
679 *dum2 = *(dum1+3);
680 dum2++;
681 *dum2 = *(dum1+2);
682 dum2++;
683 *dum2 = *(dum1+1);
684 dum2++;
685 *dum2 = *dum1;
687 dum1 = (unsigned char*) &tx.ip_dst;
688 dum2 = (unsigned char*) &tx.ip_dst_h;
690 *dum2 = *(dum1+3);
691 dum2++;
692 *dum2 = *(dum1+2);
693 dum2++;
694 *dum2 = *(dum1+1);
695 dum2++;
696 *dum2 = *dum1;
698 libnet_destroy(l);
702 // END OF ADDRESS INITIALIZATION
704 //////////////////////////////////////////////////////////////////////////
707 ////// retrieve interface parameters ///////
709 for (i=0; i<device_list_entries; i++) {
710 get_dev_params(device_list[i].dev);
714 //////////////////////////////////////////////////////////////////////////
716 // Mausezahn CLI desired?
717 if (mz_port) {
718 // has port number been specified?
719 if (strlen(tx.arg_string)) {
720 mz_port = (int) str2int (tx.arg_string);
723 if (!quiet) {
724 fprintf(stderr, "Mausezahn accepts incoming Telnet connections on port %i.\n", mz_port);
727 mz_cli_init();
728 cli();
731 //////////////////////////////////////////////////////////////////////////
733 // Mode decision
735 // Consider -t and -m option (used exclusively)
736 // -t => special packet types, stateless
738 // If -t not present then evaluate arg_string which must
739 // contain a byte-string in hexadecimal notation.
743 // ***** NEW: MOPS TRANSITION STRATEGY *****
744 if (mops_type != NULL) {
746 if (mz_strcmp(mops_type,"lldp",4)==0) {
747 mops_direct(tx.device, MOPS_LLDP, tx.arg_string);
752 if (packet_type == NULL) { // raw hex string given
753 mode = BYTE_STREAM;
755 else if (strcmp(packet_type,"arp")==0) {
756 mode = ARP;
758 else if (strcmp(packet_type,"bpdu")==0) {
759 mode = BPDU;
761 else if (strcmp(packet_type,"ip")==0) {
762 mode = IP;
764 else if (strcmp(packet_type,"udp")==0) {
765 mode = UDP;
767 else if (strcmp(packet_type,"icmp")==0) {
768 mode = ICMP;
770 else if (strcmp(packet_type,"icmp6")==0) {
771 mode = ICMP6;
773 else if (strcmp(packet_type,"tcp")==0) {
774 mode = TCP;
776 else if (strcmp(packet_type,"dns")==0) {
777 mode = DNS;
779 else if (strcmp(packet_type,"cdp")==0) {
780 mode = CDP;
782 else if (strcmp(packet_type,"syslog")==0) {
783 mode = SYSLOG;
785 else if (strcmp(packet_type,"lldp")==0) {
786 mode = LLDP;
787 tx.packet_mode=0; // create whole frame by ourself
789 else if (strcmp(packet_type,"rtp")==0) {
790 if (RX) {
791 mode = RX_RTP;
793 else {
794 mode = RTP;
795 if (!count_set) tx.count = 0;
796 if (!delay_set) tx.delay = 20000; // 20 msec inter-packet delay for RTP
799 else if (strcmp(packet_type,"help")==0) {
800 fprintf(stderr, "\n"
801 MAUSEZAHN_VERSION
802 "\n"
803 "| The following packet types are currently implemented:\n"
804 "|\n"
805 "| arp ... sends ARP packets\n"
806 "| bpdu ... sends BPDU packets (STP or PVST+)\n"
807 "| cdp ... sends CDP messages\n"
808 "| ip ... sends IPv4 packets\n"
809 "| udp ... sends UDP datagrams\n"
810 "| tcp ... sends TCP segments\n"
811 "| icmp ... sends ICMP messages\n"
812 "| dns ... sends DNS messages\n"
813 "| rtp ... sends RTP datagrams\n"
814 "| syslog ... sends Syslog messages\n"
815 "|\n"
816 "| Of course you can build any other packet type 'manually' using the direct layer 2 mode.\n"
817 "| FYI: The interactive mode supports additional protocols. (Try mz -x <port>)\n"
818 "\n"
820 exit(1);
822 else {
823 fprintf(stderr, " mz: you must specify a valid packet type!\n");
827 //////////////////////////////////////////////////////////////////////////
829 // TODO: Implement macro support
830 // Check macro types here
832 return 0;
835 int main(int argc, char **argv)
837 // These handles are only used when creating L3 and above packets.
838 libnet_t *l; // the context
839 libnet_ptag_t t2=0, t3=0, t4=0; // handles to layers
840 double cpu_time_used;
842 reset();
844 if ( getopts(argc, argv) )
846 (void) fprintf(stderr, " Invalid command line parameters!\n");
847 help();
850 // Check whether hires timers are supported or not:
851 (void) check_timer();
853 signal(SIGINT, signal_handler); // to close all file pointers etc upon SIGINT
855 switch (mode)
857 case BYTE_STREAM:
858 send_eth();
859 break;
861 case ARP:
862 (void) send_arp();
863 break;
865 case BPDU:
866 (void) send_bpdu();
867 break;
869 case CDP:
870 (void) send_cdp();
871 break;
873 case IP: // From now on a new much more modular method is used:
874 l = get_link_context();
875 t3 = create_ip_packet(l); // t3 can be used for later header changes
876 if (!quiet) complexity();
877 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
878 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
879 else
880 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
881 break;
883 case ICMP:
884 tx.ip_proto = 1;
885 l = get_link_context();
886 t4 = create_icmp_packet(l); // t4 can be used for later header changes
887 t3 = create_ip_packet(l); // t3 can be used for later header changes
888 if (!quiet) complexity();
889 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
890 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
891 else
892 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
893 break;
895 case ICMP6:
896 tx.ip_proto = 58;
897 l = get_link_context();
898 t4 = create_icmp6_packet(l); // t4 can be used for later header changes
899 t3 = create_ip_packet(l); // t3 can be used for later header changes
900 if (ipv6_mode)
901 update_ISUM(l, t4);
902 if (!quiet) complexity();
903 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
904 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
905 else
906 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
907 break;
909 case UDP:
910 tx.ip_proto = 17;
911 l = get_link_context();
912 t4 = create_udp_packet(l); // t4 can be used for later header changes
913 t3 = create_ip_packet(l); // t3 can be used for later header changes
914 if (ipv6_mode)
915 update_USUM(l, t4);
916 if (!quiet) complexity();
917 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
918 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
919 else
920 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
921 break;
923 case TCP:
924 tx.ip_proto = 6;
925 l = get_link_context();
926 t4 = create_tcp_packet(l); // t4 can be used for later header changes
927 t3 = create_ip_packet(l); // t3 can be used for later header changes
928 if (ipv6_mode)
929 update_TSUM(l, t4);
930 if (!quiet) complexity();
931 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
932 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
933 else
934 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
935 break;
937 case DNS:
938 tx.ip_proto = 17;
939 l = get_link_context();
940 (void) create_dns_packet();
941 t4 = create_udp_packet(l); // t4 can be used for later header changes
942 t3 = create_ip_packet(l); // t3 can be used for later header changes
943 if (!quiet) complexity();
944 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
945 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
946 else
947 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
948 break;
950 case RTP:
951 tx.ip_proto = 17;
952 l = get_link_context();
953 if (!quiet) fprintf(stderr, " mz: RTP mode! (count=%u, delay=%u usec)\n\n", tx.count, tx.delay);
954 (void) create_rtp_packet();
955 t4 = create_udp_packet(l); // t4 can be used for later header changes
956 t3 = create_ip_packet(l); // t3 can be used for later header changes
957 if (!quiet) complexity();
958 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
959 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
960 else
961 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
962 break;
964 case RX_RTP: // Receive RTP packets
965 rcv_rtp_init();
966 rcv_rtp();
967 break;
969 case SYSLOG:
970 tx.ip_proto = 17;
971 l = get_link_context();
972 (void) create_syslog_packet();
973 t4 = create_udp_packet(l); // t4 can be used for later header changes
974 t3 = create_ip_packet(l); // t3 can be used for later header changes
975 if (!quiet) complexity();
977 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
978 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
979 else
980 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
981 break;
983 case LLDP: // start with a new concept here
984 //l = get_link_context();
985 //(void) create_lldp_packet();
986 // // // printf("SIZE=%lu\n",sizeof(struct tx_struct));
987 fprintf(stderr, "LLDP is currently only supported via the interactive mode\n");
988 exit(1);
989 break;
992 default:
993 (void) fprintf(stderr," mz/main: unknown mode! Stop.\n");
994 return (1);
997 if (!quiet)
999 mz_stop = clock();
1000 cpu_time_used = ((double) (mz_stop - mz_start)) / CLOCKS_PER_SEC;
1001 if (cpu_time_used > 0)
1003 total_d /= cpu_time_used;
1004 fprintf(stderr, "%.2f seconds (%.Lf packets per second)\n",cpu_time_used,total_d);
1006 else
1008 fprintf(stderr, "\n");
1012 return(0);