197903da2202008733f50e69997029d7a5cfffcb8mreed/******************************************************************************/
297903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
397903da2202008733f50e69997029d7a5cfffcb8mreed/*   Copyright (c) International Business Machines  Corp., 2006               */
497903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
597903da2202008733f50e69997029d7a5cfffcb8mreed/*   This program is free software;  you can redistribute it and/or modify    */
697903da2202008733f50e69997029d7a5cfffcb8mreed/*   it under the terms of the GNU General Public License as published by     */
797903da2202008733f50e69997029d7a5cfffcb8mreed/*   the Free Software Foundation; either version 2 of the License, or        */
897903da2202008733f50e69997029d7a5cfffcb8mreed/*   (at your option) any later version.                                      */
997903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
1097903da2202008733f50e69997029d7a5cfffcb8mreed/*   This program is distributed in the hope that it will be useful,          */
1197903da2202008733f50e69997029d7a5cfffcb8mreed/*   but WITHOUT ANY WARRANTY;  without even the implied warranty of          */
1297903da2202008733f50e69997029d7a5cfffcb8mreed/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                */
1397903da2202008733f50e69997029d7a5cfffcb8mreed/*   the GNU General Public License for more details.                         */
1497903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
1597903da2202008733f50e69997029d7a5cfffcb8mreed/*   You should have received a copy of the GNU General Public License        */
1697903da2202008733f50e69997029d7a5cfffcb8mreed/*   along with this program;  if not, write to the Free Software             */
174548c6cf9bcdd96d8303caa4130ab638b61f8a30Wanlong Gao/*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  */
1897903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
1997903da2202008733f50e69997029d7a5cfffcb8mreed/******************************************************************************/
2097903da2202008733f50e69997029d7a5cfffcb8mreed
2197903da2202008733f50e69997029d7a5cfffcb8mreed/*
2297903da2202008733f50e69997029d7a5cfffcb8mreed * File:
2397903da2202008733f50e69997029d7a5cfffcb8mreed *	ns-icmpv4_sender.c
2497903da2202008733f50e69997029d7a5cfffcb8mreed *
2597903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
2697903da2202008733f50e69997029d7a5cfffcb8mreed *	This is ICMPv4 echo request sender.
2797903da2202008733f50e69997029d7a5cfffcb8mreed *	This utility is also able to set illegal information in the IP header
2897903da2202008733f50e69997029d7a5cfffcb8mreed *
2997903da2202008733f50e69997029d7a5cfffcb8mreed * Author:
3097903da2202008733f50e69997029d7a5cfffcb8mreed *	Mitsuru Chinen <mitch@jp.ibm.com>
3197903da2202008733f50e69997029d7a5cfffcb8mreed *
3297903da2202008733f50e69997029d7a5cfffcb8mreed * History:
3397903da2202008733f50e69997029d7a5cfffcb8mreed *	Mar 5 2006 - Created (Mitsuru Chinen)
3497903da2202008733f50e69997029d7a5cfffcb8mreed *---------------------------------------------------------------------------*/
3597903da2202008733f50e69997029d7a5cfffcb8mreed
3697903da2202008733f50e69997029d7a5cfffcb8mreed/*
3797903da2202008733f50e69997029d7a5cfffcb8mreed * Header Files
3897903da2202008733f50e69997029d7a5cfffcb8mreed */
3997903da2202008733f50e69997029d7a5cfffcb8mreed#include <stdio.h>
4097903da2202008733f50e69997029d7a5cfffcb8mreed#include <stdlib.h>
4197903da2202008733f50e69997029d7a5cfffcb8mreed#include <string.h>
4297903da2202008733f50e69997029d7a5cfffcb8mreed#include <errno.h>
4397903da2202008733f50e69997029d7a5cfffcb8mreed#include <netdb.h>
4497903da2202008733f50e69997029d7a5cfffcb8mreed#include <signal.h>
4597903da2202008733f50e69997029d7a5cfffcb8mreed#include <time.h>
4697903da2202008733f50e69997029d7a5cfffcb8mreed#include <unistd.h>
4797903da2202008733f50e69997029d7a5cfffcb8mreed#include <sys/ioctl.h>
4897903da2202008733f50e69997029d7a5cfffcb8mreed#include <sys/socket.h>
4997903da2202008733f50e69997029d7a5cfffcb8mreed#include <arpa/inet.h>
5097903da2202008733f50e69997029d7a5cfffcb8mreed#include <net/ethernet.h>
5197903da2202008733f50e69997029d7a5cfffcb8mreed#include <net/if_arp.h>
5297903da2202008733f50e69997029d7a5cfffcb8mreed
5397903da2202008733f50e69997029d7a5cfffcb8mreed#include "ns-traffic.h"
5497903da2202008733f50e69997029d7a5cfffcb8mreed
5597903da2202008733f50e69997029d7a5cfffcb8mreed/*
5697903da2202008733f50e69997029d7a5cfffcb8mreed * Structure Definitions
5797903da2202008733f50e69997029d7a5cfffcb8mreed */
5897903da2202008733f50e69997029d7a5cfffcb8mreedstruct icmpv4_fake {
59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct ip4_datagram pkt;
60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *src_ifname;
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sockaddr_ll saddr_ll;
62354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sockaddr_ll daddr_ll;
63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct in_addr saddr;
64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct in_addr daddr;
65354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned short int pkt_size;
66354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned short int data_size;
67354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	double timeout;
68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
69354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	u_int16_t fake_flag;
7097903da2202008733f50e69997029d7a5cfffcb8mreed};
7197903da2202008733f50e69997029d7a5cfffcb8mreed
7297903da2202008733f50e69997029d7a5cfffcb8mreed/*
7397903da2202008733f50e69997029d7a5cfffcb8mreed * Gloval variables
7497903da2202008733f50e69997029d7a5cfffcb8mreed */
7597903da2202008733f50e69997029d7a5cfffcb8mreedchar *program_name;		/* program name */
7697903da2202008733f50e69997029d7a5cfffcb8mreedstruct sigaction handler;	/* Behavior for a signal */
7797903da2202008733f50e69997029d7a5cfffcb8mreedint catch_sighup;		/* When catch the SIGHUP, set to non-zero */
7897903da2202008733f50e69997029d7a5cfffcb8mreed
7997903da2202008733f50e69997029d7a5cfffcb8mreed/*
8097903da2202008733f50e69997029d7a5cfffcb8mreed * Function: usage()
8197903da2202008733f50e69997029d7a5cfffcb8mreed *
8297903da2202008733f50e69997029d7a5cfffcb8mreed * Descripton:
8397903da2202008733f50e69997029d7a5cfffcb8mreed *  Print the usage of this program. Then, terminate this program with
8497903da2202008733f50e69997029d7a5cfffcb8mreed *  the specified exit value.
8597903da2202008733f50e69997029d7a5cfffcb8mreed *
8697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
8797903da2202008733f50e69997029d7a5cfffcb8mreed *  exit_value:	exit value
8897903da2202008733f50e69997029d7a5cfffcb8mreed *
8997903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
9097903da2202008733f50e69997029d7a5cfffcb8mreed *  This function does not return.
9197903da2202008733f50e69997029d7a5cfffcb8mreed */
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid usage(char *program_name, int exit_value)
9397903da2202008733f50e69997029d7a5cfffcb8mreed{
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	FILE *stream = stdout;	/* stream where the usage is output */
95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (exit_value == EXIT_FAILURE)
97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		stream = stderr;
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fprintf(stream, "%s [OPTION]\n"
100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-I if_name\tInterface name of the source host\n"
101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-S ip_addr\tIPv4 address of the source host\n"
102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-M mac_addr\tMAC address of the destination host\n"
103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-D ip_addr\tIPv4 address of the destination host\n"
104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-s packetsize\tnumber of data bytes (exclude header)\n"
105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-t value\ttimeout [sec]\n"
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-d\t\tdisplay debug informations\n"
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-h\t\tdisplay this usage\n"
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\n"
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t[options for fake]\n"
110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -c\tbreak checksum\n"
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -f\tbreak fragment information\n"
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -i\tbreak IPv4 destination address\n"
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -l\tbreak header length\n"
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -L\tbreak total length\n"
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -p\tbreak protocol number\n"
116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t  -v\tbreak IP version\n", program_name);
117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	exit(exit_value);
11897903da2202008733f50e69997029d7a5cfffcb8mreed}
11997903da2202008733f50e69997029d7a5cfffcb8mreed
12097903da2202008733f50e69997029d7a5cfffcb8mreed/*
12197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: set_signal_flag()
12297903da2202008733f50e69997029d7a5cfffcb8mreed *
12397903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
12497903da2202008733f50e69997029d7a5cfffcb8mreed *  This function sets global variables accordig to signal
12597903da2202008733f50e69997029d7a5cfffcb8mreed *
12697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
12797903da2202008733f50e69997029d7a5cfffcb8mreed *  type: type of signal
12897903da2202008733f50e69997029d7a5cfffcb8mreed *
12997903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
13097903da2202008733f50e69997029d7a5cfffcb8mreed *  None
13197903da2202008733f50e69997029d7a5cfffcb8mreed */
132354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid set_signal_flag(int type)
13397903da2202008733f50e69997029d7a5cfffcb8mreed{
134354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (debug)
135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Catch signal. type is %d\n", type);
13697903da2202008733f50e69997029d7a5cfffcb8mreed
137354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	switch (type) {
13897903da2202008733f50e69997029d7a5cfffcb8mreed	case SIGHUP:
139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		catch_sighup = 1;
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		handler.sa_handler = SIG_IGN;
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (sigaction(type, &handler, NULL) < 0)
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fatal_error("sigaction()");
143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		break;
14497903da2202008733f50e69997029d7a5cfffcb8mreed
14597903da2202008733f50e69997029d7a5cfffcb8mreed	default:
146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Unexpected signal (%d) is caught\n", type);
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(EXIT_FAILURE);
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
14997903da2202008733f50e69997029d7a5cfffcb8mreed}
15097903da2202008733f50e69997029d7a5cfffcb8mreed
15197903da2202008733f50e69997029d7a5cfffcb8mreed/*
15297903da2202008733f50e69997029d7a5cfffcb8mreed * Function: parse_options()
15397903da2202008733f50e69997029d7a5cfffcb8mreed *
15497903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
15597903da2202008733f50e69997029d7a5cfffcb8mreed *  This function parse the options, then modify the fake icmp data
15697903da2202008733f50e69997029d7a5cfffcb8mreed *
15797903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
15897903da2202008733f50e69997029d7a5cfffcb8mreed *   argc:  the number of argument
15997903da2202008733f50e69997029d7a5cfffcb8mreed *   argv:  arguments
16097903da2202008733f50e69997029d7a5cfffcb8mreed *  fake_p: pointer to data of fake icmp data to modify
16197903da2202008733f50e69997029d7a5cfffcb8mreed *
16297903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
16397903da2202008733f50e69997029d7a5cfffcb8mreed *  None
16497903da2202008733f50e69997029d7a5cfffcb8mreed */
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid parse_options(int argc, char *argv[], struct icmpv4_fake *fake_p)
16697903da2202008733f50e69997029d7a5cfffcb8mreed{
167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int optc;		/* option */
168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned long opt_ul;	/* option value in unsigned long */
169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	double opt_d;		/* option value in double */
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct in_addr opt_addr;	/* option value in struct in_addr */
171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sockaddr_ll opt_addr_ll;	/* option value in struct sockaddr_ll */
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int is_specified_src_ifname = 0;
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int is_specified_saddr = 0;
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int is_specified_daddr_ll = 0;
175354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int is_specified_daddr = 0;
176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
177354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while ((optc = getopt(argc, argv, "I:S:M:D:s:t:dhcfilLpv")) != EOF) {
178354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		switch (optc) {
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'I':
180354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->src_ifname = strdup(optarg);
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (fake_p->src_ifname == NULL)
182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fatal_error("strdup() failed.");
183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			is_specified_src_ifname = 1;
184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
185354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'S':
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (inet_pton(AF_INET, optarg, &opt_addr) <= 0) {
188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Source address is wrong\n");
189354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				usage(program_name, EXIT_FAILURE);
190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
191354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->saddr = opt_addr;
192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			is_specified_saddr = 1;
193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'M':
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (eth_pton(AF_INET, optarg, &opt_addr_ll)) {
197354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr,
198354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					"Destination MAC address is wrong\n");
199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				usage(program_name, EXIT_FAILURE);
200354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->daddr_ll = opt_addr_ll;
202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			is_specified_daddr_ll = 1;
203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
204354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
205354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'D':
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (inet_pton(AF_INET, optarg, &opt_addr) <= 0) {
207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr,
208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					"Destination address is wrong\n");
209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				usage(program_name, EXIT_FAILURE);
210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->daddr = opt_addr;
212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			is_specified_daddr = 1;
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 's':
216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			opt_ul = strtoul(optarg, NULL, 0);
217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (opt_ul > ICMPV4_DATA_MAXSIZE) {
218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr,
219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					"Data size sholud be less than %d\n",
220354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					ICMPV4_DATA_MAXSIZE + 1);
221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				usage(program_name, EXIT_FAILURE);
222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->data_size = opt_ul;
224354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
225354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
226354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 't':
227354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			opt_d = strtod(optarg, NULL);
228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (opt_d < 0.0) {
229354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr,
230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					"Timeout should be positive value\n");
231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				usage(program_name, EXIT_FAILURE);
232354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
233354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->timeout = opt_d;
234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
23597903da2202008733f50e69997029d7a5cfffcb8mreed
236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'd':
237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			debug = 1;
238354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
23997903da2202008733f50e69997029d7a5cfffcb8mreed
240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'h':
241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			usage(program_name, EXIT_SUCCESS);
242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
24397903da2202008733f50e69997029d7a5cfffcb8mreed
244354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			/* Options for fake */
245354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'c':
246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_CHECK;
247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
24897903da2202008733f50e69997029d7a5cfffcb8mreed
249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'f':
250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_FRAGMENT;
251354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
25297903da2202008733f50e69997029d7a5cfffcb8mreed
253354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'i':
254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_DADDR;
255354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
25697903da2202008733f50e69997029d7a5cfffcb8mreed
257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'l':
258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_IHL;
259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
26097903da2202008733f50e69997029d7a5cfffcb8mreed
261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'L':
262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_TOT_LEN;
263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
26497903da2202008733f50e69997029d7a5cfffcb8mreed
265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'p':
266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_PROTOCOL;
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
26897903da2202008733f50e69997029d7a5cfffcb8mreed
269354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'v':
270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fake_p->fake_flag |= FAKE_VERSION;
271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
27297903da2202008733f50e69997029d7a5cfffcb8mreed
273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		default:
274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			usage(program_name, EXIT_FAILURE);
275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
27797903da2202008733f50e69997029d7a5cfffcb8mreed
278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!is_specified_src_ifname) {
279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr,
280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			"Interface name of the source host is not specified\n");
281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage(program_name, EXIT_FAILURE);
282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
28397903da2202008733f50e69997029d7a5cfffcb8mreed
284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!is_specified_saddr) {
285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Source IP address is not specified\n");
286354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage(program_name, EXIT_FAILURE);
287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
28897903da2202008733f50e69997029d7a5cfffcb8mreed
289354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!is_specified_daddr_ll) {
290354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Destination MAC address is not specified\n");
291354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage(program_name, EXIT_FAILURE);
292354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
29397903da2202008733f50e69997029d7a5cfffcb8mreed
294354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!is_specified_daddr) {
295354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Destination IP address is not specified\n");
29697903da2202008733f50e69997029d7a5cfffcb8mreed		usage(program_name, EXIT_FAILURE);
29797903da2202008733f50e69997029d7a5cfffcb8mreed	}
29897903da2202008733f50e69997029d7a5cfffcb8mreed}
29997903da2202008733f50e69997029d7a5cfffcb8mreed
30097903da2202008733f50e69997029d7a5cfffcb8mreed/*
30197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: complete_eth_addrs()
30297903da2202008733f50e69997029d7a5cfffcb8mreed *
30397903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
30497903da2202008733f50e69997029d7a5cfffcb8mreed *  This function sets the source and destination ethernet address completely
30597903da2202008733f50e69997029d7a5cfffcb8mreed *
30697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
30797903da2202008733f50e69997029d7a5cfffcb8mreed *  fake_p: pointer to data of fake icmp structure
30897903da2202008733f50e69997029d7a5cfffcb8mreed *
30997903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
31097903da2202008733f50e69997029d7a5cfffcb8mreed *  None
31197903da2202008733f50e69997029d7a5cfffcb8mreed *
31297903da2202008733f50e69997029d7a5cfffcb8mreed */
313354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid complete_eth_addrs(struct icmpv4_fake *fake_p)
31497903da2202008733f50e69997029d7a5cfffcb8mreed{
315354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int sock_fd;		/* Socket for ioctl() */
316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct ifreq ifinfo;	/* Interface information */
31797903da2202008733f50e69997029d7a5cfffcb8mreed
318354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if ((sock_fd = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0)
319354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("socket()");
32097903da2202008733f50e69997029d7a5cfffcb8mreed
321354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Source */
322354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->saddr_ll.sll_family = AF_PACKET;	/* Always AF_PACKET */
323354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->saddr_ll.sll_protocol = htons(ETH_P_IP);	/* IPv4 */
324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->saddr_ll.sll_hatype = ARPHRD_ETHER;	/* Header type */
325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->saddr_ll.sll_pkttype = PACKET_HOST;	/* Packet type */
326354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->saddr_ll.sll_halen = ETH_ALEN;	/* Length of address */
32797903da2202008733f50e69997029d7a5cfffcb8mreed
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Get the MAC address of the interface at source host */
329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	get_ifinfo(&ifinfo, sock_fd, fake_p->src_ifname, SIOCGIFHWADDR);
330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memcpy(fake_p->saddr_ll.sll_addr, ifinfo.ifr_hwaddr.sa_data, ETH_ALEN);
33197903da2202008733f50e69997029d7a5cfffcb8mreed
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Get the interface index */
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	get_ifinfo(&ifinfo, sock_fd, fake_p->src_ifname, SIOCGIFINDEX);
334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->saddr_ll.sll_ifindex = ifinfo.ifr_ifindex;
335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->daddr_ll.sll_ifindex = ifinfo.ifr_ifindex;
33697903da2202008733f50e69997029d7a5cfffcb8mreed
337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	close(sock_fd);
33897903da2202008733f50e69997029d7a5cfffcb8mreed}
33997903da2202008733f50e69997029d7a5cfffcb8mreed
34097903da2202008733f50e69997029d7a5cfffcb8mreed/*
34197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: create_clean_packet()
34297903da2202008733f50e69997029d7a5cfffcb8mreed *
34397903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
34497903da2202008733f50e69997029d7a5cfffcb8mreed *  This function creates icmpv4 packet without any fakes
34597903da2202008733f50e69997029d7a5cfffcb8mreed *
34697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
34797903da2202008733f50e69997029d7a5cfffcb8mreed *  fake_p: pointer to data of fake icmp structure
34897903da2202008733f50e69997029d7a5cfffcb8mreed *
34997903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
35097903da2202008733f50e69997029d7a5cfffcb8mreed *  None
35197903da2202008733f50e69997029d7a5cfffcb8mreed */
352354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid create_clean_packet(struct icmpv4_fake *fake_p)
35397903da2202008733f50e69997029d7a5cfffcb8mreed{
354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct ip4_datagram pkt;	/* sending IPv4 packet */
355354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct icmp4_segment *icmp_p;	/* ICMPv4 part of sending packet */
356354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned short int pkt_size;
357354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
358354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset(&pkt, '\0', sizeof(struct ip4_datagram));
359354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt_size = sizeof(struct iphdr)	/* IP header */
360354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    +sizeof(struct icmphdr)	/* ICMP header */
361354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    +fake_p->data_size;	/* ICMP payload */
362354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
363354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p = (struct icmp4_segment *)&(pkt.payload);
364354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
365354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* IPv4 Header */
366354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.version = 4;
367354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.ihl = sizeof(struct iphdr) / 4;
368354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.tos = 0;
369354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.tot_len = htons(pkt_size);
370354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.id = htons(IPV4_PACKET_ID);
371354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.frag_off = htons(IPV4_DEFAULT_FLAG);
372354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.ttl = IPV4_DEFAULT_TTL;
373354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.protocol = IPPROTO_ICMP;
374354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.check = 0;	/* Calculate later */
375354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.saddr = fake_p->saddr.s_addr;
376354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.daddr = fake_p->daddr.s_addr;
377354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
378354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* ICMPv4 Header */
379354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p->hdr.type = ICMP_ECHO;
380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p->hdr.code = 0;
381354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p->hdr.checksum = 0;	/* Calculate later */
382354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p->hdr.un.echo.id = htons(ICMP_ECHO_ID);
383354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p->hdr.un.echo.sequence = htons(1);
384354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
385354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* ICMPv4 Payload */
386354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fill_payload(icmp_p->data, fake_p->data_size);
387354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
388354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Calcualte checksums */
389354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt.hdr.check = calc_checksum((u_int16_t *) (&pkt.hdr),
390354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				      sizeof(struct iphdr));
391354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	icmp_p->hdr.checksum = calc_checksum((u_int16_t *) icmp_p,
392354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					     sizeof(struct icmphdr) +
393354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					     fake_p->data_size);
394354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
395354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Store the clean packet data */
396354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->pkt = pkt;
397354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fake_p->pkt_size = pkt_size;
39897903da2202008733f50e69997029d7a5cfffcb8mreed}
39997903da2202008733f50e69997029d7a5cfffcb8mreed
40097903da2202008733f50e69997029d7a5cfffcb8mreed/*
40197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: thrust_fakes()
40297903da2202008733f50e69997029d7a5cfffcb8mreed *
40397903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
40497903da2202008733f50e69997029d7a5cfffcb8mreed *  This function thrust fake information to the icmp packet
40597903da2202008733f50e69997029d7a5cfffcb8mreed *
40697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
40797903da2202008733f50e69997029d7a5cfffcb8mreed *     pkt   : Payload of the Ethernet frame (Namely, IPv6 packet
40897903da2202008733f50e69997029d7a5cfffcb8mreed *  fake_flag: Flag which represents what information would be faked
40997903da2202008733f50e69997029d7a5cfffcb8mreed *
41097903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
41197903da2202008733f50e69997029d7a5cfffcb8mreed *  None
41297903da2202008733f50e69997029d7a5cfffcb8mreed */
413354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid thrust_fakes(struct ip4_datagram *pkt, u_int16_t fake_flag)
41497903da2202008733f50e69997029d7a5cfffcb8mreed{
415354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int rand_val;
416354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	size_t bitsize;
417354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	u_int32_t seed;
418354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
419354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (debug)
420354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "fake_flag = %2x\n", fake_flag);
421354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
422354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_VERSION) {	/* version */
423354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bitsize = 4;
424354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		seed = bit_change_seed(bitsize, 1);
425354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pkt->hdr.version ^= seed;
42697903da2202008733f50e69997029d7a5cfffcb8mreed	}
42797903da2202008733f50e69997029d7a5cfffcb8mreed
428354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_IHL) {	/* header length */
429354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bitsize = 4;
430354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		seed = bit_change_seed(bitsize, 1);
431354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pkt->hdr.ihl ^= seed;
43297903da2202008733f50e69997029d7a5cfffcb8mreed	}
43397903da2202008733f50e69997029d7a5cfffcb8mreed
434354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_TOT_LEN) {	/* total length */
435354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bitsize = sizeof(pkt->hdr.tot_len) * 8;
436354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		seed = bit_change_seed(bitsize, bitsize / 8);
437354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pkt->hdr.tot_len ^= seed;
43897903da2202008733f50e69997029d7a5cfffcb8mreed	}
43997903da2202008733f50e69997029d7a5cfffcb8mreed
440354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_FRAGMENT) {	/* fragment information */
441354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Set reserved flag */
442354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		rand_val = rand() / ((RAND_MAX + 1U) / 16);
443354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!rand_val) {
444354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
445354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Up reserved bit\n");
446354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pkt->hdr.frag_off |= htonl(0x80000000);
447354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
448354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
449354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Set more fragments flag */
450354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		rand_val = rand() / ((RAND_MAX + 1U) / 3);
451354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!rand_val) {
452354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
453354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Set more fragments flag\n");
454354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pkt->hdr.frag_off |= htons(0x2000);
455354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
456354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
457354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Unset unfragmented flag */
458354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		rand_val = rand() / ((RAND_MAX + 1U) / 3);
459354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!rand_val) {
460354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
461354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Unset unfragmented flag\n");
462354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pkt->hdr.frag_off &= htons(0xbfff);
463354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
464354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
465354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Set fragment offset */
466354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		rand_val = rand() / ((RAND_MAX + 1U) / 3);
467354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!rand_val) {
468354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bitsize = 13;
469354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			seed = bit_change_seed(bitsize, 0);
470354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
471354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Set fragment offset %02x\n",
472354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					seed);
473354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pkt->hdr.frag_off |= htons(seed);
474354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
47597903da2202008733f50e69997029d7a5cfffcb8mreed	}
47697903da2202008733f50e69997029d7a5cfffcb8mreed
477354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_PROTOCOL) {	/* protocol */
478354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		rand_val = rand() / ((RAND_MAX + 1U) / 5);
479354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		switch (rand_val) {
480354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 1:
481354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 2:
482354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
483354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Bit reverse\n");
484354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bitsize = sizeof(pkt->hdr.protocol) * 8;
485354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			seed = bit_change_seed(bitsize, 0);
486354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pkt->hdr.protocol ^= seed;
487354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
488354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
489354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 3:
490354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 4:
491354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
492354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Unknown Protocol\n");
493354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (rand_val) {
494354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				int number;
495354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				int counter;
496354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				for (counter = 0; counter <= 0xff; counter++) {
497354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					number =
498354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					    rand() / ((RAND_MAX + 1U) / 0x100);
499354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					if (getprotobynumber(number) == NULL) {
500354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						pkt->hdr.protocol = number;
501354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						break;
502354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					}
503354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				}
50497903da2202008733f50e69997029d7a5cfffcb8mreed			}
505354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
506354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
507354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		default:
508354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (debug)
509354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "Do nothing\n");
510354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
51197903da2202008733f50e69997029d7a5cfffcb8mreed		}
512354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
51397903da2202008733f50e69997029d7a5cfffcb8mreed
514354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_DADDR) {	/* destination address */
515354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bitsize = sizeof(pkt->hdr.daddr) * 8;
516354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		seed = bit_change_seed(bitsize, bitsize / 8);
517354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pkt->hdr.daddr ^= seed;
518354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
519354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
520354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Recalculate checksum once */
521354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt->hdr.check = 0;
522354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt->hdr.check =
523354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    calc_checksum((u_int16_t *) & (pkt->hdr), sizeof(struct iphdr));
524354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
525354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (fake_flag & FAKE_CHECK) {	/* checksum */
526354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bitsize = sizeof(pkt->hdr.check) * 8;
527354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		seed = bit_change_seed(bitsize, bitsize / 8);
528354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pkt->hdr.check ^= seed;
52997903da2202008733f50e69997029d7a5cfffcb8mreed	}
53097903da2202008733f50e69997029d7a5cfffcb8mreed}
53197903da2202008733f50e69997029d7a5cfffcb8mreed
53297903da2202008733f50e69997029d7a5cfffcb8mreed/*
53397903da2202008733f50e69997029d7a5cfffcb8mreed * Function: send_packet()
53497903da2202008733f50e69997029d7a5cfffcb8mreed *
53597903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
53697903da2202008733f50e69997029d7a5cfffcb8mreed *  This function sends icmpv4 packet
53797903da2202008733f50e69997029d7a5cfffcb8mreed *
53897903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
53997903da2202008733f50e69997029d7a5cfffcb8mreed *  fake_p: pointer to data of fake icmp structure
54097903da2202008733f50e69997029d7a5cfffcb8mreed *
54197903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
54297903da2202008733f50e69997029d7a5cfffcb8mreed *  None
54397903da2202008733f50e69997029d7a5cfffcb8mreed */
544354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid send_packets(struct icmpv4_fake *fake_p)
54597903da2202008733f50e69997029d7a5cfffcb8mreed{
546354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int sock_fd;
547354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int retval;
548354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct ip4_datagram pkt;
549354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	double start_time;
550354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
551354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Open a socket */
552354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sock_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
553354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sock_fd < 0)
554354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("socket()");
555354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
556354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Bind the socket to the physical address */
557354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	retval = bind(sock_fd, (struct sockaddr *)&(fake_p->saddr_ll),
558354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		      sizeof(struct sockaddr_ll));
55997903da2202008733f50e69997029d7a5cfffcb8mreed	if (retval < 0)
560354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("bind()");
561354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
562354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Set singal hander for SIGHUP */
563354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	handler.sa_handler = set_signal_flag;
564354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	handler.sa_flags = 0;
565354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sigfillset(&handler.sa_mask) < 0)
566354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("sigfillset()");
567354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sigaction(SIGHUP, &handler, NULL) < 0)
568354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("sigfillset()");
569354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
570354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/*
571354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 * loop for sending packets
572354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 */
573354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pkt = fake_p->pkt;
574354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	start_time = time(NULL);
575354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
576354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (;;) {
577354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (fake_p->fake_flag) {
578354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pkt = fake_p->pkt;
579354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			thrust_fakes(&pkt, fake_p->fake_flag);
580354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
58197903da2202008733f50e69997029d7a5cfffcb8mreed
582354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		retval = sendto(sock_fd, &pkt, fake_p->pkt_size, 0,
583354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				(struct sockaddr *)&(fake_p->daddr_ll),
584354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sizeof(struct sockaddr_ll));
585354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (retval < 0)
586354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fatal_error("sendto()");
587354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
588354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (fake_p->timeout)	/* timeout */
589354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (fake_p->timeout < difftime(time(NULL), start_time))
590354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				break;
59197903da2202008733f50e69997029d7a5cfffcb8mreed
592354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (catch_sighup)	/* catch SIGHUP */
593354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
594354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
59597903da2202008733f50e69997029d7a5cfffcb8mreed
596354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Close the socket */
597354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	close(sock_fd);
59897903da2202008733f50e69997029d7a5cfffcb8mreed}
59997903da2202008733f50e69997029d7a5cfffcb8mreed
60097903da2202008733f50e69997029d7a5cfffcb8mreed/*
60197903da2202008733f50e69997029d7a5cfffcb8mreed *
60297903da2202008733f50e69997029d7a5cfffcb8mreed *  Function: main()
60397903da2202008733f50e69997029d7a5cfffcb8mreed *
60497903da2202008733f50e69997029d7a5cfffcb8mreed */
605354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[])
60697903da2202008733f50e69997029d7a5cfffcb8mreed{
607354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct icmpv4_fake fake_data;
60897903da2202008733f50e69997029d7a5cfffcb8mreed
609354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	debug = 0;
610354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	program_name = strdup(argv[0]);
611354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	srand(getpid());
61297903da2202008733f50e69997029d7a5cfffcb8mreed
613354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset(&fake_data, '\0', sizeof(struct icmpv4_fake));
614354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	parse_options(argc, argv, &fake_data);
61597903da2202008733f50e69997029d7a5cfffcb8mreed
616354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	complete_eth_addrs(&fake_data);
617354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	create_clean_packet(&fake_data);
61897903da2202008733f50e69997029d7a5cfffcb8mreed
619354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	send_packets(&fake_data);
62097903da2202008733f50e69997029d7a5cfffcb8mreed
621354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	exit(EXIT_SUCCESS);
622ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
623