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;
}
}
list_add(&child->node, &wpan_dev->children);
+ wpan_dev->nchildren++;
unlock:
mutex_unlock(&wpan_dev->association_lock);