Example #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));
}
Example #2
0
  /* TODO: fill partner_address for application key */
  ZB_SCHEDULE_CALLBACK(zb_apsme_request_key_indication, param);

  TRACE_MSG(TRACE_SECUR2, "<<zb_aps_in_request_key", (FMT__0));
}

#endif  /* ZB_ROUTER_ROLE */
void zb_aps_in_switch_key(zb_uint8_t param)
{
  /* get source address from the nwk header and convert it to long address */
  zb_apsme_switch_key_pkt_t *pkt = (zb_apsme_switch_key_pkt_t *)ZB_BUF_BEGIN(ZB_BUF_FROM_REF(param));
  zb_apsme_switch_key_ind_t *ind = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsme_switch_key_ind_t);
  {
    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);
  }
  ind->key_seq_number = pkt->key_seq_number;
  ZB_SCHEDULE_CALLBACK(zb_apsme_switch_key_indication, param);

  TRACE_MSG(TRACE_SECUR3, "<<zb_aps_in_switch_key", (FMT__0));
}
Example #3
0
void zb_handle_scan_request(zb_uint8_t param) 
{
  zb_ret_t ret;
  zb_uint8_t scan_type;

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

  MAC_CTX().pending_buf = ZB_BUF_FROM_REF(param);
  scan_type = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mlme_scan_params_t)->scan_type;

  switch (scan_type)
  {
    case ACTIVE_SCAN:
      ret = zb_mlme_active_scan();
      break;
#ifndef ZB_LIMITED_FEATURES
    case ED_SCAN:
      ret = zb_mlme_ed_scan();
      MAC_CTX().ed_scan_step_passed = 0;
      break;
    case ORPHAN_SCAN:
      ret = zb_mlme_orphan_scan();
      break;
#endif
    default:
      ret = RET_NOT_IMPLEMENTED;
      TRACE_MSG(TRACE_MAC3, "bad scan type %hd", (FMT__H, scan_type));
      MAC_CTX().mac_status = MAC_INVALID_PARAMETER;
      break;
  }
  TRACE_MSG(TRACE_MAC2, "<< zb_handle_scan_request i", (FMT__D, ret));
}
Example #4
0
void zb_aps_in_request_key(zb_uint8_t param)
{
  /* get source address from the nwk header and convert it to long address */  
  zb_apsme_request_nwk_key_pkt_t *pkt = (zb_apsme_request_nwk_key_pkt_t *)ZB_BUF_BEGIN(ZB_BUF_FROM_REF(param));  
  zb_apsme_request_key_ind_t *ind = ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_apsme_request_key_ind_t);
  TRACE_MSG(TRACE_SECUR2, ">>zb_aps_in_request_key", (FMT__0));
  {
    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);
  }
  ind->key_type = pkt->key_type;
  /* TODO: fill partner_address for application key */
  ZB_SCHEDULE_CALLBACK(zb_apsme_request_key_indication, param);

  TRACE_MSG(TRACE_SECUR2, "<<zb_aps_in_request_key", (FMT__0));
}
Example #5
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));
}
Example #6
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));
}
Example #7
0
/* 7.1.11.1 MLME-SCAN.request */
void zb_mlme_scan_request(zb_uint8_t param) 
{
  zb_ret_t ret = RET_OK;
  zb_mlme_scan_params_t *params;
  zb_uint8_t scan_type;
  zb_uint8_t handle_scan_called = 0;

  TRACE_MSG(TRACE_MAC2, ">> zb_mlme_scan_request %hd", (FMT__H, param));

  params = ZB_GET_BUF_PARAM((zb_buf_t *)ZB_BUF_FROM_REF(param), zb_mlme_scan_params_t);
  ZB_ASSERT(params);
  MAC_CTX().mac_status = MAC_SUCCESS;
  scan_type = params->scan_type;

  if (params->scan_duration > ZB_MAX_SCAN_DURATION_VALUE && scan_type != ORPHAN_SCAN)
  {
    ret = RET_ERROR;
    MAC_CTX().mac_status = MAC_INVALID_PARAMETER;
  }

  if ((ret == RET_OK)&&(!MAC_CTX().mlme_scan_in_progress))
  {
    /* process request immediately*/
    MAC_CTX().pending_buf = ZB_BUF_FROM_REF(param);

    ZB_SCHEDULE_CALLBACK(zb_handle_scan_request, param);
    handle_scan_called = 1;
  }
  if (!handle_scan_called)
  {
    zb_mac_scan_confirm_t *scan_confirm;

    scan_confirm = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mac_scan_confirm_t);
    scan_confirm->status = (ret == RET_OK) ? MAC_SUCCESS :
      MAC_CTX().mac_status != MAC_SUCCESS ? MAC_CTX().mac_status : MAC_INVALID_PARAMETER;
    scan_confirm->scan_type = scan_type;
    ZB_SCHEDULE_CALLBACK(zb_mlme_scan_confirm, ZB_REF_FROM_BUF(MAC_CTX().pending_buf));
  }

  TRACE_MSG(TRACE_MAC2, "<< zb_mlme_scan_request", (FMT__0));
}
Example #8
0
void nwk_route_disc_failed(zb_uint8_t param) 
{
  zb_nlme_status_indication_t *status =  ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_nlme_status_indication_t);

  TRACE_MSG(TRACE_NWK1, ">> nwk_route_disc_failed", (FMT__0));

  status->status = ZB_NWK_COMMAND_STATUS_NO_ROUTE_AVAILABLE;
  status->network_addr = ZG->nwk.handle.status_ind_addr;

  /* notify */
  ZB_SCHEDULE_CALLBACK(zb_nlme_status_indication, param);
  ZB_SCHEDULE_ALARM_CANCEL(zb_nwk_mesh_expiry_route_disc, 0);
  ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_route_disc, 0, ZB_NWK_EXPIRY_ROUTE_DISCOVERY);

  TRACE_MSG(TRACE_NWK1, ">> nwk_route_disc_failed", (FMT__0));
}
Example #9
0
/* This function called periodically to find expired route requests */
void zb_nwk_mesh_expiry_rreq(zb_uint8_t param) 
{
  TRACE_MSG(TRACE_NWK1, ">> expiry_rreq p %hd", (FMT__H, param));

  TRACE_MSG(TRACE_NWK1, "rreq cnt %d", (FMT__D, ZG->nwk.nib.rreq_cnt));
  if ( ZG->nwk.nib.rreq_cnt )
  {
    zb_ushort_t i = 0;

    for (i = ZG->nwk.nib.rreq_num; i < ZB_NWK_RREQ_TABLE_SIZE; i++)
    {
      if ( ZG->nwk.nib.rreq[i].used )
      {
        /* check we have buffer to send */
        if ( param == (zb_uint8_t)(-1) )
        {
          /* wait for buffer */
          TRACE_MSG(TRACE_NWK1, "wait f/out buf", (FMT__0));
          ZB_GET_OUT_BUF_DELAYED(zb_nwk_mesh_expiry_rreq);
          goto done;
        }

        TRACE_MSG(TRACE_NWK1, "resend %d request", (FMT__D, i));
        zb_nwk_mesh_resend_rreq(ZB_BUF_FROM_REF(param), &ZG->nwk.nib.rreq[i]);
        param = -1;
      }
    }
    ZG->nwk.nib.rreq_num = 0;

    if ( ZG->nwk.nib.rreq_cnt )
    {
      /* Schedule to call later */
      ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_rreq, -1, ZB_NWK_RREQ_RETRY_INTERVAL);
    }
  }
  else
  {
    /* No route requests, do not schedule callback */
  }

  done:
  TRACE_MSG(TRACE_NWK1, "<< expiry_rreq", (FMT__0));
}
Example #10
0
/* This function is called when we got new buffer to initiate route discovery */
void zb_nwk_mesh_initiate_route_discovery(zb_uint8_t param) 
{
  zb_nwk_pend_t *ent;
  zb_buf_t *cbuf = (zb_buf_t *)ZB_BUF_FROM_REF(param);

  TRACE_MSG(TRACE_NWK1, ">> initiate_route_discovery %hd", (FMT__H, param));

  NWK_ARRAY_FIND_ENT(ZG->nwk.nib.pending_table, ent, ent->waiting_buf);
  if ( ent )
  {
    zb_nwk_hdr_t *nwhdr = (zb_nwk_hdr_t *)ZB_BUF_BEGIN(ent->buf);

    zb_nwk_mesh_route_discovery(cbuf, nwhdr->dst_addr, 0);
    ent->waiting_buf = 0;
  }
  else
  {
    zb_free_buf(cbuf);
    TRACE_MSG(TRACE_NWK1, "perepil", (FMT__0));
    ZB_ASSERT(0);
  }

  TRACE_MSG(TRACE_NWK1, "<< initiate_route_discovery", (FMT__0));
}
Example #11
0
void zb_aps_send_command(zb_uint8_t param, zb_uint16_t dest_addr, zb_uint8_t command, zb_bool_t secure)
{
  zb_buf_t *buf = (zb_buf_t *)ZB_BUF_FROM_REF(param);
  zb_ushort_t need_ack = !ZB_NWK_IS_ADDRESS_BROADCAST(dest_addr);
#ifdef ZB_DISABLE_APS_ACK_REQ
  /* Specially for test with Daintree: do not ask ACK for key transport:
     Daintree wants to encrypt ACK by its predefined key before it receive key from us */
  if (command == APS_CMD_TRANSPORT_KEY)
  {
    need_ack = 0;
  }
#endif
  TRACE_MSG(TRACE_SECUR3, ">>zb_aps_send_command param %hd cmd %hd secur %hd to %d need_ack %hd", (FMT__H_H_H_D_H, param, command, secure, dest_addr, need_ack));

  if (need_ack)
  {
    zb_uint8_t i;
    for (i = 0 ; i < ZB_N_APS_RETRANS_ENTRIES ; ++i)
    {
      if (ZG->aps.retrans.hash[i].state == ZB_APS_RETRANS_ENT_FREE)
      {
        ZG->aps.retrans.hash[i].addr = dest_addr;
        ZG->aps.retrans.hash[i].aps_counter = ZB_AIB_APS_COUNTER();
        ZG->aps.retrans.hash[i].buf = param;
        ZG->aps.retrans.hash[i].nwk_insecure = !secure;
        ZG->aps.retrans.hash[i].aps_retries = ZB_N_APS_MAX_FRAME_ENTRIES;
        ZG->aps.retrans.hash[i].state = ZB_APS_RETRANS_ENT_SENT_MAC_NOT_CONFIRMED_ALRM_RUNNING;
        TRACE_MSG(TRACE_APS2, "Store buf %hd len %hd in retrans hash %d", (FMT__H_H, param, ZB_BUF_LEN(buf), i));

        DUMP_TRAF("sending aps cmd", ZB_BUF_BEGIN(buf), ZB_BUF_LEN(buf));

        break;
      }
    }
    if (i == ZB_N_APS_RETRANS_ENTRIES)
    {
      TRACE_MSG(TRACE_APS2, "ACK table is FULL", (FMT__0));
    }
    else
    {
      ZB_SCHEDULE_ALARM(zb_aps_ack_timer_cb, i, ZB_N_APS_ACK_WAIT_DURATION);
    }
  }

  /* Fill APS command header - see 2.2.5.2.2  APS Command Frame Format.
     At the same time alloc and fill aux security header
   */

  {
    zb_aps_command_header_t *hdr;

#ifdef ZB_SECURITY
#ifdef APS_FRAME_SECURITY
    buf->u.hdr.encrypt_type = ZB_SECUR_NO_ENCR;
    if (secure)
    {
      /* Allocate here space for APS command header, aux header and command id
       * (it is in payload). */
      secure = zb_aps_command_add_secur(buf, command);
      hdr = (zb_aps_command_header_t *)ZB_BUF_BEGIN(buf);
    }
    else
#endif
#endif
    {
      /* no security - just aps command header */
      ZB_BUF_ALLOC_LEFT(buf, sizeof (*hdr), hdr);
      hdr->fc = 0;
      hdr->aps_command_id = command;
    }

    ZB_APS_FC_SET_COMMAND(hdr->fc, need_ack);
    hdr->aps_counter = ZB_AIB_APS_COUNTER();
  }
  ZB_AIB_APS_COUNTER_INC();

  fill_nldereq(param, dest_addr, secure);
  TRACE_MSG(TRACE_SECUR3, "send APS cmd %hd secur %hd to %d", (FMT__H_H_D, command, secure, dest_addr));

  ZB_SCHEDULE_CALLBACK(zb_nlde_data_request, param);
}
Example #12
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));
}