From 55a49b0614fbd0c454c655d72d9bf9825706d77c Mon Sep 17 00:00:00 2001 From: Kamil Zulewski <kamil.zulewski@iopsys.eu> Date: Thu, 9 Nov 2023 17:15:54 +0100 Subject: [PATCH] skip redundant ap autoconifg wsc based on cmdu md5 sum --- src/agent.c | 8 +++ src/agent.h | 2 + src/agent_map.c | 131 +++++++++++++++++++++++++++++++++++++++++++--- src/utils/utils.c | 1 + 4 files changed, 135 insertions(+), 7 deletions(-) diff --git a/src/agent.c b/src/agent.c index 2c97ce3ec..0a42d9369 100644 --- a/src/agent.c +++ b/src/agent.c @@ -5047,6 +5047,7 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type, enum autocfg_state state; uint16_t mid; uint16_t wsc_mid; + uint8_t autconfig_wsc_md5sum[MD5_SUM_LENGTH]; } apcfg_state[WIFI_DEVICE_MAX_NUM] = {0}; struct agent *a = (struct agent *)req->priv; struct json_object *json_msg; @@ -5079,6 +5080,10 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type, apcfg_state[i].state = a->radios[i].state; apcfg_state[i].mid = a->radios[i].mid; apcfg_state[i].wsc_mid = a->radios[i].wsc_mid; + apcfg_state[i].wsc_mid = a->radios[i].wsc_mid; + memcpy(apcfg_state[i].autconfig_wsc_md5sum, + a->radios[i].autconfig_wsc_md5sum, + MD5_SUM_LENGTH); } prev_len = a->num_radios; /* clears radio apcfg states */ @@ -5119,6 +5124,9 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type, a->radios[i].state = apcfg_state[j].state; a->radios[i].mid = apcfg_state[j].mid; a->radios[i].wsc_mid = apcfg_state[j].wsc_mid; + memcpy(a->radios[i].autconfig_wsc_md5sum, + apcfg_state[i].autconfig_wsc_md5sum, + MD5_SUM_LENGTH); } } diff --git a/src/agent.h b/src/agent.h index 31eb2092d..89b707e50 100644 --- a/src/agent.h +++ b/src/agent.h @@ -530,6 +530,7 @@ struct wifi_cac_request { uint8_t report_failed_status; }; +# define MD5_SUM_LENGTH 16 struct wifi_radio_element { char name[16]; uint8_t macaddr[6]; @@ -600,6 +601,7 @@ struct wifi_radio_element { uint16_t mid; uint16_t wsc_mid; uint16_t renew_mid; /* debug purposes */ + uint8_t autconfig_wsc_md5sum[MD5_SUM_LENGTH]; #if (EASYMESH_VERSION > 2) bool dpp_onboarded; diff --git a/src/agent_map.c b/src/agent_map.c index da683d5e7..e28373be9 100644 --- a/src/agent_map.c +++ b/src/agent_map.c @@ -37,6 +37,7 @@ #include <json-c/json.h> #include <libubox/blobmsg.h> #include <libubox/blobmsg_json.h> +#include <libubox/md5.h> #include <libubox/uloop.h> #include <libubox/ustream.h> #include <libubox/utils.h> @@ -1954,7 +1955,105 @@ bool agent_is_ts_enabled(struct agent *a) return true; } +static bool has_ap_autoconfig_wsc_changed(struct agent *a, + struct tlv *tlvs[][TLV_MAXNUM], + size_t tlvs_size, uint8_t *md5sum_out) +{ + enum { + AP_RADIO_ID = 0, + WSC = 1, + DEFAULT_8021Q_SETTINGS = 2, + TRAFFIC_SEPARATION_POLICY = 3, + + MAX_TLV_TYPES = 4 + }; + + uint8_t new_md5sum[MD5_SUM_LENGTH]; + const struct wifi_radio_element *radio; + uint8_t bssid[6]; + md5_ctx_t ctx; + int i; + + if (tlvs_size != MAX_TLV_TYPES) { + err("%s: unsupported version of CMDU.\n", __func__); + return true; + } + + memcpy(bssid, tlvs[AP_RADIO_ID][0]->data, 6); + radio = wifi_get_radio_by_mac(a, bssid); + if (!radio) { + err("%s: Unknown radio.\n", __func__); + return true; + } + + /* Calculate MD5 hash from all TLVs data */ + md5_begin(&ctx); + md5_hash(tlvs[AP_RADIO_ID][0]->data, tlv_length(tlvs[AP_RADIO_ID][0]), &ctx); + + + /* Use decrypted data of WSC TLVs */ + i = 0; + while (i < TLV_MAXNUM && tlvs[WSC][i]) { + struct wps_credential wps_out = { 0 }; + uint8_t *ext_out = NULL; + uint16_t ext_len = 0; + int ret = 0; + uint16_t m2_len = tlv_length(tlvs[WSC][i]); + /* It's workaround as wsc_process_m2 modifies m2 buffer */ + uint8_t *m2_tmp = malloc(m2_len); + + if (!m2_tmp) + return true; + + memcpy(m2_tmp, tlvs[WSC][i]->data, m2_len); + + ret = wsc_process_m2(radio->autconfig.m1_frame, + radio->autconfig.m1_size, + radio->autconfig.key, m2_tmp, m2_len, + &wps_out, &ext_out, &ext_len); + + free(m2_tmp); + + if (ret) + return true; + + md5_hash(&wps_out, sizeof(wps_out), &ctx); + md5_hash(ext_out, ext_len, &ctx); + + free(ext_out); + + ++i; + } + + + if (tlvs[DEFAULT_8021Q_SETTINGS][0]) { + md5_hash(tlvs[DEFAULT_8021Q_SETTINGS][0]->data, + tlv_length(tlvs[DEFAULT_8021Q_SETTINGS][0]), &ctx); + } + + if (tlvs[TRAFFIC_SEPARATION_POLICY][0]) { + md5_hash(tlvs[TRAFFIC_SEPARATION_POLICY][0]->data, + tlv_length(tlvs[TRAFFIC_SEPARATION_POLICY][0]), &ctx); + } + + md5_end(new_md5sum, &ctx); + + dbg("%s: current md5sum: %02x%02x%02x%02x%02x%02x...\n", __func__, + radio->autconfig_wsc_md5sum[0], radio->autconfig_wsc_md5sum[1], + radio->autconfig_wsc_md5sum[2], radio->autconfig_wsc_md5sum[3], + radio->autconfig_wsc_md5sum[4], radio->autconfig_wsc_md5sum[5]); + + dbg("%s: new md5sum: %02x%02x%02x%02x%02x%02x...\n", __func__, + new_md5sum[0], new_md5sum[1], new_md5sum[2], new_md5sum[3], + new_md5sum[4], new_md5sum[5]); + + memcpy(md5sum_out, new_md5sum, MD5_SUM_LENGTH); + + return memcmp(radio->autconfig_wsc_md5sum, new_md5sum, MD5_SUM_LENGTH); +} + #define RELOAD_TIMEOUT 5 +#define AP_AUTOCONFIG_TLVS_SIZE 4 int handle_ap_autoconfig_wsc(void *agent, struct cmdu_buff *rx_cmdu, struct node *n) @@ -1962,8 +2061,9 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_buff *rx_cmdu, struct agent *a = (struct agent *) agent; uint8_t bssid[6]; struct wifi_radio_element *radio; - struct tlv *tv[4][TLV_MAXNUM] = {0}; + struct tlv *tv[AP_AUTOCONFIG_TLVS_SIZE][TLV_MAXNUM] = {0}; int ret = 0, num = 0; + uint8_t new_md5sum[MD5_SUM_LENGTH] = {0}; trace("%s: --->\n", __func__); @@ -1978,12 +2078,6 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_buff *rx_cmdu, return -1; } - if (tv[2][0]) { - struct tlv_default_8021q_settings *tlv = (struct tlv_default_8021q_settings *) tv[2][0]->data; - //uci_apply_default_8021q_settings(tlv); - agent_fill_8021q_setting_from_tlv(a, tlv); - } - memcpy(bssid, tv[0][0]->data, 6); radio = wifi_get_radio_by_mac(a, bssid); @@ -1992,6 +2086,24 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_buff *rx_cmdu, dbg("|%s:%d| found radio = %s\n", __func__, __LINE__, radio->name); + if (!has_ap_autoconfig_wsc_changed(a, tv, AP_AUTOCONFIG_TLVS_SIZE, new_md5sum)) { + info("%s: The same config received, skip radio configuration for: " MACFMT "\n", + __func__, MAC2STR(radio->macaddr)); + + radio->state = AUTOCFG_HEARTBEAT; + goto teardown; + } + + dbg("%s: New config received for radio: " MACFMT"\n", + __func__, MAC2STR(radio->macaddr)); + + if (tv[2][0]) { + struct tlv_default_8021q_settings *tlv = (struct tlv_default_8021q_settings *) tv[2][0]->data; + //uci_apply_default_8021q_settings(tlv); + agent_fill_8021q_setting_from_tlv(a, tlv); + } + + if (radio->dedicated_backhaul) { dbg("|%s:%d| %s is dedicated backhaul"\ " radio found - discard WSC and set to"\ @@ -2131,6 +2243,11 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_buff *rx_cmdu, radio->state = AUTOCFG_HEARTBEAT; agent_autoconfig_event(a, radio->name, "success", "completed"); + /* Save successfully processed autoconfig wsc md5sum */ + memcpy(radio->autconfig_wsc_md5sum, new_md5sum, MD5_SUM_LENGTH); + dbg("%s: Applied autoconfig md5sum: %02x%02x%02x%02x%02x%02x...\n", __func__, + new_md5sum[0], new_md5sum[1], new_md5sum[2], new_md5sum[3], new_md5sum[4], new_md5sum[5]); + exit: a->reconfig_reason |= AGENT_RECONFIG_REASON_AP_AUTOCONF; /* ap autoconfig bit */ timer_set(&a->reload_scheduler, RELOAD_TIMEOUT * 1000); diff --git a/src/utils/utils.c b/src/utils/utils.c index e92350740..eb80a74d0 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -624,3 +624,4 @@ bool is_vid_valid(unsigned int vid) { return (vid < TS_VID_INVALID) && (vid > 0); } + -- GitLab