diff --git a/src/core/agent.h b/src/core/agent.h index 52777a40da848ec3a245ff505ee8b911072d6cee..ab9c2e13b4f790cf6b10fda2265f2fa32c553c62 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -133,7 +133,8 @@ struct neighbor { struct restrict_sta_entry { uint8_t sta[6]; - char fh_ifname[16]; + char fh_ifname[16]; /*TODO remove as param not needed*/ + struct netif_fh *vif; struct uloop_timeout restrict_timer; struct list_head list; }; diff --git a/src/core/agent_map.c b/src/core/agent_map.c index 9ce0176f457a13be512d18d8ff0bf3b7974e1d1b..59b8ea7cebb2381060531b88103e6754b97e28cc 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -1702,6 +1702,226 @@ int send_1905_acknowledge(void *agent, return ret; } +int agent_send_restrict_sta(void *agent, uint32_t count_sta, + uint8_t client_sta[][6], struct netif_fh *fh, + uint8_t enable) +{ + struct agent *a = (struct agent *) agent; + char client_macstr[18] = { 0 }; + char bssid_str[18] = { 0 }; + struct blob_buf bb = { 0 }; + int ret = 0, i = 0; + uint32_t id; + char ap_ifname[30] = { 0 }; + void *tbl; + + trace("agent: %s: --->\n", __func__); + if (!client_sta) + return -1; + + blob_buf_init(&bb, 0); + + tbl = blobmsg_open_array(&bb, "client"); + for (i = 0; i < count_sta; i++) { + hwaddr_ntoa(client_sta[i], client_macstr); + trace("agent: stalist :" MACFMT "\n", + MAC2STR(client_sta[i])); + blobmsg_add_string(&bb, NULL, client_macstr); + } + blobmsg_close_table(&bb, tbl); + blobmsg_add_u32(&bb, "enable", enable); + trace("Enable value is %d\n", enable); + ret = ubus_invoke(a->ubus_ctx, fh->wifi, "assoc_control", bb.head, + NULL, NULL, UBUS_TIMEOUT); + if (ret) { + trace("[%s:%d] ubus call failed for assoc_control", + __func__, __LINE__); + } +out: + blob_buf_free(&bb); + return ret; +} + +static void wifi_restrict_sta_timeout(struct uloop_timeout *t) +{ + struct netif_fh *fh; + struct restrict_sta_entry *s = + container_of(t, struct restrict_sta_entry, restrict_timer); + + trace("agent: %s: --->\n", __func__); + fh = s->vif; + if (!fh) { + trace("[%s:%d] Error BSSID not present", __func__, __LINE__); + return -1; + } + agent_send_restrict_sta(fh->agent, 1, s->sta, fh, 1); + list_del(&s->list); + free(s); +} + +int agent_check_start_validity_tmr(uint16_t validity_period, + uint32_t sta_count, uint8_t stalist[][6], + struct netif_fh *fh) +{ + uint32_t i = 0; + struct restrict_sta_entry *s, *tmp; + struct restrict_sta_entry *ss; + + trace("agent: %s: --->\n", __func__); + if (stalist == NULL) + return -1; + + for (i = 0; i < sta_count; i++) { + // check if the sta is already running a timer + // delete the timer + list_for_each_entry_safe(s, tmp, &fh->restrict_stalist, list) { + if (!memcmp(s->sta, stalist[i], 6)) { + uloop_timeout_cancel(&s->restrict_timer); + list_del(&s->list); + free(s); + } + } + + // If the timer is not already running + ss = calloc(1, sizeof(struct restrict_sta_entry)); + if (ss) { + memcpy(ss->sta, stalist[i], 6); + //memcpy(ss->bssid, fh->bssid, 6); + ss->vif = fh; + ss->restrict_timer.cb = wifi_restrict_sta_timeout; + uloop_timeout_set(&ss->restrict_timer, + validity_period * 1000); + list_add_tail(&ss->list, &fh->restrict_stalist); + } + } + return 0; +} + +int agent_check_stop_validity_tmr(uint32_t sta_count, uint8_t stalist[][6], + struct netif_fh *fh) +{ + uint32_t i = 0; + struct restrict_sta_entry *s = NULL, *tmp = NULL; + + trace("agent: %s: --->\n", __func__); + if (stalist == NULL) + return -1; + + for (i = 0; i < sta_count; i++) { + // check if the sta is already running a timer + // delete the timer + list_for_each_entry_safe(s, tmp, &fh->restrict_stalist, list) { + if (s != NULL) { + if (!memcmp(s->sta, stalist[i], 6)) { + uloop_timeout_cancel(&s->restrict_timer); + list_del(&s->list); + free(s); + } + } + } + } + return 0; +} + +int agent_process_assoc_cntl_tlv(void *agent, + struct tlv_client_assoc_control_req *p, + struct cmdu_cstruct *cmdu) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + int ret = 0, result = 0; + uint32_t match = 0, found = 0; + int i, j, k, l, m; + struct netif_fh *fh; + struct sta *s; + struct sta_error_response sta_resp[MAX_STA]; + uint32_t count = 0; + uint32_t res = 0, present = 0; + uint8_t sta_list[30][6]; + + for (m = 0; m < p->sta_list_cnt; m++) + memcpy(sta_list[m], p->client_assoc_ctrl_req_stas[m].addr, 6); + + fh = get_netif_by_bssid(a, p->bssid); + if (!fh) { + trace("[%s:%d] Error BSSID not present", __func__, __LINE__); + return -1; + } + + /*Here we first validate that the STA has been sent for + * blocking */ + if (p->assoc_control == 0x00) { + + /*Check if the validity timer value is not zero*/ + if (p->validity_period == 0) { + trace("[%s:%d] Error validity period is invalid\n", __func__, __LINE__); + return -1; + } + + /* Here we validate if the sta is associated with the bssid + * then we need to send an error TLV as the STA should not + * be associated with the bssid for which the blocking mode is + * set */ + + for (l = 0; l < p->sta_list_cnt; l++) { + list_for_each_entry(s, &fh->stalist, list) { + trace("stalist :" MACFMT "\n", + MAC2STR(s->macaddr)); + res = memcmp(s->macaddr, p->client_assoc_ctrl_req_stas[l].addr, 6); + if (res == 0) { + found = 1; + break; + } + } + if (found == 1) { + dbg("STA client already associated with the bssid!\n"); + memcpy(sta_resp[count].sta_mac, p->client_assoc_ctrl_req_stas[l].addr, 6); + sta_resp[count].response = 0x01; + count++; + } + } + /*Here we need the logic to block the STA*/ + ret = agent_send_restrict_sta(agent, p->sta_list_cnt, + sta_list, fh, p->assoc_control); + if (ret != 0) { + trace("[%s:%d] Error in agent_send_restrict_sta\n", __func__, __LINE__); + return -1; + } + /* Here we need to start the timer for which the sta is blocked as + * per the validity period also need to check if the sta is all + * in the blocking list */ + ret = agent_check_start_validity_tmr(p->validity_period, p->sta_list_cnt, sta_list, fh); + if (ret != 0) { + trace("[%s:%d] Error in start validity tmr\n", __func__, __LINE__); + return -1; + } + } else if (p->assoc_control == 0x01) { + + /*Here we will ignore the validity timer value in the request + * as the validity timer value is ignored in the unblock case */ + /*Here we need to check if the validity timer is already running + * in that case we need to stop the validity timer */ + ret = agent_check_stop_validity_tmr(p->sta_list_cnt, sta_list, fh); + if (ret != 0) { + trace("[%s:%d] Error in stop validity tmr\n", __func__, __LINE__); + return -1; + } + /*Here we need the logic to unblock the STA */ + ret = agent_send_restrict_sta(agent, p->sta_list_cnt, + sta_list, fh, p->assoc_control); + if (ret != 0) { + trace("[%s:%d] Error in agent_send_restrict_sta\n", __func__, __LINE__); + return -1; + } + } else { + trace("[%s:%d] Reserved mode is called", __func__, __LINE__); + } + +send_ack: + send_1905_acknowledge(agent, cmdu, sta_resp, count); + return ret; +} + int agent_process_steer_request_tlv(void *agent, struct tlv_steer_Req *p, struct cmdu_cstruct *cmdu) { @@ -2020,7 +2240,30 @@ int agent_transition_sta(struct agent *a, struct tlv_steer_Req *p, struct netif_ int handle_sta_assoc_control_request(void *agent, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); - return 0; + struct agent *a = (struct agent *) agent; + int ret = 0; + int i; + uint8_t *tlv = NULL; + + /* Here we first parse the steer request */ + if (cmdu->num_tlvs != 0) { + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = (uint8_t *) cmdu->tlvs[i]; + switch (*tlv) { + case MAP_TLV_CLIENT_ASSOCIATION_CONTROL_REQUEST: + { + struct tlv_client_assoc_control_req *p = + (struct tlv_client_assoc_control_req *)tlv; + + ret = agent_process_assoc_cntl_tlv(agent, + p, cmdu); + } + default: + break; + } + } + } + return ret; } int handle_hld_message(void *agent, struct cmdu_cstruct *cmdu)