Home | History | Annotate | Download | only in drivers
      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(&param, 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, &param, 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(&param, 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, &param, 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