From b5a357b47645a30165deb5c526e797eb2dfa6084 Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Thu, 13 Mar 2008 19:00:37 +0200 Subject: [PATCH] Add support for PS3 Linux wireless driver This adds support for PS3 wireless to wpa_supplicant. Although PS3 wireless driver is designed to conform the WEXT standard as much as possible, unfortunately the wext driver wrapper of wpa_supplicant can not support PS3 wireless fully because: - PS3 wireless driver uses private WEXT ioctls for accepting PSK of WPA-Personal from the userland. WEXT does not specify the way to do it. - The association and 4-way handshake are done by PS3 virtual wireless device. The guest OSes can not interfere it. - No EAPOL frames are allowed to go outside of the hypervisor/firmware nor come from. They are eaten by the firmware. Thus I needed to make a new driver wrapper for PS3 wireless. This patch can be applied against the latest 0.6.x tree. Signed-off-by: Masakazu Mokuno --- src/drivers/driver_ps3.c | 185 ++++++++++++++++++++++++++++++++++++++ src/drivers/driver_wext.c | 41 ++------- src/drivers/driver_wext.h | 37 +++++++- src/drivers/drivers.c | 6 ++ wpa_supplicant/ChangeLog | 1 + wpa_supplicant/Makefile | 6 ++ 6 files changed, 241 insertions(+), 35 deletions(-) create mode 100644 src/drivers/driver_ps3.c diff --git a/src/drivers/driver_ps3.c b/src/drivers/driver_ps3.c new file mode 100644 index 000000000..e74e48447 --- /dev/null +++ b/src/drivers/driver_ps3.c @@ -0,0 +1,185 @@ +/* + * WPA Supplicant - PS3 Linux wireless extension driver interface + * Copyright 2007, 2008 Sony Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" +#include +#include "wireless_copy.h" +#include "common.h" +#include "wpa_common.h" +#include "driver.h" +#include "eloop.h" +#include "driver_wext.h" +#include "ieee802_11_defs.h" + +static int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv, + struct wpa_driver_associate_params *params) +{ + int ret, i; + struct iwreq iwr; + char *buf, *str; + + if (!params->psk && !params->passphrase) { + wpa_printf(MSG_INFO, "%s:no PSK error\n", __FUNCTION__); + return -EINVAL; + } + + os_memset(&iwr, 0, sizeof(iwr)); + if (params->psk) { + /* includes null */ + iwr.u.data.length = PMK_LEN * 2 + 1; + buf = os_malloc(iwr.u.data.length); + if (!buf) + return -ENOMEM; + str = buf; + for (i = 0; i < PMK_LEN; i++) { + str += snprintf(str, iwr.u.data.length - (str - buf), + "%02x", params->psk[i]); + } + } else if (params->passphrase) { + /* including quotations and null */ + iwr.u.data.length = strlen(params->passphrase) + 3; + if (!buf) + return -ENOMEM; + buf[0] = '"'; + os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3); + buf[iwr.u.data.length - 2] = '"'; + buf[iwr.u.data.length - 1] = '\0'; + } + iwr.u.data.pointer = (caddr_t)buf; + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr); + os_free(buf); + + return ret; +} + +static int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv, + struct wpa_driver_associate_params *params) +{ + int ret, i; + struct iwreq iwr; + + for (i = 0; i < 4; i++) { + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.encoding.flags = i + 1; + if (params->wep_key_len[i]) { + iwr.u.encoding.pointer = (caddr_t) params->wep_key[i]; + iwr.u.encoding.length = params->wep_key_len[i]; + } else + iwr.u.encoding.flags = IW_ENCODE_NOKEY | + IW_ENCODE_DISABLED; + + if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { + perror("ioctl[SIOCSIWENCODE]"); + ret = -1; + } + } + return ret; +} + +static int wpa_driver_ps3_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_wext_data *drv = priv; + int ret, i, value; + + wpa_printf(MSG_DEBUG, "%s: <-\n", __func__); + + /* clear BSSID */ + if (!params->bssid && + wpa_driver_wext_set_bssid(drv, NULL) < 0) + ret = -1; + + if (wpa_driver_wext_set_mode(drv, params->mode) < 0) + ret = -1; + + if (params->wpa_ie == NULL || params->wpa_ie_len == 0) + value = IW_AUTH_WPA_VERSION_DISABLED; + else if (params->wpa_ie[0] == WLAN_EID_RSN) + value = IW_AUTH_WPA_VERSION_WPA2; + else + value = IW_AUTH_WPA_VERSION_WPA; + if (wpa_driver_wext_set_auth_param(drv, + IW_AUTH_WPA_VERSION, value) < 0) + ret = -1; + value = wpa_driver_wext_cipher2wext(params->pairwise_suite); + if (wpa_driver_wext_set_auth_param(drv, + IW_AUTH_CIPHER_PAIRWISE, value) < 0) + ret = -1; + value = wpa_driver_wext_cipher2wext(params->group_suite); + if (wpa_driver_wext_set_auth_param(drv, + IW_AUTH_CIPHER_GROUP, value) < 0) + ret = -1; + value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); + if (wpa_driver_wext_set_auth_param(drv, + IW_AUTH_KEY_MGMT, value) < 0) + ret = -1; + + /* set selected BSSID */ + if (params->bssid && + wpa_driver_wext_set_bssid(drv, params->bssid) < 0) + ret = -1; + + switch (params->group_suite) { + case CIPHER_NONE: + ret = 0; + break; + case CIPHER_WEP40: + case CIPHER_WEP104: + ret = wpa_driver_ps3_set_wep_keys(drv, params); + break; + case CIPHER_TKIP: + case CIPHER_CCMP: + ret = wpa_driver_ps3_set_wpa_key(drv, params); + break; + } + + /* start to associate */ + ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len); + + wpa_printf(MSG_DEBUG, "%s: ->\n", __func__); + + return ret; +} + +static int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa) +{ + int ret; + wpa_printf(MSG_DEBUG, "%s:<-\n", __func__); + + ret = wpa_driver_wext_get_capa(priv, capa); + if (ret) { + wpa_printf(MSG_INFO, "%s: base wext returns error %d\n", __func__, + ret); + return ret; + } + /* PS3 hypervisor does association and 4way handshake by itself */ + capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; + wpa_printf(MSG_DEBUG, "%s:->\n", __func__); + return 0; +} + +const struct wpa_driver_ops wpa_driver_ps3_ops = { + .name = "ps3", + .desc = "PLAYSTATION3 Linux wireless extension driver", + .get_bssid = wpa_driver_wext_get_bssid, + .get_ssid = wpa_driver_wext_get_ssid, + .scan = wpa_driver_wext_scan, + .get_scan_results2 = wpa_driver_wext_get_scan_results, + .associate = wpa_driver_ps3_associate, /* PS3 */ + .init = wpa_driver_wext_init, + .deinit = wpa_driver_wext_deinit, + .get_capa = wpa_driver_ps3_get_capa, /* PS3 */ +}; diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index db43103c9..69aae16ae 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -149,32 +149,6 @@ enum { #endif /* CONFIG_CLIENT_MLME */ -struct wpa_driver_wext_data { - void *ctx; - int event_sock; - int ioctl_sock; - int mlme_sock; - char ifname[IFNAMSIZ + 1]; - int ifindex; - int ifindex2; - u8 *assoc_req_ies; - size_t assoc_req_ies_len; - u8 *assoc_resp_ies; - size_t assoc_resp_ies_len; - struct wpa_driver_capa capa; - int has_capability; - int we_version_compiled; - - /* for set_auth_alg fallback */ - int use_crypt; - int auth_alg_fallback; - - int operstate; - - char mlmedev[IFNAMSIZ + 1]; - - int scan_complete_events; -}; static int wpa_driver_wext_flush_pmkid(void *priv); @@ -239,8 +213,8 @@ static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv, } -static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, - int idx, u32 value) +int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, + int idx, u32 value) { struct iwreq iwr; int ret = 0; @@ -1977,7 +1951,7 @@ static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie, } -static int wpa_driver_wext_cipher2wext(int cipher) +int wpa_driver_wext_cipher2wext(int cipher) { switch (cipher) { case CIPHER_NONE: @@ -1996,7 +1970,7 @@ static int wpa_driver_wext_cipher2wext(int cipher) } -static int wpa_driver_wext_keymgmt2wext(int keymgmt) +int wpa_driver_wext_keymgmt2wext(int keymgmt) { switch (keymgmt) { case KEY_MGMT_802_1X: @@ -2054,9 +2028,8 @@ wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv, } -static int -wpa_driver_wext_associate(void *priv, - struct wpa_driver_associate_params *params) +int wpa_driver_wext_associate(void *priv, + struct wpa_driver_associate_params *params) { struct wpa_driver_wext_data *drv = priv; int ret = 0; @@ -2239,7 +2212,7 @@ static int wpa_driver_wext_flush_pmkid(void *priv) } -static int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) +int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) { struct wpa_driver_wext_data *drv = priv; if (!drv->has_capability) diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h index a09a63cea..590c1e156 100644 --- a/src/drivers/driver_wext.h +++ b/src/drivers/driver_wext.h @@ -15,7 +15,34 @@ #ifndef DRIVER_WEXT_H #define DRIVER_WEXT_H -struct wpa_driver_wext_data; +#include + +struct wpa_driver_wext_data { + void *ctx; + int event_sock; + int ioctl_sock; + int mlme_sock; + char ifname[IFNAMSIZ + 1]; + int ifindex; + int ifindex2; + u8 *assoc_req_ies; + size_t assoc_req_ies_len; + u8 *assoc_resp_ies; + size_t assoc_resp_ies_len; + struct wpa_driver_capa capa; + int has_capability; + int we_version_compiled; + + /* for set_auth_alg fallback */ + int use_crypt; + int auth_alg_fallback; + + int operstate; + + char mlmedev[IFNAMSIZ + 1]; + + int scan_complete_events; +}; int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags); int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags); @@ -43,4 +70,12 @@ void wpa_driver_wext_deinit(void *priv); int wpa_driver_wext_set_operstate(void *priv, int state); int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv); +int wpa_driver_wext_associate(void *priv, + struct wpa_driver_associate_params *params); +int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa); +int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, + int idx, u32 value); +int wpa_driver_wext_cipher2wext(int cipher); +int wpa_driver_wext_keymgmt2wext(int keymgmt); + #endif /* DRIVER_WEXT_H */ diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c index faeef564e..396d7690a 100644 --- a/src/drivers/drivers.c +++ b/src/drivers/drivers.c @@ -61,6 +61,9 @@ extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */ #ifdef CONFIG_DRIVER_OSX extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */ #endif /* CONFIG_DRIVER_OSX */ +#ifdef CONFIG_DRIVER_PS3 +extern struct wpa_driver_ops wpa_driver_ps3_ops; /* driver_ps3.c */ +#endif /* CONFIG_DRIVER_PS3 */ #ifdef CONFIG_DRIVER_IPHONE extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */ #endif /* CONFIG_DRIVER_IPHONE */ @@ -113,6 +116,9 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] = #ifdef CONFIG_DRIVER_OSX &wpa_driver_osx_ops, #endif /* CONFIG_DRIVER_OSX */ +#ifdef CONFIG_DRIVER_PS3 + &wpa_driver_ps3_ops, +#endif /* CONFIG_DRIVER_PS3 */ #ifdef CONFIG_DRIVER_IPHONE &wpa_driver_iphone_ops, #endif /* CONFIG_DRIVER_IPHONE */ diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index 947b6e1cb..7def00c98 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -3,6 +3,7 @@ ChangeLog for wpa_supplicant ????-??-?? - v0.6.4 * added support for EAP Sequences in EAP-FAST Phase 2 * added support for using TNC with EAP-FAST + * added driver_ps3 for the PS3 Linux wireless driver 2008-02-22 - v0.6.3 * removed 'nai' and 'eappsk' network configuration variables that were diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 41874e02b..17c699026 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -210,6 +210,12 @@ LDFLAGS += -framework CoreFoundation LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211 endif +ifdef CONFIG_DRIVER_PS3 +CFLAGS += -DCONFIG_DRIVER_PS3 -m64 +OBJS_d += ../src/drivers/driver_ps3.o +LDFLAGS += -m64 +endif + ifdef CONFIG_DRIVER_IPHONE CFLAGS += -DCONFIG_DRIVER_IPHONE OBJS_d += ../src/drivers/driver_iphone.o