root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/ping.c

Revision 12368, 8.0 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

Line 
1 //==========================================================================
2 //
3 //      ping.c
4 //
5 //      Network utility - ping
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    gthomas
45 // Contributors: gthomas
46 // Date:         2001-01-22
47 // Purpose:     
48 // Description: 
49 //             
50 // This code is part of RedBoot (tm).
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <redboot.h>
57 #include <net/net.h>
58
59 #ifndef CYGPKG_REDBOOT_NETWORKING
60 #error CYGPKG_REDBOOT_NETWORKING required!
61 #else
62
63 static void do_ping(int argc, char *argv[]);
64 RedBoot_cmd("ping",
65             "Network connectivity test",
66             "[-v] [-n <count>] [-l <length>] [-t <timeout>] [-r <rate>]\n"
67             "        [-i <IP_addr>] -h <IP_addr>", do_ping);
68
69 static bool icmp_received;
70 static icmp_header_t hold_hdr;
71
72 static void handle_icmp(pktbuf_t * pkt, ip_route_t * src_route)
73 {
74         icmp_header_t *icmp;
75         unsigned short cksum;
76
77         icmp = pkt->icmp_hdr;
78         if (icmp->type == ICMP_TYPE_ECHOREQUEST
79             && icmp->code == 0
80             && __sum((word *) icmp, pkt->pkt_bytes, 0) == 0) {
81
82                 icmp->type = ICMP_TYPE_ECHOREPLY;
83                 icmp->checksum = 0;
84                 cksum = __sum((word *) icmp, pkt->pkt_bytes, 0);
85                 icmp->checksum = htons(cksum);
86                 __ip_send(pkt, IP_PROTO_ICMP, src_route);
87         } else if (icmp->type == ICMP_TYPE_ECHOREPLY) {
88                 memcpy(&hold_hdr, icmp, sizeof(*icmp));
89                 icmp_received = true;
90         }
91 }
92
93 static void do_ping(int argc, char *argv[])
94 {
95         struct option_info opts[7];
96         long count, timeout, length, rate, start_time, end_time, timer,
97             received, tries;
98         char *local_ip_addr, *host_ip_addr;
99         bool local_ip_addr_set, host_ip_addr_set, count_set,
100             timeout_set, length_set, rate_set, verbose;
101         struct sockaddr_in local_addr, host_addr;
102         ip_addr_t hold_addr;
103         icmp_header_t *icmp;
104         pktbuf_t *pkt;
105         ip_header_t *ip;
106         unsigned short cksum;
107         ip_route_t dest_ip;
108
109         init_opts(&opts[0], 'n', true, OPTION_ARG_TYPE_NUM,
110                   (void *)&count, (bool *) & count_set,
111                   "<count> - number of packets to test");
112         init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM, (void *)&timeout,
113                   (bool *) & timeout_set,
114                   "<timeout> - max #ms per packet [rount trip]");
115         init_opts(&opts[2], 'i', true, OPTION_ARG_TYPE_STR,
116                   (void *)&local_ip_addr, (bool *) & local_ip_addr_set,
117                   "local IP address");
118         init_opts(&opts[3], 'h', true, OPTION_ARG_TYPE_STR,
119                   (void *)&host_ip_addr, (bool *) & host_ip_addr_set,
120                   "host name or IP address");
121         init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length,
122                   (bool *) & length_set, "<length> - size of payload");
123         init_opts(&opts[5], 'v', false, OPTION_ARG_TYPE_FLG, (void *)&verbose,
124                   (bool *) 0, "verbose operation");
125         init_opts(&opts[6], 'r', true, OPTION_ARG_TYPE_NUM, (void *)&rate,
126                   (bool *) & rate_set, "<rate> - time between packets");
127         if (!scan_opts(argc, argv, 1, opts, 7, (void **)0, 0, "")) {
128                 diag_printf("PING - Invalid option specified\n");
129                 return;
130         }
131         // Set defaults; this has to be done _after_ the scan, since it will
132         // have destroyed all values not explicitly set.
133         if (local_ip_addr_set) {
134                 if (!_gethostbyname(local_ip_addr, (in_addr_t *) & local_addr)) {
135                         diag_printf("PING - Invalid local name: %s\n",
136                                     local_ip_addr);
137                         return;
138                 }
139         } else {
140                 memcpy((in_addr_t *) & local_addr, __local_ip_addr,
141                        sizeof(__local_ip_addr));
142         }
143         if (host_ip_addr_set) {
144                 if (!_gethostbyname(host_ip_addr, (in_addr_t *) & host_addr)) {
145                         diag_printf("PING - Invalid host name: %s\n",
146                                     host_ip_addr);
147                         return;
148                 }
149                 if (__arp_lookup((ip_addr_t *) & host_addr.sin_addr, &dest_ip) <
150                     0) {
151                         diag_printf("PING: Cannot reach server '%s' (%s)\n",
152                                     host_ip_addr,
153                                     inet_ntoa((in_addr_t *) & host_addr));
154                         return;
155                 }
156         } else {
157                 diag_printf("PING - host name or IP address required\n");
158                 return;
159         }
160 #define DEFAULT_LENGTH   64
161 #define DEFAULT_COUNT    10
162 #define DEFAULT_TIMEOUT  1000
163 #define DEFAULT_RATE     1000
164         if (!rate_set) {
165                 rate = DEFAULT_RATE;
166         }
167         if (!length_set) {
168                 length = DEFAULT_LENGTH;
169         }
170         if ((length < 64) || (length > 1400)) {
171                 diag_printf("Invalid length specified: %ld\n", length);
172                 return;
173         }
174         if (!count_set) {
175                 count = DEFAULT_COUNT;
176         }
177         if (!timeout_set) {
178                 timeout = DEFAULT_TIMEOUT;
179         }
180         // Note: two prints here because 'inet_ntoa' returns a static pointer
181         diag_printf("Network PING - from %s",
182                     inet_ntoa((in_addr_t *) & local_addr));
183         diag_printf(" to %s\n", inet_ntoa((in_addr_t *) & host_addr));
184         received = 0;
185         __icmp_install_listener(handle_icmp);
186         // Save default "local" address
187         memcpy(hold_addr, __local_ip_addr, sizeof(hold_addr));
188         for (tries = 0; tries < count; tries++) {
189                 // The network stack uses the global variable '__local_ip_addr'
190                 memcpy(__local_ip_addr, &local_addr, sizeof(__local_ip_addr));
191                 // Build 'ping' request
192                 if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) {
193                         // Give up if no packets - something is wrong
194                         break;
195                 }
196
197                 icmp = pkt->icmp_hdr;
198                 ip = pkt->ip_hdr;
199                 pkt->pkt_bytes = length + sizeof(icmp_header_t);
200
201                 icmp->type = ICMP_TYPE_ECHOREQUEST;
202                 icmp->code = 0;
203                 icmp->checksum = 0;
204                 icmp->seqnum = htons(tries + 1);
205                 cksum = __sum((word *) icmp, pkt->pkt_bytes, 0);
206                 icmp->checksum = htons(cksum);
207
208                 memcpy(ip->source, (in_addr_t *) & local_addr,
209                        sizeof(ip_addr_t));
210                 memcpy(ip->destination, (in_addr_t *) & host_addr,
211                        sizeof(ip_addr_t));
212                 ip->protocol = IP_PROTO_ICMP;
213                 ip->length = htons(pkt->pkt_bytes);
214
215                 __ip_send(pkt, IP_PROTO_ICMP, &dest_ip);
216                 __pktbuf_free(pkt);
217
218                 start_time = MS_TICKS();
219                 timer = start_time + timeout;
220                 icmp_received = false;
221                 while (!icmp_received && (MS_TICKS_DELAY() < timer)) {
222                         if (_rb_break(1)) {
223                                 goto abort;
224                         }
225                         MS_TICKS_DELAY();
226                         __enet_poll();
227                 }
228                 end_time = MS_TICKS();
229
230                 timer = MS_TICKS() + rate;
231                 while (MS_TICKS_DELAY() < timer) {
232                         if (_rb_break(1)) {
233                                 goto abort;
234                         }
235                         MS_TICKS_DELAY();
236                         __enet_poll();
237                 }
238
239                 if (icmp_received) {
240                         received++;
241                         if (verbose) {
242                                 diag_printf(" seq: %ld, time: %ld (ticks)\n",
243                                             ntohs(hold_hdr.seqnum),
244                                             end_time - start_time);
245                         }
246                 }
247         }
248 abort:
249         __icmp_remove_listener();
250         // Clean up
251         memcpy(__local_ip_addr, &hold_addr, sizeof(__local_ip_addr));
252         // Report
253         diag_printf("PING - received %ld of %ld expected\n", received, count);
254 }
255
256 #endif                          //CYGPKG_REDBOOT_NETWORKING
Note: See TracBrowser for help on using the browser.