Esempio n. 1
0
void zb_mac_store_pan_desc(zb_buf_t *beacon_buf)
{
  zb_uint8_t *mac_hdr = ZB_MAC_GET_FCF_PTR(ZB_BUF_BEGIN(beacon_buf));
  zb_mac_mhr_t mhr;
  zb_uint8_t mhr_len;
  zb_pan_descriptor_t pan_desc;
  zb_pan_descriptor_t *pan_desc_buf;
  zb_buf_t *desc_list_buf;
  zb_uint8_t desc_count;

  TRACE_MSG(TRACE_NWK1, ">>store_pan_desc %p", (FMT__P, beacon_buf));

  mhr_len = zb_parse_mhr(&mhr, mac_hdr);

  TRACE_MSG(TRACE_NWK3, "add pan desc", (FMT__0));
  pan_desc.coord_addr_mode = ZB_FCF_GET_SRC_ADDRESSING_MODE(&mhr.frame_control);
  pan_desc.coord_pan_id = mhr.src_pan_id;
  ZB_MEMCPY(&pan_desc.coord_address, &mhr.src_addr, sizeof(union zb_addr_u));
  pan_desc.logical_channel = ZB_MAC_GET_CURRENT_LOGICAL_CHANNEL();


  ZB_GET_SUPERFRAME(mac_hdr, mhr_len, &pan_desc.super_frame_spec);

  pan_desc.gts_permit = 0; /* use ZB_MAC_GET_GTS_FIELDS() to get exact gts value.
                              Zigbee uses beaconless mode, so gts is not used always */

  pan_desc.link_quality = ZB_MAC_GET_LQI(beacon_buf);

  if (MAC_CTX().rt_ctx.active_scan.pan_desc_buf_param == ZB_UNDEFINED_BUFFER)
  {
    desc_list_buf = beacon_buf;
    ZB_BUF_REUSE(desc_list_buf);
    MAC_CTX().rt_ctx.active_scan.pan_desc_buf_param = ZB_REF_FROM_BUF(beacon_buf);
  }
  else
  {
    desc_list_buf = ZB_BUF_FROM_REF(MAC_CTX().rt_ctx.active_scan.pan_desc_buf_param);
  }

  /* do not calculate pan descriptors number - it can be calculated using buffer length  */
  /* in this check take into account size of scan confirm structure - descriptors will follow it */
  desc_count = ZB_BUF_LEN(desc_list_buf) / sizeof(zb_pan_descriptor_t);

  if ( (ZB_BUF_GET_FREE_SIZE(desc_list_buf) >= (sizeof(zb_pan_descriptor_t) + sizeof(zb_mac_scan_confirm_t))) &&
       desc_count < ZB_ACTIVE_SCAN_MAX_PAN_DESC_COUNT)
  {
    ZB_BUF_ALLOC_RIGHT(desc_list_buf, sizeof(zb_pan_descriptor_t), pan_desc_buf);
    ZB_MEMCPY(pan_desc_buf, &pan_desc, sizeof(zb_pan_descriptor_t));
  }
  else
  {
    TRACE_MSG(TRACE_NWK3, "stop scan, no free space", (FMT__0));
    MAC_CTX().rt_ctx.active_scan.stop_scan = 1;
  }

  TRACE_MSG(TRACE_NWK1, "<<store_pan_desc", (FMT__0));
}
Esempio n. 2
0
static void send_data()
{
  zb_buf_t *buf = NULL;
  zb_apsde_data_req_t req;
  zb_uint8_t *ptr = NULL;
  zb_short_t i;

  buf = zb_get_out_buf();
  req.dst_addr.addr_short = 0; /* send to ZC */
  req.addr_mode = ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
  req.tx_options = ZB_APSDE_TX_OPT_ACK_TX;
  req.radius = 1;
  req.profileid = 2;
  req.src_endpoint = 10;
  req.dst_endpoint = 10;

  buf->u.hdr.handle = 0x11;
  ZB_BUF_INITIAL_ALLOC(buf, 80, ptr);

  for (i = 0 ; i < ZB_TEST_DATA_SIZE ; ++i)
  {
    ptr[i] = i % 32 + '0';
  }
  ZB_MEMCPY(
    ZB_GET_BUF_TAIL(buf, sizeof(req)),
    &req, sizeof(req));

  TRACE_MSG(TRACE_APS3, "Sending apsde_data.request", (FMT__0));

  ZB_SCHEDULE_CALLBACK(zb_apsde_data_request, ZB_REF_FROM_BUF(buf));
}
Esempio n. 3
0
/*
  Process an incoming route request and decide if it needs to be forwarded
  or a route reply needs to be generated. This function will check the
  discovery table to see if we received the same route request previously.
  If we did, then it will compare the path cost to see if the incoming route
  request has a more efficient path. If so, then it will replace the discovery
  entry info with the info from this route request.

  If its a new route request, then it will create a route discovery entry and a
  routing table entry. It will then check to see if its the destination. If so, then
  a route reply will be sent. Otherwise, it will relay the route request via
  broadcast.
*/
void zb_nwk_mesh_rreq_handler(zb_buf_t *buf, zb_nwk_hdr_t *nwk_hdr, zb_nwk_cmd_rreq_t *nwk_cmd_rreq) 
{
  zb_uint8_t ret = RET_OK;
  zb_uint8_t path_cost = 0;
  zb_nwk_route_discovery_t *disc_ent = NULL;
  zb_nwk_routing_t *routing_ent = NULL;

  TRACE_MSG(TRACE_NWK1, ">> rreq_handler buf %p hdr %p cmd %p", (FMT__P_P_P, buf, nwk_hdr, nwk_cmd_rreq));

  /* calc path cost */
  NWK_CALC_PATH_COST(nwk_hdr->src_addr, path_cost);
  TRACE_MSG(TRACE_NWK1, "path_cost %hd", (FMT__H, path_cost));
  path_cost += nwk_cmd_rreq->path_cost;
  TRACE_MSG(TRACE_NWK1, "total path_cost %hd", (FMT__H, path_cost));

  /* search in routing table */
  TRACE_MSG(TRACE_NWK1, "dst_addr %d", (FMT__D, nwk_cmd_rreq->dest_addr));
  NWK_ARRAY_FIND_ENT( ZG->nwk.nib.routing_table, routing_ent, (routing_ent->dest_addr == nwk_cmd_rreq->dest_addr) );
  if ( routing_ent )
  {
    TRACE_MSG(TRACE_NWK1, "r ent fnd, state %d", (FMT__D, routing_ent->status));
    if ( (routing_ent->status != ZB_NWK_ROUTE_STATE_ACTIVE)
         && (routing_ent->status != ZB_NWK_ROUTE_STATE_VALIDATION_UNDERWAY) )
    {
      routing_ent->status = ZB_NWK_ROUTE_STATE_DISCOVERY_UNDERWAY;
      TRACE_MSG(TRACE_NWK1, "change r ent state to dsc uway", (FMT__0));
    }
  }
  else
  {
    TRACE_MSG(TRACE_NWK1, "no routing enttry found, add new", (FMT__0));
    /* add new routing entry */
    NWK_ARRAY_GET_ENT(ZG->nwk.nib.routing_table, routing_ent, ZG->nwk.nib.routing_table_cnt);
    if ( routing_ent )
    {
      routing_ent->dest_addr = nwk_cmd_rreq->dest_addr;
      routing_ent->status = ZB_NWK_ROUTE_STATE_DISCOVERY_UNDERWAY;
      TRACE_MSG(TRACE_NWK1, "new routing ent : dest_addr %d status %hd", (FMT__D_H,
                routing_ent->dest_addr, routing_ent->status));
    }
    else
    {
      ret = RET_NO_MEMORY;
      TRACE_MSG(TRACE_ERROR, "no room for r ent, skip rreq", (FMT__0));
      goto done;
    }
  }

  /* search thought discovery table */
  TRACE_MSG(TRACE_NWK1, "rreq_id %hd src_addr %d", (FMT__H_D, nwk_cmd_rreq->rreq_id, nwk_hdr->src_addr));
  NWK_ARRAY_FIND_ENT( ZG->nwk.nib.route_disc_table, disc_ent,
                      (disc_ent->request_id == nwk_cmd_rreq->rreq_id) && (disc_ent->source_addr == nwk_hdr->src_addr) );
  if ( disc_ent )
  {
    TRACE_MSG(TRACE_NWK1, "dsc entry found, path_cost %hd forward_cost %hd", (FMT__H_H, path_cost, disc_ent->forward_cost));
    /* check path cost and update route disc entry */
    if ( path_cost < disc_ent->forward_cost )
    {
      zb_uint16_t src_addr;
      nwk_get_mac_source_addr(buf, &src_addr);

      TRACE_MSG(TRACE_NWK1, "new forward cost %hd node %d old %d", (FMT__H_D_D, path_cost, src_addr, disc_ent->sender_addr));
      /* replace route with better one */
      disc_ent->sender_addr = src_addr;
      disc_ent->forward_cost = path_cost;
    }
    else
    {
      /* this is normal case, do not change ret code */
      TRACE_MSG(TRACE_NWK1, "we have better path, skip rreq", (FMT__0));
      goto done;
    }
  }
  else
  {
    TRACE_MSG(TRACE_NWK1, "no disc ent, try to add new", (FMT__0));
    /* add new discovery entry */
    NWK_ARRAY_GET_ENT(ZG->nwk.nib.route_disc_table, disc_ent, ZG->nwk.nib.route_disc_table_cnt);
    if ( disc_ent )
    {
      zb_uint16_t src_addr;
      nwk_get_mac_source_addr(buf, &src_addr);

      disc_ent->request_id       = nwk_cmd_rreq->rreq_id;
      disc_ent->source_addr      = nwk_hdr->src_addr;
      disc_ent->sender_addr      = src_addr;
      disc_ent->dest_addr        = nwk_cmd_rreq->dest_addr;
      disc_ent->forward_cost     = path_cost;
      disc_ent->residual_cost    = 0xff;
      disc_ent->expiration_time  = ZB_NWK_ROUTE_DISCOVERY_EXPIRY;
      TRACE_MSG(TRACE_NWK1, "disc ent added: request_id %hd src_addr %d sndr_addr %d d_addr %d fwd_cost %hd res_cost %hd exp_time %d", (FMT__H_D_D_D_H_H_D,
                disc_ent->request_id, disc_ent->source_addr, disc_ent->sender_addr, disc_ent->dest_addr,
                disc_ent->forward_cost, disc_ent->residual_cost, disc_ent->expiration_time));
    }
    else
    {
      ret = RET_NO_MEMORY;
      TRACE_MSG(TRACE_ERROR, "no room f/disc ent, skip rreq", (FMT__0));
      goto done;
    }
  }

  /* check if this rreq is for us or our neighbour, send route reply in this
   * case, forward route request otherwise */
  {
    zb_neighbor_tbl_ent_t *nbt;

    if ( nwk_cmd_rreq->dest_addr == ZB_NIB_NETWORK_ADDRESS()
         || zb_nwk_neighbor_get_by_short(nwk_cmd_rreq->dest_addr, &nbt) == RET_OK )
    {
      zb_uint16_t src_addr;
      nwk_get_mac_source_addr(buf, &src_addr);

      TRACE_MSG(TRACE_ERROR, "this rreq f/us or neighbor, snd rrep", (FMT__0));
      zb_nwk_mesh_send_rrep(buf, nwk_cmd_rreq->rreq_id, nwk_hdr->src_addr, nwk_cmd_rreq->dest_addr, path_cost, src_addr);
      /* zb_nwk_mesh_send_rrep is now responsible for buffer */
      buf = NULL;
    }
    else
    {
      /* Buffer will be modified inside zb_nwk_mesh_send_rreq, save data we
       * need */
      zb_nwk_cmd_rreq_t nwk_cmd_rreq_save;
      ZB_MEMCPY(&nwk_cmd_rreq_save, nwk_cmd_rreq, sizeof(nwk_cmd_rreq_save));

      TRACE_MSG(TRACE_ERROR, "don't know rreq dest, prop it", (FMT__0));
      zb_nwk_mesh_send_rreq(buf, &nwk_cmd_rreq_save, nwk_hdr->src_addr, nwk_hdr->seq_num, path_cost, nwk_hdr->radius);
      /* zb_nwk_mesh_send_rreq is now responsible for buffer */
      buf = NULL;
    }
  }

  done:
  if ( ret != RET_OK )
  {
    TRACE_MSG(TRACE_NWK1, "error %d above, rm disc and r ent if", (FMT__D, ret));
    if ( disc_ent )
    {
      NWK_ARRAY_PUT_ENT(ZG->nwk.nib.route_disc_table, disc_ent, ZG->nwk.nib.route_disc_table_cnt);
    }
    if ( routing_ent )
    {
      NWK_ARRAY_PUT_ENT(ZG->nwk.nib.routing_table, routing_ent, ZG->nwk.nib.routing_table_cnt);
    }

    /* if this request was initiated by APS, confirm that route discovery failed */
    if ( ZG->nwk.nib.aps_rreq_addr
         && ZG->nwk.nib.aps_rreq_addr == nwk_cmd_rreq->dest_addr )
    {
#ifndef ZB_LIMITED_FEATURES
      NWK_ROUTE_DISCOVERY_CONFIRM(buf, ZB_NWK_STATUS_ROUTE_ERROR, ZB_NWK_COMMAND_STATUS_NO_ROUTE_AVAILABLE);
#endif
      /* prevent buffer from being free */
      buf = NULL;
    }
  }

  if ( buf )
  {
    TRACE_MSG(TRACE_NWK1, "free buf %p", (FMT__P, buf));
    zb_free_buf(buf);
  }
  TRACE_MSG(TRACE_NWK1, "<< rreq_handler", (FMT__0));
}
Esempio n. 4
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));
}
Esempio n. 5
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));

}