3 # Patch managed by http://www.holgerschurig.de/patcher.html
7 +++ wpa_supplicant/driver_hermes.c
10 + * WPA Supplicant - testing driver interface
11 + * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
13 + * This program is free software; you can redistribute it and/or modify
14 + * it under the terms of the GNU General Public License version 2 as
15 + * published by the Free Software Foundation.
17 + * Alternatively, this software may be distributed under the terms of BSD
20 + * See README and COPYING for more details.
27 +#include <sys/ioctl.h>
29 +#include <net/if_arp.h>
31 +#include "wireless_copy.h"
36 +#include "wpa_supplicant.h"
37 +#include "priv_netlink.h"
39 +#include "hostap_common.h"
40 +#include "driver_wext.h"
41 +#include "driver_hermes.h"
45 +/* Enumeration for supported Hermes Types */
48 + WL_HERMES_UNKNOWN = 0,
57 +struct wpa_driver_hermes_data {
58 + void *wext; /* private data for driver_wext */
60 + char ifname[IFNAMSIZ + 1];
67 +/****************************************************************************/
69 +/* Routines for basic device access to Agere Hermes-I/Hermes-II via the UIL */
71 +/****************************************************************************/
73 +IFBP _connect(void *priv)
75 + struct wpa_driver_hermes_data *drv = priv;
80 + //wpa_printf(MSG_DEBUG, "%s: %s %d", __FUNCTION__, drv->ifname, drv->sock);
82 + memset(&urq, 0, sizeof(urq));
84 + strcpy(urq.ifr_name, drv->ifname);
85 + urq.command = UIL_FUN_CONNECT;
87 + result = ioctl(drv->sock, WVLAN2_IOCTL_UIL, &urq);
88 + if (result == 0 && urq.result == UIL_SUCCESS) {
91 + wpa_printf(MSG_DEBUG, "%s: could not set IFBP, result %d", __FUNCTION__, result);
98 +void _disconnect(void *priv, IFBP ifbp)
100 + struct wpa_driver_hermes_data *drv = priv;
104 + //wpa_printf(MSG_DEBUG, "%s: %s", __FUNCTION__, drv->ifname);
106 + if (ifbp != NULL) {
107 + memset(&urq, 0, sizeof(struct uilreq));
109 + strcpy(urq.ifr_name, drv->ifname);
110 + urq.command = UIL_FUN_DISCONNECT;
113 + result = ioctl(drv->sock, WVLAN2_IOCTL_UIL, &urq);
115 + if (result != 0 || urq.result != UIL_SUCCESS) {
116 + wpa_printf( MSG_WARNING, "wl_disconnect(): ioctl() failed, errno: %d", errno );
117 + wpa_printf( MSG_WARNING, "wl_disconnect(): urq.result: %d", urq.result );
120 + wpa_printf(MSG_WARNING, "wl_disconnect(): called with NULL ifbp");
126 +int _get_info(void *priv, ltv_t *ltv)
128 + struct wpa_driver_hermes_data *drv = priv;
133 + //wpa_printf(MSG_DEBUG, "%s: %s", __FUNCTION__, drv->ifname);
135 + /* First, connect to the device */
136 + ifbp = _connect(priv);
137 + if (ifbp != NULL && ltv != NULL) {
138 + memset(&urq, 0, sizeof(struct uilreq));
140 + strcpy(urq.ifr_name, drv->ifname);
142 + urq.command = UIL_FUN_GET_INFO;
143 + urq.len = sizeof(ltv_t);
146 + result = ioctl(drv->sock, WVLAN2_IOCTL_UIL, &urq);
148 + if (result != 0 || urq.result != UIL_SUCCESS) {
149 + wpa_printf(MSG_WARNING, "wl_disconnect(): ioctl() failed, errno: %d", errno);
150 + wpa_printf(MSG_WARNING, "wl_disconnect(): urq.result: %d", urq.result);
152 + _disconnect(priv, ifbp);
154 + wpa_printf( MSG_WARNING, "Could not connect to the device, or LTV NULL");
161 +int _put_info(void *priv, ltv_t *ltv)
163 + struct wpa_driver_hermes_data *drv = priv;
168 + //wpa_printf(MSG_DEBUG, "%s: %s", __FUNCTION__, drv->ifname);
170 + /* First, connect to the device */
171 + ifbp = _connect(priv);
172 + if (ifbp != NULL && ltv != NULL) {
173 + memset(&urq, 0, sizeof(struct uilreq));
175 + strcpy(urq.ifr_name, drv->ifname);
177 + urq.command = UIL_FUN_PUT_INFO;
178 + urq.len = sizeof( ltv_t );
181 + result = ioctl(drv->sock, WVLAN2_IOCTL_UIL, &urq);
183 + if (result != 0 || urq.result != UIL_SUCCESS) {
184 + wpa_printf(MSG_WARNING, "_put_info(): ioctl() failed, errno: %d", errno);
185 + wpa_printf(MSG_WARNING, "_put_info(): urq.result: %d", urq.result);
188 + _disconnect(priv, ifbp);
190 + wpa_printf(MSG_WARNING, "%s: could not connect to the device, or LTV NULL", __FUNCTION__ );
198 +static void _detect_hermes_type(void *priv)
200 + struct wpa_driver_hermes_data *drv = priv;
201 + CFG_FW_IDENTITY_STRCT *fw_id;
205 + //wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
207 + drv->type = WL_HERMES_UNKNOWN;
209 + if (drv->sock >= 0) {
210 + fw_id = (CFG_FW_IDENTITY_STRCT *)<v;
211 + fw_id->len = ( sizeof(CFG_FW_IDENTITY_STRCT) / sizeof( hcf_16 )) - 1;
212 + fw_id->typ = CFG_FW_IDENTITY;
214 + result = _get_info(priv, (ltv_t *)fw_id);
215 + if (result == HCF_SUCCESS) {
216 + //wpa_printf(MSG_DEBUG, "PRI CompID : %d", fw_id->comp_id);
217 + //wpa_printf(MSG_DEBUG, "PRI Variant : %d", fw_id->variant);
218 + //wpa_printf(MSG_DEBUG, "PRI Version : %d.%02d", fw_id->version_major, fw_id->version_minor);
220 + switch(fw_id->comp_id) {
221 + case COMP_ID_FW_STA:
222 + switch (fw_id->variant) {
225 + wpa_printf(MSG_DEBUG, "found Hermes 1 STA");
226 + drv->type = WL_HERMES_1;
230 + wpa_printf(MSG_DEBUG, "found Hermes 2 STA");
231 + drv->type = WL_HERMES_2;
234 + wpa_printf(MSG_DEBUG, "found Hermes 2.5 STA");
235 + drv->type = WL_HERMES_25;
240 + case COMP_ID_FW_AP:
241 + switch (fw_id->variant) {
243 + wpa_printf(MSG_DEBUG, "found Hermes 1 AP");
244 + drv->type = WL_HERMES_1;
248 + wpa_printf(MSG_DEBUG, "found Hermes 2 AP" );
249 + drv->type = WL_HERMES_2;
255 + wpa_printf(MSG_WARNING, "could not detect Hermes type!");
264 +/****************************************************************************/
267 +static int wpa_driver_hermes_set_wpa_ie(void *priv, const char *wpa_ie,
270 + struct wpa_driver_hermes_data *drv = priv;
273 + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
276 + ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
278 + switch(drv->type) {
293 + return _put_info(priv, <v);
297 +static int wpa_driver_hermes_set_wpa(void *priv, int enabled)
301 + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
304 + ltv.typ = CFG_CNF_ENCRYPTION;
305 + ltv.u.u16[0] = enabled ? 2 : 0; /* Setting CFG_CNF_ENCRYPTION to 2 sets WPA: TKIP or better */
307 + return _put_info(priv, <v);
311 +static int wpa_driver_hermes_set_key(void *priv, wpa_alg alg,
312 + const u8 *addr, int key_idx,
313 + int set_tx, const u8 *seq, size_t seq_len,
314 + const u8 *key, size_t key_len)
316 + struct wpa_driver_hermes_data *drv = priv;
322 + hcf_8 tsc[] = { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 };
323 + hcf_8 rsc[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
343 + wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%d "
344 + "key_len=%d", __FUNCTION__, alg_name, key_idx, set_tx,
347 + if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {
348 + wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu", __FUNCTION__, (unsigned long) seq_len);
352 + /* Check the key index here; if 0, load as Pairwise Key, otherwise, load as
353 + a group key. Note that for the Hermes, the RIDs for group/pairwise keys
354 + are different from each other and different than the default WEP keys as
358 + /* Make sure that there is no data queued up in the firmware before
359 + setting the TKIP keys. If this check is not performed, some data
360 + may be sent out with incorrect MIC and cause synchronizarion
361 + errors with the AP */
362 + /* Check every 1ms for 100ms */
363 + for (count = 0; count < 100; count++) {
367 + ltv.typ = 0xFD91; // This RID not defined in HCF yet!!!
370 + _get_info( priv, <v);
372 + if (ltv.u.u16[0] == 0)
377 + wpa_printf(MSG_DEBUG, "%s: Timed out waiting for TxQ!", __FUNCTION__);
382 + /* Only load key as pairwise key for Hermes-II and II.5. For Hermes-I,
383 + fall through to the next case and load the pairwise key as
384 + a Group Key at index 0. */
385 + if (drv->type == WL_HERMES_2 || drv->type == WL_HERMES_25) {
387 + ltv.typ = CFG_ADD_TKIP_MAPPED_KEY;
389 + /* Load the BSSID */
390 + memcpy(<v.u.u8[buf_idx], addr, ETH_ALEN);
391 + buf_idx += ETH_ALEN;
393 + /* Load the TKIP key */
394 + memcpy(<v.u.u8[buf_idx], &key[0], 16);
398 + memcpy(<v.u.u8[buf_idx], tsc, 8);
402 + /* Copy the RSC from the supplicant to a local buffer, because
403 + the RSC doesn't always contain the padding needed */
404 + memcpy(rsc, seq, seq_len);
405 + memcpy(<v.u.u8[buf_idx], rsc, 8);
408 + /* Load the TxMIC key */
409 + memcpy(<v.u.u8[buf_idx], &key[16], 8);
412 + /* Load the RxMIC key */
413 + memcpy(<v.u.u8[buf_idx], &key[24], 8);
415 + /* Send the request to the Hermes */
416 + _put_info(priv, <v);
424 + ltv.typ = CFG_ADD_TKIP_DEFAULT_KEY;
426 + /* Load the key Index */
427 + ltv.u.u16[buf_idx] = key_idx;
429 + /* If this is a Tx Key, set bit 8000 */
431 + ltv.u.u16[buf_idx] |= 0x8000;
436 + /* Copy the RSC from the supplicant to a local buffer, because
437 + the RSC doesn't always contain the padding needed */
438 + memcpy(rsc, seq, seq_len);
439 + memcpy(<v.u.u8[buf_idx], rsc, 8);
442 + /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in
443 + CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */
444 + memcpy(<v.u.u8[buf_idx], key, key_len);
445 + buf_idx += key_len;
448 + memcpy(<v.u.u8[buf_idx], tsc, 8);
450 + /* Send the request to the Hermes */
451 + _put_info(priv, <v);
467 + if (drv->type == WL_HERMES_2 || drv->type == WL_HERMES_25) {
468 + /* Only clear a pairwise key for Hermes-II. For Hermes-I,
469 + fall through to the next case and clear the key as a
470 + Group Key at index 0. */
473 + ltv.typ = CFG_REMOVE_TKIP_MAPPED_KEY;
475 + memcpy(<v.u.u8[0], addr, ETH_ALEN);
477 + _put_info(priv, <v);
485 + /* Clear the Group TKIP keys by index */
487 + ltv.typ = CFG_REMOVE_TKIP_DEFAULT_KEY;
489 + ltv.u.u16[0] = key_idx;
491 + _put_info(priv, <v);
507 +static int wpa_driver_hermes_set_countermeasures(void *priv, int enabled)
511 + /* The supplicant handles all the timers related to MIC failure and
512 + countermeasures. When countermeasures are enabled, shut down the card;
513 + when disable, re-enable the card. Make sure that the EAPOL message
514 + is getting out before card disable */
516 + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
519 + ltv.typ = CFG_DRIVER_ENABLE;
520 + ltv.u.u16[0] = enabled ? 0 : 1;
522 + return _put_info(priv, <v);
526 +static int wpa_driver_hermes_set_drop_unencrypted(void *priv, int enabled)
530 + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
533 + ltv.typ = CFG_CNF_EXCL_UNENCRYPTED;
534 + ltv.u.u16[0] = enabled;
536 + return _put_info(priv, <v);
540 +static int wpa_driver_hermes_deauthenticate(void *priv, const u8 *addr,
543 + wpa_printf(MSG_DEBUG, "%s: *DUMMY* %d", __FUNCTION__, reason_code);
549 +static int wpa_driver_hermes_disassociate(void *priv, const u8 *addr, int reason_code)
553 + wpa_printf(MSG_DEBUG, "%s: reason=%d", __FUNCTION__, reason_code);
556 + ltv.typ = 0xFCC8; // This RID not defined in HCF yet!!!
557 + memcpy( <v.u.u8[0], addr, ETH_ALEN );
558 + ltv.u.u16[ETH_ALEN / 2] = reason_code;
560 + return _put_info( priv, <v);
564 +static int wpa_driver_hermes_associate(
565 + void *priv, struct wpa_driver_associate_params *params)
567 + struct wpa_driver_hermes_data *drv = priv;
570 + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
572 + wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
573 + "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
574 + __func__, priv, params->freq, params->pairwise_suite,
575 + params->group_suite, params->key_mgmt_suite,
576 + params->auth_alg, params->mode);
577 + if (params->bssid) {
578 + wpa_printf(MSG_DEBUG, " bssid=" MACSTR,
579 + MAC2STR(params->bssid));
581 + if (params->ssid) {
582 + wpa_hexdump_ascii(MSG_DEBUG, " ssid",
583 + params->ssid, params->ssid_len);
585 + if (params->wpa_ie) {
586 + wpa_hexdump(MSG_DEBUG, " wpa_ie",
587 + params->wpa_ie, params->wpa_ie_len);
591 + if (wpa_driver_hermes_set_wpa_ie(priv, params->wpa_ie, params->wpa_ie_len) < 0)
593 + if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
595 + if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) < 0)
597 +#ifdef UNSUPPORTED_IN_HERMES_DRIVER
598 + if (wpa_driver_wext_hermes_bssid(drv->wext, params->bssid) < 0)
606 +static int wpa_driver_hermes_get_bssid(void *priv, u8 *bssid)
608 + struct wpa_driver_hermes_data *drv = priv;
609 + return wpa_driver_wext_get_bssid(drv->wext, bssid);
613 +static int wpa_driver_hermes_get_ssid(void *priv, u8 *ssid)
615 + struct wpa_driver_hermes_data *drv = priv;
616 + return wpa_driver_wext_get_ssid(drv->wext, ssid);
620 +static int wpa_driver_hermes_scan(void *priv, const u8 *ssid, size_t ssid_len)
622 + struct wpa_driver_hermes_data *drv = priv;
623 + return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
627 +static int wpa_driver_hermes_get_scan_results(void *priv,
628 + struct wpa_scan_result *results,
631 + struct wpa_driver_hermes_data *drv = priv;
632 + return wpa_driver_wext_get_scan_results(drv->wext, results, max_size);
636 +static void * wpa_driver_hermes_init(void *ctx, const char *ifname)
638 + struct wpa_driver_hermes_data *drv;
640 + wpa_printf(MSG_DEBUG, "%s: %s", __FUNCTION__, ifname);
642 + drv = malloc(sizeof(*drv));
645 + memset(drv, 0, sizeof(*drv));
647 + /* Initialize wireless context */
648 + drv->wext = wpa_driver_wext_init(ctx, ifname);
649 + if (drv->wext == NULL) {
650 + perror("no wext context");
655 + strncpy(drv->ifname, ifname, sizeof(drv->ifname));
657 + drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
658 + if (drv->sock < 0) {
659 + perror("socket(PF_INET,SOCK_DGRAM)");
663 + _detect_hermes_type(drv);
668 + wpa_driver_wext_deinit(drv->wext);
675 +static void wpa_driver_hermes_deinit(void *priv)
677 + struct wpa_driver_hermes_data *drv = priv;
678 + wpa_driver_wext_deinit(drv->wext);
686 +struct wpa_driver_ops wpa_driver_hermes_ops = {
688 + .desc = "wpa_supplicant hermes driver",
690 + .init = wpa_driver_hermes_init,
691 + .deinit = wpa_driver_hermes_deinit,
693 + // from old driver_hermes.c:
694 + .get_bssid = wpa_driver_hermes_get_bssid,
695 + .get_ssid = wpa_driver_hermes_get_ssid,
696 + .set_wpa = wpa_driver_hermes_set_wpa,
697 + .set_key = wpa_driver_hermes_set_key,
698 + //.events_init = wpa_driver_wext_events_init,
699 + //.events_deinit = wpa_driver_wext_events_deinit,
700 + .set_countermeasures = wpa_driver_hermes_set_countermeasures,
701 + .set_drop_unencrypted = wpa_driver_hermes_set_drop_unencrypted,
702 + .scan = wpa_driver_hermes_scan,
703 + .get_scan_results = wpa_driver_hermes_get_scan_results,
704 + .deauthenticate = wpa_driver_hermes_deauthenticate,
705 + .disassociate = wpa_driver_hermes_disassociate,
706 + .associate = wpa_driver_hermes_associate,
710 + /* Not possible with current Hermes driver:
711 + .set_auth_alg = wpa_driver_hermes_set_auth_alg, */
715 +++ wpa_supplicant/driver_hermes.h
717 +#ifndef HERMES_DRIVER_H
718 +#define HERMES_DRIVER_H
720 +typedef unsigned char hcf_8;
721 +typedef unsigned short hcf_16;
722 +typedef unsigned long hcf_32;
723 +typedef hcf_16 hcf_io;
724 +typedef hcf_8 *wci_bufp;
729 + unsigned short * bufp;
731 +typedef RID_LOG_STRCT *RID_LOGP;
738 + hcf_16 version_major;
739 + hcf_16 version_minor;
740 +} CFG_FW_IDENTITY_STRCT;
743 + hcf_32 TxUnicastFrames;
744 + hcf_32 TxMulticastFrames;
745 + hcf_32 TxFragments;
746 + hcf_32 TxUnicastOctets;
747 + hcf_32 TxMulticastOctets;
748 + hcf_32 TxDeferredTransmissions;
749 + hcf_32 TxSingleRetryFrames;
750 + hcf_32 TxMultipleRetryFrames;
751 + hcf_32 TxRetryLimitExceeded;
753 + hcf_32 RxUnicastFrames;
754 + hcf_32 RxMulticastFrames;
755 + hcf_32 RxFragments;
756 + hcf_32 RxUnicastOctets;
757 + hcf_32 RxMulticastOctets;
758 + hcf_32 RxFCSErrors;
759 + hcf_32 RxDiscardsNoBuffer;
760 + hcf_32 TxDiscardsWrongSA;
761 + hcf_32 RxWEPUndecryptable;
762 + hcf_32 RxMsgInMsgFragments;
763 + hcf_32 RxMsgInBadMsgFragments;
764 + hcf_32 RxDiscardsWEPICVError;
765 + hcf_32 RxDiscardsWEPExcluded;
766 +} CFG_HERMES_TALLIES_STRCT;
769 + hcf_32 not_used_NoBufInq;
774 +} CFG_HCF_TALLIES_STRCT;
778 + hcf_16 IFB_IORange;
780 + hcf_32 IFB_TickIni;
782 + hcf_16 IFB_Version;
783 + hcf_16 IFB_CardStat;
784 + hcf_16 IFB_TraceLvl;
789 + hcf_16 IFB_MBInfoLen;
795 + RID_LOGP IFB_RIDLogp;
796 + hcf_16 IFB_Monitor;
799 + hcf_16 IFB_DefunctStat;
802 + hcf_16 IFB_ErrQualifier;
805 + hcf_16 IFB_LinkStat;
807 + void (*IFB_MICRxRtn)( hcf_32*, hcf_32 );
808 + void (*IFB_MICTxRtn)( hcf_32*, hcf_32 );
809 + hcf_16 IFB_rx_tlen;
810 + hcf_16 IFB_tx_tlen;
811 + hcf_8 IFB_rx_32[4];
812 + hcf_8 IFB_tx_32[4];
815 + hcf_16 IFB_DLTarget[2];
818 + hcf_16 IFB_DLOffset;
821 + hcf_16 volatile IFB_IntOffCnt;
822 + hcf_16 IFB_IntEnMask;
824 + CFG_FW_IDENTITY_STRCT IFB_FWIdentity;
826 + hcf_16 IFB_TallyTyp;
828 + CFG_HERMES_TALLIES_STRCT IFB_NIC_Tallies;
829 + CFG_HCF_TALLIES_STRCT IFB_HCF_Tallies;
834 +typedef IFB_STRCT* IFBP;
840 + char ifrn_name[16];
856 + hcf_8 u8[(512 - (sizeof(hcf_16) * 2)) / sizeof(hcf_8)];
857 + hcf_16 u16[(512 - (sizeof(hcf_16) * 2)) / sizeof(hcf_16)];
858 + hcf_32 u32[(512 - (sizeof(hcf_16) * 2)) / sizeof(hcf_32)];
863 +#define UIL_FUN_CONNECT 0x00
864 +#define UIL_FUN_DISCONNECT 0x01
865 +#define UIL_FUN_GET_INFO 0x04
866 +#define UIL_FUN_PUT_INFO 0x05
868 +#define GENERIC_INFO_ELEM 0xdd
869 +#define RSN_INFO_ELEM 0x30
871 +#define CFG_DRIVER_ENABLE 0x0902
872 +#define CFG_CNF_ENCRYPTION 0xFC20
873 +#define CFG_ADD_TKIP_DEFAULT_KEY 0xFCB4
874 +#define CFG_SET_WPA_AUTH_KEY_MGMT_SUITE 0xFCB5
875 +#define CFG_REMOVE_TKIP_DEFAULT_KEY 0xFCB6
876 +#define CFG_ADD_TKIP_MAPPED_KEY 0xFCB7
877 +#define CFG_REMOVE_TKIP_MAPPED_KEY 0xFCB8
878 +#define CFG_FW_IDENTITY 0xFD20
879 +#define CFG_CNF_EXCL_UNENCRYPTED 0xFC22
881 +#define HCF_SUCCESS 0x00
882 +#define UIL_SUCCESS 0x00
884 +#define COMP_ID_FW_STA 31
885 +#define COMP_ID_FW_AP 32
887 +#define WVLAN2_IOCTL_UIL SIOCDEVPRIVATE