1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 
13 #include <unistd.h>
14 #include <ipv4.h>
15 #include <dhcp.h>
16 #include <ethernet.h>
17 #include <sys/socket.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include "args.h"
23 #include "netapps.h"
24 
25 struct ping_args {
26 	union {
27 		char string[4];
28 		unsigned int integer;
29 	} server_ip;
30 	union {
31 		char string[4];
32 		unsigned int integer;
33 	} client_ip;
34 	union {
35 		char string[4];
36 		unsigned int integer;
37 	} gateway_ip;
38 	unsigned int timeout;
39 	unsigned int netmask;
40 };
41 
42 static void
usage(void)43 usage(void)
44 {
45 	printf
46 	    ("\nping device-path:[device-args,]server-ip,[client-ip[\\nn]],[gateway-ip][,timeout]\n");
47 
48 }
49 
50 static int
parse_args(const char * args,struct ping_args * ping_args)51 parse_args(const char *args, struct ping_args *ping_args)
52 {
53 	unsigned int argc = get_args_count(args);
54 	char buf[64];
55 	ping_args->timeout = 10;
56 	if (argc == 0)
57 		/* at least server-ip has to be specified */
58 		return -1;
59 	if (argc == 1) {
60 		/* probably only server ip is specified */
61 		argncpy(args, 0, buf, 64);
62 		if (!strtoip(buf, ping_args->server_ip.string))
63 			return -1;
64 		return 0;
65 	}
66 	/* get first option from list */
67 	argncpy(args, 0, buf, 64);
68 	if (!strtoip(buf, ping_args->server_ip.string)) {
69 		/* it is not an IP address
70 		 * therefore it has to be device-args
71 		 * device-args are not supported and just ignored */
72 		args = get_arg_ptr(args, 1);
73 		argc--;
74 	}
75 
76 	argncpy(args, 0, buf, 64);
77 	if (!strtoip(buf, ping_args->server_ip.string)) {
78 		/* this should have been the server IP address */
79 		return -1;
80 	} else {
81 		args = get_arg_ptr(args, 1);
82 		if (!--argc)
83 			return 0;
84 	}
85 
86 	argncpy(args, 0, buf, 64);
87 	if (!strtoip_netmask(buf, ping_args->client_ip.string, &ping_args->netmask)) {
88 		/* this should have been the client (our) IP address */
89 		return -1;
90 	} else {
91 		args = get_arg_ptr(args, 1);
92 		if (!--argc)
93 			return 0;
94 	}
95 	argncpy(args, 0, buf, 64);
96 	if (!strtoip(buf, ping_args->gateway_ip.string)) {
97 		/* this should have been the gateway IP address */
98 		return -1;
99 	} else {
100 		args = get_arg_ptr(args, 1);
101 		if (!--argc)
102 			return 0;
103 	}
104 	argncpy(args, 0, buf, 64);
105 	ping_args->timeout = strtol(args, 0, 10);
106 	return 0;
107 }
108 
ping(char * args_fs,unsigned alen)109 int ping(char *args_fs, unsigned alen)
110 {
111 	short arp_failed = 0;
112 	filename_ip_t fn_ip;
113 	int fd_device;
114 	struct ping_args ping_args;
115 	uint8_t own_mac[6];
116 	uint32_t netmask;
117 	char args[256];
118 	int ret = -1;
119 
120 	memset(&ping_args, 0, sizeof(struct ping_args));
121 
122 	if (alen == 0 || alen >= sizeof(args) - 1) {
123 		usage();
124 		return -1;
125 	}
126 
127 	/* Convert forth string into NUL-terminated C-string */
128 	memcpy(args, args_fs, alen);
129 	args[alen] = 0;
130 
131 	if (parse_args(args, &ping_args)) {
132 		usage();
133 		return -1;
134 	}
135 
136 	memset(&fn_ip, 0, sizeof(filename_ip_t));
137 
138 	/* Get mac_addr from device */
139 	printf("\n  Reading MAC address from device: ");
140 	fd_device = socket(AF_INET, SOCK_DGRAM, 0, (char *) own_mac);
141 	if (fd_device == -1) {
142 		printf("\nE3000: Could not read MAC address\n");
143 		return -100;
144 	} else if (fd_device == -2) {
145 		printf("\nE3006: Could not initialize network device\n");
146 		return -101;
147 	}
148 
149 	fn_ip.fd = fd_device;
150 
151 	printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
152 	       own_mac[0], own_mac[1], own_mac[2],
153 	       own_mac[3], own_mac[4], own_mac[5]);
154 
155 	// init ethernet layer
156 	set_mac_address(own_mac);
157 	// identify the BOOTP/DHCP server via broadcasts
158 	// don't do this, when using DHCP !!!
159 	//  fn_ip.server_ip = 0xFFFFFFFF;
160 	//  memset(fn_ip.server_mac, 0xff, 6);
161 
162 	if (!ping_args.client_ip.integer) {
163 		/* Get ip address for our mac address */
164 		arp_failed = dhcp(0, &fn_ip, 30, F_IPV4);
165 
166 		if (arp_failed == -1) {
167 			printf("\n  DHCP: Could not get ip address\n");
168 			goto free_out;
169 		}
170 
171 	} else {
172 		memcpy(&fn_ip.own_ip, &ping_args.client_ip.integer, 4);
173 		if (ping_args.gateway_ip.integer)
174 			set_ipv4_router(ping_args.gateway_ip.integer);
175 		if (!ping_args.netmask) {
176 			/* Netmask is not provided, assume default according to
177 			 * the network class
178 			 */
179 			ping_args.netmask = get_default_ipv4_netmask(ping_args.client_ip.string);
180 		}
181 		set_ipv4_netmask(ping_args.netmask);
182 
183 		arp_failed = 1;
184 	}
185 
186 	// reinit network stack
187 	set_ipv4_address(fn_ip.own_ip);
188 
189 	printf("  Own IP address: %d.%d.%d.%d\n",
190 	       ((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF),
191 	       ((fn_ip.own_ip >> 8) & 0xFF), (fn_ip.own_ip & 0xFF));
192 
193 	netmask = get_ipv4_netmask();
194 	if (netmask) {
195 		printf("  Netmask : ");
196 		printf("%d.%d.%d.%d\n", ((netmask >> 24) & 0xFF), ((netmask >> 16) & 0xFF),
197 		       ((netmask >> 8) & 0xFF), (netmask & 0xFF));
198 	}
199 
200 	memcpy(&fn_ip.server_ip, &ping_args.server_ip.integer, 4);
201 	printf("  Ping to %d.%d.%d.%d ", ((fn_ip.server_ip >> 24) & 0xFF),
202 	       ((fn_ip.server_ip >> 16) & 0xFF),
203 	       ((fn_ip.server_ip >> 8) & 0xFF), (fn_ip.server_ip & 0xFF));
204 
205 
206 	ping_ipv4(fd_device, fn_ip.server_ip);
207 
208 	set_timer(TICKS_SEC / 10 * ping_args.timeout);
209 	while(get_timer() > 0) {
210 		receive_ether(fd_device);
211 		if(pong_ipv4() == 0) {
212 			printf("success\n");
213 			ret = 0;
214 			goto free_out;
215 		}
216 	}
217 
218 	printf("failed\n");
219 free_out:
220 	free(fn_ip.pl_cfgfile);
221 	free(fn_ip.pl_prefix);
222 	close(fn_ip.fd);
223 
224 	return ret;
225 }
226