1f08c3bdfSopenharmony_ci/* -*- linux-c -*- */
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci *   Copyright (c) International Business Machines  Corp., 2000
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
8f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
9f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
10f08c3bdfSopenharmony_ci *   (at your option) any later version.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
13f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
14f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
18f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
19f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20f08c3bdfSopenharmony_ci *
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci */
23f08c3bdfSopenharmony_ci/*
24f08c3bdfSopenharmony_ci * ltpClient.c
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci * LTP Network Socket Test Client
27f08c3bdfSopenharmony_ci *
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci */
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_ci#include <sys/types.h>
32f08c3bdfSopenharmony_ci#include <sys/socket.h>
33f08c3bdfSopenharmony_ci#include <netinet/in.h>
34f08c3bdfSopenharmony_ci#include <netinet/ip_icmp.h>
35f08c3bdfSopenharmony_ci#include <arpa/inet.h>
36f08c3bdfSopenharmony_ci#include <netdb.h>
37f08c3bdfSopenharmony_ci#include <stdio.h>
38f08c3bdfSopenharmony_ci#include <stdlib.h>
39f08c3bdfSopenharmony_ci#include <resolv.h>
40f08c3bdfSopenharmony_ci#include <fcntl.h>
41f08c3bdfSopenharmony_ci#include <errno.h>
42f08c3bdfSopenharmony_ci#include <unistd.h>
43f08c3bdfSopenharmony_ci#include <string.h>
44f08c3bdfSopenharmony_ci#include <sys/time.h>
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci#define LOCAL_UDP_SERVER_PORT   10000
47f08c3bdfSopenharmony_ci#define LOCAL_TCP_SERVER_PORT   10001
48f08c3bdfSopenharmony_ci#define LOCAL_MCAST_SERVER_PORT 10002
49f08c3bdfSopenharmony_ci#define MAX_MSG_LEN             256
50f08c3bdfSopenharmony_ci#define TIMETOLIVE              10
51f08c3bdfSopenharmony_ci#define PACKETSIZE	            64
52f08c3bdfSopenharmony_ci#define NET_ERROR               -1
53f08c3bdfSopenharmony_ci#define PACKET_LEN              1024	/* 1K should be plenty */
54f08c3bdfSopenharmony_ci#define TRUE                    1
55f08c3bdfSopenharmony_ci#define FALSE                   0
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_cistruct protoent *protocol = NULL;
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_cistruct packet {
60f08c3bdfSopenharmony_ci	struct icmphdr hdr;
61f08c3bdfSopenharmony_ci	char msg[PACKETSIZE - sizeof(struct icmphdr)];
62f08c3bdfSopenharmony_ci};
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci/*
65f08c3bdfSopenharmony_ci*   Function Prototypes
66f08c3bdfSopenharmony_ci*/
67f08c3bdfSopenharmony_ciint ltp_run_ping_tests(char *hostName);
68f08c3bdfSopenharmony_ciint ltp_run_traceroute_tests(char *hostName);
69f08c3bdfSopenharmony_civoid ping_network(struct sockaddr_in *rawAddr, int pid);
70f08c3bdfSopenharmony_civoid output_to_display(void *netPacket, int bytes, int pid);
71f08c3bdfSopenharmony_ciunsigned short checksum(void *netPacket, int len);
72f08c3bdfSopenharmony_ciint network_listener(char *hostname, int pid);
73f08c3bdfSopenharmony_civoid ltp_traceroute(struct sockaddr_in *rawTraceAddr, char *hostName, int pid);
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci/*******************************************************************
76f08c3bdfSopenharmony_ci*  Function: Main
77f08c3bdfSopenharmony_ci*
78f08c3bdfSopenharmony_ci*  Main will run the tests in this order.
79f08c3bdfSopenharmony_ci*       UDP, TCP and Multicast will be run first, if multicast is enabled.
80f08c3bdfSopenharmony_ci*       If multicast is not enabled, the UDP/TCP tests will continue.
81f08c3bdfSopenharmony_ci*       Once those tests complete, the ping and then traceroute tests will run.
82f08c3bdfSopenharmony_ci*
83f08c3bdfSopenharmony_ci********************************************************************/
84f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
85f08c3bdfSopenharmony_ci{
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci	int udpSocketHandle, tcpSocketHandle, mcastSocketHandle, rc, i;
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	struct sockaddr_in udpClientAddr,
90f08c3bdfSopenharmony_ci	    udpRemoteServerAddr,
91f08c3bdfSopenharmony_ci	    tcpClientAddr,
92f08c3bdfSopenharmony_ci	    tcpRemoteServerAddr, mcastClientAddr, mcastRemoteServerAddr;
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ci	struct hostent *hostEntry;
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	char hostName[MAX_MSG_LEN],
97f08c3bdfSopenharmony_ci	    progName[MAX_MSG_LEN], traceName[MAX_MSG_LEN], multiCast = TRUE;
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	unsigned char ttl = 1;
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci	mcastSocketHandle = -1;
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci	/* check command line args */
104f08c3bdfSopenharmony_ci	if (argc < 4) {
105f08c3bdfSopenharmony_ci		printf
106f08c3bdfSopenharmony_ci		    ("usage :<server-hostname> <trace-hostName> <data1> ... <dataN> \n");
107f08c3bdfSopenharmony_ci		exit(1);
108f08c3bdfSopenharmony_ci	}
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci	strncpy(progName, argv[0], MAX_MSG_LEN);
111f08c3bdfSopenharmony_ci	strncpy(hostName, argv[1], MAX_MSG_LEN);
112f08c3bdfSopenharmony_ci	strncpy(traceName, argv[2], MAX_MSG_LEN);
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	/* get server IP address (no check if input is IP address or DNS name */
115f08c3bdfSopenharmony_ci	hostEntry = gethostbyname(hostName);
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci	if (hostEntry == NULL) {
118f08c3bdfSopenharmony_ci		printf("%s: unknown host passed'%s' \n", progName, hostName);
119f08c3bdfSopenharmony_ci		exit(1);
120f08c3bdfSopenharmony_ci	}
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_ci	printf("%s: sending data to '%s' (IP : %s) \n", progName,
123f08c3bdfSopenharmony_ci	       hostEntry->h_name,
124f08c3bdfSopenharmony_ci	       inet_ntoa(*(struct in_addr *)hostEntry->h_addr_list[0]));
125f08c3bdfSopenharmony_ci
126f08c3bdfSopenharmony_ci	/* Setup UDP data packets */
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ci	udpRemoteServerAddr.sin_family = hostEntry->h_addrtype;
129f08c3bdfSopenharmony_ci	memcpy((char *)&udpRemoteServerAddr.sin_addr.s_addr,
130f08c3bdfSopenharmony_ci	       hostEntry->h_addr_list[0], hostEntry->h_length);
131f08c3bdfSopenharmony_ci	udpRemoteServerAddr.sin_port = htons(LOCAL_UDP_SERVER_PORT);
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_ci	/* Setup TCP data packets */
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ci	tcpRemoteServerAddr.sin_family = hostEntry->h_addrtype;
136f08c3bdfSopenharmony_ci	memcpy((char *)&tcpRemoteServerAddr.sin_addr.s_addr,
137f08c3bdfSopenharmony_ci	       hostEntry->h_addr_list[0], hostEntry->h_length);
138f08c3bdfSopenharmony_ci	tcpRemoteServerAddr.sin_port = htons(LOCAL_TCP_SERVER_PORT);
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_ci	/* Setup multiCast data packets */
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci	mcastRemoteServerAddr.sin_family = hostEntry->h_addrtype;
143f08c3bdfSopenharmony_ci	memcpy((char *)&mcastRemoteServerAddr.sin_addr.s_addr,
144f08c3bdfSopenharmony_ci	       hostEntry->h_addr_list[0], hostEntry->h_length);
145f08c3bdfSopenharmony_ci	mcastRemoteServerAddr.sin_port = htons(LOCAL_MCAST_SERVER_PORT);
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ci	/* socket creation */
148f08c3bdfSopenharmony_ci	udpSocketHandle = socket(AF_INET, SOCK_DGRAM, 0);
149f08c3bdfSopenharmony_ci	tcpSocketHandle = socket(AF_INET, SOCK_STREAM, 0);
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci	if (udpSocketHandle < 0) {
152f08c3bdfSopenharmony_ci		printf("%s: Error: cannot open UDP socket \n", progName);
153f08c3bdfSopenharmony_ci	}
154f08c3bdfSopenharmony_ci
155f08c3bdfSopenharmony_ci	if (tcpSocketHandle < 0) {
156f08c3bdfSopenharmony_ci		printf("%s: Error: cannot open TCP socket \n", progName);
157f08c3bdfSopenharmony_ci	}
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ci	/* bind any UDP port */
160f08c3bdfSopenharmony_ci	udpClientAddr.sin_family = AF_INET;
161f08c3bdfSopenharmony_ci	udpClientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
162f08c3bdfSopenharmony_ci	udpClientAddr.sin_port = htons(0);
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci	/* bind any TCP port */
165f08c3bdfSopenharmony_ci	tcpClientAddr.sin_family = AF_INET;
166f08c3bdfSopenharmony_ci	tcpClientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
167f08c3bdfSopenharmony_ci	tcpClientAddr.sin_port = htons(0);
168f08c3bdfSopenharmony_ci
169f08c3bdfSopenharmony_ci	if (udpSocketHandle > 0) {
170f08c3bdfSopenharmony_ci		rc = bind(udpSocketHandle, (struct sockaddr *)&udpClientAddr,
171f08c3bdfSopenharmony_ci			  sizeof(udpClientAddr));
172f08c3bdfSopenharmony_ci
173f08c3bdfSopenharmony_ci		if (rc < 0) {
174f08c3bdfSopenharmony_ci			printf("%s: Error: cannot bind UDP port\n", progName);
175f08c3bdfSopenharmony_ci		}
176f08c3bdfSopenharmony_ci	}
177f08c3bdfSopenharmony_ci
178f08c3bdfSopenharmony_ci	if (tcpSocketHandle > 0) {
179f08c3bdfSopenharmony_ci		rc = bind(tcpSocketHandle, (struct sockaddr *)&tcpClientAddr,
180f08c3bdfSopenharmony_ci			  sizeof(tcpClientAddr));
181f08c3bdfSopenharmony_ci
182f08c3bdfSopenharmony_ci		if (rc < 0) {
183f08c3bdfSopenharmony_ci			printf("%s: Error: cannot bind TCP port\n", progName);
184f08c3bdfSopenharmony_ci		} else {
185f08c3bdfSopenharmony_ci			/* connect to server */
186f08c3bdfSopenharmony_ci			rc = connect(tcpSocketHandle,
187f08c3bdfSopenharmony_ci				     (struct sockaddr *)&tcpRemoteServerAddr,
188f08c3bdfSopenharmony_ci				     sizeof(tcpRemoteServerAddr));
189f08c3bdfSopenharmony_ci
190f08c3bdfSopenharmony_ci			if (rc < 0) {
191f08c3bdfSopenharmony_ci				printf
192f08c3bdfSopenharmony_ci				    ("Error: cannot connect tp TCP Server \n");
193f08c3bdfSopenharmony_ci			}
194f08c3bdfSopenharmony_ci		}
195f08c3bdfSopenharmony_ci	}
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci	/* check given address is multicast */
198f08c3bdfSopenharmony_ci	if (!IN_MULTICAST(ntohl(mcastRemoteServerAddr.sin_addr.s_addr))) {
199f08c3bdfSopenharmony_ci		printf
200f08c3bdfSopenharmony_ci		    ("%s : Hostname [%s] passed [%s] is not a multicast server\n",
201f08c3bdfSopenharmony_ci		     progName, hostName,
202f08c3bdfSopenharmony_ci		     inet_ntoa(mcastRemoteServerAddr.sin_addr));
203f08c3bdfSopenharmony_ci		printf("The multiCast Server will not be started \n");
204f08c3bdfSopenharmony_ci		multiCast = FALSE;
205f08c3bdfSopenharmony_ci	} else {
206f08c3bdfSopenharmony_ci		/* create socket */
207f08c3bdfSopenharmony_ci		mcastSocketHandle = socket(AF_INET, SOCK_DGRAM, 0);
208f08c3bdfSopenharmony_ci		if (mcastSocketHandle < 0) {
209f08c3bdfSopenharmony_ci			printf("Error: %s : cannot open mulitCast socket\n",
210f08c3bdfSopenharmony_ci			       progName);
211f08c3bdfSopenharmony_ci			multiCast = FALSE;
212f08c3bdfSopenharmony_ci		}
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ci		/* bind any port number */
215f08c3bdfSopenharmony_ci		mcastClientAddr.sin_family = AF_INET;
216f08c3bdfSopenharmony_ci		mcastClientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
217f08c3bdfSopenharmony_ci		mcastClientAddr.sin_port = htons(0);
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ci		if (bind
220f08c3bdfSopenharmony_ci		    (mcastSocketHandle, (struct sockaddr *)&mcastClientAddr,
221f08c3bdfSopenharmony_ci		     sizeof(mcastClientAddr)) < 0) {
222f08c3bdfSopenharmony_ci			printf("Error: binding multiCast socket");
223f08c3bdfSopenharmony_ci			multiCast = FALSE;
224f08c3bdfSopenharmony_ci		}
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_ci		if (setsockopt
227f08c3bdfSopenharmony_ci		    (mcastSocketHandle, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
228f08c3bdfSopenharmony_ci		     sizeof(ttl)) < 0) {
229f08c3bdfSopenharmony_ci			printf("Error: %s : cannot set ttl = %d \n", progName,
230f08c3bdfSopenharmony_ci			       ttl);
231f08c3bdfSopenharmony_ci			multiCast = FALSE;
232f08c3bdfSopenharmony_ci		}
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_ci		printf("%s : sending data on multicast group '%s' (%s)\n",
235f08c3bdfSopenharmony_ci		       progName, hostEntry->h_name,
236f08c3bdfSopenharmony_ci		       inet_ntoa(*(struct in_addr *)hostEntry->h_addr_list[0]));
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_ci	}
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ci	/* Skip over the program and hostnames and just send data */
241f08c3bdfSopenharmony_ci	for (i = 3; i < argc; i++) {
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci		if (udpSocketHandle > 0) {
244f08c3bdfSopenharmony_ci			rc = sendto(udpSocketHandle, argv[i],
245f08c3bdfSopenharmony_ci				    strlen(argv[i]) + 1, 0,
246f08c3bdfSopenharmony_ci				    (struct sockaddr *)&udpRemoteServerAddr,
247f08c3bdfSopenharmony_ci				    sizeof(udpRemoteServerAddr));
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ci			if (rc < 0) {
250f08c3bdfSopenharmony_ci				printf("%s: cannot send UDP data %d \n",
251f08c3bdfSopenharmony_ci				       progName, i - 1);
252f08c3bdfSopenharmony_ci				close(udpSocketHandle);
253f08c3bdfSopenharmony_ci			} else {
254f08c3bdfSopenharmony_ci				printf("%s: UDP data%u sent (%s)\n", progName,
255f08c3bdfSopenharmony_ci				       i - 1, argv[i]);
256f08c3bdfSopenharmony_ci			}
257f08c3bdfSopenharmony_ci		} else {
258f08c3bdfSopenharmony_ci			printf("%s UDP Socket not open for send \n", hostName);
259f08c3bdfSopenharmony_ci		}
260f08c3bdfSopenharmony_ci
261f08c3bdfSopenharmony_ci		if (tcpSocketHandle > 0) {
262f08c3bdfSopenharmony_ci			rc = send(tcpSocketHandle, argv[i], strlen(argv[i]) + 1,
263f08c3bdfSopenharmony_ci				  0);
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_ci			if (rc < 0) {
266f08c3bdfSopenharmony_ci				printf("cannot send TCP data ");
267f08c3bdfSopenharmony_ci				close(tcpSocketHandle);
268f08c3bdfSopenharmony_ci
269f08c3bdfSopenharmony_ci			} else {
270f08c3bdfSopenharmony_ci				printf("%s: TCP data%u sent (%s)\n", progName,
271f08c3bdfSopenharmony_ci				       i - 1, argv[i]);
272f08c3bdfSopenharmony_ci			}
273f08c3bdfSopenharmony_ci		} else {
274f08c3bdfSopenharmony_ci			printf("%s TCP Socket not open for send \n", hostName);
275f08c3bdfSopenharmony_ci		}
276f08c3bdfSopenharmony_ci
277f08c3bdfSopenharmony_ci		if (multiCast) {
278f08c3bdfSopenharmony_ci			rc = sendto(mcastSocketHandle, argv[i],
279f08c3bdfSopenharmony_ci				    strlen(argv[i]) + 1, 0,
280f08c3bdfSopenharmony_ci				    (struct sockaddr *)&mcastRemoteServerAddr,
281f08c3bdfSopenharmony_ci				    sizeof(mcastRemoteServerAddr));
282f08c3bdfSopenharmony_ci
283f08c3bdfSopenharmony_ci			if (rc < 0) {
284f08c3bdfSopenharmony_ci				printf("%s : cannot send multiCast data %d\n",
285f08c3bdfSopenharmony_ci				       progName, i - 1);
286f08c3bdfSopenharmony_ci				close(mcastSocketHandle);
287f08c3bdfSopenharmony_ci				multiCast = FALSE;
288f08c3bdfSopenharmony_ci			}
289f08c3bdfSopenharmony_ci		}
290f08c3bdfSopenharmony_ci	}
291f08c3bdfSopenharmony_ci
292f08c3bdfSopenharmony_ci	sleep(5);
293f08c3bdfSopenharmony_ci
294f08c3bdfSopenharmony_ci	ltp_run_traceroute_tests(traceName);
295f08c3bdfSopenharmony_ci
296f08c3bdfSopenharmony_ci	ltp_run_ping_tests(hostName);
297f08c3bdfSopenharmony_ci
298f08c3bdfSopenharmony_ci	return 0;
299f08c3bdfSopenharmony_ci
300f08c3bdfSopenharmony_ci}
301f08c3bdfSopenharmony_ci
302f08c3bdfSopenharmony_ci/*****************************************************************************
303f08c3bdfSopenharmony_ci* Function: ltp_run_traceroute_tests - host look up and start traceroute processes
304f08c3bdfSopenharmony_ci*
305f08c3bdfSopenharmony_ci******************************************************************************/
306f08c3bdfSopenharmony_ciint ltp_run_traceroute_tests(char *hostName)
307f08c3bdfSopenharmony_ci{
308f08c3bdfSopenharmony_ci
309f08c3bdfSopenharmony_ci	struct hostent *hostEntry;
310f08c3bdfSopenharmony_ci	struct sockaddr_in rawTraceAddr;
311f08c3bdfSopenharmony_ci	int pid = -1;
312f08c3bdfSopenharmony_ci
313f08c3bdfSopenharmony_ci	pid = getpid();
314f08c3bdfSopenharmony_ci
315f08c3bdfSopenharmony_ci	protocol = getprotobyname("ICMP");
316f08c3bdfSopenharmony_ci	hostEntry = gethostbyname(hostName);
317f08c3bdfSopenharmony_ci
318f08c3bdfSopenharmony_ci	memset(&rawTraceAddr, 0, sizeof(rawTraceAddr));
319f08c3bdfSopenharmony_ci
320f08c3bdfSopenharmony_ci	rawTraceAddr.sin_family = hostEntry->h_addrtype;
321f08c3bdfSopenharmony_ci	rawTraceAddr.sin_port = 0;
322f08c3bdfSopenharmony_ci	rawTraceAddr.sin_addr.s_addr = *(long *)hostEntry->h_addr;
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci	ltp_traceroute(&rawTraceAddr, hostName, pid);
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_ci	return 0;
327f08c3bdfSopenharmony_ci}
328f08c3bdfSopenharmony_ci
329f08c3bdfSopenharmony_ci/**********************************************************************
330f08c3bdfSopenharmony_ci* Function: ltp_run_ping_tests - host look up and start ping processes
331f08c3bdfSopenharmony_ci*
332f08c3bdfSopenharmony_ci***********************************************************************/
333f08c3bdfSopenharmony_ciint ltp_run_ping_tests(char *hostName)
334f08c3bdfSopenharmony_ci{
335f08c3bdfSopenharmony_ci
336f08c3bdfSopenharmony_ci	struct hostent *hostEntry;
337f08c3bdfSopenharmony_ci	struct sockaddr_in rawAddr;
338f08c3bdfSopenharmony_ci	int pid = -1;
339f08c3bdfSopenharmony_ci
340f08c3bdfSopenharmony_ci	pid = getpid();
341f08c3bdfSopenharmony_ci
342f08c3bdfSopenharmony_ci	protocol = getprotobyname("ICMP");
343f08c3bdfSopenharmony_ci	hostEntry = gethostbyname(hostName);
344f08c3bdfSopenharmony_ci
345f08c3bdfSopenharmony_ci	memset(&rawAddr, 0, sizeof(rawAddr));
346f08c3bdfSopenharmony_ci
347f08c3bdfSopenharmony_ci	rawAddr.sin_family = hostEntry->h_addrtype;
348f08c3bdfSopenharmony_ci	rawAddr.sin_port = 0;
349f08c3bdfSopenharmony_ci	rawAddr.sin_addr.s_addr = *(long *)hostEntry->h_addr;
350f08c3bdfSopenharmony_ci
351f08c3bdfSopenharmony_ci	if (fork() == 0) {
352f08c3bdfSopenharmony_ci		network_listener(hostName, pid);
353f08c3bdfSopenharmony_ci	} else {
354f08c3bdfSopenharmony_ci		ping_network(&rawAddr, pid);
355f08c3bdfSopenharmony_ci
356f08c3bdfSopenharmony_ci	}
357f08c3bdfSopenharmony_ci
358f08c3bdfSopenharmony_ci	return 0;
359f08c3bdfSopenharmony_ci}
360f08c3bdfSopenharmony_ci
361f08c3bdfSopenharmony_ci/******************************************************************************
362f08c3bdfSopenharmony_ci* Function: network_listener - separate process to listen for and collect messages
363f08c3bdfSopenharmony_ci*
364f08c3bdfSopenharmony_ci*******************************************************************************/
365f08c3bdfSopenharmony_ciint network_listener(char *hostName, int pid)
366f08c3bdfSopenharmony_ci{
367f08c3bdfSopenharmony_ci
368f08c3bdfSopenharmony_ci	int rawSocket, count, value = TIMETOLIVE;
369f08c3bdfSopenharmony_ci	struct sockaddr_in rawAddr;
370f08c3bdfSopenharmony_ci	unsigned char packet[PACKET_LEN];
371f08c3bdfSopenharmony_ci
372f08c3bdfSopenharmony_ci	rawSocket = socket(PF_INET, SOCK_RAW, protocol->p_proto);
373f08c3bdfSopenharmony_ci	count = 0;
374f08c3bdfSopenharmony_ci
375f08c3bdfSopenharmony_ci	if (rawSocket < 0) {
376f08c3bdfSopenharmony_ci		printf("%s: Error: cannot open RAW socket \n", hostName);
377f08c3bdfSopenharmony_ci		return (NET_ERROR);
378f08c3bdfSopenharmony_ci	}
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_ci	while (1) {		/* loop forever */
381f08c3bdfSopenharmony_ci
382f08c3bdfSopenharmony_ci		int bytes;
383f08c3bdfSopenharmony_ci		socklen_t len = sizeof(rawAddr);
384f08c3bdfSopenharmony_ci
385f08c3bdfSopenharmony_ci		memset(packet, 0, sizeof(packet));
386f08c3bdfSopenharmony_ci
387f08c3bdfSopenharmony_ci		bytes =
388f08c3bdfSopenharmony_ci		    recvfrom(rawSocket, packet, sizeof(packet), 0,
389f08c3bdfSopenharmony_ci			     (struct sockaddr *)&rawAddr, &len);
390f08c3bdfSopenharmony_ci
391f08c3bdfSopenharmony_ci		if (bytes > 0)
392f08c3bdfSopenharmony_ci			output_to_display(packet, bytes, pid);
393f08c3bdfSopenharmony_ci		else {
394f08c3bdfSopenharmony_ci			printf("%s : cannot receive data\n", hostName);
395f08c3bdfSopenharmony_ci			break;
396f08c3bdfSopenharmony_ci		}
397f08c3bdfSopenharmony_ci		count++;
398f08c3bdfSopenharmony_ci
399f08c3bdfSopenharmony_ci		if (value == count) {
400f08c3bdfSopenharmony_ci			printf("Exiting the network_listener...\n");
401f08c3bdfSopenharmony_ci		}
402f08c3bdfSopenharmony_ci	}
403f08c3bdfSopenharmony_ci
404f08c3bdfSopenharmony_ci	close(rawSocket);
405f08c3bdfSopenharmony_ci	return (0);
406f08c3bdfSopenharmony_ci}
407f08c3bdfSopenharmony_ci
408f08c3bdfSopenharmony_ci/****************************************************************
409f08c3bdfSopenharmony_ci* Function: checksum - standard 1s complement checksum
410f08c3bdfSopenharmony_ci*
411f08c3bdfSopenharmony_ci*****************************************************************/
412f08c3bdfSopenharmony_ciunsigned short checksum(void *netPacket, int len)
413f08c3bdfSopenharmony_ci{
414f08c3bdfSopenharmony_ci
415f08c3bdfSopenharmony_ci	unsigned short *packetPtr = netPacket, result;
416f08c3bdfSopenharmony_ci
417f08c3bdfSopenharmony_ci	unsigned int sum = 0;
418f08c3bdfSopenharmony_ci
419f08c3bdfSopenharmony_ci	for (sum = 0; len > 1; len -= 2) {
420f08c3bdfSopenharmony_ci		sum += *packetPtr++;
421f08c3bdfSopenharmony_ci	}
422f08c3bdfSopenharmony_ci
423f08c3bdfSopenharmony_ci	if (len == 1) {
424f08c3bdfSopenharmony_ci		sum += *(unsigned char *)packetPtr;
425f08c3bdfSopenharmony_ci	}
426f08c3bdfSopenharmony_ci
427f08c3bdfSopenharmony_ci	sum = (sum >> 16) + (sum & 0xFFFF);
428f08c3bdfSopenharmony_ci	sum += (sum >> 16);
429f08c3bdfSopenharmony_ci
430f08c3bdfSopenharmony_ci	result = ~sum;
431f08c3bdfSopenharmony_ci
432f08c3bdfSopenharmony_ci	return result;
433f08c3bdfSopenharmony_ci}
434f08c3bdfSopenharmony_ci
435f08c3bdfSopenharmony_ci/*****************************************************************
436f08c3bdfSopenharmony_ci* Function: output_to_display - Output to display info. from the
437f08c3bdfSopenharmony_ci*                               listener
438f08c3bdfSopenharmony_ci******************************************************************/
439f08c3bdfSopenharmony_civoid output_to_display(void *netPacket, int bytes, int pid)
440f08c3bdfSopenharmony_ci{
441f08c3bdfSopenharmony_ci
442f08c3bdfSopenharmony_ci	int i;
443f08c3bdfSopenharmony_ci	struct iphdr *ip = netPacket;
444f08c3bdfSopenharmony_ci	struct icmphdr *icmpPtr = netPacket + ip->ihl * 4;
445f08c3bdfSopenharmony_ci	struct in_addr tmp_addr;
446f08c3bdfSopenharmony_ci
447f08c3bdfSopenharmony_ci	printf
448f08c3bdfSopenharmony_ci	    ("\n************** -- Ping Tests - **********************************************\n");
449f08c3bdfSopenharmony_ci
450f08c3bdfSopenharmony_ci	for (i = 0; i < bytes; i++) {
451f08c3bdfSopenharmony_ci		if (!(i & 15)) {
452f08c3bdfSopenharmony_ci			printf("\n[%d]:  ", i);
453f08c3bdfSopenharmony_ci		}
454f08c3bdfSopenharmony_ci
455f08c3bdfSopenharmony_ci		printf("[%d] ", ((unsigned char *)netPacket)[i]);
456f08c3bdfSopenharmony_ci	}
457f08c3bdfSopenharmony_ci
458f08c3bdfSopenharmony_ci	printf("\n");
459f08c3bdfSopenharmony_ci
460f08c3bdfSopenharmony_ci	tmp_addr.s_addr = ip->saddr;
461f08c3bdfSopenharmony_ci
462f08c3bdfSopenharmony_ci	printf("IPv%d: hdr-size=%d pkt-size=%d protocol=%d TTL=%d src=%s ",
463f08c3bdfSopenharmony_ci	       ip->version, ip->ihl * 4, ntohs(ip->tot_len), ip->protocol,
464f08c3bdfSopenharmony_ci	       ip->ttl, inet_ntoa(tmp_addr));
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci	tmp_addr.s_addr = ip->daddr;
467f08c3bdfSopenharmony_ci	printf("dst=%s\n", inet_ntoa(tmp_addr));
468f08c3bdfSopenharmony_ci
469f08c3bdfSopenharmony_ci	if (icmpPtr->un.echo.id == pid) {
470f08c3bdfSopenharmony_ci
471f08c3bdfSopenharmony_ci		printf("ICMP: type[%d/%d] checksum[%d] id[%d] seq[%d]\n\n",
472f08c3bdfSopenharmony_ci		       icmpPtr->type, icmpPtr->code, ntohs(icmpPtr->checksum),
473f08c3bdfSopenharmony_ci		       icmpPtr->un.echo.id, icmpPtr->un.echo.sequence);
474f08c3bdfSopenharmony_ci
475f08c3bdfSopenharmony_ci	}
476f08c3bdfSopenharmony_ci}
477f08c3bdfSopenharmony_ci
478f08c3bdfSopenharmony_ci/***********************************************************************
479f08c3bdfSopenharmony_ci* Function: ping_network - Build a message and send it.
480f08c3bdfSopenharmony_ci*
481f08c3bdfSopenharmony_ci*
482f08c3bdfSopenharmony_ci***********************************************************************/
483f08c3bdfSopenharmony_civoid ping_network(struct sockaddr_in *rawAddr, int pid)
484f08c3bdfSopenharmony_ci{
485f08c3bdfSopenharmony_ci
486f08c3bdfSopenharmony_ci	const int value = TIMETOLIVE;
487f08c3bdfSopenharmony_ci	int i, rawSocket, count = 1;
488f08c3bdfSopenharmony_ci
489f08c3bdfSopenharmony_ci	struct packet rawPacket;
490f08c3bdfSopenharmony_ci
491f08c3bdfSopenharmony_ci	struct sockaddr_in r_addr;
492f08c3bdfSopenharmony_ci
493f08c3bdfSopenharmony_ci	rawSocket = socket(PF_INET, SOCK_RAW, protocol->p_proto);
494f08c3bdfSopenharmony_ci
495f08c3bdfSopenharmony_ci	if (rawSocket < 0) {
496f08c3bdfSopenharmony_ci		printf("Error: cannot open RAW socket %d\n", rawSocket);
497f08c3bdfSopenharmony_ci		return;
498f08c3bdfSopenharmony_ci	}
499f08c3bdfSopenharmony_ci
500f08c3bdfSopenharmony_ci	if (setsockopt(rawSocket, SOL_IP, IP_TTL, &value, sizeof(value)) != 0) {
501f08c3bdfSopenharmony_ci		printf("ERROR: Setting TimeToLive option");
502f08c3bdfSopenharmony_ci	} else {
503f08c3bdfSopenharmony_ci		printf
504f08c3bdfSopenharmony_ci		    ("The test will run for [%d] iterations -- Ctrl-C to interupt \n",
505f08c3bdfSopenharmony_ci		     value);
506f08c3bdfSopenharmony_ci		sleep(3);
507f08c3bdfSopenharmony_ci	}
508f08c3bdfSopenharmony_ci
509f08c3bdfSopenharmony_ci	if (fcntl(rawSocket, F_SETFL, O_NONBLOCK) != 0) {
510f08c3bdfSopenharmony_ci		printf("ERROR: Failed request nonblocking I/O");
511f08c3bdfSopenharmony_ci	}
512f08c3bdfSopenharmony_ci
513f08c3bdfSopenharmony_ci	while (1) {
514f08c3bdfSopenharmony_ci
515f08c3bdfSopenharmony_ci		socklen_t msgLength = sizeof(r_addr);
516f08c3bdfSopenharmony_ci
517f08c3bdfSopenharmony_ci		printf("Message ID #:%d \n", count);
518f08c3bdfSopenharmony_ci
519f08c3bdfSopenharmony_ci		if (recvfrom
520f08c3bdfSopenharmony_ci		    (rawSocket, &rawPacket, sizeof(rawPacket), 0,
521f08c3bdfSopenharmony_ci		     (struct sockaddr *)&r_addr, &msgLength) > 0) {
522f08c3bdfSopenharmony_ci			printf("*** -- Message Received -- ***\n");
523f08c3bdfSopenharmony_ci		}
524f08c3bdfSopenharmony_ci
525f08c3bdfSopenharmony_ci		memset(&rawPacket, 0, sizeof(rawPacket));
526f08c3bdfSopenharmony_ci
527f08c3bdfSopenharmony_ci		rawPacket.hdr.type = ICMP_ECHO;
528f08c3bdfSopenharmony_ci		rawPacket.hdr.un.echo.id = pid;
529f08c3bdfSopenharmony_ci
530f08c3bdfSopenharmony_ci		for (i = 0; i < sizeof(rawPacket.msg) - 1; i++) {
531f08c3bdfSopenharmony_ci			rawPacket.msg[i] = i + '0';
532f08c3bdfSopenharmony_ci		}
533f08c3bdfSopenharmony_ci
534f08c3bdfSopenharmony_ci		rawPacket.msg[i] = 0;
535f08c3bdfSopenharmony_ci		rawPacket.hdr.un.echo.sequence = count++;
536f08c3bdfSopenharmony_ci		rawPacket.hdr.checksum =
537f08c3bdfSopenharmony_ci		    checksum(&rawPacket, sizeof(rawPacket));
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_ci		if (sendto
540f08c3bdfSopenharmony_ci		    (rawSocket, &rawPacket, sizeof(rawPacket), 0,
541f08c3bdfSopenharmony_ci		     (struct sockaddr *)rawAddr, sizeof(*rawAddr)) <= 0)
542f08c3bdfSopenharmony_ci			printf("ERROR: sendto failed !!");
543f08c3bdfSopenharmony_ci
544f08c3bdfSopenharmony_ci		sleep(1);
545f08c3bdfSopenharmony_ci
546f08c3bdfSopenharmony_ci		if (value == count) {
547f08c3bdfSopenharmony_ci			printf("Exiting ping test...\n");
548f08c3bdfSopenharmony_ci			break;
549f08c3bdfSopenharmony_ci		}
550f08c3bdfSopenharmony_ci	}
551f08c3bdfSopenharmony_ci
552f08c3bdfSopenharmony_ci	close(rawSocket);
553f08c3bdfSopenharmony_ci}
554f08c3bdfSopenharmony_ci
555f08c3bdfSopenharmony_ci/**********************************************************************
556f08c3bdfSopenharmony_ci*  Function: ltp_traceroute
557f08c3bdfSopenharmony_ci*                      try to reach the destination
558f08c3bdfSopenharmony_ci*                      while outputting hops along the route
559f08c3bdfSopenharmony_ci***********************************************************************/
560f08c3bdfSopenharmony_civoid ltp_traceroute(struct sockaddr_in *rawTraceAddr, char *hostName, int pid)
561f08c3bdfSopenharmony_ci{
562f08c3bdfSopenharmony_ci
563f08c3bdfSopenharmony_ci	const int flag = TRUE;
564f08c3bdfSopenharmony_ci	int TimeToLive = 0;
565f08c3bdfSopenharmony_ci	int i, rawTraceSocket, count = 1;
566f08c3bdfSopenharmony_ci	socklen_t length;
567f08c3bdfSopenharmony_ci	struct packet rawTracePacket;
568f08c3bdfSopenharmony_ci	unsigned char tracePacket[PACKET_LEN];
569f08c3bdfSopenharmony_ci	struct sockaddr_in rawReceiveAddr;
570f08c3bdfSopenharmony_ci	struct hostent *hostEntry2;
571f08c3bdfSopenharmony_ci	struct in_addr tmp_addr;
572f08c3bdfSopenharmony_ci
573f08c3bdfSopenharmony_ci	printf
574f08c3bdfSopenharmony_ci	    ("\n************** -- Trace Route Tests - **********************************************\n");
575f08c3bdfSopenharmony_ci
576f08c3bdfSopenharmony_ci	rawTraceSocket = socket(PF_INET, SOCK_RAW, protocol->p_proto);
577f08c3bdfSopenharmony_ci
578f08c3bdfSopenharmony_ci	if (rawTraceSocket < 0) {
579f08c3bdfSopenharmony_ci		printf("Error: cannot open RAW socket %d\n", rawTraceSocket);
580f08c3bdfSopenharmony_ci		return;
581f08c3bdfSopenharmony_ci	}
582f08c3bdfSopenharmony_ci
583f08c3bdfSopenharmony_ci	if (setsockopt(rawTraceSocket, SOL_IP, SO_ERROR, &flag, sizeof(flag)) !=
584f08c3bdfSopenharmony_ci	    0)
585f08c3bdfSopenharmony_ci		printf("ERROR: Setting socket options");
586f08c3bdfSopenharmony_ci
587f08c3bdfSopenharmony_ci	do {
588f08c3bdfSopenharmony_ci		struct iphdr *ip;
589f08c3bdfSopenharmony_ci		length = sizeof(rawReceiveAddr);
590f08c3bdfSopenharmony_ci
591f08c3bdfSopenharmony_ci		TimeToLive++;
592f08c3bdfSopenharmony_ci		if (setsockopt
593f08c3bdfSopenharmony_ci		    (rawTraceSocket, SOL_IP, IP_TTL, &TimeToLive,
594f08c3bdfSopenharmony_ci		     sizeof(TimeToLive)) != 0) {
595f08c3bdfSopenharmony_ci			printf("ERROR: Setting TimeToLive option");
596f08c3bdfSopenharmony_ci		}
597f08c3bdfSopenharmony_ci
598f08c3bdfSopenharmony_ci		memset(&rawTracePacket, 0, sizeof(rawTracePacket));
599f08c3bdfSopenharmony_ci
600f08c3bdfSopenharmony_ci		rawTracePacket.hdr.type = ICMP_ECHO;
601f08c3bdfSopenharmony_ci		rawTracePacket.hdr.un.echo.id = pid;
602f08c3bdfSopenharmony_ci
603f08c3bdfSopenharmony_ci		for (i = 0; i < sizeof(rawTracePacket.msg) - 1; i++) {
604f08c3bdfSopenharmony_ci			rawTracePacket.msg[i] = i + '0';
605f08c3bdfSopenharmony_ci		}
606f08c3bdfSopenharmony_ci
607f08c3bdfSopenharmony_ci		rawTracePacket.msg[i] = 0;
608f08c3bdfSopenharmony_ci		rawTracePacket.hdr.un.echo.sequence = count++;
609f08c3bdfSopenharmony_ci		rawTracePacket.hdr.checksum =
610f08c3bdfSopenharmony_ci		    checksum(&rawTracePacket, sizeof(rawTracePacket));
611f08c3bdfSopenharmony_ci
612f08c3bdfSopenharmony_ci		if (sendto
613f08c3bdfSopenharmony_ci		    (rawTraceSocket, &rawTracePacket, sizeof(rawTracePacket), 0,
614f08c3bdfSopenharmony_ci		     (struct sockaddr *)rawTraceAddr,
615f08c3bdfSopenharmony_ci		     sizeof(*rawTraceAddr)) <= 0) {
616f08c3bdfSopenharmony_ci			printf("ERROR: sendto failed !!");
617f08c3bdfSopenharmony_ci		}
618f08c3bdfSopenharmony_ci		sleep(1);
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_ci		if (recvfrom
621f08c3bdfSopenharmony_ci		    (rawTraceSocket, tracePacket, sizeof(tracePacket),
622f08c3bdfSopenharmony_ci		     MSG_DONTWAIT, (struct sockaddr *)&rawReceiveAddr,
623f08c3bdfSopenharmony_ci		     &length) > 0) {
624f08c3bdfSopenharmony_ci			ip = (void *)tracePacket;
625f08c3bdfSopenharmony_ci
626f08c3bdfSopenharmony_ci			tmp_addr.s_addr = ip->saddr;
627f08c3bdfSopenharmony_ci			printf("Host IP:#%d: %s \n", count - 1,
628f08c3bdfSopenharmony_ci			       inet_ntoa(tmp_addr));
629f08c3bdfSopenharmony_ci
630f08c3bdfSopenharmony_ci			hostEntry2 =
631f08c3bdfSopenharmony_ci			    gethostbyaddr((void *)&rawReceiveAddr, length,
632f08c3bdfSopenharmony_ci					  rawReceiveAddr.sin_family);
633f08c3bdfSopenharmony_ci
634f08c3bdfSopenharmony_ci			if (hostEntry2 != NULL)
635f08c3bdfSopenharmony_ci				printf("(%s)\n", hostEntry2->h_name);
636f08c3bdfSopenharmony_ci			else
637f08c3bdfSopenharmony_ci				perror("Name: ");
638f08c3bdfSopenharmony_ci		} else {
639f08c3bdfSopenharmony_ci			printf("%s : data send complete...\n", hostName);
640f08c3bdfSopenharmony_ci			break;
641f08c3bdfSopenharmony_ci		}
642f08c3bdfSopenharmony_ci
643f08c3bdfSopenharmony_ci	}
644f08c3bdfSopenharmony_ci	while (rawReceiveAddr.sin_addr.s_addr != rawTraceAddr->sin_addr.s_addr);
645f08c3bdfSopenharmony_ci
646f08c3bdfSopenharmony_ci	printf
647f08c3bdfSopenharmony_ci	    ("\n************** -- End Trace Route Tests - ******************************************\n");
648f08c3bdfSopenharmony_ci
649f08c3bdfSopenharmony_ci	close(rawTraceSocket);
650f08c3bdfSopenharmony_ci}
651