Пример #1
0
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);
}
Пример #2
0
static void
send_to_uip(void)
{
  if(tcpip_inputfunc != NULL) {
    tcpip_inputfunc();
  } else {
    LOG6LBR_WARN("No input function set\n");
  }
}
Пример #3
0
/*---------------------------------------------------------------------------*/
void native_config_load(config_level_t config_level)
{
  int result;

  if (config_file_name) {
    LOG6LBR_INFO("Loading configuration : %s\n",config_file_name);
    result = ini_parse(config_file_name, native_config_handler, &config_level);
    if (result < 0) {
      LOG6LBR_WARN("Can not open %s : %s\n", config_file_name, strerror(errno));
    }
    else if (result) {
      LOG6LBR_FATAL("Syntax error in %s at line %d\n", config_file_name, result);
      exit(1);
    }
  } else {
    LOG6LBR_WARN("No configuration file specified\n");
  }
}
Пример #4
0
/*---------------------------------------------------------------------------*/
void
add(char const *str, ...)
{
  va_list arg;

  va_start(arg, str);
  if(blen<sizeof(buf)) {
    blen += vsnprintf(&buf[blen], sizeof(buf) - blen, str, arg);
  } else {
    LOG6LBR_WARN("Buffer overflow\n");
  }
  va_end(arg);
}
Пример #5
0
/*---------------------------------------------------------------------------*/
static int native_config_handler(void* user, const char* section, const char* name,
    const char* value) {
  native_config_callback_t *cb;
  for(cb = list_head(callbacks);
      cb != NULL;
      cb = list_item_next(cb)) {
    if(strcmp(section, cb->section) == 0) {
      break;
    }
  }
  if(cb) {
    return cb->callback(*(config_level_t *)user, cb->user, cb->section, name, value);
  } else {
    LOG6LBR_WARN("Invalid section : %s\n", section);
  }
  return 1;
}
Пример #6
0
void
platform_init(void)
{
  slip_config_handle_arguments(contiki_argc, contiki_argv);
  if (sixlbr_config_watchdog_interval) {
    process_start(&native_6lbr_watchdog, NULL);
  } else {
    LOG6LBR_WARN("6LBR Watchdog disabled\n");
  }
  native_config_init();
  native_config_handlers_init();
  plugins_load();

  struct sigaction action;
  /* Trap SIGUSR1. */
  action.sa_flags = SA_RESTART;
  action.sa_handler = reload_trigger;
  sigaction(SIGUSR1, &action, NULL);
}
Пример #7
0
static void
wireless_input(void)
{
  int processFrame = 0;
  int forwardFrame = 0;

  LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input\n");

  //Source filtering
  //----------------
#if CETIC_6LBR_TRANSPARENTBRIDGE && CETIC_6LBR_LEARN_RPL_MAC
  if (!rpl_mac_known) {
    //Rpl Relay not yet configured, drop packet
    uip_len = 0;
    return;
  }
  if (rimeaddr_cmp
	  (packetbuf_addr(PACKETBUF_ADDR_SENDER),
	   & rimeaddr_node_addr) != 0) {
    LOG6LBR_WARN("WSN packet received with RplRoot address, another TB is within range, dropping it\n");
    //Drop packet
    uip_len = 0;
    return;
  }
#endif

  //Destination filtering
  //---------------------
  if(IS_BROADCAST_ADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {      //Broadcast
    LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input : broadcast\n");
    forwardFrame = 1;
    processFrame = 1;
  } else {                      //unicast
    LOG6LBR_LLADDR_PRINTF(PACKET, PF_IN, (uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_RECEIVER), "wireless_input: dest: ");
    if(rimeaddr_cmp
       (packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
        (rimeaddr_t *) & wsn_mac_addr) != 0) {
      processFrame = 1;         //For us
    } else {                    //For another host
#if CETIC_6LBR_TRANSPARENTBRIDGE
      //Not for us, forward it directly
      forwardFrame = 1;
      LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input : to forward\n");
#endif
    }
  }

  //Packet forwarding
  //-----------------
#if CETIC_6LBR_TRANSPARENTBRIDGE
  if(forwardFrame) {
    LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input: forwarding frame\n");
    if(eth_output((uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_SENDER),
                  (uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
      //Restore packet as eth_output might have converted its content
      mac_translateIPLinkLayer(ll_802154_type);
    }
  }
#endif


  //Handle packet
  //-------------
  if(processFrame) {
    LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input: processing frame\n");
    send_to_uip();
  } else {
    //Drop packet
    uip_len = 0;
  }
}
Пример #8
0
void
eth_input(void)
{
#if CETIC_6LBR_TRANSPARENTBRIDGE || CETIC_6LBR_ONE_ITF || CETIC_6LBR_6LR
  uip_lladdr_t srcAddr;
#endif
  uip_lladdr_t destAddr;
  int processFrame = 0;
  int forwardFrame = 0;

  //Packet type filtering
  //---------------------
  //Keep only IPv6 traffic
  if(BUF->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) {
    LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping packet type=0x%04x\n", uip_ntohs(BUF->type));
    uip_len = 0;
    return;
  }
  //Packet source Filtering
  //-----------------------
  /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */
  if((BUF->dest.addr[0] == 0x33) && (BUF->dest.addr[1] == 0x33)) {
    forwardFrame = 1;
    processFrame = 1;
    rimeaddr_copy((rimeaddr_t *) & destAddr, &rimeaddr_null);
  } else if((BUF->dest.addr[0] == 0xFF)
            && (BUF->dest.addr[1] == 0xFF)
            && (BUF->dest.addr[2] == 0xFF)
            && (BUF->dest.addr[3] == 0xFF)
            && (BUF->dest.addr[4] == 0xFF)
            && (BUF->dest.addr[5] == 0xFF)) {
    /* IPv6 does not use broadcast addresses, hence this should not happen */
    LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping broadcast packet\n");
    uip_len = 0;
    return;
  } else {
    /* Complex Address Translation */
    if(mac_createSicslowpanLongAddr(&(BUF->dest.addr[0]), &destAddr) == 0) {
      LOG6LBR_WARN("eth_input: Address translation failed\n");
      uip_len = 0;
      return;
    }
  }

  //Packet content rewriting
  //------------------------
  //Some IP packets have link layer in them, need to change them around!
  uint8_t transReturn = mac_translateIPLinkLayer(ll_802154_type);

  if(transReturn != 0) {
    LOG6LBR_WARN("eth_input: IPTranslation returns %d\n", transReturn);
  }

  //Destination filtering
  //---------------------
  if(memcmp((uint8_t *) & eth_mac_addr, BUF->dest.addr, 6) == 0) {
    processFrame = 1;
  } else {
#if CETIC_6LBR_TRANSPARENTBRIDGE
    //Not for us, forward it directly
    forwardFrame = 1;
#endif
  }

  //Handle packet
  //-------------
#if CETIC_6LBR_TRANSPARENTBRIDGE
  if(forwardFrame) {
    mac_createSicslowpanLongAddr(&(BUF->src.addr[0]), &srcAddr);
#if CETIC_6LBR_LEARN_RPL_MAC
    if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) {
      uint8_t *buffer = UIP_ICMP_PAYLOAD;
      uint16_t rank = (uint16_t)buffer[2] << 8 | buffer[2 + 1];
      if ( rank == RPL_MIN_HOPRANKINC ) {
    	platform_set_wsn_mac((rimeaddr_t *) &srcAddr);
        rpl_mac_known=1;
      }
    }
    if (!rpl_mac_known) {
      //Rpl Relay not yet configured, drop packet
      uip_len = 0;
      return;
    }
    if(rimeaddr_cmp((rimeaddr_t *) &srcAddr, &rimeaddr_node_addr) != 0) {
      //Only forward RplRoot packets
      LOG6LBR_LLADDR_PRINTF(PACKET, PF_IN, &destAddr, "eth_input: Forwarding frame to ");
      wireless_output(NULL, &destAddr);
    }
#else
    LOG6LBR_LLADDR_PRINTF(PACKET, PF_IN, &destAddr, "eth_input: Forwarding frame to ");
    wireless_output(&srcAddr, &destAddr);
#endif
  }
#endif
  if(processFrame) {
    LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Processing frame\n");
#if CETIC_6LBR_ONE_ITF || CETIC_6LBR_6LR
  //RPL uses source packet address to populate its neighbor table
  //In this two modes RPL packets are incoming from Eth interface
  mac_createSicslowpanLongAddr(&(BUF->src.addr[0]), &srcAddr);
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *) &srcAddr);
#endif
    send_to_uip();
  } else {
    //Drop packet
    uip_len = 0;
  }
}
Пример #9
0
static int
update_config(const char *name, uint8_t *reboot_needed)
{
  const char *ptr = name;
  char *next;
  uint8_t do_update = 1;
  uip_ipaddr_t loc_fipaddr;
#if CETIC_6LBR_IP64
  uip_ip4addr_t loc_fip4addr;
#endif

  *reboot_needed = 0;

  while(*ptr) {
    const char *param = ptr;

    next = index(ptr, '=');
    if(!next)
      break;
    *next = 0;
    ptr = next + 1;
    const char *value = ptr;

    next = index(ptr, '&');
    if(next) {
      *next = 0;
      ptr = next + 1;
    } else {
      ptr += strlen(ptr);
    }

    LOG6LBR_DEBUG("Got param: '%s' = '%s'\n", param, value);
    if (0) {
    }
    UPDATE_FLAG("smart_multi", mode, CETIC_MODE_SMART_MULTI_BR, 1)
    UPDATE_FLAG("wait_ra", mode, CETIC_MODE_WAIT_RA_MASK, 1)
    UPDATE_INT("channel", channel, 1)
    UPDATE_HEX("panid", pan_id, 1)
#if CETIC_6LBR_MAC_WRAPPER
    UPDATE_INT("mac", mac_layer, 1)
#endif
    UPDATE_INT("llsec", security_layer, 1)
    UPDATE_INT("llsec_level", security_level, 1)
    UPDATE_KEY("psk", noncoresec_key, 16, 1)
    UPDATE_FLAG( "sec_dis_ar", noncoresec_flags, CETIC_6LBR_NONCORESEC_DISABLE_ANTIREPLAY, 1)
    UPDATE_FLAG( "sec_ar_wa", noncoresec_flags, CETIC_6LBR_NONCORESEC_ANTIREPLAY_WORKAROUND, 1)
    UPDATE_IPADDR("wsn_pre", wsn_net_prefix, 1)
    UPDATE_INT("wsn_pre_len", wsn_net_prefix_len, 1)
    UPDATE_IPADDR("wsn_context_0", wsn_6lowpan_context_0, 1)
    UPDATE_FLAG("wsn_auto", mode, CETIC_MODE_WSN_AUTOCONF, 1)
    UPDATE_IPADDR("wsn_addr", wsn_ip_addr, 1)
    UPDATE_IPADDR("dns", dns_server, 1)
    UPDATE_IPADDR("eth_pre", eth_net_prefix, 1)
    UPDATE_INT("eth_pre_len", eth_net_prefix_len, 1)
    UPDATE_FLAG("eth_auto", mode, CETIC_MODE_ETH_AUTOCONF, 1)
    UPDATE_IPADDR("eth_addr", eth_ip_addr, 1)
    UPDATE_IPADDR("eth_dft", eth_dft_router, 1)
    UPDATE_FLAG("ra_daemon", mode, CETIC_MODE_ROUTER_RA_DAEMON, 1)
    UPDATE_FLAG("rewrite", mode, CETIC_MODE_REWRITE_ADDR_MASK, 1)
#if CETIC_6LBR_IP64
    UPDATE_FLAG("ip64", global_flags, CETIC_GLOBAL_IP64, 1)
    UPDATE_FLAG("ip64_dhcp", eth_ip64_flags, CETIC_6LBR_IP64_DHCP, 1)
    UPDATE_IP4ADDR("ip64_addr", eth_ip64_addr, 1)
    UPDATE_IP4ADDR("ip64_netmask", eth_ip64_netmask, 1)
    UPDATE_IP4ADDR("ip64_gateway", eth_ip64_gateway, 1)
    UPDATE_FLAG("ip64_port_map", eth_ip64_flags, CETIC_6LBR_IP64_SPECIAL_PORTS, 1)
    UPDATE_FLAG("ip64_6052", eth_ip64_flags, CETIC_6LBR_IP64_RFC6052_PREFIX, 1)
#endif
#if RESOLV_CONF_SUPPORTS_MDNS
    UPDATE_FLAG("mdns", global_flags, CETIC_GLOBAL_MDNS, 1)
    UPDATE_STRING("hostname", dns_host_name, NVM_DATA_DNS_HOST_NAME_SIZE, 1)
#if RESOLV_CONF_SUPPORTS_DNS_SD
    UPDATE_FLAG("dns_sd", dns_flags, CETIC_6LBR_DNS_DNS_SD, 1)
#endif
#endif
#if CETIC_NODE_CONFIG
    UPDATE_FLAG("nc_filter", global_flags, CETIC_GLOBAL_FILTER_NODES, 1)
#endif
    UPDATE_INT( "ra_lifetime", ra_router_lifetime, 1)
    UPDATE_INT( "ra_max_interval", ra_max_interval, 1)
    UPDATE_INT( "ra_min_interval", ra_min_interval, 1)
    UPDATE_INT( "ra_min_delay", ra_min_delay, 1)

    UPDATE_FLAG( "ra_pio", ra_prefix_flags, CETIC_6LBR_MODE_SEND_PIO, 1)
    UPDATE_FLAG( "ra_prefix_o", ra_prefix_flags, UIP_ND6_RA_FLAG_ONLINK, 1)
    UPDATE_FLAG( "ra_prefix_a", ra_prefix_flags, UIP_ND6_RA_FLAG_AUTONOMOUS, 1)
    UPDATE_INT( "ra_prefix_vtime", ra_prefix_vtime, 1)
    UPDATE_INT( "ra_prefix_ptime", ra_prefix_ptime, 1)

    UPDATE_FLAG( "ra_rio_en", ra_rio_flags, CETIC_6LBR_MODE_SEND_RIO, 1)
    UPDATE_INT( "ra_rio_lifetime", ra_rio_lifetime, 1)

    UPDATE_INT( "rpl_instance_id", rpl_instance_id, 1)
    UPDATE_FLAG("dodag_manual", rpl_config, CETIC_6LBR_MODE_MANUAL_DODAG, 1)
    UPDATE_FLAG("dodag_global", rpl_config, CETIC_6LBR_MODE_GLOBAL_DODAG, 1)
    UPDATE_IPADDR("dodag_id", rpl_dodag_id, 1)
    UPDATE_INT( "rpl_preference", rpl_preference, 1)
    UPDATE_INT( "rpl_dio_intdoubl", rpl_dio_intdoubl, 1)
    UPDATE_INT( "rpl_dio_intmin", rpl_dio_intmin, 1)
    UPDATE_INT( "rpl_dio_redundancy", rpl_dio_redundancy, 1)
    UPDATE_INT( "rpl_default_lifetime", rpl_default_lifetime, 1)
    UPDATE_INT( "rpl_min_hoprankinc", rpl_min_hoprankinc, 1)
    UPDATE_INT( "rpl_max_rankinc", rpl_max_rankinc, 1)
    UPDATE_INT( "rpl_lifetime_unit", rpl_lifetime_unit, 1)

#if !LOG6LBR_STATIC
    UPDATE_INT( "log_level", log_level, 0)
    UPDATE_HEX( "log_services", log_services, 0)
#endif
    else {
      LOG6LBR_WARN("Unknown parameter '%s'\n", param);
      do_update=0;
    }
  }
  if(do_update) {
    store_nvm_config();
#if !LOG6LBR_STATIC
    if(nvm_data.log_level != 0xFF) {
      Log6lbr_level = nvm_data.log_level;
      Log6lbr_services = nvm_data.log_services;
    }
#endif
  }
  return do_update;
}
Пример #10
0
int
update_config(const char *name)
{
  const char *ptr = name;
  char *next;
  uint8_t reboot_needed = 0;
  uint8_t do_update = 1;
  uip_ipaddr_t loc_fipaddr;

  while(*ptr) {
    const char *param = ptr;

    next = index(ptr, '=');
    if(!next)
      break;
    *next = 0;
    ptr = next + 1;
    const char *value = ptr;

    next = index(ptr, '&');
    if(next) {
      *next = 0;
      ptr = next + 1;
    } else {
      ptr += strlen(ptr);
    }

    LOG6LBR_INFO("Got param: '%s' = '%s'\n", param, value);
    if (0) {
    }
    UPDATE_FLAG("smart_multi", mode, CETIC_MODE_SMART_MULTI_BR, 1)
    UPDATE_FLAG("wait_ra", mode, CETIC_MODE_WAIT_RA_MASK, 1)
    UPDATE_INT("channel", channel, 1)
    UPDATE_IPADDR("wsn_pre", wsn_net_prefix, 1)
    UPDATE_INT("wsn_pre_len", wsn_net_prefix_len, 1)
    UPDATE_FLAG("wsn_auto", mode, CETIC_MODE_WSN_AUTOCONF, 1)
    UPDATE_IPADDR("wsn_addr", wsn_ip_addr, 1)
    UPDATE_IPADDR("eth_pre", eth_net_prefix, 1)
    UPDATE_INT("eth_pre_len", eth_net_prefix_len, 1)
    UPDATE_FLAG("eth_auto", mode, CETIC_MODE_ETH_AUTOCONF, 1)
    UPDATE_IPADDR("eth_addr", eth_ip_addr, 1)
    UPDATE_IPADDR("eth_dft", eth_dft_router, 1)
    UPDATE_FLAG("ra_daemon", mode, CETIC_MODE_ROUTER_RA_DAEMON, 1)
    UPDATE_FLAG("rewrite", mode, CETIC_MODE_REWRITE_ADDR_MASK, 1)

    UPDATE_INT( "ra_lifetime", ra_router_lifetime, 1)
    UPDATE_INT( "ra_max_interval", ra_max_interval, 1)
    UPDATE_INT( "ra_min_interval", ra_min_interval, 1)
    UPDATE_INT( "ra_min_delay", ra_min_delay, 1)

    UPDATE_FLAG( "ra_pio", ra_prefix_flags, CETIC_6LBR_MODE_SEND_PIO, 1)
    UPDATE_FLAG( "ra_prefix_o", ra_prefix_flags, UIP_ND6_RA_FLAG_ONLINK, 1)
    UPDATE_FLAG( "ra_prefix_a", ra_prefix_flags, UIP_ND6_RA_FLAG_AUTONOMOUS, 1)
    UPDATE_INT( "ra_prefix_vtime", ra_prefix_vtime, 1)
    UPDATE_INT( "ra_prefix_ptime", ra_prefix_ptime, 1)

    UPDATE_FLAG( "ra_rio_en", ra_rio_flags, CETIC_6LBR_MODE_SEND_RIO, 1)
    UPDATE_INT( "ra_rio_lifetime", ra_rio_lifetime, 1)

    UPDATE_INT( "rpl_instance_id", rpl_instance_id, 1)
    UPDATE_INT( "rpl_preference", rpl_preference, 1)
    UPDATE_INT( "rpl_dio_intdoubl", rpl_dio_intdoubl, 1)
    UPDATE_INT( "rpl_dio_intmin", rpl_dio_intmin, 1)
    UPDATE_INT( "rpl_dio_redundancy", rpl_dio_redundancy, 1)
    UPDATE_INT( "rpl_default_lifetime", rpl_default_lifetime, 1)
    UPDATE_INT( "rpl_min_hoprankinc", rpl_min_hoprankinc, 1)
    UPDATE_INT( "rpl_lifetime_unit", rpl_lifetime_unit, 1)

    else {
      LOG6LBR_WARN("Unknown parameter '%s'\n", param);
      do_update=0;
    }
  }
  if(do_update) {
    store_nvm_config();
  }
  return !reboot_needed;
}
Пример #11
0
PROCESS_THREAD(cetic_6lbr_process, ev, data)
{
  PROCESS_BEGIN();

  cetic_6lbr_startup = clock_seconds();

#if CONTIKI_TARGET_NATIVE
  slip_config_handle_arguments(contiki_argc, contiki_argv);
  if (watchdog_interval) {
    process_start(&native_6lbr_watchdog, NULL);
  } else {
    LOG6LBR_WARN("6LBR Watchdog disabled\n");
  }
#endif

  LOG6LBR_INFO("Starting 6LBR version " CETIC_6LBR_VERSION " (" CONTIKI_VERSION_STRING ")\n");

  load_nvm_config();

  platform_init();

  process_start(&eth_drv_process, NULL);

  while(!ethernet_ready) {
    PROCESS_PAUSE();
  }

  //clean up any early packet
  uip_len = 0;
  process_start(&tcpip_process, NULL);

  PROCESS_PAUSE();

#if CETIC_NODE_INFO
  node_info_init();
#endif

  packet_filter_init();
  cetic_6lbr_init();

#if WEBSERVER
  process_start(&webserver_nogui_process, NULL);
#endif
#if UDPSERVER
  process_start(&udp_server_process, NULL);
#endif

  LOG6LBR_INFO("CETIC 6LBR Started\n");

#if CONTIKI_TARGET_NATIVE
  PROCESS_WAIT_EVENT();
  etimer_set(&reboot_timer, CLOCK_SECOND);
  PROCESS_WAIT_EVENT();
  switch (cetic_6lbr_restart_type) {
    case CETIC_6LBR_RESTART:
      LOG6LBR_INFO("Exiting...\n");
      exit(0);
      break;
    case CETIC_6LBR_REBOOT:
      LOG6LBR_INFO("Rebooting...\n");
      system("reboot");
      break;
    case CETIC_6LBR_HALT:
      LOG6LBR_INFO("Halting...\n");
      system("halt");
      break;
    default:
      //We should never end up here...
      exit(1);
  }
  //We should never end up here...
  exit(1);
#endif

  PROCESS_END();
}
Пример #12
0
void
check_nvm(nvm_data_t * nvm_data, int reset)
{
  uint8_t flash = 0;
  uip_ipaddr_t loc_fipaddr;
  uip_ip4addr_t loc_fip4addr;

  if(reset || nvm_data->magic != CETIC_6LBR_NVM_MAGIC
     || nvm_data->version > CETIC_6LBR_NVM_CURRENT_VERSION) {
    //NVM is invalid or we are rollbacking from another version
    //Set all data to default values
    if (!reset) {
      LOG6LBR_ERROR
        ("Invalid NVM magic number or unsupported NVM version, reseting it...\n");
    }
    nvm_data->magic = CETIC_6LBR_NVM_MAGIC;
    nvm_data->version = CETIC_6LBR_NVM_VERSION_0;

    CETIC_6LBR_NVM_DEFAULT_ETH_NET_PREFIX(&loc_fipaddr);
    memcpy(&nvm_data->eth_net_prefix, &loc_fipaddr.u8, 16);

    CETIC_6LBR_NVM_DEFAULT_ETH_IP_ADDR(&loc_fipaddr);
    memcpy(&nvm_data->eth_ip_addr, &loc_fipaddr.u8, 16);

    CETIC_6LBR_NVM_DEFAULT_WSN_NET_PREFIX(&loc_fipaddr);
    memcpy(&nvm_data->wsn_net_prefix, &loc_fipaddr.u8, 16);

    CETIC_6LBR_NVM_DEFAULT_WSN_IP_ADDR(&loc_fipaddr);
    memcpy(&nvm_data->wsn_ip_addr, &loc_fipaddr.u8, 16);

    CETIC_6LBR_NVM_DEFAULT_ETH_DFT_ROUTER(&loc_fipaddr);
    memcpy(&nvm_data->eth_dft_router, &loc_fipaddr.u8, 16);

    nvm_data->rpl_version_id = CETIC_6LBR_NVM_DEFAULT_RPL_VERSION_ID;

    nvm_data->mode = CETIC_6LBR_NVM_DEFAULT_MODE;

    nvm_data->channel = CETIC_6LBR_NVM_DEFAULT_CHANNEL;

    flash = 1;
  }
  if ( nvm_data->version < CETIC_6LBR_NVM_VERSION_1)
  {
    if (!reset) {
      LOG6LBR_WARN("Migrate NVM version 0 towards 1\n");
    }
    nvm_data->version = CETIC_6LBR_NVM_VERSION_1;

    nvm_data->global_flags = CETIC_6LBR_NVM_DEFAULT_GLOBAL_FLAGS;

    nvm_data->wsn_net_prefix_len = CETIC_6LBR_NVM_DEFAULT_WSN_NET_PREFIX_LEN;
    nvm_data->eth_net_prefix_len = CETIC_6LBR_NVM_DEFAULT_ETH_NET_PREFIX_LEN;

    nvm_data->ra_flags = CETIC_6LBR_NVM_DEFAULT_RA_FLAGS;
    nvm_data->ra_router_lifetime = CETIC_6LBR_NVM_DEFAULT_RA_ROUTER_LIFETIME;
    nvm_data->ra_max_interval = CETIC_6LBR_NVM_DEFAULT_RA_MAX_INTERVAL;
    nvm_data->ra_min_interval = CETIC_6LBR_NVM_DEFAULT_RA_MIN_INTERVAL;
    nvm_data->ra_min_delay = CETIC_6LBR_NVM_DEFAULT_RA_MIN_DELAY;

    nvm_data->ra_prefix_flags = CETIC_6LBR_NVM_DEFAULT_RA_PREFIX_FLAGS;
    nvm_data->ra_prefix_vtime = CETIC_6LBR_NVM_DEFAULT_RA_PREFIX_VTIME;
    nvm_data->ra_prefix_ptime = CETIC_6LBR_NVM_DEFAULT_RA_PREFIX_PTIME;
    nvm_data->ra_rio_flags = CETIC_6LBR_NVM_DEFAULT_RA_RIO_FLAGS;
    nvm_data->ra_rio_lifetime = CETIC_6LBR_NVM_DEFAULT_RA_RIO_LIFETIME;

    nvm_data->rpl_instance_id = CETIC_6LBR_NVM_DEFAULT_RPL_INSTANCE_ID;
    nvm_data->rpl_preference = CETIC_6LBR_NVM_DEFAULT_RPL_PREFERENCE;
    nvm_data->rpl_dio_intdoubl = CETIC_6LBR_NVM_DEFAULT_RPL_DIO_INT_DOUBLING;
    nvm_data->rpl_dio_intmin = CETIC_6LBR_NVM_DEFAULT_RPL_DIO_MIN_INT;
    nvm_data->rpl_dio_redundancy = CETIC_6LBR_NVM_DEFAULT_RPL_DIO_REDUNDANCY;
    nvm_data->rpl_default_lifetime = CETIC_6LBR_NVM_DEFAULT_RPL_DEFAULT_LIFETIME;
    nvm_data->rpl_min_hoprankinc = CETIC_6LBR_NVM_DEFAULT_RPL_MIN_HOP_RANK_INC;
    nvm_data->rpl_lifetime_unit = CETIC_6LBR_NVM_DEFAULT_RPL_LIFETIME_UNIT;

    flash = 1;
  }
  if ( nvm_data->version < CETIC_6LBR_NVM_VERSION_2)
  {
    if (!reset) {
      LOG6LBR_WARN("Migrate NVM version %d towards %d\n", nvm_data->version, CETIC_6LBR_NVM_VERSION_2);
    }
    nvm_data->version = CETIC_6LBR_NVM_VERSION_2;

    nvm_data->security_layer = CETIC_6LBR_NVM_DEFAULT_SECURITY_LAYER;
    nvm_data->security_level = CETIC_6LBR_NVM_DEFAULT_SECURITY_LEVEL;
    uint8_t key[16] = CETIC_6LBR_NVM_DEFAULT_SECURITY_KEY;
    memcpy(nvm_data->noncoresec_key, key, sizeof(key));

    nvm_data->pan_id = CETIC_6LBR_NVM_DEFAULT_PANID;

    nvm_data->rpl_config = CETIC_6LBR_NVM_DEFAULT_RPL_CONFIG;
    nvm_data->rpl_max_rankinc = CETIC_6LBR_NVM_DEFAULT_RPL_MAX_RANK_INC;
    CETIC_6LBR_NVM_DEFAULT_RPL_DODAG_ID(&loc_fipaddr);
    memcpy(&nvm_data->rpl_dodag_id, &loc_fipaddr.u8, 16);
    nvm_data->eth_ip64_flags = CETIC_6LBR_NVM_DEFAULT_IP64_FLAGS;
    CETIC_6LBR_NVM_DEFAULT_IP64_ADDRESS(&loc_fip4addr);
    memcpy(&nvm_data->eth_ip64_addr, &loc_fip4addr.u8, sizeof(loc_fip4addr));
    CETIC_6LBR_NVM_DEFAULT_IP64_NETMASK(&loc_fip4addr);
    memcpy(&nvm_data->eth_ip64_netmask, &loc_fip4addr.u8, sizeof(loc_fip4addr));
    CETIC_6LBR_NVM_DEFAULT_IP64_GATEWAY(&loc_fip4addr);
    memcpy(&nvm_data->eth_ip64_gateway, &loc_fip4addr.u8, sizeof(loc_fip4addr));

    nvm_data->dns_flags = CETIC_6LBR_NVM_DEFAULT_DNS_FLAGS;
    strcpy((char *)nvm_data->dns_host_name, CETIC_6LBR_NVM_DEFAULT_DNS_HOST_NAME);

    nvm_data->webserver_port = CETIC_6LBR_NVM_DEFAULT_WEBSERVER_PORT;

    nvm_data->mac_layer = CETIC_6LBR_NVM_DEFAULT_MAC_LAYER;

    nvm_data->noncoresec_flags = CETIC_6LBR_NVM_DEFAULT_NONCORESEC_FLAGS;

    uint8_t context[8] = CETIC_6LBR_NVM_DEFAULT_6LOWPAN_CONTEXT_0;
    memcpy(nvm_data->wsn_6lowpan_context_0, context, sizeof(context));

    CETIC_6LBR_NVM_DEFAULT_DNS_SERVER(&loc_fipaddr);
    memcpy(&nvm_data->dns_server, &loc_fipaddr.u8, 16);

    nvm_data->log_level = CETIC_6LBR_NVM_DEFAULT_LOG_LEVEL;
    nvm_data->log_services = CETIC_6LBR_NVM_DEFAULT_LOG_SERVICES;

    flash = 1;
  }

  if(flash) {
    nvm_data_write();
  }
}