Linux 2.6.32 (December 2009) introduced an alternate netlink message format for setting and querying key information, deprecating the older one. To allow hostapd/wpa_supplicant to use new features only provided via the new format this patch migrates all key netlink messages for key installs and queries to the new format. Since some parts of the nl80211 driver do already use the new format this should not change the minimal kernel requirement and only unify the netlink API usage. The following netlink attributes have been dropped from all key install and query functions: NL80211_ATTR_KEY_DATA NL80211_ATTR_KEY_TYPE NL80211_ATTR_KEY_SEQ NL80211_ATTR_KEY_IDX NL80211_ATTR_KEY_CIPHER NL80211_ATTR_KEY_DEFAULT NL80211_ATTR_KEY_DEFAULT_MGMT NL80211_ATTR_KEY_DEFAULT_TYPES And replaced by the following attributes nested in NL80211_ATTR_KEY: NL80211_KEY_DATA NL80211_KEY_TYPE NL80211_KEY_SEQ NL80211_KEY_IDX NL80211_KEY_CIPHER NL80211_KEY_DEFAULT NL80211_KEY_DEFAULT_MGMT NL80211_KEY_DEFAULT_TYPES But when detecting and reporting michael mic_failures the kernel even current kernels are still using: NL80211_ATTR_KEY_TYPE NL80211_ATTR_KEY_SEQ NL80211_ATTR_KEY_IDX Therefore we still have to use them there when processing michael mic_failures events. Signed-off-by: Alexander Wetzel <alexander@xxxxxxxxxxxxxx> --- There is not much to add to the commit log, most of it is straight forward. But I tried to keep the existing logic and therefore start an additional key netlink message to be still able to fill in the information with the existing logic and not the more usual nla_nest_start(). src/drivers/driver_nl80211.c | 88 ++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 7b31b52c7..f6035a17c 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3015,7 +3015,8 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, { struct wpa_driver_nl80211_data *drv = bss->drv; int ifindex; - struct nl_msg *msg = NULL; + struct nl_msg *msg; + struct nl_msg *key_msg; int ret; int tdls = 0; @@ -3049,26 +3050,31 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) return nl80211_set_pmk(drv, key, key_len, addr); + key_msg = nlmsg_alloc(); + if (!key_msg) + return -ENOBUFS; + if (alg == WPA_ALG_NONE) { msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY); if (!msg) - return -ENOBUFS; + goto fail2; } else { u32 suite; suite = wpa_alg_to_cipher_suite(alg, key_len); if (!suite) - goto fail; + goto fail2; msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY); - if (!msg || - nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) || - nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER, suite)) + if (!msg) + goto fail2; + if (nla_put(key_msg, NL80211_KEY_DATA, key_len, key) || + nla_put_u32(key_msg, NL80211_KEY_CIPHER, suite)) goto fail; wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len); } if (seq && seq_len) { - if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq)) + if (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq)) goto fail; wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len); } @@ -3080,7 +3086,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, if (alg != WPA_ALG_WEP && key_idx && !set_tx) { wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); - if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, + if (nla_put_u32(key_msg, NL80211_KEY_TYPE, NL80211_KEYTYPE_GROUP)) goto fail; } @@ -3089,13 +3095,14 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, wpa_printf(MSG_DEBUG, " broadcast key"); - types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES); + types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES); if (!types || - nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) + nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) goto fail; - nla_nest_end(msg, types); + nla_nest_end(key_msg, types); } - if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx)) + if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || + nla_put_nested(msg, NL80211_ATTR_KEY, key_msg)) goto fail; ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL); @@ -3115,34 +3122,43 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, !is_broadcast_ether_addr(addr)) return ret; + key_msg = nlmsg_alloc(); + if (!key_msg) + return -ENOBUFS; + msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); - if (!msg || - nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) || - nla_put_flag(msg, (alg == WPA_ALG_IGTK || - alg == WPA_ALG_BIP_GMAC_128 || - alg == WPA_ALG_BIP_GMAC_256 || - alg == WPA_ALG_BIP_CMAC_256) ? - NL80211_ATTR_KEY_DEFAULT_MGMT : - NL80211_ATTR_KEY_DEFAULT)) + if (!msg) + goto fail2; + if (!key_msg || + nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || + nla_put_flag(key_msg, (alg == WPA_ALG_IGTK || + alg == WPA_ALG_BIP_GMAC_128 || + alg == WPA_ALG_BIP_GMAC_256 || + alg == WPA_ALG_BIP_CMAC_256) ? + NL80211_KEY_DEFAULT_MGMT : + NL80211_KEY_DEFAULT)) goto fail; if (addr && is_broadcast_ether_addr(addr)) { struct nlattr *types; - types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES); + types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES); if (!types || - nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) + nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) goto fail; - nla_nest_end(msg, types); + nla_nest_end(key_msg, types); } else if (addr) { struct nlattr *types; - types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES); + types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES); if (!types || - nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST)) + nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_UNICAST)) goto fail; - nla_nest_end(msg, types); + nla_nest_end(key_msg, types); } + if (nla_put_nested(msg, NL80211_ATTR_KEY, key_msg)) + goto fail; + ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret == -ENOENT) ret = 0; @@ -3154,6 +3170,9 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, fail: nl80211_nlmsg_clear(msg); nlmsg_free(msg); +fail2: + nl80211_nlmsg_clear(key_msg); + nlmsg_free(key_msg); return -ENOBUFS; } @@ -6183,7 +6202,11 @@ static inline int min_int(int a, int b) static int get_key_handler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct nlattr *attrs[NL80211_KEY_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + static struct nla_policy key_policy[NL80211_KEY_MAX + 1] = { + [NL80211_KEY_SEQ] = { .type = NLA_BINARY }, + }; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -6194,9 +6217,11 @@ static int get_key_handler(struct nl_msg *msg, void *arg) * the kernel starts sending key notifications. */ - if (tb[NL80211_ATTR_KEY_SEQ]) - memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]), - min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6)); + if (tb[NL80211_ATTR_KEY] && + !nla_parse_nested(attrs, NL80211_KEY_MAX, tb[NL80211_ATTR_KEY], + key_policy)) + memcpy(arg, nla_data(attrs[NL80211_KEY_SEQ]), + min_int(nla_len(attrs[NL80211_KEY_SEQ]), 16)); nl80211_nlmsg_clear(msg); return NL_SKIP; } @@ -6208,16 +6233,19 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; + struct nlattr *key_attr; msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0, NL80211_CMD_GET_KEY); if (!msg || (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) || - nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) { + (key_attr = nla_nest_start(msg, NL80211_ATTR_KEY)) || + nla_put_u8(msg, NL80211_KEY_IDX, idx)) { nlmsg_free(msg); return -ENOBUFS; } + nla_nest_end(msg, key_attr); memset(seq, 0, 6); return send_and_recv_msgs(drv, msg, get_key_handler, seq); -- 2.22.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap