2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions
5 * 1. Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * 2. Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * 3. Neither the name of the Institute nor the names of its contributors
11 * may be used to endorse or promote products derived from this software
12 * without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * This file is part of the Contiki operating system.
31 #include "contiki-lib.h"
32 #include "contiki-net.h"
44 #define PRINTF(...) printf(__VA_ARGS__)
45 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
46 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
49 #define PRINT6ADDR(addr)
53 #define PING6_DATALEN 16
55 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
56 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
58 static struct etimer ping6_periodic_timer
;
59 static u8_t count
= 0;
60 static char command
[20];
62 uip_ipaddr_t dest_addr
;
64 PROCESS(ping6_process
, "PING6 process");
65 AUTOSTART_PROCESSES(&ping6_process
);
68 /*---------------------------------------------------------------------------*/
70 ping6handler(process_event_t ev
, process_data_t data
)
74 // Setup destination address.
80 uip_ip6addr(&dest_addr
, addr
[0], addr
[1],addr
[2],
81 addr
[3],addr
[4],addr
[5],addr
[6],addr
[7]);
83 // Set the command to fool the 'if' below.
84 memcpy(command
, (void *)"ping6", 5);
89 /** \note the scanf here is blocking (the all stack is blocked waiting
90 * for user input). This is far from ideal and could be improved
94 if(strcmp(command
,"ping6") != 0){
95 PRINTF("> invalid command\n");
99 if(scanf(" %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
100 &addr
[0],&addr
[1],&addr
[2],&addr
[3],
101 &addr
[4],&addr
[5],&addr
[6],&addr
[7]) == 8){
103 uip_ip6addr(&dest_addr
, addr
[0], addr
[1],addr
[2],
104 addr
[3],addr
[4],addr
[5],addr
[6],addr
[7]);
106 PRINTF("> invalid ipv6 address format\n");
113 if((strcmp(command
,"ping6") == 0) && (count
< PING6_NB
)){
115 UIP_IP_BUF
->vtc
= 0x60;
116 UIP_IP_BUF
->tcflow
= 1;
117 UIP_IP_BUF
->flow
= 0;
118 UIP_IP_BUF
->proto
= UIP_PROTO_ICMP6
;
119 UIP_IP_BUF
->ttl
= uip_ds6_if
.cur_hop_limit
;
120 uip_ipaddr_copy(&UIP_IP_BUF
->destipaddr
, &dest_addr
);
121 uip_ds6_select_src(&UIP_IP_BUF
->srcipaddr
, &UIP_IP_BUF
->destipaddr
);
123 UIP_ICMP_BUF
->type
= ICMP6_ECHO_REQUEST
;
124 UIP_ICMP_BUF
->icode
= 0;
125 /* set identifier and sequence number to 0 */
126 memset((void *)UIP_ICMP_BUF
+ UIP_ICMPH_LEN
, 0, 4);
127 /* put one byte of data */
128 memset((void *)UIP_ICMP_BUF
+ UIP_ICMPH_LEN
+ UIP_ICMP6_ECHO_REQUEST_LEN
,
129 count
, PING6_DATALEN
);
132 uip_len
= UIP_ICMPH_LEN
+ UIP_ICMP6_ECHO_REQUEST_LEN
+ UIP_IPH_LEN
+ PING6_DATALEN
;
133 UIP_IP_BUF
->len
[0] = (u8_t
)((uip_len
- 40) >> 8);
134 UIP_IP_BUF
->len
[1] = (u8_t
)((uip_len
- 40) & 0x00FF);
136 UIP_ICMP_BUF
->icmpchksum
= 0;
137 UIP_ICMP_BUF
->icmpchksum
= ~uip_icmp6chksum();
140 PRINTF("Sending Echo Request to");
141 PRINT6ADDR(&UIP_IP_BUF
->destipaddr
);
143 PRINT6ADDR(&UIP_IP_BUF
->srcipaddr
);
145 UIP_STAT(++uip_stat
.icmp
.sent
);
150 etimer_set(&ping6_periodic_timer
, 3 * CLOCK_SECOND
);
156 /*---------------------------------------------------------------------------*/
157 PROCESS_THREAD(ping6_process
, ev
, data
)
163 PRINTF("In Process PING6\n");
164 PRINTF("Wait for DAD\n");
166 etimer_set(&ping6_periodic_timer
, 15*CLOCK_SECOND
);
170 cont
= ping6handler(ev
, data
);
173 PRINTF("END PING6\n");
176 /*---------------------------------------------------------------------------*/