Loading include/net/ieee802154_netdev.h +3 −0 Original line number Diff line number Diff line Loading @@ -225,6 +225,9 @@ struct ieee802154_mac_cb { u8 type; bool ackreq; bool secen; bool secen_override; u8 seclevel; bool seclevel_override; struct ieee802154_addr source; struct ieee802154_addr dest; }; Loading net/mac802154/mac802154.h +10 −0 Original line number Diff line number Diff line Loading @@ -23,9 +23,12 @@ #ifndef MAC802154_H #define MAC802154_H #include <linux/mutex.h> #include <net/mac802154.h> #include <net/ieee802154_netdev.h> #include "llsec.h" /* mac802154 device private data */ struct mac802154_priv { struct ieee802154_dev hw; Loading Loading @@ -91,6 +94,13 @@ struct mac802154_sub_if_data { u8 bsn; /* MAC DSN field */ u8 dsn; /* protects sec from concurrent access by netlink. access by * encrypt/decrypt/header_create safe without additional protection. */ struct mutex sec_mtx; struct mac802154_llsec sec; }; #define mac802154_to_priv(_hw) container_of(_hw, struct mac802154_priv, hw) Loading net/mac802154/wpan.c +90 −28 Original line number Diff line number Diff line Loading @@ -183,6 +183,38 @@ static int mac802154_wpan_open(struct net_device *dev) return rc; } static int mac802154_set_header_security(struct mac802154_sub_if_data *priv, struct ieee802154_hdr *hdr, const struct ieee802154_mac_cb *cb) { struct ieee802154_llsec_params params; u8 level; mac802154_llsec_get_params(&priv->sec, ¶ms); if (!params.enabled && cb->secen_override && cb->secen) return -EINVAL; if (!params.enabled || (cb->secen_override && !cb->secen) || !params.out_level) return 0; if (cb->seclevel_override && !cb->seclevel) return -EINVAL; level = cb->seclevel_override ? cb->seclevel : params.out_level; hdr->fc.security_enabled = 1; hdr->sec.level = level; hdr->sec.key_id_mode = params.out_key.mode; if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX) hdr->sec.short_src = params.out_key.short_source; else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX) hdr->sec.extended_src = params.out_key.extended_source; hdr->sec.key_id = params.out_key.id; return 0; } static int mac802154_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, Loading @@ -204,6 +236,9 @@ static int mac802154_header_create(struct sk_buff *skb, hdr.fc.ack_request = cb->ackreq; hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev); if (mac802154_set_header_security(priv, &hdr, cb) < 0) return -EINVAL; if (!saddr) { spin_lock_bh(&priv->mib_lock); Loading Loading @@ -259,6 +294,7 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev) { struct mac802154_sub_if_data *priv; u8 chan, page; int rc; priv = netdev_priv(dev); Loading @@ -274,6 +310,13 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } rc = mac802154_llsec_encrypt(&priv->sec, skb); if (rc) { pr_warn("encryption failed: %i\n", rc); kfree_skb(skb); return NETDEV_TX_OK; } skb->skb_iif = dev->ifindex; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; Loading @@ -294,6 +337,15 @@ static const struct net_device_ops mac802154_wpan_ops = { .ndo_set_mac_address = mac802154_wpan_mac_addr, }; static void mac802154_wpan_free(struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); mac802154_llsec_destroy(&priv->sec); free_netdev(dev); } void mac802154_wpan_setup(struct net_device *dev) { struct mac802154_sub_if_data *priv; Loading @@ -303,14 +355,14 @@ void mac802154_wpan_setup(struct net_device *dev) dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; dev->header_ops = &mac802154_header_ops; dev->needed_tailroom = 2; /* FCS */ dev->needed_tailroom = 2 + 16; /* FCS + MIC */ dev->mtu = IEEE802154_MTU; dev->tx_queue_len = 300; dev->type = ARPHRD_IEEE802154; dev->flags = IFF_NOARP | IFF_BROADCAST; dev->watchdog_timeo = 0; dev->destructor = free_netdev; dev->destructor = mac802154_wpan_free; dev->netdev_ops = &mac802154_wpan_ops; dev->ml_priv = &mac802154_mlme_wpan; Loading @@ -321,6 +373,7 @@ void mac802154_wpan_setup(struct net_device *dev) priv->page = 0; spin_lock_init(&priv->mib_lock); mutex_init(&priv->sec_mtx); get_random_bytes(&priv->bsn, 1); get_random_bytes(&priv->dsn, 1); Loading @@ -333,6 +386,8 @@ void mac802154_wpan_setup(struct net_device *dev) priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); mac802154_llsec_init(&priv->sec); } static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) Loading @@ -341,9 +396,11 @@ static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) } static int mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb, const struct ieee802154_hdr *hdr) { __le16 span, sshort; int rc; pr_debug("getting packet via slave interface %s\n", sdata->dev->name); Loading Loading @@ -390,6 +447,12 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) skb->dev = sdata->dev; rc = mac802154_llsec_decrypt(&sdata->sec, skb); if (rc) { pr_debug("decryption failed: %i\n", rc); return NET_RX_DROP; } sdata->dev->stats.rx_packets++; sdata->dev->stats.rx_bytes += skb->len; Loading Loading @@ -421,60 +484,58 @@ static void mac802154_print_addr(const char *name, } } static int mac802154_parse_frame_start(struct sk_buff *skb) static int mac802154_parse_frame_start(struct sk_buff *skb, struct ieee802154_hdr *hdr) { int hlen; struct ieee802154_hdr hdr; struct ieee802154_mac_cb *cb = mac_cb_init(skb); hlen = ieee802154_hdr_pull(skb, &hdr); hlen = ieee802154_hdr_pull(skb, hdr); if (hlen < 0) return -EINVAL; skb->mac_len = hlen; pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr.fc), hdr.seq); pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc), hdr->seq); cb->type = hdr.fc.type; cb->ackreq = hdr.fc.ack_request; cb->secen = hdr.fc.security_enabled; cb->type = hdr->fc.type; cb->ackreq = hdr->fc.ack_request; cb->secen = hdr->fc.security_enabled; mac802154_print_addr("destination", &hdr.dest); mac802154_print_addr("source", &hdr.source); mac802154_print_addr("destination", &hdr->dest); mac802154_print_addr("source", &hdr->source); cb->source = hdr.source; cb->dest = hdr.dest; cb->source = hdr->source; cb->dest = hdr->dest; if (hdr.fc.security_enabled) { if (hdr->fc.security_enabled) { u64 key; pr_debug("seclevel %i\n", hdr.sec.level); pr_debug("seclevel %i\n", hdr->sec.level); switch (hdr.sec.key_id_mode) { switch (hdr->sec.key_id_mode) { case IEEE802154_SCF_KEY_IMPLICIT: pr_debug("implicit key\n"); break; case IEEE802154_SCF_KEY_INDEX: pr_debug("key %02x\n", hdr.sec.key_id); pr_debug("key %02x\n", hdr->sec.key_id); break; case IEEE802154_SCF_KEY_SHORT_INDEX: pr_debug("key %04x:%04x %02x\n", le32_to_cpu(hdr.sec.short_src) >> 16, le32_to_cpu(hdr.sec.short_src) & 0xffff, hdr.sec.key_id); le32_to_cpu(hdr->sec.short_src) >> 16, le32_to_cpu(hdr->sec.short_src) & 0xffff, hdr->sec.key_id); break; case IEEE802154_SCF_KEY_HW_INDEX: key = swab64((__force u64) hdr.sec.extended_src); key = swab64((__force u64) hdr->sec.extended_src); pr_debug("key source %8phC %02x\n", &key, hdr.sec.key_id); hdr->sec.key_id); break; } return -EINVAL; } return 0; Loading @@ -485,8 +546,9 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) int ret; struct sk_buff *sskb; struct mac802154_sub_if_data *sdata; struct ieee802154_hdr hdr; ret = mac802154_parse_frame_start(skb); ret = mac802154_parse_frame_start(skb, &hdr); if (ret) { pr_debug("got invalid frame\n"); return; Loading @@ -499,7 +561,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) sskb = skb_clone(skb, GFP_ATOMIC); if (sskb) mac802154_subif_frame(sdata, sskb); mac802154_subif_frame(sdata, sskb, &hdr); } rcu_read_unlock(); } Loading
include/net/ieee802154_netdev.h +3 −0 Original line number Diff line number Diff line Loading @@ -225,6 +225,9 @@ struct ieee802154_mac_cb { u8 type; bool ackreq; bool secen; bool secen_override; u8 seclevel; bool seclevel_override; struct ieee802154_addr source; struct ieee802154_addr dest; }; Loading
net/mac802154/mac802154.h +10 −0 Original line number Diff line number Diff line Loading @@ -23,9 +23,12 @@ #ifndef MAC802154_H #define MAC802154_H #include <linux/mutex.h> #include <net/mac802154.h> #include <net/ieee802154_netdev.h> #include "llsec.h" /* mac802154 device private data */ struct mac802154_priv { struct ieee802154_dev hw; Loading Loading @@ -91,6 +94,13 @@ struct mac802154_sub_if_data { u8 bsn; /* MAC DSN field */ u8 dsn; /* protects sec from concurrent access by netlink. access by * encrypt/decrypt/header_create safe without additional protection. */ struct mutex sec_mtx; struct mac802154_llsec sec; }; #define mac802154_to_priv(_hw) container_of(_hw, struct mac802154_priv, hw) Loading
net/mac802154/wpan.c +90 −28 Original line number Diff line number Diff line Loading @@ -183,6 +183,38 @@ static int mac802154_wpan_open(struct net_device *dev) return rc; } static int mac802154_set_header_security(struct mac802154_sub_if_data *priv, struct ieee802154_hdr *hdr, const struct ieee802154_mac_cb *cb) { struct ieee802154_llsec_params params; u8 level; mac802154_llsec_get_params(&priv->sec, ¶ms); if (!params.enabled && cb->secen_override && cb->secen) return -EINVAL; if (!params.enabled || (cb->secen_override && !cb->secen) || !params.out_level) return 0; if (cb->seclevel_override && !cb->seclevel) return -EINVAL; level = cb->seclevel_override ? cb->seclevel : params.out_level; hdr->fc.security_enabled = 1; hdr->sec.level = level; hdr->sec.key_id_mode = params.out_key.mode; if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX) hdr->sec.short_src = params.out_key.short_source; else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX) hdr->sec.extended_src = params.out_key.extended_source; hdr->sec.key_id = params.out_key.id; return 0; } static int mac802154_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, Loading @@ -204,6 +236,9 @@ static int mac802154_header_create(struct sk_buff *skb, hdr.fc.ack_request = cb->ackreq; hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev); if (mac802154_set_header_security(priv, &hdr, cb) < 0) return -EINVAL; if (!saddr) { spin_lock_bh(&priv->mib_lock); Loading Loading @@ -259,6 +294,7 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev) { struct mac802154_sub_if_data *priv; u8 chan, page; int rc; priv = netdev_priv(dev); Loading @@ -274,6 +310,13 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } rc = mac802154_llsec_encrypt(&priv->sec, skb); if (rc) { pr_warn("encryption failed: %i\n", rc); kfree_skb(skb); return NETDEV_TX_OK; } skb->skb_iif = dev->ifindex; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; Loading @@ -294,6 +337,15 @@ static const struct net_device_ops mac802154_wpan_ops = { .ndo_set_mac_address = mac802154_wpan_mac_addr, }; static void mac802154_wpan_free(struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); mac802154_llsec_destroy(&priv->sec); free_netdev(dev); } void mac802154_wpan_setup(struct net_device *dev) { struct mac802154_sub_if_data *priv; Loading @@ -303,14 +355,14 @@ void mac802154_wpan_setup(struct net_device *dev) dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; dev->header_ops = &mac802154_header_ops; dev->needed_tailroom = 2; /* FCS */ dev->needed_tailroom = 2 + 16; /* FCS + MIC */ dev->mtu = IEEE802154_MTU; dev->tx_queue_len = 300; dev->type = ARPHRD_IEEE802154; dev->flags = IFF_NOARP | IFF_BROADCAST; dev->watchdog_timeo = 0; dev->destructor = free_netdev; dev->destructor = mac802154_wpan_free; dev->netdev_ops = &mac802154_wpan_ops; dev->ml_priv = &mac802154_mlme_wpan; Loading @@ -321,6 +373,7 @@ void mac802154_wpan_setup(struct net_device *dev) priv->page = 0; spin_lock_init(&priv->mib_lock); mutex_init(&priv->sec_mtx); get_random_bytes(&priv->bsn, 1); get_random_bytes(&priv->dsn, 1); Loading @@ -333,6 +386,8 @@ void mac802154_wpan_setup(struct net_device *dev) priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); mac802154_llsec_init(&priv->sec); } static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) Loading @@ -341,9 +396,11 @@ static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) } static int mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb, const struct ieee802154_hdr *hdr) { __le16 span, sshort; int rc; pr_debug("getting packet via slave interface %s\n", sdata->dev->name); Loading Loading @@ -390,6 +447,12 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) skb->dev = sdata->dev; rc = mac802154_llsec_decrypt(&sdata->sec, skb); if (rc) { pr_debug("decryption failed: %i\n", rc); return NET_RX_DROP; } sdata->dev->stats.rx_packets++; sdata->dev->stats.rx_bytes += skb->len; Loading Loading @@ -421,60 +484,58 @@ static void mac802154_print_addr(const char *name, } } static int mac802154_parse_frame_start(struct sk_buff *skb) static int mac802154_parse_frame_start(struct sk_buff *skb, struct ieee802154_hdr *hdr) { int hlen; struct ieee802154_hdr hdr; struct ieee802154_mac_cb *cb = mac_cb_init(skb); hlen = ieee802154_hdr_pull(skb, &hdr); hlen = ieee802154_hdr_pull(skb, hdr); if (hlen < 0) return -EINVAL; skb->mac_len = hlen; pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr.fc), hdr.seq); pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc), hdr->seq); cb->type = hdr.fc.type; cb->ackreq = hdr.fc.ack_request; cb->secen = hdr.fc.security_enabled; cb->type = hdr->fc.type; cb->ackreq = hdr->fc.ack_request; cb->secen = hdr->fc.security_enabled; mac802154_print_addr("destination", &hdr.dest); mac802154_print_addr("source", &hdr.source); mac802154_print_addr("destination", &hdr->dest); mac802154_print_addr("source", &hdr->source); cb->source = hdr.source; cb->dest = hdr.dest; cb->source = hdr->source; cb->dest = hdr->dest; if (hdr.fc.security_enabled) { if (hdr->fc.security_enabled) { u64 key; pr_debug("seclevel %i\n", hdr.sec.level); pr_debug("seclevel %i\n", hdr->sec.level); switch (hdr.sec.key_id_mode) { switch (hdr->sec.key_id_mode) { case IEEE802154_SCF_KEY_IMPLICIT: pr_debug("implicit key\n"); break; case IEEE802154_SCF_KEY_INDEX: pr_debug("key %02x\n", hdr.sec.key_id); pr_debug("key %02x\n", hdr->sec.key_id); break; case IEEE802154_SCF_KEY_SHORT_INDEX: pr_debug("key %04x:%04x %02x\n", le32_to_cpu(hdr.sec.short_src) >> 16, le32_to_cpu(hdr.sec.short_src) & 0xffff, hdr.sec.key_id); le32_to_cpu(hdr->sec.short_src) >> 16, le32_to_cpu(hdr->sec.short_src) & 0xffff, hdr->sec.key_id); break; case IEEE802154_SCF_KEY_HW_INDEX: key = swab64((__force u64) hdr.sec.extended_src); key = swab64((__force u64) hdr->sec.extended_src); pr_debug("key source %8phC %02x\n", &key, hdr.sec.key_id); hdr->sec.key_id); break; } return -EINVAL; } return 0; Loading @@ -485,8 +546,9 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) int ret; struct sk_buff *sskb; struct mac802154_sub_if_data *sdata; struct ieee802154_hdr hdr; ret = mac802154_parse_frame_start(skb); ret = mac802154_parse_frame_start(skb, &hdr); if (ret) { pr_debug("got invalid frame\n"); return; Loading @@ -499,7 +561,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) sskb = skb_clone(skb, GFP_ATOMIC); if (sskb) mac802154_subif_frame(sdata, sskb); mac802154_subif_frame(sdata, sskb, &hdr); } rcu_read_unlock(); }