summaryrefslogtreecommitdiffstats
path: root/net/mac802154
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2023-09-27 20:12:12 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2023-11-20 11:43:19 +0100
commit80f8bf9a2a7f603662e08f7663643a58087a2cd4 (patch)
tree16c1ccbc5029038f9d123c98e00055833eb48dd7 /net/mac802154
parentce93b9378c306e6bcc4e0bd817acf4195b4a0288 (diff)
downloadlinux-80f8bf9a2a7f603662e08f7663643a58087a2cd4.tar.gz
linux-80f8bf9a2a7f603662e08f7663643a58087a2cd4.tar.bz2
linux-80f8bf9a2a7f603662e08f7663643a58087a2cd4.zip
mac802154: Follow the number of associated devices
Track the count of associated devices. Limit the number of associations using the value provided by the user if any. If we reach the maximum number of associations, we tell the device we are at capacity. If the user do not want to accept any more associations, it may specify the value 0 to the maximum number of associations, which will lead to an access denied error status returned to the peers trying to associate. 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-10-miquel.raynal@bootlin.com
Diffstat (limited to 'net/mac802154')
-rw-r--r--net/mac802154/cfg.c1
-rw-r--r--net/mac802154/scan.c33
2 files changed, 24 insertions, 10 deletions
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 083de2d3fe37..17e2032fac24 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -454,6 +454,7 @@ static int mac802154_disassociate_child(struct wpan_phy *wpan_phy,
return ret;
list_del(&child->node);
+ wpan_dev->nchildren--;
kfree(child);
return 0;
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index d5f66c204bc5..81d2c2bb1f09 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -800,20 +800,32 @@ int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
child->mode = IEEE802154_EXTENDED_ADDRESSING;
ceaddr = swab64((__force u64)child->extended_addr);
- assoc_resp_pl.status = IEEE802154_ASSOCIATION_SUCCESSFUL;
- if (assoc_req_pl.alloc_addr) {
- assoc_resp_pl.short_addr = cfg802154_get_free_short_addr(wpan_dev);
- child->mode = IEEE802154_SHORT_ADDRESSING;
+ if (wpan_dev->nchildren >= wpan_dev->max_associations) {
+ if (!wpan_dev->max_associations)
+ assoc_resp_pl.status = IEEE802154_PAN_ACCESS_DENIED;
+ else
+ assoc_resp_pl.status = IEEE802154_PAN_AT_CAPACITY;
+ assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST);
+ dev_dbg(&sdata->dev->dev,
+ "Refusing ASSOC REQ from child %8phC, %s\n", &ceaddr,
+ assoc_resp_pl.status == IEEE802154_PAN_ACCESS_DENIED ?
+ "access denied" : "too many children");
} else {
- assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
+ assoc_resp_pl.status = IEEE802154_ASSOCIATION_SUCCESSFUL;
+ if (assoc_req_pl.alloc_addr) {
+ assoc_resp_pl.short_addr = cfg802154_get_free_short_addr(wpan_dev);
+ child->mode = IEEE802154_SHORT_ADDRESSING;
+ } else {
+ assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
+ }
+ child->short_addr = assoc_resp_pl.short_addr;
+ dev_dbg(&sdata->dev->dev,
+ "Accepting ASSOC REQ from child %8phC, providing short address 0x%04x\n",
+ &ceaddr, le16_to_cpu(child->short_addr));
}
- child->short_addr = assoc_resp_pl.short_addr;
- dev_dbg(&sdata->dev->dev,
- "Accepting ASSOC REQ from child %8phC, providing short address 0x%04x\n",
- &ceaddr, le16_to_cpu(child->short_addr));
ret = mac802154_send_association_resp_locked(sdata, child, &assoc_resp_pl);
- if (ret) {
+ if (ret || assoc_resp_pl.status != IEEE802154_ASSOCIATION_SUCCESSFUL) {
kfree(child);
goto unlock;
}
@@ -834,6 +846,7 @@ int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
}
list_add(&child->node, &wpan_dev->children);
+ wpan_dev->nchildren++;
unlock:
mutex_unlock(&wpan_dev->association_lock);