2 * netsniff-ng - the packet sniffing beast
3 * Mausezahn, a fast versatile traffic generator
4 * Copyright 2008, 2009, 2010 Herbert Haas.
5 * Copyright 2012 Daniel Borkmann.
6 * Subject to the GPL, version 2.
11 #include <pcap/pcap.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <arpa/inet.h>
24 #include <sys/ioctl.h>
25 #include <netinet/in.h>
35 int verbose_level
= 0;
37 static const char *short_options
= "46hqvVSxra:A:b:B:c:d:E:f:F:p:P:t:T:M:Q:X:";
39 static void signal_handler(int number
)
44 void clean_up(int sig
)
47 struct arp_table_struct
*cur
, *next
;
49 if (!quiet
) fprintf(stderr
, "\nMausezahn cleans up...\n");
52 verbose_l1(" close files (1) ...\n");
59 if (verbose
) fprintf(stderr
, " close files (2) ...\n");
66 if (verbose
) fprintf(stderr
, " clear mops list...\n");
67 mops_cleanup(mp_head
);
68 if (verbose
) fprintf(stderr
, " clear automops list...\n");
69 automops_cleanup(amp_head
);
70 if (verbose
) fprintf(stderr
, " clear packet sequences...\n");
71 mz_ll_delete_list(packet_sequences
);
74 for (i
=0; i
<device_list_entries
; i
++) {
75 if (device_list
[i
].p_arp
!=NULL
) {
76 pcap_close(device_list
[i
].p_arp
);
77 fprintf(stderr
, " stopped ARP process for device %s\n", device_list
[i
].dev
);
79 if (device_list
[i
].arprx_thread
!=0) {
80 pthread_cancel(device_list
[i
].arprx_thread
);
82 fprintf(stderr
, " (ARP thread for device %s done)\n", device_list
[i
].dev
);
85 if (device_list
[i
].arp_table
!=NULL
) {
86 cur
=device_list
[i
].arp_table
;
89 if (cur
!=NULL
) free(cur
);
94 // close packet sockets
95 if (device_list
[i
].ps
>=0) {
96 close(device_list
[i
].ps
);
101 if (verbose
) fprintf(stderr
, "finished.\n");
106 static void help(void)
108 printf("\n%s %s, a fast versatile traffic generator\n",
109 PROGNAME_STRING
, VERSION_STRING
);
110 puts("http://www.netsniff-ng.org\n\n"
111 "Usage: mausezahn [options] [interface] <keyword>|<arg-string>|<hex-string>\n"
113 " -x <port> Interactive mode with telnet CLI, default port: 25542\n"
114 " -4 IPv4 mode (default)\n"
116 " -c <count> Send packet count times, default:1, infinite:0\n"
117 " -d <delay> Apply delay between transmissions. The delay value can be\n"
118 " specified in usec (default, no additional unit needed), or in\n"
119 " msec (e.g. 100m or 100msec), or in seconds (e.g. 100s or 100sec)\n"
120 " -r Multiplies the specified delay with a random value\n"
121 " -p <length> Pad the raw frame to specified length (using random bytes)\n"
122 " -a <srcmac|keyword> Use specified source mac address, no matter what has\n"
123 " been specified with other arguments; keywords see below,\n"
124 " Default is own interface\n"
125 " -b <dstmac|keyword> Same with destination mac address; keywords:\n"
126 " rand Use a random MAC address\n"
127 " bc Use a broadcast MAC address\n"
128 " own Use own interface MAC address (default for source MAC)\n"
129 " stp Use IEEE 802.1d STP multicast address\n"
130 " cisco Use Cisco multicast address as used for CDP, VTP, or PVST+\n"
131 " -A <srcip> Use specified source IP address (default is own interface IP)\n"
132 " -B <dstip|dnsname> Send packet to specified destination IP or domain name\n"
133 " -P <ascii payload> Use the specified ASCII payload\n"
134 " -f <filename> Read the ASCII payload from a file\n"
135 " -F <filename> Read the hexadecimal payload from a file\n"
136 " -Q <[CoS:]vlan> Specify 802.1Q VLAN tag and optional Class of Service, you can\n"
137 " specify multiple 802.1Q VLAN tags (QinQ...) by separating them\n"
138 " via a comma or a period (e.g. '5:10,20,2:30')\n"
139 " -t <packet-type> Specify packet type for autobuild (you don't need to care for\n"
140 " encapsulations in lower layers, most packet types allow/require\n"
141 " additional packet-specific arguments in an <arg-string>;\n"
142 " Currently supported types: arp, bpdu, cdp, ip, icmp, udp, tcp,\n"
143 " dns, rtp, syslog, lldp and more;\n"
144 " For context-help use 'help' as <arg-string>!\n"
145 " -T <packet-type> Specify packet type for server mode, currently only rtp is supported;\n"
146 " Enter -T help or -T rtp help for further information\n"
147 " -M <MPLS-label> Insert a MPLS label, enter '-M help' for a syntax description\n"
148 " -V|VV|... Verbose and more verbose mode\n"
149 " -q Quiet mode, even omit 'important' standard short messages\n"
150 " -S Simulation mode: DOES NOT put anything on the wire, this is\n"
151 " typically combined with one of the verbose modes (v or V)\n"
153 " -h Print this help\n\n"
156 " mausezahn -c 0 -d 2s -t bpdu conf\n"
157 " mausezahn -t cdp change -c 0\n"
158 " mausezahn -t syslog sev=3 -P \"You have been mausezahned.\" -A 10.1.1.109 -B 192.168.7.7\n"
159 " mausezahn eth0 -A rand -B 1.1.1.1 -c 0 -t tcp \"dp=1-1023, flags=syn\"\n\n"
161 " This tool is targeted for network developers! You should\n"
162 " be aware of what you are doing and what these options above\n"
163 " mean! Only use this tool in an isolated LAN that you own!\n\n"
164 "Please report bugs to <bugs@netsniff-ng.org>\n"
165 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
166 "Copyright (C) 2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
167 "Swiss federal institute of technology (ETH Zurich)\n"
168 "License: GNU GPL version 2.0\n"
169 "This is free software: you are free to change and redistribute it.\n"
170 "There is NO WARRANTY, to the extent permitted by law.\n");
174 static void version(void)
176 printf("\n%s %s, a fast versatile traffic generator\n",
177 PROGNAME_STRING
, VERSION_STRING
);
178 puts("http://www.netsniff-ng.org\n\n"
179 "Please report bugs to <bugs@netsniff-ng.org>\n"
180 "Copyright (C) 2008-2010 Herbert Haas <herbert@perihel.at>,\n"
181 "Copyright (C) 2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
182 "Swiss federal institute of technology (ETH Zurich)\n"
183 "License: GNU GPL version 2.0\n"
184 "This is free software: you are free to change and redistribute it.\n"
185 "There is NO WARRANTY, to the extent permitted by law.\n");
194 // Determine platform type sizes:
195 MZ_SIZE_LONG_INT
= sizeof(long int);
197 mz_default_config_path
[0] = 0x00;
198 mz_default_log_path
[0] = 0x00;
208 gind_max
= TIME_COUNT
;
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
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
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';
239 tx
.eth_payload
[0] = '\0';
240 tx
.eth_payload_s
= 0;
243 // Reset CDP parameters for TX:
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:
254 tx
.dot1Q_txt
[0] = '\0';
257 tx
.ascii
= 0; // 1 if specified
258 tx
.ascii_payload
[0]= '\0';
261 tx
.hex_payload_s
= 0;
263 // Reset MPLS parameters of TX:
265 tx
.mpls_txt
[0] = '\0';
270 tx
.mpls_verbose_string
[0] = '\0';
272 // Reset IP parameters of TX:
273 tx
.ip_src_txt
[0] = '\0';
275 tx
.ip_dst_txt
[0] = '\0';
276 tx
.ip_src_isrange
= 0;
282 tx
.ip_dst_isrange
= 0;
285 tx
.ip_payload
[0]= '\0';
287 tx
.ip_option
[0]= '\0';
290 // Reset ICMP parameters:
293 tx
.icmp_chksum
=0; // 0=autofill
298 // Reset general L4 parameters:
308 // Reset UDP parameters of TX:
310 tx
.udp_len
= 0; // If set to zero then create_udp_packet will calculate it
312 tx
.udp_payload
[0] = '\0';
313 tx
.udp_payload_s
= 0;
315 // Reset TCP parameters of TX:
318 tx
.tcp_seq_stop
= 42;
319 tx
.tcp_seq_delta
= 0; // also used as 'isrange' meaning
325 tx
.tcp_len
= 20; // Least size (TCP header only)
326 tx
.tcp_payload
[0] = '\0';
327 tx
.tcp_payload_s
= 0;
329 // Reset RTP parameters of TX:
333 // Initialize random generator
335 srand((unsigned int)t
);
338 for (i
=0; i
<MZ_MAX_DEVICES
; i
++) {
339 device_list
[i
].arprx_thread
= 0;
340 device_list
[i
].p_arp
= NULL
;
341 device_list
[i
].arp_table
= NULL
;
342 device_list
[i
].ps
=-1;
343 device_list
[i
].cli
=0;
344 device_list
[i
].mgmt_only
=0;
352 // Purpose: Properly handle arguments and configure global structs (tx)
353 int getopts (int argc
, char *argv
[])
355 int i
, c
, rargs
, RX
=0, count_set
=0, delay_set
=0;
356 unsigned int time_factor
;
357 char *packet_type
=NULL
, *mops_type
=NULL
;
359 unsigned char *dum1
, *dum2
;
362 char err_buf
[LIBNET_ERRBUF_SIZE
];
363 struct libnet_ether_addr
*mymac
;
366 char hexpld
[MAX_PAYLOAD_SIZE
*2];
367 int hexpld_specified
=0;
369 opterr
= 1; // let getopt print error message if necessary
372 while ((c
= getopt(argc
, argv
, short_options
)) != -1)
375 tx
.eth_type
= 0x0800;
379 tx
.eth_type
= 0x86dd;
398 mz_port
= MZ_DEFAULT_PORT
;
401 strncpy (tx
.eth_src_txt
, optarg
, 32);
405 strncpy (tx
.ip_src_txt
, optarg
, sizeof(tx
.ip_src_txt
));
408 strncpy (tx
.eth_dst_txt
, optarg
, 32);
412 strncpy (tx
.ip_dst_txt
, optarg
, sizeof(tx
.ip_dst_txt
));
416 tx
.count
= strtol(optarg
, (char **)NULL
, 10);
417 if ((errno
== ERANGE
&& (tx
.count
== LONG_MAX
|| tx
.count
== LONG_MIN
))
418 || (errno
!= 0 && tx
.count
== 0)) {
422 if (tx
.count
<0) tx
.count
=1; //TODO: Allow count=0 which means infinity (need to update all send_functions)
427 // determine whether seconds or msecs are used
428 // default is usec!!!
430 if (exists(optarg
,"s") || exists(optarg
,"sec")) time_factor
=1000000;
431 if (exists(optarg
,"m") || exists(optarg
,"msec")) time_factor
=1000;
432 dum
= strtok(optarg
,"ms");
433 tx
.delay
= strtol(dum
, (char **)NULL
, 10) * time_factor
;
434 if ((errno
== ERANGE
&& (tx
.delay
== LONG_MAX
|| tx
.delay
== LONG_MIN
))
435 || (errno
!= 0 && tx
.delay
== 0)) {
439 if (tx
.delay
<0) tx
.delay
=0; // no delay
444 tx
.padding
= strtol(optarg
, (char **)NULL
, 10);
445 if ((errno
== ERANGE
&& (tx
.padding
== LONG_MAX
|| tx
.padding
== LONG_MIN
))
446 || (errno
!= 0 && tx
.padding
== 0)) {
450 if (tx
.padding
>10000) {
451 fprintf(stderr
, " Warning: Padding must not exceed 10000!\n");
456 packet_type
= optarg
; // analyzed below
459 mops_type
= optarg
; // MOPS TRANSITION STRATEGY -- analyzed below
462 packet_type
= optarg
;
469 if (strncmp(optarg
,"help",4)==0) {
470 (void) get_mpls_params("help ");
473 strncpy (tx
.mpls_txt
, optarg
, 128);
474 tx
.eth_type
= ETHERTYPE_MPLS
;
479 case 'P': // ASCII payload
480 strncpy((char*)tx
.ascii_payload
, optarg
, MAX_PAYLOAD_SIZE
);
483 case 'f': // ASCII payload in FILE
484 afp
= fopen(optarg
, "r");
485 if (fgets((char*)tx
.ascii_payload
, MAX_PAYLOAD_SIZE
, afp
) == NULL
)
486 fprintf(stderr
, " mz/getopts: File empty?\n");
490 case 'F': // HEX payload in FILE
491 afp
= fopen(optarg
, "r");
493 while ( (hexpld
[i
]=fgetc(afp
))!=EOF
) {
494 if (isspace(hexpld
[i
])) {
503 case 'Q': // VLAN TAG
504 if (strncmp(optarg
,"help",4)==0) {
505 print_dot1Q_help(); // ugly but most simple and safe solution
508 strncpy (tx
.dot1Q_txt
, optarg
, 32);
510 // determine number of VLAN tags
511 for (i
=0; i
<strlen(tx
.dot1Q_txt
); i
++) {
512 if (tx
.dot1Q_txt
[i
]==',') tx
.dot1Q
++;
518 if ((optopt
== 'a') || (optopt
== 'b') || (optopt
= 'c') ||
519 (optopt
== 'd') || (optopt
== 'f') || (optopt
= 'p') ||
520 (optopt
== 't') || (optopt
== 'm'))
521 fprintf (stderr
, " mz/getopts: Option -%c requires an argument.\n", optopt
);
522 else if (isprint (optopt
))
523 fprintf (stderr
, " mz/getopts: Unknown option -%c'.\n", optopt
);
525 fprintf (stderr
, " mz/getopts: Unknown option character \\x%x'.\n", optopt
);
528 fprintf (stderr
," mz/getopts: Could not handle arguments properly!\n");
532 // ********************************************
533 // Handle additional arguments
534 // ********************************************
541 "Use at your own risk and responsibility!\n"
542 "-- Verbose mode --\n"
550 if ((rargs
=argc
-optind
)>2) { // number of remaining arguments
551 fprintf(stderr
," mz/getopts: Too many arguments!\n");
556 // There can be 0-2 additional arguments
559 if (lookupdev()) { // no device found
560 if (verbose
) fprintf(stderr
, " mz: no active interfaces found!\n");
561 strcpy(tx
.device
, "lo");
563 if (verbose
) // device found
564 fprintf(stderr
," mz: device not given, will use %s\n",tx
.device
);
566 case 1: // arg_string OR device given => find out!
567 if ( (strncmp(argv
[optind
],"eth",3)==0)
568 || (strncmp(argv
[optind
],"ath",3)==0)
569 || ((strncmp(argv
[optind
],"lo",2)==0)&&(strncmp(argv
[optind
],"log",3)!=0))
570 || (strncmp(argv
[optind
],"vmnet",5)==0)
571 || (strncmp(argv
[optind
],"wifi",4)==0) ) {
572 // device has been specified!
573 strncpy (tx
.device
, argv
[optind
], 16);
575 else { /// arg_string given => no device has been specified -- let's find one!
576 strncpy (tx
.arg_string
, argv
[optind
], MAX_PAYLOAD_SIZE
);
577 if (lookupdev()) { // no device found
578 if (verbose
) fprintf(stderr
, " mz: no active interfaces found!\n");
579 strcpy(tx
.device
, "lo");
582 fprintf(stderr
," mz: device not given, will use %s\n",tx
.device
);
585 case 2: // both device and arg_string given
586 strncpy (tx
.device
, argv
[optind
], 16);
587 strncpy (tx
.arg_string
, argv
[optind
+1], MAX_PAYLOAD_SIZE
);
590 fprintf(stderr
," mz/getopts: Unknown argument problem!\n");
594 if (hexpld_specified
) {
595 strcat(tx
.arg_string
, ",p=");
596 strcat(tx
.arg_string
, hexpld
);
600 //////////////////////////////////////////////////////////////////////////
602 // Initialize MAC and IP Addresses.
604 // - tx.eth_src = own interface MAC
605 // - tx.ip_src = own interface IP or user specified
606 // - tx.ip_dst = 255.255.255.255 or user specified (can be a range)
607 // - tx.ip_src_rand ... is set if needed.
610 // Get own device MAC address:
611 // Don't open context if only a help text is requested
612 if (getarg(tx
.arg_string
,"help", NULL
)!=1) {
613 l
= libnet_init (LIBNET_LINK_ADV
, tx
.device
, err_buf
);
615 fprintf(stderr
, " mz/getopts: libnet_init() failed (%s)", err_buf
);
618 mymac
= libnet_get_hwaddr(l
);
619 for (i
=0; i
<6; i
++) {
620 tx
.eth_src
[i
] = mymac
->ether_addr_octet
[i
];
621 tx
.eth_mac_own
[i
] = mymac
->ether_addr_octet
[i
];
624 // Set source IP address:
625 if (strlen(tx
.ip_src_txt
)) { // option -A has been specified
626 if (mz_strcmp(tx
.ip_src_txt
, "bcast", 2)==0) {
627 tx
.ip_src
= libnet_name2addr4 (l
, "255.255.255.255", LIBNET_DONT_RESOLVE
);
628 } else if (strcmp(tx
.ip_src_txt
, "rand") == 0) {
630 tx
.ip_src_h
= (u_int32_t
) ( ((float) rand()/RAND_MAX
)*0xE0000000); //this is 224.0.0.0
632 else if (get_ip_range_src(tx
.ip_src_txt
)) { // returns 1 when no range has been specified
633 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
635 tx
.ip6_src
= libnet_name2addr6 (l
, tx
.ip_src_txt
, LIBNET_RESOLVE
);
637 tx
.ip_src
= libnet_name2addr4 (l
, tx
.ip_src_txt
, LIBNET_RESOLVE
);
640 else { // no source IP specified: by default use own IP address
642 tx
.ip6_src
= libnet_get_ipaddr6(l
);
643 if (strncmp((char*)&tx
.ip6_src
,(char*)&in6addr_error
,sizeof(in6addr_error
))==0)
644 printf("Failed to set source IPv6 address: %s", l
->err_buf
);
647 tx
.ip_src
= libnet_get_ipaddr4(l
);
650 // Set destination IP address:
651 if (strlen(tx
.ip_dst_txt
)) { // option -B has been specified
652 if (mz_strcmp(tx
.ip_dst_txt
, "rand", 2)==0) {
653 fprintf(stderr
, "Option -B does not support random destination IP addresses currently.\n");
657 if (mz_strcmp(tx
.ip_dst_txt
, "bcast", 2)==0) {
658 tx
.ip_dst
= libnet_name2addr4 (l
, "255.255.255.255", LIBNET_DONT_RESOLVE
);
659 } else if (get_ip_range_dst(tx
.ip_dst_txt
)) { // returns 1 when no range has been specified
660 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
662 tx
.ip6_dst
= libnet_name2addr6 (l
, tx
.ip_dst_txt
, LIBNET_RESOLVE
);
664 tx
.ip_dst
= libnet_name2addr4 (l
, tx
.ip_dst_txt
, LIBNET_RESOLVE
);
667 else { // no destination IP specified: by default use broadcast
668 tx
.ip_dst
= libnet_name2addr4 (l
, "255.255.255.255", LIBNET_DONT_RESOLVE
);
671 // Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()'
672 // in verbose mode. See 'modifications.c'.
674 if (tx
.ip_src_rand
) { // ip_src_h already given, convert to ip_src
675 dum1
= (unsigned char*) &tx
.ip_src_h
;
676 dum2
= (unsigned char*) &tx
.ip_src
;
678 else { // ip_src already given, convert to ip_src_h
679 dum1
= (unsigned char*) &tx
.ip_src
;
680 dum2
= (unsigned char*) &tx
.ip_src_h
;
691 dum1
= (unsigned char*) &tx
.ip_dst
;
692 dum2
= (unsigned char*) &tx
.ip_dst_h
;
706 // END OF ADDRESS INITIALIZATION
708 //////////////////////////////////////////////////////////////////////////
711 ////// retrieve interface parameters ///////
713 for (i
=0; i
<device_list_entries
; i
++) {
714 get_dev_params(device_list
[i
].dev
);
718 //////////////////////////////////////////////////////////////////////////
720 // Mausezahn CLI desired?
722 // has port number been specified?
723 if (strlen(tx
.arg_string
)) {
724 mz_port
= (int) str2int (tx
.arg_string
);
728 fprintf(stderr
, "Mausezahn accepts incoming Telnet connections on port %i.\n", mz_port
);
735 //////////////////////////////////////////////////////////////////////////
739 // Consider -t and -m option (used exclusively)
740 // -t => special packet types, stateless
742 // If -t not present then evaluate arg_string which must
743 // contain a byte-string in hexadecimal notation.
747 // ***** NEW: MOPS TRANSITION STRATEGY *****
748 if (mops_type
!= NULL
) {
750 if (mz_strcmp(mops_type
,"lldp",4)==0) {
751 mops_direct(tx
.device
, MOPS_LLDP
, tx
.arg_string
);
756 if (packet_type
== NULL
) { // raw hex string given
759 else if (strcmp(packet_type
,"arp")==0) {
762 else if (strcmp(packet_type
,"bpdu")==0) {
765 else if (strcmp(packet_type
,"ip")==0) {
768 else if (strcmp(packet_type
,"udp")==0) {
771 else if (strcmp(packet_type
,"icmp")==0) {
774 else if (strcmp(packet_type
,"icmp6")==0) {
777 else if (strcmp(packet_type
,"tcp")==0) {
780 else if (strcmp(packet_type
,"dns")==0) {
783 else if (strcmp(packet_type
,"cdp")==0) {
786 else if (strcmp(packet_type
,"syslog")==0) {
789 else if (strcmp(packet_type
,"lldp")==0) {
791 tx
.packet_mode
=0; // create whole frame by ourself
793 else if (strcmp(packet_type
,"rtp")==0) {
799 if (!count_set
) tx
.count
= 0;
800 if (!delay_set
) tx
.delay
= 20000; // 20 msec inter-packet delay for RTP
803 else if (strcmp(packet_type
,"help")==0) {
807 "| The following packet types are currently implemented:\n"
809 "| arp ... sends ARP packets\n"
810 "| bpdu ... sends BPDU packets (STP or PVST+)\n"
811 "| cdp ... sends CDP messages\n"
812 "| ip ... sends IPv4 packets\n"
813 "| udp ... sends UDP datagrams\n"
814 "| tcp ... sends TCP segments\n"
815 "| icmp ... sends ICMP messages\n"
816 "| dns ... sends DNS messages\n"
817 "| rtp ... sends RTP datagrams\n"
818 "| syslog ... sends Syslog messages\n"
820 "| Of course you can build any other packet type 'manually' using the direct layer 2 mode.\n"
821 "| FYI: The interactive mode supports additional protocols. (Try mz -x <port>)\n"
827 fprintf(stderr
, " mz: you must specify a valid packet type!\n");
831 //////////////////////////////////////////////////////////////////////////
833 // TODO: Implement macro support
834 // Check macro types here
839 int main(int argc
, char **argv
)
841 // These handles are only used when creating L3 and above packets.
842 libnet_t
*l
; // the context
843 libnet_ptag_t t2
=0, t3
=0, t4
=0; // handles to layers
844 double cpu_time_used
;
848 if ( getopts(argc
, argv
) )
850 (void) fprintf(stderr
, " Invalid command line parameters!\n");
854 // Check whether hires timers are supported or not:
855 (void) check_timer();
857 signal(SIGINT
, signal_handler
); // to close all file pointers etc upon SIGINT
877 case IP
: // From now on a new much more modular method is used:
878 l
= get_link_context();
879 t3
= create_ip_packet(l
); // t3 can be used for later header changes
880 if (!quiet
) complexity();
881 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
882 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
884 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
889 l
= get_link_context();
890 t4
= create_icmp_packet(l
); // t4 can be used for later header changes
891 t3
= create_ip_packet(l
); // t3 can be used for later header changes
892 if (!quiet
) complexity();
893 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
894 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
896 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
901 l
= get_link_context();
902 t4
= create_icmp6_packet(l
); // t4 can be used for later header changes
903 t3
= create_ip_packet(l
); // t3 can be used for later header changes
906 if (!quiet
) complexity();
907 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
908 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
910 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
915 l
= get_link_context();
916 t4
= create_udp_packet(l
); // t4 can be used for later header changes
917 t3
= create_ip_packet(l
); // t3 can be used for later header changes
920 if (!quiet
) complexity();
921 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
922 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
924 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
929 l
= get_link_context();
930 t4
= create_tcp_packet(l
); // t4 can be used for later header changes
931 t3
= create_ip_packet(l
); // t3 can be used for later header changes
934 if (!quiet
) complexity();
935 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
936 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
938 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
943 l
= get_link_context();
944 (void) create_dns_packet();
945 t4
= create_udp_packet(l
); // t4 can be used for later header changes
946 t3
= create_ip_packet(l
); // t3 can be used for later header changes
947 if (!quiet
) complexity();
948 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
949 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
951 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
956 l
= get_link_context();
957 if (!quiet
) fprintf(stderr
, " mz: RTP mode! (count=%u, delay=%u usec)\n\n", tx
.count
, tx
.delay
);
958 (void) create_rtp_packet();
959 t4
= create_udp_packet(l
); // t4 can be used for later header changes
960 t3
= create_ip_packet(l
); // t3 can be used for later header changes
961 if (!quiet
) complexity();
962 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
963 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
965 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
968 case RX_RTP
: // Receive RTP packets
975 l
= get_link_context();
976 (void) create_syslog_packet();
977 t4
= create_udp_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();
981 if (tx
.packet_mode
==0) // Ethernet manipulation features does NOT use ARP to determine eth_dst
982 t2
= create_eth_frame(l
, t3
, t4
); // t2 can be used for later header changes
984 send_frame (l
, t3
, t4
); // NOTE: send_frame also destroys context finaly
987 case LLDP
: // start with a new concept here
988 //l = get_link_context();
989 //(void) create_lldp_packet();
990 // // // printf("SIZE=%lu\n",sizeof(struct tx_struct));
991 fprintf(stderr
, "LLDP is currently only supported via the interactive mode\n");
997 (void) fprintf(stderr
," mz/main: unknown mode! Stop.\n");
1004 cpu_time_used
= ((double) (mz_stop
- mz_start
)) / CLOCKS_PER_SEC
;
1005 if (cpu_time_used
> 0)
1007 total_d
/= cpu_time_used
;
1008 fprintf(stderr
, "%.2f seconds (%.Lf packets per second)\n",cpu_time_used
,total_d
);
1012 fprintf(stderr
, "\n");