From d1836e230853e2175256ea7b6e3435160e26d175 Mon Sep 17 00:00:00 2001 From: Liangwei Dong Date: Mon, 20 May 2019 10:47:38 +0530 Subject: [PATCH] nl80211: Introduce the interface to update new DH IE This command/event interface can be used by SME based host drivers that rely on user space (hostapd/wpa_supplicant) for DH IE processing/generation. This interface facilitates the OWE connection with host drivers by offloading DH IE processing to the user space (hostapd/wpa_supplicant). Signed-off-by: Srinivas Dasari Signed-off-by: Liangwei Dong Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 29 +++++++++++++++++++++++++++++ src/drivers/driver_common.c | 1 + src/drivers/driver_nl80211.c | 30 ++++++++++++++++++++++++++++++ src/drivers/driver_nl80211_event.c | 27 +++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 5f870a1f2..d0f449f72 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4220,6 +4220,21 @@ struct wpa_driver_ops { * Returns: 0 on success, < 0 on failure */ int (*set_4addr_mode)(void *priv, const char *bridge_ifname, int val); + + /** + * update_dh_ie - Update DH IE + * @priv: Private driver interface data + * @peer_mac: Peer MAC address + * @reason_code: Reacon code + * @ie: DH IE + * @ie_len: DH IE length in bytes + * Returns: 0 on success, -1 on failure + * + * This callback is used to let the driver know the DH processing result + * and DH IE for a pending association. + */ + int (*update_dh_ie)(void *priv, const u8 *peer_mac, u16 reason_code, + const u8 *ie, size_t ie_len); }; /** @@ -4765,6 +4780,11 @@ enum wpa_event_type { * This event is emitted when an interface is added/removed for WDS STA. */ EVENT_WDS_STA_INTERFACE_STATUS, + + /** + * EVENT_UPDATE_DH - Notification of updated DH information + */ + EVENT_UPDATE_DH, }; @@ -5598,6 +5618,15 @@ union wpa_event_data { INTERFACE_REMOVED } istatus; } wds_sta_interface; + + /** + * struct update_dh - Data for EVENT_UPDATE_DH + */ + struct update_dh { + const u8 *peer; + const u8 *ie; + size_t ie_len; + } update_dh; }; /** diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index b52e8baba..731c6a3b1 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -88,6 +88,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(STATION_OPMODE_CHANGED); E2S(INTERFACE_MAC_CHANGED); E2S(WDS_STA_INTERFACE_STATUS); + E2S(UPDATE_DH); } return "UNKNOWN"; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 96fd0aadd..45835a21b 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8750,6 +8750,35 @@ static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md, } +static int nl80211_update_dh_ie(void *priv, const u8 *peer_mac, + u16 reason_code, const u8 *ie, size_t ie_len) +{ + int ret; + struct nl_msg *msg; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "nl80211: Updating DH IE peer: " MACSTR + " reason %u", MAC2STR(peer_mac), reason_code); + if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UPDATE_OWE_INFO)) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer_mac) || + nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, reason_code) || + (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie))) { + nlmsg_free(msg); + return -ENOBUFS; + } + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) { + wpa_printf(MSG_DEBUG, + "nl80211: update_dh_ie failed err=%d (%s)", + ret, strerror(-ret)); + } + + return ret; +} + + static const u8 * wpa_driver_nl80211_get_macaddr(void *priv) { struct i802_bss *bss = priv; @@ -11052,6 +11081,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch, #endif /* CONFIG_TDLS */ .update_ft_ies = wpa_driver_nl80211_update_ft_ies, + .update_dh_ie = nl80211_update_dh_ie, .get_mac_addr = wpa_driver_nl80211_get_macaddr, .get_survey = wpa_driver_nl80211_get_survey, .status = wpa_driver_nl80211_status, diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 07aa335f6..7c1633066 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -136,6 +136,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd) C2S(NL80211_CMD_EXTERNAL_AUTH) C2S(NL80211_CMD_STA_OPMODE_CHANGED) C2S(NL80211_CMD_CONTROL_PORT_FRAME) + C2S(NL80211_CMD_UPDATE_OWE_INFO) default: return "NL80211_CMD_UNKNOWN"; } @@ -1105,6 +1106,29 @@ static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv, } +static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv, + struct i802_bss *bss, + struct nlattr *tb[]) +{ + union wpa_event_data data; + + if (!is_ap_interface(drv->nlmode)) + return; + if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_IE]) + return; + + os_memset(&data, 0, sizeof(data)); + data.update_dh.peer = nla_data(tb[NL80211_ATTR_MAC]); + data.update_dh.ie = nla_data(tb[NL80211_ATTR_IE]); + data.update_dh.ie_len = nla_len(tb[NL80211_ATTR_IE]); + + wpa_printf(MSG_DEBUG, "nl80211: DH event - peer " MACSTR, + MAC2STR(data.update_dh.peer)); + + wpa_supplicant_event(bss->ctx, EVENT_UPDATE_DH, &data); +} + + static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, struct nlattr *tb[], int external_scan) { @@ -2601,6 +2625,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_STA_OPMODE_CHANGED: nl80211_sta_opmode_change_event(drv, tb); break; + case NL80211_CMD_UPDATE_OWE_INFO: + mlme_event_dh_event(drv, bss, tb); + break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd);