Module Name: src Committed By: christos Date: Thu Oct 16 19:29:30 UTC 2014
Modified Files: src/external/bsd/wpa/bin/hostapd: Makefile src/external/bsd/wpa/bin/wpa_supplicant: Makefile src/external/bsd/wpa/dist/hostapd: hostapd_cli.c src/external/bsd/wpa/dist/src/ap: wpa_auth.c src/external/bsd/wpa/dist/src/drivers: driver_bsd.c driver_test.c src/external/bsd/wpa/dist/src/eap_server: eap_server_tls_common.c src/external/bsd/wpa/dist/src/radius: radius_das.c src/external/bsd/wpa/dist/src/utils: eloop.c os.h radiotap.h src/external/bsd/wpa/dist/wpa_supplicant: wpa_cli.c Removed Files: src/external/bsd/wpa/dist/hostapd: dump_state.c dump_state.h src/external/bsd/wpa/dist/patches: openssl-0.9.8-tls-extensions.patch openssl-0.9.8d-tls-extensions.patch openssl-0.9.8e-tls-extensions.patch openssl-0.9.8g-tls-extensions.patch openssl-0.9.8h-tls-extensions.patch openssl-0.9.8i-tls-extensions.patch openssl-0.9.8x-tls-extensions.patch openssl-0.9.9-session-ticket.patch src/external/bsd/wpa/dist/src/crypto: fips_prf_cryptoapi.c fips_prf_gnutls.c fips_prf_nss.c src/external/bsd/wpa/dist/src/utils: eloop_none.c Log Message: merge conflicts. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/external/bsd/wpa/bin/hostapd/Makefile cvs rdiff -u -r1.3 -r1.4 src/external/bsd/wpa/bin/wpa_supplicant/Makefile cvs rdiff -u -r1.1.1.3 -r0 src/external/bsd/wpa/dist/hostapd/dump_state.c cvs rdiff -u -r1.1.1.2 -r0 src/external/bsd/wpa/dist/hostapd/dump_state.h cvs rdiff -u -r1.5 -r1.6 src/external/bsd/wpa/dist/hostapd/hostapd_cli.c cvs rdiff -u -r1.1.1.1 -r0 \ src/external/bsd/wpa/dist/patches/openssl-0.9.8-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.8d-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.8e-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.8g-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.8h-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.8i-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.8x-tls-extensions.patch \ src/external/bsd/wpa/dist/patches/openssl-0.9.9-session-ticket.patch cvs rdiff -u -r1.6 -r1.7 src/external/bsd/wpa/dist/src/ap/wpa_auth.c cvs rdiff -u -r1.1.1.2 -r0 \ src/external/bsd/wpa/dist/src/crypto/fips_prf_cryptoapi.c \ src/external/bsd/wpa/dist/src/crypto/fips_prf_gnutls.c \ src/external/bsd/wpa/dist/src/crypto/fips_prf_nss.c cvs rdiff -u -r1.9 -r1.10 src/external/bsd/wpa/dist/src/drivers/driver_bsd.c cvs rdiff -u -r1.4 -r1.5 src/external/bsd/wpa/dist/src/drivers/driver_test.c cvs rdiff -u -r1.4 -r1.5 \ src/external/bsd/wpa/dist/src/eap_server/eap_server_tls_common.c cvs rdiff -u -r1.2 -r1.3 src/external/bsd/wpa/dist/src/radius/radius_das.c cvs rdiff -u -r1.4 -r1.5 src/external/bsd/wpa/dist/src/utils/eloop.c \ src/external/bsd/wpa/dist/src/utils/os.h cvs rdiff -u -r1.1.1.2 -r0 src/external/bsd/wpa/dist/src/utils/eloop_none.c cvs rdiff -u -r1.3 -r1.4 src/external/bsd/wpa/dist/src/utils/radiotap.h cvs rdiff -u -r1.4 -r1.5 src/external/bsd/wpa/dist/wpa_supplicant/wpa_cli.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/wpa/bin/hostapd/Makefile diff -u src/external/bsd/wpa/bin/hostapd/Makefile:1.5 src/external/bsd/wpa/bin/hostapd/Makefile:1.6 --- src/external/bsd/wpa/bin/hostapd/Makefile:1.5 Thu Jan 2 21:15:43 2014 +++ src/external/bsd/wpa/bin/hostapd/Makefile Thu Oct 16 15:29:29 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.5 2014/01/03 02:15:43 christos Exp $ +# $NetBSD: Makefile,v 1.6 2014/10/16 19:29:29 christos Exp $ .include "${.CURDIR}/../Makefile.inc" @@ -65,7 +65,6 @@ SRCS+= \ main.c \ config_file.c \ ctrl_iface.c \ -dump_state.c \ eap_register.c # l2_packet Index: src/external/bsd/wpa/bin/wpa_supplicant/Makefile diff -u src/external/bsd/wpa/bin/wpa_supplicant/Makefile:1.3 src/external/bsd/wpa/bin/wpa_supplicant/Makefile:1.4 --- src/external/bsd/wpa/bin/wpa_supplicant/Makefile:1.3 Thu Jan 2 21:07:31 2014 +++ src/external/bsd/wpa/bin/wpa_supplicant/Makefile Thu Oct 16 15:29:29 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.3 2014/01/03 02:07:31 christos Exp $ +# $NetBSD: Makefile,v 1.4 2014/10/16 19:29:29 christos Exp $ .include "${.CURDIR}/../Makefile.inc" @@ -22,6 +22,7 @@ eap_register.c \ eapol_supp_sm.c \ eloop.c \ events.c \ +ieee802_11_common.c \ l2_packet_freebsd.c \ main.c \ md5.c \ Index: src/external/bsd/wpa/dist/hostapd/hostapd_cli.c diff -u src/external/bsd/wpa/dist/hostapd/hostapd_cli.c:1.5 src/external/bsd/wpa/dist/hostapd/hostapd_cli.c:1.6 --- src/external/bsd/wpa/dist/hostapd/hostapd_cli.c:1.5 Thu Jan 2 21:08:16 2014 +++ src/external/bsd/wpa/dist/hostapd/hostapd_cli.c Thu Oct 16 15:29:29 2014 @@ -1,6 +1,6 @@ /* * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2012, Jouni Malinen <j...@w1.fi> + * Copyright (c) 2004-2014, Jouni Malinen <j...@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -18,7 +18,7 @@ static const char *hostapd_cli_version = "hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2012, Jouni Malinen <j...@w1.fi> and contributors"; +"Copyright (c) 2004-2014, Jouni Malinen <j...@w1.fi> and contributors"; static const char *hostapd_cli_license = @@ -79,6 +79,7 @@ static const char *commands_help = #endif /* CONFIG_WPS_NFC */ " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n" " wps_config <SSID> <auth> <encr> <key> configure AP\n" +" wps_get_status show current WPS status\n" #endif /* CONFIG_WPS */ " get_config show current configuration\n" " help show this usage help\n" @@ -90,7 +91,12 @@ static const char *commands_help = static struct wpa_ctrl *ctrl_conn; static int hostapd_cli_quit = 0; static int hostapd_cli_attached = 0; -static const char *ctrl_iface_dir = "/var/run/hostapd"; + +#ifndef CONFIG_CTRL_IFACE_DIR +#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd" +#endif /* CONFIG_CTRL_IFACE_DIR */ +static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR; + static char *ctrl_ifname = NULL; static const char *pid_file = NULL; static const char *action_file = NULL; @@ -210,8 +216,21 @@ static int hostapd_cli_cmd_relog(struct } +static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc > 0 && os_strcmp(argv[0], "driver") == 0) + return wpa_ctrl_command(ctrl, "STATUS-DRIVER"); + return wpa_ctrl_command(ctrl, "STATUS"); +} + + static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) { + if (argc > 0) { + char buf[100]; + os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]); + return wpa_ctrl_command(ctrl, buf); + } return wpa_ctrl_command(ctrl, "MIB"); } @@ -219,28 +238,19 @@ static int hostapd_cli_cmd_mib(struct wp static int hostapd_cli_exec(const char *program, const char *arg1, const char *arg2) { - char *cmd; + char *arg; size_t len; int res; - int ret = 0; - len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; - cmd = os_malloc(len); - if (cmd == NULL) - return -1; - res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); - if (res < 0 || (size_t) res >= len) { - os_free(cmd); - return -1; - } - cmd[len - 1] = '\0'; -#ifndef _WIN32_WCE - if (system(cmd) < 0) - ret = -1; -#endif /* _WIN32_WCE */ - os_free(cmd); + len = os_strlen(arg1) + os_strlen(arg2) + 2; + arg = os_malloc(len); + if (arg == NULL) + return -1; + os_snprintf(arg, len, "%s %s", arg1, arg2); + res = os_exec(program, arg, 1); + os_free(arg); - return ret; + return res; } @@ -264,12 +274,15 @@ static void hostapd_cli_action_process(c static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; - if (argc != 1) { - printf("Invalid 'sta' command - exactly one argument, STA " + if (argc < 1) { + printf("Invalid 'sta' command - at least one argument, STA " "address, is required.\n"); return -1; } - snprintf(buf, sizeof(buf), "STA %s", argv[0]); + if (argc > 1) + snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]); + else + snprintf(buf, sizeof(buf), "STA %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } @@ -470,6 +483,29 @@ static int hostapd_cli_cmd_wps_nfc_token } return wpa_ctrl_command(ctrl, cmd); } + + +static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char cmd[64]; + int res; + + if (argc != 2) { + printf("Invalid 'nfc_get_handover_sel' command - two arguments " + "are required.\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long NFC_GET_HANDOVER_SEL command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + #endif /* CONFIG_WPS_NFC */ @@ -494,6 +530,13 @@ static int hostapd_cli_cmd_wps_ap_pin(st } +static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "WPS_GET_STATUS"); +} + + static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -565,14 +608,14 @@ static int hostapd_cli_cmd_ess_disassoc( char buf[300]; int res; - if (argc < 2) { - printf("Invalid 'ess_disassoc' command - two arguments (STA " - "addr and URL) are needed\n"); + if (argc < 3) { + printf("Invalid 'ess_disassoc' command - three arguments (STA " + "addr, disassoc timer, and URL) are needed\n"); return -1; } - res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s", - argv[0], argv[1]); + res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s", + argv[0], argv[1], argv[2]); if (res < 0 || res >= (int) sizeof(buf)) return -1; return wpa_ctrl_command(ctrl, buf); @@ -652,6 +695,90 @@ static int hostapd_cli_cmd_license(struc } +static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char buf[200]; + int res; + + if (argc != 1) { + printf("Invalid 'set_qos_map_set' command - " + "one argument (comma delimited QoS map set) " + "is needed\n"); + return -1; + } + + res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]); + if (res < 0 || res >= (int) sizeof(buf)) + return -1; + return wpa_ctrl_command(ctrl, buf); +} + + +static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char buf[50]; + int res; + + if (argc != 1) { + printf("Invalid 'send_qos_map_conf' command - " + "one argument (STA addr) is needed\n"); + return -1; + } + + res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]); + if (res < 0 || res >= (int) sizeof(buf)) + return -1; + return wpa_ctrl_command(ctrl, buf); +} + + +static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[300]; + int res; + + if (argc < 2) { + printf("Invalid 'hs20_wnm_notif' command - two arguments (STA " + "addr and URL) are needed\n"); + return -1; + } + + res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s", + argv[0], argv[1]); + if (res < 0 || res >= (int) sizeof(buf)) + return -1; + return wpa_ctrl_command(ctrl, buf); +} + + +static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[300]; + int res; + + if (argc < 3) { + printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n"); + return -1; + } + + if (argc > 3) + res = os_snprintf(buf, sizeof(buf), + "HS20_DEAUTH_REQ %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + else + res = os_snprintf(buf, sizeof(buf), + "HS20_DEAUTH_REQ %s %s %s", + argv[0], argv[1], argv[2]); + if (res < 0 || res >= (int) sizeof(buf)) + return -1; + return wpa_ctrl_command(ctrl, buf); +} + + static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) { hostapd_cli_quit = 1; @@ -706,8 +833,10 @@ static int hostapd_cli_cmd_interface(str } hostapd_cli_close_connection(); - free(ctrl_ifname); - ctrl_ifname = strdup(argv[0]); + os_free(ctrl_ifname); + ctrl_ifname = os_strdup(argv[0]); + if (ctrl_ifname == NULL) + return -1; if (hostapd_cli_open_connection(ctrl_ifname)) { printf("Connected to interface '%s.\n", ctrl_ifname); @@ -765,6 +894,66 @@ static int hostapd_cli_cmd_get(struct wp } +static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char cmd[256]; + int res; + int i; + char *tmp; + int total; + + if (argc < 2) { + printf("Invalid chan_switch command: needs at least two " + "arguments (count and freq)\n" + "usage: <cs_count> <freq> [sec_channel_offset=] " + "[center_freq1=] [center_freq2=] [bandwidth=] " + "[blocktx] [ht|vht]\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long CHAN_SWITCH command.\n"); + return -1; + } + + total = res; + for (i = 2; i < argc; i++) { + tmp = cmd + total; + res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]); + if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) { + printf("Too long CHAN_SWITCH command.\n"); + return -1; + } + total += res; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256]; + int res; + + if (argc < 2 || argc > 3) { + printf("Invalid vendor command\n" + "usage: <vendor id> <command id> [<hex formatted command argument>]\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1], + argc == 3 ? argv[2] : ""); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long VENDOR command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + struct hostapd_cli_cmd { const char *cmd; int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); @@ -774,6 +963,7 @@ static struct hostapd_cli_cmd hostapd_cl { "ping", hostapd_cli_cmd_ping }, { "mib", hostapd_cli_cmd_mib }, { "relog", hostapd_cli_cmd_relog }, + { "status", hostapd_cli_cmd_status }, { "sta", hostapd_cli_cmd_sta }, { "all_sta", hostapd_cli_cmd_all_sta }, { "new_sta", hostapd_cli_cmd_new_sta }, @@ -791,9 +981,11 @@ static struct hostapd_cli_cmd hostapd_cl { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read }, { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token }, { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token }, + { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel }, #endif /* CONFIG_WPS_NFC */ { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin }, { "wps_config", hostapd_cli_cmd_wps_config }, + { "wps_get_status", hostapd_cli_cmd_wps_get_status }, #endif /* CONFIG_WPS */ { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent }, { "ess_disassoc", hostapd_cli_cmd_ess_disassoc }, @@ -805,6 +997,12 @@ static struct hostapd_cli_cmd hostapd_cl { "quit", hostapd_cli_cmd_quit }, { "set", hostapd_cli_cmd_set }, { "get", hostapd_cli_cmd_get }, + { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set }, + { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf }, + { "chan_switch", hostapd_cli_cmd_chan_switch }, + { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif }, + { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req }, + { "vendor", hostapd_cli_cmd_vendor }, { NULL, NULL } }; Index: src/external/bsd/wpa/dist/src/ap/wpa_auth.c diff -u src/external/bsd/wpa/dist/src/ap/wpa_auth.c:1.6 src/external/bsd/wpa/dist/src/ap/wpa_auth.c:1.7 --- src/external/bsd/wpa/dist/src/ap/wpa_auth.c:1.6 Thu Jan 2 21:08:16 2014 +++ src/external/bsd/wpa/dist/src/ap/wpa_auth.c Thu Oct 16 15:29:29 2014 @@ -1,6 +1,6 @@ /* * IEEE 802.11 RSN / WPA Authenticator - * Copyright (c) 2004-2011, Jouni Malinen <j...@w1.fi> + * Copyright (c) 2004-2013, Jouni Malinen <j...@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -11,6 +11,7 @@ #include "utils/common.h" #include "utils/eloop.h" #include "utils/state_machine.h" +#include "utils/bitfield.h" #include "common/ieee802_11_defs.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" @@ -82,11 +83,14 @@ static inline int wpa_auth_get_eapol(str static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, - const u8 *addr, const u8 *prev_psk) + const u8 *addr, + const u8 *p2p_dev_addr, + const u8 *prev_psk) { if (wpa_auth->cb.get_psk == NULL) return NULL; - return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk); + return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr, + prev_psk); } @@ -207,6 +211,8 @@ static int wpa_use_aes_cmac(struct wpa_s if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) ret = 1; #endif /* CONFIG_IEEE80211W */ + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) + ret = 1; return ret; } @@ -282,8 +288,9 @@ static void wpa_auth_pmksa_free_cb(struc static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - u8 buf[ETH_ALEN + 8 + sizeof(group)]; + u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)]; u8 rkey[32]; + unsigned long ptr; if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) return -1; @@ -295,7 +302,8 @@ static int wpa_group_init_gmk_and_counte */ os_memcpy(buf, wpa_auth->addr, ETH_ALEN); wpa_get_ntp_timestamp(buf + ETH_ALEN); - os_memcpy(buf + ETH_ALEN + 8, &group, sizeof(group)); + ptr = (unsigned long) group; + os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); if (random_get_bytes(rkey, sizeof(rkey)) < 0) return -1; @@ -419,6 +427,17 @@ struct wpa_authenticator * wpa_init(cons wpa_rekey_gtk, wpa_auth, NULL); } +#ifdef CONFIG_P2P + if (WPA_GET_BE32(conf->ip_addr_start)) { + int count = WPA_GET_BE32(conf->ip_addr_end) - + WPA_GET_BE32(conf->ip_addr_start) + 1; + if (count > 1000) + count = 1000; + if (count > 0) + wpa_auth->ip_pool = bitfield_alloc(count); + } +#endif /* CONFIG_P2P */ + return wpa_auth; } @@ -432,6 +451,8 @@ int wpa_init_keys(struct wpa_authenticat wpa_group_sm_step(wpa_auth, group); group->GInit = FALSE; wpa_group_sm_step(wpa_auth, group); + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; return 0; } @@ -459,6 +480,11 @@ void wpa_deinit(struct wpa_authenticator wpa_auth->ft_pmk_cache = NULL; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + bitfield_free(wpa_auth->ip_pool); +#endif /* CONFIG_P2P */ + + os_free(wpa_auth->wpa_ie); group = wpa_auth->group; @@ -506,14 +532,20 @@ int wpa_reconfig(struct wpa_authenticato struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) +wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *p2p_dev_addr) { struct wpa_state_machine *sm; + if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return NULL; + sm = os_zalloc(sizeof(struct wpa_state_machine)); if (sm == NULL) return NULL; os_memcpy(sm->addr, addr, ETH_ALEN); + if (p2p_dev_addr) + os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); sm->wpa_auth = wpa_auth; sm->group = wpa_auth->group; @@ -533,6 +565,8 @@ int wpa_auth_sta_associated(struct wpa_a wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "FT authentication already completed - do not " "start 4-way handshake"); + /* Go to PTKINITDONE state to allow GTK rekeying */ + sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; return 0; } #endif /* CONFIG_IEEE80211R */ @@ -570,12 +604,26 @@ void wpa_auth_sta_no_wpa(struct wpa_stat static void wpa_free_sta_sm(struct wpa_state_machine *sm) { +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr)) { + u32 start; + wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " + "address %u.%u.%u.%u from " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start); + bitfield_clear(sm->wpa_auth->ip_pool, + WPA_GET_BE32(sm->ip_addr) - start); + } +#endif /* CONFIG_P2P */ if (sm->GUpdateStationKeys) { sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; } #ifdef CONFIG_IEEE80211R os_free(sm->assoc_resp_ftie); + wpabuf_free(sm->ft_pending_req_ies); #endif /* CONFIG_IEEE80211R */ os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); @@ -835,6 +883,7 @@ void wpa_receive(struct wpa_authenticato if (sm->pairwise == WPA_CIPHER_CCMP || sm->pairwise == WPA_CIPHER_GCMP) { if (wpa_use_aes_cmac(sm) && + sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN && ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, @@ -958,6 +1007,9 @@ continue_processing: if (kde.rsn_ie) { eapol_key_ie = kde.rsn_ie; eapol_key_ie_len = kde.rsn_ie_len; + } else if (kde.osen) { + eapol_key_ie = kde.osen; + eapol_key_ie_len = kde.osen_len; } else { eapol_key_ie = kde.wpa_ie; eapol_key_ie_len = kde.wpa_ie_len; @@ -987,6 +1039,26 @@ continue_processing: return; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (kde.ip_addr_req && kde.ip_addr_req[0] && + wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { + int idx; + wpa_printf(MSG_DEBUG, "P2P: IP address requested in " + "EAPOL-Key exchange"); + idx = bitfield_get_first_zero(wpa_auth->ip_pool); + if (idx >= 0) { + u32 start = WPA_GET_BE32(wpa_auth->conf. + ip_addr_start); + bitfield_set(wpa_auth->ip_pool, idx); + WPA_PUT_BE32(sm->ip_addr, start + idx); + wpa_printf(MSG_DEBUG, "P2P: Assigned IP " + "address %u.%u.%u.%u to " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + } + } +#endif /* CONFIG_P2P */ break; case PAIRWISE_4: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || @@ -1223,6 +1295,8 @@ void __wpa_send_eapol(struct wpa_authent if (force_version) version = force_version; + else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) + version = WPA_KEY_INFO_TYPE_AKM_DEFINED; else if (wpa_use_aes_cmac(sm)) version = WPA_KEY_INFO_TYPE_AES_128_CMAC; else if (sm->pairwise != WPA_CIPHER_TKIP) @@ -1230,7 +1304,7 @@ void __wpa_send_eapol(struct wpa_authent else version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; + pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " @@ -1245,6 +1319,7 @@ void __wpa_send_eapol(struct wpa_authent key_data_len = kde_len; if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { pad_len = key_data_len % 8; if (pad_len) @@ -1313,8 +1388,10 @@ void __wpa_send_eapol(struct wpa_authent wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", buf, key_data_len); if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf, + if (aes_wrap(sm->PTK.kek, 16, + (key_data_len - 8) / 8, buf, (u8 *) (key + 1))) { os_free(hdr); os_free(buf); @@ -1345,6 +1422,16 @@ void __wpa_send_eapol(struct wpa_authent } wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len, key->key_mic); +#ifdef CONFIG_TESTING_OPTIONS + if (!pairwise && + wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 && + drand48() < + wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "Corrupting group EAPOL-Key Key MIC"); + key->key_mic[0]++; + } +#endif /* CONFIG_TESTING_OPTIONS */ } wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, @@ -1404,7 +1491,7 @@ static int wpa_verify_key_mic(struct wpa os_memset(key->key_mic, 0, 16); if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, data_len, key->key_mic) || - os_memcmp(mic, key->key_mic, 16) != 0) + os_memcmp_const(mic, key->key_mic, 16) != 0) ret = -1; os_memcpy(key->key_mic, mic, 16); return ret; @@ -1596,6 +1683,7 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); wpa_group_ensure_init(sm->wpa_auth, sm->group); + sm->ReAuthenticationRequest = FALSE; /* * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat @@ -1609,12 +1697,11 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " "ANonce."); - wpa_sta_disconnect(sm->wpa_auth, sm->addr); + sm->Disconnect = TRUE; return; } wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, WPA_NONCE_LEN); - sm->ReAuthenticationRequest = FALSE; /* IEEE 802.11i does not clear TimeoutCtr here, but this is more * logical place than INITIALIZE since AUTHENTICATION2 can be * re-entered on ReAuthenticationRequest without going through @@ -1666,7 +1753,7 @@ SM_STATE(WPA_PTK, INITPSK) { const u8 *psk; SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); - psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); + psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL); if (psk) { os_memcpy(sm->PMK, psk, PMK_LEN); #ifdef CONFIG_IEEE80211R @@ -1701,7 +1788,8 @@ SM_STATE(WPA_PTK, PTKSTART) * one possible PSK for this STA. */ if (sm->wpa == WPA_VERSION_WPA2 && - wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) { + wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && + sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) { pmkid = buf; pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; @@ -1729,7 +1817,7 @@ SM_STATE(WPA_PTK, PTKSTART) static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk) { - size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64; + size_t ptk_len = wpa_cipher_key_len(sm->pairwise) + 32; #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); @@ -1759,7 +1847,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) * the packet */ for (;;) { if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); + pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, + sm->p2p_dev_addr, pmk); if (pmk == NULL) break; } else @@ -1789,8 +1878,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) * Verify that PMKR1Name from EAPOL-Key message 2/4 matches * with the value we derived. */ - if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name, - WPA_PMK_NAME_LEN) != 0) { + if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "PMKR1Name mismatch in FT 4-way " "handshake"); @@ -1833,7 +1922,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) static int ieee80211w_kde_len(struct wpa_state_machine *sm) { if (sm->mgmt_frame_prot) { - return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde); + size_t len; + len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; } return 0; @@ -1844,6 +1935,8 @@ static u8 * ieee80211w_kde_add(struct wp { struct wpa_igtk_kde igtk; struct wpa_group *gsm = sm->group; + u8 rsc[WPA_KEY_RSC_LEN]; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); if (!sm->mgmt_frame_prot) return pos; @@ -1851,19 +1944,22 @@ static u8 * ieee80211w_kde_add(struct wp igtk.keyid[0] = gsm->GN_igtk; igtk.keyid[1] = 0; if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0) + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0) os_memset(igtk.pn, 0, sizeof(igtk.pn)); - os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); + else + os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); + os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); if (sm->wpa_auth->conf.disable_gtk) { /* * Provide unique random IGTK to each STA to prevent use of * IGTK in the BSS. */ - if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0) + if (random_get_bytes(igtk.igtk, len) < 0) return pos; } pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, - (const u8 *) &igtk, sizeof(igtk), NULL, 0); + (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, + NULL, 0); return pos; } @@ -1968,6 +2064,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) kde_len += 300; /* FTIE + 2 * TIE */ } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) + kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; +#endif /* CONFIG_P2P */ kde = os_malloc(kde_len); if (kde == NULL) return; @@ -2029,6 +2129,16 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos += 4; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) { + u8 addr[3 * 4]; + os_memcpy(addr, sm->ip_addr, 4); + os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); + os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); + pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, + addr, sizeof(addr), NULL, 0); + } +#endif /* CONFIG_P2P */ wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | @@ -2146,7 +2256,8 @@ SM_STEP(WPA_PTK) } break; case WPA_PTK_INITPSK: - if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL)) + if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, + NULL)) SM_ENTER(WPA_PTK, PTKSTART); else { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, @@ -2354,15 +2465,16 @@ static int wpa_gtk_update(struct wpa_aut #ifdef CONFIG_IEEE80211W if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + size_t len; + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", wpa_auth->addr, group->GNonce, - group->IGTK[group->GN_igtk - 4], - WPA_IGTK_LEN) < 0) + group->IGTK[group->GN_igtk - 4], len) < 0) ret = -1; wpa_hexdump_key(MSG_DEBUG, "IGTK", - group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); + group->IGTK[group->GN_igtk - 4], len); } #endif /* CONFIG_IEEE80211W */ @@ -2429,7 +2541,7 @@ static int wpa_group_update_sta(struct w /* update GTK when exiting WNM-Sleep Mode */ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) { - if (sm->is_wnmsleep) + if (sm == NULL || sm->is_wnmsleep) return; wpa_group_update_sta(sm, NULL); @@ -2438,7 +2550,8 @@ void wpa_wnmsleep_rekey_gtk(struct wpa_s void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) { - sm->is_wnmsleep = !!flag; + if (sm) + sm->is_wnmsleep = !!flag; } @@ -2478,26 +2591,27 @@ int wpa_wnmsleep_igtk_subelem(struct wpa { struct wpa_group *gsm = sm->group; u8 *start = pos; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); /* * IGTK subelement: * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] */ *pos++ = WNM_SLEEP_SUBELEM_IGTK; - *pos++ = 2 + 6 + WPA_IGTK_LEN; + *pos++ = 2 + 6 + len; WPA_PUT_LE16(pos, gsm->GN_igtk); pos += 2; if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) return 0; pos += 6; - os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); - pos += WPA_IGTK_LEN; + os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); + pos += len; wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", gsm->GN_igtk); wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", - gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); + gsm->IGTK[gsm->GN_igtk - 4], len); return pos - start; } @@ -2552,18 +2666,48 @@ static int wpa_group_config_group_keys(s ret = -1; #ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && - wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK, - broadcast_ether_addr, group->GN_igtk, - group->IGTK[group->GN_igtk - 4], - WPA_IGTK_LEN) < 0) - ret = -1; + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + enum wpa_alg alg; + size_t len; + + alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + + if (ret == 0 && + wpa_auth_set_key(wpa_auth, group->vlan_id, alg, + broadcast_ether_addr, group->GN_igtk, + group->IGTK[group->GN_igtk - 4], len) < 0) + ret = -1; + } #endif /* CONFIG_IEEE80211W */ return ret; } +static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) +{ + if (sm->group == ctx) { + wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR + " for discconnection due to fatal failure", + MAC2STR(sm->addr)); + sm->Disconnect = TRUE; + } + + return 0; +} + + +static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; + wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); +} + + static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { @@ -2572,8 +2716,10 @@ static int wpa_group_setkeysdone(struct group->changed = TRUE; group->wpa_group_state = WPA_GROUP_SETKEYSDONE; - if (wpa_group_config_group_keys(wpa_auth, group) < 0) + if (wpa_group_config_group_keys(wpa_auth, group) < 0) { + wpa_group_fatal_failure(wpa_auth, group); return -1; + } return 0; } @@ -2584,6 +2730,8 @@ static void wpa_group_sm_step(struct wpa { if (group->GInit) { wpa_group_gtk_init(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) { + /* Do not allow group operations */ } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && group->GTKAuthenticator) { wpa_group_setkeysdone(wpa_auth, group); @@ -2932,6 +3080,22 @@ int wpa_auth_pmksa_add_preauth(struct wp } +void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr) +{ + struct rsn_pmksa_cache_entry *pmksa; + + if (wpa_auth == NULL || wpa_auth->pmksa == NULL) + return; + pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); + if (pmksa) { + wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for " + MACSTR " based on request", MAC2STR(sta_addr)); + pmksa_cache_free_entry(wpa_auth->pmksa, pmksa); + } +} + + static struct wpa_group * wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) { @@ -2976,6 +3140,9 @@ int wpa_auth_sta_set_vlan(struct wpa_sta if (sm->group == group) return 0; + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; + wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); @@ -3020,3 +3187,22 @@ int wpa_auth_uses_sae(struct wpa_state_m return 0; return wpa_key_mgmt_sae(sm->wpa_key_mgmt); } + + +int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; +} + + +#ifdef CONFIG_P2P +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) +{ + if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) + return -1; + os_memcpy(addr, sm->ip_addr, 4); + return 0; +} +#endif /* CONFIG_P2P */ Index: src/external/bsd/wpa/dist/src/drivers/driver_bsd.c diff -u src/external/bsd/wpa/dist/src/drivers/driver_bsd.c:1.9 src/external/bsd/wpa/dist/src/drivers/driver_bsd.c:1.10 --- src/external/bsd/wpa/dist/src/drivers/driver_bsd.c:1.9 Sun Jun 29 19:10:48 2014 +++ src/external/bsd/wpa/dist/src/drivers/driver_bsd.c Thu Oct 16 15:29:30 2014 @@ -62,6 +62,9 @@ struct bsd_driver_data { int prev_roaming; /* roaming state to restore on deinit */ int prev_privacy; /* privacy state to restore on deinit */ int prev_wpa; /* wpa state to restore on deinit */ + enum ieee80211_opmode opmode; /* operation mode */ + char *event_buf; + size_t event_buf_len; }; /* Generic functions for hostapd and wpa_supplicant */ @@ -266,10 +269,15 @@ bsd_ctrl_iface(void *priv, int enable) return -1; } - if (enable) + if (enable) { + if (ifr.ifr_flags & IFF_UP) + return 0; ifr.ifr_flags |= IFF_UP; - else + } else { + if (!(ifr.ifr_flags & IFF_UP)) + return 0; ifr.ifr_flags &= ~IFF_UP; + } if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) { perror("ioctl[SIOCSIFFLAGS]"); @@ -285,6 +293,9 @@ bsd_set_key(const char *ifname, void *pr size_t seq_len, const u8 *key, size_t key_len) { struct ieee80211req_key wk; +#ifdef IEEE80211_KEY_NOREPLAY + struct bsd_driver_data *drv = priv; +#endif /* IEEE80211_KEY_NOREPLAY */ wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, @@ -339,6 +350,16 @@ bsd_set_key(const char *ifname, void *pr } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; +#ifndef HOSTAPD +#ifdef IEEE80211_KEY_NOREPLAY + /* + * Ignore replay failures in IBSS and AHDEMO mode. + */ + if (drv->opmode == IEEE80211_M_IBSS || + drv->opmode == IEEE80211_M_AHDEMO) + wk.ik_flags |= IEEE80211_KEY_NOREPLAY; +#endif /* IEEE80211_KEY_NOREPLAY */ +#endif /* HOSTAPD */ wk.ik_keylen = key_len; if (seq) { #ifdef WORDS_BIGENDIAN @@ -474,26 +495,6 @@ bsd_set_ieee8021x(void *priv, struct wpa return bsd_ctrl_iface(priv, 1); } -static int -bsd_set_sta_authorized(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - int authorized = -1; - - /* For now, only support setting Authorized flag */ - if (flags_or & WPA_STA_AUTHORIZED) - authorized = 1; - if (!(flags_and & WPA_STA_AUTHORIZED)) - authorized = 0; - - if (authorized < 0) - return 0; - - return bsd_send_mlme_param(priv, authorized ? - IEEE80211_MLME_AUTHORIZE : - IEEE80211_MLME_UNAUTHORIZE, 0, addr); -} - static void bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN]) { @@ -586,7 +587,7 @@ bsd_set_opt_ie(void *priv, const u8 *ie, return 0; } -static int +static size_t rtbuf_len(void) { size_t len; @@ -726,37 +727,26 @@ static void bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) { struct bsd_driver_data *drv = ctx; - char *buf; struct if_announcemsghdr *ifan; struct rt_msghdr *rtm; struct ieee80211_michael_event *mic; struct ieee80211_join_event *join; struct ieee80211_leave_event *leave; - int n, len; + int n; union wpa_event_data data; - len = rtbuf_len(); - - buf = os_malloc(len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__); - return; - } - - n = read(sock, buf, len); + n = read(sock, drv->event_buf, drv->event_buf_len); if (n < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_ERROR, "%s read() failed: %s\n", __func__, strerror(errno)); - os_free(buf); return; } - rtm = (struct rt_msghdr *) buf; + rtm = (struct rt_msghdr *) drv->event_buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", rtm->rtm_version); - os_free(buf); return; } ifan = (struct if_announcemsghdr *) rtm; @@ -797,7 +787,6 @@ bsd_wireless_event_receive(int sock, voi } break; } - os_free(buf); } static void @@ -814,7 +803,15 @@ bsd_init(struct hostapd_data *hapd, stru drv = os_zalloc(sizeof(struct bsd_driver_data)); if (drv == NULL) { - printf("Could not allocate memory for bsd driver data\n"); + wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data"); + return NULL; + } + + drv->event_buf_len = rtbuf_len(); + + drv->event_buf = os_malloc(drv->event_buf_len); + if (drv->event_buf == NULL) { + wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); goto bad; } @@ -858,6 +855,7 @@ bad: l2_packet_deinit(drv->sock_xmit); if (drv->sock >= 0) close(drv->sock); + os_free(drv->event_buf); os_free(drv); } return NULL; @@ -878,9 +876,37 @@ bsd_deinit(void *priv) close(drv->sock); if (drv->sock_xmit != NULL) l2_packet_deinit(drv->sock_xmit); + os_free(drv->event_buf); os_free(drv); } + +static int +bsd_commit(void *priv) +{ + return bsd_ctrl_iface(priv, 1); +} + + +static int +bsd_set_sta_authorized(void *priv, const u8 *addr, + int total_flags, int flags_or, int flags_and) +{ + int authorized = -1; + + /* For now, only support setting Authorized flag */ + if (flags_or & WPA_STA_AUTHORIZED) + authorized = 1; + if (!(flags_and & WPA_STA_AUTHORIZED)) + authorized = 0; + + if (authorized < 0) + return 0; + + return bsd_send_mlme_param(priv, authorized ? + IEEE80211_MLME_AUTHORIZE : + IEEE80211_MLME_UNAUTHORIZE, 0, addr); +} #else /* HOSTAPD */ static int @@ -1058,9 +1084,9 @@ wpa_driver_bsd_associate(void *priv, str if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) return -1; - privacy = !(params->pairwise_suite == CIPHER_NONE && - params->group_suite == CIPHER_NONE && - params->key_mgmt_suite == KEY_MGMT_NONE && + privacy = !(params->pairwise_suite == WPA_CIPHER_NONE && + params->group_suite == WPA_CIPHER_NONE && + params->key_mgmt_suite == WPA_KEY_MGMT_NONE && params->wpa_ie_len == 0); wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); @@ -1156,7 +1182,6 @@ static void wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) { struct bsd_driver_data *drv = sock_ctx; - char *buf; struct if_announcemsghdr *ifan; struct if_msghdr *ifm; struct rt_msghdr *rtm; @@ -1164,30 +1189,20 @@ wpa_driver_bsd_event_receive(int sock, v struct ieee80211_michael_event *mic; struct ieee80211_leave_event *leave; struct ieee80211_join_event *join; - int n, len; - - len = rtbuf_len(); - - buf = os_malloc(len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__); - return; - } + int n; - n = read(sock, buf, len); + n = read(sock, drv->event_buf, drv->event_buf_len); if (n < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_ERROR, "%s read() failed: %s\n", __func__, strerror(errno)); - os_free(buf); return; } - rtm = (struct rt_msghdr *) buf; + rtm = (struct rt_msghdr *) drv->event_buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", rtm->rtm_version); - os_free(buf); return; } os_memset(&event, 0, sizeof(event)); @@ -1206,7 +1221,6 @@ wpa_driver_bsd_event_receive(int sock, v event.interface_status.ievent = EVENT_INTERFACE_ADDED; break; #else - os_free(buf); return; #endif } @@ -1331,7 +1345,6 @@ wpa_driver_bsd_event_receive(int sock, v wpa_printf(MSG_DEBUG, "RTM_???: %d", rtm->rtm_type); break; } - os_free(buf); } static void @@ -1356,6 +1369,11 @@ wpa_driver_bsd_add_scan_entry(struct wpa result->caps = sr->isr_capinfo; result->level = sr->isr_rssi; result->noise = sr->isr_noise; + /* + * the rssi value reported by the kernel is in 0.5dB steps relative to + * the reported noise floor. see ieee80211_node.h for details. + */ + result->level = sr->isr_rssi / 2 + sr->isr_noise; pos = (u8 *)(result + 1); @@ -1497,6 +1515,33 @@ static int wpa_driver_bsd_capa(struct bs return 0; } +static enum ieee80211_opmode +get80211opmode(struct bsd_driver_data *drv) +{ + struct ifmediareq ifmr; + + (void) memset(&ifmr, 0, sizeof(ifmr)); + (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); + + if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { + if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { + if (ifmr.ifm_current & IFM_FLAG0) + return IEEE80211_M_AHDEMO; + else + return IEEE80211_M_IBSS; + } + if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) + return IEEE80211_M_HOSTAP; + if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) + return IEEE80211_M_MONITOR; +#ifdef IEEE80211_M_MBSS + if (ifmr.ifm_current & IFM_IEEE80211_MBSS) + return IEEE80211_M_MBSS; +#endif /* IEEE80211_M_MBSS */ + } + return IEEE80211_M_STA; +} + static void * wpa_driver_bsd_init(void *ctx, const char *ifname) { @@ -1507,6 +1552,15 @@ wpa_driver_bsd_init(void *ctx, const cha drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; + + drv->event_buf_len = rtbuf_len(); + + drv->event_buf = os_malloc(drv->event_buf_len); + if (drv->event_buf == NULL) { + wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); + goto fail1; + } + /* * NB: We require the interface name be mappable to an index. * This implies we do not support having wpa_supplicant @@ -1522,6 +1576,12 @@ wpa_driver_bsd_init(void *ctx, const cha drv->sock = socket(PF_INET, SOCK_DGRAM, 0); if (drv->sock < 0) goto fail1; + + os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + /* Down interface during setup. */ + if (bsd_ctrl_iface(drv, 0) < 0) + goto fail; + drv->route = socket(PF_ROUTE, SOCK_RAW, 0); if (drv->route < 0) goto fail; @@ -1529,11 +1589,6 @@ wpa_driver_bsd_init(void *ctx, const cha wpa_driver_bsd_event_receive, ctx, drv); drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - /* Down interface during setup. */ - if (bsd_ctrl_iface(drv, 0) < 0) - goto fail; if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", @@ -1554,10 +1609,13 @@ wpa_driver_bsd_init(void *ctx, const cha if (wpa_driver_bsd_capa(drv)) goto fail; + drv->opmode = get80211opmode(drv); + return drv; fail: close(drv->sock); fail1: + os_free(drv->event_buf); os_free(drv); return NULL; #undef GETPARAM @@ -1583,6 +1641,7 @@ wpa_driver_bsd_deinit(void *priv) l2_packet_deinit(drv->sock_xmit); (void) close(drv->route); /* ioctl socket */ (void) close(drv->sock); /* event socket */ + os_free(drv->event_buf); os_free(drv); } @@ -1609,6 +1668,8 @@ const struct wpa_driver_ops wpa_driver_b .read_sta_data = bsd_read_sta_driver_data, .sta_disassoc = bsd_sta_disassoc, .sta_deauth = bsd_sta_deauth, + .sta_set_flags = bsd_set_sta_authorized, + .commit = bsd_commit, #else /* HOSTAPD */ .init = wpa_driver_bsd_init, .deinit = wpa_driver_bsd_deinit, @@ -1627,6 +1688,5 @@ const struct wpa_driver_ops wpa_driver_b .hapd_set_ssid = bsd_set_ssid, .hapd_get_ssid = bsd_get_ssid, .hapd_send_eapol = bsd_send_eapol, - .sta_set_flags = bsd_set_sta_authorized, .set_generic_elem = bsd_set_opt_ie, }; Index: src/external/bsd/wpa/dist/src/drivers/driver_test.c diff -u src/external/bsd/wpa/dist/src/drivers/driver_test.c:1.4 src/external/bsd/wpa/dist/src/drivers/driver_test.c:1.5 --- src/external/bsd/wpa/dist/src/drivers/driver_test.c:1.4 Thu Jan 2 21:08:17 2014 +++ src/external/bsd/wpa/dist/src/drivers/driver_test.c Thu Oct 16 15:29:30 2014 @@ -28,7 +28,6 @@ #include "common/ieee802_11_defs.h" #include "crypto/sha1.h" #include "l2_packet/l2_packet.h" -#include "p2p/p2p.h" #include "wps/wps.h" #include "driver.h" @@ -102,20 +101,6 @@ struct wpa_driver_test_data { unsigned int remain_on_channel_duration; int current_freq; - - struct p2p_data *p2p; - unsigned int off_channel_freq; - struct wpabuf *pending_action_tx; - u8 pending_action_src[ETH_ALEN]; - u8 pending_action_dst[ETH_ALEN]; - u8 pending_action_bssid[ETH_ALEN]; - unsigned int pending_action_freq; - unsigned int pending_action_no_cck; - unsigned int pending_listen_freq; - unsigned int pending_listen_duration; - int pending_p2p_scan; - struct sockaddr *probe_from; - socklen_t probe_from_len; }; @@ -125,7 +110,6 @@ static int wpa_driver_test_attach(struct static void wpa_driver_test_close_test_socket( struct wpa_driver_test_data *drv); static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx); -static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv); static void test_driver_free_bss(struct test_driver_bss *bss) @@ -479,34 +463,6 @@ static int wpa_driver_test_send_mlme(voi event.tx_status.ack = ret >= 0; wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event); -#ifdef CONFIG_P2P - if (drv->p2p && - WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { - if (drv->pending_action_tx == NULL) { - wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - " - "no pending operation"); - return ret; - } - - if (os_memcmp(hdr->addr1, drv->pending_action_dst, ETH_ALEN) != - 0) { - wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - " - "unknown destination address"); - return ret; - } - - wpabuf_free(drv->pending_action_tx); - drv->pending_action_tx = NULL; - - p2p_send_action_cb(drv->p2p, drv->pending_action_freq, - drv->pending_action_dst, - drv->pending_action_src, - drv->pending_action_bssid, - ret >= 0); - } -#endif /* CONFIG_P2P */ - return ret; } @@ -553,10 +509,6 @@ static void test_driver_scan(struct wpa_ event.rx_probe_req.ie = ie; event.rx_probe_req.ie_len = ielen; wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event); -#ifdef CONFIG_P2P - if (drv->p2p) - p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen); -#endif /* CONFIG_P2P */ } dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) { @@ -1059,7 +1011,7 @@ static int test_driver_if_add(void *priv const char *ifname, const u8 *addr, void *bss_ctx, void **drv_priv, char *force_ifname, u8 *if_addr, - const char *bridge) + const char *bridge, int use_existing) { struct test_driver_bss *dbss = priv; struct wpa_driver_test_data *drv = dbss->drv; @@ -1313,24 +1265,7 @@ static void wpa_driver_test_poll(void *e static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx) { - struct wpa_driver_test_data *drv = eloop_ctx; wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - if (drv->pending_p2p_scan && drv->p2p) { -#ifdef CONFIG_P2P - size_t i; - for (i = 0; i < drv->num_scanres; i++) { - struct wpa_scan_res *bss = drv->scanres[i]; - if (p2p_scan_res_handler(drv->p2p, bss->bssid, - bss->freq, bss->age, - bss->level, - (const u8 *) (bss + 1), - bss->ie_len) > 0) - return; - } - p2p_scan_res_handled(drv->p2p); -#endif /* CONFIG_P2P */ - return; - } wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); } @@ -1543,7 +1478,7 @@ static int wpa_driver_test_associate( struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", - __func__, priv, params->freq, params->pairwise_suite, + __func__, priv, params->freq.freq, params->pairwise_suite, params->group_suite, params->key_mgmt_suite, params->auth_alg, params->mode); wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP); @@ -1594,7 +1529,8 @@ static int wpa_driver_test_associate( #endif /* DRIVER_TEST_UNIX */ if (params->mode == IEEE80211_MODE_AP) { - os_memcpy(dbss->ssid, params->ssid, params->ssid_len); + if (params->ssid) + os_memcpy(dbss->ssid, params->ssid, params->ssid_len); dbss->ssid_len = params->ssid_len; os_memcpy(dbss->bssid, drv->own_addr, ETH_ALEN); if (params->wpa_ie && params->wpa_ie_len) { @@ -1615,8 +1551,9 @@ static int wpa_driver_test_associate( MAC2STR(drv->own_addr)); if (ret >= 0 && ret < end - pos) pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, params->ssid, - params->ssid_len); + if (params->ssid) + pos += wpa_snprintf_hex(pos, end - pos, params->ssid, + params->ssid_len); ret = os_snprintf(pos, end - pos, " "); if (ret >= 0 && ret < end - pos) pos += ret; @@ -1640,12 +1577,15 @@ static int wpa_driver_test_associate( return -1; } - os_memcpy(dbss->ssid, params->ssid, params->ssid_len); + if (params->ssid) + os_memcpy(dbss->ssid, params->ssid, params->ssid_len); dbss->ssid_len = params->ssid_len; } else { drv->associated = 1; if (params->mode == IEEE80211_MODE_IBSS) { - os_memcpy(dbss->ssid, params->ssid, params->ssid_len); + if (params->ssid) + os_memcpy(dbss->ssid, params->ssid, + params->ssid_len); dbss->ssid_len = params->ssid_len; if (params->bssid) os_memcpy(dbss->bssid, params->bssid, @@ -1948,30 +1888,8 @@ static void wpa_driver_test_mlme(struct data_len - (mgmt->u.probe_req.variable - data); wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event); -#ifdef CONFIG_P2P - if (drv->p2p) - p2p_probe_req_rx(drv->p2p, mgmt->sa, - mgmt->da, mgmt->bssid, - event.rx_probe_req.ie, - event.rx_probe_req.ie_len); -#endif /* CONFIG_P2P */ } } - -#ifdef CONFIG_P2P - if (drv->p2p && - WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { - size_t hdr_len; - hdr_len = (const u8 *) - &mgmt->u.action.u.vs_public_action.action - data; - p2p_rx_action(drv->p2p, mgmt->da, mgmt->sa, mgmt->bssid, - mgmt->u.action.category, - &mgmt->u.action.u.vs_public_action.action, - data_len - hdr_len, freq); - } -#endif /* CONFIG_P2P */ - } @@ -1987,31 +1905,8 @@ static void wpa_driver_test_scan_cmd(str bss = dl_list_first(&drv->bss, struct test_driver_bss, list); /* data: optional [ STA-addr | ' ' | IEs(hex) ] */ -#ifdef CONFIG_P2P - if (drv->probe_req_report && drv->p2p && data_len) { - const char *d = (const char *) data; - u8 sa[ETH_ALEN]; - u8 ie[512]; - size_t ielen; - if (hwaddr_aton(d, sa)) - return; - d += 18; - while (*d == ' ') - d++; - ielen = os_strlen(d) / 2; - if (ielen > sizeof(ie)) - ielen = sizeof(ie); - if (hexstr2bin(d, ie, ielen) < 0) - ielen = 0; - drv->probe_from = from; - drv->probe_from_len = fromlen; - p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen); - drv->probe_from = NULL; - } -#endif /* CONFIG_P2P */ - - if (!drv->ibss) + if (bss == NULL || !drv->ibss) return; pos = buf; @@ -2166,12 +2061,6 @@ static void wpa_driver_test_deinit(void struct test_client_socket *cli, *prev; int i; -#ifdef CONFIG_P2P - if (drv->p2p) - p2p_deinit(drv->p2p); - wpabuf_free(drv->pending_action_tx); -#endif /* CONFIG_P2P */ - cli = drv->cli; while (cli) { prev = cli; @@ -2368,13 +2257,6 @@ static int wpa_driver_test_set_param(voi drv->use_associnfo = 1; } - if (os_strstr(param, "p2p_mgmt=1")) { - wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P " - "management"); - if (wpa_driver_test_init_p2p(drv) < 0) - return -1; - } - return 0; } @@ -2464,8 +2346,6 @@ static int wpa_driver_test_send_eapol(vo static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa) { - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; os_memset(capa, 0, sizeof(*capa)); capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | @@ -2481,8 +2361,6 @@ static int wpa_driver_test_get_capa(void capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | WPA_DRIVER_AUTH_LEAP; - if (drv->p2p) - capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT; capa->flags |= WPA_DRIVER_FLAGS_AP; capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE; @@ -2690,33 +2568,6 @@ static int wpa_driver_test_send_action(v } -#ifdef CONFIG_P2P -static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - - if (drv->pending_action_tx == NULL) - return; - - if (drv->off_channel_freq != drv->pending_action_freq) { - wpa_printf(MSG_DEBUG, "P2P: Pending Action frame TX " - "waiting for another freq=%u", - drv->pending_action_freq); - return; - } - wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to " - MACSTR, MAC2STR(drv->pending_action_dst)); - wpa_driver_test_send_action(drv, drv->pending_action_freq, 0, - drv->pending_action_dst, - drv->pending_action_src, - drv->pending_action_bssid, - wpabuf_head(drv->pending_action_tx), - wpabuf_len(drv->pending_action_tx), - drv->pending_action_no_cck); -} -#endif /* CONFIG_P2P */ - - static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_driver_test_data *drv = eloop_ctx; @@ -2728,9 +2579,6 @@ static void test_remain_on_channel_timeo data.remain_on_channel.freq = drv->remain_on_channel_freq; data.remain_on_channel.duration = drv->remain_on_channel_duration; - if (drv->p2p) - drv->off_channel_freq = 0; - drv->remain_on_channel_freq = 0; wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data); @@ -2764,18 +2612,6 @@ static int wpa_driver_test_remain_on_cha data.remain_on_channel.duration = duration; wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data); -#ifdef CONFIG_P2P - if (drv->p2p) { - drv->off_channel_freq = drv->remain_on_channel_freq; - test_send_action_cb(drv, NULL); - if (drv->off_channel_freq == drv->pending_listen_freq) { - p2p_listen_cb(drv->p2p, drv->pending_listen_freq, - drv->pending_listen_duration); - drv->pending_listen_freq = 0; - } - } -#endif /* CONFIG_P2P */ - return 0; } @@ -2803,464 +2639,6 @@ static int wpa_driver_test_probe_req_rep } -#ifdef CONFIG_P2P - -static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); - if (!drv->p2p) - return -1; - return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL, 0); -} - - -static int wpa_driver_test_p2p_stop_find(void *priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->p2p) - return -1; - p2p_stop_find(drv->p2p); - return 0; -} - - -static int wpa_driver_test_p2p_listen(void *priv, unsigned int timeout) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); - if (!drv->p2p) - return -1; - return p2p_listen(drv->p2p, timeout); -} - - -static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr, - int wps_method, int go_intent, - const u8 *own_interface_addr, - unsigned int force_freq, - int persistent_group) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR " wps_method=%d " - "go_intent=%d " - "own_interface_addr=" MACSTR " force_freq=%u " - "persistent_group=%d)", - __func__, MAC2STR(peer_addr), wps_method, go_intent, - MAC2STR(own_interface_addr), force_freq, persistent_group); - if (!drv->p2p) - return -1; - return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent, - own_interface_addr, force_freq, persistent_group, - NULL, 0, 0, 0); -} - - -static int wpa_driver_test_wps_success_cb(void *priv, const u8 *peer_addr) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR ")", - __func__, MAC2STR(peer_addr)); - if (!drv->p2p) - return -1; - p2p_wps_success_cb(drv->p2p, peer_addr); - return 0; -} - - -static int wpa_driver_test_p2p_group_formation_failed(void *priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->p2p) - return -1; - p2p_group_formation_failed(drv->p2p); - return 0; -} - - -static int wpa_driver_test_p2p_set_params(void *priv, - const struct p2p_params *params) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->p2p) - return -1; - if (p2p_set_dev_name(drv->p2p, params->dev_name) < 0 || - p2p_set_pri_dev_type(drv->p2p, params->pri_dev_type) < 0 || - p2p_set_sec_dev_types(drv->p2p, params->sec_dev_type, - params->num_sec_dev_types) < 0) - return -1; - return 0; -} - - -static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, - unsigned int num_req_dev_types, - const u8 *req_dev_types, const u8 *dev_id, u16 pw_id) -{ - struct wpa_driver_test_data *drv = ctx; - struct wpa_driver_scan_params params; - int ret; - struct wpabuf *wps_ie, *ies; - int social_channels[] = { 2412, 2437, 2462, 0, 0 }; - size_t ielen; - - wpa_printf(MSG_DEBUG, "%s(type=%d freq=%d)", - __func__, type, freq); - - os_memset(¶ms, 0, sizeof(params)); - - /* P2P Wildcard SSID */ - params.num_ssids = 1; - params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID; - params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; - -#if 0 /* TODO: WPS IE */ - wpa_s->wps->dev.p2p = 1; - wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev, - wpa_s->wps->uuid, WPS_REQ_ENROLLEE); -#else - wps_ie = wpabuf_alloc(1); -#endif - if (wps_ie == NULL) - return -1; - - ielen = p2p_scan_ie_buf_len(drv->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { - wpabuf_free(wps_ie); - return -1; - } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); - - p2p_scan_ie(drv->p2p, ies, dev_id); - - params.extra_ies = wpabuf_head(ies); - params.extra_ies_len = wpabuf_len(ies); - - switch (type) { - case P2P_SCAN_SOCIAL: - params.freqs = social_channels; - break; - case P2P_SCAN_FULL: - break; - case P2P_SCAN_SOCIAL_PLUS_ONE: - social_channels[3] = freq; - params.freqs = social_channels; - break; - } - - drv->pending_p2p_scan = 1; - ret = wpa_driver_test_scan(drv, ¶ms); - - wpabuf_free(ies); - - return ret; -} - - -static int test_send_action(void *ctx, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time) -{ - struct wpa_driver_test_data *drv = ctx; - - wpa_printf(MSG_DEBUG, "%s(freq=%u dst=" MACSTR " src=" MACSTR - " bssid=" MACSTR " len=%d", - __func__, freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), - (int) len); - if (freq <= 0) { - wpa_printf(MSG_WARNING, "P2P: No frequency specified for " - "action frame TX"); - return -1; - } - - if (drv->pending_action_tx) { - wpa_printf(MSG_DEBUG, "P2P: Dropped pending Action frame TX " - "to " MACSTR, MAC2STR(drv->pending_action_dst)); - wpabuf_free(drv->pending_action_tx); - } - drv->pending_action_tx = wpabuf_alloc(len); - if (drv->pending_action_tx == NULL) - return -1; - wpabuf_put_data(drv->pending_action_tx, buf, len); - os_memcpy(drv->pending_action_src, src, ETH_ALEN); - os_memcpy(drv->pending_action_dst, dst, ETH_ALEN); - os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN); - drv->pending_action_freq = freq; - drv->pending_action_no_cck = 1; - - if (drv->off_channel_freq == freq) { - /* Already on requested channel; send immediately */ - /* TODO: Would there ever be need to extend the current - * duration on the channel? */ - eloop_cancel_timeout(test_send_action_cb, drv, NULL); - eloop_register_timeout(0, 0, test_send_action_cb, drv, NULL); - return 0; - } - - wpa_printf(MSG_DEBUG, "P2P: Schedule Action frame to be transmitted " - "once the driver gets to the requested channel"); - if (wpa_driver_test_remain_on_channel(drv, freq, wait_time) < 0) { - wpa_printf(MSG_DEBUG, "P2P: Failed to request driver " - "to remain on channel (%u MHz) for Action " - "Frame TX", freq); - return -1; - } - - return 0; -} - - -static void test_send_action_done(void *ctx) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static void test_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) -{ - struct wpa_driver_test_data *drv = ctx; - union wpa_event_data event; - wpa_printf(MSG_DEBUG, "%s", __func__); - os_memset(&event, 0, sizeof(event)); - event.p2p_go_neg_completed.res = res; - wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_COMPLETED, &event); -} - - -static void test_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id) -{ - struct wpa_driver_test_data *drv = ctx; - union wpa_event_data event; - wpa_printf(MSG_DEBUG, "%s(src=" MACSTR ")", __func__, MAC2STR(src)); - os_memset(&event, 0, sizeof(event)); - event.p2p_go_neg_req_rx.src = src; - event.p2p_go_neg_req_rx.dev_passwd_id = dev_passwd_id; - wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_REQ_RX, &event); -} - - -static void test_dev_found(void *ctx, const u8 *addr, - const struct p2p_peer_info *info, int new_device) -{ - struct wpa_driver_test_data *drv = ctx; - union wpa_event_data event; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - wpa_printf(MSG_DEBUG, "%s(" MACSTR " p2p_dev_addr=" MACSTR - " pri_dev_type=%s name='%s' config_methods=0x%x " - "dev_capab=0x%x group_capab=0x%x)", - __func__, MAC2STR(addr), MAC2STR(info->p2p_device_addr), - wps_dev_type_bin2str(info->pri_dev_type, devtype, - sizeof(devtype)), - info->device_name, info->config_methods, info->dev_capab, - info->group_capab); - - os_memset(&event, 0, sizeof(event)); - event.p2p_dev_found.addr = addr; - event.p2p_dev_found.dev_addr = info->p2p_device_addr; - event.p2p_dev_found.pri_dev_type = info->pri_dev_type; - event.p2p_dev_found.dev_name = info->device_name; - event.p2p_dev_found.config_methods = info->config_methods; - event.p2p_dev_found.dev_capab = info->dev_capab; - event.p2p_dev_found.group_capab = info->group_capab; - wpa_supplicant_event(drv->ctx, EVENT_P2P_DEV_FOUND, &event); -} - - -static int test_start_listen(void *ctx, unsigned int freq, - unsigned int duration, - const struct wpabuf *probe_resp_ie) -{ - struct wpa_driver_test_data *drv = ctx; - - wpa_printf(MSG_DEBUG, "%s(freq=%u duration=%u)", - __func__, freq, duration); - - if (wpa_driver_test_probe_req_report(drv, 1) < 0) - return -1; - - drv->pending_listen_freq = freq; - drv->pending_listen_duration = duration; - - if (wpa_driver_test_remain_on_channel(drv, freq, duration) < 0) { - drv->pending_listen_freq = 0; - return -1; - } - - return 0; -} - - -static void test_stop_listen(void *ctx) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static int test_send_probe_resp(void *ctx, const struct wpabuf *buf) -{ - struct wpa_driver_test_data *drv = ctx; - char resp[512], *pos, *end; - int ret; - const struct ieee80211_mgmt *mgmt; - const u8 *ie, *ie_end; - - wpa_printf(MSG_DEBUG, "%s", __func__); - wpa_hexdump_buf(MSG_MSGDUMP, "Probe Response", buf); - if (wpabuf_len(buf) < 24) - return -1; - if (!drv->probe_from) { - wpa_printf(MSG_DEBUG, "%s: probe_from not set", __func__); - return -1; - } - - pos = resp; - end = resp + sizeof(resp); - - mgmt = wpabuf_head(buf); - - /* reply: SCANRESP BSSID SSID IEs */ - ret = os_snprintf(pos, end - pos, "SCANRESP " MACSTR " ", - MAC2STR(mgmt->bssid)); - if (ret < 0 || ret >= end - pos) - return -1; - pos += ret; - - ie = mgmt->u.probe_resp.variable; - ie_end = wpabuf_head_u8(buf) + wpabuf_len(buf); - if (ie_end - ie < 2 || ie[0] != WLAN_EID_SSID || - ie + 2 + ie[1] > ie_end) - return -1; - pos += wpa_snprintf_hex(pos, end - pos, ie + 2, ie[1]); - - ret = os_snprintf(pos, end - pos, " "); - if (ret < 0 || ret >= end - pos) - return -1; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, ie, ie_end - ie); - - sendto(drv->test_socket, resp, pos - resp, 0, - drv->probe_from, drv->probe_from_len); - - return 0; -} - - -static void test_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token, - u16 update_indic, const u8 *tlvs, size_t tlvs_len) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static void test_sd_response(void *ctx, const u8 *sa, u16 update_indic, - const u8 *tlvs, size_t tlvs_len) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static void test_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods, - const u8 *dev_addr, const u8 *pri_dev_type, - const char *dev_name, u16 supp_config_methods, - u8 dev_capab, u8 group_capab, - const u8 *group_id, size_t group_id_len) -{ - wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)", - __func__, MAC2STR(peer), config_methods); - /* TODO */ -} - - -static void test_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods) -{ - wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)", - __func__, MAC2STR(peer), config_methods); - /* TODO */ -} - -#endif /* CONFIG_P2P */ - - -static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv) -{ -#ifdef CONFIG_P2P - struct p2p_config p2p; - unsigned int r; - int i; - - os_memset(&p2p, 0, sizeof(p2p)); - p2p.msg_ctx = drv->ctx; - p2p.cb_ctx = drv; - p2p.p2p_scan = test_p2p_scan; - p2p.send_action = test_send_action; - p2p.send_action_done = test_send_action_done; - p2p.go_neg_completed = test_go_neg_completed; - p2p.go_neg_req_rx = test_go_neg_req_rx; - p2p.dev_found = test_dev_found; - p2p.start_listen = test_start_listen; - p2p.stop_listen = test_stop_listen; - p2p.send_probe_resp = test_send_probe_resp; - p2p.sd_request = test_sd_request; - p2p.sd_response = test_sd_response; - p2p.prov_disc_req = test_prov_disc_req; - p2p.prov_disc_resp = test_prov_disc_resp; - - os_memcpy(p2p.dev_addr, drv->own_addr, ETH_ALEN); - - p2p.reg_class = 12; /* TODO: change depending on location */ - /* - * Pick one of the social channels randomly as the listen - * channel. - */ - os_get_random((u8 *) &r, sizeof(r)); - p2p.channel = 1 + (r % 3) * 5; - - /* TODO: change depending on location */ - p2p.op_reg_class = 12; - /* - * For initial tests, pick the operation channel randomly. - * TODO: Use scan results (etc.) to select the best channel. - */ - p2p.op_channel = 1 + r % 11; - - os_memcpy(p2p.country, "US ", 3); - - /* FIX: fetch available channels from the driver */ - p2p.channels.reg_classes = 1; - p2p.channels.reg_class[0].reg_class = 12; /* US/12 = 2.4 GHz band */ - p2p.channels.reg_class[0].channels = 11; - for (i = 0; i < 11; i++) - p2p.channels.reg_class[0].channel[i] = i + 1; - - p2p.max_peers = 100; - - drv->p2p = p2p_init(&p2p); - if (drv->p2p == NULL) - return -1; - return 0; -#else /* CONFIG_P2P */ - wpa_printf(MSG_INFO, "driver_test: P2P support not included"); - return -1; -#endif /* CONFIG_P2P */ -} - - const struct wpa_driver_ops wpa_driver_test_ops = { "test", "wpa_supplicant test driver", @@ -3302,14 +2680,4 @@ const struct wpa_driver_ops wpa_driver_t .remain_on_channel = wpa_driver_test_remain_on_channel, .cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel, .probe_req_report = wpa_driver_test_probe_req_report, -#ifdef CONFIG_P2P - .p2p_find = wpa_driver_test_p2p_find, - .p2p_stop_find = wpa_driver_test_p2p_stop_find, - .p2p_listen = wpa_driver_test_p2p_listen, - .p2p_connect = wpa_driver_test_p2p_connect, - .wps_success_cb = wpa_driver_test_wps_success_cb, - .p2p_group_formation_failed = - wpa_driver_test_p2p_group_formation_failed, - .p2p_set_params = wpa_driver_test_p2p_set_params, -#endif /* CONFIG_P2P */ }; Index: src/external/bsd/wpa/dist/src/eap_server/eap_server_tls_common.c diff -u src/external/bsd/wpa/dist/src/eap_server/eap_server_tls_common.c:1.4 src/external/bsd/wpa/dist/src/eap_server/eap_server_tls_common.c:1.5 --- src/external/bsd/wpa/dist/src/eap_server/eap_server_tls_common.c:1.4 Thu Jan 2 21:08:17 2014 +++ src/external/bsd/wpa/dist/src/eap_server/eap_server_tls_common.c Thu Oct 16 15:29:30 2014 @@ -25,14 +25,32 @@ struct wpabuf * eap_tls_msg_alloc(EapTyp return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS, EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len, code, identifier); + else if (type == EAP_WFA_UNAUTH_TLS_TYPE) + return eap_msg_alloc(EAP_VENDOR_WFA_NEW, + EAP_VENDOR_WFA_UNAUTH_TLS, payload_len, + code, identifier); return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code, identifier); } +#ifdef CONFIG_TLS_INTERNAL +static void eap_server_tls_log_cb(void *ctx, const char *msg) +{ + struct eap_sm *sm = ctx; + eap_log_msg(sm, "TLS: %s", msg); +} +#endif /* CONFIG_TLS_INTERNAL */ + + int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, int verify_peer) { + if (sm->ssl_ctx == NULL) { + wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method"); + return -1; + } + data->eap = sm; data->phase2 = sm->init_phase2; @@ -43,6 +61,13 @@ int eap_server_tls_ssl_init(struct eap_s return -1; } +#ifdef CONFIG_TLS_INTERNAL + tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm); +#ifdef CONFIG_TESTING_OPTIONS + tls_connection_set_test_flags(data->conn, sm->tls_test_flags); +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_TLS_INTERNAL */ + if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { wpa_printf(MSG_INFO, "SSL: Failed to configure verification " "of TLS peer certificate"); @@ -394,6 +419,10 @@ int eap_server_tls_process(struct eap_sm pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, EAP_VENDOR_TYPE_UNAUTH_TLS, respData, &left); + else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE) + pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW, + EAP_VENDOR_WFA_UNAUTH_TLS, respData, + &left); else pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left); Index: src/external/bsd/wpa/dist/src/radius/radius_das.c diff -u src/external/bsd/wpa/dist/src/radius/radius_das.c:1.2 src/external/bsd/wpa/dist/src/radius/radius_das.c:1.3 --- src/external/bsd/wpa/dist/src/radius/radius_das.c:1.2 Thu Feb 27 12:42:23 2014 +++ src/external/bsd/wpa/dist/src/radius/radius_das.c Thu Oct 16 15:29:30 2014 @@ -1,6 +1,6 @@ /* * RADIUS Dynamic Authorization Server (DAS) (RFC 5176) - * Copyright (c) 2012, Jouni Malinen <j...@w1.fi> + * Copyright (c) 2012-2013, Jouni Malinen <j...@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -16,9 +16,6 @@ #include "radius_das.h" -extern int wpa_debug_level; - - struct radius_das_data { int sock; u8 *shared_secret; @@ -41,11 +38,16 @@ static struct radius_msg * radius_das_di struct radius_msg *reply; u8 allowed[] = { RADIUS_ATTR_USER_NAME, + RADIUS_ATTR_NAS_IP_ADDRESS, RADIUS_ATTR_CALLING_STATION_ID, + RADIUS_ATTR_NAS_IDENTIFIER, RADIUS_ATTR_ACCT_SESSION_ID, RADIUS_ATTR_EVENT_TIMESTAMP, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, +#ifdef CONFIG_IPV6 + RADIUS_ATTR_NAS_IPV6_ADDRESS, +#endif /* CONFIG_IPV6 */ 0 }; int error = 405; @@ -70,6 +72,36 @@ static struct radius_msg * radius_das_di os_memset(&attrs, 0, sizeof(attrs)); + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, + &buf, &len, NULL) == 0) { + if (len != 4) { + wpa_printf(MSG_INFO, "DAS: Invalid NAS-IP-Address from %s:%d", + abuf, from_port); + error = 407; + goto fail; + } + attrs.nas_ip_addr = buf; + } + +#ifdef CONFIG_IPV6 + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, + &buf, &len, NULL) == 0) { + if (len != 16) { + wpa_printf(MSG_INFO, "DAS: Invalid NAS-IPv6-Address from %s:%d", + abuf, from_port); + error = 407; + goto fail; + } + attrs.nas_ipv6_addr = buf; + } +#endif /* CONFIG_IPV6 */ + + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER, + &buf, &len, NULL) == 0) { + attrs.nas_identifier = buf; + attrs.nas_identifier_len = len; + } + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID, &buf, &len, NULL) == 0) { if (len >= sizeof(tmp)) @@ -284,7 +316,7 @@ static int radius_das_open_socket(int po s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { - perror("socket"); + wpa_printf(MSG_INFO, "RADIUS DAS: socket: %s", strerror(errno)); return -1; } @@ -292,7 +324,7 @@ static int radius_das_open_socket(int po addr.sin_family = AF_INET; addr.sin_port = htons(port); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); + wpa_printf(MSG_INFO, "RADIUS DAS: bind: %s", strerror(errno)); close(s); return -1; } Index: src/external/bsd/wpa/dist/src/utils/eloop.c diff -u src/external/bsd/wpa/dist/src/utils/eloop.c:1.4 src/external/bsd/wpa/dist/src/utils/eloop.c:1.5 --- src/external/bsd/wpa/dist/src/utils/eloop.c:1.4 Thu Jan 2 21:08:17 2014 +++ src/external/bsd/wpa/dist/src/utils/eloop.c Thu Oct 16 15:29:30 2014 @@ -7,17 +7,28 @@ */ #include "includes.h" +#include <assert.h> #include "common.h" #include "trace.h" #include "list.h" #include "eloop.h" +#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL) +#error Do not define both of poll and epoll +#endif + +#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) +#define CONFIG_ELOOP_SELECT +#endif + #ifdef CONFIG_ELOOP_POLL -#include <assert.h> #include <poll.h> #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL +#include <sys/epoll.h> +#endif /* CONFIG_ELOOP_EPOLL */ struct eloop_sock { int sock; @@ -31,7 +42,7 @@ struct eloop_sock { struct eloop_timeout { struct dl_list list; - struct os_time time; + struct os_reltime time; void *eloop_data; void *user_data; eloop_timeout_handler handler; @@ -50,7 +61,11 @@ struct eloop_signal { struct eloop_sock_table { int count; struct eloop_sock *table; +#ifdef CONFIG_ELOOP_EPOLL + eloop_event_type type; +#else /* CONFIG_ELOOP_EPOLL */ int changed; +#endif /* CONFIG_ELOOP_EPOLL */ }; struct eloop_data { @@ -63,6 +78,13 @@ struct eloop_data { struct pollfd *pollfds; struct pollfd **pollfds_map; #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + int epollfd; + int epoll_max_event_num; + int epoll_max_fd; + struct eloop_sock *epoll_table; + struct epoll_event *epoll_events; +#endif /* CONFIG_ELOOP_EPOLL */ struct eloop_sock_table readers; struct eloop_sock_table writers; struct eloop_sock_table exceptions; @@ -75,7 +97,6 @@ struct eloop_data { int pending_terminate; int terminate; - int reader_table_changed; }; static struct eloop_data eloop; @@ -128,6 +149,17 @@ int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); dl_list_init(&eloop.timeout); +#ifdef CONFIG_ELOOP_EPOLL + eloop.epollfd = epoll_create1(0); + if (eloop.epollfd < 0) { + wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n", + __func__, strerror(errno)); + return -1; + } + eloop.readers.type = EVENT_TYPE_READ; + eloop.writers.type = EVENT_TYPE_WRITE; + eloop.exceptions.type = EVENT_TYPE_EXCEPTION; +#endif /* CONFIG_ELOOP_EPOLL */ #ifdef WPA_TRACE signal(SIGSEGV, eloop_sigsegv_handler); #endif /* WPA_TRACE */ @@ -139,6 +171,11 @@ static int eloop_sock_table_add_sock(str int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { +#ifdef CONFIG_ELOOP_EPOLL + struct eloop_sock *temp_table; + struct epoll_event ev, *temp_events; + int next; +#endif /* CONFIG_ELOOP_EPOLL */ struct eloop_sock *tmp; int new_max_sock; @@ -174,6 +211,33 @@ static int eloop_sock_table_add_sock(str eloop.pollfds = n; } #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + if (new_max_sock >= eloop.epoll_max_fd) { + next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2; + temp_table = os_realloc_array(eloop.epoll_table, next, + sizeof(struct eloop_sock)); + if (temp_table == NULL) + return -1; + + eloop.epoll_max_fd = next; + eloop.epoll_table = temp_table; + } + + if (eloop.count + 1 > eloop.epoll_max_event_num) { + next = eloop.epoll_max_event_num == 0 ? 8 : + eloop.epoll_max_event_num * 2; + temp_events = os_realloc_array(eloop.epoll_events, next, + sizeof(struct epoll_event)); + if (temp_events == NULL) { + wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. " + "%s\n", __func__, strerror(errno)); + return -1; + } + + eloop.epoll_max_event_num = next; + eloop.epoll_events = temp_events; + } +#endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_remove_ref(table); tmp = os_realloc_array(table->table, table->count + 1, @@ -190,9 +254,38 @@ static int eloop_sock_table_add_sock(str table->table = tmp; eloop.max_sock = new_max_sock; eloop.count++; +#ifndef CONFIG_ELOOP_EPOLL table->changed = 1; +#endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_add_ref(table); +#ifdef CONFIG_ELOOP_EPOLL + os_memset(&ev, 0, sizeof(ev)); + switch (table->type) { + case EVENT_TYPE_READ: + ev.events = EPOLLIN; + break; + case EVENT_TYPE_WRITE: + ev.events = EPOLLOUT; + break; + /* + * Exceptions are always checked when using epoll, but I suppose it's + * possible that someone registered a socket *only* for exception + * handling. + */ + case EVENT_TYPE_EXCEPTION: + ev.events = EPOLLERR | EPOLLHUP; + break; + } + ev.data.fd = sock; + if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { + wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d " + "failed. %s\n", __func__, sock, strerror(errno)); + return -1; + } + os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1], + sizeof(struct eloop_sock)); +#endif /* CONFIG_ELOOP_EPOLL */ return 0; } @@ -219,8 +312,18 @@ static void eloop_sock_table_remove_sock } table->count--; eloop.count--; +#ifndef CONFIG_ELOOP_EPOLL table->changed = 1; +#endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_add_ref(table); +#ifdef CONFIG_ELOOP_EPOLL + if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) { + wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d " + "failed. %s\n", __func__, sock, strerror(errno)); + return; + } + os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock)); +#endif /* CONFIG_ELOOP_EPOLL */ } @@ -362,7 +465,9 @@ static void eloop_sock_table_dispatch(st max_pollfd_map, POLLERR | POLLHUP); } -#else /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_POLL */ + +#ifdef CONFIG_ELOOP_SELECT static void eloop_sock_table_set_fds(struct eloop_sock_table *table, fd_set *fds) @@ -374,8 +479,10 @@ static void eloop_sock_table_set_fds(str if (table->table == NULL) return; - for (i = 0; i < table->count; i++) + for (i = 0; i < table->count; i++) { + assert(table->table[i].sock >= 0); FD_SET(table->table[i].sock, fds); + } } @@ -399,7 +506,24 @@ static void eloop_sock_table_dispatch(st } } -#endif /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_SELECT */ + + +#ifdef CONFIG_ELOOP_EPOLL +static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds) +{ + struct eloop_sock *table; + int i; + + for (i = 0; i < nfds; i++) { + table = &eloop.epoll_table[events[i].data.fd]; + if (table->handler == NULL) + continue; + table->handler(table->sock, table->eloop_data, + table->user_data); + } +} +#endif /* CONFIG_ELOOP_EPOLL */ static void eloop_sock_table_destroy(struct eloop_sock_table *table) @@ -459,6 +583,7 @@ int eloop_register_sock(int sock, eloop_ { struct eloop_sock_table *table; + assert(sock >= 0); table = eloop_get_sock_table(type); return eloop_sock_table_add_sock(table, sock, handler, eloop_data, user_data); @@ -484,7 +609,7 @@ int eloop_register_timeout(unsigned int timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) return -1; - if (os_get_time(&timeout->time) < 0) { + if (os_get_reltime(&timeout->time) < 0) { os_free(timeout); return -1; } @@ -514,7 +639,7 @@ int eloop_register_timeout(unsigned int /* Maintain timeouts in order of increasing time */ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (os_time_before(&timeout->time, &tmp->time)) { + if (os_reltime_before(&timeout->time, &tmp->time)) { dl_list_add(tmp->list.prev, &timeout->list); return 0; } @@ -556,6 +681,33 @@ int eloop_cancel_timeout(eloop_timeout_h } +int eloop_cancel_timeout_one(eloop_timeout_handler handler, + void *eloop_data, void *user_data, + struct os_reltime *remaining) +{ + struct eloop_timeout *timeout, *prev; + int removed = 0; + struct os_reltime now; + + os_get_reltime(&now); + remaining->sec = remaining->usec = 0; + + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) { + if (timeout->handler == handler && + (timeout->eloop_data == eloop_data) && + (timeout->user_data == user_data)) { + removed = 1; + if (os_reltime_before(&now, &timeout->time)) + os_reltime_sub(&timeout->time, &now, remaining); + eloop_remove_timeout(timeout); + break; + } + } + return removed; +} + + int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data) { @@ -572,6 +724,70 @@ int eloop_is_timeout_registered(eloop_ti } +int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, + eloop_timeout_handler handler, void *eloop_data, + void *user_data) +{ + struct os_reltime now, requested, remaining; + struct eloop_timeout *tmp; + + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + requested.sec = req_secs; + requested.usec = req_usecs; + os_get_reltime(&now); + os_reltime_sub(&tmp->time, &now, &remaining); + if (os_reltime_before(&requested, &remaining)) { + eloop_cancel_timeout(handler, eloop_data, + user_data); + eloop_register_timeout(requested.sec, + requested.usec, + handler, eloop_data, + user_data); + return 1; + } + return 0; + } + } + + return -1; +} + + +int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, + eloop_timeout_handler handler, void *eloop_data, + void *user_data) +{ + struct os_reltime now, requested, remaining; + struct eloop_timeout *tmp; + + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + requested.sec = req_secs; + requested.usec = req_usecs; + os_get_reltime(&now); + os_reltime_sub(&tmp->time, &now, &remaining); + if (os_reltime_before(&remaining, &requested)) { + eloop_cancel_timeout(handler, eloop_data, + user_data); + eloop_register_timeout(requested.sec, + requested.usec, + handler, eloop_data, + user_data); + return 1; + } + return 0; + } + } + + return -1; +} + + #ifndef CONFIG_NATIVE_WINDOWS static void eloop_handle_alarm(int sig) { @@ -682,20 +898,24 @@ void eloop_run(void) #ifdef CONFIG_ELOOP_POLL int num_poll_fds; int timeout_ms = 0; -#else /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_SELECT fd_set *rfds, *wfds, *efds; struct timeval _tv; -#endif /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + int timeout_ms = -1; +#endif /* CONFIG_ELOOP_EPOLL */ int res; - struct os_time tv, now; + struct os_reltime tv, now; -#ifndef CONFIG_ELOOP_POLL +#ifdef CONFIG_ELOOP_SELECT rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) goto out; -#endif /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_SELECT */ while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || @@ -704,17 +924,18 @@ void eloop_run(void) timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { - os_get_time(&now); - if (os_time_before(&now, &timeout->time)) - os_time_sub(&timeout->time, &now, &tv); + os_get_reltime(&now); + if (os_reltime_before(&now, &timeout->time)) + os_reltime_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; -#ifdef CONFIG_ELOOP_POLL +#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) timeout_ms = tv.sec * 1000 + tv.usec / 1000; -#else /* CONFIG_ELOOP_POLL */ +#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ +#ifdef CONFIG_ELOOP_SELECT _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; -#endif /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_SELECT */ } #ifdef CONFIG_ELOOP_POLL @@ -724,30 +945,44 @@ void eloop_run(void) eloop.max_pollfd_map); res = poll(eloop.pollfds, num_poll_fds, timeout ? timeout_ms : -1); - - if (res < 0 && errno != EINTR && errno != 0) { - perror("poll"); - goto out; - } -#else /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_SELECT eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL); +#endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + if (eloop.count == 0) { + res = 0; + } else { + res = epoll_wait(eloop.epollfd, eloop.epoll_events, + eloop.count, timeout_ms); + } +#endif /* CONFIG_ELOOP_EPOLL */ if (res < 0 && errno != EINTR && errno != 0) { - perror("select"); + wpa_printf(MSG_ERROR, "eloop: %s: %s", +#ifdef CONFIG_ELOOP_POLL + "poll" +#endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_SELECT + "select" +#endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + "epoll" +#endif /* CONFIG_ELOOP_EPOLL */ + , strerror(errno)); goto out; } -#endif /* CONFIG_ELOOP_POLL */ eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { - os_get_time(&now); - if (!os_time_before(&now, &timeout->time)) { + os_get_reltime(&now); + if (!os_reltime_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; eloop_timeout_handler handler = @@ -765,19 +1000,24 @@ void eloop_run(void) eloop_sock_table_dispatch(&eloop.readers, &eloop.writers, &eloop.exceptions, eloop.pollfds_map, eloop.max_pollfd_map); -#else /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_SELECT eloop_sock_table_dispatch(&eloop.readers, rfds); eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); -#endif /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_SELECT */ +#ifdef CONFIG_ELOOP_EPOLL + eloop_sock_table_dispatch(eloop.epoll_events, res); +#endif /* CONFIG_ELOOP_EPOLL */ } + eloop.terminate = 0; out: -#ifndef CONFIG_ELOOP_POLL +#ifdef CONFIG_ELOOP_SELECT os_free(rfds); os_free(wfds); os_free(efds); -#endif /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_SELECT */ return; } @@ -791,9 +1031,9 @@ void eloop_terminate(void) void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; - struct os_time now; + struct os_reltime now; - os_get_time(&now); + os_get_reltime(&now); dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { int sec, usec; @@ -821,6 +1061,11 @@ void eloop_destroy(void) os_free(eloop.pollfds); os_free(eloop.pollfds_map); #endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + os_free(eloop.epoll_table); + os_free(eloop.epoll_events); + close(eloop.epollfd); +#endif /* CONFIG_ELOOP_EPOLL */ } @@ -843,7 +1088,13 @@ void eloop_wait_for_read_sock(int sock) pfd.events = POLLIN; poll(&pfd, 1, -1); -#else /* CONFIG_ELOOP_POLL */ +#endif /* CONFIG_ELOOP_POLL */ +#if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) + /* + * We can use epoll() here. But epoll() requres 4 system calls. + * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for + * epoll fd. So select() is better for performance here. + */ fd_set rfds; if (sock < 0) @@ -852,5 +1103,9 @@ void eloop_wait_for_read_sock(int sock) FD_ZERO(&rfds); FD_SET(sock, &rfds); select(sock + 1, &rfds, NULL, NULL, NULL); -#endif /* CONFIG_ELOOP_POLL */ +#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */ } + +#ifdef CONFIG_ELOOP_SELECT +#undef CONFIG_ELOOP_SELECT +#endif /* CONFIG_ELOOP_SELECT */ Index: src/external/bsd/wpa/dist/src/utils/os.h diff -u src/external/bsd/wpa/dist/src/utils/os.h:1.4 src/external/bsd/wpa/dist/src/utils/os.h:1.5 --- src/external/bsd/wpa/dist/src/utils/os.h:1.4 Thu Jan 2 21:08:17 2014 +++ src/external/bsd/wpa/dist/src/utils/os.h Thu Oct 16 15:29:30 2014 @@ -23,6 +23,11 @@ struct os_time { os_time_t usec; }; +struct os_reltime { + os_time_t sec; + os_time_t usec; +}; + /** * os_get_time - Get current time (sec, usec) * @t: Pointer to buffer for the time @@ -30,21 +35,84 @@ struct os_time { */ int os_get_time(struct os_time *t); +/** + * os_get_reltime - Get relative time (sec, usec) + * @t: Pointer to buffer for the time + * Returns: 0 on success, -1 on failure + */ +int os_get_reltime(struct os_reltime *t); + + +/* Helpers for handling struct os_time */ + +static inline int os_time_before(struct os_time *a, struct os_time *b) +{ + return (a->sec < b->sec) || + (a->sec == b->sec && a->usec < b->usec); +} + + +static inline void os_time_sub(struct os_time *a, struct os_time *b, + struct os_time *res) +{ + res->sec = a->sec - b->sec; + res->usec = a->usec - b->usec; + if (res->usec < 0) { + res->sec--; + res->usec += 1000000; + } +} + + +/* Helpers for handling struct os_reltime */ + +static inline int os_reltime_before(struct os_reltime *a, + struct os_reltime *b) +{ + return (a->sec < b->sec) || + (a->sec == b->sec && a->usec < b->usec); +} + -/* Helper macros for handling struct os_time */ +static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b, + struct os_reltime *res) +{ + res->sec = a->sec - b->sec; + res->usec = a->usec - b->usec; + if (res->usec < 0) { + res->sec--; + res->usec += 1000000; + } +} + + +static inline void os_reltime_age(struct os_reltime *start, + struct os_reltime *age) +{ + struct os_reltime now; + + os_get_reltime(&now); + os_reltime_sub(&now, start, age); +} + + +static inline int os_reltime_expired(struct os_reltime *now, + struct os_reltime *ts, + os_time_t timeout_secs) +{ + struct os_reltime age; + + os_reltime_sub(now, ts, &age); + return (age.sec > timeout_secs) || + (age.sec == timeout_secs && age.usec > 0); +} + + +static inline int os_reltime_initialized(struct os_reltime *t) +{ + return t->sec != 0 || t->usec != 0; +} -#define os_time_before(a, b) \ - ((a)->sec < (b)->sec || \ - ((a)->sec == (b)->sec && (a)->usec < (b)->usec)) - -#define os_time_sub(a, b, res) do { \ - (res)->sec = (a)->sec - (b)->sec; \ - (res)->usec = (a)->usec - (b)->usec; \ - if ((res)->usec < 0) { \ - (res)->sec--; \ - (res)->usec += 1000000; \ - } \ -} while (0) /** * os_mktime - Convert broken-down time into seconds since 1970-01-01 @@ -172,6 +240,13 @@ int os_unsetenv(const char *name); char * os_readfile(const char *name, size_t *len); /** + * os_file_exists - Check whether the specified file exists + * @fname: Path and name of the file + * Returns: 1 if the file exists or 0 if not + */ +int os_file_exists(const char *fname); + +/** * os_zalloc - Allocate and zero memory * @size: Number of bytes to allocate * Returns: Pointer to allocated and zeroed memory or %NULL on failure @@ -361,15 +436,6 @@ int os_strcmp(const char *s1, const char int os_strncmp(const char *s1, const char *s2, size_t n); /** - * os_strncpy - Copy a string - * @dest: Destination - * @src: Source - * @n: Maximum number of characters to copy - * Returns: dest - */ -char * os_strncpy(char *dest, const char *src, size_t n); - -/** * os_strstr - Locate a substring * @haystack: String (haystack) to search from * @needle: Needle to search from haystack @@ -465,9 +531,6 @@ char * os_strdup(const char *s); #ifndef os_strncmp #define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) #endif -#ifndef os_strncpy -#define os_strncpy(d, s, n) strncpy((d), (s), (n)) -#endif #ifndef os_strrchr #define os_strrchr(s, c) strrchr((s), (c)) #endif @@ -493,6 +556,21 @@ static inline void * os_realloc_array(vo return os_realloc(ptr, nmemb * size); } +/** + * os_remove_in_array - Remove a member from an array by index + * @ptr: Pointer to the array + * @nmemb: Current member count of the array + * @size: The size per member of the array + * @idx: Index of the member to be removed + */ +static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size, + size_t idx) +{ + if (idx < nmemb - 1) + os_memmove(((unsigned char *) ptr) + idx * size, + ((unsigned char *) ptr) + (idx + 1) * size, + (nmemb - idx - 1) * size); +} /** * os_strlcpy - Copy a string with size bound and NUL-termination @@ -506,6 +584,32 @@ static inline void * os_realloc_array(vo */ size_t os_strlcpy(char *dest, const char *src, size_t siz); +/** + * os_memcmp_const - Constant time memory comparison + * @a: First buffer to compare + * @b: Second buffer to compare + * @len: Number of octets to compare + * Returns: 0 if buffers are equal, non-zero if not + * + * This function is meant for comparing passwords or hash values where + * difference in execution time could provide external observer information + * about the location of the difference in the memory buffers. The return value + * does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to + * sort items into a defined order. Unlike os_memcmp(), execution time of + * os_memcmp_const() does not depend on the contents of the compared memory + * buffers, but only on the total compared length. + */ +int os_memcmp_const(const void *a, const void *b, size_t len); + +/** + * os_exec - Execute an external program + * @program: Path to the program + * @arg: Command line argument string + * @wait_completion: Whether to wait until the program execution completes + * Returns: 0 on success, -1 on error + */ +int os_exec(const char *program, const char *arg, int wait_completion); + #ifdef OS_REJECT_C_LIB_FUNCTIONS #define malloc OS_DO_NOT_USE_malloc Index: src/external/bsd/wpa/dist/src/utils/radiotap.h diff -u src/external/bsd/wpa/dist/src/utils/radiotap.h:1.3 src/external/bsd/wpa/dist/src/utils/radiotap.h:1.4 --- src/external/bsd/wpa/dist/src/utils/radiotap.h:1.3 Thu Jan 2 21:08:17 2014 +++ src/external/bsd/wpa/dist/src/utils/radiotap.h Thu Oct 16 15:29:30 2014 @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ -/* $NetBSD: radiotap.h,v 1.3 2014/01/03 02:08:17 christos Exp $ */ +/* $NetBSD: radiotap.h,v 1.4 2014/10/16 19:29:30 christos Exp $ */ /*- * Copyright (c) 2003, 2004 David Young. All rights reserved. @@ -175,6 +175,14 @@ struct ieee80211_radiotap_header { * * Number of unicast retries a transmitted frame used. * + * IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless + * + * Contains a bitmap of known fields/flags, the flags, and + * the MCS index. + * + * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss + * + * Contains the AMPDU information for the subframe. */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, @@ -195,6 +203,13 @@ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TX_FLAGS = 15, IEEE80211_RADIOTAP_RTS_RETRIES = 16, IEEE80211_RADIOTAP_DATA_RETRIES = 17, + + IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, + + /* valid in every it_present bitmap, even vendor namespaces */ + IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, + IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, IEEE80211_RADIOTAP_EXT = 31 }; @@ -227,8 +242,10 @@ enum ieee80211_radiotap_type { * 802.11 header and payload * (to 32-bit boundary) */ +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* frame failed FCS check */ + /* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ +#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* bad PLCP */ /* For IEEE80211_RADIOTAP_TX_FLAGS */ #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive @@ -237,4 +254,38 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ #define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ACK */ +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 + +/* For IEEE80211_RADIOTAP_MCS */ +#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01 +#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02 +#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 +#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 +#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 +#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 +#define IEEE80211_RADIOTAP_MCS_HAVE_NESS 0x40 +#define IEEE80211_RADIOTAP_MCS_NESS_BIT1 0x80 + + +#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 +#define IEEE80211_RADIOTAP_MCS_BW_20 0 +#define IEEE80211_RADIOTAP_MCS_BW_40 1 +#define IEEE80211_RADIOTAP_MCS_BW_20L 2 +#define IEEE80211_RADIOTAP_MCS_BW_20U 3 +#define IEEE80211_RADIOTAP_MCS_SGI 0x04 +#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 +#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 +#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 +#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 +#define IEEE80211_RADIOTAP_MCS_STBC_1 1 +#define IEEE80211_RADIOTAP_MCS_STBC_2 2 +#define IEEE80211_RADIOTAP_MCS_STBC_3 3 +#define IEEE80211_RADIOTAP_MCS_NESS_BIT0 0x80 + #endif /* IEEE80211_RADIOTAP_H */ Index: src/external/bsd/wpa/dist/wpa_supplicant/wpa_cli.c diff -u src/external/bsd/wpa/dist/wpa_supplicant/wpa_cli.c:1.4 src/external/bsd/wpa/dist/wpa_supplicant/wpa_cli.c:1.5 --- src/external/bsd/wpa/dist/wpa_supplicant/wpa_cli.c:1.4 Thu Jan 2 21:08:17 2014 +++ src/external/bsd/wpa/dist/wpa_supplicant/wpa_cli.c Thu Oct 16 15:29:30 2014 @@ -1,6 +1,6 @@ /* * WPA Supplicant - command line interface for wpa_supplicant daemon - * Copyright (c) 2004-2012, Jouni Malinen <j...@w1.fi> + * Copyright (c) 2004-2013, Jouni Malinen <j...@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -28,7 +28,7 @@ static const char *wpa_cli_version = "wpa_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2012, Jouni Malinen <j...@w1.fi> and contributors"; +"Copyright (c) 2004-2014, Jouni Malinen <j...@w1.fi> and contributors"; static const char *wpa_cli_license = @@ -70,7 +70,7 @@ static struct wpa_ctrl *ctrl_conn; static struct wpa_ctrl *mon_conn; static int wpa_cli_quit = 0; static int wpa_cli_attached = 0; -static int wpa_cli_connected = 0; +static int wpa_cli_connected = -1; static int wpa_cli_last_id = 0; #ifndef CONFIG_CTRL_IFACE_DIR #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant" @@ -81,6 +81,7 @@ static const char *pid_file = NULL; static const char *action_file = NULL; static int ping_interval = 5; static int interactive = 0; +static char *ifname_prefix = NULL; struct cli_txt_entry { struct dl_list list; @@ -90,6 +91,7 @@ struct cli_txt_entry { static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */ static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */ static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */ static void print_help(const char *cmd); @@ -173,11 +175,9 @@ static void cli_txt_list_del_word(struct end = os_strchr(txt, ' '); if (end == NULL) end = txt + os_strlen(txt); - buf = os_malloc(end - txt + 1); + buf = dup_binstr(txt, end - txt); if (buf == NULL) return; - os_memcpy(buf, txt, end - txt); - buf[end - txt] = '\0'; cli_txt_list_del(txt_list, buf); os_free(buf); } @@ -223,11 +223,9 @@ static int cli_txt_list_add_word(struct end = os_strchr(txt, ' '); if (end == NULL) end = txt + os_strlen(txt); - buf = os_malloc(end - txt + 1); + buf = dup_binstr(txt, end - txt); if (buf == NULL) return -1; - os_memcpy(buf, txt, end - txt); - buf[end - txt] = '\0'; ret = cli_txt_list_add(txt_list, buf); os_free(buf); return ret; @@ -433,7 +431,7 @@ static void wpa_cli_msg_cb(char *msg, si static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) { - char buf[2048]; + char buf[4096]; size_t len; int ret; @@ -441,6 +439,12 @@ static int _wpa_ctrl_command(struct wpa_ printf("Not connected to wpa_supplicant - command dropped.\n"); return -1; } + if (ifname_prefix) { + os_snprintf(buf, sizeof(buf), "IFNAME=%s %s", + ifname_prefix, cmd); + buf[sizeof(buf) - 1] = '\0'; + cmd = buf; + } len = sizeof(buf) - 1; ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, wpa_cli_msg_cb); @@ -498,7 +502,7 @@ fail: static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, int argc, char *argv[]) { - char buf[256]; + char buf[4096]; if (argc < min_args) { printf("Invalid %s command - at least %d argument%s " "required.\n", cmd, min_args, @@ -523,6 +527,8 @@ static int wpa_cli_cmd_status(struct wpa return wpa_ctrl_command(ctrl, "STATUS-VERBOSE"); if (argc > 0 && os_strcmp(argv[0], "wps") == 0) return wpa_ctrl_command(ctrl, "STATUS-WPS"); + if (argc > 0 && os_strcmp(argv[0], "driver") == 0) + return wpa_ctrl_command(ctrl, "STATUS-DRIVER"); return wpa_ctrl_command(ctrl, "STATUS"); } @@ -557,6 +563,13 @@ static int wpa_cli_cmd_pmksa(struct wpa_ } +static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PMKSA_FLUSH"); +} + + static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) { print_help(argc > 0 ? argv[0] : NULL); @@ -595,52 +608,84 @@ static int wpa_cli_cmd_quit(struct wpa_c } -static void wpa_cli_show_variables(void) -{ - printf("set variables:\n" - " EAPOL::heldPeriod (EAPOL state machine held period, " - "in seconds)\n" - " EAPOL::authPeriod (EAPOL state machine authentication " - "period, in seconds)\n" - " EAPOL::startPeriod (EAPOL state machine start period, in " - "seconds)\n" - " EAPOL::maxStart (EAPOL state machine maximum start " - "attempts)\n"); - printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " - "seconds)\n" - " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" - " threshold\n\tpercentage)\n" - " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " - "security\n\tassociation in seconds)\n"); -} - - static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; - if (argc == 0) { - wpa_cli_show_variables(); - return 0; + if (argc == 1) { + res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long SET command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); } - if (argc != 1 && argc != 2) { - printf("Invalid SET command: needs two arguments (variable " - "name and value)\n"); - return -1; - } + return wpa_cli_cmd(ctrl, "SET", 2, argc, argv); +} - if (argc == 1) - res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]); - else - res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", - argv[0], argv[1]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long SET command.\n"); - return -1; + +static char ** wpa_cli_complete_set(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + const char *fields[] = { + /* runtime values */ + "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod", + "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime", + "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout", + "wps_fragment_size", "wps_version_number", "ampdu", + "tdls_testing", "tdls_disabled", "pno", "radio_disabled", + "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps", + "no_keep_alive", + /* global configuration parameters */ + "eapol_version", "ap_scan", "disable_scan_offload", + "fast_reauth", "opensc_engine_path", "pkcs11_engine_path", + "pkcs11_module_path", "pcsc_reader", "pcsc_pin", + "driver_param", "dot11RSNAConfigPMKLifetime", + "dot11RSNAConfigPMKReauthThreshold", + "dot11RSNAConfigSATimeout", + "update_config", "load_dynamic_eap", "uuid", "device_name", + "manufacturer", "model_name", "model_number", "serial_number", + "device_type", "os_version", "config_methods", + "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type", + "p2p_listen_reg_class", "p2p_listen_channel", + "p2p_oper_reg_class", "p2p_oper_channel", + "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect", + "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan", + "p2p_no_go_freq", + "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface", + "p2p_go_vht", + "p2p_ignore_shared_freq", "country", "bss_max_count", + "bss_expiration_age", "bss_expiration_scan_count", + "filter_ssids", "filter_rssi", "max_num_sta", + "disassoc_low_ack", "hs20", "interworking", "hessid", + "access_network_type", "pbc_in_m1", "autoscan", + "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey", + "wps_nfc_dev_pw", "ext_password_backend", + "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf", + "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements", + "ignore_old_scan_res", "freq_list", "external_sim", + "tdls_external_control", "p2p_search_delay" + }; + int i, num_fields = ARRAY_SIZE(fields); + + if (arg == 1) { + char **res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(fields[i]); + if (res[i] == NULL) + return res; + } + return res; } - return wpa_ctrl_command(ctrl, cmd); + + if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0) + return cli_txt_list_array(&bsses); + + return NULL; } @@ -669,6 +714,12 @@ static int wpa_cli_cmd_reassociate(struc } +static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "REATTACH"); +} + + static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -775,6 +826,13 @@ static int wpa_cli_cmd_wps_nfc(struct wp } +static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv); +} + + static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -822,55 +880,10 @@ static int wpa_cli_cmd_nfc_get_handover_ } -static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc, +static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc, char *argv[]) { - int ret; - char *buf; - size_t buflen; - - if (argc != 1) { - printf("Invalid 'nfc_rx_handover_req' command - one argument " - "is required.\n"); - return -1; - } - - buflen = 21 + os_strlen(argv[0]); - buf = os_malloc(buflen); - if (buf == NULL) - return -1; - os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]); - - ret = wpa_ctrl_command(ctrl, buf); - os_free(buf); - - return ret; -} - - -static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - int ret; - char *buf; - size_t buflen; - - if (argc != 1) { - printf("Invalid 'nfc_rx_handover_sel' command - one argument " - "is required.\n"); - return -1; - } - - buflen = 21 + os_strlen(argv[0]); - buf = os_malloc(buflen); - if (buf == NULL) - return -1; - os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]); - - ret = wpa_ctrl_command(ctrl, buf); - os_free(buf); - - return ret; + return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv); } #endif /* CONFIG_WPS_NFC */ @@ -1252,6 +1265,38 @@ static int wpa_cli_cmd_otp(struct wpa_ct } +static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + printf("Invalid SIM command: needs two arguments " + "(network id and SIM operation response)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s", + argv[0], argv[1]); + if (ret < 0 || ret >= end - pos) { + printf("Too long SIM command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (ret < 0 || ret >= end - pos) { + printf("Too long SIM command.\n"); + return -1; + } + pos += ret; + } + return wpa_ctrl_command(ctrl, cmd); +} + + static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1409,6 +1454,24 @@ static int wpa_cli_cmd_get_network(struc } +static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc == 0) { + wpa_cli_show_network_variables(); + return 0; + } + + if (argc < 3) { + printf("Invalid DUP_NETWORK command: needs three arguments\n" + "(src netid, dest netid, and variable name)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv); +} + + static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1441,6 +1504,18 @@ static int wpa_cli_cmd_set_cred(struct w } +static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc != 2) { + printf("Invalid GET_CRED command: needs two arguments\n" + "(cred id, variable name)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv); +} + + static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1464,7 +1539,7 @@ static int wpa_cli_cmd_save_config(struc static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) { - return wpa_ctrl_command(ctrl, "SCAN"); + return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv); } @@ -1533,7 +1608,7 @@ static int wpa_cli_cmd_interface(struct os_free(ctrl_ifname); ctrl_ifname = os_strdup(argv[0]); - if (wpa_cli_open_connection(ctrl_ifname, 1)) { + if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) { printf("Connected to interface '%s.\n", ctrl_ifname); } else { printf("Could not connect to interface '%s' - re-trying\n", @@ -1671,6 +1746,13 @@ static int wpa_cli_cmd_disassociate(stru { return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv); } + +static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv); +} + #endif /* CONFIG_AP */ @@ -1686,10 +1768,12 @@ static int wpa_cli_cmd_resume(struct wpa } +#ifdef CONFIG_TESTING_OPTIONS static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DROP_SA"); } +#endif /* CONFIG_TESTING_OPTIONS */ static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) @@ -2039,6 +2123,50 @@ static int wpa_cli_cmd_p2p_set(struct wp } +static char ** wpa_cli_complete_p2p_set(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + const char *fields[] = { + "discoverability", + "managed", + "listen_channel", + "ssid_postfix", + "noa", + "ps", + "oppps", + "ctwindow", + "disabled", + "conc_pref", + "force_long_sd", + "peer_filter", + "cross_connect", + "go_apsd", + "client_apsd", + "disallow_freq", + "disc_int", + "per_sta_psk", + }; + int i, num_fields = ARRAY_SIZE(fields); + + if (arg == 1) { + char **res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(fields[i]); + if (res[i] == NULL) + return res; + } + return res; + } + + if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0) + return cli_txt_list_array(&p2p_peers); + + return NULL; +} + + static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "P2P_FLUSH"); @@ -2089,6 +2217,13 @@ static int wpa_cli_cmd_p2p_ext_listen(st return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv); } + +static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv); +} + #endif /* CONFIG_P2P */ #ifdef CONFIG_WIFI_DISPLAY @@ -2213,6 +2348,37 @@ static int wpa_cli_cmd_get_nai_home_real return wpa_ctrl_command(ctrl, cmd); } + +static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[512]; + + if (argc < 2) { + printf("Command needs two arguments (dst mac addr and " + "icon name)\n"); + return -1; + } + + if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0) + return -1; + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "FETCH_OSU"); +} + + +static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU"); +} + #endif /* CONFIG_HS20 */ @@ -2285,6 +2451,12 @@ static int wpa_cli_cmd_wnm_sleep(struct return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv); } + +static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv); +} + #endif /* CONFIG_WNM */ @@ -2296,6 +2468,32 @@ static int wpa_cli_cmd_raw(struct wpa_ct } +#ifdef ANDROID +static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv); +} +#endif /* ANDROID */ + + +static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv); +} + + +static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "FLUSH"); +} + + +static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv); +} + + enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, cli_cmd_flag_sensitive = 0x01 @@ -2343,7 +2541,7 @@ static struct wpa_cli_cmd wpa_cli_comman { "quit", wpa_cli_cmd_quit, NULL, cli_cmd_flag_none, "= exit wpa_cli" }, - { "set", wpa_cli_cmd_set, NULL, + { "set", wpa_cli_cmd_set, wpa_cli_complete_set, cli_cmd_flag_none, "= set variables (shows list of variables when run without " "arguments)" }, @@ -2359,9 +2557,15 @@ static struct wpa_cli_cmd wpa_cli_comman { "pmksa", wpa_cli_cmd_pmksa, NULL, cli_cmd_flag_none, "= show PMKSA cache" }, + { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL, + cli_cmd_flag_none, + "= flush PMKSA cache entries" }, { "reassociate", wpa_cli_cmd_reassociate, NULL, cli_cmd_flag_none, "= force reassociation" }, + { "reattach", wpa_cli_cmd_reattach, NULL, + cli_cmd_flag_none, + "= force reassociation back to the same BSS" }, { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss, cli_cmd_flag_none, "<BSSID> = force preauthentication" }, @@ -2385,6 +2589,9 @@ static struct wpa_cli_cmd wpa_cli_comman cli_cmd_flag_sensitive, "<network id> <passphrase> = configure private key passphrase\n" " for an SSID" }, + { "sim", wpa_cli_cmd_sim, NULL, + cli_cmd_flag_sensitive, + "<network id> <pin> = report SIM operation result" }, { "bssid", wpa_cli_cmd_bssid, NULL, cli_cmd_flag_none, "<network id> <BSSID> = set preferred BSSID for an SSID" }, @@ -2422,6 +2629,10 @@ static struct wpa_cli_cmd wpa_cli_comman { "get_network", wpa_cli_cmd_get_network, NULL, cli_cmd_flag_none, "<network id> <variable> = get network variables" }, + { "dup_network", wpa_cli_cmd_dup_network, NULL, + cli_cmd_flag_none, + "<src network id> <dst network id> <variable> = duplicate network variables" + }, { "list_creds", wpa_cli_cmd_list_creds, NULL, cli_cmd_flag_none, "= list configured credentials" }, @@ -2434,6 +2645,9 @@ static struct wpa_cli_cmd wpa_cli_comman { "set_cred", wpa_cli_cmd_set_cred, NULL, cli_cmd_flag_sensitive, "<cred id> <variable> <value> = set credential variables" }, + { "get_cred", wpa_cli_cmd_get_cred, NULL, + cli_cmd_flag_none, + "<cred id> <variable> = get credential variables" }, { "save_config", wpa_cli_cmd_save_config, NULL, cli_cmd_flag_none, "= save the current configuration" }, @@ -2456,7 +2670,7 @@ static struct wpa_cli_cmd wpa_cli_comman "<<idx> | <bssid>> = get detailed scan result info" }, { "get_capability", wpa_cli_cmd_get_capability, NULL, cli_cmd_flag_none, - "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> " + "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> " "= get capabilies" }, { "reconfigure", wpa_cli_cmd_reconfigure, NULL, cli_cmd_flag_none, @@ -2512,6 +2726,9 @@ static struct wpa_cli_cmd wpa_cli_comman { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss, cli_cmd_flag_none, "[BSSID] = start Wi-Fi Protected Setup: NFC" }, + { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL, + cli_cmd_flag_none, + "<WPS|NDEF> = build configuration token" }, { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL, cli_cmd_flag_none, "<WPS|NDEF> = create password token" }, @@ -2524,12 +2741,10 @@ static struct wpa_cli_cmd wpa_cli_comman { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL, cli_cmd_flag_none, "<NDEF> <WPS> = create NFC handover select" }, - { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL, + { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL, cli_cmd_flag_none, - "<hexdump of payload> = report received NFC handover request" }, - { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL, - cli_cmd_flag_none, - "<hexdump of payload> = report received NFC handover select" }, + "<role> <type> <hexdump of req> <hexdump of sel> = report completed " + "NFC handover" }, #endif /* CONFIG_WPS_NFC */ { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss, cli_cmd_flag_sensitive, @@ -2579,13 +2794,20 @@ static struct wpa_cli_cmd wpa_cli_comman { "disassociate", wpa_cli_cmd_disassociate, NULL, cli_cmd_flag_none, "<addr> = disassociate a station" }, + { "chan_switch", wpa_cli_cmd_chanswitch, NULL, + cli_cmd_flag_none, + "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]" + " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]" + " = CSA parameters" }, #endif /* CONFIG_AP */ { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none, "= notification of suspend/hibernate" }, { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none, "= notification of resume/thaw" }, +#ifdef CONFIG_TESTING_OPTIONS { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none, "= drop SA without deauth/disassoc (test command)" }, +#endif /* CONFIG_TESTING_OPTIONS */ { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss, cli_cmd_flag_none, "<addr> = roam to the specified BSS" }, @@ -2649,7 +2871,8 @@ static struct wpa_cli_cmd wpa_cli_comman { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer, cli_cmd_flag_none, "<address> = show information about known P2P peer" }, - { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none, + { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set, + cli_cmd_flag_none, "<field> <value> = set a P2P parameter" }, { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none, "= flush P2P state" }, @@ -2665,6 +2888,9 @@ static struct wpa_cli_cmd wpa_cli_comman { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL, cli_cmd_flag_none, "[<period> <interval>] = set extended listen timing" }, + { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client, + wpa_cli_complete_p2p_peer, cli_cmd_flag_none, + "<address|iface=address> = remove a peer from all groups" }, #endif /* CONFIG_P2P */ #ifdef CONFIG_WIFI_DISPLAY { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL, @@ -2704,6 +2930,14 @@ static struct wpa_cli_cmd wpa_cli_comman { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list, wpa_cli_complete_bss, cli_cmd_flag_none, "<addr> <home realm> = get HS20 nai home realm list" }, + { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request, + wpa_cli_complete_bss, cli_cmd_flag_none, + "<addr> <icon name> = get Hotspot 2.0 OSU icon" }, + { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none, + "= fetch OSU provider information from all APs" }, + { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL, + cli_cmd_flag_none, + "= cancel fetch_osu command" }, #endif /* CONFIG_HS20 */ { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL, cli_cmd_flag_none, @@ -2733,9 +2967,22 @@ static struct wpa_cli_cmd wpa_cli_comman #ifdef CONFIG_WNM { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none, "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" }, + { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none, + "<query reason> = Send BSS Transition Management Query" }, #endif /* CONFIG_WNM */ { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive, "<params..> = Sent unprocessed command" }, + { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none, + "= flush wpa_supplicant state" }, +#ifdef ANDROID + { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none, + "<command> = driver private commands" }, +#endif /* ANDROID */ + { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none, + "= radio_work <show/add/done>" }, + { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none, + "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command" + }, { NULL, NULL, NULL, cli_cmd_flag_none, NULL } }; @@ -2794,9 +3041,12 @@ static char ** wpa_list_cmd_list(void) { char **res; int i, count; + struct cli_txt_entry *e; - count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]); - res = os_calloc(count, sizeof(char *)); + count = ARRAY_SIZE(wpa_cli_commands); + count += dl_list_len(&p2p_groups); + count += dl_list_len(&ifnames); + res = os_calloc(count + 1, sizeof(char *)); if (res == NULL) return NULL; @@ -2806,6 +3056,22 @@ static char ** wpa_list_cmd_list(void) break; } + dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) { + size_t len = 8 + os_strlen(e->txt); + res[i] = os_malloc(len); + if (res[i] == NULL) + break; + os_snprintf(res[i], len, "ifname=%s", e->txt); + i++; + } + + dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) { + res[i] = os_strdup(e->txt); + if (res[i] == NULL) + break; + i++; + } + return res; } @@ -2837,6 +3103,14 @@ static char ** wpa_cli_edit_completion_c const char *end; char *cmd; + if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) { + end = os_strchr(str, ' '); + if (end && pos > end - str) { + pos -= end - str + 1; + str = end + 1; + } + } + end = os_strchr(str, ' '); if (end == NULL || str + pos < end) return wpa_list_cmd_list(); @@ -2858,6 +3132,16 @@ static int wpa_request(struct wpa_ctrl * int count; int ret = 0; + if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) { + ifname_prefix = argv[0] + 7; + argv = &argv[1]; + argc--; + } else + ifname_prefix = NULL; + + if (argc == 0) + return -1; + count = 0; cmd = wpa_cli_commands; while (cmd->cmd) { @@ -2906,34 +3190,42 @@ static int str_match(const char *a, cons static int wpa_cli_exec(const char *program, const char *arg1, const char *arg2) { - char *cmd; + char *arg; size_t len; int res; - int ret = 0; - len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; - cmd = os_malloc(len); - if (cmd == NULL) - return -1; - res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); - if (res < 0 || (size_t) res >= len) { - os_free(cmd); - return -1; - } - cmd[len - 1] = '\0'; -#ifndef _WIN32_WCE - if (system(cmd) < 0) - ret = -1; -#endif /* _WIN32_WCE */ - os_free(cmd); + len = os_strlen(arg1) + os_strlen(arg2) + 2; + arg = os_malloc(len); + if (arg == NULL) + return -1; + os_snprintf(arg, len, "%s %s", arg1, arg2); + res = os_exec(program, arg, 1); + os_free(arg); - return ret; + return res; } static void wpa_cli_action_process(const char *msg) { - const char *pos = skip_priority(msg); + const char *pos; + char *copy = NULL, *id, *pos2; + const char *ifname = ctrl_ifname; + char ifname_buf[100]; + + pos = msg; + if (os_strncmp(pos, "IFNAME=", 7) == 0) { + const char *end; + end = os_strchr(pos + 7, ' '); + if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) { + pos += 7; + os_memcpy(ifname_buf, pos, end - pos); + ifname_buf[end - pos] = '\0'; + ifname = ifname_buf; + pos = end + 1; + } + } + pos = skip_priority(msg); if (str_match(pos, WPA_EVENT_CONNECTED)) { int new_id = -1; @@ -2966,34 +3258,40 @@ static void wpa_cli_action_process(const os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); - if (!wpa_cli_connected || new_id != wpa_cli_last_id) { + if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) { wpa_cli_connected = 1; wpa_cli_last_id = new_id; - wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); + wpa_cli_exec(action_file, ifname, "CONNECTED"); } } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { if (wpa_cli_connected) { wpa_cli_connected = 0; - wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); + wpa_cli_exec(action_file, ifname, "DISCONNECTED"); } } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, WPS_EVENT_SUCCESS)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, WPS_EVENT_FAIL)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, AP_STA_CONNECTED)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, AP_STA_DISCONNECTED)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); + wpa_cli_exec(action_file, ifname, pos); + } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) { + wpa_cli_exec(action_file, ifname, pos); + } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) { + wpa_cli_exec(action_file, ifname, pos); + } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) { + wpa_cli_exec(action_file, ifname, pos); } else if (str_match(pos, WPA_EVENT_TERMINATING)) { printf("wpa_supplicant is terminating - stop monitoring\n"); wpa_cli_quit = 1; @@ -3125,7 +3423,7 @@ static void wpa_cli_recv_pending(struct return; } while (wpa_ctrl_pending(ctrl) > 0) { - char buf[256]; + char buf[4096]; size_t len = sizeof(buf) - 1; if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { buf[len] = '\0'; @@ -3189,10 +3487,18 @@ static int tokenize_cmd(char *cmd, char static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx) { - if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { - printf("Connection to wpa_supplicant lost - trying to " - "reconnect\n"); - wpa_cli_close_connection(); + if (ctrl_conn) { + int res; + char *prefix = ifname_prefix; + + ifname_prefix = NULL; + res = _wpa_ctrl_command(ctrl_conn, "PING", 0); + ifname_prefix = prefix; + if (res) { + printf("Connection to wpa_supplicant lost - trying to " + "reconnect\n"); + wpa_cli_close_connection(); + } } if (!ctrl_conn) wpa_cli_reconnect(); @@ -3255,8 +3561,74 @@ static void start_edit(void) } +static void update_bssid_list(struct wpa_ctrl *ctrl) +{ + char buf[4096]; + size_t len = sizeof(buf); + int ret; + char *cmd = "BSS RANGE=ALL MASK=0x2"; + char *pos, *end; + + if (ctrl == NULL) + return; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL); + if (ret < 0) + return; + buf[len] = '\0'; + + pos = buf; + while (pos) { + pos = os_strstr(pos, "bssid="); + if (pos == NULL) + break; + pos += 6; + end = os_strchr(pos, '\n'); + if (end == NULL) + break; + *end = '\0'; + cli_txt_list_add(&bsses, pos); + pos = end + 1; + } +} + + +static void update_ifnames(struct wpa_ctrl *ctrl) +{ + char buf[4096]; + size_t len = sizeof(buf); + int ret; + char *cmd = "INTERFACES"; + char *pos, *end; + char txt[200]; + + cli_txt_list_flush(&ifnames); + + if (ctrl == NULL) + return; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL); + if (ret < 0) + return; + buf[len] = '\0'; + + pos = buf; + while (pos) { + end = os_strchr(pos, '\n'); + if (end == NULL) + break; + *end = '\0'; + ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos); + if (ret > 0 && ret < (int) sizeof(txt)) + cli_txt_list_add(&ifnames, txt); + pos = end + 1; + } +} + + static void try_connection(void *eloop_ctx, void *timeout_ctx) { + if (ctrl_conn) + goto done; + if (ctrl_ifname == NULL) ctrl_ifname = wpa_cli_get_default_ifname(); @@ -3270,9 +3642,12 @@ static void try_connection(void *eloop_c return; } + update_bssid_list(ctrl_conn); + if (warning_displayed) printf("Connection established.\n"); +done: start_edit(); } @@ -3288,6 +3663,7 @@ static void wpa_cli_interactive(void) cli_txt_list_flush(&p2p_peers); cli_txt_list_flush(&p2p_groups); cli_txt_list_flush(&bsses); + cli_txt_list_flush(&ifnames); if (edit_started) edit_deinit(hfile, wpa_cli_edit_filter_history_cb); os_free(hfile); @@ -3394,7 +3770,7 @@ static char * wpa_cli_get_default_ifname #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - char buf[2048], *pos; + char buf[4096], *pos; size_t len; struct wpa_ctrl *ctrl; int ret; @@ -3488,6 +3864,24 @@ int main(int argc, char *argv[]) global, strerror(errno)); return -1; } + + if (interactive) { + update_ifnames(ctrl_conn); + mon_conn = wpa_ctrl_open(global); + if (mon_conn) { + if (wpa_ctrl_attach(mon_conn) == 0) { + wpa_cli_attached = 1; + eloop_register_read_sock( + wpa_ctrl_get_fd(mon_conn), + wpa_cli_mon_receive, + NULL, NULL); + } else { + printf("Failed to open monitor " + "connection through global " + "control interface\n"); + } + } + } } eloop_register_signal_terminate(wpa_cli_terminate, NULL);