1f08c3bdfSopenharmony_ci/******************************************************************************/
2f08c3bdfSopenharmony_ci/*                                                                            */
3f08c3bdfSopenharmony_ci/*   Copyright (c) International Business Machines  Corp., 2006               */
4f08c3bdfSopenharmony_ci/*                                                                            */
5f08c3bdfSopenharmony_ci/*   This program is free software;  you can redistribute it and/or modify    */
6f08c3bdfSopenharmony_ci/*   it under the terms of the GNU General Public License as published by     */
7f08c3bdfSopenharmony_ci/*   the Free Software Foundation; either version 2 of the License, or        */
8f08c3bdfSopenharmony_ci/*   (at your option) any later version.                                      */
9f08c3bdfSopenharmony_ci/*                                                                            */
10f08c3bdfSopenharmony_ci/*   This program is distributed in the hope that it will be useful,          */
11f08c3bdfSopenharmony_ci/*   but WITHOUT ANY WARRANTY;  without even the implied warranty of          */
12f08c3bdfSopenharmony_ci/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                */
13f08c3bdfSopenharmony_ci/*   the GNU General Public License for more details.                         */
14f08c3bdfSopenharmony_ci/*                                                                            */
15f08c3bdfSopenharmony_ci/*   You should have received a copy of the GNU General Public License        */
16f08c3bdfSopenharmony_ci/*   along with this program;  if not, write to the Free Software             */
17f08c3bdfSopenharmony_ci/*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  */
18f08c3bdfSopenharmony_ci/*                                                                            */
19f08c3bdfSopenharmony_ci/******************************************************************************/
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci/*
22f08c3bdfSopenharmony_ci * File:
23f08c3bdfSopenharmony_ci *	ns-icmpv4_sender.c
24f08c3bdfSopenharmony_ci *
25f08c3bdfSopenharmony_ci * Description:
26f08c3bdfSopenharmony_ci *	This is ICMPv4 echo request sender.
27f08c3bdfSopenharmony_ci *	This utility is also able to set illegal information in the IP header
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci * Author:
30f08c3bdfSopenharmony_ci *	Mitsuru Chinen <mitch@jp.ibm.com>
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci * History:
33f08c3bdfSopenharmony_ci *	Mar 5 2006 - Created (Mitsuru Chinen)
34f08c3bdfSopenharmony_ci *---------------------------------------------------------------------------*/
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci/*
37f08c3bdfSopenharmony_ci * Header Files
38f08c3bdfSopenharmony_ci */
39f08c3bdfSopenharmony_ci#include <stdio.h>
40f08c3bdfSopenharmony_ci#include <stdlib.h>
41f08c3bdfSopenharmony_ci#include <string.h>
42f08c3bdfSopenharmony_ci#include <errno.h>
43f08c3bdfSopenharmony_ci#include <netdb.h>
44f08c3bdfSopenharmony_ci#include <signal.h>
45f08c3bdfSopenharmony_ci#include <time.h>
46f08c3bdfSopenharmony_ci#include <unistd.h>
47f08c3bdfSopenharmony_ci#include <sys/ioctl.h>
48f08c3bdfSopenharmony_ci#include <sys/socket.h>
49f08c3bdfSopenharmony_ci#include <arpa/inet.h>
50f08c3bdfSopenharmony_ci#include <net/ethernet.h>
51f08c3bdfSopenharmony_ci#include <net/if_arp.h>
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci#include "ns-traffic.h"
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci/*
56f08c3bdfSopenharmony_ci * Structure Definitions
57f08c3bdfSopenharmony_ci */
58f08c3bdfSopenharmony_cistruct icmpv4_fake {
59f08c3bdfSopenharmony_ci	struct ip4_datagram pkt;
60f08c3bdfSopenharmony_ci	char *src_ifname;
61f08c3bdfSopenharmony_ci	struct sockaddr_ll saddr_ll;
62f08c3bdfSopenharmony_ci	struct sockaddr_ll daddr_ll;
63f08c3bdfSopenharmony_ci	struct in_addr saddr;
64f08c3bdfSopenharmony_ci	struct in_addr daddr;
65f08c3bdfSopenharmony_ci	unsigned short int pkt_size;
66f08c3bdfSopenharmony_ci	unsigned short int data_size;
67f08c3bdfSopenharmony_ci	double timeout;
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	u_int16_t fake_flag;
70f08c3bdfSopenharmony_ci};
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci/*
73f08c3bdfSopenharmony_ci * Gloval variables
74f08c3bdfSopenharmony_ci */
75f08c3bdfSopenharmony_cichar *program_name;		/* program name */
76f08c3bdfSopenharmony_cistruct sigaction handler;	/* Behavior for a signal */
77f08c3bdfSopenharmony_ciint catch_sighup;		/* When catch the SIGHUP, set to non-zero */
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci/*
80f08c3bdfSopenharmony_ci * Function: usage()
81f08c3bdfSopenharmony_ci *
82f08c3bdfSopenharmony_ci * Descripton:
83f08c3bdfSopenharmony_ci *  Print the usage of this program. Then, terminate this program with
84f08c3bdfSopenharmony_ci *  the specified exit value.
85f08c3bdfSopenharmony_ci *
86f08c3bdfSopenharmony_ci * Argument:
87f08c3bdfSopenharmony_ci *  exit_value:	exit value
88f08c3bdfSopenharmony_ci *
89f08c3bdfSopenharmony_ci * Return value:
90f08c3bdfSopenharmony_ci *  This function does not return.
91f08c3bdfSopenharmony_ci */
92f08c3bdfSopenharmony_civoid usage(char *program_name, int exit_value)
93f08c3bdfSopenharmony_ci{
94f08c3bdfSopenharmony_ci	FILE *stream = stdout;	/* stream where the usage is output */
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	if (exit_value == EXIT_FAILURE)
97f08c3bdfSopenharmony_ci		stream = stderr;
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	fprintf(stream, "%s [OPTION]\n"
100f08c3bdfSopenharmony_ci		"\t-I if_name\tInterface name of the source host\n"
101f08c3bdfSopenharmony_ci		"\t-S ip_addr\tIPv4 address of the source host\n"
102f08c3bdfSopenharmony_ci		"\t-M mac_addr\tMAC address of the destination host\n"
103f08c3bdfSopenharmony_ci		"\t-D ip_addr\tIPv4 address of the destination host\n"
104f08c3bdfSopenharmony_ci		"\t-s packetsize\tnumber of data bytes (exclude header)\n"
105f08c3bdfSopenharmony_ci		"\t-t value\ttimeout [sec]\n"
106f08c3bdfSopenharmony_ci		"\t-d\t\tdisplay debug informations\n"
107f08c3bdfSopenharmony_ci		"\t-h\t\tdisplay this usage\n"
108f08c3bdfSopenharmony_ci		"\n"
109f08c3bdfSopenharmony_ci		"\t[options for fake]\n"
110f08c3bdfSopenharmony_ci		"\t  -c\tbreak checksum\n"
111f08c3bdfSopenharmony_ci		"\t  -f\tbreak fragment information\n"
112f08c3bdfSopenharmony_ci		"\t  -i\tbreak IPv4 destination address\n"
113f08c3bdfSopenharmony_ci		"\t  -l\tbreak header length\n"
114f08c3bdfSopenharmony_ci		"\t  -L\tbreak total length\n"
115f08c3bdfSopenharmony_ci		"\t  -p\tbreak protocol number\n"
116f08c3bdfSopenharmony_ci		"\t  -v\tbreak IP version\n", program_name);
117f08c3bdfSopenharmony_ci	exit(exit_value);
118f08c3bdfSopenharmony_ci}
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci/*
121f08c3bdfSopenharmony_ci * Function: set_signal_flag()
122f08c3bdfSopenharmony_ci *
123f08c3bdfSopenharmony_ci * Description:
124f08c3bdfSopenharmony_ci *  This function sets global variables accordig to signal
125f08c3bdfSopenharmony_ci *
126f08c3bdfSopenharmony_ci * Argument:
127f08c3bdfSopenharmony_ci *  type: type of signal
128f08c3bdfSopenharmony_ci *
129f08c3bdfSopenharmony_ci * Return value:
130f08c3bdfSopenharmony_ci *  None
131f08c3bdfSopenharmony_ci */
132f08c3bdfSopenharmony_civoid set_signal_flag(int type)
133f08c3bdfSopenharmony_ci{
134f08c3bdfSopenharmony_ci	if (debug)
135f08c3bdfSopenharmony_ci		fprintf(stderr, "Catch signal. type is %d\n", type);
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ci	switch (type) {
138f08c3bdfSopenharmony_ci	case SIGHUP:
139f08c3bdfSopenharmony_ci		catch_sighup = 1;
140f08c3bdfSopenharmony_ci		handler.sa_handler = SIG_IGN;
141f08c3bdfSopenharmony_ci		if (sigaction(type, &handler, NULL) < 0)
142f08c3bdfSopenharmony_ci			fatal_error("sigaction()");
143f08c3bdfSopenharmony_ci		break;
144f08c3bdfSopenharmony_ci
145f08c3bdfSopenharmony_ci	default:
146f08c3bdfSopenharmony_ci		fprintf(stderr, "Unexpected signal (%d) is caught\n", type);
147f08c3bdfSopenharmony_ci		exit(EXIT_FAILURE);
148f08c3bdfSopenharmony_ci	}
149f08c3bdfSopenharmony_ci}
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci/*
152f08c3bdfSopenharmony_ci * Function: parse_options()
153f08c3bdfSopenharmony_ci *
154f08c3bdfSopenharmony_ci * Description:
155f08c3bdfSopenharmony_ci *  This function parse the options, then modify the fake icmp data
156f08c3bdfSopenharmony_ci *
157f08c3bdfSopenharmony_ci * Argument:
158f08c3bdfSopenharmony_ci *   argc:  the number of argument
159f08c3bdfSopenharmony_ci *   argv:  arguments
160f08c3bdfSopenharmony_ci *  fake_p: pointer to data of fake icmp data to modify
161f08c3bdfSopenharmony_ci *
162f08c3bdfSopenharmony_ci * Return value:
163f08c3bdfSopenharmony_ci *  None
164f08c3bdfSopenharmony_ci */
165f08c3bdfSopenharmony_civoid parse_options(int argc, char *argv[], struct icmpv4_fake *fake_p)
166f08c3bdfSopenharmony_ci{
167f08c3bdfSopenharmony_ci	int optc;		/* option */
168f08c3bdfSopenharmony_ci	unsigned long opt_ul;	/* option value in unsigned long */
169f08c3bdfSopenharmony_ci	double opt_d;		/* option value in double */
170f08c3bdfSopenharmony_ci	struct in_addr opt_addr;	/* option value in struct in_addr */
171f08c3bdfSopenharmony_ci	struct sockaddr_ll opt_addr_ll;	/* option value in struct sockaddr_ll */
172f08c3bdfSopenharmony_ci	int is_specified_src_ifname = 0;
173f08c3bdfSopenharmony_ci	int is_specified_saddr = 0;
174f08c3bdfSopenharmony_ci	int is_specified_daddr_ll = 0;
175f08c3bdfSopenharmony_ci	int is_specified_daddr = 0;
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	while ((optc = getopt(argc, argv, "I:S:M:D:s:t:dhcfilLpv")) != EOF) {
178f08c3bdfSopenharmony_ci		switch (optc) {
179f08c3bdfSopenharmony_ci		case 'I':
180f08c3bdfSopenharmony_ci			fake_p->src_ifname = strdup(optarg);
181f08c3bdfSopenharmony_ci			if (fake_p->src_ifname == NULL)
182f08c3bdfSopenharmony_ci				fatal_error("strdup() failed.");
183f08c3bdfSopenharmony_ci			is_specified_src_ifname = 1;
184f08c3bdfSopenharmony_ci			break;
185f08c3bdfSopenharmony_ci
186f08c3bdfSopenharmony_ci		case 'S':
187f08c3bdfSopenharmony_ci			if (inet_pton(AF_INET, optarg, &opt_addr) <= 0) {
188f08c3bdfSopenharmony_ci				fprintf(stderr, "Source address is wrong\n");
189f08c3bdfSopenharmony_ci				usage(program_name, EXIT_FAILURE);
190f08c3bdfSopenharmony_ci			}
191f08c3bdfSopenharmony_ci			fake_p->saddr = opt_addr;
192f08c3bdfSopenharmony_ci			is_specified_saddr = 1;
193f08c3bdfSopenharmony_ci			break;
194f08c3bdfSopenharmony_ci
195f08c3bdfSopenharmony_ci		case 'M':
196f08c3bdfSopenharmony_ci			if (eth_pton(AF_INET, optarg, &opt_addr_ll)) {
197f08c3bdfSopenharmony_ci				fprintf(stderr,
198f08c3bdfSopenharmony_ci					"Destination MAC address is wrong\n");
199f08c3bdfSopenharmony_ci				usage(program_name, EXIT_FAILURE);
200f08c3bdfSopenharmony_ci			}
201f08c3bdfSopenharmony_ci			fake_p->daddr_ll = opt_addr_ll;
202f08c3bdfSopenharmony_ci			is_specified_daddr_ll = 1;
203f08c3bdfSopenharmony_ci			break;
204f08c3bdfSopenharmony_ci
205f08c3bdfSopenharmony_ci		case 'D':
206f08c3bdfSopenharmony_ci			if (inet_pton(AF_INET, optarg, &opt_addr) <= 0) {
207f08c3bdfSopenharmony_ci				fprintf(stderr,
208f08c3bdfSopenharmony_ci					"Destination address is wrong\n");
209f08c3bdfSopenharmony_ci				usage(program_name, EXIT_FAILURE);
210f08c3bdfSopenharmony_ci			}
211f08c3bdfSopenharmony_ci			fake_p->daddr = opt_addr;
212f08c3bdfSopenharmony_ci			is_specified_daddr = 1;
213f08c3bdfSopenharmony_ci			break;
214f08c3bdfSopenharmony_ci
215f08c3bdfSopenharmony_ci		case 's':
216f08c3bdfSopenharmony_ci			opt_ul = strtoul(optarg, NULL, 0);
217f08c3bdfSopenharmony_ci			if (opt_ul > ICMPV4_DATA_MAXSIZE) {
218f08c3bdfSopenharmony_ci				fprintf(stderr,
219f08c3bdfSopenharmony_ci					"Data size sholud be less than %d\n",
220f08c3bdfSopenharmony_ci					ICMPV4_DATA_MAXSIZE + 1);
221f08c3bdfSopenharmony_ci				usage(program_name, EXIT_FAILURE);
222f08c3bdfSopenharmony_ci			}
223f08c3bdfSopenharmony_ci			fake_p->data_size = opt_ul;
224f08c3bdfSopenharmony_ci			break;
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_ci		case 't':
227f08c3bdfSopenharmony_ci			opt_d = strtod(optarg, NULL);
228f08c3bdfSopenharmony_ci			if (opt_d < 0.0) {
229f08c3bdfSopenharmony_ci				fprintf(stderr,
230f08c3bdfSopenharmony_ci					"Timeout should be positive value\n");
231f08c3bdfSopenharmony_ci				usage(program_name, EXIT_FAILURE);
232f08c3bdfSopenharmony_ci			}
233f08c3bdfSopenharmony_ci			fake_p->timeout = opt_d;
234f08c3bdfSopenharmony_ci			break;
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci		case 'd':
237f08c3bdfSopenharmony_ci			debug = 1;
238f08c3bdfSopenharmony_ci			break;
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ci		case 'h':
241f08c3bdfSopenharmony_ci			usage(program_name, EXIT_SUCCESS);
242f08c3bdfSopenharmony_ci			break;
243f08c3bdfSopenharmony_ci
244f08c3bdfSopenharmony_ci			/* Options for fake */
245f08c3bdfSopenharmony_ci		case 'c':
246f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_CHECK;
247f08c3bdfSopenharmony_ci			break;
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ci		case 'f':
250f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_FRAGMENT;
251f08c3bdfSopenharmony_ci			break;
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_ci		case 'i':
254f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_DADDR;
255f08c3bdfSopenharmony_ci			break;
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_ci		case 'l':
258f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_IHL;
259f08c3bdfSopenharmony_ci			break;
260f08c3bdfSopenharmony_ci
261f08c3bdfSopenharmony_ci		case 'L':
262f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_TOT_LEN;
263f08c3bdfSopenharmony_ci			break;
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_ci		case 'p':
266f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_PROTOCOL;
267f08c3bdfSopenharmony_ci			break;
268f08c3bdfSopenharmony_ci
269f08c3bdfSopenharmony_ci		case 'v':
270f08c3bdfSopenharmony_ci			fake_p->fake_flag |= FAKE_VERSION;
271f08c3bdfSopenharmony_ci			break;
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_ci		default:
274f08c3bdfSopenharmony_ci			usage(program_name, EXIT_FAILURE);
275f08c3bdfSopenharmony_ci		}
276f08c3bdfSopenharmony_ci	}
277f08c3bdfSopenharmony_ci
278f08c3bdfSopenharmony_ci	if (!is_specified_src_ifname) {
279f08c3bdfSopenharmony_ci		fprintf(stderr,
280f08c3bdfSopenharmony_ci			"Interface name of the source host is not specified\n");
281f08c3bdfSopenharmony_ci		usage(program_name, EXIT_FAILURE);
282f08c3bdfSopenharmony_ci	}
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci	if (!is_specified_saddr) {
285f08c3bdfSopenharmony_ci		fprintf(stderr, "Source IP address is not specified\n");
286f08c3bdfSopenharmony_ci		usage(program_name, EXIT_FAILURE);
287f08c3bdfSopenharmony_ci	}
288f08c3bdfSopenharmony_ci
289f08c3bdfSopenharmony_ci	if (!is_specified_daddr_ll) {
290f08c3bdfSopenharmony_ci		fprintf(stderr, "Destination MAC address is not specified\n");
291f08c3bdfSopenharmony_ci		usage(program_name, EXIT_FAILURE);
292f08c3bdfSopenharmony_ci	}
293f08c3bdfSopenharmony_ci
294f08c3bdfSopenharmony_ci	if (!is_specified_daddr) {
295f08c3bdfSopenharmony_ci		fprintf(stderr, "Destination IP address is not specified\n");
296f08c3bdfSopenharmony_ci		usage(program_name, EXIT_FAILURE);
297f08c3bdfSopenharmony_ci	}
298f08c3bdfSopenharmony_ci}
299f08c3bdfSopenharmony_ci
300f08c3bdfSopenharmony_ci/*
301f08c3bdfSopenharmony_ci * Function: complete_eth_addrs()
302f08c3bdfSopenharmony_ci *
303f08c3bdfSopenharmony_ci * Description:
304f08c3bdfSopenharmony_ci *  This function sets the source and destination ethernet address completely
305f08c3bdfSopenharmony_ci *
306f08c3bdfSopenharmony_ci * Argument:
307f08c3bdfSopenharmony_ci *  fake_p: pointer to data of fake icmp structure
308f08c3bdfSopenharmony_ci *
309f08c3bdfSopenharmony_ci * Return value:
310f08c3bdfSopenharmony_ci *  None
311f08c3bdfSopenharmony_ci *
312f08c3bdfSopenharmony_ci */
313f08c3bdfSopenharmony_civoid complete_eth_addrs(struct icmpv4_fake *fake_p)
314f08c3bdfSopenharmony_ci{
315f08c3bdfSopenharmony_ci	int sock_fd;		/* Socket for ioctl() */
316f08c3bdfSopenharmony_ci	struct ifreq ifinfo;	/* Interface information */
317f08c3bdfSopenharmony_ci
318f08c3bdfSopenharmony_ci	if ((sock_fd = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0)
319f08c3bdfSopenharmony_ci		fatal_error("socket()");
320f08c3bdfSopenharmony_ci
321f08c3bdfSopenharmony_ci	/* Source */
322f08c3bdfSopenharmony_ci	fake_p->saddr_ll.sll_family = AF_PACKET;	/* Always AF_PACKET */
323f08c3bdfSopenharmony_ci	fake_p->saddr_ll.sll_protocol = htons(ETH_P_IP);	/* IPv4 */
324f08c3bdfSopenharmony_ci	fake_p->saddr_ll.sll_hatype = ARPHRD_ETHER;	/* Header type */
325f08c3bdfSopenharmony_ci	fake_p->saddr_ll.sll_pkttype = PACKET_HOST;	/* Packet type */
326f08c3bdfSopenharmony_ci	fake_p->saddr_ll.sll_halen = ETH_ALEN;	/* Length of address */
327f08c3bdfSopenharmony_ci
328f08c3bdfSopenharmony_ci	/* Get the MAC address of the interface at source host */
329f08c3bdfSopenharmony_ci	get_ifinfo(&ifinfo, sock_fd, fake_p->src_ifname, SIOCGIFHWADDR);
330f08c3bdfSopenharmony_ci	memcpy(fake_p->saddr_ll.sll_addr, ifinfo.ifr_hwaddr.sa_data, ETH_ALEN);
331f08c3bdfSopenharmony_ci
332f08c3bdfSopenharmony_ci	/* Get the interface index */
333f08c3bdfSopenharmony_ci	get_ifinfo(&ifinfo, sock_fd, fake_p->src_ifname, SIOCGIFINDEX);
334f08c3bdfSopenharmony_ci	fake_p->saddr_ll.sll_ifindex = ifinfo.ifr_ifindex;
335f08c3bdfSopenharmony_ci	fake_p->daddr_ll.sll_ifindex = ifinfo.ifr_ifindex;
336f08c3bdfSopenharmony_ci
337f08c3bdfSopenharmony_ci	close(sock_fd);
338f08c3bdfSopenharmony_ci}
339f08c3bdfSopenharmony_ci
340f08c3bdfSopenharmony_ci/*
341f08c3bdfSopenharmony_ci * Function: create_clean_packet()
342f08c3bdfSopenharmony_ci *
343f08c3bdfSopenharmony_ci * Description:
344f08c3bdfSopenharmony_ci *  This function creates icmpv4 packet without any fakes
345f08c3bdfSopenharmony_ci *
346f08c3bdfSopenharmony_ci * Argument:
347f08c3bdfSopenharmony_ci *  fake_p: pointer to data of fake icmp structure
348f08c3bdfSopenharmony_ci *
349f08c3bdfSopenharmony_ci * Return value:
350f08c3bdfSopenharmony_ci *  None
351f08c3bdfSopenharmony_ci */
352f08c3bdfSopenharmony_civoid create_clean_packet(struct icmpv4_fake *fake_p)
353f08c3bdfSopenharmony_ci{
354f08c3bdfSopenharmony_ci	struct ip4_datagram pkt;	/* sending IPv4 packet */
355f08c3bdfSopenharmony_ci	struct icmp4_segment *icmp_p;	/* ICMPv4 part of sending packet */
356f08c3bdfSopenharmony_ci	unsigned short int pkt_size;
357f08c3bdfSopenharmony_ci
358f08c3bdfSopenharmony_ci	memset(&pkt, '\0', sizeof(struct ip4_datagram));
359f08c3bdfSopenharmony_ci	pkt_size = sizeof(struct iphdr)	/* IP header */
360f08c3bdfSopenharmony_ci	    +sizeof(struct icmphdr)	/* ICMP header */
361f08c3bdfSopenharmony_ci	    +fake_p->data_size;	/* ICMP payload */
362f08c3bdfSopenharmony_ci
363f08c3bdfSopenharmony_ci	icmp_p = (struct icmp4_segment *)&(pkt.payload);
364f08c3bdfSopenharmony_ci
365f08c3bdfSopenharmony_ci	/* IPv4 Header */
366f08c3bdfSopenharmony_ci	pkt.hdr.version = 4;
367f08c3bdfSopenharmony_ci	pkt.hdr.ihl = sizeof(struct iphdr) / 4;
368f08c3bdfSopenharmony_ci	pkt.hdr.tos = 0;
369f08c3bdfSopenharmony_ci	pkt.hdr.tot_len = htons(pkt_size);
370f08c3bdfSopenharmony_ci	pkt.hdr.id = htons(IPV4_PACKET_ID);
371f08c3bdfSopenharmony_ci	pkt.hdr.frag_off = htons(IPV4_DEFAULT_FLAG);
372f08c3bdfSopenharmony_ci	pkt.hdr.ttl = IPV4_DEFAULT_TTL;
373f08c3bdfSopenharmony_ci	pkt.hdr.protocol = IPPROTO_ICMP;
374f08c3bdfSopenharmony_ci	pkt.hdr.check = 0;	/* Calculate later */
375f08c3bdfSopenharmony_ci	pkt.hdr.saddr = fake_p->saddr.s_addr;
376f08c3bdfSopenharmony_ci	pkt.hdr.daddr = fake_p->daddr.s_addr;
377f08c3bdfSopenharmony_ci
378f08c3bdfSopenharmony_ci	/* ICMPv4 Header */
379f08c3bdfSopenharmony_ci	icmp_p->hdr.type = ICMP_ECHO;
380f08c3bdfSopenharmony_ci	icmp_p->hdr.code = 0;
381f08c3bdfSopenharmony_ci	icmp_p->hdr.checksum = 0;	/* Calculate later */
382f08c3bdfSopenharmony_ci	icmp_p->hdr.un.echo.id = htons(ICMP_ECHO_ID);
383f08c3bdfSopenharmony_ci	icmp_p->hdr.un.echo.sequence = htons(1);
384f08c3bdfSopenharmony_ci
385f08c3bdfSopenharmony_ci	/* ICMPv4 Payload */
386f08c3bdfSopenharmony_ci	fill_payload(icmp_p->data, fake_p->data_size);
387f08c3bdfSopenharmony_ci
388f08c3bdfSopenharmony_ci	/* Calcualte checksums */
389f08c3bdfSopenharmony_ci	pkt.hdr.check = calc_checksum((u_int16_t *) (&pkt.hdr),
390f08c3bdfSopenharmony_ci				      sizeof(struct iphdr));
391f08c3bdfSopenharmony_ci	icmp_p->hdr.checksum = calc_checksum((u_int16_t *) icmp_p,
392f08c3bdfSopenharmony_ci					     sizeof(struct icmphdr) +
393f08c3bdfSopenharmony_ci					     fake_p->data_size);
394f08c3bdfSopenharmony_ci
395f08c3bdfSopenharmony_ci	/* Store the clean packet data */
396f08c3bdfSopenharmony_ci	fake_p->pkt = pkt;
397f08c3bdfSopenharmony_ci	fake_p->pkt_size = pkt_size;
398f08c3bdfSopenharmony_ci}
399f08c3bdfSopenharmony_ci
400f08c3bdfSopenharmony_ci/*
401f08c3bdfSopenharmony_ci * Function: thrust_fakes()
402f08c3bdfSopenharmony_ci *
403f08c3bdfSopenharmony_ci * Description:
404f08c3bdfSopenharmony_ci *  This function thrust fake information to the icmp packet
405f08c3bdfSopenharmony_ci *
406f08c3bdfSopenharmony_ci * Argument:
407f08c3bdfSopenharmony_ci *     pkt   : Payload of the Ethernet frame (Namely, IPv6 packet
408f08c3bdfSopenharmony_ci *  fake_flag: Flag which represents what information would be faked
409f08c3bdfSopenharmony_ci *
410f08c3bdfSopenharmony_ci * Return value:
411f08c3bdfSopenharmony_ci *  None
412f08c3bdfSopenharmony_ci */
413f08c3bdfSopenharmony_civoid thrust_fakes(struct ip4_datagram *pkt, u_int16_t fake_flag)
414f08c3bdfSopenharmony_ci{
415f08c3bdfSopenharmony_ci	int rand_val;
416f08c3bdfSopenharmony_ci	size_t bitsize;
417f08c3bdfSopenharmony_ci	u_int32_t seed;
418f08c3bdfSopenharmony_ci
419f08c3bdfSopenharmony_ci	if (debug)
420f08c3bdfSopenharmony_ci		fprintf(stderr, "fake_flag = %2x\n", fake_flag);
421f08c3bdfSopenharmony_ci
422f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_VERSION) {	/* version */
423f08c3bdfSopenharmony_ci		bitsize = 4;
424f08c3bdfSopenharmony_ci		seed = bit_change_seed(bitsize, 1);
425f08c3bdfSopenharmony_ci		pkt->hdr.version ^= seed;
426f08c3bdfSopenharmony_ci	}
427f08c3bdfSopenharmony_ci
428f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_IHL) {	/* header length */
429f08c3bdfSopenharmony_ci		bitsize = 4;
430f08c3bdfSopenharmony_ci		seed = bit_change_seed(bitsize, 1);
431f08c3bdfSopenharmony_ci		pkt->hdr.ihl ^= seed;
432f08c3bdfSopenharmony_ci	}
433f08c3bdfSopenharmony_ci
434f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_TOT_LEN) {	/* total length */
435f08c3bdfSopenharmony_ci		bitsize = sizeof(pkt->hdr.tot_len) * 8;
436f08c3bdfSopenharmony_ci		seed = bit_change_seed(bitsize, bitsize / 8);
437f08c3bdfSopenharmony_ci		pkt->hdr.tot_len ^= seed;
438f08c3bdfSopenharmony_ci	}
439f08c3bdfSopenharmony_ci
440f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_FRAGMENT) {	/* fragment information */
441f08c3bdfSopenharmony_ci		/* Set reserved flag */
442f08c3bdfSopenharmony_ci		rand_val = rand() / ((RAND_MAX + 1U) / 16);
443f08c3bdfSopenharmony_ci		if (!rand_val) {
444f08c3bdfSopenharmony_ci			if (debug)
445f08c3bdfSopenharmony_ci				fprintf(stderr, "Up reserved bit\n");
446f08c3bdfSopenharmony_ci			pkt->hdr.frag_off |= htonl(0x80000000);
447f08c3bdfSopenharmony_ci		}
448f08c3bdfSopenharmony_ci
449f08c3bdfSopenharmony_ci		/* Set more fragments flag */
450f08c3bdfSopenharmony_ci		rand_val = rand() / ((RAND_MAX + 1U) / 3);
451f08c3bdfSopenharmony_ci		if (!rand_val) {
452f08c3bdfSopenharmony_ci			if (debug)
453f08c3bdfSopenharmony_ci				fprintf(stderr, "Set more fragments flag\n");
454f08c3bdfSopenharmony_ci			pkt->hdr.frag_off |= htons(0x2000);
455f08c3bdfSopenharmony_ci		}
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci		/* Unset unfragmented flag */
458f08c3bdfSopenharmony_ci		rand_val = rand() / ((RAND_MAX + 1U) / 3);
459f08c3bdfSopenharmony_ci		if (!rand_val) {
460f08c3bdfSopenharmony_ci			if (debug)
461f08c3bdfSopenharmony_ci				fprintf(stderr, "Unset unfragmented flag\n");
462f08c3bdfSopenharmony_ci			pkt->hdr.frag_off &= htons(0xbfff);
463f08c3bdfSopenharmony_ci		}
464f08c3bdfSopenharmony_ci
465f08c3bdfSopenharmony_ci		/* Set fragment offset */
466f08c3bdfSopenharmony_ci		rand_val = rand() / ((RAND_MAX + 1U) / 3);
467f08c3bdfSopenharmony_ci		if (!rand_val) {
468f08c3bdfSopenharmony_ci			bitsize = 13;
469f08c3bdfSopenharmony_ci			seed = bit_change_seed(bitsize, 0);
470f08c3bdfSopenharmony_ci			if (debug)
471f08c3bdfSopenharmony_ci				fprintf(stderr, "Set fragment offset %02x\n",
472f08c3bdfSopenharmony_ci					seed);
473f08c3bdfSopenharmony_ci			pkt->hdr.frag_off |= htons(seed);
474f08c3bdfSopenharmony_ci		}
475f08c3bdfSopenharmony_ci	}
476f08c3bdfSopenharmony_ci
477f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_PROTOCOL) {	/* protocol */
478f08c3bdfSopenharmony_ci		rand_val = rand() / ((RAND_MAX + 1U) / 5);
479f08c3bdfSopenharmony_ci		switch (rand_val) {
480f08c3bdfSopenharmony_ci		case 1:
481f08c3bdfSopenharmony_ci		case 2:
482f08c3bdfSopenharmony_ci			if (debug)
483f08c3bdfSopenharmony_ci				fprintf(stderr, "Bit reverse\n");
484f08c3bdfSopenharmony_ci			bitsize = sizeof(pkt->hdr.protocol) * 8;
485f08c3bdfSopenharmony_ci			seed = bit_change_seed(bitsize, 0);
486f08c3bdfSopenharmony_ci			pkt->hdr.protocol ^= seed;
487f08c3bdfSopenharmony_ci			break;
488f08c3bdfSopenharmony_ci
489f08c3bdfSopenharmony_ci		case 3:
490f08c3bdfSopenharmony_ci		case 4:
491f08c3bdfSopenharmony_ci			if (debug)
492f08c3bdfSopenharmony_ci				fprintf(stderr, "Unknown Protocol\n");
493f08c3bdfSopenharmony_ci			if (rand_val) {
494f08c3bdfSopenharmony_ci				int number;
495f08c3bdfSopenharmony_ci				int counter;
496f08c3bdfSopenharmony_ci				for (counter = 0; counter <= 0xff; counter++) {
497f08c3bdfSopenharmony_ci					number =
498f08c3bdfSopenharmony_ci					    rand() / ((RAND_MAX + 1U) / 0x100);
499f08c3bdfSopenharmony_ci					if (getprotobynumber(number) == NULL) {
500f08c3bdfSopenharmony_ci						pkt->hdr.protocol = number;
501f08c3bdfSopenharmony_ci						break;
502f08c3bdfSopenharmony_ci					}
503f08c3bdfSopenharmony_ci				}
504f08c3bdfSopenharmony_ci			}
505f08c3bdfSopenharmony_ci			break;
506f08c3bdfSopenharmony_ci
507f08c3bdfSopenharmony_ci		default:
508f08c3bdfSopenharmony_ci			if (debug)
509f08c3bdfSopenharmony_ci				fprintf(stderr, "Do nothing\n");
510f08c3bdfSopenharmony_ci			break;
511f08c3bdfSopenharmony_ci		}
512f08c3bdfSopenharmony_ci	}
513f08c3bdfSopenharmony_ci
514f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_DADDR) {	/* destination address */
515f08c3bdfSopenharmony_ci		bitsize = sizeof(pkt->hdr.daddr) * 8;
516f08c3bdfSopenharmony_ci		seed = bit_change_seed(bitsize, bitsize / 8);
517f08c3bdfSopenharmony_ci		pkt->hdr.daddr ^= seed;
518f08c3bdfSopenharmony_ci	}
519f08c3bdfSopenharmony_ci
520f08c3bdfSopenharmony_ci	/* Recalculate checksum once */
521f08c3bdfSopenharmony_ci	pkt->hdr.check = 0;
522f08c3bdfSopenharmony_ci	pkt->hdr.check =
523f08c3bdfSopenharmony_ci	    calc_checksum((u_int16_t *) & (pkt->hdr), sizeof(struct iphdr));
524f08c3bdfSopenharmony_ci
525f08c3bdfSopenharmony_ci	if (fake_flag & FAKE_CHECK) {	/* checksum */
526f08c3bdfSopenharmony_ci		bitsize = sizeof(pkt->hdr.check) * 8;
527f08c3bdfSopenharmony_ci		seed = bit_change_seed(bitsize, bitsize / 8);
528f08c3bdfSopenharmony_ci		pkt->hdr.check ^= seed;
529f08c3bdfSopenharmony_ci	}
530f08c3bdfSopenharmony_ci}
531f08c3bdfSopenharmony_ci
532f08c3bdfSopenharmony_ci/*
533f08c3bdfSopenharmony_ci * Function: send_packet()
534f08c3bdfSopenharmony_ci *
535f08c3bdfSopenharmony_ci * Description:
536f08c3bdfSopenharmony_ci *  This function sends icmpv4 packet
537f08c3bdfSopenharmony_ci *
538f08c3bdfSopenharmony_ci * Argument:
539f08c3bdfSopenharmony_ci *  fake_p: pointer to data of fake icmp structure
540f08c3bdfSopenharmony_ci *
541f08c3bdfSopenharmony_ci * Return value:
542f08c3bdfSopenharmony_ci *  None
543f08c3bdfSopenharmony_ci */
544f08c3bdfSopenharmony_civoid send_packets(struct icmpv4_fake *fake_p)
545f08c3bdfSopenharmony_ci{
546f08c3bdfSopenharmony_ci	int sock_fd;
547f08c3bdfSopenharmony_ci	int retval;
548f08c3bdfSopenharmony_ci	struct ip4_datagram pkt;
549f08c3bdfSopenharmony_ci	double start_time;
550f08c3bdfSopenharmony_ci
551f08c3bdfSopenharmony_ci	/* Open a socket */
552f08c3bdfSopenharmony_ci	sock_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
553f08c3bdfSopenharmony_ci	if (sock_fd < 0)
554f08c3bdfSopenharmony_ci		fatal_error("socket()");
555f08c3bdfSopenharmony_ci
556f08c3bdfSopenharmony_ci	/* Bind the socket to the physical address */
557f08c3bdfSopenharmony_ci	retval = bind(sock_fd, (struct sockaddr *)&(fake_p->saddr_ll),
558f08c3bdfSopenharmony_ci		      sizeof(struct sockaddr_ll));
559f08c3bdfSopenharmony_ci	if (retval < 0)
560f08c3bdfSopenharmony_ci		fatal_error("bind()");
561f08c3bdfSopenharmony_ci
562f08c3bdfSopenharmony_ci	/* Set singal hander for SIGHUP */
563f08c3bdfSopenharmony_ci	handler.sa_handler = set_signal_flag;
564f08c3bdfSopenharmony_ci	handler.sa_flags = 0;
565f08c3bdfSopenharmony_ci	if (sigfillset(&handler.sa_mask) < 0)
566f08c3bdfSopenharmony_ci		fatal_error("sigfillset()");
567f08c3bdfSopenharmony_ci	if (sigaction(SIGHUP, &handler, NULL) < 0)
568f08c3bdfSopenharmony_ci		fatal_error("sigfillset()");
569f08c3bdfSopenharmony_ci
570f08c3bdfSopenharmony_ci	/*
571f08c3bdfSopenharmony_ci	 * loop for sending packets
572f08c3bdfSopenharmony_ci	 */
573f08c3bdfSopenharmony_ci	pkt = fake_p->pkt;
574f08c3bdfSopenharmony_ci	start_time = time(NULL);
575f08c3bdfSopenharmony_ci
576f08c3bdfSopenharmony_ci	for (;;) {
577f08c3bdfSopenharmony_ci		if (fake_p->fake_flag) {
578f08c3bdfSopenharmony_ci			pkt = fake_p->pkt;
579f08c3bdfSopenharmony_ci			thrust_fakes(&pkt, fake_p->fake_flag);
580f08c3bdfSopenharmony_ci		}
581f08c3bdfSopenharmony_ci
582f08c3bdfSopenharmony_ci		retval = sendto(sock_fd, &pkt, fake_p->pkt_size, 0,
583f08c3bdfSopenharmony_ci				(struct sockaddr *)&(fake_p->daddr_ll),
584f08c3bdfSopenharmony_ci				sizeof(struct sockaddr_ll));
585f08c3bdfSopenharmony_ci		if (retval < 0)
586f08c3bdfSopenharmony_ci			fatal_error("sendto()");
587f08c3bdfSopenharmony_ci
588f08c3bdfSopenharmony_ci		if (fake_p->timeout)	/* timeout */
589f08c3bdfSopenharmony_ci			if (fake_p->timeout < difftime(time(NULL), start_time))
590f08c3bdfSopenharmony_ci				break;
591f08c3bdfSopenharmony_ci
592f08c3bdfSopenharmony_ci		if (catch_sighup)	/* catch SIGHUP */
593f08c3bdfSopenharmony_ci			break;
594f08c3bdfSopenharmony_ci	}
595f08c3bdfSopenharmony_ci
596f08c3bdfSopenharmony_ci	/* Close the socket */
597f08c3bdfSopenharmony_ci	close(sock_fd);
598f08c3bdfSopenharmony_ci}
599f08c3bdfSopenharmony_ci
600f08c3bdfSopenharmony_ci/*
601f08c3bdfSopenharmony_ci *
602f08c3bdfSopenharmony_ci *  Function: main()
603f08c3bdfSopenharmony_ci *
604f08c3bdfSopenharmony_ci */
605f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
606f08c3bdfSopenharmony_ci{
607f08c3bdfSopenharmony_ci	struct icmpv4_fake fake_data;
608f08c3bdfSopenharmony_ci
609f08c3bdfSopenharmony_ci	debug = 0;
610f08c3bdfSopenharmony_ci	program_name = strdup(argv[0]);
611f08c3bdfSopenharmony_ci	srand(getpid());
612f08c3bdfSopenharmony_ci
613f08c3bdfSopenharmony_ci	memset(&fake_data, '\0', sizeof(struct icmpv4_fake));
614f08c3bdfSopenharmony_ci	parse_options(argc, argv, &fake_data);
615f08c3bdfSopenharmony_ci
616f08c3bdfSopenharmony_ci	complete_eth_addrs(&fake_data);
617f08c3bdfSopenharmony_ci	create_clean_packet(&fake_data);
618f08c3bdfSopenharmony_ci
619f08c3bdfSopenharmony_ci	send_packets(&fake_data);
620f08c3bdfSopenharmony_ci
621f08c3bdfSopenharmony_ci	exit(EXIT_SUCCESS);
622f08c3bdfSopenharmony_ci}
623