1/* 2 * WPA Supplicant - Driver interaction with Atmel Wireless LAN drivers 3 * Copyright (c) 2000-2005, ATMEL Corporation 4 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Alternatively, this software may be distributed under the terms of BSD 11 * license. 12 * 13 * See README and COPYING for more details. 14 */ 15 16/****************************************************************************** 17 Copyright 2000-2001 ATMEL Corporation. 18 19 WPA Supplicant - driver interaction with Atmel Wireless lan drivers. 20 21 This is free software; you can redistribute it and/or modify 22 it under the terms of the GNU General Public License as published by 23 the Free Software Foundation; either version 2 of the License, or 24 (at your option) any later version. 25 26 This program is distributed in the hope that it will be useful, 27 but WITHOUT ANY WARRANTY; without even the implied warranty of 28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 GNU General Public License for more details. 30 31 You should have received a copy of the GNU General Public License 32 along with Atmel wireless lan drivers; if not, write to the Free Software 33 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 34 35******************************************************************************/ 36 37/* 38 * Alternatively, this software may be distributed under the terms of BSD 39 * license. 40 */ 41 42#include "includes.h" 43#include <sys/ioctl.h> 44 45#include "wireless_copy.h" 46#include "common.h" 47#include "driver.h" 48#include "driver_wext.h" 49 50struct wpa_driver_atmel_data { 51 void *wext; /* private data for driver_wext */ 52 void *ctx; 53 char ifname[IFNAMSIZ + 1]; 54 int sock; 55}; 56 57 58#define ATMEL_WPA_IOCTL (SIOCIWFIRSTPRIV + 2) 59#define ATMEL_WPA_IOCTL_PARAM (SIOCIWFIRSTPRIV + 3) 60#define ATMEL_WPA_IOCTL_GET_PARAM (SIOCIWFIRSTPRIV + 4) 61 62 63/* ATMEL_WPA_IOCTL ioctl() cmd: */ 64enum { 65 SET_WPA_ENCRYPTION = 1, 66 SET_CIPHER_SUITES = 2, 67 MLME_STA_DEAUTH = 3, 68 MLME_STA_DISASSOC = 4 69}; 70 71/* ATMEL_WPA_IOCTL_PARAM ioctl() cmd: */ 72enum { 73 ATMEL_PARAM_WPA = 1, 74 ATMEL_PARAM_PRIVACY_INVOKED = 2, 75 ATMEL_PARAM_WPA_TYPE = 3 76}; 77 78#define MAX_KEY_LENGTH 40 79 80struct atmel_param{ 81 unsigned char sta_addr[6]; 82 int cmd; 83 u8 alg; 84 u8 key_idx; 85 u8 set_tx; 86 u8 seq[8]; 87 u8 seq_len; 88 u16 key_len; 89 u8 key[MAX_KEY_LENGTH]; 90 struct{ 91 int reason_code; 92 u8 state; 93 }mlme; 94 u8 pairwise_suite; 95 u8 group_suite; 96 u8 key_mgmt_suite; 97}; 98 99 100 101static int atmel_ioctl(struct wpa_driver_atmel_data *drv, 102 struct atmel_param *param, 103 int len, int show_err) 104{ 105 struct iwreq iwr; 106 107 os_memset(&iwr, 0, sizeof(iwr)); 108 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 109 iwr.u.data.pointer = (caddr_t) param; 110 iwr.u.data.length = len; 111 112 if (ioctl(drv->sock, ATMEL_WPA_IOCTL, &iwr) < 0) { 113 int ret; 114 ret = errno; 115 if (show_err) 116 perror("ioctl[ATMEL_WPA_IOCTL]"); 117 return ret; 118 } 119 120 return 0; 121} 122 123 124static int atmel2param(struct wpa_driver_atmel_data *drv, int param, int value) 125{ 126 struct iwreq iwr; 127 int *i, ret = 0; 128 129 os_memset(&iwr, 0, sizeof(iwr)); 130 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 131 i = (int *) iwr.u.name; 132 *i++ = param; 133 *i++ = value; 134 135 if (ioctl(drv->sock, ATMEL_WPA_IOCTL_PARAM, &iwr) < 0) { 136 perror("ioctl[ATMEL_WPA_IOCTL_PARAM]"); 137 ret = -1; 138 } 139 return ret; 140} 141 142 143#if 0 144static int wpa_driver_atmel_set_wpa_ie(struct wpa_driver_atmel_data *drv, 145 const char *wpa_ie, size_t wpa_ie_len) 146{ 147 struct atmel_param *param; 148 int res; 149 size_t blen = ATMEL_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; 150 if (blen < sizeof(*param)) 151 blen = sizeof(*param); 152 153 param = os_zalloc(blen); 154 if (param == NULL) 155 return -1; 156 157 param->cmd = ATMEL_SET_GENERIC_ELEMENT; 158 param->u.generic_elem.len = wpa_ie_len; 159 os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); 160 res = atmel_ioctl(drv, param, blen, 1); 161 162 os_free(param); 163 164 return res; 165} 166#endif 167 168 169static int wpa_driver_atmel_set_wpa(void *priv, int enabled) 170{ 171 struct wpa_driver_atmel_data *drv = priv; 172 int ret = 0; 173 174 printf("wpa_driver_atmel_set_wpa %s\n", drv->ifname); 175 176 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); 177 178#if 0 179 if (!enabled && wpa_driver_atmel_set_wpa_ie(drv, NULL, 0) < 0) 180 ret = -1; 181#endif 182 if (atmel2param(drv, ATMEL_PARAM_PRIVACY_INVOKED, enabled) < 0) 183 ret = -1; 184 if (atmel2param(drv, ATMEL_PARAM_WPA, enabled) < 0) 185 ret = -1; 186 187 return ret; 188} 189 190 191static int wpa_driver_atmel_set_key(const char *ifname, void *priv, 192 enum wpa_alg alg, const u8 *addr, 193 int key_idx, int set_tx, 194 const u8 *seq, size_t seq_len, 195 const u8 *key, size_t key_len) 196{ 197 struct wpa_driver_atmel_data *drv = priv; 198 int ret = 0; 199 struct atmel_param *param; 200 u8 *buf; 201 u8 alg_type; 202 203 size_t blen; 204 char *alg_name; 205 206 switch (alg) { 207 case WPA_ALG_NONE: 208 alg_name = "none"; 209 alg_type = 0; 210 break; 211 case WPA_ALG_WEP: 212 alg_name = "WEP"; 213 alg_type = 1; 214 break; 215 case WPA_ALG_TKIP: 216 alg_name = "TKIP"; 217 alg_type = 2; 218 break; 219 case WPA_ALG_CCMP: 220 alg_name = "CCMP"; 221 alg_type = 3; 222 break; 223 default: 224 return -1; 225 } 226 227 wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " 228 "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, 229 (unsigned long) seq_len, (unsigned long) key_len); 230 231 if (seq_len > 8) 232 return -2; 233 234 blen = sizeof(*param) + key_len; 235 buf = os_zalloc(blen); 236 if (buf == NULL) 237 return -1; 238 239 param = (struct atmel_param *) buf; 240 241 param->cmd = SET_WPA_ENCRYPTION; 242 243 if (addr == NULL) 244 os_memset(param->sta_addr, 0xff, ETH_ALEN); 245 else 246 os_memcpy(param->sta_addr, addr, ETH_ALEN); 247 248 param->alg = alg_type; 249 param->key_idx = key_idx; 250 param->set_tx = set_tx; 251 os_memcpy(param->seq, seq, seq_len); 252 param->seq_len = seq_len; 253 param->key_len = key_len; 254 os_memcpy((u8 *)param->key, key, key_len); 255 256 if (atmel_ioctl(drv, param, blen, 1)) { 257 wpa_printf(MSG_WARNING, "Failed to set encryption."); 258 /* TODO: show key error*/ 259 ret = -1; 260 } 261 os_free(buf); 262 263 return ret; 264} 265 266 267static int wpa_driver_atmel_set_countermeasures(void *priv, 268 int enabled) 269{ 270 /* FIX */ 271 printf("wpa_driver_atmel_set_countermeasures - not yet " 272 "implemented\n"); 273 return 0; 274} 275 276 277static int wpa_driver_atmel_mlme(void *priv, const u8 *addr, int cmd, 278 int reason_code) 279{ 280 struct wpa_driver_atmel_data *drv = priv; 281 struct atmel_param param; 282 int ret; 283 int mgmt_error = 0xaa; 284 285 os_memset(¶m, 0, sizeof(param)); 286 os_memcpy(param.sta_addr, addr, ETH_ALEN); 287 param.cmd = cmd; 288 param.mlme.reason_code = reason_code; 289 param.mlme.state = mgmt_error; 290 ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); 291 return ret; 292} 293 294 295#if 0 296static int wpa_driver_atmel_set_suites(struct wpa_driver_atmel_data *drv, 297 u8 pairwise_suite, u8 group_suite, 298 u8 key_mgmt_suite) 299{ 300 struct atmel_param param; 301 int ret; 302 303 os_memset(¶m, 0, sizeof(param)); 304 param.cmd = SET_CIPHER_SUITES; 305 param.pairwise_suite = pairwise_suite; 306 param.group_suite = group_suite; 307 param.key_mgmt_suite = key_mgmt_suite; 308 309 ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); 310 return ret; 311} 312#endif 313 314 315static int wpa_driver_atmel_deauthenticate(void *priv, const u8 *addr, 316 int reason_code) 317{ 318 struct wpa_driver_atmel_data *drv = priv; 319 printf("wpa_driver_atmel_deauthenticate\n"); 320 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 321 return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DEAUTH, 322 reason_code); 323 324} 325 326 327static int wpa_driver_atmel_disassociate(void *priv, const u8 *addr, 328 int reason_code) 329{ 330 struct wpa_driver_atmel_data *drv = priv; 331 printf("wpa_driver_atmel_disassociate\n"); 332 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 333 return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DISASSOC, 334 reason_code); 335 336} 337 338 339#if 0 340/* Atmel driver uses specific values for each cipher suite */ 341static int convertSuiteToDriver(enum wpa_cipher suite) 342{ 343 u8 suite_type; 344 345 switch(suite) { 346 case CIPHER_NONE: 347 suite_type = 0; 348 break; 349 case CIPHER_WEP40: 350 suite_type = 1; 351 break; 352 case CIPHER_TKIP: 353 suite_type = 2; 354 break; 355 case CIPHER_WEP104: 356 suite_type = 5; 357 break; 358 case CIPHER_CCMP: 359 suite_type = 3; 360 break; 361 default: 362 suite_type = 2; 363 } 364 365 return suite_type; 366 367} 368#endif 369 370static int 371wpa_driver_atmel_associate(void *priv, 372 struct wpa_driver_associate_params *params) 373{ 374 struct wpa_driver_atmel_data *drv = priv; 375 int ret = 0; 376#if 0 377 u8 pairwise_suite_driver; 378 u8 group_suite_driver; 379 u8 key_mgmt_suite_driver; 380 381 pairwise_suite_driver = convertSuiteToDriver(params->pairwise_suite); 382 group_suite_driver = convertSuiteToDriver(params->group_suite); 383 key_mgmt_suite_driver = convertSuiteToDriver(params->key_mgmt_suite); 384 385 if (wpa_driver_atmel_set_suites(drv, pairwise_suite_driver, 386 group_suite_driver, 387 key_mgmt_suite_driver) < 0){ 388 printf("wpa_driver_atmel_set_suites.\n"); 389 ret = -1; 390 } 391 if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) { 392 printf("wpa_driver_atmel_set_freq.\n"); 393 ret = -1; 394 } 395#endif 396 if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) 397 < 0) { 398 printf("FAILED : wpa_driver_atmel_set_ssid.\n"); 399 ret = -1; 400 } 401 if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) { 402 printf("FAILED : wpa_driver_atmel_set_bssid.\n"); 403 ret = -1; 404 } 405 406 return ret; 407} 408 409 410static int wpa_driver_atmel_get_bssid(void *priv, u8 *bssid) 411{ 412 struct wpa_driver_atmel_data *drv = priv; 413 return wpa_driver_wext_get_bssid(drv->wext, bssid); 414} 415 416 417static int wpa_driver_atmel_get_ssid(void *priv, u8 *ssid) 418{ 419 struct wpa_driver_atmel_data *drv = priv; 420 return wpa_driver_wext_get_ssid(drv->wext, ssid); 421} 422 423 424static int wpa_driver_atmel_scan(void *priv, 425 struct wpa_driver_scan_params *params) 426{ 427 struct wpa_driver_atmel_data *drv = priv; 428 return wpa_driver_wext_scan(drv->wext, params); 429} 430 431 432static struct wpa_scan_results * wpa_driver_atmel_get_scan_results(void *priv) 433{ 434 struct wpa_driver_atmel_data *drv = priv; 435 return wpa_driver_wext_get_scan_results(drv->wext); 436} 437 438 439static int wpa_driver_atmel_set_operstate(void *priv, int state) 440{ 441 struct wpa_driver_atmel_data *drv = priv; 442 return wpa_driver_wext_set_operstate(drv->wext, state); 443} 444 445 446static void * wpa_driver_atmel_init(void *ctx, const char *ifname) 447{ 448 struct wpa_driver_atmel_data *drv; 449 450 drv = os_zalloc(sizeof(*drv)); 451 if (drv == NULL) 452 return NULL; 453 drv->wext = wpa_driver_wext_init(ctx, ifname); 454 if (drv->wext == NULL) { 455 os_free(drv); 456 return NULL; 457 } 458 459 drv->ctx = ctx; 460 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 461 drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 462 if (drv->sock < 0) { 463 wpa_driver_wext_deinit(drv->wext); 464 os_free(drv); 465 return NULL; 466 } 467 468 wpa_driver_atmel_set_wpa(drv, 1); 469 470 return drv; 471} 472 473 474static void wpa_driver_atmel_deinit(void *priv) 475{ 476 struct wpa_driver_atmel_data *drv = priv; 477 wpa_driver_atmel_set_wpa(drv, 0); 478 wpa_driver_wext_deinit(drv->wext); 479 close(drv->sock); 480 os_free(drv); 481} 482 483 484const struct wpa_driver_ops wpa_driver_atmel_ops = { 485 .name = "atmel", 486 .desc = "ATMEL AT76C5XXx (USB, PCMCIA)", 487 .get_bssid = wpa_driver_atmel_get_bssid, 488 .get_ssid = wpa_driver_atmel_get_ssid, 489 .set_key = wpa_driver_atmel_set_key, 490 .init = wpa_driver_atmel_init, 491 .deinit = wpa_driver_atmel_deinit, 492 .set_countermeasures = wpa_driver_atmel_set_countermeasures, 493 .scan2 = wpa_driver_atmel_scan, 494 .get_scan_results2 = wpa_driver_atmel_get_scan_results, 495 .deauthenticate = wpa_driver_atmel_deauthenticate, 496 .disassociate = wpa_driver_atmel_disassociate, 497 .associate = wpa_driver_atmel_associate, 498 .set_operstate = wpa_driver_atmel_set_operstate, 499}; 500