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.
10 #include <pcap/pcap.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>
36 enum operating_modes mode
;
39 int quiet
; // don't even print 'important standard short messages'
40 int verbose
; // report character
41 int simulate
; // if 1 then don't really send frames
45 FILE *fp
, *fp2
; // global multipurpose file pointer
48 clock_t mz_start
, mz_stop
;
54 jitter
[TIME_COUNT_MAX
];
58 time0_flag
, // If set then time0 has valid data
62 mz_ssrc
[4]; // holds RTP stream identifier for rcv_rtp()
70 gind
, // a global index to run through deltaRX, deltaTX, and jitter
71 gind_max
; // the amount of entries used in the (ugly oversized) arrays; per default set to TIME_COUNT
73 struct tx_struct tx
; // NOTE: tx elements are considered as default values for MOPS
75 struct device_struct device_list
[MZ_MAX_DEVICES
];
77 int device_list_entries
;
79 int verbose_level
= 0;
81 char mz_default_config_path
[256];
82 char mz_default_log_path
[256];
84 static const char *short_options
= "46hqvVSxra:A:b:B:c:d:E:f:F:l:p:P:R:t:T:M:Q:X:";
86 static void signal_handler(int number
)
91 void clean_up(int sig
)
94 struct arp_table_struct
*cur
, *next
;
96 if (!quiet
) fprintf(stderr
, "\nMausezahn cleans up...\n");
99 verbose_l1(" close files (1) ...\n");
106 if (verbose
) fprintf(stderr
, " close files (2) ...\n");
113 if (verbose
) fprintf(stderr
, " clear mops list...\n");
114 mops_cleanup(mp_head
);
115 if (verbose
) fprintf(stderr
, " clear automops list...\n");
116 automops_cleanup(amp_head
);
117 if (verbose
) fprintf(stderr
, " clear packet sequences...\n");
118 mz_ll_delete_list(packet_sequences
);
121 for (i
=0; i
<device_list_entries
; i
++) {
122 if (device_list
[i
].p_arp
!=NULL
) {
123 pcap_close(device_list
[i
].p_arp
);
124 fprintf(stderr
, " stopped ARP process for device %s\n", device_list
[i
].dev
);
126 if (device_list
[i
].arprx_thread
!=0) {
127 pthread_cancel(device_list
[i
].arprx_thread
);
129 fprintf(stderr
, " (ARP thread for device %s done)\n", device_list
[i
].dev
);
132 if (device_list
[i
].arp_table
!=NULL
) {
133 cur
=device_list
[i
].arp_table
;
136 if (cur
!=NULL
) free(cur
);
141 // close packet sockets
142 if (device_list
[i
].ps
>=0) {
143 close(device_list
[i
].ps
);
148 if (verbose
) fprintf(stderr
, "finished.\n");
153 static void help(void)
155 printf("\nmausezahn %s, a fast versatile traffic generator\n", VERSION_STRING
);
156 puts("http://www.netsniff-ng.org\n\n"
157 "Usage: mausezahn [options] [interface] <keyword>|<arg-string>|<hex-string>\n"
159 " -x <port> Interactive mode with telnet CLI, default port: 25542\n"
160 " -l <ip> Listen address to bind to when in interactive mode, default: 0.0.0.0\n"
161 " -4 IPv4 mode (default)\n"
163 " -R <PRIO> Set socket priority\n"
164 " -c <count> Send packet count times, default:1, infinite:0\n"
165 " -d <delay> Apply delay between transmissions. The delay value can be\n"
166 " specified in usec (default, no additional unit needed), or in\n"
167 " msec (e.g. 100m or 100msec), or in seconds (e.g. 100s or 100sec)\n"
168 " -r Multiplies the specified delay with a random value\n"
169 " -p <length> Pad the raw frame to specified length (using random bytes)\n"
170 " -a <srcmac|keyword> Use specified source mac address, no matter what has\n"
171 " been specified with other arguments; keywords see below,\n"
172 " Default is own interface\n"
173 " -b <dstmac|keyword> Same with destination mac address; keywords:\n"
174 " rand Use a random MAC address\n"
175 " bc Use a broadcast MAC address\n"
176 " own Use own interface MAC address (default for source MAC)\n"
177 " stp Use IEEE 802.1d STP multicast address\n"
178 " cisco Use Cisco multicast address as used for CDP, VTP, or PVST+\n"
179 " -A <srcip> Use specified source IP address (default is own interface IP)\n"
180 " -B <dstip|dnsname> Send packet to specified destination IP or domain name\n"
181 " -P <ascii payload> Use the specified ASCII payload\n"
182 " -f <filename> Read the ASCII payload from a file\n"
183 " -F <filename> Read the hexadecimal payload from a file\n"
184 " -Q <[CoS:]vlan> Specify 802.1Q VLAN tag and optional Class of Service, you can\n"
185 " specify multiple 802.1Q VLAN tags (QinQ...) by separating them\n"
186 " via a comma or a period (e.g. '5:10,20,2:30')\n"
187 " -t <packet-type|help> Specify packet type for autobuild (you don't need to care for\n"
188 " encapsulations in lower layers, most packet types allow/require\n"
189 " additional packet-specific arguments in an <arg-string>;\n"
190 " Currently supported types: arp, bpdu, cdp, ip, icmp, udp, tcp,\n"
191 " dns, rtp, syslog, lldp and more;\n"
192 " For context-help use 'help' as <arg-string>!\n"
193 " -T <packet-type> Specify packet type for server mode, currently only rtp is supported;\n"
194 " Enter -T help or -T rtp help for further information\n"
195 " -M <MPLS-label> Insert a MPLS label, enter '-M help' for a syntax description\n"
196 " -V|VV|... Verbose and more verbose mode\n"
197 " -q Quiet mode, even omit 'important' standard short messages\n"
198 " -S Simulation mode: DOES NOT put anything on the wire, this is\n"
199 " typically combined with one of the verbose modes (v or V)\n"
201 " -h Print this help\n\n"
204 " mausezahn -c 0 -d 2s -t bpdu conf\n"
205 " mausezahn -t cdp change -c 0\n"
206 " mausezahn -t syslog sev=3 -P \"You have been mausezahned.\" -A 10.1.1.109 -B 192.168.7.7\n"
207 " mausezahn eth0 -A rand -B 1.1.1.1 -c 0 -t tcp \"dp=1-1023, flags=syn\"\n\n"
209 " This tool is targeted for network developers! You should\n"
210 " be aware of what you are doing and what these options above\n"
211 " mean! Only use this tool in an isolated LAN that you own!\n\n"
212 "Please report bugs to <bugs@netsniff-ng.org>\n"
213 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
214 "Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
215 "Swiss federal institute of technology (ETH Zurich)\n"
216 "License: GNU GPL version 2.0\n"
217 "This is free software: you are free to change and redistribute it.\n"
218 "There is NO WARRANTY, to the extent permitted by law.\n");
222 static void version(void)
224 printf("\nmausezahn %s, Git id: %s\n", VERSION_LONG
, GITVERSION
);
225 puts("a fast versatile traffic generator\n"
226 "http://www.netsniff-ng.org\n\n"
227 "Please report bugs at https://github.com/netsniff-ng/netsniff-ng/issues\n"
228 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
229 "Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
230 "Swiss federal institute of technology (ETH Zurich)\n"
231 "License: GNU GPL version 2.0\n"
232 "This is free software: you are free to change and redistribute it.\n"
233 "There is NO WARRANTY, to the extent permitted by law.\n");
242 mz_default_config_path
[0] = 0x00;
243 mz_default_log_path
[0] = 0x00;
253 gind_max
= TIME_COUNT
;
258 char mz_listen_addr
[16] = "0.0.0.0";
261 for (i
=0;i
<TIME_COUNT_MAX
;i
++) jitter
[i
] = 0;
263 time0_flag
= 0; // If set then time0 has valid data
264 sqnr0_flag
= 0; // If set then sqnr_last and sqnr_next has valid data
266 mz_ssrc
[0]=0; mz_ssrc
[1]=0; mz_ssrc
[2]=0; mz_ssrc
[3]=0;
268 // Reset mgmt parameters of TX:
269 tx
.packet_mode
= 1; // assume we don't care about L2
271 tx
.delay
= DEFAULT_DELAY
;
273 tx
.arg_string
[0] = '\0';
275 // Reset Ethernet parameters of TX:
276 tx
.eth_params_already_set
= 0;
277 for (i
=0; i
<6; i
++) tx
.eth_dst
[i
] = 0xff;
278 for (i
=0; i
<6; i
++) tx
.eth_src
[i
] = 0; // TODO: Get own MAC !!!
279 tx
.eth_dst_txt
[0] = '\0';
280 tx
.eth_src_txt
[0] = '\0';
286 tx
.eth_payload
[0] = '\0';
287 tx
.eth_payload_s
= 0;
290 // Reset CDP parameters for TX:
294 tx
.cdp_payload
[0] = '\0';
295 tx
.cdp_payload_s
= 0;
296 tx
.cdp_tlv_id
[0] = '\0';
297 tx
.cdp_tlv_id_len
= 0;
299 // Reset 802.1Q parameters of TX:
301 tx
.dot1Q_txt
[0] = '\0';
304 tx
.ascii
= 0; // 1 if specified
305 tx
.ascii_payload
[0]= '\0';
308 tx
.hex_payload_s
= 0;
310 // Reset MPLS parameters of TX:
312 tx
.mpls_txt
[0] = '\0';
317 tx
.mpls_verbose_string
[0] = '\0';
319 // Reset IP parameters of TX:
320 tx
.ip_src_txt
[0] = '\0';
322 tx
.ip_dst_txt
[0] = '\0';
323 tx
.ip_src_isrange
= 0;
326 memset(&tx
.ip6_src_start
, 0, sizeof(tx
.ip6_src_start
));
327 memset(&tx
.ip6_src_stop
, 0, sizeof(tx
.ip6_src_stop
));
331 memset(&tx
.ip6_dst_start
, 0, sizeof(tx
.ip6_dst_start
));
332 memset(&tx
.ip6_dst_stop
, 0, sizeof(tx
.ip6_dst_stop
));
333 tx
.ip_dst_isrange
= 0;
337 tx
.ip_payload
[0]= '\0';
339 tx
.ip_option
[0]= '\0';
342 // Reset ICMP parameters:
345 tx
.icmp_chksum
=0; // 0=autofill
350 // Reset general L4 parameters:
360 // Reset UDP parameters of TX:
362 tx
.udp_len
= 0; // If set to zero then create_udp_packet will calculate it
364 tx
.udp_payload
[0] = '\0';
365 tx
.udp_payload_s
= 0;
367 // Reset TCP parameters of TX:
370 tx
.tcp_seq_stop
= 42;
371 tx
.tcp_seq_delta
= 0; // also used as 'isrange' meaning
377 tx
.tcp_len
= 20; // Least size (TCP header only)
378 tx
.tcp_payload
[0] = '\0';
379 tx
.tcp_payload_s
= 0;
381 // Reset RTP parameters of TX:
385 // Initialize random generator
387 srand((unsigned int)t
);
391 for (i
=0; i
<MZ_MAX_DEVICES
; i
++) {
392 device_list
[i
].arprx_thread
= 0;
393 device_list
[i
].p_arp
= NULL
;
394 device_list
[i
].arp_table
= NULL
;
395 device_list
[i
].ps
=-1;
396 device_list
[i
].cli
=0;
397 device_list
[i
].mgmt_only
=0;
403 static void print_packet_types(void)
408 "| The following packet types are currently implemented:\n"
410 "| arp ... sends ARP packets\n"
411 "| bpdu ... sends BPDU packets (STP or PVST+)\n"
412 "| cdp ... sends CDP messages\n"
413 "| ip ... sends IPv4 packets\n"
414 "| udp ... sends UDP datagrams\n"
415 "| tcp ... sends TCP segments\n"
416 "| icmp ... sends ICMP messages\n"
417 "| igmp ... sends IGMP messages\n"
418 "| dns ... sends DNS messages\n"
419 "| rtp ... sends RTP datagrams\n"
420 "| syslog ... sends Syslog messages\n"
422 "| Of course you can build any other packet type 'manually' using the direct layer 2 mode.\n"
423 "| FYI: The interactive mode supports additional protocols. (Try mz -x <port>)\n"
429 // Purpose: Properly handle arguments and configure global structs (tx)
430 int getopts (int argc
, char *argv
[])
432 int i
, c
, rargs
, RX
=0, count_set
=0, delay_set
=0;
433 unsigned int time_factor
;
434 char *packet_type
=NULL
, *mops_type
=NULL
;
436 unsigned char *dum1
, *dum2
;
437 bool do_help
= false;
440 char err_buf
[LIBNET_ERRBUF_SIZE
];
441 struct libnet_ether_addr
*mymac
;
444 char hexpld
[MAX_PAYLOAD_SIZE
*2];
445 int hexpld_specified
=0;
450 opterr
= 1; // let getopt print error message if necessary
451 while ((c
= getopt_long(argc
, argv
, short_options
, NULL
, NULL
)) != -1) {
454 tx
.eth_type
= 0x0800;
458 tx
.eth_type
= 0x86dd;
463 prio
= strtol(optarg
, NULL
, 0);
465 perror("Couldn't parse priority");
468 if (prio
< 0 || prio
> 0xffffffff) {
469 perror("Invalid priority value");
490 mz_port
= MZ_DEFAULT_PORT
;
493 strncpy (mz_listen_addr
, optarg
, sizeof(mz_listen_addr
));
496 strncpy (tx
.eth_src_txt
, optarg
, 32);
500 strncpy (tx
.ip_src_txt
, optarg
, sizeof(tx
.ip_src_txt
));
503 strncpy (tx
.eth_dst_txt
, optarg
, 32);
507 strncpy (tx
.ip_dst_txt
, optarg
, sizeof(tx
.ip_dst_txt
));
511 tx
.count
= strtol(optarg
, (char **)NULL
, 10);
512 if ((errno
== ERANGE
&& (tx
.count
== LONG_MAX
|| tx
.count
== LONG_MIN
))
513 || (errno
!= 0 && tx
.count
== 0)) {
517 if (tx
.count
<0) tx
.count
=1; //TODO: Allow count=0 which means infinity (need to update all send_functions)
524 unit
='u'; // default is usecs
525 if (sscanf(optarg
, "%ld%c", &delay
, &unit
) == EOF
) {
530 fprintf(stderr
, " Incorrect delay format\n");
533 if (unit
== 's') time_factor
=1000000; // seconds
534 else if (unit
== 'm') time_factor
=1000; // msecs
535 else if (unit
== 'u') time_factor
=1; // usecs
537 fprintf(stderr
, " Incorrect delay format\n");
540 tx
.delay
= delay
* time_factor
;
541 if ((errno
== ERANGE
&& (tx
.delay
== LONG_MAX
|| tx
.delay
== LONG_MIN
))
542 || (errno
!= 0 && tx
.delay
== 0)) {
546 if (tx
.delay
<0) tx
.delay
=0; // no delay
551 tx
.padding
= strtol(optarg
, (char **)NULL
, 10);
552 if ((errno
== ERANGE
&& (tx
.padding
== LONG_MAX
|| tx
.padding
== LONG_MIN
))
553 || (errno
!= 0 && tx
.padding
== 0)) {
557 if (tx
.padding
>10000) {
558 fprintf(stderr
, " Warning: Padding must not exceed 10000!\n");
563 packet_type
= optarg
; // analyzed below
564 if (strcmp(packet_type
,"help") == 0)
565 print_packet_types();
568 mops_type
= optarg
; // MOPS TRANSITION STRATEGY -- analyzed below
571 packet_type
= optarg
;
578 if (strncmp(optarg
,"help",4)==0) {
579 (void) get_mpls_params("help ");
582 strncpy (tx
.mpls_txt
, optarg
, 128);
583 tx
.eth_type
= ETHERTYPE_MPLS
;
588 case 'P': // ASCII payload
589 strncpy((char*)tx
.ascii_payload
, optarg
, MAX_PAYLOAD_SIZE
);
592 case 'f': // ASCII payload in FILE
593 afp
= fopen(optarg
, "r");
595 fprintf(stderr
, " mz/getopts: Can not open file %s. %s!\n", optarg
, strerror(errno
));
598 if (fgets((char*)tx
.ascii_payload
, MAX_PAYLOAD_SIZE
, afp
) == NULL
)
599 fprintf(stderr
, " mz/getopts: File empty?\n");
603 case 'F': // HEX payload in FILE
604 afp
= fopen(optarg
, "r");
606 fprintf(stderr
, " mz/getopts: Can not open file %s. %s!\n", optarg
, strerror(errno
));
610 while ( (hexpld
[i
]=fgetc(afp
))!=EOF
) {
611 if (isspace(hexpld
[i
])) {
620 case 'Q': // VLAN TAG
621 if (strncmp(optarg
,"help",4)==0) {
622 print_dot1Q_help(); // ugly but most simple and safe solution
625 strncpy (tx
.dot1Q_txt
, optarg
, 32);
627 // determine number of VLAN tags
628 for (i
=0; i
<strlen(tx
.dot1Q_txt
); i
++) {
629 if (tx
.dot1Q_txt
[i
]==',') tx
.dot1Q
++;
635 if ((optopt
== 'a') || (optopt
== 'b') || (optopt
== 'c') ||
636 (optopt
== 'd') || (optopt
== 'f') || (optopt
== 'p') ||
637 (optopt
== 't') || (optopt
== 'm'))
638 fprintf (stderr
, " mz/getopts: Option -%c requires an argument.\n", optopt
);
639 else if (isprint (optopt
))
640 fprintf (stderr
, " mz/getopts: Unknown option -%c'.\n", optopt
);
642 fprintf (stderr
, " mz/getopts: Unknown option character \\x%x'.\n", optopt
);
645 fprintf (stderr
," mz/getopts: Could not handle arguments properly!\n");
649 // ********************************************
650 // Handle additional arguments
651 // ********************************************
658 "Use at your own risk and responsibility!\n"
659 "-- Verbose mode --\n"
663 if (optind
+2 < argc
) {
667 if ((rargs
=argc
-optind
)>2) { // number of remaining arguments
668 fprintf(stderr
," mz/getopts: Too many arguments!\n");
673 // There can be 0-2 additional arguments
676 if (lookupdev()) { // no device found
677 if (verbose
) fprintf(stderr
, " mz: no active interfaces found!\n");
678 strcpy(tx
.device
, "lo");
681 case 1: // arg_string OR device given => find out!
682 if (__device_ifindex(argv
[optind
]) > 0) {
683 strncpy(tx
.device
, argv
[optind
], 16);
685 else { /// arg_string given => no device has been specified -- let's find one!
686 strncpy (tx
.arg_string
, argv
[optind
], MAX_PAYLOAD_SIZE
);
687 do_help
= !!getarg(tx
.arg_string
,"help", NULL
);
690 /* no device found */
692 fprintf(stderr
, " mz: no active interfaces found!\n");
693 strcpy(tx
.device
, "lo");
696 fprintf(stderr
," mz: device not given, will use %s\n",tx
.device
);
700 case 2: // both device and arg_string given
701 strncpy (tx
.device
, argv
[optind
], 16);
702 strncpy (tx
.arg_string
, argv
[optind
+1], MAX_PAYLOAD_SIZE
);
705 fprintf(stderr
," mz/getopts: Unknown argument problem!\n");
709 if (hexpld_specified
) {
710 strcat(tx
.arg_string
, ",p=");
711 strcat(tx
.arg_string
, hexpld
);
715 //////////////////////////////////////////////////////////////////////////
717 // Initialize MAC and IP Addresses.
719 // - tx.eth_src = own interface MAC
720 // - tx.ip_src = own interface IP or user specified
721 // - tx.ip_dst = 255.255.255.255 or user specified (can be a range)
722 // - tx.ip_src_rand ... is set if needed.
725 // Get own device MAC address:
726 // Don't open context if only a help text is requested
727 if (!do_help
&& getarg(tx
.arg_string
,"help", NULL
) !=1) {
728 l
= libnet_init (LIBNET_LINK_ADV
, tx
.device
, err_buf
);
730 fprintf(stderr
, " mz/getopts: libnet_init() failed (%s)", err_buf
);
733 mymac
= libnet_get_hwaddr(l
);
734 for (i
=0; i
<6; i
++) {
735 tx
.eth_src
[i
] = mymac
->ether_addr_octet
[i
];
736 tx
.eth_mac_own
[i
] = mymac
->ether_addr_octet
[i
];
739 // Set source IP address:
740 if (strlen(tx
.ip_src_txt
)) { // option -A has been specified
741 if (mz_strcmp(tx
.ip_src_txt
, "bcast", 2)==0) {
743 fprintf(stderr
, "Option -A does not support 'bcast' when in IPv6 mode.\n");
746 tx
.ip_src
= libnet_name2addr4 (l
, "255.255.255.255", LIBNET_DONT_RESOLVE
);
747 } else if (strcmp(tx
.ip_src_txt
, "rand") == 0) {
749 fprintf(stderr
, "Option -A does not support 'rand' when in IPv6 mode.\n");
753 tx
.ip_src_h
= (u_int32_t
) ( ((float) rand()/RAND_MAX
)*0xE0000000); //this is 224.0.0.0
756 (ipv6_mode
&& get_ip6_range_src(tx
.ip_src_txt
, l
)) || // returns 1 when no range has been specified
757 (!ipv6_mode
&& get_ip_range_src(tx
.ip_src_txt
))
760 // name2addr{4,6} accepts a valid IP address or a FQDN:
762 tx
.ip6_src
= libnet_name2addr6(l
, tx
.ip_src_txt
, LIBNET_RESOLVE
);
763 if (libnet_in6_is_error(tx
.ip6_src
)) {
764 /* libnet_in6_is_error returns 1 for the valid IPv6 address
765 * ffff:ffff:ffff:ffff:ffff:ffff. Use an additional inet_pton()
766 * check to cover cases where this address is specified
769 struct in6_addr src_check
;
770 if (inet_pton(AF_INET6
, tx
.ip_src_txt
, &src_check
) != 1) {
771 fprintf(stderr
, "Failed to set source"
772 " IPv6 address. Please check if"
773 " source is set to a valid IPv6 address.\n");
778 tx
.ip_src
= libnet_name2addr4(l
, tx
.ip_src_txt
, LIBNET_RESOLVE
);
779 if (tx
.ip_src
== -1) {
780 /* libnet_name2addr4() returns -1 for the valid address 255.255.255.255.
781 * Use an additional inet_pton() check to cover case where this address
782 * is specified as source
784 struct in_addr src_check
;
785 if (inet_pton(AF_INET
, tx
.ip_src_txt
, &src_check
) != 1) {
786 fprintf(stderr
, "Failed to set source"
787 " IPv4 address. Please check if"
788 " source is set to a valid IPv4 address.\n");
795 // no source IP specified: by default use own IP address
797 tx
.ip6_src
= libnet_get_ipaddr6(l
);
798 if (strncmp((char*)&tx
.ip6_src
,(char*)&in6addr_error
, sizeof(in6addr_error
))==0)
799 printf("Failed to set source IPv6 address: %s", l
->err_buf
);
802 tx
.ip_src
= libnet_get_ipaddr4(l
);
805 // Set destination IP address:
806 if (strlen(tx
.ip_dst_txt
)) { // option -B has been specified
807 if (mz_strcmp(tx
.ip_dst_txt
, "rand", 2)==0) {
808 fprintf(stderr
, "Option -B does not support random destination IP addresses currently.\n");
812 if (mz_strcmp(tx
.ip_dst_txt
, "bcast", 2)==0) {
814 fprintf(stderr
, "Option -B does not support 'bcast' when in IPv6 mode.\n");
817 tx
.ip_dst
= libnet_name2addr4 (l
, "255.255.255.255", LIBNET_DONT_RESOLVE
);
819 (ipv6_mode
&& get_ip6_range_dst(tx
.ip_dst_txt
, l
)) || // returns 1 when no range has been specified
820 (!ipv6_mode
&& get_ip_range_dst(tx
.ip_dst_txt
)))
822 // name2addr{4, 6} accepts a valid IP address or a FQDN:
824 tx
.ip6_dst
= libnet_name2addr6(l
, tx
.ip_dst_txt
, LIBNET_RESOLVE
);
825 if (libnet_in6_is_error(tx
.ip6_dst
)) {
826 /* libnet_in6_is_error returns 1 for the valid IPv6 address
827 * ffff:ffff:ffff:ffff:ffff:ffff. Use an additional inet_pton()
828 * check to cover cases where this address is specified
831 struct in6_addr dst_check
;
832 if (inet_pton(AF_INET6
, tx
.ip_dst_txt
, &dst_check
) != 1) {
833 fprintf(stderr
, "Failed to set destination"
834 " IPv6 address. Please check if"
835 " source is set to a valid IPv6 address.\n");
840 tx
.ip_dst
= libnet_name2addr4(l
, tx
.ip_dst_txt
, LIBNET_RESOLVE
);
841 if (tx
.ip_dst
== -1) {
842 /* libnet_name2addr4() returns -1 for the valid address 255.255.255.255.
843 * Use an additional inet_pton() check to cover case where this address
844 * is specified as destination
846 struct in_addr dst_check
;
847 if (inet_pton(AF_INET
, tx
.ip_dst_txt
, &dst_check
) != 1) {
848 fprintf(stderr
, "Failed to set destination"
849 " IPv4 address. Please check if"
850 " destination is set to a valid IPv4 address.\n");
858 else { // no destination IP specified: by default use broadcast
860 tx
.ip6_dst
= libnet_name2addr6 (l
, "ff02::1", LIBNET_DONT_RESOLVE
);
862 tx
.ip_dst
= libnet_name2addr4 (l
, "255.255.255.255", LIBNET_DONT_RESOLVE
);
866 // Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()'
867 // in verbose mode. See 'modifications.c'.
869 if (tx
.ip_src_rand
) { // ip_src_h already given, convert to ip_src
870 dum1
= (unsigned char*) &tx
.ip_src_h
;
871 dum2
= (unsigned char*) &tx
.ip_src
;
873 else { // ip_src already given, convert to ip_src_h
875 if (tx
.ip_src_isrange
) {
876 tx
.ip6_src
= tx
.ip6_src_start
;
879 dum1
= (unsigned char*) &tx
.ip_src
;
880 dum2
= (unsigned char*) &tx
.ip_src_h
;
885 if (tx
.ip_dst_isrange
) {
886 tx
.ip6_dst
= tx
.ip6_dst_start
;
897 dum1
= (unsigned char*) &tx
.ip_dst
;
898 dum2
= (unsigned char*) &tx
.ip_dst_h
;
913 // END OF ADDRESS INITIALIZATION
915 //////////////////////////////////////////////////////////////////////////
918 ////// retrieve interface parameters ///////
920 for (i
=0; i
<device_list_entries
; i
++) {
921 get_dev_params(device_list
[i
].dev
);
925 //////////////////////////////////////////////////////////////////////////
927 // Mausezahn CLI desired?
929 // has port number been specified?
930 if (strlen(tx
.arg_string
)) {
931 mz_port
= (int) str2int (tx
.arg_string
);
938 //////////////////////////////////////////////////////////////////////////
942 // Consider -t and -m option (used exclusively)
943 // -t => special packet types, stateless
945 // If -t not present then evaluate arg_string which must
946 // contain a byte-string in hexadecimal notation.
950 // ***** NEW: MOPS TRANSITION STRATEGY *****
951 if (mops_type
!= NULL
) {
953 if (mz_strcmp(mops_type
,"lldp",4)==0) {
954 mops_direct(tx
.device
, MOPS_LLDP
, tx
.arg_string
);
959 if (packet_type
== NULL
) { // raw hex string given
962 else if (strcmp(packet_type
,"arp")==0) {
965 else if (strcmp(packet_type
,"bpdu")==0) {
968 else if (strcmp(packet_type
,"ip")==0) {
971 else if (strcmp(packet_type
,"udp")==0) {
974 else if (strcmp(packet_type
,"icmp")==0) {
977 else if (strcmp(packet_type
,"icmp6")==0) {
980 else if (strcmp(packet_type
,"tcp")==0) {
983 else if (strcmp(packet_type
,"dns")==0) {
986 else if (strcmp(packet_type
,"cdp")==0) {
989 else if (strcmp(packet_type
,"syslog")==0) {
992 else if (strcmp(packet_type
, "igmp") == 0) {
995 else if (strcmp(packet_type
,"lldp")==0) {
997 tx
.packet_mode
=0; // create whole frame by ourself
999 else if (strcmp(packet_type
,"rtp")==0) {
1005 if (!count_set
) tx
.count
= 0;
1006 if (!delay_set
) tx
.delay
= 20000; // 20 msec inter-packet delay for RTP
1010 fprintf(stderr
, " mz: you must specify a valid packet type!\n");
1014 //////////////////////////////////////////////////////////////////////////
1016 // TODO: Implement macro support
1017 // Check macro types here
1022 int main(int argc
, char **argv
)
1024 // These handles are only used when creating L3 and above packets.
1025 libnet_t
*l
; // the context
1026 libnet_ptag_t t2
=0, t3
=0, t4
=0; // handles to layers
1027 double cpu_time_used
;
1031 if ( getopts(argc
, argv
) )
1033 (void) fprintf(stderr
, " Invalid command line parameters!\n");
1037 // Check whether hires timers are supported or not:
1038 (void) check_timer();
1040 signal(SIGINT
, signal_handler
); // to close all file pointers etc upon SIGINT
1060 case IP
: // From now on a new much more modular method is used:
1061 l
= get_link_context();
1062 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1063 if (!quiet
) complexity();
1064 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1065 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1067 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1072 l
= get_link_context();
1073 t4
= create_icmp_packet(l
); // t4 can be used for later header changes
1074 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1075 if (!quiet
) complexity();
1076 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1077 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1079 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1084 l
= get_link_context();
1085 t4
= create_icmp6_packet(l
); // t4 can be used for later header changes
1086 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1087 if (!quiet
) complexity();
1088 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1089 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1091 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1096 l
= get_link_context();
1097 t4
= create_udp_packet(l
); // t4 can be used for later header changes
1098 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1099 if (!quiet
) complexity();
1100 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1101 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1103 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1108 l
= get_link_context();
1109 t4
= create_tcp_packet(l
); // t4 can be used for later header changes
1110 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1111 if (!quiet
) complexity();
1112 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1113 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1115 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1120 l
= get_link_context();
1121 t4
= create_igmp_packet(l
);
1122 /* t3 can be used for later header changes */
1123 t3
= create_ip_packet(l
);
1127 /* Ethernet manipulation features does NOT use ARP to determine eth_dst
1129 if (tx
.packet_mode
== 0)
1130 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1132 send_frame(l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1137 l
= get_link_context();
1138 (void) create_dns_packet();
1139 t4
= create_udp_packet(l
); // t4 can be used for later header changes
1140 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1141 if (!quiet
) complexity();
1142 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1143 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1145 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1150 l
= get_link_context();
1151 if (!quiet
) fprintf(stderr
, " mz: RTP mode! (count=%u, delay=%u usec)\n\n", tx
.count
, tx
.delay
);
1152 (void) create_rtp_packet();
1153 t4
= create_udp_packet(l
); // t4 can be used for later header changes
1154 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1155 if (!quiet
) complexity();
1156 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1157 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1159 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1162 case RX_RTP
: // Receive RTP packets
1169 l
= get_link_context();
1170 (void) create_syslog_packet();
1171 t4
= create_udp_packet(l
); // t4 can be used for later header changes
1172 t3
= create_ip_packet(l
); // t3 can be used for later header changes
1173 if (!quiet
) complexity();
1175 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
1176 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
1178 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
1181 case LLDP
: // start with a new concept here
1182 //l = get_link_context();
1183 //(void) create_lldp_packet();
1184 // // // printf("SIZE=%lu\n",sizeof(struct tx_struct));
1185 fprintf(stderr
, "LLDP is currently only supported via the interactive mode\n");
1191 (void) fprintf(stderr
," mz/main: unknown mode! Stop.\n");
1198 cpu_time_used
= ((double) (mz_stop
- mz_start
)) / CLOCKS_PER_SEC
;
1199 if (cpu_time_used
> 0)
1201 total_d
/= cpu_time_used
;
1202 fprintf(stderr
, "%.2f seconds (%.Lf packets per second)\n",cpu_time_used
,total_d
);
1206 fprintf(stderr
, "\n");