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 (at) 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 50 struct 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: */ 64 enum { 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: */ 72 enum { 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 80 struct 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 101 static 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 124 static 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 144 static 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 169 static 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 191 static 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 266 static 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 276 static 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 286 static 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 305 static 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 324 static 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 336 static 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 */ 350 static 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 379 static int 380 wpa_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 419 static 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 426 static 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 433 static 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 440 static 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 447 static 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 454 static 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 480 static 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 489 const 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