netsniff-ng: Allow to compile without libnl
[netsniff-ng-new.git] / staging / mausezahn.c
blob70f1e72a7ef1ce640d5349a880e24f83204f84e2
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 "config.h"
31 #include "llist.h"
32 #include "die.h"
34 int verbose_level = 0;
36 static const char *short_options = "46hqvVSxra:A:b:B:c:d:E:f:F:l:p:P:t:T:M:Q:X:";
38 static void signal_handler(int number)
40 clean_up(number);
43 void clean_up(int sig)
45 int i;
46 struct arp_table_struct *cur, *next;
48 if (!quiet) fprintf(stderr, "\nMausezahn cleans up...\n");
50 if (fp != NULL) {
51 verbose_l1(" close files (1) ...\n");
53 fflush(fp);
54 fclose(fp);
57 if (fp2!=NULL) {
58 if (verbose) fprintf(stderr, " close files (2) ...\n");
59 (void) fflush(fp2);
60 (void) fclose(fp2);
63 // interactive mode?
64 if (mz_port) {
65 if (verbose) fprintf(stderr, " clear mops list...\n");
66 mops_cleanup(mp_head);
67 if (verbose) fprintf(stderr, " clear automops list...\n");
68 automops_cleanup(amp_head);
69 if (verbose) fprintf(stderr, " clear packet sequences...\n");
70 mz_ll_delete_list(packet_sequences);
73 for (i=0; i<device_list_entries; i++) {
74 if (device_list[i].p_arp!=NULL) {
75 pcap_close(device_list[i].p_arp);
76 fprintf(stderr, " stopped ARP process for device %s\n", device_list[i].dev);
78 if (device_list[i].arprx_thread!=0) {
79 pthread_cancel(device_list[i].arprx_thread);
80 if (verbose)
81 fprintf(stderr, " (ARP thread for device %s done)\n", device_list[i].dev);
84 if (device_list[i].arp_table!=NULL) {
85 cur=device_list[i].arp_table;
86 while (cur!=NULL) {
87 next = cur->next;
88 if (cur!=NULL) free(cur);
89 cur=next;
93 // close packet sockets
94 if (device_list[i].ps>=0) {
95 close(device_list[i].ps);
100 if (verbose) fprintf(stderr, "finished.\n");
101 exit(sig);
105 static void help(void)
107 printf("\nmausezahn %s, a fast versatile traffic generator\n", VERSION_STRING);
108 puts("http://www.netsniff-ng.org\n\n"
109 "Usage: mausezahn [options] [interface] <keyword>|<arg-string>|<hex-string>\n"
110 "Options:\n"
111 " -x <port> Interactive mode with telnet CLI, default port: 25542\n"
112 " -l <ip> Listen address to bind to when in interactive mode, default: 0.0.0.0\n"
113 " -4 IPv4 mode (default)\n"
114 " -6 IPv6 mode\n"
115 " -c <count> Send packet count times, default:1, infinite:0\n"
116 " -d <delay> Apply delay between transmissions. The delay value can be\n"
117 " specified in usec (default, no additional unit needed), or in\n"
118 " msec (e.g. 100m or 100msec), or in seconds (e.g. 100s or 100sec)\n"
119 " -r Multiplies the specified delay with a random value\n"
120 " -p <length> Pad the raw frame to specified length (using random bytes)\n"
121 " -a <srcmac|keyword> Use specified source mac address, no matter what has\n"
122 " been specified with other arguments; keywords see below,\n"
123 " Default is own interface\n"
124 " -b <dstmac|keyword> Same with destination mac address; keywords:\n"
125 " rand Use a random MAC address\n"
126 " bc Use a broadcast MAC address\n"
127 " own Use own interface MAC address (default for source MAC)\n"
128 " stp Use IEEE 802.1d STP multicast address\n"
129 " cisco Use Cisco multicast address as used for CDP, VTP, or PVST+\n"
130 " -A <srcip> Use specified source IP address (default is own interface IP)\n"
131 " -B <dstip|dnsname> Send packet to specified destination IP or domain name\n"
132 " -P <ascii payload> Use the specified ASCII payload\n"
133 " -f <filename> Read the ASCII payload from a file\n"
134 " -F <filename> Read the hexadecimal payload from a file\n"
135 " -Q <[CoS:]vlan> Specify 802.1Q VLAN tag and optional Class of Service, you can\n"
136 " specify multiple 802.1Q VLAN tags (QinQ...) by separating them\n"
137 " via a comma or a period (e.g. '5:10,20,2:30')\n"
138 " -t <packet-type|help> Specify packet type for autobuild (you don't need to care for\n"
139 " encapsulations in lower layers, most packet types allow/require\n"
140 " additional packet-specific arguments in an <arg-string>;\n"
141 " Currently supported types: arp, bpdu, cdp, ip, icmp, udp, tcp,\n"
142 " dns, rtp, syslog, lldp and more;\n"
143 " For context-help use 'help' as <arg-string>!\n"
144 " -T <packet-type> Specify packet type for server mode, currently only rtp is supported;\n"
145 " Enter -T help or -T rtp help for further information\n"
146 " -M <MPLS-label> Insert a MPLS label, enter '-M help' for a syntax description\n"
147 " -V|VV|... Verbose and more verbose mode\n"
148 " -q Quiet mode, even omit 'important' standard short messages\n"
149 " -S Simulation mode: DOES NOT put anything on the wire, this is\n"
150 " typically combined with one of the verbose modes (v or V)\n"
151 " -v Show version\n"
152 " -h Print this help\n\n"
153 "Examples:\n"
154 " mausezahn -x 99\n"
155 " mausezahn -c 0 -d 2s -t bpdu conf\n"
156 " mausezahn -t cdp change -c 0\n"
157 " mausezahn -t syslog sev=3 -P \"You have been mausezahned.\" -A 10.1.1.109 -B 192.168.7.7\n"
158 " mausezahn eth0 -A rand -B 1.1.1.1 -c 0 -t tcp \"dp=1-1023, flags=syn\"\n\n"
159 "Note:\n"
160 " This tool is targeted for network developers! You should\n"
161 " be aware of what you are doing and what these options above\n"
162 " mean! Only use this tool in an isolated LAN that you own!\n\n"
163 "Please report bugs to <bugs@netsniff-ng.org>\n"
164 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
165 "Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
166 "Swiss federal institute of technology (ETH Zurich)\n"
167 "License: GNU GPL version 2.0\n"
168 "This is free software: you are free to change and redistribute it.\n"
169 "There is NO WARRANTY, to the extent permitted by law.\n");
170 die();
173 static void version(void)
175 printf("\nmausezahn %s, Git id: %s\n", VERSION_LONG, GITVERSION);
176 puts("a fast versatile traffic generator\n"
177 "http://www.netsniff-ng.org\n\n"
178 "Please report bugs to <bugs@netsniff-ng.org>\n"
179 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
180 "Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
181 "Swiss federal institute of technology (ETH Zurich)\n"
182 "License: GNU GPL version 2.0\n"
183 "This is free software: you are free to change and redistribute it.\n"
184 "There is NO WARRANTY, to the extent permitted by law.\n");
185 die();
188 int reset(void)
190 int i;
191 time_t t;
193 // Determine platform type sizes:
194 MZ_SIZE_LONG_INT = sizeof(long int);
196 mz_default_config_path[0] = 0x00;
197 mz_default_log_path[0] = 0x00;
199 // Reset globals:
200 quiet = 0;
201 ipv6_mode = 0;
202 verbose = 0;
203 simulate = 0;
204 filename[0] = '\0';
205 path[0] = '\0';
206 gind=0;
207 gind_max = TIME_COUNT;
208 fp = NULL;
209 fp2 = NULL;
210 mz_port = 0;
211 mz_rand = 0;
212 char mz_listen_addr[16] = "0.0.0.0";
213 mp_head = NULL;
215 for (i=0;i<TIME_COUNT_MAX;i++) jitter[i] = 0;
217 time0_flag = 0; // If set then time0 has valid data
218 sqnr0_flag = 0; // If set then sqnr_last and sqnr_next has valid data
219 rtp_log = 0;
220 mz_ssrc[0]=0; mz_ssrc[1]=0; mz_ssrc[2]=0; mz_ssrc[3]=0;
222 // Reset mgmt parameters of TX:
223 tx.packet_mode = 1; // assume we don't care about L2
224 tx.count = 1;
225 tx.delay = DEFAULT_DELAY;
226 tx.arg_string[0] = '\0';
228 // Reset Ethernet parameters of TX:
229 tx.eth_params_already_set = 0;
230 for (i=0; i<6; i++) tx.eth_dst[i] = 0xff;
231 for (i=0; i<6; i++) tx.eth_src[i] = 0; // TODO: Get own MAC !!!
232 tx.eth_dst_txt[0] = '\0';
233 tx.eth_src_txt[0] = '\0';
234 tx.eth_dst_rand = 0;
235 tx.eth_src_rand = 0;
237 tx.eth_type = 0x800;
238 tx.eth_len = 0;
239 tx.eth_payload[0] = '\0';
240 tx.eth_payload_s = 0;
241 tx.padding = 0;
243 // Reset CDP parameters for TX:
244 tx.cdp_sum = 0;
245 tx.cdp_version = 0;
246 tx.cdp_ttl = 0;
247 tx.cdp_payload[0] = '\0';
248 tx.cdp_payload_s = 0;
249 tx.cdp_tlv_id[0] = '\0';
250 tx.cdp_tlv_id_len = 0;
252 // Reset 802.1Q parameters of TX:
253 tx.dot1Q=0;
254 tx.dot1Q_txt[0] = '\0';
256 // ASCII Payload:
257 tx.ascii = 0; // 1 if specified
258 tx.ascii_payload[0]= '\0';
260 // HEX Payload:
261 tx.hex_payload_s = 0;
263 // Reset MPLS parameters of TX:
264 tx.mpls = 0;
265 tx.mpls_txt[0] = '\0';
266 tx.mpls_label = 0;
267 tx.mpls_exp = 0;
268 tx.mpls_bos = 1;
269 tx.mpls_ttl = 255;
270 tx.mpls_verbose_string[0] = '\0';
272 // Reset IP parameters of TX:
273 tx.ip_src_txt[0] = '\0';
274 tx.ip_src_rand = 0;
275 tx.ip_dst_txt[0] = '\0';
276 tx.ip_src_isrange = 0;
277 tx.ip_src_start = 0;
278 tx.ip_src_stop = 0;
279 memset(&tx.ip6_src_start, 0, sizeof(tx.ip6_src_start));
280 memset(&tx.ip6_src_stop, 0, sizeof(tx.ip6_src_stop));
282 tx.ip_dst_start = 0;
283 tx.ip_dst_stop = 0;
284 memset(&tx.ip6_dst_start, 0, sizeof(tx.ip6_dst_start));
285 memset(&tx.ip6_dst_stop, 0, sizeof(tx.ip6_dst_stop));
286 tx.ip_dst_isrange = 0;
288 tx.ip_ttl = 0;
289 tx.ip_len = 0;
290 tx.ip_payload[0]= '\0';
291 tx.ip_payload_s = 0;
292 tx.ip_option[0]= '\0';
293 tx.ip_option_s = 0;
295 // Reset ICMP parameters:
296 tx.icmp_type=0;
297 tx.icmp_code=0;
298 tx.icmp_chksum=0; // 0=autofill
299 tx.icmp_ident=0x42;
300 tx.icmp_sqnr=0x1;
301 tx.icmp_payload_s=0;
303 // Reset general L4 parameters:
304 tx.sp = 0;
305 tx.dp = 0;
306 tx.sp_start = 0;
307 tx.sp_stop = 0;
308 tx.dp_start = 0;
309 tx.dp_stop = 0;
310 tx.sp_isrange = 0;
311 tx.dp_isrange = 0;
313 // Reset UDP parameters of TX:
315 tx.udp_len = 0; // If set to zero then create_udp_packet will calculate it
316 tx.udp_sum = 0;
317 tx.udp_payload[0] = '\0';
318 tx.udp_payload_s = 0;
320 // Reset TCP parameters of TX:
322 tx.tcp_seq = 42;
323 tx.tcp_seq_stop = 42;
324 tx.tcp_seq_delta = 0; // also used as 'isrange' meaning
325 tx.tcp_ack = 42;
326 tx.tcp_control = 0;
327 tx.tcp_win = 10000;
328 tx.tcp_sum = 0;
329 tx.tcp_urg = 0;
330 tx.tcp_len = 20; // Least size (TCP header only)
331 tx.tcp_payload[0] = '\0';
332 tx.tcp_payload_s = 0;
334 // Reset RTP parameters of TX:
335 tx.rtp_sqnr = 0;
336 tx.rtp_stmp = 0;
338 // Initialize random generator
339 time(&t);
340 srand((unsigned int)t);
342 // Reset device_list
343 for (i=0; i<MZ_MAX_DEVICES; i++) {
344 device_list[i].arprx_thread = 0;
345 device_list[i].p_arp = NULL;
346 device_list[i].arp_table = NULL;
347 device_list[i].ps=-1;
348 device_list[i].cli=0;
349 device_list[i].mgmt_only=0;
352 return 0;
355 static void print_packet_types(void)
357 fprintf(stderr, "\n"
358 MAUSEZAHN_VERSION
359 "\n"
360 "| The following packet types are currently implemented:\n"
361 "|\n"
362 "| arp ... sends ARP packets\n"
363 "| bpdu ... sends BPDU packets (STP or PVST+)\n"
364 "| cdp ... sends CDP messages\n"
365 "| ip ... sends IPv4 packets\n"
366 "| udp ... sends UDP datagrams\n"
367 "| tcp ... sends TCP segments\n"
368 "| icmp ... sends ICMP messages\n"
369 "| igmp ... sends IGMP messages\n"
370 "| dns ... sends DNS messages\n"
371 "| rtp ... sends RTP datagrams\n"
372 "| syslog ... sends Syslog messages\n"
373 "|\n"
374 "| Of course you can build any other packet type 'manually' using the direct layer 2 mode.\n"
375 "| FYI: The interactive mode supports additional protocols. (Try mz -x <port>)\n"
376 "\n");
378 die();
381 // Purpose: Properly handle arguments and configure global structs (tx)
382 int getopts (int argc, char *argv[])
384 int i, c, rargs, RX=0, count_set=0, delay_set=0;
385 unsigned int time_factor;
386 char *packet_type=NULL, *mops_type=NULL;
387 char *dum;
388 unsigned char *dum1, *dum2;
389 bool do_help = false;
391 libnet_t *l;
392 char err_buf[LIBNET_ERRBUF_SIZE];
393 struct libnet_ether_addr *mymac;
395 FILE *afp;
396 char hexpld[MAX_PAYLOAD_SIZE*2];
397 int hexpld_specified=0;
399 opterr = 1; // let getopt print error message if necessary
402 while ((c = getopt(argc, argv, short_options)) != -1)
403 switch (c) {
404 case '4':
405 tx.eth_type = 0x0800;
406 ipv6_mode=0;
407 break;
408 case '6':
409 tx.eth_type = 0x86dd;
410 ipv6_mode=1;
411 break;
412 case 'h':
413 help();
414 break;
415 case 'q':
416 quiet=1;
417 break;
418 case 'v':
419 version();
420 break;
421 case 'V':
422 verbose++;
423 break;
424 case 'S':
425 simulate=1;
426 break;
427 case 'x':
428 mz_port = MZ_DEFAULT_PORT;
429 break;
430 case 'l':
431 strncpy (mz_listen_addr, optarg, sizeof(mz_listen_addr));
432 break;
433 case 'a':
434 strncpy (tx.eth_src_txt, optarg, 32);
435 tx.packet_mode = 0;
436 break;
437 case 'A':
438 strncpy (tx.ip_src_txt, optarg, sizeof(tx.ip_src_txt));
439 break;
440 case 'b':
441 strncpy (tx.eth_dst_txt, optarg, 32);
442 tx.packet_mode = 0;
443 break;
444 case 'B':
445 strncpy (tx.ip_dst_txt, optarg, sizeof(tx.ip_dst_txt));
446 break;
447 case 'c':
448 errno=0;
449 tx.count = strtol(optarg, (char **)NULL, 10);
450 if ((errno == ERANGE && (tx.count == LONG_MAX || tx.count == LONG_MIN))
451 || (errno != 0 && tx.count == 0)) {
452 perror("strtol");
453 return (-1);
455 if (tx.count<0) tx.count=1; //TODO: Allow count=0 which means infinity (need to update all send_functions)
456 count_set=1;
457 break;
458 case 'd':
459 errno=0;
460 // determine whether seconds or msecs are used
461 // default is usec!!!
462 time_factor=1;
463 if (exists(optarg,"s") || exists(optarg,"sec")) time_factor=1000000;
464 if (exists(optarg,"m") || exists(optarg,"msec")) time_factor=1000;
465 dum = strtok(optarg,"ms");
466 tx.delay = strtol(dum, (char **)NULL, 10) * time_factor;
467 if ((errno == ERANGE && (tx.delay == LONG_MAX || tx.delay == LONG_MIN))
468 || (errno != 0 && tx.delay == 0)) {
469 perror("strtol");
470 return (-1);
472 if (tx.delay<0) tx.delay=0; // no delay
473 delay_set=1;
474 break;
475 case 'p':
476 errno=0;
477 tx.padding = strtol(optarg, (char **)NULL, 10);
478 if ((errno == ERANGE && (tx.padding == LONG_MAX || tx.padding == LONG_MIN))
479 || (errno != 0 && tx.padding == 0)) {
480 perror("strtol");
481 return (-1);
483 if (tx.padding>10000) {
484 fprintf(stderr, " Warning: Padding must not exceed 10000!\n");
485 return -1;
487 break;
488 case 't':
489 packet_type = optarg; // analyzed below
490 if (strcmp(packet_type,"help") == 0)
491 print_packet_types();
492 break;
493 case 'X':
494 mops_type = optarg; // MOPS TRANSITION STRATEGY -- analyzed below
495 break;
496 case 'T':
497 packet_type = optarg;
498 RX = 1;
499 break;
500 case 'r':
501 mz_rand = 1;
502 break;
503 case 'M':
504 if (strncmp(optarg,"help",4)==0) {
505 (void) get_mpls_params("help ");
507 else {
508 strncpy (tx.mpls_txt, optarg, 128);
509 tx.eth_type = ETHERTYPE_MPLS;
510 tx.packet_mode = 0;
511 tx.mpls=1;
513 break;
514 case 'P': // ASCII payload
515 strncpy((char*)tx.ascii_payload, optarg, MAX_PAYLOAD_SIZE);
516 tx.ascii = 1;
517 break;
518 case 'f': // ASCII payload in FILE
519 afp = fopen(optarg, "r");
520 if (fgets((char*)tx.ascii_payload, MAX_PAYLOAD_SIZE, afp) == NULL)
521 fprintf(stderr, " mz/getopts: File empty?\n");
522 fclose(afp);
523 tx.ascii = 1;
524 break;
525 case 'F': // HEX payload in FILE
526 afp = fopen(optarg, "r");
527 i=0;
528 while ( (hexpld[i]=fgetc(afp))!=EOF ) {
529 if (isspace(hexpld[i])) {
530 hexpld[i]=':';
532 i++;
534 hexpld[i]='\0';
535 fclose(afp);
536 hexpld_specified=1;
537 break;
538 case 'Q': // VLAN TAG
539 if (strncmp(optarg,"help",4)==0) {
540 print_dot1Q_help(); // ugly but most simple and safe solution
542 else {
543 strncpy (tx.dot1Q_txt, optarg, 32);
544 tx.dot1Q=1;
545 // determine number of VLAN tags
546 for (i=0; i<strlen(tx.dot1Q_txt); i++) {
547 if (tx.dot1Q_txt[i]==',') tx.dot1Q++;
549 tx.packet_mode = 0;
551 break;
552 case '?':
553 if ((optopt == 'a') || (optopt == 'b') || (optopt = 'c') ||
554 (optopt == 'd') || (optopt == 'f') || (optopt = 'p') ||
555 (optopt == 't') || (optopt == 'm'))
556 fprintf (stderr, " mz/getopts: Option -%c requires an argument.\n", optopt);
557 else if (isprint (optopt))
558 fprintf (stderr, " mz/getopts: Unknown option -%c'.\n", optopt);
559 else
560 fprintf (stderr, " mz/getopts: Unknown option character \\x%x'.\n", optopt);
561 return 1;
562 default:
563 fprintf (stderr," mz/getopts: Could not handle arguments properly!\n");
564 return 1;
567 // ********************************************
568 // Handle additional arguments
569 // ********************************************
571 // Greeting text
572 if (verbose) {
573 fprintf(stderr,"\n"
574 MAUSEZAHN_VERSION
575 "\n"
576 "Use at your own risk and responsibility!\n"
577 "-- Verbose mode --\n"
578 "\n");
581 if (argc<2) {
582 help();
585 if ((rargs=argc-optind)>2) { // number of remaining arguments
586 fprintf(stderr," mz/getopts: Too many arguments!\n");
587 return -1;
591 // There can be 0-2 additional arguments
592 switch (rargs) {
593 case 0:
594 if (lookupdev()) { // no device found
595 if (verbose) fprintf(stderr, " mz: no active interfaces found!\n");
596 strcpy(tx.device, "lo");
598 break;
599 case 1: // arg_string OR device given => find out!
600 if ( (strncmp(argv[optind],"eth",3)==0)
601 || (strncmp(argv[optind],"ath",3)==0)
602 || ((strncmp(argv[optind],"lo",2)==0)&&(strncmp(argv[optind],"log",3)!=0))
603 || (strncmp(argv[optind],"vmnet",5)==0)
604 || (strncmp(argv[optind],"wifi",4)==0) ) {
605 // device has been specified!
606 strncpy (tx.device, argv[optind], 16);
608 else { /// arg_string given => no device has been specified -- let's find one!
609 strncpy (tx.arg_string, argv[optind], MAX_PAYLOAD_SIZE);
610 do_help = !!getarg(tx.arg_string,"help", NULL);
611 if (!do_help) {
612 if (lookupdev()) {
613 /* no device found */
614 if (verbose)
615 fprintf(stderr, " mz: no active interfaces found!\n");
616 strcpy(tx.device, "lo");
618 if (verbose)
619 fprintf(stderr," mz: device not given, will use %s\n",tx.device);
622 break;
623 case 2: // both device and arg_string given
624 strncpy (tx.device, argv[optind], 16);
625 strncpy (tx.arg_string, argv[optind+1], MAX_PAYLOAD_SIZE);
626 break;
627 default:
628 fprintf(stderr," mz/getopts: Unknown argument problem!\n");
629 return 1;
632 if (hexpld_specified) {
633 strcat(tx.arg_string, ",p=");
634 strcat(tx.arg_string, hexpld);
638 //////////////////////////////////////////////////////////////////////////
640 // Initialize MAC and IP Addresses.
642 // - tx.eth_src = own interface MAC
643 // - tx.ip_src = own interface IP or user specified
644 // - tx.ip_dst = 255.255.255.255 or user specified (can be a range)
645 // - tx.ip_src_rand ... is set if needed.
648 // Get own device MAC address:
649 // Don't open context if only a help text is requested
650 if (!do_help && getarg(tx.arg_string,"help", NULL) !=1) {
651 l = libnet_init (LIBNET_LINK_ADV, tx.device, err_buf );
652 if (l == NULL) {
653 fprintf(stderr, " mz/getopts: libnet_init() failed (%s)", err_buf);
654 return -1;
656 mymac = libnet_get_hwaddr(l);
657 for (i=0; i<6; i++) {
658 tx.eth_src[i] = mymac->ether_addr_octet[i];
659 tx.eth_mac_own[i] = mymac->ether_addr_octet[i];
662 // Set source IP address:
663 if (strlen(tx.ip_src_txt)) { // option -A has been specified
664 if (mz_strcmp(tx.ip_src_txt, "bcast", 2)==0) {
665 if (ipv6_mode) {
666 fprintf(stderr, "Option -A does not support 'bcast' when in IPv6 mode.\n");
667 return 1;
669 tx.ip_src = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
670 } else if (strcmp(tx.ip_src_txt, "rand") == 0) {
671 if (ipv6_mode) {
672 fprintf(stderr, "Option -A does not support 'rand' when in IPv6 mode.\n");
673 return 1;
675 tx.ip_src_rand = 1;
676 tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0
678 else if (
679 (ipv6_mode && get_ip6_range_src(tx.ip_src_txt, l)) || // returns 1 when no range has been specified
680 (!ipv6_mode && get_ip_range_src(tx.ip_src_txt))
683 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
684 if (ipv6_mode)
685 tx.ip6_src = libnet_name2addr6 (l, tx.ip_src_txt, LIBNET_RESOLVE);
686 else
687 tx.ip_src = libnet_name2addr4 (l, tx.ip_src_txt, LIBNET_RESOLVE);
690 else { // no source IP specified: by default use own IP address
691 if (ipv6_mode) {
692 tx.ip6_src = libnet_get_ipaddr6(l);
693 if (strncmp((char*)&tx.ip6_src,(char*)&in6addr_error,sizeof(in6addr_error))==0)
694 printf("Failed to set source IPv6 address: %s", l->err_buf);
696 else
697 tx.ip_src = libnet_get_ipaddr4(l);
700 // Set destination IP address:
701 if (strlen(tx.ip_dst_txt)) { // option -B has been specified
702 if (mz_strcmp(tx.ip_dst_txt, "rand", 2)==0) {
703 fprintf(stderr, "Option -B does not support random destination IP addresses currently.\n");
704 return 1;
707 if (mz_strcmp(tx.ip_dst_txt, "bcast", 2)==0) {
708 if (ipv6_mode) {
709 fprintf(stderr, "Option -B does not support 'bcast' when in IPv6 mode.\n");
710 return 1;
712 tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
713 } else if (
714 (ipv6_mode && get_ip6_range_dst(tx.ip_dst_txt, l)) || // returns 1 when no range has been specified
715 (!ipv6_mode && get_ip_range_dst(tx.ip_dst_txt)))
717 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
718 if (ipv6_mode)
719 tx.ip6_dst = libnet_name2addr6 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
720 else
721 tx.ip_dst = libnet_name2addr4 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
724 else { // no destination IP specified: by default use broadcast
725 if (ipv6_mode) {
726 // XXX I think we want to use a link-local
727 // broadcast address instead.
728 tx.ip6_dst = libnet_name2addr6 (l, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", LIBNET_DONT_RESOLVE);
729 } else {
730 tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
734 // Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()'
735 // in verbose mode. See 'modifications.c'.
737 if (tx.ip_src_rand) { // ip_src_h already given, convert to ip_src
738 dum1 = (unsigned char*) &tx.ip_src_h;
739 dum2 = (unsigned char*) &tx.ip_src;
741 else { // ip_src already given, convert to ip_src_h
742 if (ipv6_mode) {
743 if (tx.ip_src_isrange) {
744 tx.ip6_src = tx.ip6_src_start;
746 } else {
747 dum1 = (unsigned char*) &tx.ip_src;
748 dum2 = (unsigned char*) &tx.ip_src_h;
752 if (ipv6_mode) {
753 if (tx.ip_dst_isrange) {
754 tx.ip6_dst = tx.ip6_dst_start;
756 } else {
757 *dum2 = *(dum1+3);
758 dum2++;
759 *dum2 = *(dum1+2);
760 dum2++;
761 *dum2 = *(dum1+1);
762 dum2++;
763 *dum2 = *dum1;
765 dum1 = (unsigned char*) &tx.ip_dst;
766 dum2 = (unsigned char*) &tx.ip_dst_h;
768 *dum2 = *(dum1+3);
769 dum2++;
770 *dum2 = *(dum1+2);
771 dum2++;
772 *dum2 = *(dum1+1);
773 dum2++;
774 *dum2 = *dum1;
777 libnet_destroy(l);
781 // END OF ADDRESS INITIALIZATION
783 //////////////////////////////////////////////////////////////////////////
786 ////// retrieve interface parameters ///////
788 for (i=0; i<device_list_entries; i++) {
789 get_dev_params(device_list[i].dev);
793 //////////////////////////////////////////////////////////////////////////
795 // Mausezahn CLI desired?
796 if (mz_port) {
797 // has port number been specified?
798 if (strlen(tx.arg_string)) {
799 mz_port = (int) str2int (tx.arg_string);
802 mz_cli_init();
803 cli();
806 //////////////////////////////////////////////////////////////////////////
808 // Mode decision
810 // Consider -t and -m option (used exclusively)
811 // -t => special packet types, stateless
813 // If -t not present then evaluate arg_string which must
814 // contain a byte-string in hexadecimal notation.
818 // ***** NEW: MOPS TRANSITION STRATEGY *****
819 if (mops_type != NULL) {
821 if (mz_strcmp(mops_type,"lldp",4)==0) {
822 mops_direct(tx.device, MOPS_LLDP, tx.arg_string);
827 if (packet_type == NULL) { // raw hex string given
828 mode = BYTE_STREAM;
830 else if (strcmp(packet_type,"arp")==0) {
831 mode = ARP;
833 else if (strcmp(packet_type,"bpdu")==0) {
834 mode = BPDU;
836 else if (strcmp(packet_type,"ip")==0) {
837 mode = IP;
839 else if (strcmp(packet_type,"udp")==0) {
840 mode = UDP;
842 else if (strcmp(packet_type,"icmp")==0) {
843 mode = ICMP;
845 else if (strcmp(packet_type,"icmp6")==0) {
846 mode = ICMP6;
848 else if (strcmp(packet_type,"tcp")==0) {
849 mode = TCP;
851 else if (strcmp(packet_type,"dns")==0) {
852 mode = DNS;
854 else if (strcmp(packet_type,"cdp")==0) {
855 mode = CDP;
857 else if (strcmp(packet_type,"syslog")==0) {
858 mode = SYSLOG;
860 else if (strcmp(packet_type, "igmp") == 0) {
861 mode = IGMP;
863 else if (strcmp(packet_type,"lldp")==0) {
864 mode = LLDP;
865 tx.packet_mode=0; // create whole frame by ourself
867 else if (strcmp(packet_type,"rtp")==0) {
868 if (RX) {
869 mode = RX_RTP;
871 else {
872 mode = RTP;
873 if (!count_set) tx.count = 0;
874 if (!delay_set) tx.delay = 20000; // 20 msec inter-packet delay for RTP
877 else {
878 fprintf(stderr, " mz: you must specify a valid packet type!\n");
882 //////////////////////////////////////////////////////////////////////////
884 // TODO: Implement macro support
885 // Check macro types here
887 return 0;
890 int main(int argc, char **argv)
892 // These handles are only used when creating L3 and above packets.
893 libnet_t *l; // the context
894 libnet_ptag_t t2=0, t3=0, t4=0; // handles to layers
895 double cpu_time_used;
897 reset();
899 if ( getopts(argc, argv) )
901 (void) fprintf(stderr, " Invalid command line parameters!\n");
902 help();
905 // Check whether hires timers are supported or not:
906 (void) check_timer();
908 signal(SIGINT, signal_handler); // to close all file pointers etc upon SIGINT
910 switch (mode)
912 case BYTE_STREAM:
913 send_eth();
914 break;
916 case ARP:
917 (void) send_arp();
918 break;
920 case BPDU:
921 (void) send_bpdu();
922 break;
924 case CDP:
925 (void) send_cdp();
926 break;
928 case IP: // From now on a new much more modular method is used:
929 l = get_link_context();
930 t3 = create_ip_packet(l); // t3 can be used for later header changes
931 if (!quiet) complexity();
932 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
933 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
934 else
935 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
936 break;
938 case ICMP:
939 tx.ip_proto = 1;
940 l = get_link_context();
941 t4 = create_icmp_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 ICMP6:
951 tx.ip_proto = 58;
952 l = get_link_context();
953 t4 = create_icmp6_packet(l); // t4 can be used for later header changes
954 t3 = create_ip_packet(l); // t3 can be used for later header changes
955 if (!quiet) complexity();
956 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
957 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
958 else
959 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
960 break;
962 case UDP:
963 tx.ip_proto = 17;
964 l = get_link_context();
965 t4 = create_udp_packet(l); // t4 can be used for later header changes
966 t3 = create_ip_packet(l); // t3 can be used for later header changes
967 if (!quiet) complexity();
968 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
969 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
970 else
971 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
972 break;
974 case TCP:
975 tx.ip_proto = 6;
976 l = get_link_context();
977 t4 = create_tcp_packet(l); // t4 can be used for later header changes
978 t3 = create_ip_packet(l); // t3 can be used for later header changes
979 if (!quiet) complexity();
980 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
981 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
982 else
983 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
984 break;
986 case IGMP:
987 tx.ip_proto = 2;
988 l = get_link_context();
989 t4 = create_igmp_packet(l);
990 /* t3 can be used for later header changes */
991 t3 = create_ip_packet(l);
992 if (!quiet)
993 complexity();
995 /* Ethernet manipulation features does NOT use ARP to determine eth_dst
996 * */
997 if (tx.packet_mode == 0)
998 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
999 else
1000 send_frame(l, t3, t4); // NOTE: send_frame also destroys context finaly
1001 break;
1003 case DNS:
1004 tx.ip_proto = 17;
1005 l = get_link_context();
1006 (void) create_dns_packet();
1007 t4 = create_udp_packet(l); // t4 can be used for later header changes
1008 t3 = create_ip_packet(l); // t3 can be used for later header changes
1009 if (!quiet) complexity();
1010 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1011 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
1012 else
1013 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
1014 break;
1016 case RTP:
1017 tx.ip_proto = 17;
1018 l = get_link_context();
1019 if (!quiet) fprintf(stderr, " mz: RTP mode! (count=%u, delay=%u usec)\n\n", tx.count, tx.delay);
1020 (void) create_rtp_packet();
1021 t4 = create_udp_packet(l); // t4 can be used for later header changes
1022 t3 = create_ip_packet(l); // t3 can be used for later header changes
1023 if (!quiet) complexity();
1024 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1025 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
1026 else
1027 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
1028 break;
1030 case RX_RTP: // Receive RTP packets
1031 rcv_rtp_init();
1032 rcv_rtp();
1033 break;
1035 case SYSLOG:
1036 tx.ip_proto = 17;
1037 l = get_link_context();
1038 (void) create_syslog_packet();
1039 t4 = create_udp_packet(l); // t4 can be used for later header changes
1040 t3 = create_ip_packet(l); // t3 can be used for later header changes
1041 if (!quiet) complexity();
1043 if (tx.packet_mode==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1044 t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes
1045 else
1046 send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly
1047 break;
1049 case LLDP: // start with a new concept here
1050 //l = get_link_context();
1051 //(void) create_lldp_packet();
1052 // // // printf("SIZE=%lu\n",sizeof(struct tx_struct));
1053 fprintf(stderr, "LLDP is currently only supported via the interactive mode\n");
1054 exit(1);
1055 break;
1058 default:
1059 (void) fprintf(stderr," mz/main: unknown mode! Stop.\n");
1060 return (1);
1063 if (!quiet)
1065 mz_stop = clock();
1066 cpu_time_used = ((double) (mz_stop - mz_start)) / CLOCKS_PER_SEC;
1067 if (cpu_time_used > 0)
1069 total_d /= cpu_time_used;
1070 fprintf(stderr, "%.2f seconds (%.Lf packets per second)\n",cpu_time_used,total_d);
1072 else
1074 fprintf(stderr, "\n");
1078 return(0);