driver_atheros.c revision 61d9df3e62aaa0e87ad05452fcb95142159a17b6
17faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/* 27faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * hostapd / Driver interaction with Atheros driver 37faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Copyright (c) 2004, Sam Leffler <sam@errno.com> 47faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Copyright (c) 2004, Video54 Technologies 57faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> 67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Copyright (c) 2009, Atheros Communications 77faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 87faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * This software may be distributed under the terms of the BSD license. 97faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * See README for more details. 107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "includes.h" 137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include <net/if.h> 147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include <sys/ioctl.h> 157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "common.h" 177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "eloop.h" 187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "common/ieee802_11_defs.h" 197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "l2_packet/l2_packet.h" 207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "p2p/p2p.h" 217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "common.h" 237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifndef _BYTE_ORDER 247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifdef WORDS_BIGENDIAN 257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define _BYTE_ORDER _BIG_ENDIAN 267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#else 277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define _BYTE_ORDER _LITTLE_ENDIAN 287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif 297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif /* _BYTE_ORDER */ 307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/* 327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Note, the ATH_WPS_IE setting must match with the driver build.. If the 337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * driver does not include this, the IEEE80211_IOCTL_GETWPAIE ioctl will fail. 347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define ATH_WPS_IE 367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "ieee80211_external.h" 387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifdef CONFIG_WPS 417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include <netpacket/packet.h> 427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif /* CONFIG_WPS */ 437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifndef ETH_P_80211_RAW 457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define ETH_P_80211_RAW 0x0019 467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif 477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "linux_wext.h" 497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "driver.h" 517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "eloop.h" 527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "priv_netlink.h" 537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "l2_packet/l2_packet.h" 547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "common/ieee802_11_defs.h" 557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "netlink.h" 567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "linux_ioctl.h" 577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstruct atheros_driver_data { 607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct hostapd_data *hapd; /* back pointer */ 617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez char iface[IFNAMSIZ + 1]; 637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int ifindex; 647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ 657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct l2_packet_data *sock_recv; /* raw packet recv socket */ 667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int ioctl_sock; /* socket for ioctl() use */ 677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct netlink_data *netlink; 687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int we_version; 697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez u8 acct_mac[ETH_ALEN]; 707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct hostap_sta_driver_data acct_data; 717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct l2_packet_data *sock_raw; /* raw 802.11 management frames */ 737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct wpabuf *wpa_ie; 747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct wpabuf *wps_beacon_ie; 757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez struct wpabuf *wps_probe_resp_ie; 767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez u8 own_addr[ETH_ALEN]; 777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}; 787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstatic int atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, 807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int reason_code); 817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstatic int atheros_set_privacy(void *priv, int enabled); 827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstatic const char * athr_get_ioctl_name(int op) 847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez switch (op) { 867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETPARAM: 877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETPARAM"; 887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GETPARAM: 897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GETPARAM"; 907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETKEY: 917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETKEY"; 927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETWMMPARAMS: 937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETWMMPARAMS"; 947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_DELKEY: 957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "DELKEY"; 967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GETWMMPARAMS: 977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GETWMMPARAMS"; 987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETMLME: 997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETMLME"; 1007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GETCHANINFO: 1017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GETCHANINFO"; 1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETOPTIE: 1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETOPTIE"; 1047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GETOPTIE: 1057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GETOPTIE"; 1067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_ADDMAC: 1077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "ADDMAC"; 1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_DELMAC: 1097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "DELMAC"; 1107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GETCHANLIST: 1117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GETCHANLIST"; 1127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETCHANLIST: 1137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETCHANLIST"; 1147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_KICKMAC: 1157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "KICKMAC"; 1167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_CHANSWITCH: 1177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "CHANSWITCH"; 1187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GETMODE: 1197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GETMODE"; 1207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_SETMODE: 1217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "SETMODE"; 1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez case IEEE80211_IOCTL_GET_APPIEBUF: 1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return "GET_APPIEBUF"; 124 case IEEE80211_IOCTL_SET_APPIEBUF: 125 return "SET_APPIEBUF"; 126 case IEEE80211_IOCTL_SET_ACPARAMS: 127 return "SET_ACPARAMS"; 128 case IEEE80211_IOCTL_FILTERFRAME: 129 return "FILTERFRAME"; 130 case IEEE80211_IOCTL_SET_RTPARAMS: 131 return "SET_RTPARAMS"; 132 case IEEE80211_IOCTL_SET_MEDENYENTRY: 133 return "SET_MEDENYENTRY"; 134 case IEEE80211_IOCTL_GET_MACADDR: 135 return "GET_MACADDR"; 136 case IEEE80211_IOCTL_SET_HBRPARAMS: 137 return "SET_HBRPARAMS"; 138 case IEEE80211_IOCTL_SET_RXTIMEOUT: 139 return "SET_RXTIMEOUT"; 140 case IEEE80211_IOCTL_STA_STATS: 141 return "STA_STATS"; 142 case IEEE80211_IOCTL_GETWPAIE: 143 return "GETWPAIE"; 144 default: 145 return "??"; 146 } 147} 148 149 150static const char * athr_get_param_name(int op) 151{ 152 switch (op) { 153 case IEEE80211_IOC_MCASTCIPHER: 154 return "MCASTCIPHER"; 155 case IEEE80211_PARAM_MCASTKEYLEN: 156 return "MCASTKEYLEN"; 157 case IEEE80211_PARAM_UCASTCIPHERS: 158 return "UCASTCIPHERS"; 159 case IEEE80211_PARAM_KEYMGTALGS: 160 return "KEYMGTALGS"; 161 case IEEE80211_PARAM_RSNCAPS: 162 return "RSNCAPS"; 163 case IEEE80211_PARAM_WPA: 164 return "WPA"; 165 case IEEE80211_PARAM_AUTHMODE: 166 return "AUTHMODE"; 167 case IEEE80211_PARAM_PRIVACY: 168 return "PRIVACY"; 169 case IEEE80211_PARAM_COUNTERMEASURES: 170 return "COUNTERMEASURES"; 171 default: 172 return "??"; 173 } 174} 175 176 177static int 178set80211priv(struct atheros_driver_data *drv, int op, void *data, int len) 179{ 180 struct iwreq iwr; 181 int do_inline = len < IFNAMSIZ; 182 183 /* Certain ioctls must use the non-inlined method */ 184 if (op == IEEE80211_IOCTL_SET_APPIEBUF || 185 op == IEEE80211_IOCTL_FILTERFRAME) 186 do_inline = 0; 187 188 memset(&iwr, 0, sizeof(iwr)); 189 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 190 if (do_inline) { 191 /* 192 * Argument data fits inline; put it there. 193 */ 194 memcpy(iwr.u.name, data, len); 195 } else { 196 /* 197 * Argument data too big for inline transfer; setup a 198 * parameter block instead; the kernel will transfer 199 * the data for the driver. 200 */ 201 iwr.u.data.pointer = data; 202 iwr.u.data.length = len; 203 } 204 205 if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { 206 wpa_printf(MSG_DEBUG, "atheros: %s: %s: ioctl op=0x%x " 207 "(%s) len=%d failed: %d (%s)", 208 __func__, drv->iface, op, 209 athr_get_ioctl_name(op), 210 len, errno, strerror(errno)); 211 return -1; 212 } 213 return 0; 214} 215 216static int 217set80211param(struct atheros_driver_data *drv, int op, int arg) 218{ 219 struct iwreq iwr; 220 221 memset(&iwr, 0, sizeof(iwr)); 222 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 223 iwr.u.mode = op; 224 memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); 225 226 if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { 227 perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); 228 wpa_printf(MSG_DEBUG, "%s: %s: Failed to set parameter (op %d " 229 "(%s) arg %d)", __func__, drv->iface, op, 230 athr_get_param_name(op), arg); 231 return -1; 232 } 233 return 0; 234} 235 236#ifndef CONFIG_NO_STDOUT_DEBUG 237static const char * 238ether_sprintf(const u8 *addr) 239{ 240 static char buf[sizeof(MACSTR)]; 241 242 if (addr != NULL) 243 snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 244 else 245 snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); 246 return buf; 247} 248#endif /* CONFIG_NO_STDOUT_DEBUG */ 249 250/* 251 * Configure WPA parameters. 252 */ 253static int 254atheros_configure_wpa(struct atheros_driver_data *drv, 255 struct wpa_bss_params *params) 256{ 257 int v; 258 259 switch (params->wpa_group) { 260 case WPA_CIPHER_CCMP: 261 v = IEEE80211_CIPHER_AES_CCM; 262 break; 263 case WPA_CIPHER_TKIP: 264 v = IEEE80211_CIPHER_TKIP; 265 break; 266 case WPA_CIPHER_WEP104: 267 v = IEEE80211_CIPHER_WEP; 268 break; 269 case WPA_CIPHER_WEP40: 270 v = IEEE80211_CIPHER_WEP; 271 break; 272 case WPA_CIPHER_NONE: 273 v = IEEE80211_CIPHER_NONE; 274 break; 275 default: 276 wpa_printf(MSG_ERROR, "Unknown group key cipher %u", 277 params->wpa_group); 278 return -1; 279 } 280 wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v); 281 if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) { 282 printf("Unable to set group key cipher to %u\n", v); 283 return -1; 284 } 285 if (v == IEEE80211_CIPHER_WEP) { 286 /* key length is done only for specific ciphers */ 287 v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); 288 if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) { 289 printf("Unable to set group key length to %u\n", v); 290 return -1; 291 } 292 } 293 294 v = 0; 295 if (params->wpa_pairwise & WPA_CIPHER_CCMP) 296 v |= 1<<IEEE80211_CIPHER_AES_CCM; 297 if (params->wpa_pairwise & WPA_CIPHER_TKIP) 298 v |= 1<<IEEE80211_CIPHER_TKIP; 299 if (params->wpa_pairwise & WPA_CIPHER_NONE) 300 v |= 1<<IEEE80211_CIPHER_NONE; 301 wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v); 302 if (set80211param(drv, IEEE80211_PARAM_UCASTCIPHERS, v)) { 303 printf("Unable to set pairwise key ciphers to 0x%x\n", v); 304 return -1; 305 } 306 307 wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x", 308 __func__, params->wpa_key_mgmt); 309 if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, 310 params->wpa_key_mgmt)) { 311 printf("Unable to set key management algorithms to 0x%x\n", 312 params->wpa_key_mgmt); 313 return -1; 314 } 315 316 v = 0; 317 if (params->rsn_preauth) 318 v |= BIT(0); 319#ifdef CONFIG_IEEE80211W 320 if (params->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 321 v |= BIT(7); 322 if (params->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 323 v |= BIT(6); 324 } 325#endif /* CONFIG_IEEE80211W */ 326 327 wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", 328 __func__, params->rsn_preauth); 329 if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) { 330 printf("Unable to set RSN capabilities to 0x%x\n", v); 331 return -1; 332 } 333 334 wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, params->wpa); 335 if (set80211param(drv, IEEE80211_PARAM_WPA, params->wpa)) { 336 printf("Unable to set WPA to %u\n", params->wpa); 337 return -1; 338 } 339 return 0; 340} 341 342static int 343atheros_set_ieee8021x(void *priv, struct wpa_bss_params *params) 344{ 345 struct atheros_driver_data *drv = priv; 346 347 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); 348 349 if (!params->enabled) { 350 /* XXX restore state */ 351 if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, 352 IEEE80211_AUTH_AUTO) < 0) 353 return -1; 354 /* IEEE80211_AUTH_AUTO ends up enabling Privacy; clear that */ 355 return atheros_set_privacy(drv, 0); 356 } 357 if (!params->wpa && !params->ieee802_1x) { 358 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, 359 HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); 360 return -1; 361 } 362 if (params->wpa && atheros_configure_wpa(drv, params) != 0) { 363 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, 364 HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); 365 return -1; 366 } 367 if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, 368 (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { 369 hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, 370 HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); 371 return -1; 372 } 373 374 return 0; 375} 376 377static int 378atheros_set_privacy(void *priv, int enabled) 379{ 380 struct atheros_driver_data *drv = priv; 381 382 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 383 384 return set80211param(drv, IEEE80211_PARAM_PRIVACY, enabled); 385} 386 387static int 388atheros_set_sta_authorized(void *priv, const u8 *addr, int authorized) 389{ 390 struct atheros_driver_data *drv = priv; 391 struct ieee80211req_mlme mlme; 392 int ret; 393 394 wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", 395 __func__, ether_sprintf(addr), authorized); 396 397 if (authorized) 398 mlme.im_op = IEEE80211_MLME_AUTHORIZE; 399 else 400 mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; 401 mlme.im_reason = 0; 402 memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 403 ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); 404 if (ret < 0) { 405 wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR, 406 __func__, authorized ? "" : "un", MAC2STR(addr)); 407 } 408 409 return ret; 410} 411 412static int 413atheros_sta_set_flags(void *priv, const u8 *addr, 414 int total_flags, int flags_or, int flags_and) 415{ 416 /* For now, only support setting Authorized flag */ 417 if (flags_or & WPA_STA_AUTHORIZED) 418 return atheros_set_sta_authorized(priv, addr, 1); 419 if (!(flags_and & WPA_STA_AUTHORIZED)) 420 return atheros_set_sta_authorized(priv, addr, 0); 421 return 0; 422} 423 424static int 425atheros_del_key(void *priv, const u8 *addr, int key_idx) 426{ 427 struct atheros_driver_data *drv = priv; 428 struct ieee80211req_del_key wk; 429 int ret; 430 431 wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", 432 __func__, ether_sprintf(addr), key_idx); 433 434 memset(&wk, 0, sizeof(wk)); 435 if (addr != NULL) { 436 memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); 437 wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE; 438 } else { 439 wk.idk_keyix = key_idx; 440 } 441 442 ret = set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk)); 443 if (ret < 0) { 444 wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s" 445 " key_idx %d)", __func__, ether_sprintf(addr), 446 key_idx); 447 } 448 449 return ret; 450} 451 452static int 453atheros_set_key(const char *ifname, void *priv, enum wpa_alg alg, 454 const u8 *addr, int key_idx, int set_tx, const u8 *seq, 455 size_t seq_len, const u8 *key, size_t key_len) 456{ 457 struct atheros_driver_data *drv = priv; 458 struct ieee80211req_key wk; 459 u_int8_t cipher; 460 int ret; 461 462 if (alg == WPA_ALG_NONE) 463 return atheros_del_key(drv, addr, key_idx); 464 465 wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d", 466 __func__, alg, ether_sprintf(addr), key_idx); 467 468 switch (alg) { 469 case WPA_ALG_WEP: 470 cipher = IEEE80211_CIPHER_WEP; 471 break; 472 case WPA_ALG_TKIP: 473 cipher = IEEE80211_CIPHER_TKIP; 474 break; 475 case WPA_ALG_CCMP: 476 cipher = IEEE80211_CIPHER_AES_CCM; 477 break; 478#ifdef CONFIG_IEEE80211W 479 case WPA_ALG_IGTK: 480 cipher = IEEE80211_CIPHER_AES_CMAC; 481 break; 482#endif /* CONFIG_IEEE80211W */ 483 default: 484 printf("%s: unknown/unsupported algorithm %d\n", 485 __func__, alg); 486 return -1; 487 } 488 489 if (key_len > sizeof(wk.ik_keydata)) { 490 printf("%s: key length %lu too big\n", __func__, 491 (unsigned long) key_len); 492 return -3; 493 } 494 495 memset(&wk, 0, sizeof(wk)); 496 wk.ik_type = cipher; 497 wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; 498 if (addr == NULL || is_broadcast_ether_addr(addr)) { 499 memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); 500 wk.ik_keyix = key_idx; 501 if (set_tx) 502 wk.ik_flags |= IEEE80211_KEY_DEFAULT; 503 } else { 504 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 505 wk.ik_keyix = IEEE80211_KEYIX_NONE; 506 } 507 wk.ik_keylen = key_len; 508 memcpy(wk.ik_keydata, key, key_len); 509 510 ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk)); 511 if (ret < 0) { 512 wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s" 513 " key_idx %d alg %d key_len %lu set_tx %d)", 514 __func__, ether_sprintf(wk.ik_macaddr), key_idx, 515 alg, (unsigned long) key_len, set_tx); 516 } 517 518 return ret; 519} 520 521 522static int 523atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, 524 u8 *seq) 525{ 526 struct atheros_driver_data *drv = priv; 527 struct ieee80211req_key wk; 528 529 wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", 530 __func__, ether_sprintf(addr), idx); 531 532 memset(&wk, 0, sizeof(wk)); 533 if (addr == NULL) 534 memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); 535 else 536 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 537 wk.ik_keyix = idx; 538 539 if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) { 540 wpa_printf(MSG_DEBUG, "%s: Failed to get encryption data " 541 "(addr " MACSTR " key_idx %d)", 542 __func__, MAC2STR(wk.ik_macaddr), idx); 543 return -1; 544 } 545 546#ifdef WORDS_BIGENDIAN 547 { 548 /* 549 * wk.ik_keytsc is in host byte order (big endian), need to 550 * swap it to match with the byte order used in WPA. 551 */ 552 int i; 553#ifndef WPA_KEY_RSC_LEN 554#define WPA_KEY_RSC_LEN 8 555#endif 556 u8 tmp[WPA_KEY_RSC_LEN]; 557 memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); 558 for (i = 0; i < WPA_KEY_RSC_LEN; i++) { 559 seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; 560 } 561 } 562#else /* WORDS_BIGENDIAN */ 563 memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); 564#endif /* WORDS_BIGENDIAN */ 565 return 0; 566} 567 568 569static int 570atheros_flush(void *priv) 571{ 572 u8 allsta[IEEE80211_ADDR_LEN]; 573 memset(allsta, 0xff, IEEE80211_ADDR_LEN); 574 return atheros_sta_deauth(priv, NULL, allsta, 575 IEEE80211_REASON_AUTH_LEAVE); 576} 577 578 579static int 580atheros_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, 581 const u8 *addr) 582{ 583 struct atheros_driver_data *drv = priv; 584 struct ieee80211req_sta_stats stats; 585 586 memset(data, 0, sizeof(*data)); 587 588 /* 589 * Fetch statistics for station from the system. 590 */ 591 memset(&stats, 0, sizeof(stats)); 592 memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); 593 if (set80211priv(drv, IEEE80211_IOCTL_STA_STATS, 594 &stats, sizeof(stats))) { 595 wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr " 596 MACSTR ")", __func__, MAC2STR(addr)); 597 if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { 598 memcpy(data, &drv->acct_data, sizeof(*data)); 599 return 0; 600 } 601 602 printf("Failed to get station stats information element.\n"); 603 return -1; 604 } 605 606 data->rx_packets = stats.is_stats.ns_rx_data; 607 data->rx_bytes = stats.is_stats.ns_rx_bytes; 608 data->tx_packets = stats.is_stats.ns_tx_data; 609 data->tx_bytes = stats.is_stats.ns_tx_bytes; 610 return 0; 611} 612 613 614static int 615atheros_sta_clear_stats(void *priv, const u8 *addr) 616{ 617 struct atheros_driver_data *drv = priv; 618 struct ieee80211req_mlme mlme; 619 int ret; 620 621 wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr)); 622 623 mlme.im_op = IEEE80211_MLME_CLEAR_STATS; 624 memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 625 ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, 626 sizeof(mlme)); 627 if (ret < 0) { 628 wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr " 629 MACSTR ")", __func__, MAC2STR(addr)); 630 } 631 632 return ret; 633} 634 635 636static int 637atheros_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) 638{ 639 struct atheros_driver_data *drv = priv; 640 u8 buf[512]; 641 struct ieee80211req_getset_appiebuf *app_ie; 642 643 wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__, 644 (unsigned long) ie_len); 645 wpa_hexdump(MSG_DEBUG, "atheros: set_generic_elem", ie, ie_len); 646 647 wpabuf_free(drv->wpa_ie); 648 drv->wpa_ie = wpabuf_alloc_copy(ie, ie_len); 649 650 app_ie = (struct ieee80211req_getset_appiebuf *) buf; 651 os_memcpy(&(app_ie->app_buf[0]), ie, ie_len); 652 app_ie->app_buflen = ie_len; 653 654 app_ie->app_frmtype = IEEE80211_APPIE_FRAME_BEACON; 655 656 /* append WPS IE for Beacon */ 657 if (drv->wps_beacon_ie != NULL) { 658 os_memcpy(&(app_ie->app_buf[ie_len]), 659 wpabuf_head(drv->wps_beacon_ie), 660 wpabuf_len(drv->wps_beacon_ie)); 661 app_ie->app_buflen = ie_len + wpabuf_len(drv->wps_beacon_ie); 662 } 663 wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF(Beacon)", 664 app_ie->app_buf, app_ie->app_buflen); 665 set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie, 666 sizeof(struct ieee80211req_getset_appiebuf) + 667 app_ie->app_buflen); 668 669 /* append WPS IE for Probe Response */ 670 app_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_RESP; 671 if (drv->wps_probe_resp_ie != NULL) { 672 os_memcpy(&(app_ie->app_buf[ie_len]), 673 wpabuf_head(drv->wps_probe_resp_ie), 674 wpabuf_len(drv->wps_probe_resp_ie)); 675 app_ie->app_buflen = ie_len + 676 wpabuf_len(drv->wps_probe_resp_ie); 677 } else 678 app_ie->app_buflen = ie_len; 679 wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF(ProbeResp)", 680 app_ie->app_buf, app_ie->app_buflen); 681 set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie, 682 sizeof(struct ieee80211req_getset_appiebuf) + 683 app_ie->app_buflen); 684 return 0; 685} 686 687static int 688atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, 689 int reason_code) 690{ 691 struct atheros_driver_data *drv = priv; 692 struct ieee80211req_mlme mlme; 693 int ret; 694 695 wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", 696 __func__, ether_sprintf(addr), reason_code); 697 698 mlme.im_op = IEEE80211_MLME_DEAUTH; 699 mlme.im_reason = reason_code; 700 memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 701 ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); 702 if (ret < 0) { 703 wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR 704 " reason %d)", 705 __func__, MAC2STR(addr), reason_code); 706 } 707 708 return ret; 709} 710 711static int 712atheros_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, 713 int reason_code) 714{ 715 struct atheros_driver_data *drv = priv; 716 struct ieee80211req_mlme mlme; 717 int ret; 718 719 wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", 720 __func__, ether_sprintf(addr), reason_code); 721 722 mlme.im_op = IEEE80211_MLME_DISASSOC; 723 mlme.im_reason = reason_code; 724 memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 725 ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); 726 if (ret < 0) { 727 wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr " 728 MACSTR " reason %d)", 729 __func__, MAC2STR(addr), reason_code); 730 } 731 732 return ret; 733} 734 735#ifdef CONFIG_WPS 736static void atheros_raw_recv_wps(void *ctx, const u8 *src_addr, const u8 *buf, 737 size_t len) 738{ 739 struct atheros_driver_data *drv = ctx; 740 const struct ieee80211_mgmt *mgmt; 741 u16 fc; 742 union wpa_event_data event; 743 744 /* Send Probe Request information to WPS processing */ 745 746 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) 747 return; 748 mgmt = (const struct ieee80211_mgmt *) buf; 749 750 fc = le_to_host16(mgmt->frame_control); 751 if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || 752 WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) 753 return; 754 755 os_memset(&event, 0, sizeof(event)); 756 event.rx_probe_req.sa = mgmt->sa; 757 event.rx_probe_req.da = mgmt->da; 758 event.rx_probe_req.bssid = mgmt->bssid; 759 event.rx_probe_req.ie = mgmt->u.probe_req.variable; 760 event.rx_probe_req.ie_len = 761 len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); 762 wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event); 763} 764#endif /* CONFIG_WPS */ 765 766#ifdef CONFIG_IEEE80211R 767static void atheros_raw_recv_11r(void *ctx, const u8 *src_addr, const u8 *buf, 768 size_t len) 769{ 770 struct atheros_driver_data *drv = ctx; 771 union wpa_event_data event; 772 const struct ieee80211_mgmt *mgmt; 773 u16 fc; 774 u16 stype; 775 int ielen; 776 const u8 *iebuf; 777 778 /* Do 11R processing for ASSOC/AUTH/FT ACTION frames */ 779 if (len < IEEE80211_HDRLEN) 780 return; 781 mgmt = (const struct ieee80211_mgmt *) buf; 782 783 fc = le_to_host16(mgmt->frame_control); 784 785 if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) 786 return; 787 stype = WLAN_FC_GET_STYPE(fc); 788 789 wpa_printf(MSG_DEBUG, "%s: subtype 0x%x len %d", __func__, stype, 790 (int) len); 791 792 if (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) != 0) { 793 wpa_printf(MSG_DEBUG, "%s: BSSID does not match - ignore", 794 __func__); 795 return; 796 } 797 switch (stype) { 798 case WLAN_FC_STYPE_ASSOC_REQ: 799 if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.assoc_req)) 800 break; 801 ielen = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req)); 802 iebuf = mgmt->u.assoc_req.variable; 803 drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 0); 804 break; 805 case WLAN_FC_STYPE_REASSOC_REQ: 806 if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.reassoc_req)) 807 break; 808 ielen = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req)); 809 iebuf = mgmt->u.reassoc_req.variable; 810 drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1); 811 break; 812 case WLAN_FC_STYPE_ACTION: 813 if (&mgmt->u.action.category > buf + len) 814 break; 815 os_memset(&event, 0, sizeof(event)); 816 event.rx_action.da = mgmt->da; 817 event.rx_action.sa = mgmt->sa; 818 event.rx_action.bssid = mgmt->bssid; 819 event.rx_action.category = mgmt->u.action.category; 820 event.rx_action.data = &mgmt->u.action.category; 821 event.rx_action.len = buf + len - event.rx_action.data; 822 wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event); 823 break; 824 case WLAN_FC_STYPE_AUTH: 825 if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.auth)) 826 break; 827 os_memset(&event, 0, sizeof(event)); 828 os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN); 829 os_memcpy(event.auth.bssid, mgmt->bssid, ETH_ALEN); 830 event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg); 831 event.auth.status_code = 832 le_to_host16(mgmt->u.auth.status_code); 833 event.auth.auth_transaction = 834 le_to_host16(mgmt->u.auth.auth_transaction); 835 event.auth.ies = mgmt->u.auth.variable; 836 event.auth.ies_len = len - IEEE80211_HDRLEN - 837 sizeof(mgmt->u.auth); 838 wpa_supplicant_event(drv->hapd, EVENT_AUTH, &event); 839 break; 840 default: 841 break; 842 } 843} 844#endif /* CONFIG_IEEE80211R */ 845 846#ifdef CONFIG_HS20 847static void atheros_raw_recv_hs20(void *ctx, const u8 *src_addr, const u8 *buf, 848 size_t len) 849{ 850 struct atheros_driver_data *drv = ctx; 851 const struct ieee80211_mgmt *mgmt; 852 u16 fc; 853 union wpa_event_data event; 854 855 /* Send the Action frame for HS20 processing */ 856 857 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.action.category) + 858 sizeof(mgmt->u.action.u.public_action)) 859 return; 860 861 mgmt = (const struct ieee80211_mgmt *) buf; 862 863 fc = le_to_host16(mgmt->frame_control); 864 if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || 865 WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION || 866 mgmt->u.action.category != WLAN_ACTION_PUBLIC) 867 return; 868 869 wpa_printf(MSG_DEBUG, "%s:Received Public Action frame", __func__); 870 871 os_memset(&event, 0, sizeof(event)); 872 event.rx_mgmt.frame = (const u8 *) mgmt; 873 event.rx_mgmt.frame_len = len; 874 wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event); 875} 876#endif /* CONFIG_HS20 */ 877 878#if defined(CONFIG_IEEE80211V) && !defined(CONFIG_IEEE80211R) 879static void atheros_raw_recv_11v(void *ctx, const u8 *src_addr, const u8 *buf, 880 size_t len) 881{ 882 struct atheros_driver_data *drv = ctx; 883 union wpa_event_data event; 884 const struct ieee80211_mgmt *mgmt; 885 u16 fc; 886 u16 stype; 887 888 /* Do 11R processing for WNM ACTION frames */ 889 if (len < IEEE80211_HDRLEN) 890 return; 891 mgmt = (const struct ieee80211_mgmt *) buf; 892 893 fc = le_to_host16(mgmt->frame_control); 894 895 if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) 896 return; 897 stype = WLAN_FC_GET_STYPE(fc); 898 899 wpa_printf(MSG_DEBUG, "%s: subtype 0x%x len %d", __func__, stype, 900 (int) len); 901 902 if (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) != 0) { 903 wpa_printf(MSG_DEBUG, "%s: BSSID does not match - ignore", 904 __func__); 905 return; 906 } 907 908 switch (stype) { 909 case WLAN_FC_STYPE_ACTION: 910 if (&mgmt->u.action.category > buf + len) 911 break; 912 os_memset(&event, 0, sizeof(event)); 913 event.rx_action.da = mgmt->da; 914 event.rx_action.sa = mgmt->sa; 915 event.rx_action.bssid = mgmt->bssid; 916 event.rx_action.category = mgmt->u.action.category; 917 event.rx_action.data = &mgmt->u.action.category; 918 event.rx_action.len = buf + len - event.rx_action.data; 919 wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event); 920 break; 921 default: 922 break; 923 } 924} 925#endif /* CONFIG_IEEE80211V */ 926 927#if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211V) 928static void atheros_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, 929 size_t len) 930{ 931#ifdef CONFIG_WPS 932 atheros_raw_recv_wps(ctx, src_addr, buf, len); 933#endif /* CONFIG_WPS */ 934#ifdef CONFIG_IEEE80211R 935 atheros_raw_recv_11r(ctx, src_addr, buf, len); 936#endif /* CONFIG_IEEE80211R */ 937#if defined(CONFIG_IEEE80211V) && !defined(CONFIG_IEEE80211R) 938 atheros_raw_recv_11v(ctx, src_addr, buf, len); 939#endif /* CONFIG_IEEE80211V */ 940#ifdef CONFIG_HS20 941 atheros_raw_recv_hs20(ctx, src_addr, buf, len); 942#endif /* CONFIG_HS20 */ 943} 944#endif /* CONFIG_WPS || CONFIG_IEEE80211R */ 945 946static int atheros_receive_pkt(struct atheros_driver_data *drv) 947{ 948 int ret = 0; 949 struct ieee80211req_set_filter filt; 950 951 wpa_printf(MSG_DEBUG, "%s Enter", __func__); 952 filt.app_filterype = 0; 953#ifdef CONFIG_WPS 954 filt.app_filterype |= IEEE80211_FILTER_TYPE_PROBE_REQ; 955#endif /* CONFIG_WPS */ 956#ifdef CONFIG_IEEE80211R 957 filt.app_filterype |= (IEEE80211_FILTER_TYPE_ASSOC_REQ | 958 IEEE80211_FILTER_TYPE_AUTH | 959 IEEE80211_FILTER_TYPE_ACTION); 960#endif 961#ifdef CONFIG_IEEE80211V 962 filt.app_filterype |= IEEE80211_FILTER_TYPE_ACTION; 963#endif /* CONFIG_IEEE80211V */ 964#ifdef CONFIG_HS20 965 filt.app_filterype |= IEEE80211_FILTER_TYPE_ACTION; 966#endif /* CONFIG_HS20 */ 967 if (filt.app_filterype) { 968 ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt, 969 sizeof(struct ieee80211req_set_filter)); 970 if (ret) 971 return ret; 972 } 973 974#if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R) 975 drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW, 976 atheros_raw_receive, drv, 1); 977 if (drv->sock_raw == NULL) 978 return -1; 979#endif /* CONFIG_WPS || CONFIG_IEEE80211R */ 980 if (l2_packet_get_own_addr(drv->sock_xmit, drv->own_addr)) 981 return -1; 982 return ret; 983} 984 985static int atheros_reset_appfilter(struct atheros_driver_data *drv) 986{ 987 struct ieee80211req_set_filter filt; 988 filt.app_filterype = 0; 989 return set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt, 990 sizeof(struct ieee80211req_set_filter)); 991} 992 993#ifdef CONFIG_WPS 994static int 995atheros_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype) 996{ 997 struct atheros_driver_data *drv = priv; 998 u8 buf[512]; 999 struct ieee80211req_getset_appiebuf *beac_ie; 1000 1001 wpa_printf(MSG_DEBUG, "%s buflen = %lu frametype=%u", __func__, 1002 (unsigned long) len, frametype); 1003 wpa_hexdump(MSG_DEBUG, "atheros: IE", ie, len); 1004 1005 beac_ie = (struct ieee80211req_getset_appiebuf *) buf; 1006 beac_ie->app_frmtype = frametype; 1007 beac_ie->app_buflen = len; 1008 os_memcpy(&(beac_ie->app_buf[0]), ie, len); 1009 1010 /* append the WPA/RSN IE if it is set already */ 1011 if (((frametype == IEEE80211_APPIE_FRAME_BEACON) || 1012 (frametype == IEEE80211_APPIE_FRAME_PROBE_RESP)) && 1013 (drv->wpa_ie != NULL)) { 1014 wpa_hexdump_buf(MSG_DEBUG, "atheros: Append WPA/RSN IE", 1015 drv->wpa_ie); 1016 os_memcpy(&(beac_ie->app_buf[len]), wpabuf_head(drv->wpa_ie), 1017 wpabuf_len(drv->wpa_ie)); 1018 beac_ie->app_buflen += wpabuf_len(drv->wpa_ie); 1019 } 1020 1021 wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF", 1022 beac_ie->app_buf, beac_ie->app_buflen); 1023 return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie, 1024 sizeof(struct ieee80211req_getset_appiebuf) + 1025 beac_ie->app_buflen); 1026} 1027 1028static int 1029atheros_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, 1030 const struct wpabuf *proberesp, 1031 const struct wpabuf *assocresp) 1032{ 1033 struct atheros_driver_data *drv = priv; 1034 1035 wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - beacon", beacon); 1036 wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - proberesp", 1037 proberesp); 1038 wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - assocresp", 1039 assocresp); 1040 wpabuf_free(drv->wps_beacon_ie); 1041 drv->wps_beacon_ie = beacon ? wpabuf_dup(beacon) : NULL; 1042 wpabuf_free(drv->wps_probe_resp_ie); 1043 drv->wps_probe_resp_ie = proberesp ? wpabuf_dup(proberesp) : NULL; 1044 1045 atheros_set_wps_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL, 1046 assocresp ? wpabuf_len(assocresp) : 0, 1047 IEEE80211_APPIE_FRAME_ASSOC_RESP); 1048 if (atheros_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL, 1049 beacon ? wpabuf_len(beacon) : 0, 1050 IEEE80211_APPIE_FRAME_BEACON)) 1051 return -1; 1052 return atheros_set_wps_ie(priv, 1053 proberesp ? wpabuf_head(proberesp) : NULL, 1054 proberesp ? wpabuf_len(proberesp): 0, 1055 IEEE80211_APPIE_FRAME_PROBE_RESP); 1056} 1057#else /* CONFIG_WPS */ 1058#define atheros_set_ap_wps_ie NULL 1059#endif /* CONFIG_WPS */ 1060 1061#ifdef CONFIG_IEEE80211R 1062static int 1063atheros_sta_auth(void *priv, const u8 *own_addr, const u8 *addr, u16 seq, 1064 u16 status_code, const u8 *ie, size_t len) 1065{ 1066 struct atheros_driver_data *drv = priv; 1067 struct ieee80211req_mlme mlme; 1068 int ret; 1069 1070 wpa_printf(MSG_DEBUG, "%s: addr=%s status_code=%d", 1071 __func__, ether_sprintf(addr), status_code); 1072 1073 mlme.im_op = IEEE80211_MLME_AUTH; 1074 mlme.im_reason = status_code; 1075 mlme.im_seq = seq; 1076 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 1077 mlme.im_optie_len = len; 1078 if (len) { 1079 if (len < IEEE80211_MAX_OPT_IE) { 1080 os_memcpy(mlme.im_optie, ie, len); 1081 } else { 1082 wpa_printf(MSG_DEBUG, "%s: Not enough space to copy " 1083 "opt_ie STA (addr " MACSTR " reason %d, " 1084 "ie_len %d)", 1085 __func__, MAC2STR(addr), status_code, 1086 (int) len); 1087 return -1; 1088 } 1089 } 1090 ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); 1091 if (ret < 0) { 1092 wpa_printf(MSG_DEBUG, "%s: Failed to auth STA (addr " MACSTR 1093 " reason %d)", 1094 __func__, MAC2STR(addr), status_code); 1095 } 1096 return ret; 1097} 1098 1099static int 1100atheros_sta_assoc(void *priv, const u8 *own_addr, const u8 *addr, 1101 int reassoc, u16 status_code, const u8 *ie, size_t len) 1102{ 1103 struct atheros_driver_data *drv = priv; 1104 struct ieee80211req_mlme mlme; 1105 int ret; 1106 1107 wpa_printf(MSG_DEBUG, "%s: addr=%s status_code=%d reassoc %d", 1108 __func__, ether_sprintf(addr), status_code, reassoc); 1109 1110 if (reassoc) 1111 mlme.im_op = IEEE80211_MLME_REASSOC; 1112 else 1113 mlme.im_op = IEEE80211_MLME_ASSOC; 1114 mlme.im_reason = status_code; 1115 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 1116 mlme.im_optie_len = len; 1117 if (len) { 1118 if (len < IEEE80211_MAX_OPT_IE) { 1119 os_memcpy(mlme.im_optie, ie, len); 1120 } else { 1121 wpa_printf(MSG_DEBUG, "%s: Not enough space to copy " 1122 "opt_ie STA (addr " MACSTR " reason %d, " 1123 "ie_len %d)", 1124 __func__, MAC2STR(addr), status_code, 1125 (int) len); 1126 return -1; 1127 } 1128 } 1129 ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); 1130 if (ret < 0) { 1131 wpa_printf(MSG_DEBUG, "%s: Failed to assoc STA (addr " MACSTR 1132 " reason %d)", 1133 __func__, MAC2STR(addr), status_code); 1134 } 1135 return ret; 1136} 1137#endif /* CONFIG_IEEE80211R */ 1138 1139static void 1140atheros_new_sta(struct atheros_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) 1141{ 1142 struct hostapd_data *hapd = drv->hapd; 1143 struct ieee80211req_wpaie ie; 1144 int ielen = 0; 1145 u8 *iebuf = NULL; 1146 1147 /* 1148 * Fetch negotiated WPA/RSN parameters from the system. 1149 */ 1150 memset(&ie, 0, sizeof(ie)); 1151 memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); 1152 if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) { 1153 /* 1154 * See ATH_WPS_IE comment in the beginning of the file for a 1155 * possible cause for the failure.. 1156 */ 1157 wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s", 1158 __func__, strerror(errno)); 1159 goto no_ie; 1160 } 1161 wpa_hexdump(MSG_MSGDUMP, "atheros req WPA IE", 1162 ie.wpa_ie, IEEE80211_MAX_OPT_IE); 1163 wpa_hexdump(MSG_MSGDUMP, "atheros req RSN IE", 1164 ie.rsn_ie, IEEE80211_MAX_OPT_IE); 1165#ifdef ATH_WPS_IE 1166 wpa_hexdump(MSG_MSGDUMP, "atheros req WPS IE", 1167 ie.wps_ie, IEEE80211_MAX_OPT_IE); 1168#endif /* ATH_WPS_IE */ 1169 iebuf = ie.wpa_ie; 1170 /* atheros seems to return some random data if WPA/RSN IE is not set. 1171 * Assume the IE was not included if the IE type is unknown. */ 1172 if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC) 1173 iebuf[1] = 0; 1174 if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) { 1175 /* atheros-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not 1176 * set. This is needed for WPA2. */ 1177 iebuf = ie.rsn_ie; 1178 if (iebuf[0] != WLAN_EID_RSN) 1179 iebuf[1] = 0; 1180 } 1181 1182 ielen = iebuf[1]; 1183 1184#ifdef ATH_WPS_IE 1185 /* if WPS IE is present, preference is given to WPS */ 1186 if (ie.wps_ie && 1187 (ie.wps_ie[1] > 0 && (ie.wps_ie[0] == WLAN_EID_VENDOR_SPECIFIC))) { 1188 iebuf = ie.wps_ie; 1189 ielen = ie.wps_ie[1]; 1190 } 1191#endif /* ATH_WPS_IE */ 1192 1193 if (ielen == 0) 1194 iebuf = NULL; 1195 else 1196 ielen += 2; 1197 1198no_ie: 1199 drv_event_assoc(hapd, addr, iebuf, ielen, 0); 1200 1201 if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { 1202 /* Cached accounting data is not valid anymore. */ 1203 memset(drv->acct_mac, 0, ETH_ALEN); 1204 memset(&drv->acct_data, 0, sizeof(drv->acct_data)); 1205 } 1206} 1207 1208static void 1209atheros_wireless_event_wireless_custom(struct atheros_driver_data *drv, 1210 char *custom, char *end) 1211{ 1212 wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); 1213 1214 if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { 1215 char *pos; 1216 u8 addr[ETH_ALEN]; 1217 pos = strstr(custom, "addr="); 1218 if (pos == NULL) { 1219 wpa_printf(MSG_DEBUG, 1220 "MLME-MICHAELMICFAILURE.indication " 1221 "without sender address ignored"); 1222 return; 1223 } 1224 pos += 5; 1225 if (hwaddr_aton(pos, addr) == 0) { 1226 union wpa_event_data data; 1227 os_memset(&data, 0, sizeof(data)); 1228 data.michael_mic_failure.unicast = 1; 1229 data.michael_mic_failure.src = addr; 1230 wpa_supplicant_event(drv->hapd, 1231 EVENT_MICHAEL_MIC_FAILURE, &data); 1232 } else { 1233 wpa_printf(MSG_DEBUG, 1234 "MLME-MICHAELMICFAILURE.indication " 1235 "with invalid MAC address"); 1236 } 1237 } else if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) { 1238 char *key, *value; 1239 u32 val; 1240 key = custom; 1241 while ((key = strchr(key, '\n')) != NULL) { 1242 key++; 1243 value = strchr(key, '='); 1244 if (value == NULL) 1245 continue; 1246 *value++ = '\0'; 1247 val = strtoul(value, NULL, 10); 1248 if (strcmp(key, "mac") == 0) 1249 hwaddr_aton(value, drv->acct_mac); 1250 else if (strcmp(key, "rx_packets") == 0) 1251 drv->acct_data.rx_packets = val; 1252 else if (strcmp(key, "tx_packets") == 0) 1253 drv->acct_data.tx_packets = val; 1254 else if (strcmp(key, "rx_bytes") == 0) 1255 drv->acct_data.rx_bytes = val; 1256 else if (strcmp(key, "tx_bytes") == 0) 1257 drv->acct_data.tx_bytes = val; 1258 key = value; 1259 } 1260#ifdef CONFIG_WPS 1261 } else if (strncmp(custom, "PUSH-BUTTON.indication", 22) == 0) { 1262 /* Some atheros kernels send push button as a wireless event */ 1263 /* PROBLEM! this event is received for ALL BSSs ... 1264 * so all are enabled for WPS... ugh. 1265 */ 1266 wpa_supplicant_event(drv->hapd, EVENT_WPS_BUTTON_PUSHED, NULL); 1267#endif /* CONFIG_WPS */ 1268#if defined(CONFIG_WPS) || defined(CONFIG_IEEE80211R) || defined(CONFIG_HS20) 1269#define MGMT_FRAM_TAG_SIZE 30 /* hardcoded in driver */ 1270 } else if (strncmp(custom, "Manage.prob_req ", 16) == 0) { 1271 /* 1272 * Atheros driver uses a hack to pass Probe Request frames as a 1273 * binary data in the custom wireless event. The old way (using 1274 * packet sniffing) didn't work when bridging. 1275 * Format: "Manage.prob_req <frame len>" | zero padding | frame 1276 */ 1277 int len = atoi(custom + 16); 1278 if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) { 1279 wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req event " 1280 "length %d", len); 1281 return; 1282 } 1283 atheros_raw_receive(drv, NULL, 1284 (u8 *) custom + MGMT_FRAM_TAG_SIZE, len); 1285 } else if (strncmp(custom, "Manage.assoc_req ", 17) == 0) { 1286 /* Format: "Manage.assoc_req <frame len>" | zero padding | 1287 * frame */ 1288 int len = atoi(custom + 17); 1289 if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) { 1290 wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req/" 1291 "assoc_req/auth event length %d", len); 1292 return; 1293 } 1294 atheros_raw_receive(drv, NULL, 1295 (u8 *) custom + MGMT_FRAM_TAG_SIZE, len); 1296 } else if (strncmp(custom, "Manage.action ", 14) == 0) { 1297 /* Format: "Manage.assoc_req <frame len>" | zero padding | 1298 * frame */ 1299 int len = atoi(custom + 14); 1300 if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) { 1301 wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req/" 1302 "assoc_req/auth event length %d", len); 1303 return; 1304 } 1305 atheros_raw_receive(drv, NULL, 1306 (u8 *) custom + MGMT_FRAM_TAG_SIZE, len); 1307 } else if (strncmp(custom, "Manage.auth ", 12) == 0) { 1308 /* Format: "Manage.auth <frame len>" | zero padding | frame 1309 */ 1310 int len = atoi(custom + 12); 1311 if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) { 1312 wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req/" 1313 "assoc_req/auth event length %d", len); 1314 return; 1315 } 1316 atheros_raw_receive(drv, NULL, 1317 (u8 *) custom + MGMT_FRAM_TAG_SIZE, len); 1318#endif /* CONFIG_WPS or CONFIG_IEEE80211R */ 1319 } 1320} 1321 1322/* 1323* Handle size of data problem. WEXT only allows data of 256 bytes for custom 1324* events, and p2p data can be much bigger. So the athr driver sends a small 1325* event telling me to collect the big data with an ioctl. 1326* On the first event, send all pending events to supplicant. 1327*/ 1328static void fetch_pending_big_events(struct atheros_driver_data *drv) 1329{ 1330 union wpa_event_data event; 1331 const struct ieee80211_mgmt *mgmt; 1332 u8 tbuf[IW_PRIV_SIZE_MASK]; /* max size is 2047 bytes */ 1333 u16 fc, stype; 1334 struct iwreq iwr; 1335 size_t data_len; 1336 u32 freq, frame_type; 1337 1338 while (1) { 1339 os_memset(&iwr, 0, sizeof(iwr)); 1340 os_strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 1341 1342 iwr.u.data.pointer = (void *) tbuf; 1343 iwr.u.data.length = sizeof(tbuf); 1344 iwr.u.data.flags = IEEE80211_IOC_P2P_FETCH_FRAME; 1345 1346 if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_P2P_BIG_PARAM, &iwr) 1347 < 0) { 1348 if (errno == ENOSPC) { 1349 wpa_printf(MSG_DEBUG, "%s:%d exit", 1350 __func__, __LINE__); 1351 return; 1352 } 1353 wpa_printf(MSG_DEBUG, "athr: %s: P2P_BIG_PARAM[" 1354 "P2P_FETCH_FRAME] failed: %s", 1355 __func__, strerror(errno)); 1356 return; 1357 } 1358 data_len = iwr.u.data.length; 1359 wpa_hexdump(MSG_DEBUG, "athr: P2P_FETCH_FRAME data", 1360 (u8 *) tbuf, data_len); 1361 if (data_len < sizeof(freq) + sizeof(frame_type) + 24) { 1362 wpa_printf(MSG_DEBUG, "athr: frame too short"); 1363 continue; 1364 } 1365 os_memcpy(&freq, tbuf, sizeof(freq)); 1366 os_memcpy(&frame_type, &tbuf[sizeof(freq)], 1367 sizeof(frame_type)); 1368 mgmt = (void *) &tbuf[sizeof(freq) + sizeof(frame_type)]; 1369 data_len -= sizeof(freq) + sizeof(frame_type); 1370 1371 if (frame_type == IEEE80211_EV_RX_MGMT) { 1372 fc = le_to_host16(mgmt->frame_control); 1373 stype = WLAN_FC_GET_STYPE(fc); 1374 1375 wpa_printf(MSG_DEBUG, "athr: EV_RX_MGMT stype=%u " 1376 "freq=%u len=%u", stype, freq, (int) data_len); 1377 1378 if (stype == WLAN_FC_STYPE_ACTION) { 1379 os_memset(&event, 0, sizeof(event)); 1380 event.rx_mgmt.frame = (const u8 *) mgmt; 1381 event.rx_mgmt.frame_len = data_len; 1382 wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, 1383 &event); 1384 continue; 1385 } 1386 } else { 1387 wpa_printf(MSG_DEBUG, "athr: %s unknown type %d", 1388 __func__, frame_type); 1389 continue; 1390 } 1391 } 1392} 1393 1394static void 1395atheros_wireless_event_atheros_custom(struct atheros_driver_data *drv, 1396 int opcode, char *buf, int len) 1397{ 1398 switch (opcode) { 1399 case IEEE80211_EV_RX_MGMT: 1400 wpa_printf(MSG_DEBUG, "WEXT: EV_RX_MGMT"); 1401 fetch_pending_big_events(drv); 1402 break; 1403 default: 1404 break; 1405 } 1406} 1407 1408static void 1409atheros_wireless_event_wireless(struct atheros_driver_data *drv, 1410 char *data, int len) 1411{ 1412 struct iw_event iwe_buf, *iwe = &iwe_buf; 1413 char *pos, *end, *custom, *buf; 1414 1415 pos = data; 1416 end = data + len; 1417 1418 while (pos + IW_EV_LCP_LEN <= end) { 1419 /* Event data may be unaligned, so make a local, aligned copy 1420 * before processing. */ 1421 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 1422 wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d", 1423 iwe->cmd, iwe->len); 1424 if (iwe->len <= IW_EV_LCP_LEN) 1425 return; 1426 1427 custom = pos + IW_EV_POINT_LEN; 1428 if (drv->we_version > 18 && 1429 (iwe->cmd == IWEVMICHAELMICFAILURE || 1430 iwe->cmd == IWEVASSOCREQIE || 1431 iwe->cmd == IWEVCUSTOM)) { 1432 /* WE-19 removed the pointer from struct iw_point */ 1433 char *dpos = (char *) &iwe_buf.u.data.length; 1434 int dlen = dpos - (char *) &iwe_buf; 1435 memcpy(dpos, pos + IW_EV_LCP_LEN, 1436 sizeof(struct iw_event) - dlen); 1437 } else { 1438 memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 1439 custom += IW_EV_POINT_OFF; 1440 } 1441 1442 switch (iwe->cmd) { 1443 case IWEVEXPIRED: 1444 drv_event_disassoc(drv->hapd, 1445 (u8 *) iwe->u.addr.sa_data); 1446 break; 1447 case IWEVREGISTERED: 1448 atheros_new_sta(drv, (u8 *) iwe->u.addr.sa_data); 1449 break; 1450 case IWEVASSOCREQIE: 1451 /* Driver hack.. Use IWEVASSOCREQIE to bypass 1452 * IWEVCUSTOM size limitations. Need to handle this 1453 * just like IWEVCUSTOM. 1454 */ 1455 case IWEVCUSTOM: 1456 if (custom + iwe->u.data.length > end) 1457 return; 1458 buf = malloc(iwe->u.data.length + 1); 1459 if (buf == NULL) 1460 return; /* XXX */ 1461 memcpy(buf, custom, iwe->u.data.length); 1462 buf[iwe->u.data.length] = '\0'; 1463 1464 if (iwe->u.data.flags != 0) { 1465 atheros_wireless_event_atheros_custom( 1466 drv, (int) iwe->u.data.flags, 1467 buf, len); 1468 } else { 1469 atheros_wireless_event_wireless_custom( 1470 drv, buf, buf + iwe->u.data.length); 1471 } 1472 free(buf); 1473 break; 1474 } 1475 1476 pos += iwe->len; 1477 } 1478} 1479 1480 1481static void 1482atheros_wireless_event_rtm_newlink(void *ctx, 1483 struct ifinfomsg *ifi, u8 *buf, size_t len) 1484{ 1485 struct atheros_driver_data *drv = ctx; 1486 int attrlen, rta_len; 1487 struct rtattr *attr; 1488 1489 if (ifi->ifi_index != drv->ifindex) 1490 return; 1491 1492 attrlen = len; 1493 attr = (struct rtattr *) buf; 1494 1495 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 1496 while (RTA_OK(attr, attrlen)) { 1497 if (attr->rta_type == IFLA_WIRELESS) { 1498 atheros_wireless_event_wireless( 1499 drv, ((char *) attr) + rta_len, 1500 attr->rta_len - rta_len); 1501 } 1502 attr = RTA_NEXT(attr, attrlen); 1503 } 1504} 1505 1506 1507static int 1508atheros_get_we_version(struct atheros_driver_data *drv) 1509{ 1510 struct iw_range *range; 1511 struct iwreq iwr; 1512 int minlen; 1513 size_t buflen; 1514 1515 drv->we_version = 0; 1516 1517 /* 1518 * Use larger buffer than struct iw_range in order to allow the 1519 * structure to grow in the future. 1520 */ 1521 buflen = sizeof(struct iw_range) + 500; 1522 range = os_zalloc(buflen); 1523 if (range == NULL) 1524 return -1; 1525 1526 memset(&iwr, 0, sizeof(iwr)); 1527 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 1528 iwr.u.data.pointer = (caddr_t) range; 1529 iwr.u.data.length = buflen; 1530 1531 minlen = ((char *) &range->enc_capa) - (char *) range + 1532 sizeof(range->enc_capa); 1533 1534 if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { 1535 perror("ioctl[SIOCGIWRANGE]"); 1536 free(range); 1537 return -1; 1538 } else if (iwr.u.data.length >= minlen && 1539 range->we_version_compiled >= 18) { 1540 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " 1541 "WE(source)=%d enc_capa=0x%x", 1542 range->we_version_compiled, 1543 range->we_version_source, 1544 range->enc_capa); 1545 drv->we_version = range->we_version_compiled; 1546 } 1547 1548 os_free(range); 1549 return 0; 1550} 1551 1552 1553static int 1554atheros_wireless_event_init(struct atheros_driver_data *drv) 1555{ 1556 struct netlink_config *cfg; 1557 1558 atheros_get_we_version(drv); 1559 1560 cfg = os_zalloc(sizeof(*cfg)); 1561 if (cfg == NULL) 1562 return -1; 1563 cfg->ctx = drv; 1564 cfg->newlink_cb = atheros_wireless_event_rtm_newlink; 1565 drv->netlink = netlink_init(cfg); 1566 if (drv->netlink == NULL) { 1567 os_free(cfg); 1568 return -1; 1569 } 1570 1571 return 0; 1572} 1573 1574 1575static int 1576atheros_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, 1577 int encrypt, const u8 *own_addr, u32 flags) 1578{ 1579 struct atheros_driver_data *drv = priv; 1580 unsigned char buf[3000]; 1581 unsigned char *bp = buf; 1582 struct l2_ethhdr *eth; 1583 size_t len; 1584 int status; 1585 1586 /* 1587 * Prepend the Ethernet header. If the caller left us 1588 * space at the front we could just insert it but since 1589 * we don't know we copy to a local buffer. Given the frequency 1590 * and size of frames this probably doesn't matter. 1591 */ 1592 len = data_len + sizeof(struct l2_ethhdr); 1593 if (len > sizeof(buf)) { 1594 bp = malloc(len); 1595 if (bp == NULL) { 1596 printf("EAPOL frame discarded, cannot malloc temp " 1597 "buffer of size %lu!\n", (unsigned long) len); 1598 return -1; 1599 } 1600 } 1601 eth = (struct l2_ethhdr *) bp; 1602 memcpy(eth->h_dest, addr, ETH_ALEN); 1603 memcpy(eth->h_source, own_addr, ETH_ALEN); 1604 eth->h_proto = host_to_be16(ETH_P_EAPOL); 1605 memcpy(eth+1, data, data_len); 1606 1607 wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); 1608 1609 status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); 1610 1611 if (bp != buf) 1612 free(bp); 1613 return status; 1614} 1615 1616static void 1617handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) 1618{ 1619 struct atheros_driver_data *drv = ctx; 1620 drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr), 1621 len - sizeof(struct l2_ethhdr)); 1622} 1623 1624static void * 1625atheros_init(struct hostapd_data *hapd, struct wpa_init_params *params) 1626{ 1627 struct atheros_driver_data *drv; 1628 struct ifreq ifr; 1629 struct iwreq iwr; 1630 char brname[IFNAMSIZ]; 1631 1632 drv = os_zalloc(sizeof(struct atheros_driver_data)); 1633 if (drv == NULL) { 1634 printf("Could not allocate memory for atheros driver data\n"); 1635 return NULL; 1636 } 1637 1638 drv->hapd = hapd; 1639 drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); 1640 if (drv->ioctl_sock < 0) { 1641 perror("socket[PF_INET,SOCK_DGRAM]"); 1642 goto bad; 1643 } 1644 memcpy(drv->iface, params->ifname, sizeof(drv->iface)); 1645 1646 memset(&ifr, 0, sizeof(ifr)); 1647 os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); 1648 if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { 1649 perror("ioctl(SIOCGIFINDEX)"); 1650 goto bad; 1651 } 1652 drv->ifindex = ifr.ifr_ifindex; 1653 1654 drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, 1655 handle_read, drv, 1); 1656 if (drv->sock_xmit == NULL) 1657 goto bad; 1658 if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) 1659 goto bad; 1660 if (params->bridge[0]) { 1661 wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.", 1662 params->bridge[0]); 1663 drv->sock_recv = l2_packet_init(params->bridge[0], NULL, 1664 ETH_P_EAPOL, handle_read, drv, 1665 1); 1666 if (drv->sock_recv == NULL) 1667 goto bad; 1668 } else if (linux_br_get(brname, drv->iface) == 0) { 1669 wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for " 1670 "EAPOL receive", brname); 1671 drv->sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL, 1672 handle_read, drv, 1); 1673 if (drv->sock_recv == NULL) 1674 goto bad; 1675 } else 1676 drv->sock_recv = drv->sock_xmit; 1677 1678 memset(&iwr, 0, sizeof(iwr)); 1679 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 1680 1681 iwr.u.mode = IW_MODE_MASTER; 1682 1683 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { 1684 perror("ioctl[SIOCSIWMODE]"); 1685 printf("Could not set interface to master mode!\n"); 1686 goto bad; 1687 } 1688 1689 /* mark down during setup */ 1690 linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0); 1691 atheros_set_privacy(drv, 0); /* default to no privacy */ 1692 1693 atheros_receive_pkt(drv); 1694 1695 if (atheros_wireless_event_init(drv)) 1696 goto bad; 1697 1698 return drv; 1699bad: 1700 if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) 1701 l2_packet_deinit(drv->sock_recv); 1702 if (drv->sock_xmit != NULL) 1703 l2_packet_deinit(drv->sock_xmit); 1704 if (drv->ioctl_sock >= 0) 1705 close(drv->ioctl_sock); 1706 if (drv != NULL) 1707 free(drv); 1708 return NULL; 1709} 1710 1711 1712static void 1713atheros_deinit(void *priv) 1714{ 1715 struct atheros_driver_data *drv = priv; 1716 1717 atheros_reset_appfilter(drv); 1718 netlink_deinit(drv->netlink); 1719 (void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0); 1720 if (drv->ioctl_sock >= 0) 1721 close(drv->ioctl_sock); 1722 if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) 1723 l2_packet_deinit(drv->sock_recv); 1724 if (drv->sock_xmit != NULL) 1725 l2_packet_deinit(drv->sock_xmit); 1726 if (drv->sock_raw) 1727 l2_packet_deinit(drv->sock_raw); 1728 wpabuf_free(drv->wpa_ie); 1729 wpabuf_free(drv->wps_beacon_ie); 1730 wpabuf_free(drv->wps_probe_resp_ie); 1731 free(drv); 1732} 1733 1734static int 1735atheros_set_ssid(void *priv, const u8 *buf, int len) 1736{ 1737 struct atheros_driver_data *drv = priv; 1738 struct iwreq iwr; 1739 1740 memset(&iwr, 0, sizeof(iwr)); 1741 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 1742 iwr.u.essid.flags = 1; /* SSID active */ 1743 iwr.u.essid.pointer = (caddr_t) buf; 1744 iwr.u.essid.length = len + 1; 1745 1746 if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { 1747 perror("ioctl[SIOCSIWESSID]"); 1748 printf("len=%d\n", len); 1749 return -1; 1750 } 1751 return 0; 1752} 1753 1754static int 1755atheros_get_ssid(void *priv, u8 *buf, int len) 1756{ 1757 struct atheros_driver_data *drv = priv; 1758 struct iwreq iwr; 1759 int ret = 0; 1760 1761 memset(&iwr, 0, sizeof(iwr)); 1762 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 1763 iwr.u.essid.pointer = (caddr_t) buf; 1764 iwr.u.essid.length = (len > IW_ESSID_MAX_SIZE) ? 1765 IW_ESSID_MAX_SIZE : len; 1766 1767 if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { 1768 perror("ioctl[SIOCGIWESSID]"); 1769 ret = -1; 1770 } else 1771 ret = iwr.u.essid.length; 1772 1773 return ret; 1774} 1775 1776static int 1777atheros_set_countermeasures(void *priv, int enabled) 1778{ 1779 struct atheros_driver_data *drv = priv; 1780 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); 1781 return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled); 1782} 1783 1784static int 1785atheros_commit(void *priv) 1786{ 1787 struct atheros_driver_data *drv = priv; 1788 return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1); 1789} 1790 1791static int atheros_set_authmode(void *priv, int auth_algs) 1792{ 1793 int authmode; 1794 1795 if ((auth_algs & WPA_AUTH_ALG_OPEN) && 1796 (auth_algs & WPA_AUTH_ALG_SHARED)) 1797 authmode = IEEE80211_AUTH_AUTO; 1798 else if (auth_algs & WPA_AUTH_ALG_OPEN) 1799 authmode = IEEE80211_AUTH_OPEN; 1800 else if (auth_algs & WPA_AUTH_ALG_SHARED) 1801 authmode = IEEE80211_AUTH_SHARED; 1802 else 1803 return -1; 1804 1805 return set80211param(priv, IEEE80211_PARAM_AUTHMODE, authmode); 1806} 1807 1808static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params) 1809{ 1810 /* 1811 * TODO: Use this to replace set_authmode, set_privacy, set_ieee8021x, 1812 * set_generic_elem, and hapd_set_ssid. 1813 */ 1814 1815 wpa_printf(MSG_DEBUG, "atheros: set_ap - pairwise_ciphers=0x%x " 1816 "group_cipher=0x%x key_mgmt_suites=0x%x auth_algs=0x%x " 1817 "wpa_version=0x%x privacy=%d interworking=%d", 1818 params->pairwise_ciphers, params->group_cipher, 1819 params->key_mgmt_suites, params->auth_algs, 1820 params->wpa_version, params->privacy, params->interworking); 1821 wpa_hexdump_ascii(MSG_DEBUG, "atheros: SSID", 1822 params->ssid, params->ssid_len); 1823 if (params->hessid) 1824 wpa_printf(MSG_DEBUG, "atheros: HESSID " MACSTR, 1825 MAC2STR(params->hessid)); 1826 wpa_hexdump_buf(MSG_DEBUG, "atheros: beacon_ies", 1827 params->beacon_ies); 1828 wpa_hexdump_buf(MSG_DEBUG, "atheros: proberesp_ies", 1829 params->proberesp_ies); 1830 wpa_hexdump_buf(MSG_DEBUG, "atheros: assocresp_ies", 1831 params->assocresp_ies); 1832 1833 return 0; 1834} 1835 1836 1837#ifdef CONFIG_IEEE80211R 1838 1839static int atheros_send_mgmt(void *priv, const u8 *frm, size_t data_len, 1840 int noack) 1841{ 1842 struct atheros_driver_data *drv = priv; 1843 u8 buf[1510]; 1844 const struct ieee80211_mgmt *mgmt; 1845 struct ieee80211req_mgmtbuf *mgmt_frm; 1846 1847 mgmt = (const struct ieee80211_mgmt *) frm; 1848 wpa_printf(MSG_DEBUG, "%s frmlen = %lu " MACSTR, __func__, 1849 (unsigned long) data_len, MAC2STR(mgmt->da)); 1850 mgmt_frm = (struct ieee80211req_mgmtbuf *) buf; 1851 memcpy(mgmt_frm->macaddr, (u8 *)mgmt->da, IEEE80211_ADDR_LEN); 1852 mgmt_frm->buflen = data_len; 1853 if (&mgmt_frm->buf[0] + data_len > buf + sizeof(buf)) { 1854 wpa_printf(MSG_INFO, "atheros: Too long frame for " 1855 "atheros_send_mgmt (%u)", (unsigned int) data_len); 1856 return -1; 1857 } 1858 os_memcpy(&mgmt_frm->buf[0], frm, data_len); 1859 return set80211priv(drv, IEEE80211_IOCTL_SEND_MGMT, mgmt_frm, 1860 sizeof(struct ieee80211req_mgmtbuf) + data_len); 1861} 1862 1863 1864static int atheros_add_tspec(void *priv, const u8 *addr, u8 *tspec_ie, 1865 size_t tspec_ielen) 1866{ 1867 struct atheros_driver_data *drv = priv; 1868 int retv; 1869 struct ieee80211req_res req; 1870 struct ieee80211req_res_addts *addts = &req.u.addts; 1871 1872 wpa_printf(MSG_DEBUG, "%s", __func__); 1873 req.type = IEEE80211_RESREQ_ADDTS; 1874 os_memcpy(&req.macaddr[0], addr, IEEE80211_ADDR_LEN); 1875 os_memcpy(addts->tspecie, tspec_ie, tspec_ielen); 1876 retv = set80211priv(drv, IEEE80211_IOCTL_RES_REQ, &req, 1877 sizeof(struct ieee80211req_res)); 1878 if (retv < 0) { 1879 wpa_printf(MSG_DEBUG, "%s IEEE80211_IOCTL_RES_REQ FAILED " 1880 "retv = %d", __func__, retv); 1881 return -1; 1882 } 1883 os_memcpy(tspec_ie, addts->tspecie, tspec_ielen); 1884 return addts->status; 1885} 1886 1887 1888static int atheros_add_sta_node(void *priv, const u8 *addr, u16 auth_alg) 1889{ 1890 struct atheros_driver_data *drv = priv; 1891 struct ieee80211req_res req; 1892 struct ieee80211req_res_addnode *addnode = &req.u.addnode; 1893 1894 wpa_printf(MSG_DEBUG, "%s", __func__); 1895 req.type = IEEE80211_RESREQ_ADDNODE; 1896 os_memcpy(&req.macaddr[0], addr, IEEE80211_ADDR_LEN); 1897 addnode->auth_alg = auth_alg; 1898 return set80211priv(drv, IEEE80211_IOCTL_RES_REQ, &req, 1899 sizeof(struct ieee80211req_res)); 1900} 1901 1902#endif /* CONFIG_IEEE80211R */ 1903 1904 1905/* Use only to set a big param, get will not work. */ 1906static int 1907set80211big(struct atheros_driver_data *drv, int op, const void *data, int len) 1908{ 1909 struct iwreq iwr; 1910 1911 os_memset(&iwr, 0, sizeof(iwr)); 1912 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); 1913 1914 iwr.u.data.pointer = (void *) data; 1915 iwr.u.data.length = len; 1916 iwr.u.data.flags = op; 1917 wpa_printf(MSG_DEBUG, "%s: op=0x%x=%d (%s) len=0x%x", 1918 __func__, op, op, athr_get_param_name(op), len); 1919 1920 if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_P2P_BIG_PARAM, &iwr) < 0) { 1921 wpa_printf(MSG_DEBUG, "%s: op=0x%x (%s) subop=0x%x=%d " 1922 "value=0x%x,0x%x failed: %d (%s)", 1923 __func__, op, athr_get_ioctl_name(op), iwr.u.mode, 1924 iwr.u.mode, iwr.u.data.length, 1925 iwr.u.data.flags, errno, strerror(errno)); 1926 return -1; 1927 } 1928 return 0; 1929} 1930 1931 1932static int atheros_send_action(void *priv, unsigned int freq, 1933 unsigned int wait, 1934 const u8 *dst, const u8 *src, 1935 const u8 *bssid, 1936 const u8 *data, size_t data_len, int no_cck) 1937{ 1938 struct atheros_driver_data *drv = priv; 1939 struct ieee80211_p2p_send_action *act; 1940 int res; 1941 1942 act = os_zalloc(sizeof(*act) + data_len); 1943 if (act == NULL) 1944 return -1; 1945 act->freq = freq; 1946 os_memcpy(act->dst_addr, dst, ETH_ALEN); 1947 os_memcpy(act->src_addr, src, ETH_ALEN); 1948 os_memcpy(act->bssid, bssid, ETH_ALEN); 1949 os_memcpy(act + 1, data, data_len); 1950 wpa_printf(MSG_DEBUG, "%s: freq=%d, wait=%u, dst=" MACSTR ", src=" 1951 MACSTR ", bssid=" MACSTR, 1952 __func__, act->freq, wait, MAC2STR(act->dst_addr), 1953 MAC2STR(act->src_addr), MAC2STR(act->bssid)); 1954 wpa_hexdump(MSG_MSGDUMP, "athr: act", (u8 *) act, sizeof(*act)); 1955 wpa_hexdump(MSG_MSGDUMP, "athr: data", data, data_len); 1956 1957 res = set80211big(drv, IEEE80211_IOC_P2P_SEND_ACTION, 1958 act, sizeof(*act) + data_len); 1959 os_free(act); 1960 return res; 1961} 1962 1963 1964#ifdef CONFIG_IEEE80211V 1965static int athr_wnm_tfs(struct atheros_driver_data *drv, const u8* peer, 1966 u8 *ie, u16 *len, enum wnm_oper oper) 1967{ 1968#define IEEE80211_APPIE_MAX 1024 /* max appie buffer size */ 1969 u8 buf[IEEE80211_APPIE_MAX]; 1970 struct ieee80211req_getset_appiebuf *tfs_ie; 1971 u16 val; 1972 1973 wpa_printf(MSG_DEBUG, "atheros: ifname=%s, WNM TFS IE oper=%d " MACSTR, 1974 drv->iface, oper, MAC2STR(peer)); 1975 1976 switch (oper) { 1977 case WNM_SLEEP_TFS_REQ_IE_SET: 1978 if (*len > IEEE80211_APPIE_MAX - 1979 sizeof(struct ieee80211req_getset_appiebuf)) { 1980 wpa_printf(MSG_DEBUG, "TFS Req IE(s) too large"); 1981 return -1; 1982 } 1983 tfs_ie = (struct ieee80211req_getset_appiebuf *) buf; 1984 tfs_ie->app_frmtype = IEEE80211_APPIE_FRAME_WNM; 1985 tfs_ie->app_buflen = ETH_ALEN + 2 + 2 + *len; 1986 1987 /* Command header for driver */ 1988 os_memcpy(&(tfs_ie->app_buf[0]), peer, ETH_ALEN); 1989 val = oper; 1990 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN, &val, 2); 1991 val = *len; 1992 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN + 2, &val, 2); 1993 1994 /* copy the ie */ 1995 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN + 2 + 2, ie, *len); 1996 1997 if (set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, tfs_ie, 1998 IEEE80211_APPIE_MAX)) { 1999 wpa_printf(MSG_DEBUG, "%s: Failed to set WNM TFS IE: " 2000 "%s", __func__, strerror(errno)); 2001 return -1; 2002 } 2003 break; 2004 case WNM_SLEEP_TFS_RESP_IE_ADD: 2005 tfs_ie = (struct ieee80211req_getset_appiebuf *) buf; 2006 tfs_ie->app_frmtype = IEEE80211_APPIE_FRAME_WNM; 2007 tfs_ie->app_buflen = IEEE80211_APPIE_MAX - 2008 sizeof(struct ieee80211req_getset_appiebuf); 2009 /* Command header for driver */ 2010 os_memcpy(&(tfs_ie->app_buf[0]), peer, ETH_ALEN); 2011 val = oper; 2012 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN, &val, 2); 2013 val = 0; 2014 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN + 2, &val, 2); 2015 2016 if (set80211priv(drv, IEEE80211_IOCTL_GET_APPIEBUF, tfs_ie, 2017 IEEE80211_APPIE_MAX)) { 2018 wpa_printf(MSG_DEBUG, "%s: Failed to get WNM TFS IE: " 2019 "%s", __func__, strerror(errno)); 2020 return -1; 2021 } 2022 2023 *len = tfs_ie->app_buflen; 2024 os_memcpy(ie, &(tfs_ie->app_buf[0]), *len); 2025 wpa_printf(MSG_DEBUG, "atheros: %c len=%d", tfs_ie->app_buf[0], 2026 *len); 2027 break; 2028 case WNM_SLEEP_TFS_RESP_IE_NONE: 2029 *len = 0; 2030 break; 2031 case WNM_SLEEP_TFS_IE_DEL: 2032 tfs_ie = (struct ieee80211req_getset_appiebuf *) buf; 2033 tfs_ie->app_frmtype = IEEE80211_APPIE_FRAME_WNM; 2034 tfs_ie->app_buflen = IEEE80211_APPIE_MAX - 2035 sizeof(struct ieee80211req_getset_appiebuf); 2036 /* Command header for driver */ 2037 os_memcpy(&(tfs_ie->app_buf[0]), peer, ETH_ALEN); 2038 val = oper; 2039 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN, &val, 2); 2040 val = 0; 2041 os_memcpy(&(tfs_ie->app_buf[0]) + ETH_ALEN + 2, &val, 2); 2042 2043 if (set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, tfs_ie, 2044 IEEE80211_APPIE_MAX)) { 2045 wpa_printf(MSG_DEBUG, "%s: Failed to set WNM TFS IE: " 2046 "%s", __func__, strerror(errno)); 2047 return -1; 2048 } 2049 break; 2050 default: 2051 wpa_printf(MSG_DEBUG, "Unsupported TFS oper %d", oper); 2052 break; 2053 } 2054 2055 return 0; 2056} 2057 2058 2059static int atheros_wnm_sleep(struct atheros_driver_data *drv, 2060 const u8 *peer, enum wnm_oper oper) 2061{ 2062 u8 *data, *pos; 2063 size_t dlen; 2064 int ret; 2065 u16 val; 2066 2067 wpa_printf(MSG_DEBUG, "atheros: WNM-Sleep Oper %d, " MACSTR, 2068 oper, MAC2STR(peer)); 2069 2070 dlen = ETH_ALEN + 2 + 2; 2071 data = os_malloc(dlen); 2072 if (data == NULL) 2073 return -1; 2074 2075 /* Command header for driver */ 2076 pos = data; 2077 os_memcpy(pos, peer, ETH_ALEN); 2078 pos += ETH_ALEN; 2079 2080 val = oper; 2081 os_memcpy(pos, &val, 2); 2082 pos += 2; 2083 2084 val = 0; 2085 os_memcpy(pos, &val, 2); 2086 2087 ret = atheros_set_wps_ie(drv, data, dlen, IEEE80211_APPIE_FRAME_WNM); 2088 2089 os_free(data); 2090 2091 return ret; 2092} 2093 2094 2095static int atheros_wnm_oper(void *priv, enum wnm_oper oper, const u8 *peer, 2096 u8 *buf, u16 *buf_len) 2097{ 2098 struct atheros_driver_data *drv = priv; 2099 2100 switch (oper) { 2101 case WNM_SLEEP_ENTER_CONFIRM: 2102 case WNM_SLEEP_ENTER_FAIL: 2103 case WNM_SLEEP_EXIT_CONFIRM: 2104 case WNM_SLEEP_EXIT_FAIL: 2105 return atheros_wnm_sleep(drv, peer, oper); 2106 case WNM_SLEEP_TFS_REQ_IE_SET: 2107 case WNM_SLEEP_TFS_RESP_IE_ADD: 2108 case WNM_SLEEP_TFS_RESP_IE_NONE: 2109 case WNM_SLEEP_TFS_IE_DEL: 2110 return athr_wnm_tfs(drv, peer, buf, buf_len, oper); 2111 default: 2112 wpa_printf(MSG_DEBUG, "atheros: Unsupported WNM operation %d", 2113 oper); 2114 return -1; 2115 } 2116} 2117#endif /* CONFIG_IEEE80211V */ 2118 2119 2120const struct wpa_driver_ops wpa_driver_atheros_ops = { 2121 .name = "atheros", 2122 .hapd_init = atheros_init, 2123 .hapd_deinit = atheros_deinit, 2124 .set_ieee8021x = atheros_set_ieee8021x, 2125 .set_privacy = atheros_set_privacy, 2126 .set_key = atheros_set_key, 2127 .get_seqnum = atheros_get_seqnum, 2128 .flush = atheros_flush, 2129 .set_generic_elem = atheros_set_opt_ie, 2130 .sta_set_flags = atheros_sta_set_flags, 2131 .read_sta_data = atheros_read_sta_driver_data, 2132 .hapd_send_eapol = atheros_send_eapol, 2133 .sta_disassoc = atheros_sta_disassoc, 2134 .sta_deauth = atheros_sta_deauth, 2135 .hapd_set_ssid = atheros_set_ssid, 2136 .hapd_get_ssid = atheros_get_ssid, 2137 .set_countermeasures = atheros_set_countermeasures, 2138 .sta_clear_stats = atheros_sta_clear_stats, 2139 .commit = atheros_commit, 2140 .set_ap_wps_ie = atheros_set_ap_wps_ie, 2141 .set_authmode = atheros_set_authmode, 2142 .set_ap = atheros_set_ap, 2143#ifdef CONFIG_IEEE80211R 2144 .sta_assoc = atheros_sta_assoc, 2145 .sta_auth = atheros_sta_auth, 2146 .send_mlme = atheros_send_mgmt, 2147 .add_tspec = atheros_add_tspec, 2148 .add_sta_node = atheros_add_sta_node, 2149#endif /* CONFIG_IEEE80211R */ 2150 .send_action = atheros_send_action, 2151#ifdef CONFIG_IEEE80211V 2152 .wnm_oper = atheros_wnm_oper, 2153#endif /* CONFIG_IEEE80211V */ 2154}; 2155