Contiki 3.x
ping6.c
1 /*
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that the following conditions
4  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * This file is part of the Contiki operating system.
27  *
28  */
29 
30 #include "contiki.h"
31 #include "contiki-lib.h"
32 #include "contiki-net.h"
33 
34 #include "mac.h"
35 
36 #include <string.h>
37 #include <stdio.h>
38 
39 #define MACDEBUG 0
40 
41 #define DEBUG 0
42 #if DEBUG
43 #include <stdio.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 ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_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])
47 #else
48 #define PRINTF(...)
49 #define PRINT6ADDR(addr)
50 #endif
51 
52 #define PING6_NB 5
53 #define PING6_DATALEN 16
54 
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])
57 
58 static struct etimer ping6_periodic_timer;
59 static uint8_t count = 0;
60 static char command[20];
61 static uint16_t addr[8];
62 uip_ipaddr_t dest_addr;
63 
64 PROCESS(ping6_process, "PING6 process");
65 AUTOSTART_PROCESSES(&ping6_process);
66 
67 
68 /*---------------------------------------------------------------------------*/
69 static uint8_t
70 ping6handler(process_event_t ev, process_data_t data)
71 {
72  if(count == 0){
73 #if MACDEBUG
74  // Setup destination address.
75  addr[0] = 0xFE80;
76  addr[4] = 0x6466;
77  addr[5] = 0x6666;
78  addr[6] = 0x6666;
79  addr[7] = 0x6666;
80  uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2],
81  addr[3],addr[4],addr[5],addr[6],addr[7]);
82 
83  // Set the command to fool the 'if' below.
84  memcpy(command, (void *)"ping6", 5);
85 
86 #else
87 /* prompt */
88  printf("> ");
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
91  */
92  scanf("%s", command);
93 
94  if(strcmp(command,"ping6") != 0){
95  PRINTF("> invalid command\n");
96  return 0;
97  }
98 
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){
102 
103  uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2],
104  addr[3],addr[4],addr[5],addr[6],addr[7]);
105  } else {
106  PRINTF("> invalid ipv6 address format\n");
107  return 0;
108  }
109 #endif
110 
111  }
112 
113  if((strcmp(command,"ping6") == 0) && (count < PING6_NB)){
114 
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);
122 
124  UIP_ICMP_BUF->icode = 0;
125  /* set identifier and sequence number to 0 */
126  memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4);
127  /* put one byte of data */
128  memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN,
129  count, PING6_DATALEN);
130 
131 
132  uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN;
133  UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8);
134  UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF);
135 
136  UIP_ICMP_BUF->icmpchksum = 0;
137  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
138 
139 
140  PRINTF("Sending Echo Request to");
141  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
142  PRINTF("from");
143  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
144  PRINTF("\n");
145  UIP_STAT(++uip_stat.icmp.sent);
146 
148 
149  count++;
150  etimer_set(&ping6_periodic_timer, 3 * CLOCK_SECOND);
151  return 1;
152  }
153  return 0;
154 }
155 
156 /*---------------------------------------------------------------------------*/
157 PROCESS_THREAD(ping6_process, ev, data)
158 {
159 
160  uint8_t cont = 1;
161 
162  PROCESS_BEGIN();
163  PRINTF("In Process PING6\n");
164  PRINTF("Wait for DAD\n");
165 
166  etimer_set(&ping6_periodic_timer, 15*CLOCK_SECOND);
167 
168  while(cont) {
169  PROCESS_YIELD();
170  cont = ping6handler(ev, data);
171  }
172 
173  PRINTF("END PING6\n");
174  PROCESS_END();
175 }
176 /*---------------------------------------------------------------------------*/
uip_len
The length of the packet in the uip_buf buffer.
Definition: tcp_loader.c:75
void tcpip_ipv6_output(void)
This function does address resolution and then calls tcpip_output.
Definition: tcpip.c:540
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define UIP_STAT(s)
The uIP TCP/IP statistics.
Definition: uip.h:1431
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define UIP_IP_BUF
Pointer to IP header.
Definition: uip-nd6.c:104
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
uint16_t uip_icmp6chksum(void)
Calculate the ICMP checksum of the packet in uip_buf.
Definition: uip6.c:387
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1026
#define ICMP6_ECHO_REQUEST
Echo request.
Definition: uip-icmp6.h:57
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
Definition: uip-ds6.c:497
#define UIP_ICMP_BUF
Pointer to ICMP header.
Definition: uip-nd6.c:105
#define PROCESS_YIELD()
Yield the currently running process.
Definition: process.h:164
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
Definition: uip.h:969
A timer.
Definition: etimer.h:76
MAC driver header file
#define UIP_ICMP6_ECHO_REQUEST_LEN
Echo Request constant part length.
Definition: uip-icmp6.h:99
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82