1 /* 2 * WPA Supplicant - PS3 Linux wireless extension driver interface 3 * Copyright 2007, 2008 Sony Corporation 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 #include <sys/ioctl.h> 17 #include "wireless_copy.h" 18 #include "common.h" 19 #include "wpa_common.h" 20 #include "driver.h" 21 #include "eloop.h" 22 #include "driver_wext.h" 23 #include "ieee802_11_defs.h" 24 25 static int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv, 26 struct wpa_driver_associate_params *params) 27 { 28 int ret, i; 29 struct iwreq iwr; 30 char *buf, *str; 31 32 if (!params->psk && !params->passphrase) { 33 wpa_printf(MSG_INFO, "%s:no PSK error", __func__); 34 return -EINVAL; 35 } 36 37 os_memset(&iwr, 0, sizeof(iwr)); 38 if (params->psk) { 39 /* includes null */ 40 iwr.u.data.length = PMK_LEN * 2 + 1; 41 buf = os_malloc(iwr.u.data.length); 42 if (!buf) 43 return -ENOMEM; 44 str = buf; 45 for (i = 0; i < PMK_LEN; i++) { 46 str += snprintf(str, iwr.u.data.length - (str - buf), 47 "%02x", params->psk[i]); 48 } 49 } else if (params->passphrase) { 50 /* including quotations and null */ 51 iwr.u.data.length = strlen(params->passphrase) + 3; 52 buf = os_malloc(iwr.u.data.length); 53 if (!buf) 54 return -ENOMEM; 55 buf[0] = '"'; 56 os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3); 57 buf[iwr.u.data.length - 2] = '"'; 58 buf[iwr.u.data.length - 1] = '\0'; 59 } else 60 return -EINVAL; 61 iwr.u.data.pointer = (caddr_t) buf; 62 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 63 ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr); 64 os_free(buf); 65 66 return ret; 67 } 68 69 static int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv, 70 struct wpa_driver_associate_params *params) 71 { 72 int ret, i; 73 struct iwreq iwr; 74 75 for (i = 0; i < 4; i++) { 76 os_memset(&iwr, 0, sizeof(iwr)); 77 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 78 iwr.u.encoding.flags = i + 1; 79 if (params->wep_key_len[i]) { 80 iwr.u.encoding.pointer = (caddr_t) params->wep_key[i]; 81 iwr.u.encoding.length = params->wep_key_len[i]; 82 } else 83 iwr.u.encoding.flags = IW_ENCODE_NOKEY | 84 IW_ENCODE_DISABLED; 85 86 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 87 perror("ioctl[SIOCSIWENCODE]"); 88 ret = -1; 89 } 90 } 91 return ret; 92 } 93 94 static int wpa_driver_ps3_associate(void *priv, 95 struct wpa_driver_associate_params *params) 96 { 97 struct wpa_driver_wext_data *drv = priv; 98 int ret, value; 99 100 wpa_printf(MSG_DEBUG, "%s: <-", __func__); 101 102 /* clear BSSID */ 103 if (!params->bssid && 104 wpa_driver_wext_set_bssid(drv, NULL) < 0) 105 ret = -1; 106 107 if (wpa_driver_wext_set_mode(drv, params->mode) < 0) 108 ret = -1; 109 110 if (params->wpa_ie == NULL || params->wpa_ie_len == 0) 111 value = IW_AUTH_WPA_VERSION_DISABLED; 112 else if (params->wpa_ie[0] == WLAN_EID_RSN) 113 value = IW_AUTH_WPA_VERSION_WPA2; 114 else 115 value = IW_AUTH_WPA_VERSION_WPA; 116 if (wpa_driver_wext_set_auth_param(drv, 117 IW_AUTH_WPA_VERSION, value) < 0) 118 ret = -1; 119 value = wpa_driver_wext_cipher2wext(params->pairwise_suite); 120 if (wpa_driver_wext_set_auth_param(drv, 121 IW_AUTH_CIPHER_PAIRWISE, value) < 0) 122 ret = -1; 123 value = wpa_driver_wext_cipher2wext(params->group_suite); 124 if (wpa_driver_wext_set_auth_param(drv, 125 IW_AUTH_CIPHER_GROUP, value) < 0) 126 ret = -1; 127 value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); 128 if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_KEY_MGMT, value) < 0) 129 ret = -1; 130 131 /* set selected BSSID */ 132 if (params->bssid && 133 wpa_driver_wext_set_bssid(drv, params->bssid) < 0) 134 ret = -1; 135 136 switch (params->group_suite) { 137 case CIPHER_NONE: 138 ret = 0; 139 break; 140 case CIPHER_WEP40: 141 case CIPHER_WEP104: 142 ret = wpa_driver_ps3_set_wep_keys(drv, params); 143 break; 144 case CIPHER_TKIP: 145 case CIPHER_CCMP: 146 ret = wpa_driver_ps3_set_wpa_key(drv, params); 147 break; 148 } 149 150 /* start to associate */ 151 ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len); 152 153 wpa_printf(MSG_DEBUG, "%s: ->", __func__); 154 155 return ret; 156 } 157 158 static int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa) 159 { 160 int ret; 161 wpa_printf(MSG_DEBUG, "%s:<-", __func__); 162 163 ret = wpa_driver_wext_get_capa(priv, capa); 164 if (ret) { 165 wpa_printf(MSG_INFO, "%s: base wext returns error %d", 166 __func__, ret); 167 return ret; 168 } 169 /* PS3 hypervisor does association and 4way handshake by itself */ 170 capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; 171 wpa_printf(MSG_DEBUG, "%s:->", __func__); 172 return 0; 173 } 174 175 const struct wpa_driver_ops wpa_driver_ps3_ops = { 176 .name = "ps3", 177 .desc = "PLAYSTATION3 Linux wireless extension driver", 178 .get_bssid = wpa_driver_wext_get_bssid, 179 .get_ssid = wpa_driver_wext_get_ssid, 180 .scan = wpa_driver_wext_scan, 181 .get_scan_results2 = wpa_driver_wext_get_scan_results, 182 .associate = wpa_driver_ps3_associate, /* PS3 */ 183 .init = wpa_driver_wext_init, 184 .deinit = wpa_driver_wext_deinit, 185 .get_capa = wpa_driver_ps3_get_capa, /* PS3 */ 186 }; 187