int main(int argc, char **argv) { contiki_argc = argc; contiki_argv = argv; /* The first one or two args are used for wpcap configuration */ /* so this needs to be "removed" from contiki_args. */ contiki_argc--; contiki_argv++; #ifdef UIP_FALLBACK_INTERFACE contiki_argc--; contiki_argv++; #endif process_init(); procinit_init(); #ifdef PLATFORM_BUILD program_handler_add(&directory_dsc, "Directory", 1); program_handler_add(&www_dsc, "Web browser", 1); #endif /* PLATFORM_BUILD */ autostart_start(autostart_processes); #if !NETSTACK_CONF_WITH_IPV6 { uip_ipaddr_t addr; uip_ipaddr(&addr, 192,168,0,111); uip_sethostaddr(&addr); log_message("IP Address: ", inet_ntoa(*(struct in_addr*)&addr)); uip_ipaddr(&addr, 255,255,255,0); uip_setnetmask(&addr); log_message("Subnet Mask: ", inet_ntoa(*(struct in_addr*)&addr)); uip_ipaddr(&addr, 192,168,0,1); uip_setdraddr(&addr); log_message("Def. Router: ", inet_ntoa(*(struct in_addr*)&addr)); uip_ipaddr(&addr, 192,168,0,1); uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); log_message("DNS Server: ", inet_ntoa(*(struct in_addr*)&addr)); } #else /* NETSTACK_CONF_WITH_IPV6 */ #if !UIP_CONF_IPV6_RPL #ifdef HARD_CODED_ADDRESS uip_ipaddr_t ipaddr; uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); if ((ipaddr.u16[0]!=0) || (ipaddr.u16[1]!=0) || (ipaddr.u16[2]!=0) || (ipaddr.u16[3]!=0)) { #if UIP_CONF_ROUTER uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0); #else /* UIP_CONF_ROUTER */ uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0); #endif /* UIP_CONF_ROUTER */ #if !UIP_CONF_IPV6_RPL uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); #endif } #endif /* HARD_CODED_ADDRESS */ #endif #endif while(1) { process_run(); etimer_request_poll(); /* Allow user-mode APC to execute. */ SleepEx(10, TRUE); #ifdef PLATFORM_BUILD if(console_resize()) { ctk_restore(); } #endif /* PLATFORM_BUILD */ } }
/*---------------------------------------------------------------------------*/ int main(void) { clock_init(); #if UIP_CONF_IPV6 /* A hard coded address overrides the stack default MAC address to allow multiple instances. uip6.c defines it as {0x00,0x06,0x98,0x00,0x02,0x32} giving an ipv6 address of [fe80::206:98ff:fe00:232] We make it simpler, {0x02,0x00,0x00 + the last three bytes of the hard coded address (if any are nonzero). HARD_CODED_ADDRESS can be defined in the contiki-conf.h file, or here to allow quick builds using different addresses. If HARD_CODED_ADDRESS has a prefix it also applied, unless built as a RPL end node. E.g. bbbb::12:3456 becomes fe80::ff:fe12:3456 and prefix bbbb::/64 if non-RPL ::10 becomes fe80::ff:fe00:10 and prefix awaits RA or RPL formation bbbb:: gives an address of bbbb::206:98ff:fe00:232 if non-RPL */ #ifdef HARD_CODED_ADDRESS { uip_ipaddr_t ipaddr; uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); if((ipaddr.u8[13] != 0) || (ipaddr.u8[14] != 0) || (ipaddr.u8[15] != 0)) { if(sizeof(uip_lladdr) == 6) { /* Minimal-net uses ethernet MAC */ uip_lladdr.addr[0] = 0x02; uip_lladdr.addr[1] = 0; uip_lladdr.addr[2] = 0; uip_lladdr.addr[3] = ipaddr.u8[13]; uip_lladdr.addr[4] = ipaddr.u8[14]; uip_lladdr.addr[5] = ipaddr.u8[15]; } } } #endif /* HARD_CODED_ADDRESS */ #endif /* UIP_CONF_IPV6 */ process_init(); /* procinit_init initializes RPL which sets a ctimer for the first DIS */ /* We must start etimers and ctimers,before calling it */ process_start(&etimer_process, NULL); ctimer_init(); #if RPL_BORDER_ROUTER process_start(&border_router_process, NULL); printf("Border Router Process started\n"); #elif UIP_CONF_IPV6_RPL printf("RPL enabled\n"); #endif procinit_init(); autostart_start(autostart_processes); /* Set default IP addresses if not specified */ #if !UIP_CONF_IPV6 { uip_ipaddr_t addr; uip_gethostaddr(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 10,1,1,1); } printf("IP Address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_sethostaddr(&addr); uip_getnetmask(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 255,0,0,0); uip_setnetmask(&addr); } printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_getdraddr(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 10,1,1,100); uip_setdraddr(&addr); } printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); } #else /* UIP_CONF_IPV6 */ #if !UIP_CONF_IPV6_RPL { uip_ipaddr_t ipaddr; #ifdef HARD_CODED_ADDRESS uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); #else uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); #endif if((ipaddr.u16[0] != 0) || (ipaddr.u16[1] != 0) || (ipaddr.u16[2] != 0) || (ipaddr.u16[3] != 0)) { #if UIP_CONF_ROUTER uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0); #else /* UIP_CONF_ROUTER */ uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0); #endif /* UIP_CONF_ROUTER */ uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } } #endif /* !UIP_CONF_IPV6_RPL */ #endif /* !UIP_CONF_IPV6 */ // procinit_init(); // autostart_start(autostart_processes); /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); printf("\n*******%s online*******\n",CONTIKI_VERSION_STRING); #if UIP_CONF_IPV6 && !RPL_BORDER_ROUTER /* Border router process prints addresses later */ { uint8_t i; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { printf("IPV6 Addresss: "); sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); printf("\n"); } } } #endif while(1) { fd_set fds; int n; struct timeval tv; n = process_run(); tv.tv_sec = 0; tv.tv_usec = 1000; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); select(1, &fds, NULL, NULL, &tv); if(FD_ISSET(STDIN_FILENO, &fds)) { char c; if(read(STDIN_FILENO, &c, 1) > 0) { serial_line_input_byte(c); } } etimer_request_poll(); } return 0; }
/* * Process a Router Advertisement * * - Possible actions when receiving a RA: add router to router list, * recalculate reachable time, update link hop limit, update retrans timer. * - If MTU option: update MTU. * - If SLLAO option: update entry in neighbor cache * - If prefix option: start autoconf, add prefix to prefix list */ void ra_input(void) { PRINTF("Received RA from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv); #if UIP_CONF_IPV6_CHECKS if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) || (UIP_ICMP_BUF->icode != 0)) { PRINTF("RA received is bad"); goto discard; } #endif /*UIP_CONF_IPV6_CHECKS */ if(UIP_ND6_RA_BUF->cur_ttl != 0) { uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl; PRINTF("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit); } if(UIP_ND6_RA_BUF->reachable_time != 0) { if(uip_ds6_if.base_reachable_time != uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) { uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time); uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time(); } } if(UIP_ND6_RA_BUF->retrans_timer != 0) { uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer); } /* Options processing */ nd6_opt_offset = UIP_ND6_RA_LEN; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { if(UIP_ND6_OPT_HDR_BUF->len == 0) { PRINTF("RA received is bad"); goto discard; } switch (UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: PRINTF("Processing SLLAO option in RA\n"); nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF; nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 1, NBR_STALE); } else { if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); nbr->state = NBR_STALE; } nbr->isrouter = 1; } break; case UIP_ND6_OPT_MTU: PRINTF("Processing MTU option in RA\n"); uip_ds6_if.link_mtu = uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu); break; case UIP_ND6_OPT_PREFIX_INFO: PRINTF("Processing PREFIX option in RA\n"); nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF; if((uip_ntohl(nd6_opt_prefix_info->validlt) >= uip_ntohl(nd6_opt_prefix_info->preferredlt)) && (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) { /* on-link flag related processing */ if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) { prefix = uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix, nd6_opt_prefix_info->preflen); if(prefix == NULL) { if(nd6_opt_prefix_info->validlt != 0) { if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) { prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix, nd6_opt_prefix_info->preflen, uip_ntohl(nd6_opt_prefix_info-> validlt)); } else { prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix, nd6_opt_prefix_info->preflen, 0); } } } else { switch (nd6_opt_prefix_info->validlt) { case 0: uip_ds6_prefix_rm(prefix); break; case UIP_ND6_INFINITE_LIFETIME: prefix->isinfinite = 1; break; default: PRINTF("Updating timer of prefix"); PRINT6ADDR(&prefix->ipaddr); PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt)); stimer_set(&prefix->vlifetime, uip_ntohl(nd6_opt_prefix_info->validlt)); prefix->isinfinite = 0; break; } } } /* End of on-link flag related processing */ /* autonomous flag related processing */ if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS) && (nd6_opt_prefix_info->validlt != 0) && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) { uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); addr = uip_ds6_addr_lookup(&ipaddr); if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) { if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) { /* The processing below is defined in RFC4862 section 5.5.3 e */ if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) || (uip_ntohl(nd6_opt_prefix_info->validlt) > stimer_remaining(&addr->vlifetime))) { PRINTF("Updating timer of address"); PRINT6ADDR(&addr->ipaddr); PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt)); stimer_set(&addr->vlifetime, uip_ntohl(nd6_opt_prefix_info->validlt)); } else { stimer_set(&addr->vlifetime, 2 * 60 * 60); PRINTF("Updating timer of address "); PRINT6ADDR(&addr->ipaddr); PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60)); } addr->isinfinite = 0; } else { addr->isinfinite = 1; } } else { if(uip_ntohl(nd6_opt_prefix_info->validlt) == UIP_ND6_INFINITE_LIFETIME) { uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } else { uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt), ADDR_AUTOCONF); } } } /* End of autonomous flag related processing */ } break; default: PRINTF("ND option not supported in RA"); break; } nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); } defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr); if(UIP_ND6_RA_BUF->router_lifetime != 0) { if(nbr != NULL) { nbr->isrouter = 1; } if(defrt == NULL) { uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr, (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime))); } else { stimer_set(&(defrt->lifetime), (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime))); } } else { if(defrt != NULL) { uip_ds6_defrt_rm(defrt); } } #if UIP_CONF_IPV6_QUEUE_PKT /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state * and we got a SLLAO), check if we had buffered a pkt for it */ /* if((nbr != NULL) && (nbr->queue_buf_len != 0)) { uip_len = nbr->queue_buf_len; memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); nbr->queue_buf_len = 0; return; }*/ if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); return; } #endif /*UIP_CONF_IPV6_QUEUE_PKT */ discard: uip_len = 0; return; }
void cetic_6lbr_init(void) { uip_ds6_addr_t *local = uip_ds6_get_link_local(-1); uip_ipaddr_copy(&wsn_ip_local_addr, &local->ipaddr); LOG6LBR_6ADDR(INFO, &wsn_ip_local_addr, "Tentative local IPv6 address "); #if CETIC_6LBR_SMARTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) //Manual configuration { memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address "); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); if ( !uip_is_addr_unspecified(ð_dft_router) ) { uip_ds6_defrt_add(ð_dft_router, 0); } } //End manual configuration #endif #if CETIC_6LBR_ROUTER //WSN network configuration memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); wsn_net_prefix_len = nvm_data.wsn_net_prefix_len; if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address (WSN) "); //Ethernet network configuration memcpy(eth_net_prefix.u8, &nvm_data.eth_net_prefix, sizeof(nvm_data.eth_net_prefix)); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); if ( !uip_is_addr_unspecified(ð_dft_router) ) { uip_ds6_defrt_add(ð_dft_router, 0); } eth_mac64_addr.addr[0] = eth_mac_addr[0]; eth_mac64_addr.addr[1] = eth_mac_addr[1]; eth_mac64_addr.addr[2] = eth_mac_addr[2]; eth_mac64_addr.addr[3] = CETIC_6LBR_ETH_EXT_A; eth_mac64_addr.addr[4] = CETIC_6LBR_ETH_EXT_B; eth_mac64_addr.addr[5] = eth_mac_addr[3]; eth_mac64_addr.addr[6] = eth_mac_addr[4]; eth_mac64_addr.addr[7] = eth_mac_addr[5]; if((nvm_data.mode & CETIC_MODE_ETH_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(ð_ip_addr, ð_net_prefix); uip_ds6_set_addr_iid(ð_ip_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(eth_ip_addr.u8, &nvm_data.eth_ip_addr, sizeof(nvm_data.eth_ip_addr)); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, ð_ip_addr, "Tentative global IPv6 address (ETH) "); //Ugly hack : in order to set WSN local address as the default address //We must add it afterwards as uip_ds6_addr_add allocates addr from the end of the list uip_ds6_addr_rm(local); uip_create_linklocal_prefix(ð_ip_local_addr); uip_ds6_set_addr_iid(ð_ip_local_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_addr_add(&wsn_ip_local_addr, 0, ADDR_AUTOCONF); //Prefix and RA configuration #if UIP_CONF_IPV6_RPL uint8_t publish = (nvm_data.ra_prefix_flags & CETIC_6LBR_MODE_SEND_PIO) != 0; uip_ds6_prefix_add(ð_net_prefix, nvm_data.eth_net_prefix_len, publish, nvm_data.ra_prefix_flags, nvm_data.ra_prefix_vtime, nvm_data.ra_prefix_ptime); #else uip_ds6_prefix_add(ð_net_prefix, nvm_data.eth_net_prefix_len, 0, 0, 0, 0); uint8_t publish = (nvm_data.ra_prefix_flags & CETIC_6LBR_MODE_SEND_PIO) != 0; uip_ds6_prefix_add(&wsn_net_prefix, nvm_data.wsn_net_prefix_len, publish, nvm_data.ra_prefix_flags, nvm_data.ra_prefix_vtime, nvm_data.ra_prefix_ptime); #endif #if UIP_CONF_IPV6_RPL if ((nvm_data.ra_rio_flags & CETIC_6LBR_MODE_SEND_RIO) != 0 ) { uip_ds6_route_info_add(&wsn_net_prefix, nvm_data.wsn_net_prefix_len, nvm_data.ra_rio_flags, nvm_data.ra_rio_lifetime); } #endif #endif #if UIP_CONF_IPV6_RPL && CETIC_6LBR_DODAG_ROOT //DODAGID = link-local address used ! cetic_dag = rpl_set_root(nvm_data.rpl_instance_id, &wsn_ip_local_addr); #if CETIC_6LBR_SMARTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) { rpl_set_prefix(cetic_dag, &wsn_net_prefix, nvm_data.wsn_net_prefix_len); } #else rpl_set_prefix(cetic_dag, &wsn_net_prefix, nvm_data.wsn_net_prefix_len); #endif LOG6LBR_INFO("Configured as DODAG Root\n"); #endif #if CETIC_6LBR_TRANSPARENTBRIDGE #if CETIC_6LBR_LEARN_RPL_MAC LOG6LBR_INFO("Starting as RPL Relay\n"); #else LOG6LBR_INFO("Starting as Full TRANSPARENT-BRIDGE\n"); #endif #elif CETIC_6LBR_SMARTBRIDGE LOG6LBR_INFO("Starting as SMART-BRIDGE\n"); #elif CETIC_6LBR_ROUTER #if UIP_CONF_IPV6_RPL LOG6LBR_INFO("Starting as RPL ROUTER\n"); #else LOG6LBR_INFO("Starting as NDP ROUTER\n"); #endif #elif CETIC_6LBR_6LR LOG6LBR_INFO("Starting as 6LR\n"); #else LOG6LBR_INFO("Starting in UNKNOWN mode\n"); #endif #if CONTIKI_TARGET_NATIVE if (ip_config_file_name) { char str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, (struct sockaddr_in6 *)ð_ip_addr, str, INET6_ADDRSTRLEN); FILE *ip_config_file = fopen(ip_config_file_name, "w"); fprintf(ip_config_file, "%s\n", str); fclose(ip_config_file); } #endif }
void cetic_6lbr_init(void) { #if !CETIC_6LBR_TRANSPARENTBRIDGE uip_ipaddr_t loc_fipaddr; //DODAGID = link-local address used ! uip_create_linklocal_prefix(&loc_fipaddr); uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr); cetic_dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &loc_fipaddr); #endif uip_ds6_addr_t *local = uip_ds6_get_link_local(-1); uip_ipaddr_copy(&wsn_ip_local_addr, &local->ipaddr); PRINTF("Tentative local IPv6 address "); PRINT6ADDR(&wsn_ip_local_addr); PRINTF("\n"); #if CETIC_6LBR_SMARTBRIDGE || CETIC_6LBR_TRANSPARENTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) //Manual configuration { memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } PRINTF("Tentative global IPv6 address "); PRINT6ADDR(&wsn_ip_addr.u8); PRINTF("\n"); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); uip_ds6_defrt_add(ð_dft_router, 0); #if CETIC_6LBR_SMARTBRIDGE rpl_set_prefix(cetic_dag, &wsn_net_prefix, 64); #endif } //End manual configuration #if CETIC_6LBR_TRANSPARENTBRIDGE printf("Starting as Transparent-BRIDGE\n"); #else printf("Starting as Smart-BRIDGE\n"); #endif #else /* ROUTER */ //WSN network configuration memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } PRINTF("Tentative global IPv6 address (WSN) "); PRINT6ADDR(&wsn_ip_addr.u8); PRINTF("\n"); //Ethernet network configuration memcpy(eth_net_prefix.u8, &nvm_data.eth_net_prefix, sizeof(nvm_data.eth_net_prefix)); if((nvm_data.mode & CETIC_MODE_ROUTER_SEND_CONFIG) != 0) { PRINTF("RA with autoconfig\n"); uip_ds6_prefix_add(ð_net_prefix, 64, 1, UIP_ND6_RA_FLAG_ONLINK | UIP_ND6_RA_FLAG_AUTONOMOUS, 30000, 30000); } else { PRINTF("RA without autoconfig\n"); uip_ds6_prefix_add(ð_net_prefix, 64, 0, 0, 0, 0); } memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); uip_ds6_defrt_add(ð_dft_router, 0); eth_mac64_addr.addr[0] = eth_mac_addr[0]; eth_mac64_addr.addr[1] = eth_mac_addr[1]; eth_mac64_addr.addr[2] = eth_mac_addr[2]; eth_mac64_addr.addr[3] = CETIC_6LBR_ETH_EXT_A; eth_mac64_addr.addr[4] = CETIC_6LBR_ETH_EXT_B; eth_mac64_addr.addr[5] = eth_mac_addr[3]; eth_mac64_addr.addr[6] = eth_mac_addr[4]; eth_mac64_addr.addr[7] = eth_mac_addr[5]; if((nvm_data.mode & CETIC_MODE_ETH_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(ð_ip_addr, ð_net_prefix); uip_ds6_set_addr_iid(ð_ip_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(eth_ip_addr.u8, &nvm_data.eth_ip_addr, sizeof(nvm_data.eth_ip_addr)); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_MANUAL); } PRINTF("Tentative global IPv6 address (ETH) "); PRINT6ADDR(ð_ip_addr.u8); PRINTF("\n"); rpl_set_prefix(cetic_dag, &wsn_net_prefix, 64); //Ugly hack : in order to set WSN local address as the default address //We must add it afterwards as uip_ds6_addr_add allocates addr from the end of the list uip_ds6_addr_rm(local); uip_create_linklocal_prefix(ð_ip_local_addr); uip_ds6_set_addr_iid(ð_ip_local_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_addr_add(&wsn_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_route_info_add(&wsn_net_prefix, 64, 0, 600); printf("Starting as ROUTER\n"); #endif }
/*------Done in a subroutine to keep main routine stack usage small--------*/ void initialize(void) { #if WITH_SLIP //Slip border router on uart0 rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); #else /* First rs232 port for debugging */ rs232_init(RS232_PORT_0, USART_BAUD_57600,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); /* Redirect stdout to first port */ rs232_redirect_stdout(RS232_PORT_0); /* Get input from first port */ rs232_set_input(RS232_PORT_0, serial_line_input_byte); #endif clock_init(); if(MCUSR & (1<<PORF )) PRINTA("Power-on reset.\n"); if(MCUSR & (1<<EXTRF)) PRINTA("External reset!\n"); if(MCUSR & (1<<BORF )) PRINTA("Brownout reset!\n"); if(MCUSR & (1<<WDRF )) PRINTA("Watchdog reset!\n"); if(MCUSR & (1<<JTRF )) PRINTA("JTAG reset!\n"); #if ANNOUNCE_BOOT PRINTA("\n*******Booting %s*******\n",CONTIKI_VERSION_STRING); #endif /* Initialize process subsystem */ process_init(); /* etimers must be started before ctimer_init */ process_start(&etimer_process, NULL); /* Initilaize serial line for input */ serial_line_init(); /* Initialize board LEDs */ leds_init(); /* When used for testing, we should start with them off */ leds_off(LEDS_GREEN|LEDS_YELLOW); ctimer_init(); /* Start radio and radio receive process */ NETSTACK_RADIO.init(); /* Set addresses BEFORE starting tcpip process */ rimeaddr_t addr; memset(&addr, 0, sizeof(rimeaddr_t)); get_mac_from_eeprom(addr.u8); memcpy(&uip_lladdr.addr, &addr.u8, 8); // Is this required with IPv6, I wonder? #if 1 rf230_set_pan_addr( IEEE802154_PANID, 0, (uint8_t *)&addr.u8 ); rf230_set_channel(26); rimeaddr_set_node_addr(&addr); #endif PRINTF("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); /* Initialize stack protocols */ queuebuf_init(); NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); #if ANNOUNCE_BOOT PRINTA("%s %s, channel %u",NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel()); if (NETSTACK_RDC.channel_check_interval) //function pointer is zero for sicslowmac { unsigned short tmp; tmp=CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval == 0 ? 1:\ NETSTACK_RDC.channel_check_interval()); if (tmp<65535) PRINTA(", check rate %u Hz",tmp); } PRINTA("\n"); #endif #if UIP_CONF_ROUTER //#warning Zigduino has not been tested with UIP_CONF_ROUTER #if ANNOUNCE_BOOT PRINTA("Routing Enabled\n"); #endif #endif /* Sensors process means all processes will get an event posted whenever sensors change. Not always desired, so may want to put this on a compile switch. */ process_start(&sensors_process, NULL); SENSORS_ACTIVATE(button_sensor); process_start(&tcpip_process, NULL); //Give ourselves a prefix // init_net(); /* Add easy addresses for testing */ uip_ip6addr_t ipaddr; uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, addr.u8[7]); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); #if UIP_CONF_ROUTER uip_ds6_prefix_add(&ipaddr,64,0,0,0,0); #else uip_ds6_prefix_add(&ipaddr,64,0); #endif /* Create a route through the border router for site-local addresses, fec0::/64. */ uip_ds6_route_t *rep; uip_ip6addr_t next_hop; uip_ip6addr(&ipaddr, 0xfec0, 0, 0, 0, 0, 0, 0, 0); uip_ip6addr(&next_hop, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); if((rep = uip_ds6_route_add(&ipaddr, 64, &next_hop, 0)) == NULL) { printf("*** Failed to add a route to fec0::/64\n"); } printf("Autostart other processes\n"); /* Autostart other processes */ autostart_start(autostart_processes); /*--------------------------Announce the configuration---------------------*/ #if ANNOUNCE_BOOT extern uip_ds6_netif_t uip_ds6_if; uint8_t i; PRINTA("\nIP addresses [%u max]\n",UIP_DS6_ADDR_NB); for (i=0; i<UIP_DS6_ADDR_NB; i++) { if (uip_ds6_if.addr_list[i].isused) { uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); PRINTA("\n"); } } #endif /* ANNOUNCE_BOOT */ }
/*---------------------------------------------------------------------------*/ int main(void) { clock_init(); #if UIP_CONF_IPV6 /* A hard coded address overrides the stack default MAC address to allow multiple instances. uip6.c defines it as {0x00,0x06,0x98,0x00,0x02,0x32} giving an ipv6 address of [fe80::206:98ff:fe00:232] We make it simpler, {0x02,0x00,0x00 + the last three bytes of the hard coded address (if any are nonzero). HARD_CODED_ADDRESS can be defined in the contiki-conf.h file, or here to allow quick builds using different addresses. If HARD_CODED_ADDRESS has a prefix it also applied, unless built as a RPL end node. E.g. bbbb::12:3456 becomes fe80::ff:fe12:3456 and prefix bbbb::/64 if non-RPL ::10 becomes fe80::ff:fe00:10 and prefix awaits RA or RPL formation bbbb:: gives an address of bbbb::206:98ff:fe00:232 if non-RPL */ #ifdef HARD_CODED_ADDRESS { uip_ipaddr_t ipaddr; uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); if((ipaddr.u8[13] != 0) || (ipaddr.u8[14] != 0) || (ipaddr.u8[15] != 0)) { if(sizeof(uip_lladdr) == 6) { /* Minimal-net uses ethernet MAC */ uip_lladdr.addr[0] = 0x02; uip_lladdr.addr[1] = 0; uip_lladdr.addr[2] = 0; uip_lladdr.addr[3] = ipaddr.u8[13]; uip_lladdr.addr[4] = ipaddr.u8[14]; uip_lladdr.addr[5] = ipaddr.u8[15]; } } } #endif /* HARD_CODED_ADDRESS */ #endif /* UIP_CONF_IPV6 */ process_init(); /* procinit_init initializes RPL which sets a ctimer for the first DIS */ /* We must start etimers and ctimers,before calling it */ process_start(&etimer_process, NULL); ctimer_init(); #if RPL_BORDER_ROUTER process_start(&border_router_process, NULL); printf("Border Router Process started\n"); #elif UIP_CONF_IPV6_RPL printf("RPL enabled\n"); #endif procinit_init(); autostart_start(autostart_processes); /* Set default IP addresses if not specified */ #if !UIP_CONF_IPV6 { uip_ipaddr_t addr; uip_gethostaddr(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 172,18,0,2); } printf("IP Address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_sethostaddr(&addr); uip_getnetmask(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 255,255,0,0); uip_setnetmask(&addr); } printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_getdraddr(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 172,18,0,1); uip_setdraddr(&addr); } printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); } #else /* UIP_CONF_IPV6 */ #if !UIP_CONF_IPV6_RPL { uip_ipaddr_t ipaddr; #ifdef HARD_CODED_ADDRESS uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); #else uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); #endif if((ipaddr.u16[0] != 0) || (ipaddr.u16[1] != 0) || (ipaddr.u16[2] != 0) || (ipaddr.u16[3] != 0)) { #if UIP_CONF_ROUTER if(!uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0)) { fprintf(stderr,"uip_ds6_prefix_add() failed.\n"); exit(EXIT_FAILURE); } #else /* UIP_CONF_ROUTER */ if(!uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0)) { fprintf(stderr,"uip_ds6_prefix_add() failed.\n"); exit(EXIT_FAILURE); } #endif /* UIP_CONF_ROUTER */ uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } } #endif /* !UIP_CONF_IPV6_RPL */ #endif /* !UIP_CONF_IPV6 */ // procinit_init(); // autostart_start(autostart_processes); /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); printf("\n*******%s online*******\n",CONTIKI_VERSION_STRING); #if UIP_CONF_IPV6 && !RPL_BORDER_ROUTER /* Border router process prints addresses later */ { int i = 0; int interface_count = 0; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { printf("IPV6 Addresss: "); sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); printf("\n"); interface_count++; } } assert(0 < interface_count); } #endif while(1) { fd_set fds; int n; struct timeval tv; clock_time_t next_event; n = process_run(); next_event = etimer_next_expiration_time() - clock_time(); #if DEBUG_SLEEP if(n > 0) printf("sleep: %d events pending\n",n); else printf("sleep: next event @ T-%.03f\n",(double)next_event / (double)CLOCK_SECOND); #endif #ifdef __CYGWIN__ /* wpcap doesn't appear to support select, so * we can't idle the process on windows. */ next_event = 0; #endif if(next_event > (CLOCK_SECOND * 2)) next_event = CLOCK_SECOND * 2; tv.tv_sec = n ? 0 : (next_event / CLOCK_SECOND); tv.tv_usec = n ? 0 : ((next_event % 1000) * 1000); FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); #ifdef __CYGWIN__ select(1, &fds, NULL, NULL, &tv); #else FD_SET(tapdev_fd(), &fds); if(0 > select(tapdev_fd() + 1, &fds, NULL, NULL, &tv)) { perror("Call to select() failed."); exit(EXIT_FAILURE); } #endif if(FD_ISSET(STDIN_FILENO, &fds)) { char c; if(read(STDIN_FILENO, &c, 1) > 0) { serial_line_input_byte(c); } } #ifdef __CYGWIN__ process_poll(&wpcap_process); #else process_poll(&tapdev_process); #endif etimer_request_poll(); } return 0; }
/*---------------------------------------------------------------------------*/ void uip_ds6_init(void) { uip_ds6_neighbors_init(); uip_ds6_route_init(); PRINTF("Init of IPv6 data structures\n"); PRINTF("%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n", NBR_TABLE_MAX_NEIGHBORS, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB, UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB); memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list)); memset(&uip_ds6_if, 0, sizeof(uip_ds6_if)); #if CONF_6LOWPAN_ND memset(uip_ds6_context_pref_list, 0, sizeof(uip_ds6_context_pref_list)); memset(uip_ds6_br_list, 0, sizeof(uip_ds6_br_list)); #if UIP_CONF_6LBR memset(uip_ds6_dup_addr_list, 0, sizeof(uip_ds6_dup_addr_list)); #endif /* UIP_CONF_6LBR */ #endif /* CONF_6LOWPAN_ND */ uip_ds6_addr_size = sizeof(struct uip_ds6_addr); uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list); /* Set interface parameters */ uip_ds6_if.link_mtu = UIP_LINK_MTU; uip_ds6_if.cur_hop_limit = UIP_TTL; uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME; uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time(); uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER; uip_ds6_if.maxdadns = UIP_ND6_DEF_MAXDADNS; /* Create link local address, prefix, multicast addresses, anycast addresses */ uip_create_linklocal_prefix(&loc_fipaddr); #if UIP_CONF_ROUTER uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0); #else /* UIP_CONF_ROUTER */ uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0); #endif /* UIP_CONF_ROUTER */ uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr); uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF); uip_create_linklocal_allnodes_mcast(&loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr); #if UIP_CONF_ROUTER uip_create_linklocal_allrouters_mcast(&loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr); #if UIP_ND6_SEND_RA #if !CONF_6LOWPAN_ND || UIP_ND6_RA_PERIODIC PRINTF("Will Sending periodic RA\n"); stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */ #endif /* #if !CONF_6LOWPAN_ND || UIP_ND6_RA_PERIODIC */ #endif /* UIP_ND6_SEND_RA */ #if UIP_CONF_6LR etimer_set(&uip_ds6_timer_rs, random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); #endif /* UIP_CONF_6LR */ #else /* UIP_CONF_ROUTER */ etimer_set(&uip_ds6_timer_rs, random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); #endif /* UIP_CONF_ROUTER */ etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD); #if CONF_6LOWPAN_ND_OPTI_START && UIP_CONF_6L_ROUTER rpl_started = 0; #endif /* CONF_6LOWPAN_ND_OPTI_START && UIP_CONF_6L_ROUTER */ return; }