html: give address to list
[netsniff-ng.git] / src / init.c
blob12bd787e6c76b779f3a542bb8082388603a2fd35
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
22 // ****************************************************************************
23 // Two features here:
24 // 1. Initialize globals
25 // 2. Handle arguments in *argv[] and make a mode decision
26 // ****************************************************************************
28 #include "mz.h"
29 #include "cli.h"
30 #include "mops.h"
32 // Purpose: reset globals, global structs, etc.
33 int reset()
35 int i;
36 time_t t;
38 // Determine platform type sizes:
39 MZ_SIZE_LONG_INT = sizeof(long int);
41 mz_default_config_path[0] = 0x00;
42 mz_default_log_path[0] = 0x00;
44 // Reset globals:
45 quiet = 0;
46 ipv6_mode = 0;
47 verbose = 0;
48 simulate = 0;
49 filename[0] = '\0';
50 path[0] = '\0';
51 gind=0;
52 gind_max = TIME_COUNT;
53 fp = NULL;
54 fp2 = NULL;
55 mz_port = 0;
56 mz_rand = 0;
57 mp_head = NULL;
59 for (i=0;i<TIME_COUNT_MAX;i++) jitter[i] = 0;
61 time0_flag = 0; // If set then time0 has valid data
62 sqnr0_flag = 0; // If set then sqnr_last and sqnr_next has valid data
63 rtp_log = 0;
64 mz_ssrc[0]=0; mz_ssrc[1]=0; mz_ssrc[2]=0; mz_ssrc[3]=0;
66 // Reset mgmt parameters of TX:
67 tx.packet_mode = 1; // assume we don't care about L2
68 tx.count = 1;
69 tx.delay = DEFAULT_DELAY;
70 tx.arg_string[0] = '\0';
72 // Reset Ethernet parameters of TX:
73 tx.eth_params_already_set = 0;
74 for (i=0; i<6; i++) tx.eth_dst[i] = 0xff;
75 for (i=0; i<6; i++) tx.eth_src[i] = 0; // TODO: Get own MAC !!!
76 tx.eth_dst_txt[0] = '\0';
77 tx.eth_src_txt[0] = '\0';
78 tx.eth_dst_rand = 0;
79 tx.eth_src_rand = 0;
81 tx.eth_type = 0x800;
82 tx.eth_len = 0;
83 tx.eth_payload[0] = '\0';
84 tx.eth_payload_s = 0;
85 tx.padding = 0;
87 // Reset CDP parameters for TX:
88 tx.cdp_sum = 0;
89 tx.cdp_version = 0;
90 tx.cdp_ttl = 0;
91 tx.cdp_payload[0] = '\0';
92 tx.cdp_payload_s = 0;
93 tx.cdp_tlv_id[0] = '\0';
94 tx.cdp_tlv_id_len = 0;
96 // Reset 802.1Q parameters of TX:
97 tx.dot1Q=0;
98 tx.dot1Q_txt[0] = '\0';
100 // ASCII Payload:
101 tx.ascii = 0; // 1 if specified
102 tx.ascii_payload[0]= '\0';
104 // HEX Payload:
105 tx.hex_payload_s = 0;
107 // Reset MPLS parameters of TX:
108 tx.mpls = 0;
109 tx.mpls_txt[0] = '\0';
110 tx.mpls_label = 0;
111 tx.mpls_exp = 0;
112 tx.mpls_bos = 1;
113 tx.mpls_ttl = 255;
114 tx.mpls_verbose_string[0] = '\0';
116 // Reset IP parameters of TX:
117 tx.ip_src_txt[0] = '\0';
118 tx.ip_src_rand = 0;
119 tx.ip_dst_txt[0] = '\0';
120 tx.ip_src_isrange = 0;
121 tx.ip_src_start = 0;
122 tx.ip_src_stop = 0;
124 tx.ip_dst_start = 0;
125 tx.ip_dst_stop = 0;
126 tx.ip_dst_isrange = 0;
128 tx.ip_len = 0;
129 tx.ip_payload[0]= '\0';
130 tx.ip_payload_s = 0;
131 tx.ip_option[0]= '\0';
132 tx.ip_option_s = 0;
134 // Reset ICMP parameters:
135 tx.icmp_type=0;
136 tx.icmp_code=0;
137 tx.icmp_chksum=0; // 0=autofill
138 tx.icmp_ident=0x42;
139 tx.icmp_sqnr=0x1;
140 tx.icmp_payload_s=0;
142 // Reset general L4 parameters:
143 tx.sp = 0;
144 tx.dp = 0;
145 tx.sp_start = 0;
146 tx.sp_stop = 0;
147 tx.dp_start = 0;
148 tx.dp_stop = 0;
149 tx.sp_isrange = 0;
150 tx.dp_isrange = 0;
152 // Reset UDP parameters of TX:
154 tx.udp_len = 0; // If set to zero then create_udp_packet will calculate it
155 tx.udp_sum = 0;
156 tx.udp_payload[0] = '\0';
157 tx.udp_payload_s = 0;
159 // Reset TCP parameters of TX:
161 tx.tcp_seq = 42;
162 tx.tcp_seq_stop = 42;
163 tx.tcp_seq_delta = 0; // also used as 'isrange' meaning
164 tx.tcp_ack = 42;
165 tx.tcp_control = 0;
166 tx.tcp_win = 10000;
167 tx.tcp_sum = 0;
168 tx.tcp_urg = 0;
169 tx.tcp_len = 20; // Least size (TCP header only)
170 tx.tcp_payload[0] = '\0';
171 tx.tcp_payload_s = 0;
173 // Reset RTP parameters of TX:
174 tx.rtp_sqnr = 0;
175 tx.rtp_stmp = 0;
177 // Initialize random generator
178 time(&t);
179 srand((unsigned int)t);
181 // Reset device_list
182 for (i=0; i<MZ_MAX_DEVICES; i++) {
183 device_list[i].arprx_thread = 0;
184 device_list[i].p_arp = NULL;
185 device_list[i].arp_table = NULL;
186 device_list[i].ps=-1;
187 device_list[i].cli=0;
188 device_list[i].mgmt_only=0;
191 return 0;
196 // Purpose: Properly handle arguments and configure global structs (tx)
197 int getopts (int argc, char *argv[])
199 int i, c, rargs, RX=0, count_set=0, delay_set=0;
200 unsigned int time_factor;
201 char *packet_type=NULL, *mops_type=NULL;
202 char *dum;
203 unsigned char *dum1, *dum2;
205 libnet_t *l;
206 char err_buf[LIBNET_ERRBUF_SIZE];
207 struct libnet_ether_addr *mymac;
209 FILE *afp;
210 char hexpld[MAX_PAYLOAD_SIZE*2];
211 int hexpld_specified=0;
213 opterr = 1; // let getopt print error message if necessary
216 while ((c = getopt (argc, argv, "46hqvVSxra:A:b:B:c:d:E:f:F:p:P:t:T:M:Q:X:")) != -1)
217 switch (c) {
218 case '4':
219 tx.eth_type = 0x0800;
220 ipv6_mode=0;
221 break;
222 case '6':
223 tx.eth_type = 0x86dd;
224 ipv6_mode=1;
225 break;
226 case 'h':
227 usage();
228 break;
229 case 'q':
230 quiet=1;
231 break;
232 case 'v':
233 verbose=1;
234 break;
235 case 'V':
236 verbose=2;
237 break;
238 case 'S':
239 simulate=1;
240 break;
241 case 'x':
242 mz_port = MZ_DEFAULT_PORT;
243 break;
244 case 'a':
245 strncpy (tx.eth_src_txt, optarg, 32);
246 tx.packet_mode = 0;
247 break;
248 case 'A':
249 strncpy (tx.ip_src_txt, optarg, sizeof(tx.ip_src_txt));
250 break;
251 case 'b':
252 strncpy (tx.eth_dst_txt, optarg, 32);
253 tx.packet_mode = 0;
254 break;
255 case 'B':
256 strncpy (tx.ip_dst_txt, optarg, sizeof(tx.ip_dst_txt));
257 break;
258 case 'c':
259 errno=0;
260 tx.count = strtol(optarg, (char **)NULL, 10);
261 if ((errno == ERANGE && (tx.count == LONG_MAX || tx.count == LONG_MIN))
262 || (errno != 0 && tx.count == 0)) {
263 perror("strtol");
264 return (-1);
266 if (tx.count<0) tx.count=1; //TODO: Allow count=0 which means infinity (need to update all send_functions)
267 count_set=1;
268 break;
269 case 'd':
270 errno=0;
271 // determine whether seconds or msecs are used
272 // default is usec!!!
273 time_factor=1;
274 if (exists(optarg,"s") || exists(optarg,"sec")) time_factor=1000000;
275 if (exists(optarg,"m") || exists(optarg,"msec")) time_factor=1000;
276 dum = strtok(optarg,"ms");
277 tx.delay = strtol(dum, (char **)NULL, 10) * time_factor;
278 if ((errno == ERANGE && (tx.delay == LONG_MAX || tx.delay == LONG_MIN))
279 || (errno != 0 && tx.delay == 0)) {
280 perror("strtol");
281 return (-1);
283 if (tx.delay<0) tx.delay=0; // no delay
284 delay_set=1;
285 break;
286 case 'p':
287 errno=0;
288 tx.padding = strtol(optarg, (char **)NULL, 10);
289 if ((errno == ERANGE && (tx.padding == LONG_MAX || tx.padding == LONG_MIN))
290 || (errno != 0 && tx.padding == 0)) {
291 perror("strtol");
292 return (-1);
294 if (tx.padding>10000) {
295 fprintf(stderr, " Warning: Padding must not exceed 10000!\n");
296 return -1;
298 break;
299 case 't':
300 packet_type = optarg; // analyzed below
301 break;
302 case 'X':
303 mops_type = optarg; // MOPS TRANSITION STRATEGY -- analyzed below
304 break;
305 case 'T':
306 packet_type = optarg;
307 RX = 1;
308 break;
309 case 'r':
310 mz_rand = 1;
311 break;
312 case 'M':
313 if (strncmp(optarg,"help",4)==0) {
314 (void) get_mpls_params("help ");
316 else {
317 strncpy (tx.mpls_txt, optarg, 128);
318 tx.eth_type = ETHERTYPE_MPLS;
319 tx.packet_mode = 0;
320 tx.mpls=1;
322 break;
323 case 'P': // ASCII payload
324 strncpy((char*)tx.ascii_payload, optarg, MAX_PAYLOAD_SIZE);
325 tx.ascii = 1;
326 break;
327 case 'f': // ASCII payload in FILE
328 afp = fopen(optarg, "r");
329 if (fgets((char*)tx.ascii_payload, MAX_PAYLOAD_SIZE, afp) == NULL)
330 fprintf(stderr, " mz/getopts: File empty?\n");
331 fclose(afp);
332 tx.ascii = 1;
333 break;
334 case 'F': // HEX payload in FILE
335 afp = fopen(optarg, "r");
336 i=0;
337 while ( (hexpld[i]=fgetc(afp))!=EOF ) {
338 if (isspace(hexpld[i])) {
339 hexpld[i]=':';
341 i++;
343 hexpld[i]='\0';
344 fclose(afp);
345 hexpld_specified=1;
346 break;
347 case 'Q': // VLAN TAG
348 if (strncmp(optarg,"help",4)==0) {
349 print_dot1Q_help(); // ugly but most simple and safe solution
351 else {
352 strncpy (tx.dot1Q_txt, optarg, 32);
353 tx.dot1Q=1;
354 // determine number of VLAN tags
355 for (i=0; i<strlen(tx.dot1Q_txt); i++) {
356 if (tx.dot1Q_txt[i]==',') tx.dot1Q++;
358 tx.packet_mode = 0;
360 break;
361 case '?':
362 if ((optopt == 'a') || (optopt == 'b') || (optopt = 'c') ||
363 (optopt == 'd') || (optopt == 'f') || (optopt = 'p') ||
364 (optopt == 't') || (optopt == 'm'))
365 fprintf (stderr, " mz/getopts: Option -%c requires an argument.\n", optopt);
366 else if (isprint (optopt))
367 fprintf (stderr, " mz/getopts: Unknown option -%c'.\n", optopt);
368 else
369 fprintf (stderr, " mz/getopts: Unknown option character \\x%x'.\n", optopt);
370 return 1;
371 default:
372 fprintf (stderr," mz/getopts: Could not handle arguments properly!\n");
373 return 1;
376 // ********************************************
377 // Handle additional arguments
378 // ********************************************
380 // Greeting text
381 if (verbose) {
382 fprintf(stderr,"\n"
383 MAUSEZAHN_VERSION
384 "\n"
385 "Use at your own risk and responsibility!\n"
386 "-- Verbose mode --\n"
387 "\n");
390 if (argc<2) {
391 usage();
394 if ((rargs=argc-optind)>2) { // number of remaining arguments
395 fprintf(stderr," mz/getopts: Too many arguments!\n");
396 return -1;
400 // There can be 0-2 additional arguments
401 switch (rargs) {
402 case 0:
403 if (lookupdev()) { // no device found
404 if (verbose) fprintf(stderr, " mz: no active interfaces found!\n");
405 strcpy(tx.device, "lo");
407 if (verbose) // device found
408 fprintf(stderr," mz: device not given, will use %s\n",tx.device);
409 break;
410 case 1: // arg_string OR device given => find out!
411 if ( (strncmp(argv[optind],"eth",3)==0)
412 || (strncmp(argv[optind],"ath",3)==0)
413 || ((strncmp(argv[optind],"lo",2)==0)&&(strncmp(argv[optind],"log",3)!=0))
414 || (strncmp(argv[optind],"vmnet",5)==0)
415 || (strncmp(argv[optind],"wifi",4)==0) ) {
416 // device has been specified!
417 strncpy (tx.device, argv[optind], 16);
419 else { /// arg_string given => no device has been specified -- let's find one!
420 strncpy (tx.arg_string, argv[optind], MAX_PAYLOAD_SIZE);
421 if (lookupdev()) { // no device found
422 if (verbose) fprintf(stderr, " mz: no active interfaces found!\n");
423 strcpy(tx.device, "lo");
425 if (verbose)
426 fprintf(stderr," mz: device not given, will use %s\n",tx.device);
428 break;
429 case 2: // both device and arg_string given
430 strncpy (tx.device, argv[optind], 16);
431 strncpy (tx.arg_string, argv[optind+1], MAX_PAYLOAD_SIZE);
432 break;
433 default:
434 fprintf(stderr," mz/getopts: Unknown argument problem!\n");
435 return 1;
438 if (hexpld_specified) {
439 strcat(tx.arg_string, ",p=");
440 strcat(tx.arg_string, hexpld);
444 //////////////////////////////////////////////////////////////////////////
446 // Initialize MAC and IP Addresses.
448 // - tx.eth_src = own interface MAC
449 // - tx.ip_src = own interface IP or user specified
450 // - tx.ip_dst = 255.255.255.255 or user specified (can be a range)
451 // - tx.ip_src_rand ... is set if needed.
454 // Get own device MAC address:
455 // Don't open context if only a help text is requested
456 if (getarg(tx.arg_string,"help", NULL)!=1) {
457 l = libnet_init (LIBNET_LINK_ADV, tx.device, err_buf );
458 if (l == NULL) {
459 fprintf(stderr, " mz/getopts: libnet_init() failed (%s)", err_buf);
460 return -1;
462 mymac = libnet_get_hwaddr(l);
463 for (i=0; i<6; i++) {
464 tx.eth_src[i] = mymac->ether_addr_octet[i];
465 tx.eth_mac_own[i] = mymac->ether_addr_octet[i];
468 // Set source IP address:
469 if (strlen(tx.ip_src_txt)) { // option -A has been specified
470 if (mz_strcmp(tx.ip_src_txt, "bcast", 2)==0) {
471 tx.ip_src = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
472 } else if (strcmp(tx.ip_src_txt, "rand") == 0) {
473 tx.ip_src_rand = 1;
474 tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0
476 else if (get_ip_range_src(tx.ip_src_txt)) { // returns 1 when no range has been specified
477 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
478 if (ipv6_mode)
479 tx.ip6_src = libnet_name2addr6 (l, tx.ip_src_txt, LIBNET_RESOLVE);
480 else
481 tx.ip_src = libnet_name2addr4 (l, tx.ip_src_txt, LIBNET_RESOLVE);
484 else { // no source IP specified: by default use own IP address
485 if (ipv6_mode) {
486 tx.ip6_src = libnet_get_ipaddr6(l);
487 if (strncmp((char*)&tx.ip6_src,(char*)&in6addr_error,sizeof(in6addr_error))==0)
488 printf("Failed to set source IPv6 address: %s", l->err_buf);
490 else
491 tx.ip_src = libnet_get_ipaddr4(l);
494 // Set destination IP address:
495 if (strlen(tx.ip_dst_txt)) { // option -B has been specified
496 if (mz_strcmp(tx.ip_dst_txt, "rand", 2)==0) {
497 fprintf(stderr, "Option -B does not support random destination IP addresses currently.\n");
498 return 1;
501 if (mz_strcmp(tx.ip_dst_txt, "bcast", 2)==0) {
502 tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
503 } else if (get_ip_range_dst(tx.ip_dst_txt)) { // returns 1 when no range has been specified
504 // name2addr4 accepts a DOTTED DECIMAL ADDRESS or a FQDN:
505 if (ipv6_mode)
506 tx.ip6_dst = libnet_name2addr6 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
507 else
508 tx.ip_dst = libnet_name2addr4 (l, tx.ip_dst_txt, LIBNET_RESOLVE);
511 else { // no destination IP specified: by default use broadcast
512 tx.ip_dst = libnet_name2addr4 (l, "255.255.255.255", LIBNET_DONT_RESOLVE);
515 // Initialize tx.ip_src_h and tx.ip_dst_h which are used by 'print_frame_details()'
516 // in verbose mode. See 'modifications.c'.
518 if (tx.ip_src_rand) { // ip_src_h already given, convert to ip_src
519 dum1 = (unsigned char*) &tx.ip_src_h;
520 dum2 = (unsigned char*) &tx.ip_src;
522 else { // ip_src already given, convert to ip_src_h
523 dum1 = (unsigned char*) &tx.ip_src;
524 dum2 = (unsigned char*) &tx.ip_src_h;
527 *dum2 = *(dum1+3);
528 dum2++;
529 *dum2 = *(dum1+2);
530 dum2++;
531 *dum2 = *(dum1+1);
532 dum2++;
533 *dum2 = *dum1;
535 dum1 = (unsigned char*) &tx.ip_dst;
536 dum2 = (unsigned char*) &tx.ip_dst_h;
538 *dum2 = *(dum1+3);
539 dum2++;
540 *dum2 = *(dum1+2);
541 dum2++;
542 *dum2 = *(dum1+1);
543 dum2++;
544 *dum2 = *dum1;
546 libnet_destroy(l);
550 // END OF ADDRESS INITIALIZATION
552 //////////////////////////////////////////////////////////////////////////
555 ////// retrieve interface parameters ///////
557 for (i=0; i<device_list_entries; i++) {
558 get_dev_params(device_list[i].dev);
562 //////////////////////////////////////////////////////////////////////////
564 // Mausezahn CLI desired?
565 if (mz_port) {
566 // has port number been specified?
567 if (strlen(tx.arg_string)) {
568 mz_port = (int) str2int (tx.arg_string);
571 if (!quiet) {
572 fprintf(stderr, "Mausezahn accepts incoming Telnet connections on port %i.\n", mz_port);
575 mz_cli_init();
576 cli();
579 //////////////////////////////////////////////////////////////////////////
581 // Mode decision
583 // Consider -t and -m option (used exclusively)
584 // -t => special packet types, stateless
586 // If -t not present then evaluate arg_string which must
587 // contain a byte-string in hexadecimal notation.
591 // ***** NEW: MOPS TRANSITION STRATEGY *****
592 if (mops_type != NULL) {
594 if (mz_strcmp(mops_type,"lldp",4)==0) {
595 mops_direct(tx.device, MOPS_LLDP, tx.arg_string);
600 if (packet_type == NULL) { // raw hex string given
601 mode = BYTE_STREAM;
603 else if (strcmp(packet_type,"arp")==0) {
604 mode = ARP;
606 else if (strcmp(packet_type,"bpdu")==0) {
607 mode = BPDU;
609 else if (strcmp(packet_type,"ip")==0) {
610 mode = IP;
612 else if (strcmp(packet_type,"udp")==0) {
613 mode = UDP;
615 else if (strcmp(packet_type,"icmp")==0) {
616 mode = ICMP;
618 else if (strcmp(packet_type,"icmp6")==0) {
619 mode = ICMP6;
621 else if (strcmp(packet_type,"tcp")==0) {
622 mode = TCP;
624 else if (strcmp(packet_type,"dns")==0) {
625 mode = DNS;
627 else if (strcmp(packet_type,"cdp")==0) {
628 mode = CDP;
630 else if (strcmp(packet_type,"syslog")==0) {
631 mode = SYSLOG;
633 else if (strcmp(packet_type,"lldp")==0) {
634 mode = LLDP;
635 tx.packet_mode=0; // create whole frame by ourself
637 else if (strcmp(packet_type,"rtp")==0) {
638 if (RX) {
639 mode = RX_RTP;
641 else {
642 mode = RTP;
643 if (!count_set) tx.count = 0;
644 if (!delay_set) tx.delay = 20000; // 20 msec inter-packet delay for RTP
647 else if (strcmp(packet_type,"help")==0) {
648 fprintf(stderr, "\n"
649 MAUSEZAHN_VERSION
650 "\n"
651 "| The following packet types are currently implemented:\n"
652 "|\n"
653 "| arp ... sends ARP packets\n"
654 "| bpdu ... sends BPDU packets (STP or PVST+)\n"
655 "| cdp ... sends CDP messages\n"
656 "| ip ... sends IPv4 packets\n"
657 "| udp ... sends UDP datagrams\n"
658 "| tcp ... sends TCP segments\n"
659 "| icmp ... sends ICMP messages\n"
660 "| dns ... sends DNS messages\n"
661 "| rtp ... sends RTP datagrams\n"
662 "| syslog ... sends Syslog messages\n"
663 "|\n"
664 "| Of course you can build any other packet type 'manually' using the direct layer 2 mode.\n"
665 "| FYI: The interactive mode supports additional protocols. (Try mz -x <port>)\n"
666 "\n"
668 exit(1);
670 else {
671 fprintf(stderr, " mz: you must specify a valid packet type!\n");
675 //////////////////////////////////////////////////////////////////////////
677 // TODO: Implement macro support
678 // Check macro types here
680 return 0;