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,int alen)109 int ping(char *args_fs, int 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(0, 0, 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