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 #include "wpa_supplicant.h" 50 51 struct wpa_driver_atmel_data { 52 void *wext; /* private data for driver_wext */ 53 void *ctx; 54 char ifname[IFNAMSIZ + 1]; 55 int sock; 56 }; 57 58 59 #define ATMEL_WPA_IOCTL (SIOCIWFIRSTPRIV + 2) 60 #define ATMEL_WPA_IOCTL_PARAM (SIOCIWFIRSTPRIV + 3) 61 #define ATMEL_WPA_IOCTL_GET_PARAM (SIOCIWFIRSTPRIV + 4) 62 63 64 /* ATMEL_WPA_IOCTL ioctl() cmd: */ 65 enum { 66 SET_WPA_ENCRYPTION = 1, 67 SET_CIPHER_SUITES = 2, 68 MLME_STA_DEAUTH = 3, 69 MLME_STA_DISASSOC = 4 70 }; 71 72 /* ATMEL_WPA_IOCTL_PARAM ioctl() cmd: */ 73 enum { 74 ATMEL_PARAM_WPA = 1, 75 ATMEL_PARAM_PRIVACY_INVOKED = 2, 76 ATMEL_PARAM_WPA_TYPE = 3 77 }; 78 79 #define MAX_KEY_LENGTH 40 80 81 struct atmel_param{ 82 unsigned char sta_addr[6]; 83 int cmd; 84 u8 alg; 85 u8 key_idx; 86 u8 set_tx; 87 u8 seq[8]; 88 u8 seq_len; 89 u16 key_len; 90 u8 key[MAX_KEY_LENGTH]; 91 struct{ 92 int reason_code; 93 u8 state; 94 }mlme; 95 u8 pairwise_suite; 96 u8 group_suite; 97 u8 key_mgmt_suite; 98 }; 99 100 101 102 static int atmel_ioctl(struct wpa_driver_atmel_data *drv, 103 struct atmel_param *param, 104 int len, int show_err) 105 { 106 struct iwreq iwr; 107 108 os_memset(&iwr, 0, sizeof(iwr)); 109 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 110 iwr.u.data.pointer = (caddr_t) param; 111 iwr.u.data.length = len; 112 113 if (ioctl(drv->sock, ATMEL_WPA_IOCTL, &iwr) < 0) { 114 int ret; 115 ret = errno; 116 if (show_err) 117 perror("ioctl[ATMEL_WPA_IOCTL]"); 118 return ret; 119 } 120 121 return 0; 122 } 123 124 125 static int atmel2param(struct wpa_driver_atmel_data *drv, int param, int value) 126 { 127 struct iwreq iwr; 128 int *i, ret = 0; 129 130 os_memset(&iwr, 0, sizeof(iwr)); 131 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 132 i = (int *) iwr.u.name; 133 *i++ = param; 134 *i++ = value; 135 136 if (ioctl(drv->sock, ATMEL_WPA_IOCTL_PARAM, &iwr) < 0) { 137 perror("ioctl[ATMEL_WPA_IOCTL_PARAM]"); 138 ret = -1; 139 } 140 return ret; 141 } 142 143 144 #if 0 145 static int wpa_driver_atmel_set_wpa_ie(struct wpa_driver_atmel_data *drv, 146 const char *wpa_ie, size_t wpa_ie_len) 147 { 148 struct atmel_param *param; 149 int res; 150 size_t blen = ATMEL_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; 151 if (blen < sizeof(*param)) 152 blen = sizeof(*param); 153 154 param = os_zalloc(blen); 155 if (param == NULL) 156 return -1; 157 158 param->cmd = ATMEL_SET_GENERIC_ELEMENT; 159 param->u.generic_elem.len = wpa_ie_len; 160 os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); 161 res = atmel_ioctl(drv, param, blen, 1); 162 163 os_free(param); 164 165 return res; 166 } 167 #endif 168 169 170 static int wpa_driver_atmel_set_wpa(void *priv, int enabled) 171 { 172 struct wpa_driver_atmel_data *drv = priv; 173 int ret = 0; 174 175 printf("wpa_driver_atmel_set_wpa %s\n", drv->ifname); 176 177 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); 178 179 #if 0 180 if (!enabled && wpa_driver_atmel_set_wpa_ie(drv, NULL, 0) < 0) 181 ret = -1; 182 #endif 183 if (atmel2param(drv, ATMEL_PARAM_PRIVACY_INVOKED, enabled) < 0) 184 ret = -1; 185 if (atmel2param(drv, ATMEL_PARAM_WPA, enabled) < 0) 186 ret = -1; 187 188 return ret; 189 } 190 191 192 static int wpa_driver_atmel_set_key(void *priv, wpa_alg alg, 193 const u8 *addr, int key_idx, 194 int set_tx, 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 267 static 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 277 static int wpa_driver_atmel_set_drop_unencrypted(void *priv, 278 int enabled) 279 { 280 /* FIX */ 281 printf("wpa_driver_atmel_set_drop_unencrypted - not yet " 282 "implemented\n"); 283 return 0; 284 } 285 286 287 static int wpa_driver_atmel_mlme(void *priv, const u8 *addr, int cmd, 288 int reason_code) 289 { 290 struct wpa_driver_atmel_data *drv = priv; 291 struct atmel_param param; 292 int ret; 293 int mgmt_error = 0xaa; 294 295 os_memset(¶m, 0, sizeof(param)); 296 os_memcpy(param.sta_addr, addr, ETH_ALEN); 297 param.cmd = cmd; 298 param.mlme.reason_code = reason_code; 299 param.mlme.state = mgmt_error; 300 ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); 301 return ret; 302 } 303 304 305 #if 0 306 static int wpa_driver_atmel_set_suites(struct wpa_driver_atmel_data *drv, 307 u8 pairwise_suite, u8 group_suite, 308 u8 key_mgmt_suite) 309 { 310 struct atmel_param param; 311 int ret; 312 313 os_memset(¶m, 0, sizeof(param)); 314 param.cmd = SET_CIPHER_SUITES; 315 param.pairwise_suite = pairwise_suite; 316 param.group_suite = group_suite; 317 param.key_mgmt_suite = key_mgmt_suite; 318 319 ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); 320 return ret; 321 } 322 #endif 323 324 325 static int wpa_driver_atmel_deauthenticate(void *priv, const u8 *addr, 326 int reason_code) 327 { 328 struct wpa_driver_atmel_data *drv = priv; 329 printf("wpa_driver_atmel_deauthenticate\n"); 330 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 331 return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DEAUTH, 332 reason_code); 333 334 } 335 336 337 static int wpa_driver_atmel_disassociate(void *priv, const u8 *addr, 338 int reason_code) 339 { 340 struct wpa_driver_atmel_data *drv = priv; 341 printf("wpa_driver_atmel_disassociate\n"); 342 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 343 return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DISASSOC, 344 reason_code); 345 346 } 347 348 349 #if 0 350 /* Atmel driver uses specific values for each cipher suite */ 351 static int convertSuiteToDriver(wpa_cipher suite) 352 { 353 u8 suite_type; 354 355 switch(suite) { 356 case CIPHER_NONE: 357 suite_type = 0; 358 break; 359 case CIPHER_WEP40: 360 suite_type = 1; 361 break; 362 case CIPHER_TKIP: 363 suite_type = 2; 364 break; 365 case CIPHER_WEP104: 366 suite_type = 5; 367 break; 368 case CIPHER_CCMP: 369 suite_type = 3; 370 break; 371 default: 372 suite_type = 2; 373 } 374 375 return suite_type; 376 377 } 378 #endif 379 380 static int 381 wpa_driver_atmel_associate(void *priv, 382 struct wpa_driver_associate_params *params) 383 { 384 struct wpa_driver_atmel_data *drv = priv; 385 int ret = 0; 386 #if 0 387 u8 pairwise_suite_driver; 388 u8 group_suite_driver; 389 u8 key_mgmt_suite_driver; 390 391 pairwise_suite_driver = convertSuiteToDriver(params->pairwise_suite); 392 group_suite_driver = convertSuiteToDriver(params->group_suite); 393 key_mgmt_suite_driver = convertSuiteToDriver(params->key_mgmt_suite); 394 395 if (wpa_driver_atmel_set_suites(drv, pairwise_suite_driver, 396 group_suite_driver, 397 key_mgmt_suite_driver) < 0){ 398 printf("wpa_driver_atmel_set_suites.\n"); 399 ret = -1; 400 } 401 if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) { 402 printf("wpa_driver_atmel_set_freq.\n"); 403 ret = -1; 404 } 405 #endif 406 if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) 407 < 0) { 408 printf("FAILED : wpa_driver_atmel_set_ssid.\n"); 409 ret = -1; 410 } 411 if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) { 412 printf("FAILED : wpa_driver_atmel_set_bssid.\n"); 413 ret = -1; 414 } 415 416 return ret; 417 } 418 419 420 static int wpa_driver_atmel_get_bssid(void *priv, u8 *bssid) 421 { 422 struct wpa_driver_atmel_data *drv = priv; 423 return wpa_driver_wext_get_bssid(drv->wext, bssid); 424 } 425 426 427 static int wpa_driver_atmel_get_ssid(void *priv, u8 *ssid) 428 { 429 struct wpa_driver_atmel_data *drv = priv; 430 return wpa_driver_wext_get_ssid(drv->wext, ssid); 431 } 432 433 434 static int wpa_driver_atmel_scan(void *priv, const u8 *ssid, size_t ssid_len) 435 { 436 struct wpa_driver_atmel_data *drv = priv; 437 return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); 438 } 439 440 441 static int wpa_driver_atmel_get_scan_results(void *priv, 442 struct wpa_scan_result *results, 443 size_t max_size) 444 { 445 struct wpa_driver_atmel_data *drv = priv; 446 return wpa_driver_wext_get_scan_results(drv->wext, results, max_size); 447 } 448 449 450 static int wpa_driver_atmel_set_operstate(void *priv, int state) 451 { 452 struct wpa_driver_atmel_data *drv = priv; 453 return wpa_driver_wext_set_operstate(drv->wext, state); 454 } 455 456 457 static void * wpa_driver_atmel_init(void *ctx, const char *ifname) 458 { 459 struct wpa_driver_atmel_data *drv; 460 461 drv = os_zalloc(sizeof(*drv)); 462 if (drv == NULL) 463 return NULL; 464 drv->wext = wpa_driver_wext_init(ctx, ifname); 465 if (drv->wext == NULL) { 466 os_free(drv); 467 return NULL; 468 } 469 470 drv->ctx = ctx; 471 os_strncpy(drv->ifname, ifname, sizeof(drv->ifname)); 472 drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 473 if (drv->sock < 0) { 474 wpa_driver_wext_deinit(drv->wext); 475 os_free(drv); 476 return NULL; 477 } 478 479 return drv; 480 } 481 482 483 static void wpa_driver_atmel_deinit(void *priv) 484 { 485 struct wpa_driver_atmel_data *drv = priv; 486 wpa_driver_wext_deinit(drv->wext); 487 close(drv->sock); 488 os_free(drv); 489 } 490 491 492 const struct wpa_driver_ops wpa_driver_atmel_ops = { 493 .name = "atmel", 494 .desc = "ATMEL AT76C5XXx (USB, PCMCIA)", 495 .get_bssid = wpa_driver_atmel_get_bssid, 496 .get_ssid = wpa_driver_atmel_get_ssid, 497 .set_wpa = wpa_driver_atmel_set_wpa, 498 .set_key = wpa_driver_atmel_set_key, 499 .init = wpa_driver_atmel_init, 500 .deinit = wpa_driver_atmel_deinit, 501 .set_countermeasures = wpa_driver_atmel_set_countermeasures, 502 .set_drop_unencrypted = wpa_driver_atmel_set_drop_unencrypted, 503 .scan = wpa_driver_atmel_scan, 504 .get_scan_results = wpa_driver_atmel_get_scan_results, 505 .deauthenticate = wpa_driver_atmel_deauthenticate, 506 .disassociate = wpa_driver_atmel_disassociate, 507 .associate = wpa_driver_atmel_associate, 508 .set_operstate = wpa_driver_atmel_set_operstate, 509 }; 510