static void check_dodag_creation(void *data) { if(!rpl_can_become_root) { //It's forbidden to become DODAG root right now, skipping checks ctimer_set(&create_dodag_root_timer, CLOCK_SECOND, check_dodag_creation, NULL); } else { if(!is_dodag_available()) { LOG6LBR_INFO("No DODAGs found\n"); uip_ds6_notification_rm(&create_dodag_root_route_callback); cetic_6lbr_start_dodag_root(); } else if(is_own_dodag()) { LOG6LBR_INFO("Own DODAG already existing\n"); uip_ds6_notification_rm(&create_dodag_root_route_callback); cetic_6lbr_start_dodag_root(); } else if(rpl_ignore_other_dodags) { LOG6LBR_INFO("Ignoring other DODAGs\n"); uip_ds6_notification_rm(&create_dodag_root_route_callback); cetic_6lbr_start_dodag_root(); } else { //Another DODAG is present on the network, stay as simple router ctimer_set(&create_dodag_root_timer, CLOCK_SECOND, check_dodag_creation, NULL); } } }
void platform_restart(void) { switch (cetic_6lbr_restart_type) { case CETIC_6LBR_RESTART: LOG6LBR_INFO("Exiting...\n"); exit(0); break; case CETIC_6LBR_REBOOT: LOG6LBR_INFO("Rebooting...\n"); if(system("reboot") != 0) { LOG6LBR_WARN("Reboot command failed\n"); } break; case CETIC_6LBR_HALT: LOG6LBR_INFO("Halting...\n"); if(system("halt") != 0) { LOG6LBR_WARN("Halt command failed\n"); } break; default: //We should never end up here... exit(1); } //We should never end up here... exit(1); }
void nvm_data_write(void) { long err; int retry = 4; while (retry > 0 ) { LOG6LBR_INFO("Flashing 6LBR NVM\n"); err = rom_util_page_erase(CETIC_6LBR_NVM_ADDRESS, CETIC_6LBR_NVM_SIZE); if ( err != 0 ) { LOG6LBR_ERROR("erase error : %ld\n", err); } rom_util_program_flash( (uint32_t*)&nvm_data, CETIC_6LBR_NVM_ADDRESS, (sizeof(nvm_data_t)/4+1)*4); if ( err != 0 ) { LOG6LBR_ERROR("write error : %ld\n", err); } if(rom_util_memcmp( (void *)&nvm_data, (void *)CETIC_6LBR_NVM_ADDRESS, sizeof(nvm_data_t)) == 0) { break; } LOG6LBR_ERROR("verify NVM failed, retry\n"); retry--; } if(retry == 0) { LOG6LBR_FATAL("Could not program 6LBR NVM !\n"); } else { LOG6LBR_INFO("Flashing 6LBR NVM done\n"); } }
void load_nvm_config(void) { nvm_data_read(); LOG6LBR_INFO("NVM Magic : %x\n", nvm_data.magic); LOG6LBR_INFO("NVM Version : %x\n", nvm_data.version); check_nvm(&nvm_data, 0); }
/*---------------------------------------------------------------------------*/ void eth_drv_init(void) { if(sixlbr_config_use_raw_ethernet) { LOG6LBR_INFO("RAW Ethernet interface init\n"); } else { LOG6LBR_INFO("TAP Ethernet interface init\n"); } eth_dev_init(); process_start(ð_drv_process, NULL); }
void cetic_6lbr_init_finalize(void) { #if CETIC_6LBR_WITH_RPL if(rpl_fast_startup) { cetic_6lbr_start_dodag_root(); } else { cetic_6lbr_start_delayed_dodag_root(1); } #endif #if CETIC_6LBR_WITH_IP64 if((nvm_data.global_flags & CETIC_GLOBAL_IP64) != 0) { LOG6LBR_INFO("Starting IP64\n"); ip64_eth_addr_set((struct ip64_eth_addr *)eth_mac_addr); if((nvm_data.eth_ip64_flags & CETIC_6LBR_IP64_RFC6052_PREFIX) != 0) { uip_ip6addr_t ip64_prefix = {{ 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; ip64_addr_set_prefix(&ip64_prefix, 96); } ip64_init(); if((nvm_data.eth_ip64_flags & CETIC_6LBR_IP64_DHCP) == 0) { memcpy(ð_ip64_addr, nvm_data.eth_ip64_addr, sizeof(nvm_data.eth_ip64_addr)); memcpy(ð_ip64_netmask, nvm_data.eth_ip64_netmask, sizeof(nvm_data.eth_ip64_netmask)); memcpy(ð_ip64_gateway, nvm_data.eth_ip64_gateway, sizeof(nvm_data.eth_ip64_gateway)); ip64_set_ipv4_address(ð_ip64_addr, ð_ip64_netmask); ip64_set_draddr(ð_ip64_gateway); LOG6LBR_4ADDR(INFO, ð_ip64_addr, "IPv4 address : "); } else { ip64_ipv4_dhcp_init(); } } #endif #if RESOLV_CONF_SUPPORTS_MDNS if((nvm_data.global_flags & CETIC_GLOBAL_MDNS) != 0) { LOG6LBR_INFO("Starting MDNS\n"); process_start(&resolv_process, NULL); resolv_set_hostname((char *)nvm_data.dns_host_name); #if RESOLV_CONF_SUPPORTS_DNS_SD if((nvm_data.dns_flags & CETIC_6LBR_DNS_DNS_SD) != 0) { resolv_add_service("_6lbr._tcp", "", nvm_data.webserver_port); } #endif } #endif LOG6LBR_INFO("Starting as " CETIC_6LBR_MODE "\n"); #if CONTIKI_TARGET_NATIVE cetic_6lbr_save_ip(); #endif }
void llsec_wrapper_init(void) { if(nvm_data.security_layer == CETIC_6LBR_SECURITY_LAYER_NONE) { LOG6LBR_INFO("Using 'nullsec' llsec driver\n"); current_llsec_driver = &nullsec_driver; } else if(nvm_data.security_layer == CETIC_6LBR_SECURITY_LAYER_NONCORESEC) { LOG6LBR_INFO("Using 'noncoresec' llsec driver\n"); current_llsec_driver = &noncoresec_driver; } else { LOG6LBR_ERROR("Unknown llsec driver, using 'nullsec' instead\n"); current_llsec_driver = &nullsec_driver; } }
void slip_request_mac(void) { LOG6LBR_INFO("Fetching MAC address\n"); radio_mac_addr_ready = 0; write_to_slip((uint8_t *) "?M", 2); }
void nvm_data_write(void) { LOG6LBR_INFO("Writing 6LBR NVM\n"); int rv; rv = ext_flash_open(); if(!rv) { LOG6LBR_ERROR("Could not open external flash\n"); ext_flash_close(); return; } rv = ext_flash_erase(CETIC_6LBR_NVM_ADDRESS, CETIC_6LBR_NVM_SIZE); if(!rv) { LOG6LBR_ERROR("Error erasing flash\n"); } else { rv = ext_flash_write(CETIC_6LBR_NVM_ADDRESS, sizeof(nvm_data_t), (uint8_t *)&nvm_data); if(!rv) { LOG6LBR_ERROR("Error writing flash\n"); } } ext_flash_close(); }
void cetic_6lbr_start_delayed_dodag_root(int send_dis) { if(rpl_can_become_root && is_own_dodag()) { LOG6LBR_INFO("Own DODAG already existing\n"); cetic_6lbr_start_dodag_root(); } else { dodag_root_check_interval = rpl_wait_delay / 2 + random_rand() % (rpl_wait_delay / 2); LOG6LBR_INFO("Wait for potential DODAGs\n"); ctimer_set(&create_dodag_root_timer, dodag_root_check_interval, check_dodag_creation, NULL); uip_ds6_notification_add(&create_dodag_root_route_callback, route_callback); if(send_dis) { dis_output(NULL); } } }
/*---------------------------------------------------------------------------*/ void ifconf(const char *tundev) { if(slip_config_ifup_script != NULL) { if(access(slip_config_ifup_script, R_OK | X_OK) == 0) { LOG6LBR_INFO("Running 6lbr-ifdown script '%s'\n", slip_config_ifup_script); ssystem("%s %s %s 2>&1", slip_config_ifup_script, use_raw_ethernet ? "raw" : "tap", slip_config_tundev); } else { LOG6LBR_ERROR("Could not access %s : %s\n", slip_config_ifup_script, strerror(errno)); } } else { LOG6LBR_INFO("No 6lbr-down script specified\n"); } }
/*---------------------------------------------------------------------------*/ void eth_dev_init() { if(sixlbr_config_use_raw_ethernet) { eth_fd = eth_alloc(sixlbr_config_eth_device); } else { eth_fd = tap_alloc(sixlbr_config_eth_device); } if(eth_fd == -1) { LOG6LBR_FATAL("eth_dev_init() : %s\n", strerror(errno)); exit(1); } select_set_callback(eth_fd, ð_select_callback); LOG6LBR_INFO("opened device /dev/%s\n", sixlbr_config_eth_device); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); ifconf(sixlbr_config_eth_device); #if !CETIC_6LBR_ONE_ITF if(sixlbr_config_use_raw_ethernet) { #endif fetch_mac(eth_fd, sixlbr_config_eth_device, ð_mac_addr); LOG6LBR_ETHADDR(INFO, ð_mac_addr, "Eth MAC address : "); eth_mac_addr_ready = 1; #if !CETIC_6LBR_ONE_ITF } #endif }
void tun_init() { setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ if(use_raw_ethernet) { tunfd = eth_alloc(slip_config_tundev); } else { tunfd = tun_alloc(slip_config_tundev); } if(tunfd == -1) { LOG6LBR_FATAL("tun_alloc() : %s\n", strerror(errno)); exit(1); } select_set_callback(tunfd, &tun_select_callback); LOG6LBR_INFO("opened device /dev/%s\n", slip_config_tundev); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); ifconf(slip_config_tundev); #if !CETIC_6LBR_ONE_ITF if(use_raw_ethernet) { #endif fetch_mac(tunfd, slip_config_tundev, ð_mac_addr); LOG6LBR_ETHADDR(INFO, ð_mac_addr, "Eth MAC address : "); eth_mac_addr_ready = 1; #if !CETIC_6LBR_ONE_ITF } #endif }
void node_config_init(void) { LOG6LBR_INFO("Node Config init\n"); node_config_impl_init(); if((nvm_data.global_flags & CETIC_GLOBAL_FILTER_NODES) != 0) { cetic_6lbr_allowed_node_hook = node_config_allowed_node_hook; } }
void mac_wrapper_init(void) { if(nvm_data.mac_layer == CETIC_6LBR_MAC_LAYER_NONE) { LOG6LBR_INFO("Using 'nullmac' mac driver\n"); current_mac_driver = &nullmac_driver; } else if(nvm_data.mac_layer == CETIC_6LBR_MAC_LAYER_CSMA) { LOG6LBR_INFO("Using 'csma' mac driver\n"); current_mac_driver = &csma_driver; } else { LOG6LBR_ERROR("Unknown mac driver, using 'csma' instead\n"); current_mac_driver = &csma_driver; nvm_data.mac_layer = CETIC_6LBR_MAC_LAYER_CSMA; } current_mac_driver->init(); }
void cetic_6lbr_set_prefix(uip_ipaddr_t * prefix, unsigned len, uip_ipaddr_t * ipaddr) { #if CETIC_6LBR_SMARTBRIDGE int new_prefix = cetic_dag != NULL && !uip_ipaddr_prefixcmp(&cetic_dag->prefix_info.prefix, prefix, len); if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) { LOG6LBR_DEBUG("Ignoring RA\n"); return; } LOG6LBR_INFO("CETIC_BRIDGE : set_prefix\n"); uip_ipaddr_copy(&wsn_ip_addr, ipaddr); if(cetic_dag != NULL) { rpl_set_prefix(cetic_dag, prefix, len); uip_ipaddr_copy(&wsn_net_prefix, prefix); wsn_net_prefix_len = len; if(new_prefix) { LOG6LBR_6ADDR(INFO, prefix, "Setting DAG prefix : "); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } #if CONTIKI_TARGET_NATIVE cetic_6lbr_save_ip(); #endif #endif }
void nvm_data_read(void) { LOG6LBR_INFO("Reading 6LBR NVM\n"); rom_util_memcpy( (void *)&nvm_data, (void *)CETIC_6LBR_NVM_ADDRESS, sizeof(nvm_data_t)); }
void platform_radio_init(void) { LOG6LBR_INFO("Setting channel %d\n", nvm_data.channel); set_channel(nvm_data.channel - 11); radio_ready = 1; radio_mac_addr_ready = 1; }
/*---------------------------------------------------------------------------*/ void cleanup(void) { if(slip_config_ifdown_script != NULL) { if(access(slip_config_ifdown_script, R_OK | X_OK) == 0) { LOG6LBR_INFO("Running 6lbr-ifup script '%s'\n", slip_config_ifdown_script); ssystem("%s %s %s 2>&1", slip_config_ifdown_script, use_raw_ethernet ? "raw" : "tap", slip_config_tundev); } else { LOG6LBR_ERROR("Could not access %s : %s\n", slip_config_ifdown_script, strerror(errno)); } } else { LOG6LBR_INFO("No 6lbr-ifup script specified\n"); } #if !CETIC_6LBR_ONE_ITF slip_set_mac(&linkaddr_null); slip_flushbuf(slipfd); #endif }
/*---------------------------------------------------------------------------*/ static void ifconf(const char *eth_dev) { if(sixlbr_config_ifup_script != NULL) { if(access(sixlbr_config_ifup_script, R_OK | X_OK) == 0) { LOG6LBR_INFO("Running 6lbr-ifup script '%s'\n", sixlbr_config_ifup_script); int status = ssystem("%s %s %s 2>&1", sixlbr_config_ifup_script, sixlbr_config_use_raw_ethernet ? "raw" : "tap", sixlbr_config_eth_device); if(status != 0) { LOG6LBR_FATAL("6lbr-ifup script returned an error, aborting...\n"); exit(1); } } else { LOG6LBR_ERROR("Could not access %s : %s\n", sixlbr_config_ifup_script, strerror(errno)); } } else { LOG6LBR_INFO("No 6lbr-up script specified\n"); } }
int nvm_data_reset(void) { int force_reset = 0; LOG6LBR_DEBUG("Opening nvm factory file '%s'\n", sixlbr_config_factory_nvm_file); memset(nvm_mem, 0xff, NVM_SIZE); int s = open(sixlbr_config_factory_nvm_file, O_RDONLY); if(s > 0) { if(read(s, nvm_mem, NVM_SIZE) < 0) { LOG6LBR_INFO("Could not read factory NVM"); force_reset = 1; } close(s); } else { LOG6LBR_INFO("Could not open factory nvm file\n"); force_reset = 1; } memcpy((uint8_t *) & nvm_data, nvm_mem, sizeof(nvm_data)); nvm_data_write(); return force_reset; }
static void plugin_load(char const * plugin_file) { void *handle; const char *error; sixlbr_plugin_t *plugin_descriptor; sixlbr_plugin_info_t *plugin_info; LOG6LBR_INFO("Loading %s\n", plugin_file); handle = dlopen(plugin_file, RTLD_NOW); if(handle == NULL) { LOG6LBR_ERROR("Could not open %s : %s\n", plugin_file, dlerror()); return; } *(void **)(&plugin_descriptor) = dlsym(handle, "sixlbr_plugin_info"); if((error = dlerror()) || plugin_descriptor == NULL) { LOG6LBR_ERROR("Plugin descriptor not found in %s\n", plugin_file); return; } plugin_info = (sixlbr_plugin_info_t *)malloc(sizeof(sixlbr_plugin_info_t)); plugin_info->plugin = plugin_descriptor; list_add(sixlbr_plugins, plugin_info); if (plugin_descriptor->api_version < SIXLBR_PLUGIN_API_VERSION) { LOG6LBR_ERROR("Plugin %s uses an obsolete api\n", plugin_file); plugin_info->status = -1; return; } plugin_info->status = 0; int result = 0; if (plugin_descriptor->load != NULL) { LOG6LBR_INFO("Initialising %s\n", plugin_descriptor->id); result = plugin_descriptor->load(); } if (result != 0) { LOG6LBR_ERROR("Load code of %s failed, error code is %d\n", plugin_descriptor->id, result); } plugin_info->init_status = result; }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(eth_drv_process, ev, data) { PROCESS_BEGIN(); LOG6LBR_INFO("ENC-28J60 Process started\n"); while(1) { enc28j60_pollhandler(); PROCESS_PAUSE(); } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ void native_config_load(config_level_t config_level) { int result; if (sixlbr_config_config_file_name) { if(config_level == CONFIG_LEVEL_BOOT) { LOG6LBR_INFO("Loading configuration : %s\n",sixlbr_config_config_file_name); } result = ini_parse(sixlbr_config_config_file_name, native_config_handler, &config_level); if (result < 0) { LOG6LBR_WARN("Can not open %s : %s\n", sixlbr_config_config_file_name, strerror(errno)); } else if (result) { LOG6LBR_FATAL("Syntax error in %s at line %d\n", sixlbr_config_config_file_name, result); exit(1); } } else { if(config_level == CONFIG_LEVEL_BOOT) { LOG6LBR_INFO("No configuration file specified\n"); } } }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { int size; /* 3 bytes per packet attribute is required for serialization */ uint8_t buf[PACKETBUF_NUM_ATTRS * 3 + PACKETBUF_SIZE + 3]; int sid; packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); /* ack or not ? */ packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); if(NETSTACK_FRAMER.create_and_secure() < 0) { /* Failed to allocate space for headers */ LOG6LBR_ERROR("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); } else { /* here we send the data over SLIP to the radio-chip */ size = 0; if(sixlbr_config_slip_serialize_tx_attrs) { size = packetutils_serialize_atts(&buf[3], sizeof(buf) - 3); } if(size < 0 || size + packetbuf_totlen() + 3 > sizeof(buf)) { LOG6LBR_ERROR("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); } else { sid = setup_callback(sent, ptr); if (sid != -1) { LOG6LBR_PRINTF(PACKET, RADIO_OUT, "write: %d (sid: %d, cb: %d)\n", packetbuf_datalen(), sid, callback_count); LOG6LBR_DUMP_PACKET(RADIO_OUT, packetbuf_dataptr(), packetbuf_datalen()); buf[0] = '!'; buf[1] = 'S'; buf[2] = sid; /* sequence or session number for this packet */ /* Copy packet data */ memcpy(&buf[3 + size], packetbuf_hdrptr(), packetbuf_totlen()); callbacks[sid].buf_len = packetbuf_totlen() + size + 3; memcpy(callbacks[sid].buf, buf, callbacks[sid].buf_len); write_to_slip(buf, callbacks[sid].buf_len); } else { LOG6LBR_INFO("native-rdc queue full\n"); mac_call_sent_callback(sent, ptr, MAC_TX_NOACK, 1); } } } }
void nvm_data_write(void) { memcpy(nvm_mem, (uint8_t *) & nvm_data, sizeof(nvm_data)); LOG6LBR_INFO("Opening nvm file '%s'\n", nvm_file); int s = open(nvm_file, O_WRONLY | O_TRUNC | O_CREAT, 0644); if(s > 0) { write(s, nvm_mem, NVM_SIZE); close(s); } else { LOG6LBR_ERROR("Could not write nvm file\n"); } }
/*---------------------------------------------------------------------------*/ void eth_drv_init() { LOG6LBR_INFO("ENC28J60 init\n"); linkaddr_copy((linkaddr_t *) & wsn_mac_addr, &linkaddr_node_addr); mac_createEthernetAddr((uint8_t *) eth_mac_addr, &wsn_mac_addr); LOG6LBR_ETHADDR(INFO, ð_mac_addr, "Eth MAC address : "); eth_mac_addr_ready = 1; enc28j60_init(eth_mac_addr); process_start(ð_drv_process, NULL); ethernet_ready = 1; }
PROCESS_THREAD(httpd_process, ev, data) { PROCESS_BEGIN(); tcp_listen(UIP_HTONS(nvm_data.webserver_port)); LOG6LBR_INFO("Starting webserver on port %d\n", nvm_data.webserver_port); memb_init(&conns); while(1) { PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); httpd_appcall(data); } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static void cleanup(void) { if(sixlbr_config_ifdown_script != NULL) { if(access(sixlbr_config_ifdown_script, R_OK | X_OK) == 0) { LOG6LBR_INFO("Running 6lbr-ifdown script '%s'\n", sixlbr_config_ifdown_script); int status = ssystem("%s %s %s 2>&1", sixlbr_config_ifdown_script, sixlbr_config_use_raw_ethernet ? "raw" : "tap", sixlbr_config_eth_device); if(status != 0) { LOG6LBR_ERROR("6lbr-ifdown script returned an error\n"); } } else { LOG6LBR_ERROR("Could not access %s : %s\n", sixlbr_config_ifdown_script, strerror(errno)); } } else { LOG6LBR_INFO("No 6lbr-ifdown script specified\n"); } cetic_6lbr_clear_ip(); #if !CETIC_6LBR_ONE_ITF slip_set_mac(&linkaddr_null); slip_flushbuf(slipfd); #endif }
void cetic_6lbr_end_dodag_root(rpl_instance_t *instance) { if(is_dodag_root()) { LOG6LBR_INFO("Leaving DODAG root\n"); rpl_local_repair(instance); dio_output(instance, NULL); rpl_free_dag(instance->current_dag); rpl_free_instance(instance); if(!rpl_fast_startup) { //Restart DODAG creation check ctimer_set(&create_dodag_root_timer, CLOCK_SECOND, check_dodag_creation, NULL); } } }