2 * Copyright (c) 2004, Adam Dunkels.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * This file is part of the Contiki operating system.
31 * Author: Adam Dunkels <adam@sics.se>
33 * $Id: shell-ping.c,v 1.5 2010/10/19 18:29:03 adamdunkels Exp $
41 #include "contiki-net.h"
43 /*---------------------------------------------------------------------------*/
44 PROCESS(shell_ping_process
, "ping");
45 SHELL_COMMAND(ping_command
,
47 "ping <host>: ping an IP host",
49 /*---------------------------------------------------------------------------*/
51 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
52 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
53 #define PING_DATALEN 16
55 #define ICMP_ECHO_REPLY 0
58 #define ICMP6_ECHO_REPLY 129
59 #define ICMP6_ECHO 128
61 static uip_ipaddr_t remoteaddr
;
62 static unsigned char running
;
63 /*---------------------------------------------------------------------------*/
65 send_ping(uip_ipaddr_t
*dest_addr
)
68 static uint16_t count
;
69 UIP_IP_BUF
->vtc
= 0x60;
70 UIP_IP_BUF
->tcflow
= 1;
72 UIP_IP_BUF
->proto
= UIP_PROTO_ICMP6
;
73 UIP_IP_BUF
->ttl
= uip_ds6_if
.cur_hop_limit
;
74 uip_ipaddr_copy(&UIP_IP_BUF
->destipaddr
, dest_addr
);
75 uip_ds6_select_src(&UIP_IP_BUF
->srcipaddr
, &UIP_IP_BUF
->destipaddr
);
77 UIP_ICMP_BUF
->type
= ICMP6_ECHO_REQUEST
;
78 UIP_ICMP_BUF
->icode
= 0;
79 /* set identifier and sequence number to 0 */
80 memset((void *)UIP_ICMP_BUF
+ UIP_ICMPH_LEN
, 0, 4);
81 /* put one byte of data */
82 memset((void *)UIP_ICMP_BUF
+ UIP_ICMPH_LEN
+ UIP_ICMP6_ECHO_REQUEST_LEN
,
86 uip_len
= UIP_ICMPH_LEN
+ UIP_ICMP6_ECHO_REQUEST_LEN
+
87 UIP_IPH_LEN
+ PING_DATALEN
;
88 UIP_IP_BUF
->len
[0] = (u8_t
)((uip_len
- 40) >> 8);
89 UIP_IP_BUF
->len
[1] = (u8_t
)((uip_len
- 40) & 0x00ff);
91 UIP_ICMP_BUF
->icmpchksum
= 0;
92 UIP_ICMP_BUF
->icmpchksum
= ~uip_icmp6chksum();
96 #else /* UIP_CONF_IPV6 */
98 static uint16_t ipid
= 0;
99 static uint16_t seqno
= 0;
101 UIP_IP_BUF
->vhl
= 0x45;
103 UIP_IP_BUF
->ipoffset
[0] = UIP_IP_BUF
->ipoffset
[1] = 0;
105 UIP_IP_BUF
->ipid
[0] = ipid
>> 8;
106 UIP_IP_BUF
->ipid
[1] = ipid
& 0xff;
107 UIP_IP_BUF
->proto
= UIP_PROTO_ICMP
;
108 UIP_IP_BUF
->ttl
= UIP_TTL
;
110 uip_ipaddr_copy(&UIP_IP_BUF
->destipaddr
, dest_addr
);
111 uip_ipaddr_copy(&UIP_IP_BUF
->srcipaddr
, &uip_hostaddr
);
113 UIP_ICMP_BUF
->type
= ICMP_ECHO
;
114 UIP_ICMP_BUF
->icode
= 0;
115 UIP_ICMP_BUF
->id
= 0xadad;
116 UIP_ICMP_BUF
->seqno
= uip_htons(seqno
++);
118 uip_len
= UIP_ICMPH_LEN
+ UIP_IPH_LEN
+ PING_DATALEN
;
119 UIP_IP_BUF
->len
[0] = (u8_t
)((uip_len
) >> 8);
120 UIP_IP_BUF
->len
[1] = (u8_t
)((uip_len
) & 0x00ff);
122 UIP_ICMP_BUF
->icmpchksum
= 0;
123 UIP_ICMP_BUF
->icmpchksum
= ~uip_chksum((u16_t
*)&(UIP_ICMP_BUF
->type
),
124 UIP_ICMPH_LEN
+ PING_DATALEN
);
126 /* Calculate IP checksum. */
127 UIP_IP_BUF
->ipchksum
= 0;
128 UIP_IP_BUF
->ipchksum
= ~(uip_ipchksum());
132 #endif /* UIP_CONF_IPV6 */
133 /*---------------------------------------------------------------------------*/
134 PROCESS_THREAD(shell_ping_process
, ev
, data
)
136 struct shell_input
*input
;
141 shell_output_str(&ping_command
,
142 "ping <server>: server as address", "");
145 uiplib_ipaddrconv(data
, &remoteaddr
);
147 send_ping(&remoteaddr
);
152 static struct etimer e
;
155 etimer_set(&e
, CLOCK_SECOND
* 10);
157 PROCESS_WAIT_EVENT();
159 if(etimer_expired(&e
)) {
163 if(ev
== shell_event_input
) {
165 if(input
->len1
+ input
->len2
== 0) {
169 } else if(ev
== resolv_event_found
) {
170 /* Either found a hostname, or not. */
171 if((char *)data
!= NULL
&&
172 resolv_lookup((char *)data
) != NULL
) {
173 uip_ipaddr_copy(serveraddr
, ipaddr
);
174 telnet_connect(&s
, server
, serveraddr
, nick
);
176 shell_output_str(&ping_command
, "Host not found.", "");
184 /*---------------------------------------------------------------------------*/
186 shell_ping_init(void)
188 shell_register_command(&ping_command
);
190 /*---------------------------------------------------------------------------*/