/** 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)); }
void *zb_buf_cut_left(zb_buf_t *zbbuf, zb_uint8_t size) { ZB_ASSERT(ZB_BUF_LEN(zbbuf) >= (size)); /* ++VS */ (zbbuf)->u.hdr.len -= (size); (zbbuf)->u.hdr.data_offset += (size); return (void *)ZB_BUF_BEGIN(zbbuf); }
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)); }
/** Initial allocate space in buffer. @param zbbuf - buffer @param size - size to allocate @param ptr - (out) pointer to the buffer begin */ zb_void_t *zb_buf_initial_alloc(zb_buf_t *zbbuf, zb_uint8_t size) { zb_uint8_t is_in_buf = zbbuf->u.hdr.is_in_buf; ZB_ASSERT((size) < ZB_IO_BUF_SIZE); ZB_BZERO(&zbbuf->u, sizeof(zbbuf->u)); zbbuf->u.hdr.is_in_buf = is_in_buf; (zbbuf)->u.hdr.len = (size); (zbbuf)->u.hdr.data_offset = (ZB_IO_BUF_SIZE - (size)) / 2; return (void *)ZB_BUF_BEGIN(zbbuf); }
/* 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)); }
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)); }
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)); }
zb_ret_t zb_nwk_mesh_add_buf_to_pending(zb_buf_t *buf, zb_uint8_t handle) { zb_ret_t ret = RET_OK; zb_nwk_hdr_t *nwhdr = (zb_nwk_hdr_t *)ZB_BUF_BEGIN(buf); zb_nwk_pend_t *pend; NWK_ARRAY_GET_ENT(ZG->nwk.nib.pending_table, pend, ZG->nwk.nib.pending_table_cnt); if ( pend ) { TRACE_MSG(TRACE_ERROR, "buf %p added to pendlist", (FMT__P, buf)); pend->buf = buf; pend->handle = handle; pend->dest_addr = nwhdr->dst_addr; pend->expiry = ZB_NWK_PENDING_ENTRY_EXPIRY; pend->waiting_buf = 1; } else { ret = RET_NO_MEMORY; } return ret; }
/* 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)); }
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); }
/** 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)); }
zb_ret_t zb_aps_unsecure_frame(zb_buf_t *buf) { zb_ret_t ret = RET_OK; zb_uint8_t *aps_hdr; zb_aps_nwk_aux_frame_hdr_t *aux; zb_ushort_t a_size; zb_uint8_t *key; zb_uint8_t *payload; zb_address_ieee_ref_t addr_ref; { zb_apsde_data_indication_t * ind = ZB_GET_BUF_PARAM(buf, zb_apsde_data_indication_t); ret = zb_address_by_short(ind->src_addr, ZB_FALSE, ZB_FALSE, &addr_ref); if (ret != RET_OK) { TRACE_MSG(TRACE_SECUR3, "can't get addr %d", (FMT__D, ind->src_addr)); } } if (ret == RET_OK) { aps_hdr = ZB_BUF_BEGIN(buf); aux = (zb_aps_nwk_aux_frame_hdr_t *)(aps_hdr + ZB_APS_HDR_SIZE(*aps_hdr)); a_size = ((zb_uint8_t *)aux - aps_hdr); if (ZB_SECUR_AUX_HDR_GET_KEY_TYPE(aux->secur_control) == ZB_SECUR_DATA_KEY) { aux->secur_control = ZB_APS_DATA_STD_SECUR_CONTROL; payload = (zb_uint8_t *)aux + sizeof(zb_aps_data_aux_frame_hdr_t); /* TODO: implement Data key */ /* obtain secure material. */ /* check frame counters */ key = 0; a_size += sizeof(zb_aps_data_aux_frame_hdr_t); } else { /* NWK key */ zb_neighbor_tbl_ent_t *nbe; /* Update security level which was zeroed before send */ aux->secur_control = ZB_APS_NWK_STD_SECUR_CONTROL; payload = (zb_uint8_t *)aux + sizeof(zb_aps_nwk_aux_frame_hdr_t); key = secur_nwk_key_by_seq(aux->key_seq_number); a_size += sizeof(zb_aps_nwk_aux_frame_hdr_t); /* Get neighbor table entry by source address. */ ret = zb_nwk_neighbor_get(addr_ref, ZB_TRUE, &nbe); if (ret == RET_OK) { if (key && nbe->key_seq_number != aux->key_seq_number) { /* Peer now use another nwk key */ nbe->incoming_frame_counter = 0; nbe->key_seq_number = aux->key_seq_number; TRACE_MSG(TRACE_SECUR3, "peer switched key", (FMT__0)); } { /* Check NWK FrameCounter */ zb_uint32_t frame_counter; ZB_LETOH32(&frame_counter, &aux->frame_counter); if (nbe->incoming_frame_counter > frame_counter || nbe->incoming_frame_counter == (zb_uint32_t)~0) { ret = RET_ERROR; TRACE_MSG(TRACE_SECUR3, "frm cnt %ld->%ld shift back", (FMT__L_L, nbe->incoming_frame_counter, frame_counter)); } else { nbe->incoming_frame_counter = frame_counter; } } } else { TRACE_MSG(TRACE_SECUR3, "can't get neighbor", (FMT__0)); } } } if (ret == RET_OK && !key) { /* set 'frame security failed' */ ret = RET_ERROR; TRACE_MSG(TRACE_SECUR3, "no key by seq %hd", (FMT__H, aux->key_seq_number)); } if (ret == RET_OK) { /* decrypt */ zb_secur_ccm_nonce_t nonce; zb_address_ieee_by_ref(nonce.source_address, addr_ref); nonce.frame_counter = aux->frame_counter; nonce.secur_control = aux->secur_control; ret = zb_ccm_decrypt_n_auth_stdsecur(key, (zb_uint8_t *)&nonce, buf, a_size, (ZB_BUF_BEGIN(buf) + ZB_BUF_LEN(buf)) - (aps_hdr + a_size)); if (ret == RET_OK) { /* Remove MIC */ TRACE_MSG(TRACE_SECUR3, "unsecured frm %p[%hd] ok", (FMT__P_H, buf, ZB_BUF_LEN(buf))); } else { TRACE_MSG(TRACE_SECUR3, "unsecure failed", (FMT__0)); } } return ret; }
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)); }