bool ieee802154_create_data_frame(struct net_if *iface, struct in6_addr *dst, uint8_t *p_buf, uint8_t len) { struct ieee802154_context *ctx = net_if_l2_data(iface); struct ieee802154_frame_params params; struct ieee802154_fcf_seq *fs; uint8_t *frag_start = p_buf; fs = generate_fcf_grounds(&p_buf, ctx->ack_requested); fs->fc.frame_type = IEEE802154_FRAME_TYPE_DATA; fs->sequence = ctx->sequence++; params.dst.pan_id = ctx->pan_id; params.pan_id = ctx->pan_id; data_addr_to_fs_settings(iface, dst, fs, ¶ms); p_buf = generate_addressing_fields(iface, fs, ¶ms, p_buf); if ((p_buf - frag_start) != len) { /* ll reserve was too small? We probably overwrote * payload bytes */ return false; } /* Todo: handle security aux header */ dbg_print_fs(fs); return true; }
struct net_buf * ieee802154_create_mac_cmd_frame(struct net_if *iface, enum ieee802154_cfi type, struct ieee802154_frame_params *params) { struct ieee802154_context *ctx = net_if_l2_data(iface); struct ieee802154_fcf_seq *fs; struct net_buf *buf, *frag; uint8_t *p_buf; buf = net_nbuf_get_reserve_tx(0); if (!buf) { return NULL; } frag = net_nbuf_get_reserve_data(0); if (!frag) { goto error; } net_buf_frag_add(buf, frag); p_buf = net_nbuf_ll(buf); fs = generate_fcf_grounds(&p_buf, false); fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND; fs->sequence = ctx->sequence; if (!cfi_to_fs_settings(type, fs, params)) { goto error; } p_buf = generate_addressing_fields(iface, fs, params, p_buf); /* Let's insert the cfi */ ((struct ieee802154_command *)p_buf)->cfi = type; /* In MAC command, we consider ll header being the mhr. * Rest will be the MAC command itself. This will proove * to be easy to handle afterwards to point directly to MAC * command space, in order to fill-in its content. */ net_nbuf_set_ll_reserve(buf, p_buf - net_nbuf_ll(buf)); net_buf_pull(frag, net_nbuf_ll_reserve(buf)); /* Thus setting the right MAC command length * Now up to the caller to fill-in this space relevantly. * See ieee802154_mac_command() helper. */ net_nbuf_set_len(frag, mac_command_length(type)); dbg_print_fs(fs); return buf; error: net_nbuf_unref(buf); return NULL; }
bool ieee802154_create_ack_frame(struct net_if *iface, struct net_buf *buf, uint8_t seq) { uint8_t *p_buf = net_nbuf_ll(buf); struct ieee802154_fcf_seq *fs; if (!p_buf) { return false; } fs = generate_fcf_grounds(&p_buf, 0); fs->fc.dst_addr_mode = 0; fs->fc.src_addr_mode = 0; fs->fc.frame_type = IEEE802154_FRAME_TYPE_ACK; fs->sequence = seq; return true; }
struct net_pkt * ieee802154_create_mac_cmd_frame(struct ieee802154_context *ctx, enum ieee802154_cfi type, struct ieee802154_frame_params *params) { struct ieee802154_fcf_seq *fs; struct net_pkt *pkt; struct net_buf *frag; u8_t *p_buf; pkt = net_pkt_get_reserve_tx(0, K_FOREVER); if (!pkt) { return NULL; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { goto error; } net_pkt_frag_add(pkt, frag); p_buf = net_pkt_ll(pkt); fs = generate_fcf_grounds(&p_buf, type == IEEE802154_CFI_BEACON_REQUEST ? false : ctx->ack_requested); fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND; fs->sequence = ctx->sequence; if (!cfi_to_fs_settings(type, fs, params)) { goto error; } p_buf = generate_addressing_fields(ctx, fs, params, p_buf); /* Let's insert the cfi */ ((struct ieee802154_command *)p_buf)->cfi = type; /* In MAC command, we consider ll header being the mhr. * Rest will be the MAC command itself. This will proove * to be easy to handle afterwards to point directly to MAC * command space, in order to fill-in its content. */ net_pkt_set_ll_reserve(pkt, p_buf - net_pkt_ll(pkt)); net_buf_pull(frag, net_pkt_ll_reserve(pkt)); /* Thus setting the right MAC command length * Now up to the caller to fill-in this space relevantly. * See ieee802154_mac_command() helper. */ frag->len = mac_command_length(type); dbg_print_fs(fs); return pkt; error: net_pkt_unref(pkt); return NULL; }
bool ieee802154_create_data_frame(struct ieee802154_context *ctx, struct net_linkaddr *dst, struct net_buf *frag, u8_t reserved_len) { struct ieee802154_frame_params params; struct ieee802154_fcf_seq *fs; u8_t *p_buf = frag->data - reserved_len; u8_t *frag_start = p_buf; bool broadcast; fs = generate_fcf_grounds(&p_buf, ctx->ack_requested); fs->fc.frame_type = IEEE802154_FRAME_TYPE_DATA; fs->sequence = ctx->sequence++; params.dst.pan_id = ctx->pan_id; params.pan_id = ctx->pan_id; broadcast = data_addr_to_fs_settings(dst, fs, ¶ms); p_buf = generate_addressing_fields(ctx, fs, ¶ms, p_buf); #ifdef CONFIG_NET_L2_IEEE802154_SECURITY if (broadcast) { NET_DBG("No security hdr needed: broadcasting"); goto no_security_hdr; } fs->fc.security_enabled = 1; p_buf = generate_aux_security_hdr(&ctx->sec_ctx, p_buf); /* If tagged, let's retrieve tag space from ll reserved space. * See comment in ieee802154_compute_header_size() */ if (ctx->sec_ctx.level != IEEE802154_SECURITY_LEVEL_NONE && ctx->sec_ctx.level != IEEE802154_SECURITY_LEVEL_ENC) { u8_t level; level = ctx->sec_ctx.level; if (level >= IEEE802154_SECURITY_LEVEL_ENC) { level -= 4; } /* p_buf should point to the right place */ memmove(p_buf, frag->data, frag->len); reserved_len -= level_2_tag_size[level]; } no_security_hdr: #endif /* CONFIG_NET_L2_IEEE802154_SECURITY */ if ((p_buf - frag_start) != reserved_len) { /* ll reserve was too small? We probably overwrote * payload bytes */ NET_ERR("Could not generate data frame %zu vs %u", (p_buf - frag_start), reserved_len); return false; } dbg_print_fs(fs); /* Let's encrypt/auth only in the end, is needed */ return ieee802154_encrypt_auth(broadcast ? NULL : &ctx->sec_ctx, frag_start, reserved_len, frag->len, ctx->ext_addr); }