For debugging purposes, it can be useful to be able to retrieve keys. Add a "iw key get" command, to be able to retrieve keys when the key index is known. A new "key" section is also introduced, in preparation for future key-related commands. Example retrieving a pairwise key: iw dev wlan0 key get 0 02:02:03:04:05:06 Example retrieving a group key: iw dev wlan0 key get 1 Note that only the outer ATTR_KEY_DATA (and seq) is reported, the nested KEY_DATA (and seq) within ATTR_KEY is not. Signed-off-by: Raphaël Mélotte <raphael.melotte@xxxxxxx> --- Changes v2 -> v3: - Check parsing of index. - Move pairwise type before argv++ and add line break. Changes v1 -> v2: - Introduce a 'key' section and update commit message - Fix documentation (and remove pairwise flag) - Return error when MAC is invalid - Rebase on master keys.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 keys.c diff --git a/keys.c b/keys.c new file mode 100644 index 0000000..65aa426 --- /dev/null +++ b/keys.c @@ -0,0 +1,83 @@ +#include <errno.h> +#include <netlink/genl/genl.h> +#include <netlink/genl/family.h> +#include <netlink/genl/ctrl.h> +#include <netlink/msg.h> +#include <netlink/attr.h> +#include "nl80211.h" +#include "iw.h" + +SECTION(key); + +static int print_keys(struct nl_msg *msg, void *arg) +{ + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_KEY_IDX]) { + fprintf(stderr, "KEY_IDX missing!\n"); + return NL_SKIP; + } + + if (!tb[NL80211_ATTR_KEY_DATA]) { + fprintf(stderr, "ATTR_KEY_DATA missing!\n"); + return NL_SKIP; + } + + iw_hexdump("Key", nla_data(tb[NL80211_ATTR_KEY_DATA]), + nla_len(tb[NL80211_ATTR_KEY_DATA])); + + if (!tb[NL80211_ATTR_KEY_SEQ]) { + fprintf(stderr, "ATTR_KEY_SEQ missing!\n"); + return NL_SKIP; + } + + iw_hexdump("Key seq", nla_data(tb[NL80211_ATTR_KEY_SEQ]), + nla_len(tb[NL80211_ATTR_KEY_SEQ])); + + return NL_OK; +} + +static int handle_get_key(struct nl80211_state *state, + struct nl_msg *msg, int argc, char **argv, + enum id_input id) +{ + char *end; + unsigned char mac[6]; + + /* key index */ + if (argc) { + nla_put_u8(msg, NL80211_ATTR_KEY_IDX, strtoul(argv[0], &end, 10)); + if (*end != '\0') + return -EINVAL; + argv++; + argc--; + } + + /* mac */ + if (argc) { + if (mac_addr_a2n(mac, argv[0]) == 0) { + NLA_PUT(msg, NL80211_ATTR_MAC, 6, mac); + nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, + NL80211_KEYTYPE_PAIRWISE); + argv++; + argc--; + } else { + return -EINVAL; + } + } else { + nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, NL80211_KEYTYPE_GROUP); + } + + register_handler(print_keys, NULL); + return 0; + + nla_put_failure: + return -ENOSPC; +} +COMMAND(key, get, "<key index> <MAC address>", + NL80211_CMD_GET_KEY, 0, CIB_NETDEV, handle_get_key, + "Retrieve a key and key sequence.\n"); -- 2.38.1