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(void *priv, wpa_alg alg, 192 const u8 *addr, int key_idx, 193 int set_tx, const u8 *seq, size_t seq_len, 194 const u8 *key, size_t key_len) 195{ 196 struct wpa_driver_atmel_data *drv = priv; 197 int ret = 0; 198 struct atmel_param *param; 199 u8 *buf; 200 u8 alg_type; 201 202 size_t blen; 203 char *alg_name; 204 205 switch (alg) { 206 case WPA_ALG_NONE: 207 alg_name = "none"; 208 alg_type = 0; 209 break; 210 case WPA_ALG_WEP: 211 alg_name = "WEP"; 212 alg_type = 1; 213 break; 214 case WPA_ALG_TKIP: 215 alg_name = "TKIP"; 216 alg_type = 2; 217 break; 218 case WPA_ALG_CCMP: 219 alg_name = "CCMP"; 220 alg_type = 3; 221 break; 222 default: 223 return -1; 224 } 225 226 wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " 227 "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, 228 (unsigned long) seq_len, (unsigned long) key_len); 229 230 if (seq_len > 8) 231 return -2; 232 233 blen = sizeof(*param) + key_len; 234 buf = os_zalloc(blen); 235 if (buf == NULL) 236 return -1; 237 238 param = (struct atmel_param *) buf; 239 240 param->cmd = SET_WPA_ENCRYPTION; 241 242 if (addr == NULL) 243 os_memset(param->sta_addr, 0xff, ETH_ALEN); 244 else 245 os_memcpy(param->sta_addr, addr, ETH_ALEN); 246 247 param->alg = alg_type; 248 param->key_idx = key_idx; 249 param->set_tx = set_tx; 250 os_memcpy(param->seq, seq, seq_len); 251 param->seq_len = seq_len; 252 param->key_len = key_len; 253 os_memcpy((u8 *)param->key, key, key_len); 254 255 if (atmel_ioctl(drv, param, blen, 1)) { 256 wpa_printf(MSG_WARNING, "Failed to set encryption."); 257 /* TODO: show key error*/ 258 ret = -1; 259 } 260 os_free(buf); 261 262 return ret; 263} 264 265 266static int wpa_driver_atmel_set_countermeasures(void *priv, 267 int enabled) 268{ 269 /* FIX */ 270 printf("wpa_driver_atmel_set_countermeasures - not yet " 271 "implemented\n"); 272 return 0; 273} 274 275 276static int wpa_driver_atmel_set_drop_unencrypted(void *priv, 277 int enabled) 278{ 279 /* FIX */ 280 printf("wpa_driver_atmel_set_drop_unencrypted - not yet " 281 "implemented\n"); 282 return 0; 283} 284 285 286static int wpa_driver_atmel_mlme(void *priv, const u8 *addr, int cmd, 287 int reason_code) 288{ 289 struct wpa_driver_atmel_data *drv = priv; 290 struct atmel_param param; 291 int ret; 292 int mgmt_error = 0xaa; 293 294 os_memset(¶m, 0, sizeof(param)); 295 os_memcpy(param.sta_addr, addr, ETH_ALEN); 296 param.cmd = cmd; 297 param.mlme.reason_code = reason_code; 298 param.mlme.state = mgmt_error; 299 ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); 300 return ret; 301} 302 303 304#if 0 305static int wpa_driver_atmel_set_suites(struct wpa_driver_atmel_data *drv, 306 u8 pairwise_suite, u8 group_suite, 307 u8 key_mgmt_suite) 308{ 309 struct atmel_param param; 310 int ret; 311 312 os_memset(¶m, 0, sizeof(param)); 313 param.cmd = SET_CIPHER_SUITES; 314 param.pairwise_suite = pairwise_suite; 315 param.group_suite = group_suite; 316 param.key_mgmt_suite = key_mgmt_suite; 317 318 ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); 319 return ret; 320} 321#endif 322 323 324static int wpa_driver_atmel_deauthenticate(void *priv, const u8 *addr, 325 int reason_code) 326{ 327 struct wpa_driver_atmel_data *drv = priv; 328 printf("wpa_driver_atmel_deauthenticate\n"); 329 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 330 return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DEAUTH, 331 reason_code); 332 333} 334 335 336static int wpa_driver_atmel_disassociate(void *priv, const u8 *addr, 337 int reason_code) 338{ 339 struct wpa_driver_atmel_data *drv = priv; 340 printf("wpa_driver_atmel_disassociate\n"); 341 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 342 return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DISASSOC, 343 reason_code); 344 345} 346 347 348#if 0 349/* Atmel driver uses specific values for each cipher suite */ 350static int convertSuiteToDriver(wpa_cipher suite) 351{ 352 u8 suite_type; 353 354 switch(suite) { 355 case CIPHER_NONE: 356 suite_type = 0; 357 break; 358 case CIPHER_WEP40: 359 suite_type = 1; 360 break; 361 case CIPHER_TKIP: 362 suite_type = 2; 363 break; 364 case CIPHER_WEP104: 365 suite_type = 5; 366 break; 367 case CIPHER_CCMP: 368 suite_type = 3; 369 break; 370 default: 371 suite_type = 2; 372 } 373 374 return suite_type; 375 376} 377#endif 378 379static int 380wpa_driver_atmel_associate(void *priv, 381 struct wpa_driver_associate_params *params) 382{ 383 struct wpa_driver_atmel_data *drv = priv; 384 int ret = 0; 385#if 0 386 u8 pairwise_suite_driver; 387 u8 group_suite_driver; 388 u8 key_mgmt_suite_driver; 389 390 pairwise_suite_driver = convertSuiteToDriver(params->pairwise_suite); 391 group_suite_driver = convertSuiteToDriver(params->group_suite); 392 key_mgmt_suite_driver = convertSuiteToDriver(params->key_mgmt_suite); 393 394 if (wpa_driver_atmel_set_suites(drv, pairwise_suite_driver, 395 group_suite_driver, 396 key_mgmt_suite_driver) < 0){ 397 printf("wpa_driver_atmel_set_suites.\n"); 398 ret = -1; 399 } 400 if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) { 401 printf("wpa_driver_atmel_set_freq.\n"); 402 ret = -1; 403 } 404#endif 405 if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) 406 < 0) { 407 printf("FAILED : wpa_driver_atmel_set_ssid.\n"); 408 ret = -1; 409 } 410 if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) { 411 printf("FAILED : wpa_driver_atmel_set_bssid.\n"); 412 ret = -1; 413 } 414 415 return ret; 416} 417 418 419static int wpa_driver_atmel_get_bssid(void *priv, u8 *bssid) 420{ 421 struct wpa_driver_atmel_data *drv = priv; 422 return wpa_driver_wext_get_bssid(drv->wext, bssid); 423} 424 425 426static int wpa_driver_atmel_get_ssid(void *priv, u8 *ssid) 427{ 428 struct wpa_driver_atmel_data *drv = priv; 429 return wpa_driver_wext_get_ssid(drv->wext, ssid); 430} 431 432 433static int wpa_driver_atmel_scan(void *priv, const u8 *ssid, size_t ssid_len) 434{ 435 struct wpa_driver_atmel_data *drv = priv; 436 return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); 437} 438 439 440static struct wpa_scan_results * wpa_driver_atmel_get_scan_results(void *priv) 441{ 442 struct wpa_driver_atmel_data *drv = priv; 443 return wpa_driver_wext_get_scan_results(drv->wext); 444} 445 446 447static int wpa_driver_atmel_set_operstate(void *priv, int state) 448{ 449 struct wpa_driver_atmel_data *drv = priv; 450 return wpa_driver_wext_set_operstate(drv->wext, state); 451} 452 453 454static void * wpa_driver_atmel_init(void *ctx, const char *ifname) 455{ 456 struct wpa_driver_atmel_data *drv; 457 458 drv = os_zalloc(sizeof(*drv)); 459 if (drv == NULL) 460 return NULL; 461 drv->wext = wpa_driver_wext_init(ctx, ifname); 462 if (drv->wext == NULL) { 463 os_free(drv); 464 return NULL; 465 } 466 467 drv->ctx = ctx; 468 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 469 drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 470 if (drv->sock < 0) { 471 wpa_driver_wext_deinit(drv->wext); 472 os_free(drv); 473 return NULL; 474 } 475 476 return drv; 477} 478 479 480static void wpa_driver_atmel_deinit(void *priv) 481{ 482 struct wpa_driver_atmel_data *drv = priv; 483 wpa_driver_wext_deinit(drv->wext); 484 close(drv->sock); 485 os_free(drv); 486} 487 488 489const struct wpa_driver_ops wpa_driver_atmel_ops = { 490 .name = "atmel", 491 .desc = "ATMEL AT76C5XXx (USB, PCMCIA)", 492 .get_bssid = wpa_driver_atmel_get_bssid, 493 .get_ssid = wpa_driver_atmel_get_ssid, 494 .set_wpa = wpa_driver_atmel_set_wpa, 495 .set_key = wpa_driver_atmel_set_key, 496 .init = wpa_driver_atmel_init, 497 .deinit = wpa_driver_atmel_deinit, 498 .set_countermeasures = wpa_driver_atmel_set_countermeasures, 499 .set_drop_unencrypted = wpa_driver_atmel_set_drop_unencrypted, 500 .scan = wpa_driver_atmel_scan, 501 .get_scan_results2 = wpa_driver_atmel_get_scan_results, 502 .deauthenticate = wpa_driver_atmel_deauthenticate, 503 .disassociate = wpa_driver_atmel_disassociate, 504 .associate = wpa_driver_atmel_associate, 505 .set_operstate = wpa_driver_atmel_set_operstate, 506}; 507