diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2023-09-27 21:12:13 +0300 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2023-11-20 13:43:33 +0300 |
commit | 1e2a45f1f854ce63c114b42298ea686dce9ae4fd (patch) | |
tree | 5acc58a704ba9487ed022a5350aee5e3524e7ccd /net/mac802154/scan.c | |
parent | 80f8bf9a2a7f603662e08f7663643a58087a2cd4 (diff) | |
download | linux-1e2a45f1f854ce63c114b42298ea686dce9ae4fd.tar.xz |
mac802154: Handle disassociation notifications from peers
Peers may decided to disassociate from us, their coordinator, in this
case they will send a disassociation notification which we must
acknowledge. If we don't, the peer device considers itself disassociated
anyway. We also need to drop the reference to this child from our
internal structures.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Acked-by: Stefan Schmidt <stefan@datenfreihafen.org>
Acked-by: Alexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/linux-wpan/20230927181214.129346-11-miquel.raynal@bootlin.com
Diffstat (limited to 'net/mac802154/scan.c')
-rw-r--r-- | net/mac802154/scan.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c index 81d2c2bb1f09..7597072aed57 100644 --- a/net/mac802154/scan.c +++ b/net/mac802154/scan.c @@ -852,3 +852,58 @@ unlock: mutex_unlock(&wpan_dev->association_lock); return ret; } + +int mac802154_process_disassociation_notif(struct ieee802154_sub_if_data *sdata, + struct sk_buff *skb) +{ + struct ieee802154_addr *src = &mac_cb(skb)->source; + struct ieee802154_addr *dest = &mac_cb(skb)->dest; + struct wpan_dev *wpan_dev = &sdata->wpan_dev; + struct ieee802154_pan_device *child; + struct ieee802154_addr target; + bool parent; + u64 teaddr; + + if (skb->len != sizeof(u8)) + return -EINVAL; + + if (unlikely(src->mode != IEEE802154_EXTENDED_ADDRESSING)) + return -EINVAL; + + if (dest->mode == IEEE802154_EXTENDED_ADDRESSING && + unlikely(dest->extended_addr != wpan_dev->extended_addr)) + return -ENODEV; + else if (dest->mode == IEEE802154_SHORT_ADDRESSING && + unlikely(dest->short_addr != wpan_dev->short_addr)) + return -ENODEV; + + if (dest->pan_id != wpan_dev->pan_id) + return -ENODEV; + + target.mode = IEEE802154_EXTENDED_ADDRESSING; + target.extended_addr = src->extended_addr; + teaddr = swab64((__force u64)target.extended_addr); + dev_dbg(&skb->dev->dev, "Processing DISASSOC NOTIF from %8phC\n", &teaddr); + + mutex_lock(&wpan_dev->association_lock); + parent = cfg802154_device_is_parent(wpan_dev, &target); + if (!parent) + child = cfg802154_device_is_child(wpan_dev, &target); + if (!parent && !child) { + mutex_unlock(&wpan_dev->association_lock); + return -EINVAL; + } + + if (parent) { + kfree(wpan_dev->parent); + wpan_dev->parent = NULL; + } else { + list_del(&child->node); + kfree(child); + wpan_dev->nchildren--; + } + + mutex_unlock(&wpan_dev->association_lock); + + return 0; +} |