Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2002, Adam Dunkels. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above 00011 * copyright notice, this list of conditions and the following 00012 * disclaimer in the documentation and/or other materials provided 00013 * with the distribution. 00014 * 3. The name of the author may not be used to endorse or promote 00015 * products derived from this software without specific prior 00016 * written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00019 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00020 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00022 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00023 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00024 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * This file is part of the Contiki OS 00031 * 00032 * 00033 */ 00034 00035 #include <stdio.h> 00036 #include <time.h> 00037 #include <sys/select.h> 00038 #include <unistd.h> 00039 #include <memory.h> 00040 00041 #include "contiki.h" 00042 #include "contiki-net.h" 00043 00044 #include "dev/serial-line.h" 00045 00046 #include "net/uip.h" 00047 #ifdef __CYGWIN__ 00048 #include "net/wpcap-drv.h" 00049 #else /* __CYGWIN__ */ 00050 #include "net/tapdev-drv.h" 00051 #endif /* __CYGWIN__ */ 00052 00053 #ifdef __CYGWIN__ 00054 PROCINIT(&etimer_process, &tcpip_process, &wpcap_process, &serial_line_process); 00055 #else /* __CYGWIN__ */ 00056 PROCINIT(&etimer_process, &tapdev_process, &tcpip_process, &serial_line_process); 00057 #endif /* __CYGWIN__ */ 00058 00059 #if RPL_BORDER_ROUTER 00060 #include "net/rpl/rpl.h" 00061 00062 static uint16_t dag_id[] = {0x1111, 0x1100, 0, 0, 0, 0, 0, 0x0011}; 00063 00064 PROCESS(border_router_process, "RPL Border Router"); 00065 PROCESS_THREAD(border_router_process, ev, data) 00066 { 00067 00068 PROCESS_BEGIN(); 00069 00070 PROCESS_PAUSE(); 00071 00072 { 00073 rpl_dag_t *dag; 00074 char buf[sizeof(dag_id)]; 00075 memcpy(buf,dag_id,sizeof(dag_id)); 00076 dag = rpl_set_root((uip_ip6addr_t *)buf); 00077 00078 /* Assign separate addresses to the uip stack and the host network 00079 interface, but with the same prefix E.g. bbbb::ff:fe00:200 to 00080 the stack and bbbb::1 to the host *fallback* network interface 00081 Otherwise the host will trap packets intended for the stack, 00082 just as the stack will trap packets intended for the host 00083 $ifconfig usb0 -arp on Ubuntu to skip the neighbor 00084 solicitations. Add explicit neighbors on other OSs */ 00085 00086 if(dag != NULL) { 00087 printf("Created a new RPL dag\n"); 00088 00089 #if UIP_CONF_ROUTER_RECEIVE_RA 00090 /* Contiki stack will shut down until assigned an address from the 00091 interface RA Currently this requires changes in the core 00092 rpl-icmp6.c to pass the link-local RA broadcast. 00093 */ 00094 00095 #else 00096 { 00097 static void sprint_ip6(uip_ip6addr_t addr); 00098 int i; 00099 uip_ip6addr_t ipaddr; 00100 #ifdef HARD_CODED_ADDRESS 00101 uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); 00102 #else 00103 uip_ip6addr(&ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1); 00104 #endif 00105 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 00106 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 00107 rpl_set_prefix(dag, &ipaddr, 64); 00108 00109 for(i = 0; i < UIP_DS6_ADDR_NB; i++) { 00110 if(uip_ds6_if.addr_list[i].isused) { 00111 printf("IPV6 Address: "); 00112 sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); 00113 printf("\n"); 00114 } 00115 } 00116 } 00117 #endif 00118 } 00119 } 00120 /* The border router runs with a 100% duty cycle in order to ensure high 00121 packet reception rates. */ 00122 /* NETSTACK_MAC.off(1); */ 00123 00124 while(1) { 00125 PROCESS_YIELD(); 00126 /* Local and global dag repair can be done from ? */ 00127 /* rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64); 00128 rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); */ 00129 } 00130 00131 PROCESS_END(); 00132 } 00133 #endif /* RPL_BORDER_ROUTER */ 00134 00135 #if UIP_CONF_IPV6 00136 /*---------------------------------------------------------------------------*/ 00137 static void 00138 sprint_ip6(uip_ip6addr_t addr) 00139 { 00140 unsigned char i = 0; 00141 unsigned char zerocnt = 0; 00142 unsigned char numprinted = 0; 00143 unsigned char notskipped = 0; 00144 char thestring[40]; 00145 char *result = thestring; 00146 00147 *result++ = '['; 00148 while(numprinted < 8) { 00149 if((addr.u16[i] == 0) && (zerocnt == 0)) { 00150 while(addr.u16[zerocnt + i] == 0) { 00151 zerocnt++; 00152 } 00153 if(zerocnt == 1 && notskipped) { 00154 *result++ = '0'; 00155 numprinted++; 00156 notskipped = 1; 00157 continue; 00158 } 00159 i += zerocnt; 00160 numprinted += zerocnt; 00161 } else { 00162 result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i]))); 00163 i++; 00164 numprinted++; 00165 } 00166 if(numprinted != 8) { 00167 *result++ = ':'; 00168 } 00169 } 00170 *result++=']'; 00171 *result=0; 00172 printf("%s", thestring); 00173 } 00174 #endif /* UIP_CONF_IPV6 */ 00175 /*---------------------------------------------------------------------------*/ 00176 int 00177 main(void) 00178 { 00179 clock_init(); 00180 #if UIP_CONF_IPV6 00181 /* A hard coded address overrides the stack default MAC address to 00182 allow multiple instances. uip6.c defines it as 00183 {0x00,0x06,0x98,0x00,0x02,0x32} giving an ipv6 address of 00184 [fe80::206:98ff:fe00:232] We make it simpler, {0x02,0x00,0x00 + the 00185 last three bytes of the hard coded address (if any are nonzero). 00186 HARD_CODED_ADDRESS can be defined in the contiki-conf.h file, or 00187 here to allow quick builds using different addresses. If 00188 HARD_CODED_ADDRESS has a prefix it also applied, unless built as a 00189 RPL end node. E.g. bbbb::12:3456 becomes fe80::ff:fe12:3456 and 00190 prefix bbbb::/64 if non-RPL ::10 becomes fe80::ff:fe00:10 and 00191 prefix awaits RA or RPL formation bbbb:: gives an address of 00192 bbbb::206:98ff:fe00:232 if non-RPL */ 00193 #ifdef HARD_CODED_ADDRESS 00194 { 00195 uip_ipaddr_t ipaddr; 00196 uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); 00197 if((ipaddr.u8[13] != 0) || 00198 (ipaddr.u8[14] != 0) || 00199 (ipaddr.u8[15] != 0)) { 00200 if(sizeof(uip_lladdr) == 6) { /* Minimal-net uses ethernet MAC */ 00201 uip_lladdr.addr[0] = 0x02; 00202 uip_lladdr.addr[1] = 0; 00203 uip_lladdr.addr[2] = 0; 00204 uip_lladdr.addr[3] = ipaddr.u8[13]; 00205 uip_lladdr.addr[4] = ipaddr.u8[14]; 00206 uip_lladdr.addr[5] = ipaddr.u8[15]; 00207 } 00208 } 00209 } 00210 #endif /* HARD_CODED_ADDRESS */ 00211 #endif /* UIP_CONF_IPV6 */ 00212 00213 process_init(); 00214 /* procinit_init initializes RPL which sets a ctimer for the first DIS */ 00215 /* We must start etimers and ctimers,before calling it */ 00216 process_start(&etimer_process, NULL); 00217 ctimer_init(); 00218 00219 #if RPL_BORDER_ROUTER 00220 process_start(&border_router_process, NULL); 00221 printf("Border Router Process started\n"); 00222 #elif UIP_CONF_IPV6_RPL 00223 printf("RPL enabled\n"); 00224 #endif 00225 00226 procinit_init(); 00227 autostart_start(autostart_processes); 00228 00229 /* Set default IP addresses if not specified */ 00230 #if !UIP_CONF_IPV6 00231 { 00232 uip_ipaddr_t addr; 00233 00234 uip_gethostaddr(&addr); 00235 if(addr.u8[0] == 0) { 00236 uip_ipaddr(&addr, 10,1,1,1); 00237 } 00238 printf("IP Address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); 00239 uip_sethostaddr(&addr); 00240 00241 uip_getnetmask(&addr); 00242 if(addr.u8[0] == 0) { 00243 uip_ipaddr(&addr, 255,0,0,0); 00244 uip_setnetmask(&addr); 00245 } 00246 printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); 00247 00248 uip_getdraddr(&addr); 00249 if(addr.u8[0] == 0) { 00250 uip_ipaddr(&addr, 10,1,1,100); 00251 uip_setdraddr(&addr); 00252 } 00253 printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); 00254 } 00255 #else /* UIP_CONF_IPV6 */ 00256 00257 #if !UIP_CONF_IPV6_RPL 00258 { 00259 uip_ipaddr_t ipaddr; 00260 #ifdef HARD_CODED_ADDRESS 00261 uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); 00262 #else 00263 uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); 00264 #endif 00265 if((ipaddr.u16[0] != 0) || 00266 (ipaddr.u16[1] != 0) || 00267 (ipaddr.u16[2] != 0) || 00268 (ipaddr.u16[3] != 0)) { 00269 #if UIP_CONF_ROUTER 00270 uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0); 00271 #else /* UIP_CONF_ROUTER */ 00272 uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0); 00273 #endif /* UIP_CONF_ROUTER */ 00274 00275 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 00276 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 00277 } 00278 } 00279 #endif /* !UIP_CONF_IPV6_RPL */ 00280 00281 #endif /* !UIP_CONF_IPV6 */ 00282 00283 // procinit_init(); 00284 // autostart_start(autostart_processes); 00285 00286 /* Make standard output unbuffered. */ 00287 setvbuf(stdout, (char *)NULL, _IONBF, 0); 00288 00289 printf("\n*******%s online*******\n",CONTIKI_VERSION_STRING); 00290 00291 #if UIP_CONF_IPV6 && !RPL_BORDER_ROUTER /* Border router process prints addresses later */ 00292 { 00293 uint8_t i; 00294 for(i = 0; i < UIP_DS6_ADDR_NB; i++) { 00295 if(uip_ds6_if.addr_list[i].isused) { 00296 printf("IPV6 Addresss: "); 00297 sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); 00298 printf("\n"); 00299 } 00300 } 00301 } 00302 #endif 00303 00304 while(1) { 00305 fd_set fds; 00306 int n; 00307 struct timeval tv; 00308 00309 n = process_run(); 00310 00311 tv.tv_sec = 0; 00312 tv.tv_usec = 1000; 00313 FD_ZERO(&fds); 00314 FD_SET(STDIN_FILENO, &fds); 00315 select(1, &fds, NULL, NULL, &tv); 00316 00317 if(FD_ISSET(STDIN_FILENO, &fds)) { 00318 char c; 00319 if(read(STDIN_FILENO, &c, 1) > 0) { 00320 serial_line_input_byte(c); 00321 } 00322 } 00323 etimer_request_poll(); 00324 } 00325 00326 return 0; 00327 } 00328 /*---------------------------------------------------------------------------*/ 00329 void 00330 log_message(char *m1, char *m2) 00331 { 00332 printf("%s%s\n", m1, m2); 00333 } 00334 /*---------------------------------------------------------------------------*/ 00335 void 00336 uip_log(char *m) 00337 { 00338 printf("uIP: '%s'\n", m); 00339 } 00340 /*---------------------------------------------------------------------------*/ 00341 unsigned short 00342 sensors_light1(void) 00343 { 00344 static unsigned short count; 00345 return count++; 00346 } 00347 /*---------------------------------------------------------------------------*/