static int mac802154_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *_daddr, const void *_saddr, unsigned len) { const struct ieee802154_addr *saddr = _saddr; const struct ieee802154_addr *daddr = _daddr; struct ieee802154_addr dev_addr; struct mac802154_sub_if_data *priv = netdev_priv(dev); int pos = 2; u8 head[MAC802154_FRAME_HARD_HEADER_LEN]; u16 fc; if (!daddr) return -EINVAL; head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */ fc = mac_cb_type(skb); if (mac_cb_is_ackreq(skb)) fc |= IEEE802154_FC_ACK_REQ; if (!saddr) { spin_lock_bh(&priv->mib_lock); if (priv->short_addr == IEEE802154_ADDR_BROADCAST || priv->short_addr == IEEE802154_ADDR_UNDEF || priv->pan_id == IEEE802154_PANID_BROADCAST) { dev_addr.addr_type = IEEE802154_ADDR_LONG; memcpy(dev_addr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN); } else { dev_addr.addr_type = IEEE802154_ADDR_SHORT; dev_addr.short_addr = priv->short_addr; } dev_addr.pan_id = priv->pan_id; saddr = &dev_addr; spin_unlock_bh(&priv->mib_lock); } if (daddr->addr_type != IEEE802154_ADDR_NONE) { fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT); head[pos++] = daddr->pan_id & 0xff; head[pos++] = daddr->pan_id >> 8; if (daddr->addr_type == IEEE802154_ADDR_SHORT) { head[pos++] = daddr->short_addr & 0xff; head[pos++] = daddr->short_addr >> 8; } else {
static int mac802154_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len) { struct ieee802154_hdr hdr; struct mac802154_sub_if_data *priv = netdev_priv(dev); int hlen; if (!daddr) return -EINVAL; memset(&hdr.fc, 0, sizeof(hdr.fc)); hdr.fc.type = mac_cb_type(skb); hdr.fc.security_enabled = mac_cb_is_secen(skb); hdr.fc.ack_request = mac_cb_is_ackreq(skb); if (!saddr) { spin_lock_bh(&priv->mib_lock); if (priv->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) || priv->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || priv->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) { hdr.source.mode = IEEE802154_ADDR_LONG; hdr.source.extended_addr = priv->extended_addr; } else { hdr.source.mode = IEEE802154_ADDR_SHORT; hdr.source.short_addr = priv->short_addr; } hdr.source.pan_id = priv->pan_id; spin_unlock_bh(&priv->mib_lock); } else { hdr.source = *(const struct ieee802154_addr *)saddr; } hdr.dest = *(const struct ieee802154_addr *)daddr; hlen = ieee802154_hdr_push(skb, &hdr); if (hlen < 0) return -EINVAL; skb_reset_mac_header(skb); skb->mac_len = hlen; if (hlen + len + 2 > dev->mtu) return -EMSGSIZE; return hlen; }
static int mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) { __le16 span, sshort; pr_debug("getting packet via slave interface %s\n", sdata->dev->name); spin_lock_bh(&sdata->mib_lock); span = sdata->pan_id; sshort = sdata->short_addr; switch (mac_cb(skb)->dest.mode) { case IEEE802154_ADDR_NONE: if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE) /* FIXME: check if we are PAN coordinator */ skb->pkt_type = PACKET_OTHERHOST; else /* ACK comes with both addresses empty */ skb->pkt_type = PACKET_HOST; break; case IEEE802154_ADDR_LONG: if (mac_cb(skb)->dest.pan_id != span && mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST)) skb->pkt_type = PACKET_OTHERHOST; else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr) skb->pkt_type = PACKET_HOST; else skb->pkt_type = PACKET_OTHERHOST; break; case IEEE802154_ADDR_SHORT: if (mac_cb(skb)->dest.pan_id != span && mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST)) skb->pkt_type = PACKET_OTHERHOST; else if (mac_cb(skb)->dest.short_addr == sshort) skb->pkt_type = PACKET_HOST; else if (mac_cb(skb)->dest.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_OTHERHOST; break; default: break; } spin_unlock_bh(&sdata->mib_lock); skb->dev = sdata->dev; sdata->dev->stats.rx_packets++; sdata->dev->stats.rx_bytes += skb->len; switch (mac_cb_type(skb)) { case IEEE802154_FC_TYPE_DATA: return mac802154_process_data(sdata->dev, skb); default: pr_warn("ieee802154: bad frame received (type = %d)\n", mac_cb_type(skb)); kfree_skb(skb); return NET_RX_DROP; } }