RDKBWIFI-278: CACR add multi-STA support and received subdoc from UWM - #1222
RDKBWIFI-278: CACR add multi-STA support and received subdoc from UWM#1222sundram0711 wants to merge 1 commit into
Conversation
sundram0711
commented
Jun 23, 2026
- Refactored implementation to support multiple STA entries per message (spec compliant)
- Changed the struct to json format to carry cacr information from UWM to OneWifi.
There was a problem hiding this comment.
Pull request overview
This PR updates the EasyMesh Client Association Control Request (CACR) handling to accept a JSON sub-document from UWM and to apply the request to multiple STAs per message, rather than a single STA.
Changes:
- Switched CACR payload handling from a binary struct (
client_assoc_ctrl_req_t) to a JSON subdoc parser (parse_client_assoc_ctrl_json()). - Added multi-STA processing loop for
StaMacListand per-STA ACL timer scheduling/cancellation tracking. - Extended
kick_details_tto carry a scheduler timer ID for cancel support.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| source/core/wifi_ctrl.h | Extends kick_details_t with a timer_id field to track scheduled ACL removal timers. |
| source/apps/em/wifi_em.c | Implements JSON parsing for CACR, multi-STA handling, and pending timer tracking/cancellation. |
| include/wifi_base.h | Removes the old binary CACR request struct (client_assoc_ctrl_req_t) now replaced by JSON payloads. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
c4a31aa to
4a907f6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
source/apps/em/wifi_em.c:3290
- The error
cleanup:path only freeskick_details, but whenkick_details->kick_listhas been allocated (e.g.,strdup()succeeded) this leaks memory. Freekick_details->kick_listfirst (it is safe tofree(NULL)).
cleanup:
if (kick_details) {
free(kick_details);
}
4a907f6 to
a7f6696
Compare
a7f6696 to
436d6a1
Compare
436d6a1 to
02c6fcf
Compare
02c6fcf to
8bc17f3
Compare
8bc17f3 to
fb7a95e
Compare
fb7a95e to
9ec193e
Compare
9ec193e to
5d0ebd0
Compare
5d0ebd0 to
1f17f6f
Compare
1f17f6f to
8514563
Compare
8514563 to
68bb3bb
Compare
68bb3bb to
eb22b83
Compare
|
@sundram0711 please address recent copilot comments. If they are not applicable comment why. |
eb22b83 to
e08db5b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
source/apps/em/wifi_em.c:3699
- This path cancels the timer and then relies on del_acl_cb() to free kick_details and call acl_block_end(), but scheduler_cancel_timer_task() only marks the task as canceled and the scheduler never executes callbacks for canceled tasks (they are removed in scheduler_remove_complete_tasks). This can leak kick_details and keep the VAP in blacklist mode longer than intended.
pending->cancelled_by_unblock = true;
if (pending->timer_id >= 0) {
scheduler_cancel_timer_task(ctrl->sched, pending->timer_id);
}
e08db5b to
e5accf3
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
source/apps/em/wifi_em.c:3527
- For bus_data_type_string, cJSON_Parse expects a NUL-terminated string. The handler only checks raw_data.bytes != NULL, but does not validate raw_data_len or ensure the buffer is NUL-terminated, which can lead to an out-of-bounds read if the bus payload is not terminated as expected. Add a length check and reject non-terminated input (or copy into a terminated buffer) before parsing.
if (p_data->raw_data.bytes == NULL) {
wifi_util_error_print(WIFI_CTRL, "%s:%d: Invalid Received:%s raw_data.bytes is NULL\n",
__func__, __LINE__, event_name);
return bus_error_invalid_input;
}
source/apps/em/wifi_em.c:3700
- The unblock path cancels the scheduled timer and then relies on del_acl_cb() to perform cleanup (free kick_details, call acl_block_end to restore ACL mode). However scheduler_cancel_timer_task() only sets a cancel flag and the scheduler never invokes the callback for cancelled tasks, so this leaks kick_details and leaves g_vap_acl_state.active_blocks incremented (potentially leaving the VAP stuck in blacklist mode). Instead of cancelling, reschedule the timer to fire immediately so del_acl_cb() runs and performs the intended cleanup.
pending->cancelled_by_unblock = true;
if (pending->timer_id >= 0) {
scheduler_cancel_timer_task(ctrl->sched, pending->timer_id);
}
- Refactored implementation to support multiple STA entries per message (spec compliant) - Changed the struct to json format to carry cacr information from UWM to OneWifi. Signed-off-by: Sundram Patel <sundram.p@tataelxsi.co.in>
e5accf3 to
4497176
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Suppressed comments (2)
source/apps/em/wifi_em.c:3690
- The unblock path removes the pending node, then later sets pending->cancelled_by_unblock and cancels the timer. There are multiple race/leak issues here: (1) the timer callback may run between removal and the flag write, freeing the same kick_details (use-after-free when writing cancelled_by_unblock); (2) scheduler_cancel_timer_task() prevents del_acl_cb() from running, but the scheduler does not free tt->arg on cancel, so kick_details leaks and acl_block_end() is never called, leaving the VAP stuck in blacklist mode (which can weaken whitelist enforcement). Prefer to keep the node tracked, set cancelled_by_unblock under the pending list lock, and expedite the timer callback (update interval/timeout) instead of canceling it.
kick_details_t *pending = find_remove_and_cancel_pending_block(vap_index, sta_mac_list[i]);
#ifdef NL80211_ACL
//if sta already block then removed it from acl list
success = (wifi_hal_delHostapdDenyAclDevice(vap_index, sta_mac_list[i]) == RETURN_OK);
source/apps/em/wifi_em.c:3905
- timer_id is treated as valid when >= 0 elsewhere (initialized to -1 and checked with >= 0), but em_deinit only cancels when timer_id > 0. If the scheduler ever returns 0 as a valid id, this would skip cancellation and leave the task queued during teardown.
if (node->kick_details->timer_id > 0) {
| // Parse JSON subdoc | ||
| memset(sta_mac_list, 0, sizeof(sta_mac_list)); | ||
| ret = parse_client_assoc_ctrl_json((const char *)p_data->raw_data.bytes, &bssid, &assoc_control, &validity_period, | ||
| sta_mac_list, &sta_count); | ||
| if (ret != bus_error_success) { | ||
| wifi_util_error_print(WIFI_CTRL, "%s:%d Failed to parse client assoc ctrl JSON\n", __func__, __LINE__); | ||
| return ret; | ||
| } |
| if (add_pending_block(kick_details) != RETURN_OK) { | ||
| scheduler_cancel_timer_task(ctrl->sched, kick_details->timer_id); | ||
|
|
||
| #ifdef NL80211_ACL | ||
| wifi_hal_delHostapdDenyAclDevice(vap_index, kick_details->kick_list); | ||
| #else | ||
| wifi_delApAclDevice(vap_index, kick_details->kick_list); | ||
| #endif | ||
|
|
||
| acl_block_end(vap_index); | ||
|
|
||
| free(kick_details->kick_list); | ||
| free(kick_details); | ||
|
|
||
| ret = bus_error_out_of_resources; | ||
| goto cleanup; | ||
| } |