Пример #1
0
/**
   Reaction on incoming UPDATE-DEVICE

   Issue UPDATE-DEVICE.indication
 */
void zb_aps_in_update_device(zb_uint8_t param)
{
  /* get source address from the nwk header and convert it to long address */
  zb_apsme_update_device_pkt_t *pkt = (zb_apsme_update_device_pkt_t *)ZB_BUF_BEGIN(ZB_BUF_FROM_REF(param));
  zb_apsme_update_device_ind_t *ind = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsme_update_device_ind_t);

  TRACE_MSG(TRACE_SECUR3, ">>zb_aps_in_update_device %d", (FMT__H, param));

  {
    zb_uint16_t src_short_addr = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsde_data_indication_t)->src_addr;
    zb_address_ieee_by_short(src_short_addr, ind->src_address);
  }

  ZB_IEEE_ADDR_COPY(ind->device_address, pkt->device_address);
  ZB_LETOH16(&ind->device_short_address, &pkt->device_short_address);
  /* We have short and long addresses of the device UPDATE-DEVICE is
   * about. Remember it. */
  {
    zb_address_ieee_ref_t ref;
    (void)zb_address_update(ind->device_address, ind->device_short_address, ZB_FALSE, &ref);
  }
  ind->status = pkt->status;

  ZB_SCHEDULE_CALLBACK(zb_apsme_update_device_indication, param);

  TRACE_MSG(TRACE_SECUR3, "<<zb_aps_in_update_device", (FMT__0));
}
Пример #2
0
MAIN()
{
  ARGV_UNUSED;

#ifndef KEIL
  if ( argc < 3 )
  {
    printf("%s <read pipe path> <write pipe path>\n", argv[0]);
    return 0;
  }
#endif

#if defined ZB_NS_BUILD && defined ZB_SECURITY
  if ( argc > 3
       && !strcmp(argv[3], "auth") )
  {
    g_auth = 1;
  }
#endif

  /* Init device, load IB values from nvram or set it to default */
#ifndef ZB8051
  ZB_INIT("zdo_zed", argv[1], argv[2]);
#else
  ZB_INIT("zdo_zed", "2", "2");
#endif

  /* set ieee addr */
  ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_ieee_addr);
#ifndef ZB_NS_BUILD
  ZB_UPDATE_LONGMAC();
#endif


#ifdef ZB_SECURITY
  /* turn security */
  ZB_NIB_SECURITY_LEVEL() = g_auth ? 1 : 0;
#endif

  /* become an ED */
  ZB_NIB_DEVICE_TYPE() = ZB_NWK_DEVICE_TYPE_ED;
  ZB_PIB_RX_ON_WHEN_IDLE() = ZB_TRUE;

  if (zdo_dev_start() != RET_OK)
  {
    TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0));
  }
  else
  {
    zdo_main_loop();
  }

  TRACE_DEINIT();

  MAIN_RETURN(0);
}
Пример #3
0
/*
  7.3.6 sends orphan notification command
  return RET_OK, RET_ERROR
*/
zb_ret_t zb_orphan_notification_command()
{

  zb_ret_t ret;
  zb_uint8_t mhr_len;
  zb_uint8_t *ptr = NULL;
  zb_mac_mhr_t mhr;

/*
  Orphan notification command
  1. Fill MHR fields
  - set dst pan id = 0xffff
  - set dst addr = 0xffff
  2. Fill FCF
  - set frame pending = 0, ack req = 0, security enabled = 0
  - set dst addr mode to ZB_ADDR_16BIT_DEV_OR_BROADCAST
  - set src addr mode to ZB_ADDR_64BIT_DEV
  3. Set command frame id = 0x07 (Beacon request)
*/

  TRACE_MSG(TRACE_MAC2, ">>orphan_notif_cmd", (FMT__0));

  mhr_len = zb_mac_calculate_mhr_length(ZB_ADDR_64BIT_DEV, ZB_ADDR_16BIT_DEV_OR_BROADCAST, 1);
  {
    zb_uint8_t packet_length = mhr_len + 1;
    ZB_BUF_INITIAL_ALLOC(MAC_CTX().operation_buf, packet_length, ptr);
    ZB_ASSERT(ptr);
    ZB_BZERO(ptr, packet_length);
  }

  /* TODO: optimize FC fill */
  ZB_BZERO2(mhr.frame_control);
  ZB_FCF_SET_FRAME_TYPE(mhr.frame_control, MAC_FRAME_COMMAND);
  ZB_FCF_SET_DST_ADDRESSING_MODE(mhr.frame_control, ZB_ADDR_16BIT_DEV_OR_BROADCAST);
  ZB_FCF_SET_SRC_ADDRESSING_MODE(mhr.frame_control, ZB_ADDR_64BIT_DEV);
  ZB_FCF_SET_PANID_COMPRESSION_BIT(mhr.frame_control, 1);
  ZB_FCF_SET_FRAME_VERSION(mhr.frame_control, MAC_FRAME_VERSION);

  /* 7.2.1 General MAC frame format */
  mhr.seq_number = ZB_MAC_DSN();
  ZB_INC_MAC_DSN();

  mhr.dst_pan_id = ZB_BROADCAST_PAN_ID;
  mhr.dst_addr.addr_short = ZB_MAC_SHORT_ADDR_NO_VALUE;
  ZB_IEEE_ADDR_COPY(mhr.src_addr.addr_long, ZB_PIB_EXTENDED_ADDRESS());

  zb_mac_fill_mhr(ptr, &mhr);
  *(ptr + mhr_len) = MAC_CMD_ORPHAN_NOTIFICATION;
  MAC_ADD_FCS(MAC_CTX().operation_buf);

  ret = ZB_TRANS_SEND_COMMAND(mhr_len, MAC_CTX().operation_buf);

  TRACE_MSG(TRACE_MAC2, "<<orphan_notif_cmd %hd", (FMT__H, ret));
  return ret;
}
Пример #4
0
MAIN()
{
  ARGV_UNUSED;

#ifndef KEIL
  if ( argc < 3 )
  {
    printf("%s <read pipe path> <write pipe path>\n", argv[0]);
    return 0;
  }
#endif

  /* Init device, load IB values from nvram or set it to default */
#ifndef ZB8051
  ZB_INIT("zdo_zed1_", argv[1], argv[2]);
#else
  ZB_INIT("zdo_zed1_", "2", "2");
#endif

  /* set ieee addr */
  ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_ieee_addr);
#ifndef ZB_NS_BUILD
  ZB_UPDATE_LONGMAC();
#endif

#ifdef ZB_SECURITY
  /* turn off security */
  ZB_NIB_SECURITY_LEVEL() = 0;
#endif

  MAC_ADD_VISIBLE_LONG(g_zr_ieee_addr);
  MAC_ADD_INVISIBLE_SHORT(0);   /* ignore beacons from ZC */

  /* become an ED */
  ZB_NIB_DEVICE_TYPE() = ZB_NWK_DEVICE_TYPE_ED;
  ZB_PIB_RX_ON_WHEN_IDLE() = ZB_FALSE;

  /* configure poll timer */
  ZDO_CTX().conf_attr.nwk_indirect_poll_rate = 2*ZB_TIME_ONE_SECOND;

  if (zdo_dev_start() != RET_OK)
  {
    TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0));
  }
  else
  {
    zdo_main_loop();
  }

  TRACE_DEINIT();

  MAIN_RETURN(0);
}
Пример #5
0
MAIN()
{
  ARGV_UNUSED;

#ifndef KEIL
  if ( argc < 3 )
  {
    printf("%s <read pipe path> <write pipe path>\n", argv[0]);
    return 0;
  }
#endif

  /* Init device, load IB values from nvram or set it to default */
#ifndef ZB8051
  ZB_INIT("zdo_zc", argv[1], argv[2]);
#else
  ZB_INIT("zdo_zc", "1", "1");
#endif

  /* let's always be coordinator */
  ZB_AIB().aps_designated_coordinator = 1;

  /* set ieee addr */
  ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_ieee_addr);

#ifndef ZB_NS_BUILD
  ZB_UPDATE_LONGMAC();
#endif

#ifdef ZB_SECURITY
  /* turn off security */
  ZB_NIB_SECURITY_LEVEL() = 0;
#endif

  /* accept only one child */
  ZB_NWK().max_children = 3;

  /* configure join duration */
  ZDO_CTX().conf_attr.permit_join_duration = 10;

  if ( zdo_dev_start() != RET_OK )
  {
    TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0));
  }
  else
  {
    zdo_main_loop();
  }

  TRACE_DEINIT();

  MAIN_RETURN(0);
}
Пример #6
0
MAIN()
{
  ARGV_UNUSED;

#ifndef KEIL
  if ( argc < 3 )
  {
    printf("%s <read pipe path> <write pipe path>\n", argv[0]);
    return 0;
  }
#endif

  /* Init device, load IB values from nvram or set it to default */
#ifndef ZB8051
  ZB_INIT("zdo_zr1", argv[1], argv[2]);
#else
  ZB_INIT("zdo_zr1", "2", "2");
#endif

  /* set ieee addr */
  ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_ieee_addr);

  /* join as a router */
  ZB_NIB_DEVICE_TYPE() = ZB_NWK_DEVICE_TYPE_ROUTER;
  ZB_NWK().max_children = 0;

#ifndef ZB_NS_BUILD
  ZB_UPDATE_LONGMAC();
  ZB_UPDATE_PAN_ID();
#endif

#ifdef ZB_SECURITY
  /* turn off security */
  ZB_NIB_SECURITY_LEVEL() = 0;
#endif

  if (zdo_dev_start() != RET_OK)
  {
    TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0));
  }
  else
  {
    zdo_main_loop();
  }

  TRACE_DEINIT();

  MAIN_RETURN(0);
}
Пример #7
0
MAIN()
{
  ARGV_UNUSED;

#ifndef KEIL
  if ( argc < 3 )
  {
    printf("%s <read pipe path> <write pipe path>\n", argv[0]);
    return 0;
  }
#endif

  /* Init device, load IB values from nvram or set it to default */
#ifndef ZB8051
  ZB_INIT("zdo_zc", argv[1], argv[2]);
#else
  ZB_INIT("zdo_zc", "1", "1");
#endif

  /* let's always be coordinator */
  ZB_AIB().aps_designated_coordinator = 1;
  MAC_PIB().mac_pan_id = 0x1aaa;
  /* set ieee addr */
  ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_ieee_addr);

#ifndef ZB_NS_BUILD
  ZB_UPDATE_LONGMAC();
  ZB_UPDATE_PAN_ID();
#endif

#ifdef ZB_SECURITY
  /* turn off security */
  ZB_NIB_SECURITY_LEVEL() = 0;
#endif

  if ( zdo_dev_start() != RET_OK )
  {
    TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0));
  }
  else
  {
    zdo_main_loop();
  }

  TRACE_DEINIT();

  MAIN_RETURN(0);
}
Пример #8
0
void zb_aps_in_remove_device(zb_uint8_t param)
{
  /* get source address from the nwk header and convert it to long address */
  zb_apsme_remove_device_pkt_t *pkt = (zb_apsme_remove_device_pkt_t *)ZB_BUF_BEGIN(ZB_BUF_FROM_REF(param));
  zb_apsme_remove_device_ind_t *ind = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsme_remove_device_ind_t);

  TRACE_MSG(TRACE_SECUR3, ">>zb_aps_in_remove_device %d", (FMT__H, param));

  {
    zb_uint16_t src_short_addr = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsde_data_indication_t)->src_addr;
    zb_address_ieee_by_short(src_short_addr, ind->src_address);
  }
  ZB_IEEE_ADDR_COPY(ind->child_address, pkt->child_address);

  ZB_SCHEDULE_CALLBACK(zb_apsme_remove_device_indication, param);

  TRACE_MSG(TRACE_SECUR3, "<<zb_aps_in_remove_device", (FMT__0));
}
Пример #9
0
MAIN()
{
  ARGV_UNUSED;

#ifndef KEIL
  if ( argc < 3 )
  {
    printf("%s <read pipe path> <write pipe path>\n", argv[0]);
    return 0;
  }
#endif

  /* Init device, load IB values from nvram or set it to default */
#ifndef ZB8051
  ZB_INIT("zdo_zr1", argv[1], argv[2]);
#else
  ZB_INIT("zdo_zr1", "2", "2");
#endif
  ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_ieee_addr);

#ifndef ZB_NS_BUILD
  ZB_UPDATE_LONGMAC();
  ZB_UPDATE_PAN_ID();
#endif

#ifdef ZB_SECURITY
  ZG->nwk.nib.security_level = 0;
#endif


  if (zdo_dev_start() != RET_OK)
  {
    TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0));
  }
  else
  {
    zdo_main_loop();
  }

  TRACE_DEINIT();

  MAIN_RETURN(0);
}
Пример #10
0
/**
   Reaction on TRANSPORT-KEY APS command
 */
void zb_aps_in_transport_key(zb_uint8_t param)
{
  zb_transport_key_nwk_key_dsc_pkt_t *dsc =
    (zb_transport_key_nwk_key_dsc_pkt_t *)ZB_BUF_BEGIN(ZB_BUF_FROM_REF(param));

  TRACE_MSG(TRACE_SECUR3, ">>zb_aps_in_transport_key %d", (FMT__H, param));

  /* See 4.4.3.3  Upon Receipt of a Transport-Key Command */

  switch (dsc->key_type)
  {
    case ZB_STANDARD_NETWORK_KEY:
      if (
        /* key is for me */
        ZB_IEEE_ADDR_CMP(dsc->dest_address, ZB_PIB_EXTENDED_ADDRESS())
        /* key is for all */
          || ZB_IEEE_ADDR_IS_ZERO(dsc->dest_address))
      {
        /* This key is for me. Issue APSME-TRANSPORT-KEY.indication. ZDO will
         * setup keys and remember TC address.
         */
        zb_apsme_transport_key_indication_t *ind = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsme_transport_key_indication_t);

        TRACE_MSG(TRACE_SECUR3, "in std nwk key #%d for me", (FMT__D, dsc->seq_number));
        ind->key_type = dsc->key_type;
        ZB_IEEE_ADDR_COPY(ind->src_address, dsc->source_address);
        ind->key.nwk.key_seq_number = dsc->seq_number;
        ZB_MEMCPY(ind->key.nwk.key, dsc->key, ZB_CCM_KEY_SIZE);
        ZB_SCHEDULE_CALLBACK(zb_apsme_transport_key_indication, param);

/* #ifdef ZB_ROUTER_ROLE */
/* This feature should be processed at request */
#if 0
        if (ZB_IEEE_ADDR_IS_ZERO(dsc->dest_address)
            /* && check for secured transfer at nwk level */
            && ZB_IEEE_ADDR_CMP(dsc->source_address, ZB_AIB().trust_center_address))
        {
          /*
           * Need to pass key to all rx-off-when-idle children. Need another
           * packet buffer for it.
           * Do the rest in the calback: this is blocked
           * buffer alloc. Not need to save current key: it will be aleady
           * assigned, so can send my own key.
           */
          ZG->aps.tmp.neighbor_table_iterator = zb_nwk_neighbor_next_ze_children_rx_off_i(0);
          ZG->aps.tmp.key_seq_number = ind->key.nwk.key_seq_number;
          if (ZG->aps.tmp.neighbor_table_iterator != (zb_ushort_t)~0)
          {
            TRACE_MSG(TRACE_SECUR3, "send key #%hd to all ZE", (FMT__H, dsc->seq_number));
            zb_get_out_buf_delayed(zb_aps_pass_nwk_key_to_children);
          }
        }
#endif  /* ZB_ROUTER_ROLE */
      }
#ifdef ZB_ROUTER_ROLE
      else
      {
        zb_address_ieee_ref_t addr_ref;
        zb_neighbor_tbl_ent_t *nbe;
        /* Search for child in the Neighbor table, mark child as Authenticated,
         * send key to it using unsecured NWK transfer */
        if (zb_address_by_ieee(dsc->dest_address, ZB_FALSE, ZB_FALSE, &addr_ref) == RET_OK
            && zb_nwk_neighbor_get(addr_ref, ZB_FALSE, &nbe) == RET_OK
            && (nbe->relationship == ZB_NWK_RELATIONSHIP_UNAUTHENTICATED_CHILD
                || nbe->relationship == ZB_NWK_RELATIONSHIP_CHILD))
        {
          zb_uint16_t addr;
          zb_address_short_by_ref(&addr, addr_ref);
          TRACE_MSG(TRACE_SECUR3, "send key #%hd to ZE %d, auth ok", (FMT__H_D, dsc->seq_number, addr));
          zb_aps_send_command(param, addr, APS_CMD_TRANSPORT_KEY,
                              (nbe->relationship != ZB_NWK_RELATIONSHIP_UNAUTHENTICATED_CHILD));
          nbe->relationship = ZB_NWK_RELATIONSHIP_CHILD;
        }
        else
        {
          TRACE_MSG(TRACE_SECUR1, "child " TRACE_FORMAT_64 " not found", (FMT__A, TRACE_ARG_64(dsc->dest_address)));
          zb_free_buf(ZB_BUF_FROM_REF(param));
        }
      }
#endif  /* ZB_ROUTER_ROLE */
      break;
    default:
      break;
  }

  TRACE_MSG(TRACE_SECUR3, "<<zb_aps_in_transport_key", (FMT__0));
}
Пример #11
0
void zb_aps_secure_frame(zb_buf_t *src, zb_uint_t mac_hdr_size, zb_buf_t *dst)
{
  zb_uint8_t *aps_hdr;
  zb_uint8_t *payload;
  zb_secur_ccm_nonce_t nonce;
  zb_uint8_t *dp;
  zb_uint8_t *key;
  zb_ushort_t hdrs_size;
  zb_aps_nwk_aux_frame_hdr_t *aux;

  {
    zb_nwk_hdr_t *nwk_hdr = (zb_nwk_hdr_t *)(ZB_BUF_BEGIN(src) + mac_hdr_size);
    aps_hdr = (zb_uint8_t *)nwk_hdr + ZB_NWK_HDR_SIZE(nwk_hdr->frame_control);
  }

  aux = (zb_aps_nwk_aux_frame_hdr_t *)(aps_hdr + ZB_APS_HDR_SIZE(*aps_hdr));

  if (ZB_SECUR_AUX_HDR_GET_KEY_TYPE(aux->secur_control) == ZB_SECUR_DATA_KEY)
  {
    payload = (zb_uint8_t *)aux + sizeof(zb_aps_data_aux_frame_hdr_t);
    /* get src and dst address from APS header, get data key */
    key = 0;                    /* aps data key */
  }
  else
  {
    /* nwk key */
    payload = (zb_uint8_t *)aux + sizeof(zb_aps_nwk_aux_frame_hdr_t);
    key = ZG->nwk.nib.secur_material_set[ZG->nwk.nib.active_secur_material_i].key;
  }
  /* fill nonce - see 4.5.2.2 */

  nonce.frame_counter = aux->frame_counter;
  nonce.secur_control = aux->secur_control;
  ZB_IEEE_ADDR_COPY(nonce.source_address, ZB_PIB_EXTENDED_ADDRESS());

  hdrs_size = payload - ZB_BUF_BEGIN(src);

  /* Secure  */
  (void)zb_ccm_encrypt_n_auth(key,
                              (zb_uint8_t *)&nonce,
                              (zb_uint8_t *)aps_hdr, (payload - aps_hdr),
                              (zb_uint8_t *)payload, (ZB_BUF_LEN(src) - hdrs_size),
                              dst);
  ZB_BUF_ALLOC_LEFT(dst, (aps_hdr - ZB_BUF_BEGIN(src)), dp);
  /* copy headers */
  ZB_MEMCPY(dp, ZB_BUF_BEGIN(src), (aps_hdr - ZB_BUF_BEGIN(src)));

  /* clear security level - see 4.4.1.1/11 */
  aux = (zb_aps_nwk_aux_frame_hdr_t *)(ZB_BUF_BEGIN(dst) + ((zb_uint8_t*)aux - ZB_BUF_BEGIN(src)));
  if (ZB_SECUR_AUX_HDR_GET_KEY_TYPE(aux->secur_control) == ZB_SECUR_DATA_KEY)
  {
    aux->secur_control = ZB_APS_DATA_STD_SECUR_CONTROL_ZEROED_LEVEL;
  }
  else
  {
    aux->secur_control = ZB_APS_NWK_STD_SECUR_CONTROL_ZEROED_LEVEL;
  }

  TRACE_MSG(TRACE_SECUR3, "secured aps frm %p[%hd] -> %p hdrs_size %hd fcnt %lx", (FMT__P_H_P_H_L,
                           src, ZB_BUF_LEN(src), dst, hdrs_size, aux->frame_counter));

}
Пример #12
0
zb_ret_t zb_read_formdesc_data()
{
  zb_uint8_t read_bytes = 0;
  zb_uint8_t buf[8];
  zb_ieee_addr_t parent_addr;
  zb_uint16_t s_parent_addr;
  read_bytes = ZB_CONFIG_SIZE;

  /* Stack profile */
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_uint8_t));    
  /* Parent's long addr */
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_ieee_addr_t));  
  /* this can be replaced by memcmp, but it will cost more code space*/
  if ((buf[0]&buf[1]&buf[2]&buf[3]&buf[4]&buf[5]&buf[6]&buf[7])!=0xFF)
  {
	  zb_neighbor_tbl_ent_t *nbt;
	  ZB_IEEE_ADDR_COPY(parent_addr, buf);
	  /* channel mask */
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_uint32_t));
	  ZB_AIB().aps_channel_mask = *(zb_uint32_t*)buf;
	  /* Parent's short address */
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_uint16_t));
	  s_parent_addr = *(zb_uint16_t*)buf;
	  /*we have long and short parent's address, so we can update neighbour table now */
	  zb_address_update(parent_addr, s_parent_addr,ZB_FALSE, &ZG->nwk.handle.parent);
	  zb_nwk_neighbor_get(ZG->nwk.handle.parent, ZB_TRUE, &nbt);
	  nbt->relationship = ZB_NWK_RELATIONSHIP_PARENT;
	  nbt->device_type = ZB_NWK_DEVICE_TYPE_COORDINATOR;
	  nbt->rx_on_when_idle = ZB_TRUE;
	  nbt->addr_ref = ZG->nwk.handle.parent;
      

	  /* Device depth */
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_uint8_t));
	  ZB_NIB_DEPTH() = buf[0];
	  /* Short PanID */
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_uint16_t));
	  MAC_PIB().mac_pan_id = *(zb_uint16_t*)buf;
	  ZB_UPDATE_PAN_ID();
	  /* Extended PanID */
	  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_ext_pan_id_t));	  
	  ZB_IEEE_ADDR_COPY(ZG->nwk.nib.extended_pan_id, buf);
	  /* Short address */ 
  read_bytes+=zb_read_nvram(ZB_CONFIG_PAGE + read_bytes, buf, sizeof(zb_uint16_t));
	  MAC_PIB().mac_short_address = *(zb_uint16_t *)buf;
	  ZB_UPDATE_SHORT_ADDR();
/* define to pass bv-31, it contradicts specification, so this hack only for test*/
#ifdef TP_PRO_BV_31
	{
	  zb_uint8_t channel_number;
	  /*We're joined already */	  
	  ZG->nwk.handle.joined = 1;
	  for(channel_number = ZB_MAC_START_CHANNEL_NUMBER; channel_number <= ZB_MAC_MAX_CHANNEL_NUMBER; channel_number++)
	  {
	      /* check channel mask */
	      if (ZB_DEFAULT_APS_CHANNEL_MASK & (1l << channel_number))
	      {	   
	        ZB_TRANSCEIVER_SET_CHANNEL(channel_number);
			break;
	      }
	   }	 
	   ZB_AIB_APS_COUNTER() = 0xF0;
	}
#endif 
  }
  return RET_OK;
}