From e99a3956364cc28f99dbe0efeb2b1710113933c2 Mon Sep 17 00:00:00 2001 From: Saurabh Verma <saurabh.verma@iopsys.eu> Date: Fri, 19 Feb 2021 14:15:31 +0000 Subject: [PATCH] map-agent: Added support for tunnel message for assoc/reassoc method. --- src/core/agent.c | 116 +++++++++++++++++++++++++++++++- src/core/agent.h | 2 + src/core/agent_cmdu_generator.c | 67 ++++++++++++++++++ src/core/agent_cmdu_generator.h | 2 + src/core/agent_map.c | 51 ++++++++++++++ src/core/agent_tlv_generator.c | 55 +++++++++++++++ src/core/agent_tlv_generator.h | 5 ++ 7 files changed, 295 insertions(+), 3 deletions(-) diff --git a/src/core/agent.c b/src/core/agent.c index d6201c67b..5df9bc35f 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -223,6 +223,34 @@ static int ubus_call_object(struct agent *a, wifi_object_t wobj, return 0; } +static int ubus_call_object_subscribe_unsubscribe(struct agent *a, wifi_object_t wobj, + const char *method, + void (*response_cb)(struct ubus_request *, int, struct blob_attr *), + void *priv) +{ + struct blob_buf bb = {}; + int ret; + struct subscribe_fr { + uint8_t type; + uint8_t stype; + } *subfr; + + subfr = (struct subscribe_fr *)priv; + blob_buf_init(&bb, 0); + blobmsg_add_u32(&bb, "type", subfr->type); + blobmsg_add_u32(&bb, "stype", subfr->stype); + ret = ubus_invoke(a->ubus_ctx, wobj, method, bb.head, + response_cb, priv, 2 * 1000); + if (ret) { + err("Failed to get '%s' (ret = %d)\n", method, ret); + blob_buf_free(&bb); + return -1; + } + + blob_buf_free(&bb); + return 0; +} + static uint32_t ubus_get_object(struct ubus_context *ctx, const char *name) { uint32_t id; @@ -1624,6 +1652,71 @@ out_frame: return -1; } +static int get_frame_type(struct agent *a, struct json_object *frameobj) +{ + const char *framestr; + int frame_type = -1; + + framestr = json_object_to_json_string(frameobj); + if (!framestr) + return -1; + + if (strstr(framestr, "reassoc")) + frame_type = WIFI_FRAME_REASSOC_REQ; + else if (strstr(framestr, "assoc")) + frame_type = WIFI_FRAME_ASSOC_REQ; + else if (strstr(framestr, "deauth")) + frame_type = WIFI_FRAME_DEAUTH; + else if (strstr(framestr, "auth")) + frame_type = WIFI_FRAME_AUTH; + else if (strstr(framestr, "action")) + frame_type = WIFI_FRAME_ACTION; + + return frame_type; +} + +static int wifi_parse_all_frame(struct agent *a, struct json_object *frameobj) +{ + trace("%s\n", __func__); + const char *framestr; + int stype; + uint8_t protocol = 0xff; + + stype = get_frame_type(a, frameobj); + if (stype == -1) + return -1; + + switch (stype) { + case WIFI_FRAME_REASSOC_REQ: + protocol = 0x01; + framestr = json_get_string(frameobj, "reassoc"); + break; + case WIFI_FRAME_ASSOC_REQ: + protocol = 0x00; + framestr = json_get_string(frameobj, "assoc"); + break; + case WIFI_FRAME_DEAUTH: + framestr = json_get_string(frameobj, "deauth"); + break; + case WIFI_FRAME_AUTH: + framestr = json_get_string(frameobj, "auth"); + break; + case WIFI_FRAME_ACTION: + framestr = json_get_string(frameobj, "action"); + break; + default: + framestr = NULL; + break; + } + + if (!framestr) + return -1; + + prepare_tunneled_message((void *)a, protocol, framestr); + + return 0; +} + static void wifi_iface_event_handler(void *c, struct blob_attr *msg) { struct agent *a = (struct agent *)c; @@ -1656,9 +1749,15 @@ static void wifi_iface_event_handler(void *c, struct blob_attr *msg) if (!event) goto out_json; - if (!strcmp(event, "frame-rx")) + if (!strcmp(event, "frame-rx")) { wifi_parse_frame(a, data); + /* parse all tunneled type message + * (assoc, reassoc, BTM, WNM, ANQP) + */ + wifi_parse_all_frame(a, data); + } + out_json: json_object_put(jmsg); out_str: @@ -3398,6 +3497,14 @@ static int agent_init_interfaces(struct agent *a) fn = netif_alloc_fh(f->name); if (fn) { + struct subscribe_fr { + uint8_t type; + uint8_t stype; + } subfr[] = {{0, 0}, {0, 2}, {0, 10}, + {0, 11}, {0, 12}, {0, 13}}; + int num_subfr = ARRAY_SIZE(subfr); + int k; + fn->wifi = wobj; fn->radio = r_wobj; fn->cfg = f; @@ -3405,8 +3512,11 @@ static int agent_init_interfaces(struct agent *a) list_add(&fn->list, &a->fhlist); ubus_call_object(a, wobj, "status", parse_ap, fn); - ubus_call_object(a, wobj, "subscribe_frame", - NULL, NULL); + + for (k = 0; k < num_subfr; k++) + ubus_call_object_subscribe_unsubscribe(a, wobj, + "subscribe_frame", NULL, &subfr[k]); + ubus_call_object(a, wobj, "stats", parse_ap_stats, fn); } } diff --git a/src/core/agent.h b/src/core/agent.h index 4336fb777..85f281ec8 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -481,5 +481,7 @@ extern int plugins_unload(struct list_head *plugins); struct netif_fh *wifi_radio_to_ap(struct agent *a, const char *radio); struct wifi_radio_element *wifi_ifname_to_radio_element(struct agent *a, char *ifname); +int prepare_tunneled_message(void *agent, uint8_t protocol, + const char *framestr); #endif /* AGENT_H */ diff --git a/src/core/agent_cmdu_generator.c b/src/core/agent_cmdu_generator.c index 73e84b74b..aeff49442 100644 --- a/src/core/agent_cmdu_generator.c +++ b/src/core/agent_cmdu_generator.c @@ -579,3 +579,70 @@ error: return NULL; } + +struct cmdu_cstruct *agent_gen_tunneled_msg(struct agent *a, uint8_t protocol, + uint8_t *sta, int frame_len, uint8_t *frame_body) +{ + struct cmdu_cstruct *cmdu; + struct tlv_source_info *p1; + struct tlv_tunnel_msg_type *p2; + struct tlv_tunneled *p3; + int tlv_index = 0; + + /* TODO: check profile type + * return NULL,in case of PROFILE-1 + * #ifdef PROFILE1 + * return NULL; + * #endif + */ + + if (!sta && !frame_body) + return NULL; + + cmdu = calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu) + return NULL; + + cmdu->message_type = CMDU_TUNNELED; + memcpy(cmdu->origin, a->cntlr_almac, 6); + /* TODO/FIXME: interface name + * hardcoded: br-lan + */ + strncpy(cmdu->intf_name, "br-lan", IFNAMESIZE - 1); + + cmdu->num_tlvs = 3; + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, + sizeof(uint8_t *)); + if (!cmdu->tlvs) { + cmdu->num_tlvs = 0; + goto error; + } + + /* Source Info TLV */ + p1 = agent_gen_source_info(a, sta); + if (!p1) + goto error; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p1; + + /* Tunneled message type TLV */ + p2 = agent_gen_tunnel_msg_type(a, protocol); + if (!p2) + goto error; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p2; + + /* Tunneled TLV */ + p3 = agent_gen_tunneled(a, frame_len, frame_body); + if (!p3) + goto error; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p3; + + return cmdu; + +error: + map_free_cmdu(cmdu); + + return NULL; +} diff --git a/src/core/agent_cmdu_generator.h b/src/core/agent_cmdu_generator.h index ced1c60c6..2eb4d20eb 100644 --- a/src/core/agent_cmdu_generator.h +++ b/src/core/agent_cmdu_generator.h @@ -19,5 +19,7 @@ struct cmdu_cstruct *agent_gen_assoc_sta_metric_response_per_intf( struct agent *a, char *ifname); struct cmdu_cstruct *agent_gen_assoc_sta_metric_response( struct agent *a, struct cmdu_cstruct *rec_cmdu); +struct cmdu_cstruct *agent_gen_tunneled_msg(struct agent *a, uint8_t protocol, + uint8_t *sta, int frame_len, uint8_t *frame_body); #endif diff --git a/src/core/agent_map.c b/src/core/agent_map.c index 3bef6dcdd..a97e67a1d 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -3013,6 +3013,57 @@ int handle_error_response(void *agent, struct cmdu_cstruct *cmdu) return 0; } +int prepare_tunneled_message(void *agent, + uint8_t protocol, const char *framestr) +{ + trace("%s: --->\n", __func__); + struct agent *a = (struct agent *)agent; + struct cmdu_cstruct *cmdu; + uint8_t *frame; + uint8_t sta_mac[6] = { 0 }; + int len; + int index; + + if (!framestr) + return -1; + + /* TODO/FIXME: add other protocol + * checking (BTM/WNM/ANQP) + * as of now checking assoc/reassoc + * type only. + */ + if ((protocol != 0x00) && (protocol != 0x01)) + return -1; + + len = strlen(framestr); + len = (len - 1) / 2; + frame = calloc(len, sizeof(uint8_t)); + if (!frame) + return -1; + + if (!strtob((char *)framestr, len, frame)) + goto error; + + index = 2 + 2 + 6; /* sta mac index */ + memcpy(sta_mac, frame + index, 6); + + cmdu = agent_gen_tunneled_msg(a, protocol, sta_mac, + len, frame); + if (!cmdu) + goto error; + + agent_send_cmdu(a, cmdu); + map_free_cmdu(cmdu); + free(frame); + + return 0; + +error: + free(frame); + + return -1; +} + int handle_backhaul_sta_caps_query(void *agent, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); diff --git a/src/core/agent_tlv_generator.c b/src/core/agent_tlv_generator.c index 946e38002..d87296d50 100644 --- a/src/core/agent_tlv_generator.c +++ b/src/core/agent_tlv_generator.c @@ -901,6 +901,61 @@ struct tlv_ap_radio_identifier *agent_gen_ap_radio_identifier( return p; } +struct tlv_source_info *agent_gen_source_info( + struct agent *a, uint8_t *mac) +{ + struct tlv_source_info *p; + + if (!mac) + return NULL; + + p = calloc(1, sizeof(*p)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_SOURCE_INFO; + memcpy(p->mac, mac, 6); + return p; +} + +struct tlv_tunnel_msg_type *agent_gen_tunnel_msg_type( + struct agent *a, uint8_t protocol) +{ + struct tlv_tunnel_msg_type *p; + + p = calloc(1, sizeof(*p)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_TUNNELED_MSG_TYPE; + p->tunnel_protocol_type = protocol; + return p; +} + +struct tlv_tunneled *agent_gen_tunneled(struct agent *a, + int frame_len, uint8_t *frame_body) +{ + struct tlv_tunneled *p; + + if ((!frame_body) || (frame_len <= 0)) + return NULL; + + p = calloc(1, sizeof(*p)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_TUNNELED; + p->tlv_len = frame_len; + p->frame_body = calloc(frame_len, sizeof(uint8_t)); + if (!p->frame_body) { + free(p); + return NULL; + } + + memcpy(p->frame_body, frame_body, frame_len); + return p; +} + int agent_fill_steering_policy(struct agent *a, struct tlv_steering_policy *p, struct uci_context *ctx, struct uci_package *pkg) diff --git a/src/core/agent_tlv_generator.h b/src/core/agent_tlv_generator.h index cd2587a25..5c4117eb3 100644 --- a/src/core/agent_tlv_generator.h +++ b/src/core/agent_tlv_generator.h @@ -67,6 +67,11 @@ struct tlv_assoc_sta_ext_link_metric *agent_gen_assoc_sta_ext_link_metric( struct agent *a, struct sta *s, uint8_t *bssid); struct tlv_ap_radio_identifier *agent_gen_ap_radio_identifier( struct agent *a, uint8_t *radio_id); +struct tlv_source_info *agent_gen_source_info(struct agent *a, uint8_t *mac); +struct tlv_tunnel_msg_type *agent_gen_tunnel_msg_type( + struct agent *a, uint8_t protocol); +struct tlv_tunneled *agent_gen_tunneled(struct agent *a, + int frame_len, uint8_t *frame_body); /* Policy config related functions */ int agent_fill_steering_policy(struct agent *a, -- GitLab