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