Remove unused files.

This commit is contained in:
Rui Paulo 2010-06-14 15:52:50 +00:00
parent 85afbc31fa
commit 4f95cb6e9c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=209160
27 changed files with 0 additions and 16422 deletions

View File

@ -1,156 +0,0 @@
#ifndef APPLE80211_H
#define APPLE80211_H
/*
* Apple80211 framework definitions
* This is an undocumented interface and the definitions here are based on
* information from MacStumbler (http://www.macstumbler.com/Apple80211.h) and
* whatever related information can be found with google and experiments ;-).
*/
typedef struct __WirelessRef *WirelessRef;
typedef SInt32 WirelessError;
#define errWirelessNoError 0
typedef struct WirelessInfo {
UInt16 link_qual;
UInt16 comms_qual;
UInt16 signal;
UInt16 noise;
UInt16 port_stat;
UInt16 client_mode;
UInt16 res1;
UInt16 power;
UInt16 res2;
UInt8 bssID[6];
UInt8 ssid[34];
} WirelessInfo;
typedef struct WirelessInfo2 {
/* TODO - these are probably not in correct order or complete */
WirelessInfo info1;
UInt8 macAddress[6];
} WirelessInfo2;
typedef struct WirelessNetworkInfo {
UInt16 channel;
UInt16 noise;
UInt16 signal;
UInt8 bssid[6];
UInt16 beacon_int;
UInt16 capability;
UInt16 ssid_len;
UInt8 ssid[32];
} WirelessNetworkInfo;
typedef int wirelessKeyType; /* TODO */
int WirelessIsAvailable(void);
WirelessError WirelessAttach(WirelessRef *ref, UInt32 res);
WirelessError WirelessDetach(WirelessRef ref);
WirelessError WirelessPrivate(WirelessRef ref, void *in_ptr, int in_bytes,
void *out_ptr, int out_bytes);
WirelessError WirelessSetEnabled(WirelessRef ref, UInt8 enabled);
WirelessError WirelessGetEnabled(WirelessRef ref, UInt8 *enabled);
WirelessError WirelessSetPower(WirelessRef ref, UInt8 power);
WirelessError WirelessGetPower(WirelessRef ref, UInt8 *power);
WirelessError WirelessGetInfo(WirelessRef ref, WirelessInfo *info);
WirelessError WirelessGetInfo2(WirelessRef ref, WirelessInfo2 *info);
WirelessError WirelessScan(WirelessRef ref, CFArrayRef *results,
UInt32 strip_dups);
WirelessError WirelessScanSplit(WirelessRef ref, CFArrayRef *ap_results,
CFArrayRef *ibss_results, UInt32 strip_dups);
WirelessError WirelessDirectedScan(WirelessRef ref, CFArrayRef *results,
UInt32 strip_dups, CFStringRef ssid);
WirelessError WirelessDirectedScan2(WirelessRef ref, CFDataRef ssid,
UInt32 strip_dups, CFArrayRef *results);
WirelessError WirelessJoin(WirelessRef ref, CFStringRef ssid);
WirelessError WirelessJoinWEP(WirelessRef ref, CFStringRef ssid,
CFStringRef passwd);
WirelessError WirelessJoin8021x(WirelessRef ref, CFStringRef ssid);
/*
* Set WEP key
* ref: wireless reference from WirelessAttach()
* type: ?
* key_idx: 0..3
* key_len: 13 for WEP-104 or 0 for clearing the key
* key: Pointer to the key or %NULL if key_len = 0
*/
WirelessError WirelessSetKey(WirelessRef ref, wirelessKeyType type,
int key_idx, int key_len,
const unsigned char *key);
/*
* Set WPA key (e.g., PMK for 4-way handshake)
* ref: wireless reference from WirelessAttach()
* type: 0..4; 1 = PMK
* key_len: 16, 32, or 0
* key: Pointer to the key or %NULL if key_len = 0
*/
WirelessError WirelessSetWPAKey(WirelessRef ref, wirelessKeyType type,
int key_len, const unsigned char *key);
WirelessError WirelessAssociate(WirelessRef ref, int type, CFDataRef ssid,
CFStringRef key);
WirelessError WirelessAssociate2(WirelessRef ref, CFDictionaryRef scan_res,
CFStringRef key);
WirelessError WirelessDisassociate(WirelessRef ref);
/*
* Get a copy of scan results for the given SSID
* The returned dictionary includes following entries:
* beaconInterval: CFNumber(kCFNumberSInt32Type)
* SSID: CFData buffer of the SSID
* isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 = WPA2
* name: Name of the network (SSID string)
* BSSID: CFData buffer of the BSSID
* channel: CFNumber(kCFNumberSInt32Type)
* signal: CFNumber(kCFNumberSInt32Type)
* appleIE: CFData
* WPSNOPINRequired: CFBoolean
* noise: CFNumber(kCFNumberSInt32Type)
* capability: CFNumber(kCFNumberSInt32Type)
* uniCipher: CFArray of CFNumber(kCFNumberSInt32Type)
* appleIE_Version: CFNumber(kCFNumberSInt32Type)
* appleIE_Robust: CFBoolean
* WPSConfigured: CFBoolean
* scanWasDirected: CFBoolean
* appleIE_Product: CFNumber(kCFNumberSInt32Type)
* authModes: CFArray of CFNumber(kCFNumberSInt32Type)
* multiCipher: CFNumber(kCFNumberSInt32Type)
*/
CFDictionaryRef WirelessSafeDirectedScanCopy(WirelessRef ref, CFDataRef ssid);
/*
* Get information about the current association
* The returned dictionary includes following entries:
* keyData: CFData buffer of the key (e.g., 32-octet PSK)
* multiCipher: CFNumber(kCFNumberSInt32Type); 0 = none, 5 = CCMP?
* channel: CFNumber(kCFNumberSInt32Type)
* isIBSS: CFBoolean
* authMode: CFNumber(kCFNumberSInt32Type); 2 = WPA-Personal; 3 = open,
* 129 = WPA2-Enterprise
* isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 == WPA2
* SSID: CFData buffer of the SSID
* cipherMode: CFNumber(kCFNumberSInt32Type); 0 = none, 4 = CCMP?
*/
CFDictionaryRef WirelessGetAssociationInfo(WirelessRef ref);
WirelessError WirelessConfigure(WirelessRef ref);
/*
* Get ASP information
* The returned dictionary includes following entries:
* Version: version number (e.g., 3.0)
* Channel: channel (e.g., 1)
* Vendor: vendor (e.g., 2)
*/
CFDictionaryRef WirelessGetInfoASP(void);
/*
* Get a copy of the interface dictionary
* The returned dictionary has a key,value pairs for wireless interfaces.
* The key is the interface name and the value is the driver identifier, e.g.,
* en1: com.apple.driver.AirPort.Atheros
*/
CFDictionaryRef WirelessCopyInterfaceDict(void);
#endif /* APPLE80211_H */

View File

@ -1,189 +0,0 @@
#include "includes.h"
#include <dlfcn.h>
#include "common.h"
#include <CoreFoundation/CoreFoundation.h>
#include "MobileApple80211.h"
/*
* Code for dynamically loading Apple80211 functions from Aeropuerto to avoid
* having to link with full Preferences.framework.
*/
static void *aeropuerto = NULL;
int _Apple80211Initialized(void)
{
return aeropuerto ? 1 : 0;
}
static int (*__Apple80211Open)(Apple80211Ref *ctx) = NULL;
int Apple80211Open(Apple80211Ref *ctx)
{
return __Apple80211Open(ctx);
}
static int (*__Apple80211Close)(Apple80211Ref ctx) = NULL;
int Apple80211Close(Apple80211Ref ctx)
{
return __Apple80211Close(ctx);
}
static int (*__Apple80211GetIfListCopy)(Apple80211Ref handle, CFArrayRef *list)
= NULL;
int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list)
{
return __Apple80211GetIfListCopy(handle, list);
}
static int (*__Apple80211BindToInterface)(Apple80211Ref handle,
CFStringRef interface) = NULL;
int Apple80211BindToInterface(Apple80211Ref handle,
CFStringRef interface)
{
return __Apple80211BindToInterface(handle, interface);
}
static int (*__Apple80211GetInterfaceNameCopy)(Apple80211Ref handle,
CFStringRef *name) = NULL;
int Apple80211GetInterfaceNameCopy(Apple80211Ref handle,
CFStringRef *name)
{
return __Apple80211GetInterfaceNameCopy(handle, name);
}
static int (*__Apple80211GetInfoCopy)(Apple80211Ref handle,
CFDictionaryRef *info) = NULL;
int Apple80211GetInfoCopy(Apple80211Ref handle,
CFDictionaryRef *info)
{
return __Apple80211GetInfoCopy(handle, info);
}
static int (*__Apple80211GetPower)(Apple80211Ref handle, char *pwr) = NULL;
int Apple80211GetPower(Apple80211Ref handle, char *pwr)
{
return __Apple80211GetPower(handle, pwr);
}
static int (*__Apple80211SetPower)(Apple80211Ref handle, char pwr) = NULL;
int Apple80211SetPower(Apple80211Ref handle, char pwr)
{
return __Apple80211SetPower(handle, pwr);
}
static int (*__Apple80211Scan)(Apple80211Ref handle, CFArrayRef *list,
CFDictionaryRef parameters) = NULL;
int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list,
CFDictionaryRef parameters)
{
return __Apple80211Scan(handle, list, parameters);
}
static int (*__Apple80211Associate)(Apple80211Ref handle, CFDictionaryRef bss,
CFStringRef password) = NULL;
int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss,
CFStringRef password)
{
return __Apple80211Associate(handle, bss, password);
}
static int (*__Apple80211AssociateAndCopyInfo)(Apple80211Ref handle,
CFDictionaryRef bss,
CFStringRef password,
CFDictionaryRef *info) =
NULL;
int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss,
CFStringRef password, CFDictionaryRef *info)
{
return __Apple80211AssociateAndCopyInfo(handle, bss, password, info);
}
static int (*__Apple80211CopyValue)(Apple80211Ref handle, int field,
CFDictionaryRef arg2, void *value) = NULL;
int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2,
void *value)
{
return __Apple80211CopyValue(handle, field, arg2, value);
}
#define DLSYM(s) \
do { \
__ ## s = dlsym(aeropuerto, #s); \
if (__ ## s == NULL) { \
wpa_printf(MSG_ERROR, "MobileApple80211: Could not resolve " \
"symbol '" #s "' (%s)", dlerror()); \
err = 1; \
} \
} while (0)
__attribute__ ((constructor))
void _Apple80211_constructor(void)
{
const char *fname = "/System/Library/SystemConfiguration/"
"Aeropuerto.bundle/Aeropuerto";
int err = 0;
aeropuerto = dlopen(fname, RTLD_LAZY);
if (!aeropuerto) {
wpa_printf(MSG_ERROR, "MobileApple80211: Failed to open %s "
"for symbols", fname);
return;
}
DLSYM(Apple80211Open);
DLSYM(Apple80211Close);
DLSYM(Apple80211GetIfListCopy);
DLSYM(Apple80211BindToInterface);
DLSYM(Apple80211GetInterfaceNameCopy);
DLSYM(Apple80211GetInfoCopy);
DLSYM(Apple80211GetPower);
DLSYM(Apple80211SetPower);
DLSYM(Apple80211Scan);
DLSYM(Apple80211Associate);
DLSYM(Apple80211AssociateAndCopyInfo);
DLSYM(Apple80211CopyValue);
if (err) {
dlclose(aeropuerto);
aeropuerto = NULL;
}
}
__attribute__ ((destructor))
void _Apple80211_destructor(void)
{
if (aeropuerto) {
dlclose(aeropuerto);
aeropuerto = NULL;
}
}

View File

@ -1,43 +0,0 @@
#ifndef MOBILEAPPLE80211_H
#define MOBILEAPPLE80211_H
/*
* MobileApple80211 interface for iPhone/iPod touch
* These functions are available from Aeropuerto.
*/
struct Apple80211;
typedef struct Apple80211 *Apple80211Ref;
int Apple80211Open(Apple80211Ref *ctx);
int Apple80211Close(Apple80211Ref ctx);
int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list);
int Apple80211BindToInterface(Apple80211Ref handle,
CFStringRef interface);
int Apple80211GetInterfaceNameCopy(Apple80211Ref handle,
CFStringRef *name);
int Apple80211GetInfoCopy(Apple80211Ref handle,
CFDictionaryRef *info);
int Apple80211GetPower(Apple80211Ref handle, char *pwr);
int Apple80211SetPower(Apple80211Ref handle, char pwr);
/* parameters can be NULL; returns scan results in CFArrayRef *list;
* caller will need to free with CFRelease() */
int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list,
CFDictionaryRef parameters);
int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss,
CFStringRef password);
int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss,
CFStringRef password,
CFDictionaryRef *info);
enum {
APPLE80211_VALUE_SSID = 1,
APPLE80211_VALUE_BSSID = 9
};
int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2,
void *value);
#endif /* MOBILEAPPLE80211_H */

View File

@ -1,506 +0,0 @@
/*
* WPA Supplicant - Driver interaction with Atmel Wireless LAN drivers
* Copyright (c) 2000-2005, ATMEL Corporation
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
/******************************************************************************
Copyright 2000-2001 ATMEL Corporation.
WPA Supplicant - driver interaction with Atmel Wireless lan drivers.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Atmel wireless lan drivers; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
/*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "wireless_copy.h"
#include "common.h"
#include "driver.h"
#include "driver_wext.h"
struct wpa_driver_atmel_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
};
#define ATMEL_WPA_IOCTL (SIOCIWFIRSTPRIV + 2)
#define ATMEL_WPA_IOCTL_PARAM (SIOCIWFIRSTPRIV + 3)
#define ATMEL_WPA_IOCTL_GET_PARAM (SIOCIWFIRSTPRIV + 4)
/* ATMEL_WPA_IOCTL ioctl() cmd: */
enum {
SET_WPA_ENCRYPTION = 1,
SET_CIPHER_SUITES = 2,
MLME_STA_DEAUTH = 3,
MLME_STA_DISASSOC = 4
};
/* ATMEL_WPA_IOCTL_PARAM ioctl() cmd: */
enum {
ATMEL_PARAM_WPA = 1,
ATMEL_PARAM_PRIVACY_INVOKED = 2,
ATMEL_PARAM_WPA_TYPE = 3
};
#define MAX_KEY_LENGTH 40
struct atmel_param{
unsigned char sta_addr[6];
int cmd;
u8 alg;
u8 key_idx;
u8 set_tx;
u8 seq[8];
u8 seq_len;
u16 key_len;
u8 key[MAX_KEY_LENGTH];
struct{
int reason_code;
u8 state;
}mlme;
u8 pairwise_suite;
u8 group_suite;
u8 key_mgmt_suite;
};
static int atmel_ioctl(struct wpa_driver_atmel_data *drv,
struct atmel_param *param,
int len, int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = (caddr_t) param;
iwr.u.data.length = len;
if (ioctl(drv->sock, ATMEL_WPA_IOCTL, &iwr) < 0) {
int ret;
ret = errno;
if (show_err)
perror("ioctl[ATMEL_WPA_IOCTL]");
return ret;
}
return 0;
}
static int atmel2param(struct wpa_driver_atmel_data *drv, int param, int value)
{
struct iwreq iwr;
int *i, ret = 0;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i++ = param;
*i++ = value;
if (ioctl(drv->sock, ATMEL_WPA_IOCTL_PARAM, &iwr) < 0) {
perror("ioctl[ATMEL_WPA_IOCTL_PARAM]");
ret = -1;
}
return ret;
}
#if 0
static int wpa_driver_atmel_set_wpa_ie(struct wpa_driver_atmel_data *drv,
const char *wpa_ie, size_t wpa_ie_len)
{
struct atmel_param *param;
int res;
size_t blen = ATMEL_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
if (blen < sizeof(*param))
blen = sizeof(*param);
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = ATMEL_SET_GENERIC_ELEMENT;
param->u.generic_elem.len = wpa_ie_len;
os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
res = atmel_ioctl(drv, param, blen, 1);
os_free(param);
return res;
}
#endif
static int wpa_driver_atmel_set_wpa(void *priv, int enabled)
{
struct wpa_driver_atmel_data *drv = priv;
int ret = 0;
printf("wpa_driver_atmel_set_wpa %s\n", drv->ifname);
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
#if 0
if (!enabled && wpa_driver_atmel_set_wpa_ie(drv, NULL, 0) < 0)
ret = -1;
#endif
if (atmel2param(drv, ATMEL_PARAM_PRIVACY_INVOKED, enabled) < 0)
ret = -1;
if (atmel2param(drv, ATMEL_PARAM_WPA, enabled) < 0)
ret = -1;
return ret;
}
static int wpa_driver_atmel_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx,
int set_tx, const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_atmel_data *drv = priv;
int ret = 0;
struct atmel_param *param;
u8 *buf;
u8 alg_type;
size_t blen;
char *alg_name;
switch (alg) {
case WPA_ALG_NONE:
alg_name = "none";
alg_type = 0;
break;
case WPA_ALG_WEP:
alg_name = "WEP";
alg_type = 1;
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
alg_type = 2;
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
alg_type = 3;
break;
default:
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > 8)
return -2;
blen = sizeof(*param) + key_len;
buf = os_zalloc(blen);
if (buf == NULL)
return -1;
param = (struct atmel_param *) buf;
param->cmd = SET_WPA_ENCRYPTION;
if (addr == NULL)
os_memset(param->sta_addr, 0xff, ETH_ALEN);
else
os_memcpy(param->sta_addr, addr, ETH_ALEN);
param->alg = alg_type;
param->key_idx = key_idx;
param->set_tx = set_tx;
os_memcpy(param->seq, seq, seq_len);
param->seq_len = seq_len;
param->key_len = key_len;
os_memcpy((u8 *)param->key, key, key_len);
if (atmel_ioctl(drv, param, blen, 1)) {
wpa_printf(MSG_WARNING, "Failed to set encryption.");
/* TODO: show key error*/
ret = -1;
}
os_free(buf);
return ret;
}
static int wpa_driver_atmel_set_countermeasures(void *priv,
int enabled)
{
/* FIX */
printf("wpa_driver_atmel_set_countermeasures - not yet "
"implemented\n");
return 0;
}
static int wpa_driver_atmel_set_drop_unencrypted(void *priv,
int enabled)
{
/* FIX */
printf("wpa_driver_atmel_set_drop_unencrypted - not yet "
"implemented\n");
return 0;
}
static int wpa_driver_atmel_mlme(void *priv, const u8 *addr, int cmd,
int reason_code)
{
struct wpa_driver_atmel_data *drv = priv;
struct atmel_param param;
int ret;
int mgmt_error = 0xaa;
os_memset(&param, 0, sizeof(param));
os_memcpy(param.sta_addr, addr, ETH_ALEN);
param.cmd = cmd;
param.mlme.reason_code = reason_code;
param.mlme.state = mgmt_error;
ret = atmel_ioctl(drv, &param, sizeof(param), 1);
return ret;
}
#if 0
static int wpa_driver_atmel_set_suites(struct wpa_driver_atmel_data *drv,
u8 pairwise_suite, u8 group_suite,
u8 key_mgmt_suite)
{
struct atmel_param param;
int ret;
os_memset(&param, 0, sizeof(param));
param.cmd = SET_CIPHER_SUITES;
param.pairwise_suite = pairwise_suite;
param.group_suite = group_suite;
param.key_mgmt_suite = key_mgmt_suite;
ret = atmel_ioctl(drv, &param, sizeof(param), 1);
return ret;
}
#endif
static int wpa_driver_atmel_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_atmel_data *drv = priv;
printf("wpa_driver_atmel_deauthenticate\n");
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DEAUTH,
reason_code);
}
static int wpa_driver_atmel_disassociate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_atmel_data *drv = priv;
printf("wpa_driver_atmel_disassociate\n");
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DISASSOC,
reason_code);
}
#if 0
/* Atmel driver uses specific values for each cipher suite */
static int convertSuiteToDriver(wpa_cipher suite)
{
u8 suite_type;
switch(suite) {
case CIPHER_NONE:
suite_type = 0;
break;
case CIPHER_WEP40:
suite_type = 1;
break;
case CIPHER_TKIP:
suite_type = 2;
break;
case CIPHER_WEP104:
suite_type = 5;
break;
case CIPHER_CCMP:
suite_type = 3;
break;
default:
suite_type = 2;
}
return suite_type;
}
#endif
static int
wpa_driver_atmel_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_atmel_data *drv = priv;
int ret = 0;
#if 0
u8 pairwise_suite_driver;
u8 group_suite_driver;
u8 key_mgmt_suite_driver;
pairwise_suite_driver = convertSuiteToDriver(params->pairwise_suite);
group_suite_driver = convertSuiteToDriver(params->group_suite);
key_mgmt_suite_driver = convertSuiteToDriver(params->key_mgmt_suite);
if (wpa_driver_atmel_set_suites(drv, pairwise_suite_driver,
group_suite_driver,
key_mgmt_suite_driver) < 0){
printf("wpa_driver_atmel_set_suites.\n");
ret = -1;
}
if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) {
printf("wpa_driver_atmel_set_freq.\n");
ret = -1;
}
#endif
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len)
< 0) {
printf("FAILED : wpa_driver_atmel_set_ssid.\n");
ret = -1;
}
if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) {
printf("FAILED : wpa_driver_atmel_set_bssid.\n");
ret = -1;
}
return ret;
}
static int wpa_driver_atmel_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_atmel_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_atmel_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_atmel_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static int wpa_driver_atmel_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_atmel_data *drv = priv;
return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
}
static struct wpa_scan_results * wpa_driver_atmel_get_scan_results(void *priv)
{
struct wpa_driver_atmel_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_atmel_set_operstate(void *priv, int state)
{
struct wpa_driver_atmel_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static void * wpa_driver_atmel_init(void *ctx, const char *ifname)
{
struct wpa_driver_atmel_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL) {
os_free(drv);
return NULL;
}
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0) {
wpa_driver_wext_deinit(drv->wext);
os_free(drv);
return NULL;
}
return drv;
}
static void wpa_driver_atmel_deinit(void *priv)
{
struct wpa_driver_atmel_data *drv = priv;
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_atmel_ops = {
.name = "atmel",
.desc = "ATMEL AT76C5XXx (USB, PCMCIA)",
.get_bssid = wpa_driver_atmel_get_bssid,
.get_ssid = wpa_driver_atmel_get_ssid,
.set_wpa = wpa_driver_atmel_set_wpa,
.set_key = wpa_driver_atmel_set_key,
.init = wpa_driver_atmel_init,
.deinit = wpa_driver_atmel_deinit,
.set_countermeasures = wpa_driver_atmel_set_countermeasures,
.set_drop_unencrypted = wpa_driver_atmel_set_drop_unencrypted,
.scan = wpa_driver_atmel_scan,
.get_scan_results2 = wpa_driver_atmel_get_scan_results,
.deauthenticate = wpa_driver_atmel_deauthenticate,
.disassociate = wpa_driver_atmel_disassociate,
.associate = wpa_driver_atmel_associate,
.set_operstate = wpa_driver_atmel_set_operstate,
};

View File

@ -1,604 +0,0 @@
/*
* WPA Supplicant - driver interaction with old Broadcom wl.o driver
* Copyright (c) 2004, Nikki Chumkov <nikki@gattaca.ru>
* Copyright (c) 2004, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*
* Please note that the newer Broadcom driver ("hybrid Linux driver") supports
* Linux wireless extensions and does not need (or even work) with this old
* driver wrapper. Use driver_wext.c with that driver.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "common.h"
#if 0
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
#else
#include <linux/if_packet.h>
#include <linux/if_ether.h> /* The L2 protocols */
#endif
#include <net/if.h>
#include <typedefs.h>
/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys
* WRT54G GPL tarball. */
#include <wlioctl.h>
#include "driver.h"
#include "eloop.h"
struct wpa_driver_broadcom_data {
void *ctx;
int ioctl_sock;
int event_sock;
char ifname[IFNAMSIZ + 1];
};
#ifndef WLC_DEAUTHENTICATE
#define WLC_DEAUTHENTICATE 143
#endif
#ifndef WLC_DEAUTHENTICATE_WITH_REASON
#define WLC_DEAUTHENTICATE_WITH_REASON 201
#endif
#ifndef WLC_SET_TKIP_COUNTERMEASURES
#define WLC_SET_TKIP_COUNTERMEASURES 202
#endif
#if !defined(PSK_ENABLED) /* NEW driver interface */
#define WL_VERSION 360130
/* wireless authentication bit vector */
#define WPA_ENABLED 1
#define PSK_ENABLED 2
#define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED)
#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED)
#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED))
#define WSEC_PRIMARY_KEY WL_PRIMARY_KEY
typedef wl_wsec_key_t wsec_key_t;
#endif
typedef struct {
uint32 val;
struct ether_addr ea;
uint16 res;
} wlc_deauth_t;
static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
void *timeout_ctx);
static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd,
void *buf, int len)
{
struct ifreq ifr;
wl_ioctl_t ioc;
int ret = 0;
wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)",
drv->ifname, cmd, len, buf);
/* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */
ioc.cmd = cmd;
ioc.buf = buf;
ioc.len = len;
os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ);
ifr.ifr_data = (caddr_t) &ioc;
if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) {
if (cmd != WLC_GET_MAGIC)
perror(ifr.ifr_name);
wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d",
cmd, ret);
}
return ret;
}
static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_broadcom_data *drv = priv;
if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0)
return 0;
os_memset(bssid, 0, ETH_ALEN);
return -1;
}
static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_broadcom_data *drv = priv;
wlc_ssid_t s;
if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1)
return -1;
os_memcpy(ssid, s.SSID, s.SSID_len);
return s.SSID_len;
}
static int wpa_driver_broadcom_set_wpa(void *priv, int enable)
{
struct wpa_driver_broadcom_data *drv = priv;
unsigned int wauth, wsec;
struct ether_addr ea;
os_memset(&ea, enable ? 0xff : 0, sizeof(ea));
if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) ==
-1 ||
broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1)
return -1;
if (enable) {
wauth = PSK_ENABLED;
wsec = TKIP_ENABLED;
} else {
wauth = 255;
wsec &= ~(TKIP_ENABLED | AES_ENABLED);
}
if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) ==
-1 ||
broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1)
return -1;
/* FIX: magic number / error handling? */
broadcom_ioctl(drv, 122, &ea, sizeof(ea));
return 0;
}
static int wpa_driver_broadcom_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_broadcom_data *drv = priv;
int ret;
wsec_key_t wkt;
os_memset(&wkt, 0, sizeof wkt);
wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d",
set_tx ? "PRIMARY " : "", key_idx, alg);
if (key && key_len > 0)
wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len);
switch (alg) {
case WPA_ALG_NONE:
wkt.algo = CRYPTO_ALGO_OFF;
break;
case WPA_ALG_WEP:
wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */
break;
case WPA_ALG_TKIP:
wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */
break;
case WPA_ALG_CCMP:
wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM;
* AES_OCB_MSDU, AES_OCB_MPDU? */
break;
default:
wkt.algo = CRYPTO_ALGO_NALG;
break;
}
if (seq && seq_len > 0)
wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len);
if (addr)
wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN);
wkt.index = key_idx;
wkt.len = key_len;
if (key && key_len > 0) {
os_memcpy(wkt.data, key, key_len);
if (key_len == 32) {
/* hack hack hack XXX */
os_memcpy(&wkt.data[16], &key[24], 8);
os_memcpy(&wkt.data[24], &key[16], 8);
}
}
/* wkt.algo = CRYPTO_ALGO_...; */
wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY;
if (addr && set_tx)
os_memcpy(&wkt.ea, addr, sizeof(wkt.ea));
ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt));
if (addr && set_tx) {
/* FIX: magic number / error handling? */
broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea));
}
return ret;
}
static void wpa_driver_broadcom_event_receive(int sock, void *ctx,
void *sock_ctx)
{
char buf[8192];
int left;
wl_wpa_header_t *wwh;
union wpa_event_data data;
if ((left = recv(sock, buf, sizeof buf, 0)) < 0)
return;
wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left);
if ((size_t) left < sizeof(wl_wpa_header_t))
return;
wwh = (wl_wpa_header_t *) buf;
if (wwh->snap.type != WL_WPA_ETHER_TYPE)
return;
if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0)
return;
os_memset(&data, 0, sizeof(data));
switch (wwh->type) {
case WLC_ASSOC_MSG:
left -= WL_WPA_HEADER_LEN;
wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)",
left);
if (left > 0) {
data.assoc_info.resp_ies = os_malloc(left);
if (data.assoc_info.resp_ies == NULL)
return;
os_memcpy(data.assoc_info.resp_ies,
buf + WL_WPA_HEADER_LEN, left);
data.assoc_info.resp_ies_len = left;
wpa_hexdump(MSG_MSGDUMP, "BROADCOM: copying %d bytes "
"into resp_ies",
data.assoc_info.resp_ies, left);
}
/* data.assoc_info.req_ies = NULL; */
/* data.assoc_info.req_ies_len = 0; */
wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
break;
case WLC_DISASSOC_MSG:
wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE");
wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
break;
case WLC_PTK_MIC_MSG:
wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE");
data.michael_mic_failure.unicast = 1;
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
break;
case WLC_GTK_MIC_MSG:
wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE");
data.michael_mic_failure.unicast = 0;
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
break;
default:
wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)",
wwh->type);
break;
}
os_free(data.assoc_info.resp_ies);
}
static void * wpa_driver_broadcom_init(void *ctx, const char *ifname)
{
int s;
struct sockaddr_ll ll;
struct wpa_driver_broadcom_data *drv;
struct ifreq ifr;
/* open socket to kernel */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return NULL;
}
/* do it */
os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror(ifr.ifr_name);
return NULL;
}
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->ioctl_sock = s;
s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2));
if (s < 0) {
perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))");
close(drv->ioctl_sock);
os_free(drv);
return NULL;
}
os_memset(&ll, 0, sizeof(ll));
ll.sll_family = AF_PACKET;
ll.sll_protocol = ntohs(ETH_P_802_2);
ll.sll_ifindex = ifr.ifr_ifindex;
ll.sll_hatype = 0;
ll.sll_pkttype = PACKET_HOST;
ll.sll_halen = 0;
if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
perror("bind(netlink)");
close(s);
close(drv->ioctl_sock);
os_free(drv);
return NULL;
}
eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx,
NULL);
drv->event_sock = s;
return drv;
}
static void wpa_driver_broadcom_deinit(void *priv)
{
struct wpa_driver_broadcom_data *drv = priv;
eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
eloop_unregister_read_sock(drv->event_sock);
close(drv->event_sock);
close(drv->ioctl_sock);
os_free(drv);
}
static int wpa_driver_broadcom_set_countermeasures(void *priv,
int enabled)
{
#if 0
struct wpa_driver_broadcom_data *drv = priv;
/* FIX: ? */
return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled,
sizeof(enabled));
#else
return 0;
#endif
}
static int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled)
{
struct wpa_driver_broadcom_data *drv = priv;
/* SET_EAP_RESTRICT, SET_WEP_RESTRICT */
int restrict = (enabled ? 1 : 0);
if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT,
&restrict, sizeof(restrict)) < 0 ||
broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT,
&restrict, sizeof(restrict)) < 0)
return -1;
return 0;
}
static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
void *timeout_ctx)
{
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
static int wpa_driver_broadcom_scan(void *priv, const u8 *ssid,
size_t ssid_len)
{
struct wpa_driver_broadcom_data *drv = priv;
wlc_ssid_t wst = { 0, "" };
if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) {
wst.SSID_len = ssid_len;
os_memcpy(wst.SSID, ssid, ssid_len);
}
if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0)
return -1;
eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv,
drv->ctx);
return 0;
}
static const int frequency_list[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484
};
struct bss_ie_hdr {
u8 elem_id;
u8 len;
u8 oui[3];
/* u8 oui_type; */
/* u16 version; */
} __attribute__ ((packed));
static int
wpa_driver_broadcom_get_scan_results(void *priv,
struct wpa_scan_result *results,
size_t max_size)
{
struct wpa_driver_broadcom_data *drv = priv;
char *buf;
wl_scan_results_t *wsr;
wl_bss_info_t *wbi;
size_t ap_num;
buf = os_malloc(WLC_IOCTL_MAXLEN);
if (buf == NULL)
return -1;
wsr = (wl_scan_results_t *) buf;
wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr);
wsr->version = 107;
wsr->count = 0;
if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) {
os_free(buf);
return -1;
}
os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) {
int left;
struct bss_ie_hdr *ie;
os_memcpy(results[ap_num].bssid, &wbi->BSSID, ETH_ALEN);
os_memcpy(results[ap_num].ssid, wbi->SSID, wbi->SSID_len);
results[ap_num].ssid_len = wbi->SSID_len;
results[ap_num].freq = frequency_list[wbi->channel - 1];
/* get ie's */
wpa_hexdump(MSG_MSGDUMP, "BROADCOM: AP IEs",
(u8 *) wbi + sizeof(*wbi), wbi->ie_length);
ie = (struct bss_ie_hdr *) ((u8 *) wbi + sizeof(*wbi));
for (left = wbi->ie_length; left > 0;
left -= (ie->len + 2), ie = (struct bss_ie_hdr *)
((u8 *) ie + 2 + ie->len)) {
wpa_printf(MSG_MSGDUMP, "BROADCOM: IE: id:%x, len:%d",
ie->elem_id, ie->len);
if (ie->len >= 3)
wpa_printf(MSG_MSGDUMP,
"BROADCOM: oui:%02x%02x%02x",
ie->oui[0], ie->oui[1], ie->oui[2]);
if (ie->elem_id != 0xdd ||
ie->len < 6 ||
os_memcmp(ie->oui, WPA_OUI, 3) != 0)
continue;
os_memcpy(results[ap_num].wpa_ie, ie, ie->len + 2);
results[ap_num].wpa_ie_len = ie->len + 2;
break;
}
wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length);
}
wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu "
"BSSes)",
wsr->buflen, (unsigned long) ap_num);
os_free(buf);
return ap_num;
}
static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_broadcom_data *drv = priv;
wlc_deauth_t wdt;
wdt.val = reason_code;
os_memcpy(&wdt.ea, addr, sizeof wdt.ea);
wdt.res = 0x7fff;
return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt,
sizeof(wdt));
}
static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_broadcom_data *drv = priv;
return broadcom_ioctl(drv, WLC_DISASSOC, 0, 0);
}
static int
wpa_driver_broadcom_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_broadcom_data *drv = priv;
wlc_ssid_t s;
int infra = 1;
int auth = 0;
int wsec = 4;
int dummy;
int wpa_auth;
s.SSID_len = params->ssid_len;
os_memcpy(s.SSID, params->ssid, params->ssid_len);
switch (params->pairwise_suite) {
case CIPHER_WEP40:
case CIPHER_WEP104:
wsec = 1;
break;
case CIPHER_TKIP:
wsec = 2;
break;
case CIPHER_CCMP:
wsec = 4;
break;
default:
wsec = 0;
break;
}
switch (params->key_mgmt_suite) {
case KEY_MGMT_802_1X:
wpa_auth = 1;
break;
case KEY_MGMT_PSK:
wpa_auth = 2;
break;
default:
wpa_auth = 255;
break;
}
/* printf("broadcom_associate: %u %u %u\n", pairwise_suite,
* group_suite, key_mgmt_suite);
* broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec));
* wl join uses wlc_sec_wep here, not wlc_set_wsec */
if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 ||
broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth,
sizeof(wpa_auth)) < 0 ||
broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 ||
broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 ||
broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 ||
broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 ||
broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0)
return -1;
return 0;
}
const struct wpa_driver_ops wpa_driver_broadcom_ops = {
.name = "broadcom",
.desc = "Broadcom wl.o driver",
.get_bssid = wpa_driver_broadcom_get_bssid,
.get_ssid = wpa_driver_broadcom_get_ssid,
.set_wpa = wpa_driver_broadcom_set_wpa,
.set_key = wpa_driver_broadcom_set_key,
.init = wpa_driver_broadcom_init,
.deinit = wpa_driver_broadcom_deinit,
.set_countermeasures = wpa_driver_broadcom_set_countermeasures,
.set_drop_unencrypted = wpa_driver_broadcom_set_drop_unencrypted,
.scan = wpa_driver_broadcom_scan,
.get_scan_results = wpa_driver_broadcom_get_scan_results,
.deauthenticate = wpa_driver_broadcom_deauthenticate,
.disassociate = wpa_driver_broadcom_disassociate,
.associate = wpa_driver_broadcom_associate,
};

View File

@ -1,795 +0,0 @@
/*
* WPA Supplicant - driver interaction with BSD net80211 layer
* Copyright (c) 2004, Sam Leffler <sam@errno.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "ieee802_11_defs.h"
#include <net/if.h>
#ifdef __NetBSD__
#include <net/if_ether.h>
#define COMPAT_FREEBSD_NET80211
#else
#include <net/ethernet.h>
#endif
#include <net80211/_ieee80211.h>
#include <net80211/ieee80211.h>
#include <net80211/ieee80211_crypto.h>
#include <net80211/ieee80211_ioctl.h>
struct wpa_driver_bsd_data {
int sock; /* open socket for 802.11 ioctls */
int route; /* routing socket for events */
char ifname[IFNAMSIZ+1]; /* interface name */
unsigned int ifindex; /* interface index */
void *ctx;
int prev_roaming; /* roaming state to restore on deinit */
int prev_privacy; /* privacy state to restore on deinit */
int prev_wpa; /* wpa state to restore on deinit */
};
static int
set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
{
struct ieee80211req ireq;
os_memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
ireq.i_type = op;
ireq.i_len = arg_len;
ireq.i_data = (void *) arg;
if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
op, arg_len, strerror(errno));
return -1;
}
return 0;
}
static int
get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
{
struct ieee80211req ireq;
os_memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
ireq.i_type = op;
ireq.i_len = arg_len;
ireq.i_data = arg;
if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
op, arg_len, strerror(errno));
return -1;
}
return ireq.i_len;
}
static int
set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
{
struct ieee80211req ireq;
os_memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
ireq.i_type = op;
ireq.i_val = arg;
if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
op, arg, strerror(errno));
return -1;
}
return 0;
}
static int
get80211param(struct wpa_driver_bsd_data *drv, int op)
{
struct ieee80211req ireq;
os_memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
ireq.i_type = op;
if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
op, strerror(errno));
return -1;
}
return ireq.i_val;
}
static int
getifflags(struct wpa_driver_bsd_data *drv, int *flags)
{
struct ifreq ifr;
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
perror("SIOCGIFFLAGS");
return errno;
}
*flags = ifr.ifr_flags & 0xffff;
return 0;
}
static int
setifflags(struct wpa_driver_bsd_data *drv, int flags)
{
struct ifreq ifr;
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_flags = flags & 0xffff;
if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
perror("SIOCSIFFLAGS");
return errno;
}
return 0;
}
static int
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_bsd_data *drv = priv;
return get80211var(drv, IEEE80211_IOC_BSSID,
bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
}
#if 0
static int
wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
{
struct wpa_driver_bsd_data *drv = priv;
return set80211var(drv, IEEE80211_IOC_BSSID,
bssid, IEEE80211_ADDR_LEN);
}
#endif
static int
wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_bsd_data *drv = priv;
return get80211var(drv, IEEE80211_IOC_SSID,
ssid, IEEE80211_NWID_LEN);
}
static int
wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid,
size_t ssid_len)
{
struct wpa_driver_bsd_data *drv = priv;
return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
}
static int
wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
const u8 *wpa_ie, size_t wpa_ie_len)
{
return set80211var(drv, IEEE80211_IOC_APPIE, wpa_ie, wpa_ie_len);
}
static int
wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
{
struct wpa_driver_bsd_data *drv = priv;
int ret = 0;
wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
__FUNCTION__, wpa, privacy);
if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
ret = -1;
if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
ret = -1;
if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
ret = -1;
return ret;
}
static int
wpa_driver_bsd_set_wpa(void *priv, int enabled)
{
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
}
static int
wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
const unsigned char *addr)
{
struct ieee80211req_del_key wk;
os_memset(&wk, 0, sizeof(wk));
if (addr != NULL &&
bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) {
struct ether_addr ea;
os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d",
__func__, ether_ntoa(&ea), key_idx);
os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE;
} else {
wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx);
wk.idk_keyix = key_idx;
}
return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
}
static int
wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
const unsigned char *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_bsd_data *drv = priv;
struct ieee80211req_key wk;
struct ether_addr ea;
char *alg_name;
u_int8_t cipher;
if (alg == WPA_ALG_NONE)
return wpa_driver_bsd_del_key(drv, key_idx, addr);
switch (alg) {
case WPA_ALG_WEP:
alg_name = "WEP";
cipher = IEEE80211_CIPHER_WEP;
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
cipher = IEEE80211_CIPHER_TKIP;
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
cipher = IEEE80211_CIPHER_AES_CCM;
break;
default:
wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
__func__, alg);
return -1;
}
os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
wpa_printf(MSG_DEBUG,
"%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
__func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
seq_len, key_len);
if (seq_len > sizeof(u_int64_t)) {
wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
__func__, seq_len);
return -2;
}
if (key_len > sizeof(wk.ik_keydata)) {
wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
__func__, key_len);
return -3;
}
os_memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV;
if (set_tx)
wk.ik_flags |= IEEE80211_KEY_XMIT;
os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
/*
* Deduce whether group/global or unicast key by checking
* the address (yech). Note also that we can only mark global
* keys default; doing this for a unicast key is an error.
*/
if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
wk.ik_flags |= IEEE80211_KEY_GROUP;
wk.ik_keyix = key_idx;
} else {
wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
}
if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
wk.ik_keylen = key_len;
os_memcpy(&wk.ik_keyrsc, seq, seq_len);
os_memcpy(wk.ik_keydata, key, key_len);
return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
}
static int
wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_bsd_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
}
static int
wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
{
struct wpa_driver_bsd_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
}
static int
wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_bsd_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s", __func__);
os_memset(&mlme, 0, sizeof(mlme));
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = reason_code;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_bsd_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s", __func__);
os_memset(&mlme, 0, sizeof(mlme));
mlme.im_op = IEEE80211_MLME_DISASSOC;
mlme.im_reason = reason_code;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
{
struct wpa_driver_bsd_data *drv = priv;
struct ieee80211req_mlme mlme;
int privacy;
wpa_printf(MSG_DEBUG,
"%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
, __func__
, params->ssid_len, params->ssid
, params->wpa_ie_len
, params->pairwise_suite
, params->group_suite
, params->key_mgmt_suite
);
/* XXX error handling is wrong but unclear what to do... */
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
return -1;
privacy = !(params->pairwise_suite == CIPHER_NONE &&
params->group_suite == CIPHER_NONE &&
params->key_mgmt_suite == KEY_MGMT_NONE &&
params->wpa_ie_len == 0);
wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
return -1;
if (params->wpa_ie_len &&
set80211param(drv, IEEE80211_IOC_WPA,
params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
return -1;
os_memset(&mlme, 0, sizeof(mlme));
mlme.im_op = IEEE80211_MLME_ASSOC;
if (params->ssid != NULL)
os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
mlme.im_ssid_len = params->ssid_len;
if (params->bssid != NULL)
os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
return -1;
return 0;
}
static int
wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
{
struct wpa_driver_bsd_data *drv = priv;
int authmode;
if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
(auth_alg & AUTH_ALG_SHARED_KEY))
authmode = IEEE80211_AUTH_AUTO;
else if (auth_alg & AUTH_ALG_SHARED_KEY)
authmode = IEEE80211_AUTH_SHARED;
else
authmode = IEEE80211_AUTH_OPEN;
return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
}
static int
wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_bsd_data *drv = priv;
int flags;
/* NB: interface must be marked UP to do a scan */
if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
return -1;
/* set desired ssid before scan */
if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
return -1;
/* NB: net80211 delivers a scan complete event so no need to poll */
return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
}
#include <net/route.h>
#if __FreeBSD__
#include <net80211/ieee80211_freebsd.h>
#endif
#if __NetBSD__
#include <net80211/ieee80211_netbsd.h>
#endif
static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct wpa_driver_bsd_data *drv = sock_ctx;
char buf[2048];
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm;
union wpa_event_data event;
struct ieee80211_michael_event *mic;
int n;
n = read(sock, buf, sizeof(buf));
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
perror("read(PF_ROUTE)");
return;
}
rtm = (struct rt_msghdr *) buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Routing message version %d not "
"understood\n", rtm->rtm_version);
return;
}
os_memset(&event, 0, sizeof(event));
switch (rtm->rtm_type) {
case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *) rtm;
if (ifan->ifan_index != drv->ifindex)
break;
strlcpy(event.interface_status.ifname, drv->ifname,
sizeof(event.interface_status.ifname));
switch (ifan->ifan_what) {
case IFAN_DEPARTURE:
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
default:
return;
}
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
event.interface_status.ifname,
ifan->ifan_what == IFAN_DEPARTURE ?
"removed" : "added");
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
break;
case RTM_IEEE80211:
ifan = (struct if_announcemsghdr *) rtm;
if (ifan->ifan_index != drv->ifindex)
break;
switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC:
wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
break;
case RTM_IEEE80211_DISASSOC:
wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
break;
case RTM_IEEE80211_SCAN:
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
break;
case RTM_IEEE80211_REPLAY:
/* ignore */
break;
case RTM_IEEE80211_MICHAEL:
mic = (struct ieee80211_michael_event *) &ifan[1];
wpa_printf(MSG_DEBUG,
"Michael MIC failure wireless event: "
"keyix=%u src_addr=" MACSTR, mic->iev_keyix,
MAC2STR(mic->iev_src));
os_memset(&event, 0, sizeof(event));
event.michael_mic_failure.unicast =
!IEEE80211_IS_MULTICAST(mic->iev_dst);
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
&event);
break;
}
break;
case RTM_IFINFO:
ifm = (struct if_msghdr *) rtm;
if (ifm->ifm_index != drv->ifindex)
break;
if ((rtm->rtm_flags & RTF_UP) == 0) {
strlcpy(event.interface_status.ifname, drv->ifname,
sizeof(event.interface_status.ifname));
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
event.interface_status.ifname);
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
}
break;
}
}
/* Compare function for sorting scan results. Return >0 if @b is consider
* better. */
static int
wpa_scan_result_compar(const void *a, const void *b)
{
const struct wpa_scan_result *wa = a;
const struct wpa_scan_result *wb = b;
/* WPA/WPA2 support preferred */
if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
!(wa->wpa_ie_len || wa->rsn_ie_len))
return 1;
if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
(wa->wpa_ie_len || wa->rsn_ie_len))
return -1;
/* privacy support preferred */
if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
(wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
return 1;
if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
(wb->caps & IEEE80211_CAPINFO_PRIVACY))
return -1;
/* best/max rate preferred if signal level close enough XXX */
if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
return wb->maxrate - wa->maxrate;
/* use freq for channel preference */
/* all things being equal, use signal level */
return wb->level - wa->level;
}
static int
getmaxrate(uint8_t rates[15], uint8_t nrates)
{
int i, maxrate = -1;
for (i = 0; i < nrates; i++) {
int rate = rates[i] & IEEE80211_RATE_VAL;
if (rate > maxrate)
rate = maxrate;
}
return maxrate;
}
/* unalligned little endian access */
#define LE_READ_4(p) \
((u_int32_t) \
((((const u_int8_t *)(p))[0] ) | \
(((const u_int8_t *)(p))[1] << 8) | \
(((const u_int8_t *)(p))[2] << 16) | \
(((const u_int8_t *)(p))[3] << 24)))
static int __inline
iswpaoui(const u_int8_t *frm)
{
return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
}
static int
wpa_driver_bsd_get_scan_results(void *priv,
struct wpa_scan_result *results,
size_t max_size)
{
#define min(a,b) ((a)>(b)?(b):(a))
struct wpa_driver_bsd_data *drv = priv;
uint8_t buf[24*1024];
uint8_t *cp, *vp;
struct ieee80211req_scan_result *sr;
struct wpa_scan_result *wsr;
int len, ielen;
os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
if (len < 0)
return -1;
cp = buf;
wsr = results;
while (len >= sizeof(struct ieee80211req_scan_result)) {
sr = (struct ieee80211req_scan_result *) cp;
os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
wsr->ssid_len = sr->isr_ssid_len;
wsr->freq = sr->isr_freq;
wsr->noise = sr->isr_noise;
wsr->qual = sr->isr_rssi;
wsr->level = 0; /* XXX? */
wsr->caps = sr->isr_capinfo;
wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
vp = (u_int8_t *)(sr+1);
os_memcpy(wsr->ssid, vp, sr->isr_ssid_len);
if (sr->isr_ie_len > 0) {
vp += sr->isr_ssid_len;
ielen = sr->isr_ie_len;
while (ielen > 0) {
switch (vp[0]) {
case IEEE80211_ELEMID_VENDOR:
if (!iswpaoui(vp))
break;
wsr->wpa_ie_len =
min(2+vp[1], SSID_MAX_WPA_IE_LEN);
os_memcpy(wsr->wpa_ie, vp,
wsr->wpa_ie_len);
break;
case IEEE80211_ELEMID_RSN:
wsr->rsn_ie_len =
min(2+vp[1], SSID_MAX_WPA_IE_LEN);
os_memcpy(wsr->rsn_ie, vp,
wsr->rsn_ie_len);
break;
}
ielen -= 2+vp[1];
vp += 2+vp[1];
}
}
cp += sr->isr_len, len -= sr->isr_len;
wsr++;
}
qsort(results, wsr - results, sizeof(struct wpa_scan_result),
wpa_scan_result_compar);
wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
len, wsr - results);
return wsr - results;
#undef min
}
static void *
wpa_driver_bsd_init(void *ctx, const char *ifname)
{
#define GETPARAM(drv, param, v) \
(((v) = get80211param(drv, param)) != -1)
struct wpa_driver_bsd_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
/*
* NB: We require the interface name be mappable to an index.
* This implies we do not support having wpa_supplicant
* wait for an interface to appear. This seems ok; that
* doesn't belong here; it's really the job of devd.
*/
drv->ifindex = if_nametoindex(ifname);
if (drv->ifindex == 0) {
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
__func__, ifname);
goto fail1;
}
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0)
goto fail1;
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
if (drv->route < 0)
goto fail;
eloop_register_read_sock(drv->route,
wpa_driver_bsd_event_receive, ctx, drv);
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
__func__, strerror(errno));
goto fail;
}
if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
__func__, strerror(errno));
goto fail;
}
if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
__func__, strerror(errno));
goto fail;
}
if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
"roaming: %s", __func__, strerror(errno));
goto fail;
}
if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
__func__, strerror(errno));
goto fail;
}
return drv;
fail:
close(drv->sock);
fail1:
os_free(drv);
return NULL;
#undef GETPARAM
}
static void
wpa_driver_bsd_deinit(void *priv)
{
struct wpa_driver_bsd_data *drv = priv;
int flags;
eloop_unregister_read_sock(drv->route);
/* NB: mark interface down */
if (getifflags(drv, &flags) == 0)
(void) setifflags(drv, flags &~ IFF_UP);
wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
__func__);
(void) close(drv->route); /* ioctl socket */
(void) close(drv->sock); /* event socket */
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_bsd_ops = {
.name = "bsd",
.desc = "BSD 802.11 support (Atheros, etc.)",
.init = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,
.get_bssid = wpa_driver_bsd_get_bssid,
.get_ssid = wpa_driver_bsd_get_ssid,
.set_wpa = wpa_driver_bsd_set_wpa,
.set_key = wpa_driver_bsd_set_key,
.set_countermeasures = wpa_driver_bsd_set_countermeasures,
.set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted,
.scan = wpa_driver_bsd_scan,
.get_scan_results = wpa_driver_bsd_get_scan_results,
.deauthenticate = wpa_driver_bsd_deauthenticate,
.disassociate = wpa_driver_bsd_disassociate,
.associate = wpa_driver_bsd_associate,
.set_auth_alg = wpa_driver_bsd_set_auth_alg,
};

View File

@ -1,513 +0,0 @@
/*
* WPA Supplicant - driver interaction with Linux Host AP driver
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "wireless_copy.h"
#include "common.h"
#include "driver.h"
#include "driver_wext.h"
#include "eloop.h"
#include "driver_hostap.h"
struct wpa_driver_hostap_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
int current_mode; /* infra/adhoc */
};
static int hostapd_ioctl(struct wpa_driver_hostap_data *drv,
struct prism2_hostapd_param *param,
int len, int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = (caddr_t) param;
iwr.u.data.length = len;
if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
int ret = errno;
if (show_err)
perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
return ret;
}
return 0;
}
static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv,
const u8 *wpa_ie, size_t wpa_ie_len)
{
struct prism2_hostapd_param *param;
int res;
size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
if (blen < sizeof(*param))
blen = sizeof(*param);
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
param->u.generic_elem.len = wpa_ie_len;
os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
res = hostapd_ioctl(drv, param, blen, 1);
os_free(param);
return res;
}
static int prism2param(struct wpa_driver_hostap_data *drv, int param,
int value)
{
struct iwreq iwr;
int *i, ret = 0;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i++ = param;
*i++ = value;
if (ioctl(drv->sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
ret = -1;
}
return ret;
}
static int wpa_driver_hostap_set_wpa(void *priv, int enabled)
{
struct wpa_driver_hostap_data *drv = priv;
int ret = 0;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
if (!enabled && wpa_driver_hostap_set_wpa_ie(drv, NULL, 0) < 0)
ret = -1;
if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, enabled ? 2 : 0) < 0)
ret = -1;
if (prism2param(drv, PRISM2_PARAM_WPA, enabled) < 0)
ret = -1;
return ret;
}
static void show_set_key_error(struct prism2_hostapd_param *param)
{
switch (param->u.crypt.err) {
case HOSTAP_CRYPT_ERR_UNKNOWN_ALG:
wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
param->u.crypt.alg);
wpa_printf(MSG_INFO, "You may need to load kernel module to "
"register that algorithm.");
wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for "
"WEP.");
break;
case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR:
wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
MAC2STR(param->sta_addr));
break;
case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED:
wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
break;
case HOSTAP_CRYPT_ERR_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "Key setting failed.");
break;
case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "TX key index setting failed.");
break;
case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED:
wpa_printf(MSG_INFO, "Card configuration failed.");
break;
}
}
static int wpa_driver_hostap_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx,
int set_tx, const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_hostap_data *drv = priv;
struct prism2_hostapd_param *param;
u8 *buf;
size_t blen;
int ret = 0;
char *alg_name;
switch (alg) {
case WPA_ALG_NONE:
alg_name = "none";
break;
case WPA_ALG_WEP:
alg_name = "WEP";
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
break;
default:
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > 8)
return -2;
blen = sizeof(*param) + key_len;
buf = os_zalloc(blen);
if (buf == NULL)
return -1;
param = (struct prism2_hostapd_param *) buf;
param->cmd = PRISM2_SET_ENCRYPTION;
/* TODO: In theory, STA in client mode can use five keys; four default
* keys for receiving (with keyidx 0..3) and one individual key for
* both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
* keyidx 0 is reserved for this unicast use and default keys can only
* use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
* This should be fine for more or less all cases, but for completeness
* sake, the driver could be enhanced to support the missing key. */
#if 0
if (addr == NULL)
os_memset(param->sta_addr, 0xff, ETH_ALEN);
else
os_memcpy(param->sta_addr, addr, ETH_ALEN);
#else
os_memset(param->sta_addr, 0xff, ETH_ALEN);
#endif
os_strlcpy((char *) param->u.crypt.alg, alg_name,
HOSTAP_CRYPT_ALG_NAME_LEN);
param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
param->u.crypt.idx = key_idx;
os_memcpy(param->u.crypt.seq, seq, seq_len);
param->u.crypt.key_len = key_len;
os_memcpy((u8 *) (param + 1), key, key_len);
if (hostapd_ioctl(drv, param, blen, 1)) {
wpa_printf(MSG_WARNING, "Failed to set encryption.");
show_set_key_error(param);
ret = -1;
}
os_free(buf);
return ret;
}
static int wpa_driver_hostap_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return prism2param(drv, PRISM2_PARAM_TKIP_COUNTERMEASURES, enabled);
}
static int wpa_driver_hostap_set_drop_unencrypted(void *priv, int enabled)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED, enabled);
}
static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv,
int type)
{
struct iwreq iwr;
int *i, ret = 0;
wpa_printf(MSG_DEBUG, "%s: type=%d", __FUNCTION__, type);
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
i = (int *) iwr.u.name;
*i++ = type;
if (ioctl(drv->sock, PRISM2_IOCTL_RESET, &iwr) < 0) {
perror("ioctl[PRISM2_IOCTL_RESET]");
ret = -1;
}
return ret;
}
static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv,
const u8 *addr, int cmd, int reason_code)
{
struct prism2_hostapd_param param;
int ret;
/* There does not seem to be a better way of deauthenticating or
* disassociating with Prism2/2.5/3 than sending the management frame
* and then resetting the Port0 to make sure both the AP and the STA
* end up in disconnected state. */
os_memset(&param, 0, sizeof(param));
param.cmd = PRISM2_HOSTAPD_MLME;
os_memcpy(param.sta_addr, addr, ETH_ALEN);
param.u.mlme.cmd = cmd;
param.u.mlme.reason_code = reason_code;
ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
if (ret == 0) {
os_sleep(0, 100000);
ret = wpa_driver_hostap_reset(drv, 2);
}
return ret;
}
static int wpa_driver_hostap_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DEAUTH,
reason_code);
}
static int wpa_driver_hostap_disassociate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DISASSOC,
reason_code);
}
static int
wpa_driver_hostap_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_hostap_data *drv = priv;
int ret = 0;
int allow_unencrypted_eapol;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
if (params->mode != drv->current_mode) {
/* At the moment, Host AP driver requires host_roaming=2 for
* infrastructure mode and host_roaming=0 for adhoc. */
if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING,
params->mode == IEEE80211_MODE_IBSS ? 0 : 2) <
0) {
wpa_printf(MSG_DEBUG, "%s: failed to set host_roaming",
__func__);
}
drv->current_mode = params->mode;
}
if (prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
params->key_mgmt_suite != KEY_MGMT_NONE) < 0)
ret = -1;
if (wpa_driver_hostap_set_wpa_ie(drv, params->wpa_ie,
params->wpa_ie_len) < 0)
ret = -1;
if (wpa_driver_wext_set_mode(drv->wext, params->mode) < 0)
ret = -1;
if (params->freq &&
wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len)
< 0)
ret = -1;
if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
ret = -1;
/* Allow unencrypted EAPOL messages even if pairwise keys are set when
* not using WPA. IEEE 802.1X specifies that these frames are not
* encrypted, but WPA encrypts them when pairwise keys are in use. */
if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
params->key_mgmt_suite == KEY_MGMT_PSK)
allow_unencrypted_eapol = 0;
else
allow_unencrypted_eapol = 1;
if (prism2param(drv, PRISM2_PARAM_IEEE_802_1X,
allow_unencrypted_eapol) < 0) {
wpa_printf(MSG_DEBUG, "hostap: Failed to configure "
"ieee_802_1x param");
/* Ignore this error.. driver_hostap.c can also be used with
* other drivers that do not support this prism2_param. */
}
return ret;
}
static int wpa_driver_hostap_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_hostap_data *drv = priv;
struct prism2_hostapd_param param;
int ret;
if (ssid == NULL) {
/* Use standard Linux Wireless Extensions ioctl if possible
* because some drivers using hostap code in wpa_supplicant
* might not support Host AP specific scan request (with SSID
* info). */
return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
}
if (ssid_len > 32)
ssid_len = 32;
os_memset(&param, 0, sizeof(param));
param.cmd = PRISM2_HOSTAPD_SCAN_REQ;
param.u.scan_req.ssid_len = ssid_len;
os_memcpy(param.u.scan_req.ssid, ssid, ssid_len);
ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
/* Not all drivers generate "scan completed" wireless event, so try to
* read results after a timeout. */
eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
return ret;
}
static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg)
{
struct wpa_driver_hostap_data *drv = priv;
int algs = 0;
if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
algs |= 1;
if (auth_alg & AUTH_ALG_SHARED_KEY)
algs |= 2;
if (auth_alg & AUTH_ALG_LEAP)
algs |= 4;
if (algs == 0)
algs = 1; /* at least one algorithm should be set */
return prism2param(drv, PRISM2_PARAM_AP_AUTH_ALGS, algs);
}
static int wpa_driver_hostap_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_hostap_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static struct wpa_scan_results * wpa_driver_hostap_get_scan_results(void *priv)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_hostap_set_operstate(void *priv, int state)
{
struct wpa_driver_hostap_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static void * wpa_driver_hostap_init(void *ctx, const char *ifname)
{
struct wpa_driver_hostap_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL) {
os_free(drv);
return NULL;
}
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0) {
perror("socket");
wpa_driver_wext_deinit(drv->wext);
os_free(drv);
return NULL;
}
if (os_strncmp(ifname, "wlan", 4) == 0) {
/*
* Host AP driver may use both wlan# and wifi# interface in
* wireless events.
*/
char ifname2[IFNAMSIZ + 1];
os_strlcpy(ifname2, ifname, sizeof(ifname2));
os_memcpy(ifname2, "wifi", 4);
wpa_driver_wext_alternative_ifindex(drv->wext, ifname2);
}
return drv;
}
static void wpa_driver_hostap_deinit(void *priv)
{
struct wpa_driver_hostap_data *drv = priv;
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_hostap_ops = {
.name = "hostap",
.desc = "Host AP driver (Intersil Prism2/2.5/3)",
.get_bssid = wpa_driver_hostap_get_bssid,
.get_ssid = wpa_driver_hostap_get_ssid,
.set_wpa = wpa_driver_hostap_set_wpa,
.set_key = wpa_driver_hostap_set_key,
.set_countermeasures = wpa_driver_hostap_set_countermeasures,
.set_drop_unencrypted = wpa_driver_hostap_set_drop_unencrypted,
.scan = wpa_driver_hostap_scan,
.get_scan_results2 = wpa_driver_hostap_get_scan_results,
.deauthenticate = wpa_driver_hostap_deauthenticate,
.disassociate = wpa_driver_hostap_disassociate,
.associate = wpa_driver_hostap_associate,
.set_auth_alg = wpa_driver_hostap_set_auth_alg,
.init = wpa_driver_hostap_init,
.deinit = wpa_driver_hostap_deinit,
.set_operstate = wpa_driver_hostap_set_operstate,
};

View File

@ -1,153 +0,0 @@
/*
* WPA Supplicant - driver interaction with Linux Host AP driver
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef HOSTAP_DRIVER_H
#define HOSTAP_DRIVER_H
#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
enum {
/* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
PRISM2_PARAM_TXRATECTRL = 2,
PRISM2_PARAM_BEACON_INT = 3,
PRISM2_PARAM_PSEUDO_IBSS = 4,
PRISM2_PARAM_ALC = 5,
/* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
PRISM2_PARAM_DUMP = 7,
PRISM2_PARAM_OTHER_AP_POLICY = 8,
PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
PRISM2_PARAM_DTIM_PERIOD = 11,
PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
PRISM2_PARAM_MAX_WDS = 13,
PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
PRISM2_PARAM_AP_AUTH_ALGS = 15,
PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
PRISM2_PARAM_HOST_ENCRYPT = 17,
PRISM2_PARAM_HOST_DECRYPT = 18,
PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19,
PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20,
PRISM2_PARAM_HOST_ROAMING = 21,
PRISM2_PARAM_BCRX_STA_KEY = 22,
PRISM2_PARAM_IEEE_802_1X = 23,
PRISM2_PARAM_ANTSEL_TX = 24,
PRISM2_PARAM_ANTSEL_RX = 25,
PRISM2_PARAM_MONITOR_TYPE = 26,
PRISM2_PARAM_WDS_TYPE = 27,
PRISM2_PARAM_HOSTSCAN = 28,
PRISM2_PARAM_AP_SCAN = 29,
PRISM2_PARAM_ENH_SEC = 30,
PRISM2_PARAM_IO_DEBUG = 31,
PRISM2_PARAM_BASIC_RATES = 32,
PRISM2_PARAM_OPER_RATES = 33,
PRISM2_PARAM_HOSTAPD = 34,
PRISM2_PARAM_HOSTAPD_STA = 35,
PRISM2_PARAM_WPA = 36,
PRISM2_PARAM_PRIVACY_INVOKED = 37,
PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
PRISM2_PARAM_DROP_UNENCRYPTED = 39,
PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
};
/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
enum {
PRISM2_HOSTAPD_FLUSH = 1,
PRISM2_HOSTAPD_ADD_STA = 2,
PRISM2_HOSTAPD_REMOVE_STA = 3,
PRISM2_HOSTAPD_GET_INFO_STA = 4,
/* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
PRISM2_SET_ENCRYPTION = 6,
PRISM2_GET_ENCRYPTION = 7,
PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
PRISM2_HOSTAPD_GET_RID = 9,
PRISM2_HOSTAPD_SET_RID = 10,
PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
PRISM2_HOSTAPD_MLME = 13,
PRISM2_HOSTAPD_SCAN_REQ = 14,
PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
};
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
#define PRISM2_HOSTAPD_RID_HDR_LEN \
((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
*/
#define HOSTAP_CRYPT_ALG_NAME_LEN 16
struct prism2_hostapd_param {
u32 cmd;
u8 sta_addr[ETH_ALEN];
union {
struct {
u16 aid;
u16 capability;
u8 tx_supp_rates;
} add_sta;
struct {
u32 inactive_sec;
} get_info_sta;
struct {
u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
u32 flags;
u32 err;
u8 idx;
u8 seq[8]; /* sequence counter (set: RX, get: TX) */
u16 key_len;
u8 key[0];
} crypt;
struct {
u32 flags_and;
u32 flags_or;
} set_flags_sta;
struct {
u16 rid;
u16 len;
u8 data[0];
} rid;
struct {
u8 len;
u8 data[0];
} generic_elem;
struct {
#define MLME_STA_DEAUTH 0
#define MLME_STA_DISASSOC 1
u16 cmd;
u16 reason_code;
} mlme;
struct {
u8 ssid_len;
u8 ssid[32];
} scan_req;
} u;
};
#define HOSTAP_CRYPT_FLAG_SET_TX_KEY 0x01
#define HOSTAP_CRYPT_FLAG_PERMANENT 0x02
#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
#endif /* HOSTAP_DRIVER_H */

View File

@ -1,466 +0,0 @@
/*
* WPA Supplicant - iPhone/iPod touch Apple80211 driver interface
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#define Boolean __DummyBoolean
#include <CoreFoundation/CoreFoundation.h>
#undef Boolean
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "ieee802_11_defs.h"
#include "MobileApple80211.h"
struct wpa_driver_iphone_data {
void *ctx;
Apple80211Ref wireless_ctx;
CFArrayRef scan_results;
int ctrl_power;
};
static const void * cfdict_get_key_str(CFDictionaryRef dict, const char *key)
{
const void *res;
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, key,
kCFStringEncodingMacRoman);
if (str == NULL)
return NULL;
res = CFDictionaryGetValue(dict, str);
CFRelease(str);
return res;
}
static int wpa_driver_iphone_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_iphone_data *drv = priv;
CFDataRef data;
int err, len;
err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_SSID, 0,
&data);
if (err != 0) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(SSID) "
"failed: %d", err);
return -1;
}
len = CFDataGetLength(data);
if (len > 32) {
CFRelease(data);
return -1;
}
os_memcpy(ssid, CFDataGetBytePtr(data), len);
CFRelease(data);
return len;
}
static int wpa_driver_iphone_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_iphone_data *drv = priv;
CFStringRef data;
int err;
int a1, a2, a3, a4, a5, a6;
err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_BSSID, 0,
&data);
if (err != 0) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(BSSID) "
"failed: %d", err);
return -1;
}
sscanf(CFStringGetCStringPtr(data, kCFStringEncodingMacRoman),
"%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6);
bssid[0] = a1;
bssid[1] = a2;
bssid[2] = a3;
bssid[3] = a4;
bssid[4] = a5;
bssid[5] = a6;
CFRelease(data);
return 0;
}
static void wpa_driver_iphone_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
static int wpa_driver_iphone_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_iphone_data *drv = priv;
int err;
if (drv->scan_results) {
CFRelease(drv->scan_results);
drv->scan_results = NULL;
}
err = Apple80211Scan(drv->wireless_ctx, &drv->scan_results, NULL);
if (err) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211Scan failed: %d",
err);
return -1;
}
eloop_register_timeout(0, 0, wpa_driver_iphone_scan_timeout, drv,
drv->ctx);
return 0;
}
static int wpa_driver_iphone_get_scan_results(void *priv,
struct wpa_scan_result *results,
size_t max_size)
{
struct wpa_driver_iphone_data *drv = priv;
size_t i, num;
if (drv->scan_results == NULL)
return 0;
num = CFArrayGetCount(drv->scan_results);
if (num > max_size)
num = max_size;
os_memset(results, 0, num * sizeof(struct wpa_scan_result));
for (i = 0; i < num; i++) {
struct wpa_scan_result *res = &results[i];
CFDictionaryRef dict =
CFArrayGetValueAtIndex(drv->scan_results, i);
CFDataRef data;
CFStringRef str;
CFNumberRef num;
int val;
data = cfdict_get_key_str(dict, "SSID");
if (data) {
res->ssid_len = CFDataGetLength(data);
if (res->ssid_len > 32)
res->ssid_len = 32;
os_memcpy(res->ssid, CFDataGetBytePtr(data),
res->ssid_len);
}
str = cfdict_get_key_str(dict, "BSSID");
if (str) {
int a1, a2, a3, a4, a5, a6;
sscanf(CFStringGetCStringPtr(
str, kCFStringEncodingMacRoman),
"%x:%x:%x:%x:%x:%x",
&a1, &a2, &a3, &a4, &a5, &a6);
res->bssid[0] = a1;
res->bssid[1] = a2;
res->bssid[2] = a3;
res->bssid[3] = a4;
res->bssid[4] = a5;
res->bssid[5] = a6;
}
num = cfdict_get_key_str(dict, "CAPABILITIES");
if (num) {
if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
res->caps = val;
}
num = cfdict_get_key_str(dict, "CHANNEL");
if (num) {
if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
res->freq = 2407 + val * 5;
}
num = cfdict_get_key_str(dict, "RSSI");
if (num) {
if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
res->level = val;
}
num = cfdict_get_key_str(dict, "NOISE");
if (num) {
if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
res->noise = val;
}
data = cfdict_get_key_str(dict, "IE");
if (data) {
u8 *ptr = (u8 *) CFDataGetBytePtr(data);
int len = CFDataGetLength(data);
u8 *pos = ptr, *end = ptr + len;
while (pos + 2 < end) {
if (pos + 2 + pos[1] > end)
break;
if (pos[0] == WLAN_EID_RSN &&
pos[1] <= SSID_MAX_WPA_IE_LEN) {
os_memcpy(res->rsn_ie, pos,
2 + pos[1]);
res->rsn_ie_len = 2 + pos[1];
}
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
pos[1] > 4 && pos[2] == 0x00 &&
pos[3] == 0x50 && pos[4] == 0xf2 &&
pos[5] == 0x01) {
os_memcpy(res->wpa_ie, pos,
2 + pos[1]);
res->wpa_ie_len = 2 + pos[1];
}
pos = pos + 2 + pos[1];
}
}
}
return num;
}
static void wpa_driver_iphone_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_iphone_data *drv = eloop_ctx;
u8 bssid[ETH_ALEN];
if (wpa_driver_iphone_get_bssid(drv, bssid) != 0) {
eloop_register_timeout(1, 0, wpa_driver_iphone_assoc_timeout,
drv, drv->ctx);
return;
}
wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL);
}
static int wpa_driver_iphone_associate(
void *priv, struct wpa_driver_associate_params *params)
{
struct wpa_driver_iphone_data *drv = priv;
int i, num, err;
size_t ssid_len;
CFDictionaryRef bss = NULL;
/*
* TODO: Consider generating parameters instead of just using an entry
* from scan results in order to support ap_scan=2.
*/
if (drv->scan_results == NULL) {
wpa_printf(MSG_DEBUG, "iPhone: No scan results - cannot "
"associate");
return -1;
}
num = CFArrayGetCount(drv->scan_results);
for (i = 0; i < num; i++) {
CFDictionaryRef dict =
CFArrayGetValueAtIndex(drv->scan_results, i);
CFDataRef data;
data = cfdict_get_key_str(dict, "SSID");
if (data == NULL)
continue;
ssid_len = CFDataGetLength(data);
if (ssid_len != params->ssid_len ||
os_memcmp(CFDataGetBytePtr(data), params->ssid, ssid_len)
!= 0)
continue;
bss = dict;
break;
}
if (bss == NULL) {
wpa_printf(MSG_DEBUG, "iPhone: Could not find SSID from scan "
"results - cannot associate");
return -1;
}
wpa_printf(MSG_DEBUG, "iPhone: Trying to associate with a BSS found "
"from scan results");
err = Apple80211Associate(drv->wireless_ctx, bss, NULL);
if (err) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211Associate() failed: "
"%d", err);
return -1;
}
/*
* Driver is actually already associated; report association from an
* eloop callback.
*/
eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx);
eloop_register_timeout(0, 0, wpa_driver_iphone_assoc_timeout, drv,
drv->ctx);
return 0;
}
static int wpa_driver_iphone_set_key(void *priv, wpa_alg alg, const u8 *addr,
int key_idx, int set_tx, const u8 *seq,
size_t seq_len, const u8 *key,
size_t key_len)
{
/*
* TODO: Need to either support configuring PMK for 4-way handshake or
* PTK for TKIP/CCMP.
*/
return -1;
}
static int wpa_driver_iphone_get_capa(void *priv, struct wpa_driver_capa *capa)
{
os_memset(capa, 0, sizeof(*capa));
capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 |
WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP;
capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED |
WPA_DRIVER_AUTH_LEAP;
capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
return 0;
}
static void * wpa_driver_iphone_init(void *ctx, const char *ifname)
{
struct wpa_driver_iphone_data *drv;
int err;
char power;
CFStringRef name;
CFDictionaryRef dict;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->ctx = ctx;
err = Apple80211Open(&drv->wireless_ctx);
if (err) {
wpa_printf(MSG_ERROR, "iPhone: Apple80211Open failed: %d",
err);
os_free(drv);
return NULL;
}
name = CFStringCreateWithCString(kCFAllocatorDefault, ifname,
kCFStringEncodingISOLatin1);
if (name == NULL) {
wpa_printf(MSG_ERROR, "iPhone: ifname -> CFString failed");
Apple80211Close(drv->wireless_ctx);
os_free(drv);
return NULL;
}
err = Apple80211BindToInterface(drv->wireless_ctx, name);
CFRelease(name);
if (err) {
wpa_printf(MSG_ERROR, "iPhone: Apple80211BindToInterface "
"failed: %d", err);
Apple80211Close(drv->wireless_ctx);
os_free(drv);
return NULL;
}
err = Apple80211GetPower(drv->wireless_ctx, &power);
if (err)
wpa_printf(MSG_DEBUG, "iPhone: Apple80211GetPower failed: %d",
err);
wpa_printf(MSG_DEBUG, "iPhone: Power=%d", power);
if (!power) {
drv->ctrl_power = 1;
err = Apple80211SetPower(drv->wireless_ctx, 1);
if (err) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower "
"failed: %d", err);
Apple80211Close(drv->wireless_ctx);
os_free(drv);
return NULL;
}
}
err = Apple80211GetInfoCopy(drv->wireless_ctx, &dict);
if (err == 0) {
CFShow(dict);
CFRelease(dict);
} else {
printf("Apple80211GetInfoCopy: %d\n", err);
}
return drv;
}
static void wpa_driver_iphone_deinit(void *priv)
{
struct wpa_driver_iphone_data *drv = priv;
int err;
eloop_cancel_timeout(wpa_driver_iphone_scan_timeout, drv, drv->ctx);
eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx);
if (drv->ctrl_power) {
wpa_printf(MSG_DEBUG, "iPhone: Power down the interface");
err = Apple80211SetPower(drv->wireless_ctx, 0);
if (err) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower(0) "
"failed: %d", err);
}
}
err = Apple80211Close(drv->wireless_ctx);
if (err) {
wpa_printf(MSG_DEBUG, "iPhone: Apple80211Close failed: %d",
err);
}
if (drv->scan_results)
CFRelease(drv->scan_results);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_iphone_ops = {
.name = "iphone",
.desc = "iPhone/iPod touch Apple80211 driver",
.get_ssid = wpa_driver_iphone_get_ssid,
.get_bssid = wpa_driver_iphone_get_bssid,
.init = wpa_driver_iphone_init,
.deinit = wpa_driver_iphone_deinit,
.scan = wpa_driver_iphone_scan,
.get_scan_results = wpa_driver_iphone_get_scan_results,
.associate = wpa_driver_iphone_associate,
.set_key = wpa_driver_iphone_set_key,
.get_capa = wpa_driver_iphone_get_capa,
};

View File

@ -1,463 +0,0 @@
/*
* WPA Supplicant - driver interaction with Linux ipw2100/2200 drivers
* Copyright (c) 2005 Zhu Yi <yi.zhu@intel.com>
* Copyright (c) 2004 Lubomir Gelo <lgelo@cnc.sk>
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*
* Please note that ipw2100/2200 drivers change to use generic Linux wireless
* extensions if the kernel includes support for WE-18 or newer (Linux 2.6.13
* or newer). driver_wext.c should be used in those cases.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "wireless_copy.h"
#include "common.h"
#include "driver.h"
#include "driver_wext.h"
struct wpa_driver_ipw_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
};
/* following definitions must be kept in sync with ipw2100.c and ipw2200.c */
#define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
#define IPW_CMD_SET_WPA_PARAM 1
#define IPW_CMD_SET_WPA_IE 2
#define IPW_CMD_SET_ENCRYPTION 3
#define IPW_CMD_MLME 4
#define IPW_PARAM_WPA_ENABLED 1
#define IPW_PARAM_TKIP_COUNTERMEASURES 2
#define IPW_PARAM_DROP_UNENCRYPTED 3
#define IPW_PARAM_PRIVACY_INVOKED 4
#define IPW_PARAM_AUTH_ALGS 5
#define IPW_PARAM_IEEE_802_1X 6
#define IPW_MLME_STA_DEAUTH 1
#define IPW_MLME_STA_DISASSOC 2
#define IPW_CRYPT_ERR_UNKNOWN_ALG 2
#define IPW_CRYPT_ERR_UNKNOWN_ADDR 3
#define IPW_CRYPT_ERR_CRYPT_INIT_FAILED 4
#define IPW_CRYPT_ERR_KEY_SET_FAILED 5
#define IPW_CRYPT_ERR_TX_KEY_SET_FAILED 6
#define IPW_CRYPT_ERR_CARD_CONF_FAILED 7
#define IPW_CRYPT_ALG_NAME_LEN 16
struct ipw_param {
u32 cmd;
u8 sta_addr[ETH_ALEN];
union {
struct {
u8 name;
u32 value;
} wpa_param;
struct {
u32 len;
u8 reserved[32];
u8 data[0];
} wpa_ie;
struct{
u32 command;
u32 reason_code;
} mlme;
struct {
u8 alg[IPW_CRYPT_ALG_NAME_LEN];
u8 set_tx;
u32 err;
u8 idx;
u8 seq[8];
u16 key_len;
u8 key[0];
} crypt;
} u;
};
/* end of ipw2100.c and ipw2200.c code */
static int ipw_ioctl(struct wpa_driver_ipw_data *drv,
struct ipw_param *param, int len, int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = (caddr_t) param;
iwr.u.data.length = len;
if (ioctl(drv->sock, IPW_IOCTL_WPA_SUPPLICANT, &iwr) < 0) {
int ret = errno;
if (show_err)
perror("ioctl[IPW_IOCTL_WPA_SUPPLICANT]");
return ret;
}
return 0;
}
static void ipw_show_set_key_error(struct ipw_param *param)
{
switch (param->u.crypt.err) {
case IPW_CRYPT_ERR_UNKNOWN_ALG:
wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
param->u.crypt.alg);
wpa_printf(MSG_INFO, "You may need to load kernel module to "
"register that algorithm.");
wpa_printf(MSG_INFO, "E.g., 'modprobe ieee80211_crypt_wep' for"
" WEP.");
break;
case IPW_CRYPT_ERR_UNKNOWN_ADDR:
wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
MAC2STR(param->sta_addr));
break;
case IPW_CRYPT_ERR_CRYPT_INIT_FAILED:
wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
break;
case IPW_CRYPT_ERR_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "Key setting failed.");
break;
case IPW_CRYPT_ERR_TX_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "TX key index setting failed.");
break;
case IPW_CRYPT_ERR_CARD_CONF_FAILED:
wpa_printf(MSG_INFO, "Card configuration failed.");
break;
}
}
static int ipw_set_wpa_ie(struct wpa_driver_ipw_data *drv,
const u8 *wpa_ie, size_t wpa_ie_len)
{
struct ipw_param *param;
int ret;
size_t blen = sizeof(*param) + wpa_ie_len;
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = IPW_CMD_SET_WPA_IE;
param->u.wpa_ie.len = wpa_ie_len;
os_memcpy(param->u.wpa_ie.data, wpa_ie, wpa_ie_len);
ret = ipw_ioctl(drv, param, blen, 1);
os_free(param);
return ret;
}
static int ipw_set_wpa_param(struct wpa_driver_ipw_data *drv, u8 name,
u32 value)
{
struct ipw_param param;
os_memset(&param, 0, sizeof(param));
param.cmd = IPW_CMD_SET_WPA_PARAM;
param.u.wpa_param.name = name;
param.u.wpa_param.value = value;
return ipw_ioctl(drv, &param, sizeof(param), 1);
}
static int ipw_mlme(struct wpa_driver_ipw_data *drv, const u8 *addr,
int cmd, int reason)
{
struct ipw_param param;
os_memset(&param, 0, sizeof(param));
os_memcpy(param.sta_addr, addr, ETH_ALEN);
param.cmd = IPW_CMD_MLME;
param.u.mlme.command = cmd;
param.u.mlme.reason_code = reason;
return ipw_ioctl(drv, &param, sizeof(param), 1);
}
static int wpa_driver_ipw_set_wpa(void *priv, int enabled)
{
struct wpa_driver_ipw_data *drv = priv;
int ret = 0;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
if (!enabled && ipw_set_wpa_ie(drv, NULL, 0) < 0)
ret = -1;
if (ipw_set_wpa_param(drv, IPW_PARAM_WPA_ENABLED, enabled) < 0)
ret = -1;
return ret;
}
static int wpa_driver_ipw_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_ipw_data *drv = priv;
struct ipw_param *param;
u8 *buf;
size_t blen;
int ret = 0;
char *alg_name;
switch (alg) {
case WPA_ALG_NONE:
alg_name = "none";
break;
case WPA_ALG_WEP:
alg_name = "WEP";
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
break;
default:
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > 8)
return -2;
blen = sizeof(*param) + key_len;
buf = os_zalloc(blen);
if (buf == NULL)
return -1;
param = (struct ipw_param *) buf;
param->cmd = IPW_CMD_SET_ENCRYPTION;
os_memset(param->sta_addr, 0xff, ETH_ALEN);
os_strlcpy((char *) param->u.crypt.alg, alg_name,
IPW_CRYPT_ALG_NAME_LEN);
param->u.crypt.set_tx = set_tx ? 1 : 0;
param->u.crypt.idx = key_idx;
os_memcpy(param->u.crypt.seq, seq, seq_len);
param->u.crypt.key_len = key_len;
os_memcpy((u8 *) (param + 1), key, key_len);
if (ipw_ioctl(drv, param, blen, 1)) {
wpa_printf(MSG_WARNING, "Failed to set encryption.");
ipw_show_set_key_error(param);
ret = -1;
}
os_free(buf);
return ret;
}
static int wpa_driver_ipw_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_ipw_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return ipw_set_wpa_param(drv, IPW_PARAM_TKIP_COUNTERMEASURES,
enabled);
}
static int wpa_driver_ipw_set_drop_unencrypted(void *priv, int enabled)
{
struct wpa_driver_ipw_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return ipw_set_wpa_param(drv, IPW_PARAM_DROP_UNENCRYPTED,
enabled);
}
static int wpa_driver_ipw_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_ipw_data *drv = priv;
return ipw_mlme(drv, addr, IPW_MLME_STA_DEAUTH, reason_code);
}
static int wpa_driver_ipw_disassociate(void *priv, const u8 *addr,
int reason_code)
{
struct wpa_driver_ipw_data *drv = priv;
return ipw_mlme(drv, addr, IPW_MLME_STA_DISASSOC, reason_code);
}
static int
wpa_driver_ipw_associate(void *priv, struct wpa_driver_associate_params *params)
{
struct wpa_driver_ipw_data *drv = priv;
int ret = 0;
int unencrypted_eapol;
if (ipw_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
params->ssid_len) < 0)
ret = -1;
if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
ret = -1;
if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
params->key_mgmt_suite == KEY_MGMT_PSK)
unencrypted_eapol = 0;
else
unencrypted_eapol = 1;
if (ipw_set_wpa_param(drv, IPW_PARAM_IEEE_802_1X,
unencrypted_eapol) < 0) {
wpa_printf(MSG_DEBUG, "ipw: Failed to configure "
"ieee_802_1x param");
}
return ret;
}
static int wpa_driver_ipw_set_auth_alg(void *priv, int auth_alg)
{
struct wpa_driver_ipw_data *drv = priv;
int algs = 0;
if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
algs |= 1;
if (auth_alg & AUTH_ALG_SHARED_KEY)
algs |= 2;
if (auth_alg & AUTH_ALG_LEAP)
algs |= 4;
if (algs == 0)
algs = 1; /* at least one algorithm should be set */
wpa_printf(MSG_DEBUG, "%s: auth_alg=0x%x", __FUNCTION__, algs);
return ipw_set_wpa_param(drv, IPW_PARAM_AUTH_ALGS, algs);
}
static int wpa_driver_ipw_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_ipw_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_ipw_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_ipw_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static int wpa_driver_ipw_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_ipw_data *drv = priv;
return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
}
static struct wpa_scan_results * wpa_driver_ipw_get_scan_results(void *priv)
{
struct wpa_driver_ipw_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_ipw_set_operstate(void *priv, int state)
{
struct wpa_driver_ipw_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static void * wpa_driver_ipw_init(void *ctx, const char *ifname)
{
struct wpa_driver_ipw_data *drv;
int ver;
wpa_printf(MSG_DEBUG, "%s is called", __FUNCTION__);
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL) {
os_free(drv);
return NULL;
}
ver = wpa_driver_wext_get_version(drv->wext);
if (ver >= 18) {
wpa_printf(MSG_WARNING, "Linux wireless extensions version %d "
"detected.", ver);
wpa_printf(MSG_WARNING, "ipw2x00 driver uses driver_wext "
"(-Dwext) instead of driver_ipw.");
}
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0) {
wpa_driver_wext_deinit(drv->wext);
os_free(drv);
return NULL;
}
return drv;
}
static void wpa_driver_ipw_deinit(void *priv)
{
struct wpa_driver_ipw_data *drv = priv;
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_ipw_ops = {
.name = "ipw",
.desc = "Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 "
"or newer)",
.get_bssid = wpa_driver_ipw_get_bssid,
.get_ssid = wpa_driver_ipw_get_ssid,
.set_wpa = wpa_driver_ipw_set_wpa,
.set_key = wpa_driver_ipw_set_key,
.set_countermeasures = wpa_driver_ipw_set_countermeasures,
.set_drop_unencrypted = wpa_driver_ipw_set_drop_unencrypted,
.scan = wpa_driver_ipw_scan,
.get_scan_results2 = wpa_driver_ipw_get_scan_results,
.deauthenticate = wpa_driver_ipw_deauthenticate,
.disassociate = wpa_driver_ipw_disassociate,
.associate = wpa_driver_ipw_associate,
.set_auth_alg = wpa_driver_ipw_set_auth_alg,
.init = wpa_driver_ipw_init,
.deinit = wpa_driver_ipw_deinit,
.set_operstate = wpa_driver_ipw_set_operstate,
};

View File

@ -1,601 +0,0 @@
/*
* WPA Supplicant - driver interaction with MADWIFI 802.11 driver
* Copyright (c) 2004, Sam Leffler <sam@errno.com>
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*
* Please note that madwifi supports WPA configuration via Linux wireless
* extensions and if the kernel includes support for this, driver_wext.c should
* be used instead of this driver wrapper.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "common.h"
#include "driver.h"
#include "driver_wext.h"
#include "eloop.h"
#include "ieee802_11_defs.h"
#include "wireless_copy.h"
/*
* Avoid conflicts with wpa_supplicant definitions by undefining a definition.
*/
#undef WME_OUI_TYPE
#include <include/compat.h>
#include <net80211/ieee80211.h>
#ifdef WME_NUM_AC
/* Assume this is built against BSD branch of madwifi driver. */
#define MADWIFI_BSD
#include <net80211/_ieee80211.h>
#endif /* WME_NUM_AC */
#include <net80211/ieee80211_crypto.h>
#include <net80211/ieee80211_ioctl.h>
#ifdef IEEE80211_IOCTL_SETWMMPARAMS
/* Assume this is built against madwifi-ng */
#define MADWIFI_NG
#endif /* IEEE80211_IOCTL_SETWMMPARAMS */
struct wpa_driver_madwifi_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
};
static int
set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len,
int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
if (len < IFNAMSIZ &&
op != IEEE80211_IOCTL_SET_APPIEBUF) {
/*
* Argument data fits inline; put it there.
*/
os_memcpy(iwr.u.name, data, len);
} else {
/*
* Argument data too big for inline transfer; setup a
* parameter block instead; the kernel will transfer
* the data for the driver.
*/
iwr.u.data.pointer = data;
iwr.u.data.length = len;
}
if (ioctl(drv->sock, op, &iwr) < 0) {
if (show_err) {
#ifdef MADWIFI_NG
int first = IEEE80211_IOCTL_SETPARAM;
int last = IEEE80211_IOCTL_KICKMAC;
static const char *opnames[] = {
"ioctl[IEEE80211_IOCTL_SETPARAM]",
"ioctl[IEEE80211_IOCTL_GETPARAM]",
"ioctl[IEEE80211_IOCTL_SETMODE]",
"ioctl[IEEE80211_IOCTL_GETMODE]",
"ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
"ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
"ioctl[IEEE80211_IOCTL_SETCHANLIST]",
"ioctl[IEEE80211_IOCTL_GETCHANLIST]",
"ioctl[IEEE80211_IOCTL_CHANSWITCH]",
NULL,
"ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
"ioctl[IEEE80211_IOCTL_GETSCANRESULTS]",
NULL,
"ioctl[IEEE80211_IOCTL_GETCHANINFO]",
"ioctl[IEEE80211_IOCTL_SETOPTIE]",
"ioctl[IEEE80211_IOCTL_GETOPTIE]",
"ioctl[IEEE80211_IOCTL_SETMLME]",
NULL,
"ioctl[IEEE80211_IOCTL_SETKEY]",
NULL,
"ioctl[IEEE80211_IOCTL_DELKEY]",
NULL,
"ioctl[IEEE80211_IOCTL_ADDMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_DELMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_WDSMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_WDSDELMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_KICKMAC]",
};
#else /* MADWIFI_NG */
int first = IEEE80211_IOCTL_SETPARAM;
int last = IEEE80211_IOCTL_CHANLIST;
static const char *opnames[] = {
"ioctl[IEEE80211_IOCTL_SETPARAM]",
"ioctl[IEEE80211_IOCTL_GETPARAM]",
"ioctl[IEEE80211_IOCTL_SETKEY]",
"ioctl[IEEE80211_IOCTL_GETKEY]",
"ioctl[IEEE80211_IOCTL_DELKEY]",
NULL,
"ioctl[IEEE80211_IOCTL_SETMLME]",
NULL,
"ioctl[IEEE80211_IOCTL_SETOPTIE]",
"ioctl[IEEE80211_IOCTL_GETOPTIE]",
"ioctl[IEEE80211_IOCTL_ADDMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_DELMAC]",
NULL,
"ioctl[IEEE80211_IOCTL_CHANLIST]",
};
#endif /* MADWIFI_NG */
int idx = op - first;
if (first <= op && op <= last &&
idx < (int) (sizeof(opnames) / sizeof(opnames[0]))
&& opnames[idx])
perror(opnames[idx]);
else
perror("ioctl[unknown???]");
}
return -1;
}
return 0;
}
static int
set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg,
int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.mode = op;
os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg));
if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
if (show_err)
perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
return -1;
}
return 0;
}
static int
wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv,
const u8 *wpa_ie, size_t wpa_ie_len)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
/* NB: SETOPTIE is not fixed-size so must not be inlined */
iwr.u.data.pointer = (void *) wpa_ie;
iwr.u.data.length = wpa_ie_len;
if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) {
perror("ioctl[IEEE80211_IOCTL_SETOPTIE]");
return -1;
}
return 0;
}
static int
wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx,
const u8 *addr)
{
struct ieee80211req_del_key wk;
wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
os_memset(&wk, 0, sizeof(wk));
wk.idk_keyix = key_idx;
if (addr != NULL)
os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1);
}
static int
wpa_driver_madwifi_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_key wk;
char *alg_name;
u_int8_t cipher;
if (alg == WPA_ALG_NONE)
return wpa_driver_madwifi_del_key(drv, key_idx, addr);
switch (alg) {
case WPA_ALG_WEP:
if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
ETH_ALEN) == 0) {
/*
* madwifi did not seem to like static WEP key
* configuration with IEEE80211_IOCTL_SETKEY, so use
* Linux wireless extensions ioctl for this.
*/
return wpa_driver_wext_set_key(drv->wext, alg, addr,
key_idx, set_tx,
seq, seq_len,
key, key_len);
}
alg_name = "WEP";
cipher = IEEE80211_CIPHER_WEP;
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
cipher = IEEE80211_CIPHER_TKIP;
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
cipher = IEEE80211_CIPHER_AES_CCM;
break;
default:
wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
__FUNCTION__, alg);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > sizeof(u_int64_t)) {
wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big",
__FUNCTION__, (unsigned long) seq_len);
return -2;
}
if (key_len > sizeof(wk.ik_keydata)) {
wpa_printf(MSG_DEBUG, "%s: key length %lu too big",
__FUNCTION__, (unsigned long) key_len);
return -3;
}
os_memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV;
if (addr == NULL ||
os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
wk.ik_flags |= IEEE80211_KEY_GROUP;
if (set_tx) {
wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
} else
os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
wk.ik_keylen = key_len;
#ifdef WORDS_BIGENDIAN
#define WPA_KEY_RSC_LEN 8
{
size_t i;
u8 tmp[WPA_KEY_RSC_LEN];
os_memset(tmp, 0, sizeof(tmp));
for (i = 0; i < seq_len; i++)
tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
}
#else /* WORDS_BIGENDIAN */
os_memcpy(&wk.ik_keyrsc, seq, seq_len);
#endif /* WORDS_BIGENDIAN */
os_memcpy(wk.ik_keydata, key, key_len);
return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1);
}
static int
wpa_driver_madwifi_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_madwifi_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1);
}
static int
wpa_driver_madwifi_set_drop_unencrypted(void *priv, int enabled)
{
struct wpa_driver_madwifi_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, enabled, 1);
}
static int
wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = reason_code;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
}
static int
wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
mlme.im_op = IEEE80211_MLME_DISASSOC;
mlme.im_reason = reason_code;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
}
static int
wpa_driver_madwifi_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_madwifi_data *drv = priv;
struct ieee80211req_mlme mlme;
int ret = 0, privacy = 1;
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
/*
* NB: Don't need to set the freq or cipher-related state as
* this is implied by the bssid which is used to locate
* the scanned node state which holds it. The ssid is
* needed to disambiguate an AP that broadcasts multiple
* ssid's but uses the same bssid.
*/
/* XXX error handling is wrong but unclear what to do... */
if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie,
params->wpa_ie_len) < 0)
ret = -1;
if (params->pairwise_suite == CIPHER_NONE &&
params->group_suite == CIPHER_NONE &&
params->key_mgmt_suite == KEY_MGMT_NONE &&
params->wpa_ie_len == 0)
privacy = 0;
if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0)
ret = -1;
if (params->wpa_ie_len &&
set80211param(drv, IEEE80211_PARAM_WPA,
params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0)
ret = -1;
if (params->bssid == NULL) {
/* ap_scan=2 mode - driver takes care of AP selection and
* roaming */
/* FIX: this does not seem to work; would probably need to
* change something in the driver */
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
params->ssid_len) < 0)
ret = -1;
} else {
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
params->ssid_len) < 0)
ret = -1;
os_memset(&mlme, 0, sizeof(mlme));
mlme.im_op = IEEE80211_MLME_ASSOC;
os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
sizeof(mlme), 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed",
__func__);
ret = -1;
}
}
return ret;
}
static int
wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg)
{
struct wpa_driver_madwifi_data *drv = priv;
int authmode;
if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
(auth_alg & AUTH_ALG_SHARED_KEY))
authmode = IEEE80211_AUTH_AUTO;
else if (auth_alg & AUTH_ALG_SHARED_KEY)
authmode = IEEE80211_AUTH_SHARED;
else
authmode = IEEE80211_AUTH_OPEN;
return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1);
}
static int
wpa_driver_madwifi_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_madwifi_data *drv = priv;
struct iwreq iwr;
int ret = 0;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
/* set desired ssid before scan */
/* FIX: scan should not break the current association, so using
* set_ssid may not be the best way of doing this.. */
if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0)
ret = -1;
if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) {
perror("ioctl[SIOCSIWSCAN]");
ret = -1;
}
/*
* madwifi delivers a scan complete event so no need to poll, but
* register a backup timeout anyway to make sure that we recover even
* if the driver does not send this event for any reason. This timeout
* will only be used if the event is not delivered (event handler will
* cancel the timeout).
*/
eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext,
drv->ctx);
return ret;
}
static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static struct wpa_scan_results *
wpa_driver_madwifi_get_scan_results(void *priv)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_madwifi_set_operstate(void *priv, int state)
{
struct wpa_driver_madwifi_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies,
size_t ies_len)
{
struct ieee80211req_getset_appiebuf *probe_req_ie;
int ret;
probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len);
if (probe_req_ie == NULL)
return -1;
probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ;
probe_req_ie->app_buflen = ies_len;
os_memcpy(probe_req_ie->app_buf, ies, ies_len);
ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie,
sizeof(struct ieee80211req_getset_appiebuf) +
ies_len, 1);
os_free(probe_req_ie);
return ret;
}
static void * wpa_driver_madwifi_init(void *ctx, const char *ifname)
{
struct wpa_driver_madwifi_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL)
goto fail;
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0)
goto fail2;
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
"roaming", __FUNCTION__);
goto fail3;
}
if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support",
__FUNCTION__);
goto fail3;
}
return drv;
fail3:
close(drv->sock);
fail2:
wpa_driver_wext_deinit(drv->wext);
fail:
os_free(drv);
return NULL;
}
static void wpa_driver_madwifi_deinit(void *priv)
{
struct wpa_driver_madwifi_data *drv = priv;
if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE",
__FUNCTION__);
}
if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based "
"roaming", __FUNCTION__);
}
if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy "
"flag", __FUNCTION__);
}
if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) {
wpa_printf(MSG_DEBUG, "%s: failed to disable WPA",
__FUNCTION__);
}
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_madwifi_ops = {
.name = "madwifi",
.desc = "MADWIFI 802.11 support (Atheros, etc.)",
.get_bssid = wpa_driver_madwifi_get_bssid,
.get_ssid = wpa_driver_madwifi_get_ssid,
.set_key = wpa_driver_madwifi_set_key,
.init = wpa_driver_madwifi_init,
.deinit = wpa_driver_madwifi_deinit,
.set_countermeasures = wpa_driver_madwifi_set_countermeasures,
.set_drop_unencrypted = wpa_driver_madwifi_set_drop_unencrypted,
.scan = wpa_driver_madwifi_scan,
.get_scan_results2 = wpa_driver_madwifi_get_scan_results,
.deauthenticate = wpa_driver_madwifi_deauthenticate,
.disassociate = wpa_driver_madwifi_disassociate,
.associate = wpa_driver_madwifi_associate,
.set_auth_alg = wpa_driver_madwifi_set_auth_alg,
.set_operstate = wpa_driver_madwifi_set_operstate,
.set_probe_req_ie = wpa_driver_madwifi_set_probe_req_ie,
};

File diff suppressed because it is too large Load Diff

View File

@ -1,432 +0,0 @@
/*
* WPA Supplicant - Mac OS X Apple80211 driver interface
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#define Boolean __DummyBoolean
#include <CoreFoundation/CoreFoundation.h>
#undef Boolean
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "Apple80211.h"
struct wpa_driver_osx_data {
void *ctx;
WirelessRef wireless_ctx;
CFArrayRef scan_results;
};
#ifndef CONFIG_NO_STDOUT_DEBUG
extern int wpa_debug_level;
static void dump_dict_cb(const void *key, const void *value, void *context)
{
if (MSG_DEBUG < wpa_debug_level)
return;
wpa_printf(MSG_DEBUG, "Key:");
CFShow(key);
wpa_printf(MSG_DEBUG, "Value:");
CFShow(value);
}
#endif /* CONFIG_NO_STDOUT_DEBUG */
static void wpa_driver_osx_dump_dict(CFDictionaryRef dict, const char *title)
{
#ifndef CONFIG_NO_STDOUT_DEBUG
wpa_printf(MSG_DEBUG, "OSX: Dump dictionary %s - %u entries",
title, (unsigned int) CFDictionaryGetCount(dict));
CFDictionaryApplyFunction(dict, dump_dict_cb, NULL);
#endif /* CONFIG_NO_STDOUT_DEBUG */
}
static int wpa_driver_osx_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_osx_data *drv = priv;
WirelessError err;
WirelessInfo info;
int len;
err = WirelessGetInfo(drv->wireless_ctx, &info);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d",
(int) err);
return -1;
}
if (!info.power) {
wpa_printf(MSG_DEBUG, "OSX: Wireless device power off");
return -1;
}
for (len = 0; len < 32; len++)
if (info.ssid[len] == 0)
break;
os_memcpy(ssid, info.ssid, len);
return len;
}
static int wpa_driver_osx_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_osx_data *drv = priv;
WirelessError err;
WirelessInfo info;
err = WirelessGetInfo(drv->wireless_ctx, &info);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d",
(int) err);
return -1;
}
if (!info.power) {
wpa_printf(MSG_DEBUG, "OSX: Wireless device power off");
return -1;
}
os_memcpy(bssid, info.bssID, ETH_ALEN);
return 0;
}
static void wpa_driver_osx_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
static int wpa_driver_osx_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_osx_data *drv = priv;
WirelessError err;
if (drv->scan_results) {
CFRelease(drv->scan_results);
drv->scan_results = NULL;
}
if (ssid) {
CFStringRef data;
data = CFStringCreateWithBytes(kCFAllocatorDefault,
ssid, ssid_len,
kCFStringEncodingISOLatin1,
FALSE);
if (data == NULL) {
wpa_printf(MSG_DEBUG, "CFStringCreateWithBytes "
"failed");
return -1;
}
err = WirelessDirectedScan(drv->wireless_ctx,
&drv->scan_results, 0, data);
CFRelease(data);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessDirectedScan "
"failed: 0x%08x", (unsigned int) err);
return -1;
}
} else {
err = WirelessScan(drv->wireless_ctx, &drv->scan_results, 0);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessScan failed: "
"0x%08x", (unsigned int) err);
return -1;
}
}
eloop_register_timeout(0, 0, wpa_driver_osx_scan_timeout, drv,
drv->ctx);
return 0;
}
static int wpa_driver_osx_get_scan_results(void *priv,
struct wpa_scan_result *results,
size_t max_size)
{
struct wpa_driver_osx_data *drv = priv;
size_t i, num;
if (drv->scan_results == NULL)
return 0;
num = CFArrayGetCount(drv->scan_results);
if (num > max_size)
num = max_size;
os_memset(results, 0, num * sizeof(struct wpa_scan_result));
for (i = 0; i < num; i++) {
struct wpa_scan_result *res = &results[i];
WirelessNetworkInfo *info;
info = (WirelessNetworkInfo *)
CFDataGetBytePtr(CFArrayGetValueAtIndex(
drv->scan_results, i));
os_memcpy(res->bssid, info->bssid, ETH_ALEN);
if (info->ssid_len > 32) {
wpa_printf(MSG_DEBUG, "OSX: Invalid SSID length %d in "
"scan results", (int) info->ssid_len);
continue;
}
os_memcpy(res->ssid, info->ssid, info->ssid_len);
res->ssid_len = info->ssid_len;
res->caps = info->capability;
res->freq = 2407 + info->channel * 5;
res->level = info->signal;
res->noise = info->noise;
}
return num;
}
static void wpa_driver_osx_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_osx_data *drv = eloop_ctx;
u8 bssid[ETH_ALEN];
CFDictionaryRef ai;
if (wpa_driver_osx_get_bssid(drv, bssid) != 0) {
eloop_register_timeout(1, 0, wpa_driver_osx_assoc_timeout,
drv, drv->ctx);
return;
}
ai = WirelessGetAssociationInfo(drv->wireless_ctx);
if (ai) {
wpa_driver_osx_dump_dict(ai, "WirelessGetAssociationInfo");
CFRelease(ai);
} else {
wpa_printf(MSG_DEBUG, "OSX: Failed to get association info");
}
wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL);
}
static int wpa_driver_osx_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_osx_data *drv = priv;
WirelessError err;
CFDataRef ssid;
CFStringRef key;
int assoc_type;
ssid = CFDataCreate(kCFAllocatorDefault, params->ssid,
params->ssid_len);
if (ssid == NULL)
return -1;
/* TODO: support for WEP */
if (params->key_mgmt_suite == KEY_MGMT_PSK) {
if (params->passphrase == NULL)
return -1;
key = CFStringCreateWithCString(kCFAllocatorDefault,
params->passphrase,
kCFStringEncodingISOLatin1);
if (key == NULL) {
CFRelease(ssid);
return -1;
}
} else
key = NULL;
if (params->key_mgmt_suite == KEY_MGMT_NONE)
assoc_type = 0;
else
assoc_type = 4;
wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate(type=%d key=%p)",
assoc_type, key);
err = WirelessAssociate(drv->wireless_ctx, assoc_type, ssid, key);
CFRelease(ssid);
if (key)
CFRelease(key);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate failed: 0x%08x",
(unsigned int) err);
return -1;
}
/*
* Driver is actually already associated; report association from an
* eloop callback.
*/
eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx);
eloop_register_timeout(0, 0, wpa_driver_osx_assoc_timeout, drv,
drv->ctx);
return 0;
}
static int wpa_driver_osx_set_key(void *priv, wpa_alg alg, const u8 *addr,
int key_idx, int set_tx, const u8 *seq,
size_t seq_len, const u8 *key,
size_t key_len)
{
struct wpa_driver_osx_data *drv = priv;
WirelessError err;
if (alg == WPA_ALG_WEP) {
err = WirelessSetKey(drv->wireless_ctx, 1, key_idx, key_len,
key);
if (err != 0) {
wpa_printf(MSG_DEBUG, "OSX: WirelessSetKey failed: "
"0x%08x", (unsigned int) err);
return -1;
}
return 0;
}
if (alg == WPA_ALG_PMK) {
err = WirelessSetWPAKey(drv->wireless_ctx, 1, key_len, key);
if (err != 0) {
wpa_printf(MSG_DEBUG, "OSX: WirelessSetWPAKey failed: "
"0x%08x", (unsigned int) err);
return -1;
}
return 0;
}
wpa_printf(MSG_DEBUG, "OSX: Unsupported set_key alg %d", alg);
return -1;
}
static int wpa_driver_osx_get_capa(void *priv, struct wpa_driver_capa *capa)
{
os_memset(capa, 0, sizeof(*capa));
capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 |
WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP;
capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED |
WPA_DRIVER_AUTH_LEAP;
capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
return 0;
}
static void * wpa_driver_osx_init(void *ctx, const char *ifname)
{
struct wpa_driver_osx_data *drv;
WirelessError err;
u8 enabled, power;
if (!WirelessIsAvailable()) {
wpa_printf(MSG_ERROR, "OSX: No wireless interface available");
return NULL;
}
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->ctx = ctx;
err = WirelessAttach(&drv->wireless_ctx, 0);
if (err) {
wpa_printf(MSG_ERROR, "OSX: WirelessAttach failed: %d",
(int) err);
os_free(drv);
return NULL;
}
err = WirelessGetEnabled(drv->wireless_ctx, &enabled);
if (err)
wpa_printf(MSG_DEBUG, "OSX: WirelessGetEnabled failed: 0x%08x",
(unsigned int) err);
err = WirelessGetPower(drv->wireless_ctx, &power);
if (err)
wpa_printf(MSG_DEBUG, "OSX: WirelessGetPower failed: 0x%08x",
(unsigned int) err);
wpa_printf(MSG_DEBUG, "OSX: Enabled=%d Power=%d", enabled, power);
if (!enabled) {
err = WirelessSetEnabled(drv->wireless_ctx, 1);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessSetEnabled failed:"
" 0x%08x", (unsigned int) err);
WirelessDetach(drv->wireless_ctx);
os_free(drv);
return NULL;
}
}
if (!power) {
err = WirelessSetPower(drv->wireless_ctx, 1);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower failed: "
"0x%08x", (unsigned int) err);
WirelessDetach(drv->wireless_ctx);
os_free(drv);
return NULL;
}
}
return drv;
}
static void wpa_driver_osx_deinit(void *priv)
{
struct wpa_driver_osx_data *drv = priv;
WirelessError err;
eloop_cancel_timeout(wpa_driver_osx_scan_timeout, drv, drv->ctx);
eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx);
err = WirelessSetPower(drv->wireless_ctx, 0);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower(0) failed: "
"0x%08x", (unsigned int) err);
}
err = WirelessDetach(drv->wireless_ctx);
if (err) {
wpa_printf(MSG_DEBUG, "OSX: WirelessDetach failed: 0x%08x",
(unsigned int) err);
}
if (drv->scan_results)
CFRelease(drv->scan_results);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_osx_ops = {
.name = "osx",
.desc = "Mac OS X Apple80211 driver",
.get_ssid = wpa_driver_osx_get_ssid,
.get_bssid = wpa_driver_osx_get_bssid,
.init = wpa_driver_osx_init,
.deinit = wpa_driver_osx_deinit,
.scan = wpa_driver_osx_scan,
.get_scan_results = wpa_driver_osx_get_scan_results,
.associate = wpa_driver_osx_associate,
.set_key = wpa_driver_osx_set_key,
.get_capa = wpa_driver_osx_get_capa,
};

View File

@ -1,381 +0,0 @@
/*
* WPA Supplicant - driver interaction with Linux Prism54.org driver
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004, Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "wireless_copy.h"
#include "common.h"
#include "driver.h"
#include "driver_wext.h"
#include "driver_hostap.h"
struct wpa_driver_prism54_data {
void *wext; /* private data for driver_wext */
void *ctx;
char ifname[IFNAMSIZ + 1];
int sock;
};
#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12
#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25
#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26
static void show_set_key_error(struct prism2_hostapd_param *);
static int hostapd_ioctl_prism54(struct wpa_driver_prism54_data *drv,
struct prism2_hostapd_param *param,
int len, int show_err)
{
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.data.pointer = (caddr_t) param;
iwr.u.data.length = len;
if (ioctl(drv->sock, PRISM54_HOSTAPD, &iwr) < 0) {
int ret = errno;
if (show_err)
perror("ioctl[PRISM54_HOSTAPD]");
return ret;
}
return 0;
}
static int wpa_driver_prism54_set_wpa_ie(struct wpa_driver_prism54_data *drv,
const u8 *wpa_ie,
size_t wpa_ie_len)
{
struct prism2_hostapd_param *param;
int res;
size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
if (blen < sizeof(*param))
blen = sizeof(*param);
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
param->u.generic_elem.len = wpa_ie_len;
os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
res = hostapd_ioctl_prism54(drv, param, blen, 1);
os_free(param);
return res;
}
/* This is called at wpa_supplicant daemon init time */
static int wpa_driver_prism54_set_wpa(void *priv, int enabled)
{
struct wpa_driver_prism54_data *drv = priv;
struct prism2_hostapd_param *param;
int res;
size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
if (blen < sizeof(*param))
blen = sizeof(*param);
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = PRISM54_SET_WPA;
param->u.generic_elem.len = 0;
res = hostapd_ioctl_prism54(drv, param, blen, 1);
os_free(param);
return res;
}
static int wpa_driver_prism54_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_prism54_data *drv = priv;
struct prism2_hostapd_param *param;
u8 *buf;
size_t blen;
int ret = 0;
char *alg_name;
switch (alg) {
case WPA_ALG_NONE:
alg_name = "none";
return -1;
break;
case WPA_ALG_WEP:
alg_name = "WEP";
return -1;
break;
case WPA_ALG_TKIP:
alg_name = "TKIP";
break;
case WPA_ALG_CCMP:
alg_name = "CCMP";
return -1;
break;
default:
return -1;
}
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
"key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
if (seq_len > 8)
return -2;
blen = sizeof(*param) + key_len;
buf = os_zalloc(blen);
if (buf == NULL)
return -1;
param = (struct prism2_hostapd_param *) buf;
param->cmd = PRISM2_SET_ENCRYPTION;
/* TODO: In theory, STA in client mode can use five keys; four default
* keys for receiving (with keyidx 0..3) and one individual key for
* both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
* keyidx 0 is reserved for this unicast use and default keys can only
* use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
* This should be fine for more or less all cases, but for completeness
* sake, the driver could be enhanced to support the missing key. */
#if 0
if (addr == NULL)
os_memset(param->sta_addr, 0xff, ETH_ALEN);
else
os_memcpy(param->sta_addr, addr, ETH_ALEN);
#else
os_memset(param->sta_addr, 0xff, ETH_ALEN);
#endif
os_strlcpy((char *) param->u.crypt.alg, alg_name,
HOSTAP_CRYPT_ALG_NAME_LEN);
param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
param->u.crypt.idx = key_idx;
os_memcpy(param->u.crypt.seq, seq, seq_len);
param->u.crypt.key_len = key_len;
os_memcpy((u8 *) (param + 1), key, key_len);
if (hostapd_ioctl_prism54(drv, param, blen, 1)) {
wpa_printf(MSG_WARNING, "Failed to set encryption.");
show_set_key_error(param);
ret = -1;
}
os_free(buf);
return ret;
}
static int wpa_driver_prism54_set_countermeasures(void *priv,
int enabled)
{
/* FIX */
printf("wpa_driver_prism54_set_countermeasures - not yet "
"implemented\n");
return 0;
}
static int wpa_driver_prism54_set_drop_unencrypted(void *priv,
int enabled)
{
struct wpa_driver_prism54_data *drv = priv;
struct prism2_hostapd_param *param;
int res;
size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
if (blen < sizeof(*param))
blen = sizeof(*param);
param = os_zalloc(blen);
if (param == NULL)
return -1;
param->cmd = PRISM54_DROP_UNENCRYPTED;
param->u.generic_elem.len = 0;
res = hostapd_ioctl_prism54(drv, param, blen, 1);
os_free(param);
return res;
}
static int wpa_driver_prism54_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
/* FIX */
printf("wpa_driver_prism54_deauthenticate - not yet implemented\n");
return 0;
}
static int wpa_driver_prism54_disassociate(void *priv, const u8 *addr,
int reason_code)
{
/* FIX */
printf("wpa_driver_prism54_disassociate - not yet implemented\n");
return 0;
}
static int
wpa_driver_prism54_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_prism54_data *drv = priv;
int ret = 0;
if (wpa_driver_prism54_set_wpa_ie(drv, params->wpa_ie,
params->wpa_ie_len) < 0)
ret = -1;
if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
ret = -1;
if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
params->ssid_len) < 0)
ret = -1;
if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
ret = -1;
return ret;
}
static void show_set_key_error(struct prism2_hostapd_param *param)
{
switch (param->u.crypt.err) {
case HOSTAP_CRYPT_ERR_UNKNOWN_ALG:
wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
param->u.crypt.alg);
wpa_printf(MSG_INFO, "You may need to load kernel module to "
"register that algorithm.");
wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for "
"WEP.");
break;
case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR:
wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
MAC2STR(param->sta_addr));
break;
case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED:
wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
break;
case HOSTAP_CRYPT_ERR_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "Key setting failed.");
break;
case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED:
wpa_printf(MSG_INFO, "TX key index setting failed.");
break;
case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED:
wpa_printf(MSG_INFO, "Card configuration failed.");
break;
}
}
static int wpa_driver_prism54_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_prism54_data *drv = priv;
return wpa_driver_wext_get_bssid(drv->wext, bssid);
}
static int wpa_driver_prism54_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_prism54_data *drv = priv;
return wpa_driver_wext_get_ssid(drv->wext, ssid);
}
static int wpa_driver_prism54_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_prism54_data *drv = priv;
return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
}
static struct wpa_scan_results *
wpa_driver_prism54_get_scan_results(void *priv)
{
struct wpa_driver_prism54_data *drv = priv;
return wpa_driver_wext_get_scan_results(drv->wext);
}
static int wpa_driver_prism54_set_operstate(void *priv, int state)
{
struct wpa_driver_prism54_data *drv = priv;
return wpa_driver_wext_set_operstate(drv->wext, state);
}
static void * wpa_driver_prism54_init(void *ctx, const char *ifname)
{
struct wpa_driver_prism54_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->wext = wpa_driver_wext_init(ctx, ifname);
if (drv->wext == NULL) {
os_free(drv);
return NULL;
}
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0) {
wpa_driver_wext_deinit(drv->wext);
os_free(drv);
return NULL;
}
return drv;
}
static void wpa_driver_prism54_deinit(void *priv)
{
struct wpa_driver_prism54_data *drv = priv;
wpa_driver_wext_deinit(drv->wext);
close(drv->sock);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_prism54_ops = {
.name = "prism54",
.desc = "Prism54.org driver (Intersil Prism GT/Duette/Indigo)",
.get_bssid = wpa_driver_prism54_get_bssid,
.get_ssid = wpa_driver_prism54_get_ssid,
.set_wpa = wpa_driver_prism54_set_wpa,
.set_key = wpa_driver_prism54_set_key,
.set_countermeasures = wpa_driver_prism54_set_countermeasures,
.set_drop_unencrypted = wpa_driver_prism54_set_drop_unencrypted,
.scan = wpa_driver_prism54_scan,
.get_scan_results2 = wpa_driver_prism54_get_scan_results,
.deauthenticate = wpa_driver_prism54_deauthenticate,
.disassociate = wpa_driver_prism54_disassociate,
.associate = wpa_driver_prism54_associate,
.init = wpa_driver_prism54_init,
.deinit = wpa_driver_prism54_deinit,
.set_operstate = wpa_driver_prism54_set_operstate,
};

View File

@ -1,820 +0,0 @@
/*
* WPA Supplicant - privilege separated driver interface
* Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/un.h>
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "privsep_commands.h"
struct wpa_driver_privsep_data {
void *ctx;
u8 own_addr[ETH_ALEN];
int priv_socket;
char *own_socket_path;
int cmd_socket;
char *own_cmd_path;
struct sockaddr_un priv_addr;
char ifname[16];
};
static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
{
int res;
res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0,
(struct sockaddr *) &drv->priv_addr,
sizeof(drv->priv_addr));
if (res < 0)
perror("sendto");
return res < 0 ? -1 : 0;
}
static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
const void *data, size_t data_len,
void *reply, size_t *reply_len)
{
struct msghdr msg;
struct iovec io[2];
io[0].iov_base = &cmd;
io[0].iov_len = sizeof(cmd);
io[1].iov_base = (u8 *) data;
io[1].iov_len = data_len;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
msg.msg_iovlen = data ? 2 : 1;
msg.msg_name = &drv->priv_addr;
msg.msg_namelen = sizeof(drv->priv_addr);
if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
perror("sendmsg(cmd_socket)");
return -1;
}
if (reply) {
fd_set rfds;
struct timeval tv;
int res;
FD_ZERO(&rfds);
FD_SET(drv->cmd_socket, &rfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
if (res < 0 && errno != EINTR) {
perror("select");
return -1;
}
if (FD_ISSET(drv->cmd_socket, &rfds)) {
res = recv(drv->cmd_socket, reply, *reply_len, 0);
if (res < 0) {
perror("recv");
return -1;
}
*reply_len = res;
} else {
wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting "
"for reply (cmd=%d)", cmd);
return -1;
}
}
return 0;
}
static int wpa_driver_privsep_set_wpa(void *priv, int enabled)
{
struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_WPA, &enabled,
sizeof(enabled), NULL, NULL);
}
static int wpa_driver_privsep_scan(void *priv, const u8 *ssid, size_t ssid_len)
{
struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len,
NULL, NULL);
}
static struct wpa_scan_results *
wpa_driver_privsep_get_scan_results2(void *priv)
{
struct wpa_driver_privsep_data *drv = priv;
int res, num;
u8 *buf, *pos, *end;
size_t reply_len = 60000;
struct wpa_scan_results *results;
struct wpa_scan_res *r;
buf = os_malloc(reply_len);
if (buf == NULL)
return NULL;
res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
NULL, 0, buf, &reply_len);
if (res < 0) {
os_free(buf);
return NULL;
}
wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
(unsigned long) reply_len);
if (reply_len < sizeof(int)) {
wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
(unsigned long) reply_len);
os_free(buf);
return NULL;
}
pos = buf;
end = buf + reply_len;
os_memcpy(&num, pos, sizeof(int));
if (num < 0 || num > 1000) {
os_free(buf);
return NULL;
}
pos += sizeof(int);
results = os_zalloc(sizeof(*results));
if (results == NULL) {
os_free(buf);
return NULL;
}
results->res = os_zalloc(num * sizeof(struct wpa_scan_res *));
if (results->res == NULL) {
os_free(results);
os_free(buf);
return NULL;
}
while (results->num < (size_t) num && pos + sizeof(int) < end) {
int len;
os_memcpy(&len, pos, sizeof(int));
pos += sizeof(int);
if (len < 0 || len > 10000 || pos + len > end)
break;
r = os_malloc(len);
if (r == NULL)
break;
os_memcpy(r, pos, len);
pos += len;
if (sizeof(*r) + r->ie_len > (size_t) len) {
os_free(r);
break;
}
results->res[results->num++] = r;
}
os_free(buf);
return results;
}
static int wpa_driver_privsep_set_key(void *priv, wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_privsep_data *drv = priv;
struct privsep_cmd_set_key cmd;
wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
__func__, priv, alg, key_idx, set_tx);
os_memset(&cmd, 0, sizeof(cmd));
cmd.alg = alg;
if (addr)
os_memcpy(cmd.addr, addr, ETH_ALEN);
else
os_memset(cmd.addr, 0xff, ETH_ALEN);
cmd.key_idx = key_idx;
cmd.set_tx = set_tx;
if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
os_memcpy(cmd.seq, seq, seq_len);
cmd.seq_len = seq_len;
}
if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
os_memcpy(cmd.key, key, key_len);
cmd.key_len = key_len;
}
return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
NULL, NULL);
}
static int wpa_driver_privsep_associate(
void *priv, struct wpa_driver_associate_params *params)
{
struct wpa_driver_privsep_data *drv = priv;
struct privsep_cmd_associate *data;
int res;
size_t buflen;
wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
"group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
__func__, priv, params->freq, params->pairwise_suite,
params->group_suite, params->key_mgmt_suite,
params->auth_alg, params->mode);
buflen = sizeof(*data) + params->wpa_ie_len;
data = os_zalloc(buflen);
if (data == NULL)
return -1;
if (params->bssid)
os_memcpy(data->bssid, params->bssid, ETH_ALEN);
os_memcpy(data->ssid, params->ssid, params->ssid_len);
data->ssid_len = params->ssid_len;
data->freq = params->freq;
data->pairwise_suite = params->pairwise_suite;
data->group_suite = params->group_suite;
data->key_mgmt_suite = params->key_mgmt_suite;
data->auth_alg = params->auth_alg;
data->mode = params->mode;
data->wpa_ie_len = params->wpa_ie_len;
if (params->wpa_ie)
os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
/* TODO: add support for other assoc parameters */
res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
NULL, NULL);
os_free(data);
return res;
}
static int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_privsep_data *drv = priv;
int res;
size_t len = ETH_ALEN;
res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
if (res < 0 || len != ETH_ALEN)
return -1;
return 0;
}
static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
{
struct wpa_driver_privsep_data *drv = priv;
int res, ssid_len;
u8 reply[sizeof(int) + 32];
size_t len = sizeof(reply);
res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
if (res < 0 || len < sizeof(int))
return -1;
os_memcpy(&ssid_len, reply, sizeof(int));
if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) {
wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
return -1;
}
os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
return ssid_len;
}
static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
int reason_code)
{
//struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
__func__, MAC2STR(addr), reason_code);
wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
return 0;
}
static int wpa_driver_privsep_disassociate(void *priv, const u8 *addr,
int reason_code)
{
//struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
__func__, MAC2STR(addr), reason_code);
wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
return 0;
}
static void wpa_driver_privsep_event_assoc(void *ctx, wpa_event_type event,
u8 *buf, size_t len)
{
union wpa_event_data data;
int inc_data = 0;
u8 *pos, *end;
int ie_len;
os_memset(&data, 0, sizeof(data));
pos = buf;
end = buf + len;
if (end - pos < (int) sizeof(int))
return;
os_memcpy(&ie_len, pos, sizeof(int));
pos += sizeof(int);
if (ie_len < 0 || ie_len > end - pos)
return;
if (ie_len) {
data.assoc_info.req_ies = pos;
data.assoc_info.req_ies_len = ie_len;
pos += ie_len;
inc_data = 1;
}
wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
}
static void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
size_t len)
{
union wpa_event_data data;
int ievent;
if (len < sizeof(int) ||
len - sizeof(int) > sizeof(data.interface_status.ifname))
return;
os_memcpy(&ievent, buf, sizeof(int));
os_memset(&data, 0, sizeof(data));
data.interface_status.ievent = ievent;
os_memcpy(data.interface_status.ifname, buf + sizeof(int),
len - sizeof(int));
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
}
static void wpa_driver_privsep_event_michael_mic_failure(
void *ctx, u8 *buf, size_t len)
{
union wpa_event_data data;
if (len != sizeof(int))
return;
os_memset(&data, 0, sizeof(data));
os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
}
static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
size_t len)
{
union wpa_event_data data;
if (len != sizeof(struct pmkid_candidate))
return;
os_memset(&data, 0, sizeof(data));
os_memcpy(&data.pmkid_candidate, buf, len);
wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
}
static void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
{
union wpa_event_data data;
if (len != ETH_ALEN)
return;
os_memset(&data, 0, sizeof(data));
os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
}
static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
size_t len)
{
union wpa_event_data data;
if (len < sizeof(int) + ETH_ALEN)
return;
os_memset(&data, 0, sizeof(data));
os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
}
static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
{
if (len < ETH_ALEN)
return;
wpa_supplicant_rx_eapol(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
}
static void wpa_driver_privsep_event_sta_rx(void *ctx, u8 *buf, size_t len)
{
#ifdef CONFIG_CLIENT_MLME
struct ieee80211_rx_status *rx_status;
if (len < sizeof(*rx_status))
return;
rx_status = (struct ieee80211_rx_status *) buf;
buf += sizeof(*rx_status);
len -= sizeof(*rx_status);
wpa_supplicant_sta_rx(ctx, buf, len, rx_status);
#endif /* CONFIG_CLIENT_MLME */
}
static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct wpa_driver_privsep_data *drv = eloop_ctx;
u8 *buf, *event_buf;
size_t event_len;
int res, event;
enum privsep_event e;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
const size_t buflen = 2000;
buf = os_malloc(buflen);
if (buf == NULL)
return;
res = recvfrom(sock, buf, buflen, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
perror("recvfrom(priv_socket)");
os_free(buf);
return;
}
wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
if (res < (int) sizeof(int)) {
wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
return;
}
os_memcpy(&event, buf, sizeof(int));
event_buf = &buf[sizeof(int)];
event_len = res - sizeof(int);
wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)",
event, (unsigned long) event_len);
e = event;
switch (e) {
case PRIVSEP_EVENT_SCAN_RESULTS:
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
break;
case PRIVSEP_EVENT_ASSOC:
wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
event_buf, event_len);
break;
case PRIVSEP_EVENT_DISASSOC:
wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
break;
case PRIVSEP_EVENT_ASSOCINFO:
wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
event_buf, event_len);
break;
case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
wpa_driver_privsep_event_michael_mic_failure(
drv->ctx, event_buf, event_len);
break;
case PRIVSEP_EVENT_INTERFACE_STATUS:
wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
event_len);
break;
case PRIVSEP_EVENT_PMKID_CANDIDATE:
wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
event_len);
break;
case PRIVSEP_EVENT_STKSTART:
wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
event_len);
break;
case PRIVSEP_EVENT_FT_RESPONSE:
wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
event_len);
break;
case PRIVSEP_EVENT_RX_EAPOL:
wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
event_len);
break;
case PRIVSEP_EVENT_STA_RX:
wpa_driver_privsep_event_sta_rx(drv->ctx, event_buf,
event_len);
break;
}
os_free(buf);
}
static void * wpa_driver_privsep_init(void *ctx, const char *ifname)
{
struct wpa_driver_privsep_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->ctx = ctx;
drv->priv_socket = -1;
drv->cmd_socket = -1;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
return drv;
}
static void wpa_driver_privsep_deinit(void *priv)
{
struct wpa_driver_privsep_data *drv = priv;
if (drv->priv_socket >= 0) {
wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
eloop_unregister_read_sock(drv->priv_socket);
close(drv->priv_socket);
}
if (drv->own_socket_path) {
unlink(drv->own_socket_path);
os_free(drv->own_socket_path);
}
if (drv->cmd_socket >= 0) {
eloop_unregister_read_sock(drv->cmd_socket);
close(drv->cmd_socket);
}
if (drv->own_cmd_path) {
unlink(drv->own_cmd_path);
os_free(drv->own_cmd_path);
}
os_free(drv);
}
static int wpa_driver_privsep_set_param(void *priv, const char *param)
{
struct wpa_driver_privsep_data *drv = priv;
const char *pos;
char *own_dir, *priv_dir;
static unsigned int counter = 0;
size_t len;
struct sockaddr_un addr;
wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
if (param == NULL)
pos = NULL;
else
pos = os_strstr(param, "own_dir=");
if (pos) {
char *end;
own_dir = os_strdup(pos + 8);
if (own_dir == NULL)
return -1;
end = os_strchr(own_dir, ' ');
if (end)
*end = '\0';
} else {
own_dir = os_strdup("/tmp");
if (own_dir == NULL)
return -1;
}
if (param == NULL)
pos = NULL;
else
pos = os_strstr(param, "priv_dir=");
if (pos) {
char *end;
priv_dir = os_strdup(pos + 9);
if (priv_dir == NULL) {
os_free(own_dir);
return -1;
}
end = os_strchr(priv_dir, ' ');
if (end)
*end = '\0';
} else {
priv_dir = os_strdup("/var/run/wpa_priv");
if (priv_dir == NULL) {
os_free(own_dir);
return -1;
}
}
len = os_strlen(own_dir) + 50;
drv->own_socket_path = os_malloc(len);
if (drv->own_socket_path == NULL) {
os_free(priv_dir);
os_free(own_dir);
return -1;
}
os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
own_dir, getpid(), counter++);
len = os_strlen(own_dir) + 50;
drv->own_cmd_path = os_malloc(len);
if (drv->own_cmd_path == NULL) {
os_free(drv->own_socket_path);
drv->own_socket_path = NULL;
os_free(priv_dir);
os_free(own_dir);
return -1;
}
os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
own_dir, getpid(), counter++);
os_free(own_dir);
drv->priv_addr.sun_family = AF_UNIX;
os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
"%s/%s", priv_dir, drv->ifname);
os_free(priv_dir);
drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
if (drv->priv_socket < 0) {
perror("socket(PF_UNIX)");
os_free(drv->own_socket_path);
drv->own_socket_path = NULL;
return -1;
}
os_memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
perror("bind(PF_UNIX)");
close(drv->priv_socket);
drv->priv_socket = -1;
unlink(drv->own_socket_path);
os_free(drv->own_socket_path);
drv->own_socket_path = NULL;
return -1;
}
eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
drv, NULL);
drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
if (drv->cmd_socket < 0) {
perror("socket(PF_UNIX)");
os_free(drv->own_cmd_path);
drv->own_cmd_path = NULL;
return -1;
}
os_memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
perror("bind(PF_UNIX)");
close(drv->cmd_socket);
drv->cmd_socket = -1;
unlink(drv->own_cmd_path);
os_free(drv->own_cmd_path);
drv->own_cmd_path = NULL;
return -1;
}
if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
return -1;
}
return 0;
}
static int wpa_driver_privsep_get_capa(void *priv,
struct wpa_driver_capa *capa)
{
struct wpa_driver_privsep_data *drv = priv;
int res;
size_t len = sizeof(*capa);
res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
if (res < 0 || len != sizeof(*capa))
return -1;
return 0;
}
static const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
{
struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s", __func__);
return drv->own_addr;
}
static int wpa_driver_privsep_set_mode(void *priv, int mode)
{
struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s mode=%d", __func__, mode);
return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_MODE, &mode, sizeof(mode),
NULL, NULL);
}
static int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
{
struct wpa_driver_privsep_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
os_strlen(alpha2), NULL, NULL);
}
struct wpa_driver_ops wpa_driver_privsep_ops = {
"privsep",
"wpa_supplicant privilege separated driver",
wpa_driver_privsep_get_bssid,
wpa_driver_privsep_get_ssid,
wpa_driver_privsep_set_wpa,
wpa_driver_privsep_set_key,
wpa_driver_privsep_init,
wpa_driver_privsep_deinit,
wpa_driver_privsep_set_param,
NULL /* set_countermeasures */,
NULL /* set_drop_unencrypted */,
wpa_driver_privsep_scan,
NULL /* get_scan_results */,
wpa_driver_privsep_deauthenticate,
wpa_driver_privsep_disassociate,
wpa_driver_privsep_associate,
NULL /* set_auth_alg */,
NULL /* add_pmkid */,
NULL /* remove_pmkid */,
NULL /* flush_pmkid */,
wpa_driver_privsep_get_capa,
NULL /* poll */,
NULL /* get_ifname */,
wpa_driver_privsep_get_mac_addr,
NULL /* send_eapol */,
NULL /* set_operstate */,
NULL /* mlme_setprotection */,
NULL /* get_hw_feature_data */,
NULL /* set_channel */,
NULL /* set_ssid */,
NULL /* set_bssid */,
NULL /* send_mlme */,
NULL /* mlme_add_sta */,
NULL /* mlme_remove_sta */,
NULL /* update_ft_ies */,
NULL /* send_ft_action */,
wpa_driver_privsep_get_scan_results2,
NULL /* set_probe_req_ie */,
wpa_driver_privsep_set_mode,
wpa_driver_privsep_set_country,
NULL /* global_init */,
NULL /* global_deinit */,
NULL /* init2 */,
NULL /* get_interfaces */
};
struct wpa_driver_ops *wpa_supplicant_drivers[] =
{
&wpa_driver_privsep_ops,
NULL
};

View File

@ -1,186 +0,0 @@
/*
* WPA Supplicant - PS3 Linux wireless extension driver interface
* Copyright 2007, 2008 Sony Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include "wireless_copy.h"
#include "common.h"
#include "wpa_common.h"
#include "driver.h"
#include "eloop.h"
#include "driver_wext.h"
#include "ieee802_11_defs.h"
static int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv,
struct wpa_driver_associate_params *params)
{
int ret, i;
struct iwreq iwr;
char *buf, *str;
if (!params->psk && !params->passphrase) {
wpa_printf(MSG_INFO, "%s:no PSK error", __func__);
return -EINVAL;
}
os_memset(&iwr, 0, sizeof(iwr));
if (params->psk) {
/* includes null */
iwr.u.data.length = PMK_LEN * 2 + 1;
buf = os_malloc(iwr.u.data.length);
if (!buf)
return -ENOMEM;
str = buf;
for (i = 0; i < PMK_LEN; i++) {
str += snprintf(str, iwr.u.data.length - (str - buf),
"%02x", params->psk[i]);
}
} else if (params->passphrase) {
/* including quotations and null */
iwr.u.data.length = strlen(params->passphrase) + 3;
buf = os_malloc(iwr.u.data.length);
if (!buf)
return -ENOMEM;
buf[0] = '"';
os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3);
buf[iwr.u.data.length - 2] = '"';
buf[iwr.u.data.length - 1] = '\0';
} else
return -EINVAL;
iwr.u.data.pointer = (caddr_t) buf;
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr);
os_free(buf);
return ret;
}
static int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv,
struct wpa_driver_associate_params *params)
{
int ret, i;
struct iwreq iwr;
for (i = 0; i < 4; i++) {
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
iwr.u.encoding.flags = i + 1;
if (params->wep_key_len[i]) {
iwr.u.encoding.pointer = (caddr_t) params->wep_key[i];
iwr.u.encoding.length = params->wep_key_len[i];
} else
iwr.u.encoding.flags = IW_ENCODE_NOKEY |
IW_ENCODE_DISABLED;
if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
perror("ioctl[SIOCSIWENCODE]");
ret = -1;
}
}
return ret;
}
static int wpa_driver_ps3_associate(void *priv,
struct wpa_driver_associate_params *params)
{
struct wpa_driver_wext_data *drv = priv;
int ret, value;
wpa_printf(MSG_DEBUG, "%s: <-", __func__);
/* clear BSSID */
if (!params->bssid &&
wpa_driver_wext_set_bssid(drv, NULL) < 0)
ret = -1;
if (wpa_driver_wext_set_mode(drv, params->mode) < 0)
ret = -1;
if (params->wpa_ie == NULL || params->wpa_ie_len == 0)
value = IW_AUTH_WPA_VERSION_DISABLED;
else if (params->wpa_ie[0] == WLAN_EID_RSN)
value = IW_AUTH_WPA_VERSION_WPA2;
else
value = IW_AUTH_WPA_VERSION_WPA;
if (wpa_driver_wext_set_auth_param(drv,
IW_AUTH_WPA_VERSION, value) < 0)
ret = -1;
value = wpa_driver_wext_cipher2wext(params->pairwise_suite);
if (wpa_driver_wext_set_auth_param(drv,
IW_AUTH_CIPHER_PAIRWISE, value) < 0)
ret = -1;
value = wpa_driver_wext_cipher2wext(params->group_suite);
if (wpa_driver_wext_set_auth_param(drv,
IW_AUTH_CIPHER_GROUP, value) < 0)
ret = -1;
value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite);
if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_KEY_MGMT, value) < 0)
ret = -1;
/* set selected BSSID */
if (params->bssid &&
wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
ret = -1;
switch (params->group_suite) {
case CIPHER_NONE:
ret = 0;
break;
case CIPHER_WEP40:
case CIPHER_WEP104:
ret = wpa_driver_ps3_set_wep_keys(drv, params);
break;
case CIPHER_TKIP:
case CIPHER_CCMP:
ret = wpa_driver_ps3_set_wpa_key(drv, params);
break;
}
/* start to associate */
ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len);
wpa_printf(MSG_DEBUG, "%s: ->", __func__);
return ret;
}
static int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa)
{
int ret;
wpa_printf(MSG_DEBUG, "%s:<-", __func__);
ret = wpa_driver_wext_get_capa(priv, capa);
if (ret) {
wpa_printf(MSG_INFO, "%s: base wext returns error %d",
__func__, ret);
return ret;
}
/* PS3 hypervisor does association and 4way handshake by itself */
capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
wpa_printf(MSG_DEBUG, "%s:->", __func__);
return 0;
}
const struct wpa_driver_ops wpa_driver_ps3_ops = {
.name = "ps3",
.desc = "PLAYSTATION3 Linux wireless extension driver",
.get_bssid = wpa_driver_wext_get_bssid,
.get_ssid = wpa_driver_wext_get_ssid,
.scan = wpa_driver_wext_scan,
.get_scan_results2 = wpa_driver_wext_get_scan_results,
.associate = wpa_driver_ps3_associate, /* PS3 */
.init = wpa_driver_wext_init,
.deinit = wpa_driver_wext_deinit,
.get_capa = wpa_driver_ps3_get_capa, /* PS3 */
};

File diff suppressed because it is too large Load Diff

View File

@ -1,382 +0,0 @@
/*
* WPA Supplicant - driver_ralink exported functions
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007, Snowpin Lee <snowpin_lee@ralinktech.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
// Ralink defined OIDs
#if WIRELESS_EXT <= 11
#ifndef SIOCDEVPRIVATE
#define SIOCDEVPRIVATE 0x8BE0
#endif
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
#endif
#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E)
#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02)
// IEEE 802.11 OIDs & Ralink defined OIDs ******
// (RaConfig Set/QueryInform) ==>
#define OID_GET_SET_TOGGLE 0x8000
#define OID_802_11_ADD_WEP 0x0112
#define OID_802_11_REMOVE_WEP 0x0113
#define OID_802_11_DISASSOCIATE 0x0114
#define OID_802_11_PRIVACY_FILTER 0x0118
#define OID_802_11_ASSOCIATION_INFORMATION 0x011E
#define OID_802_11_BSSID_LIST_SCAN 0x0508
#define OID_802_11_SSID 0x0509
#define OID_802_11_BSSID 0x050A
#define OID_802_11_WEP_STATUS 0x0510
#define OID_802_11_AUTHENTICATION_MODE 0x0511
#define OID_802_11_INFRASTRUCTURE_MODE 0x0512
#define OID_802_11_TX_POWER_LEVEL 0x0517
#define OID_802_11_REMOVE_KEY 0x0519
#define OID_802_11_ADD_KEY 0x0520
#define OID_802_11_DEAUTHENTICATION 0x0526
#define OID_802_11_DROP_UNENCRYPTED 0x0527
#define OID_802_11_BSSID_LIST 0x0609
#define OID_802_3_CURRENT_ADDRESS 0x060A
#define OID_SET_COUNTERMEASURES 0x0616
#define OID_802_11_SET_IEEE8021X 0x0617 // For IEEE8021x mode
#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 // For DynamicWEP in IEEE802.1x mode
#define OID_802_11_PMKID 0x0620
#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 // for trigger driver enable/disable wpa_supplicant support
#define RT_OID_WE_VERSION_COMPILED 0x0622
#define RT_OID_NEW_DRIVER 0x0623
#define PACKED __attribute__ ((packed))
//wpa_supplicant event flags
#define RT_ASSOC_EVENT_FLAG 0x0101
#define RT_DISASSOC_EVENT_FLAG 0x0102
#define RT_REQIE_EVENT_FLAG 0x0103
#define RT_RESPIE_EVENT_FLAG 0x0104
#define RT_ASSOCINFO_EVENT_FLAG 0x0105
#define RT_PMKIDCAND_FLAG 0x0106
#define RT_INTERFACE_DOWN 0x0107
#define RT_REPORT_AP_INFO 0x0108
//
// IEEE 802.11 Structures and definitions
//
// new types for Media Specific Indications
#ifndef ULONG
#define CHAR char
#define INT int
#define SHORT int
#define UINT u32
#undef ULONG
//#define ULONG u32
#define ULONG unsigned long /* 32-bit in 32-bit CPU or 64-bit in 64-bit CPU */
#define USHORT unsigned short
#define UCHAR unsigned char
#define uint32 u32
#define uint8 u8
#define BOOLEAN u8
//#define LARGE_INTEGER s64
#define VOID void
#define LONG long
#define LONGLONG s64
#define ULONGLONG u64
typedef VOID *PVOID;
typedef CHAR *PCHAR;
typedef UCHAR *PUCHAR;
typedef USHORT *PUSHORT;
typedef LONG *PLONG;
typedef ULONG *PULONG;
typedef union _LARGE_INTEGER {
struct {
ULONG LowPart;
LONG HighPart;
}vv;
struct {
ULONG LowPart;
LONG HighPart;
} u;
s64 QuadPart;
} LARGE_INTEGER;
#endif
#define NDIS_802_11_LENGTH_SSID 32
#define NDIS_802_11_LENGTH_RATES 8
#define NDIS_802_11_LENGTH_RATES_EX 16
#define MAX_LEN_OF_SSID 32
#define MAC_ADDR_LEN 6
typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
// mask for authentication/integrity fields
#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f
#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
// Added new types for OFDM 5G and 2.4G
typedef enum _NDIS_802_11_NETWORK_TYPE
{
Ndis802_11FH,
Ndis802_11DS,
Ndis802_11OFDM5,
Ndis802_11OFDM24,
Ndis802_11Automode,
Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound
} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE;
//
// Received Signal Strength Indication
//
typedef LONG NDIS_802_11_RSSI; // in dBm
typedef struct _NDIS_802_11_CONFIGURATION_FH
{
ULONG Length; // Length of structure
ULONG HopPattern; // As defined by 802.11, MSB set
ULONG HopSet; // to one if non-802.11
ULONG DwellTime; // units are Kusec
} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH;
typedef struct _NDIS_802_11_CONFIGURATION
{
ULONG Length; // Length of structure
ULONG BeaconPeriod; // units are Kusec
ULONG ATIMWindow; // units are Kusec
ULONG DSConfig; // Frequency, units are kHz
NDIS_802_11_CONFIGURATION_FH FHConfig;
} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION;
typedef ULONG NDIS_802_11_KEY_INDEX;
typedef ULONGLONG NDIS_802_11_KEY_RSC;
// Key mapping keys require a BSSID
typedef struct _NDIS_802_11_KEY
{
UINT Length; // Length of this structure
UINT KeyIndex;
UINT KeyLength; // length of key in bytes
NDIS_802_11_MAC_ADDRESS BSSID;
NDIS_802_11_KEY_RSC KeyRSC;
UCHAR KeyMaterial[1]; // variable length depending on above field
} NDIS_802_11_KEY, *PNDIS_802_11_KEY;
typedef struct _NDIS_802_11_REMOVE_KEY
{
UINT Length; // Length of this structure
UINT KeyIndex;
NDIS_802_11_MAC_ADDRESS BSSID;
} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY;
typedef struct PACKED _NDIS_802_11_WEP
{
UINT Length; // Length of this structure
UINT KeyIndex; // 0 is the per-client key, 1-N are the
// global keys
UINT KeyLength; // length of key in bytes
UCHAR KeyMaterial[1];// variable length depending on above field
} NDIS_802_11_WEP, *PNDIS_802_11_WEP;
typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE
{
Ndis802_11IBSS,
Ndis802_11Infrastructure,
Ndis802_11AutoUnknown,
Ndis802_11InfrastructureMax // Not a real value, defined as upper bound
} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE;
// PMKID Structures
typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
typedef struct _BSSID_INFO
{
NDIS_802_11_MAC_ADDRESS BSSID;
NDIS_802_11_PMKID_VALUE PMKID;
} BSSID_INFO, *PBSSID_INFO;
typedef struct _NDIS_802_11_PMKID
{
ULONG Length;
ULONG BSSIDInfoCount;
BSSID_INFO BSSIDInfo[1];
} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID;
//Added new types for PMKID Candidate lists.
typedef struct _PMKID_CANDIDATE {
NDIS_802_11_MAC_ADDRESS BSSID;
ULONG Flags;
} PMKID_CANDIDATE, *PPMKID_CANDIDATE;
typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST
{
ULONG Version; // Version of the structure
ULONG NumCandidates; // No. of pmkid candidates
PMKID_CANDIDATE CandidateList[1];
} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST;
//Flags for PMKID Candidate list structure
#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
// Add new authentication modes
typedef enum _NDIS_802_11_AUTHENTICATION_MODE
{
Ndis802_11AuthModeOpen,
Ndis802_11AuthModeShared,
Ndis802_11AuthModeAutoSwitch,
Ndis802_11AuthModeWPA,
Ndis802_11AuthModeWPAPSK,
Ndis802_11AuthModeWPANone,
Ndis802_11AuthModeWPA2,
Ndis802_11AuthModeWPA2PSK,
Ndis802_11AuthModeMax // Not a real mode, defined as upper bound
} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE;
typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates
typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates
typedef struct PACKED _NDIS_802_11_SSID
{
INT SsidLength; // length of SSID field below, in bytes;
// this can be zero.
UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field
} NDIS_802_11_SSID, *PNDIS_802_11_SSID;
typedef struct PACKED _NDIS_WLAN_BSSID
{
ULONG Length; // Length of this structure
NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID
UCHAR Reserved[2];
NDIS_802_11_SSID Ssid; // SSID
ULONG Privacy; // WEP encryption requirement
NDIS_802_11_RSSI Rssi; // receive signal
// strength in dBm
NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
NDIS_802_11_CONFIGURATION Configuration;
NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
NDIS_802_11_RATES SupportedRates;
} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID;
typedef struct PACKED _NDIS_802_11_BSSID_LIST
{
UINT NumberOfItems; // in list below, at least 1
NDIS_WLAN_BSSID Bssid[1];
} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;
// Added Capabilities, IELength and IEs for each BSSID
typedef struct PACKED _NDIS_WLAN_BSSID_EX
{
ULONG Length; // Length of this structure
NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID
UCHAR Reserved[2];
NDIS_802_11_SSID Ssid; // SSID
UINT Privacy; // WEP encryption requirement
NDIS_802_11_RSSI Rssi; // receive signal
// strength in dBm
NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
NDIS_802_11_CONFIGURATION Configuration;
NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
NDIS_802_11_RATES_EX SupportedRates;
ULONG IELength;
UCHAR IEs[1];
} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX;
typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX
{
UINT NumberOfItems; // in list below, at least 1
NDIS_WLAN_BSSID_EX Bssid[1];
} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX;
typedef struct PACKED _NDIS_802_11_FIXED_IEs
{
UCHAR Timestamp[8];
USHORT BeaconInterval;
USHORT Capabilities;
} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs;
// Added new encryption types
// Also aliased typedef to new name
typedef enum _NDIS_802_11_WEP_STATUS
{
Ndis802_11WEPEnabled,
Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
Ndis802_11WEPDisabled,
Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
Ndis802_11WEPKeyAbsent,
Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
Ndis802_11WEPNotSupported,
Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
Ndis802_11Encryption2Enabled,
Ndis802_11Encryption2KeyAbsent,
Ndis802_11Encryption3Enabled,
Ndis802_11Encryption3KeyAbsent
} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS,
NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
typedef enum _NDIS_802_11_RELOAD_DEFAULTS
{
Ndis802_11ReloadWEPKeys
} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS;
#define NDIS_802_11_AI_REQFI_CAPABILITIES 1
#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2
#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4
#define NDIS_802_11_AI_RESFI_CAPABILITIES 1
#define NDIS_802_11_AI_RESFI_STATUSCODE 2
#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
typedef struct _NDIS_802_11_AI_REQFI
{
USHORT Capabilities;
USHORT ListenInterval;
NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI;
typedef struct _NDIS_802_11_AI_RESFI
{
USHORT Capabilities;
USHORT StatusCode;
USHORT AssociationId;
} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI;
typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
{
ULONG Length;
USHORT AvailableRequestFixedIEs;
NDIS_802_11_AI_REQFI RequestFixedIEs;
ULONG RequestIELength;
ULONG OffsetRequestIEs;
USHORT AvailableResponseFixedIEs;
NDIS_802_11_AI_RESFI ResponseFixedIEs;
ULONG ResponseIELength;
ULONG OffsetResponseIEs;
} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
struct ndis_pmkid_entry {
struct ndis_pmkid_entry *next;
u8 bssid[ETH_ALEN];
u8 pmkid[16];
};
typedef struct _MLME_DEAUTH_REQ_STRUCT {
UCHAR Addr[MAC_ADDR_LEN];
USHORT Reason;
} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT;

View File

@ -1,476 +0,0 @@
/*
* WPA Supplicant - roboswitch driver interface
* Copyright (c) 2008-2009 Jouke Witteveen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <linux/if_ether.h>
#include <linux/mii.h>
#include "common.h"
#include "driver.h"
#include "l2_packet/l2_packet.h"
#ifndef ETH_P_EAPOL
#define ETH_P_EAPOL 0x888e
#endif
#define ROBO_PHY_ADDR 0x1e /* RoboSwitch PHY address */
/* MII access registers */
#define ROBO_MII_PAGE 0x10 /* MII page register */
#define ROBO_MII_ADDR 0x11 /* MII address register */
#define ROBO_MII_DATA_OFFSET 0x18 /* Start of MII data registers */
#define ROBO_MII_PAGE_ENABLE 0x01 /* MII page op code */
#define ROBO_MII_ADDR_WRITE 0x01 /* MII address write op code */
#define ROBO_MII_ADDR_READ 0x02 /* MII address read op code */
#define ROBO_MII_DATA_MAX 4 /* Consecutive MII data registers */
#define ROBO_MII_RETRY_MAX 10 /* Read attempts before giving up */
/* Page numbers */
#define ROBO_ARLCTRL_PAGE 0x04 /* ARL control page */
#define ROBO_VLAN_PAGE 0x34 /* VLAN page */
/* ARL control page registers */
#define ROBO_ARLCTRL_CONF 0x00 /* ARL configuration register */
#define ROBO_ARLCTRL_ADDR_1 0x10 /* Multiport address 1 */
#define ROBO_ARLCTRL_VEC_1 0x16 /* Multiport vector 1 */
#define ROBO_ARLCTRL_ADDR_2 0x20 /* Multiport address 2 */
#define ROBO_ARLCTRL_VEC_2 0x26 /* Multiport vector 2 */
/* VLAN page registers */
#define ROBO_VLAN_ACCESS 0x08 /* VLAN table access register */
#define ROBO_VLAN_ACCESS_5350 0x06 /* VLAN table access register (5350) */
#define ROBO_VLAN_READ 0x0c /* VLAN read register */
#define ROBO_VLAN_MAX 0xff /* Maximum number of VLANs */
static const u8 pae_group_addr[ETH_ALEN] =
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
struct wpa_driver_roboswitch_data {
void *ctx;
struct l2_packet_data *l2;
char ifname[IFNAMSIZ + 1];
u8 own_addr[ETH_ALEN];
struct ifreq ifr;
int fd, is_5350;
u16 ports;
};
/* Copied from the kernel-only part of mii.h. */
static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
{
return (struct mii_ioctl_data *) &rq->ifr_ifru;
}
/*
* RoboSwitch uses 16-bit Big Endian addresses.
* The ordering of the words is reversed in the MII registers.
*/
static void wpa_driver_roboswitch_addr_be16(const u8 addr[ETH_ALEN], u16 *be)
{
int i;
for (i = 0; i < ETH_ALEN; i += 2)
be[(ETH_ALEN - i) / 2 - 1] = WPA_GET_BE16(addr + i);
}
static u16 wpa_driver_roboswitch_mdio_read(
struct wpa_driver_roboswitch_data *drv, u8 reg)
{
struct mii_ioctl_data *mii = if_mii(&drv->ifr);
mii->phy_id = ROBO_PHY_ADDR;
mii->reg_num = reg;
if (ioctl(drv->fd, SIOCGMIIREG, &drv->ifr) < 0) {
perror("ioctl[SIOCGMIIREG]");
return 0x00;
}
return mii->val_out;
}
static void wpa_driver_roboswitch_mdio_write(
struct wpa_driver_roboswitch_data *drv, u8 reg, u16 val)
{
struct mii_ioctl_data *mii = if_mii(&drv->ifr);
mii->phy_id = ROBO_PHY_ADDR;
mii->reg_num = reg;
mii->val_in = val;
if (ioctl(drv->fd, SIOCSMIIREG, &drv->ifr) < 0) {
perror("ioctl[SIOCSMIIREG");
}
}
static int wpa_driver_roboswitch_reg(struct wpa_driver_roboswitch_data *drv,
u8 page, u8 reg, u8 op)
{
int i;
/* set page number */
wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_PAGE,
(page << 8) | ROBO_MII_PAGE_ENABLE);
/* set register address */
wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_ADDR, (reg << 8) | op);
/* check if operation completed */
for (i = 0; i < ROBO_MII_RETRY_MAX; ++i) {
if ((wpa_driver_roboswitch_mdio_read(drv, ROBO_MII_ADDR) & 3)
== 0)
return 0;
}
/* timeout */
return -1;
}
static int wpa_driver_roboswitch_read(struct wpa_driver_roboswitch_data *drv,
u8 page, u8 reg, u16 *val, int len)
{
int i;
if (len > ROBO_MII_DATA_MAX ||
wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_READ) < 0)
return -1;
for (i = 0; i < len; ++i) {
val[i] = wpa_driver_roboswitch_mdio_read(
drv, ROBO_MII_DATA_OFFSET + i);
}
return 0;
}
static int wpa_driver_roboswitch_write(struct wpa_driver_roboswitch_data *drv,
u8 page, u8 reg, u16 *val, int len)
{
int i;
if (len > ROBO_MII_DATA_MAX) return -1;
for (i = 0; i < len; ++i) {
wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_DATA_OFFSET + i,
val[i]);
}
return wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_WRITE);
}
static void wpa_driver_roboswitch_receive(void *priv, const u8 *src_addr,
const u8 *buf, size_t len)
{
struct wpa_driver_roboswitch_data *drv = priv;
if (len > 14 && WPA_GET_BE16(buf + 12) == ETH_P_EAPOL &&
os_memcmp(buf, drv->own_addr, ETH_ALEN) == 0) {
wpa_supplicant_rx_eapol(drv->ctx, src_addr, buf + 14,
len - 14);
}
}
static int wpa_driver_roboswitch_get_ssid(void *priv, u8 *ssid)
{
ssid[0] = 0;
return 0;
}
static int wpa_driver_roboswitch_get_bssid(void *priv, u8 *bssid)
{
/* Report PAE group address as the "BSSID" for wired connection. */
os_memcpy(bssid, pae_group_addr, ETH_ALEN);
return 0;
}
static int wpa_driver_roboswitch_set_param(void *priv, const char *param)
{
struct wpa_driver_roboswitch_data *drv = priv;
char *sep;
if (param == NULL || os_strstr(param, "multicast_only=1") == NULL) {
sep = drv->ifname + os_strlen(drv->ifname);
*sep = '.';
drv->l2 = l2_packet_init(drv->ifname, NULL, ETH_P_ALL,
wpa_driver_roboswitch_receive, drv,
1);
if (drv->l2 == NULL) {
wpa_printf(MSG_INFO, "%s: Unable to listen on %s",
__func__, drv->ifname);
return -1;
}
*sep = '\0';
l2_packet_get_own_addr(drv->l2, drv->own_addr);
} else {
wpa_printf(MSG_DEBUG, "%s: Ignoring unicast frames", __func__);
drv->l2 = NULL;
}
return 0;
}
static const char * wpa_driver_roboswitch_get_ifname(void *priv)
{
struct wpa_driver_roboswitch_data *drv = priv;
return drv->ifname;
}
static int wpa_driver_roboswitch_join(struct wpa_driver_roboswitch_data *drv,
u16 ports, const u8 *addr)
{
u16 read1[3], read2[3], addr_be16[3];
wpa_driver_roboswitch_addr_be16(addr, addr_be16);
if (wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_CONF, read1, 1) < 0)
return -1;
if (!(read1[0] & (1 << 4))) {
/* multiport addresses are not yet enabled */
read1[0] |= 1 << 4;
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_1, addr_be16, 3);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_1, &ports, 1);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_2, addr_be16, 3);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_2, &ports, 1);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_CONF, read1, 1);
} else {
/* if both multiport addresses are the same we can add */
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_1, read1, 3);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_2, read2, 3);
if (os_memcmp(read1, read2, 6) != 0)
return -1;
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_1, read1, 1);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_2, read2, 1);
if (read1[0] != read2[0])
return -1;
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_1, addr_be16, 3);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_1, &ports, 1);
}
return 0;
}
static int wpa_driver_roboswitch_leave(struct wpa_driver_roboswitch_data *drv,
u16 ports, const u8 *addr)
{
u16 _read, addr_be16[3], addr_read[3], ports_read;
wpa_driver_roboswitch_addr_be16(addr, addr_be16);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_CONF,
&_read, 1);
/* If ARL control is disabled, there is nothing to leave. */
if (!(_read & (1 << 4))) return -1;
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_1, addr_read, 3);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_VEC_1,
&ports_read, 1);
/* check if we occupy multiport address 1 */
if (os_memcmp(addr_read, addr_be16, 6) == 0 && ports_read == ports) {
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_2, addr_read, 3);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_2, &ports_read, 1);
/* and multiport address 2 */
if (os_memcmp(addr_read, addr_be16, 6) == 0 &&
ports_read == ports) {
_read &= ~(1 << 4);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_CONF, &_read,
1);
} else {
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_1,
addr_read, 3);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_1,
&ports_read, 1);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_2,
addr_read, 3);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_2,
&ports_read, 1);
}
} else {
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_2, addr_read, 3);
wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_2, &ports_read, 1);
/* or multiport address 2 */
if (os_memcmp(addr_read, addr_be16, 6) == 0 &&
ports_read == ports) {
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_ADDR_1,
addr_read, 3);
wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
ROBO_ARLCTRL_VEC_1,
&ports_read, 1);
} else return -1;
}
return 0;
}
static void * wpa_driver_roboswitch_init(void *ctx, const char *ifname)
{
struct wpa_driver_roboswitch_data *drv;
char *sep;
u16 vlan = 0, _read[2];
drv = os_zalloc(sizeof(*drv));
if (drv == NULL) return NULL;
drv->ctx = ctx;
drv->own_addr[0] = '\0';
/* copy ifname and take a pointer to the second to last character */
sep = drv->ifname +
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)) - 2;
/* find the '.' seperating <interface> and <vlan> */
while (sep > drv->ifname && *sep != '.') sep--;
if (sep <= drv->ifname) {
wpa_printf(MSG_INFO, "%s: No <interface>.<vlan> pair in "
"interface name %s", __func__, drv->ifname);
os_free(drv);
return NULL;
}
*sep = '\0';
while (*++sep) {
if (*sep < '0' || *sep > '9') {
wpa_printf(MSG_INFO, "%s: Invalid vlan specification "
"in interface name %s", __func__, ifname);
os_free(drv);
return NULL;
}
vlan *= 10;
vlan += *sep - '0';
if (vlan > ROBO_VLAN_MAX) {
wpa_printf(MSG_INFO, "%s: VLAN out of range in "
"interface name %s", __func__, ifname);
os_free(drv);
return NULL;
}
}
drv->fd = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->fd < 0) {
wpa_printf(MSG_INFO, "%s: Unable to create socket", __func__);
os_free(drv);
return NULL;
}
os_memset(&drv->ifr, 0, sizeof(drv->ifr));
os_strlcpy(drv->ifr.ifr_name, drv->ifname, IFNAMSIZ);
if (ioctl(drv->fd, SIOCGMIIPHY, &drv->ifr) < 0) {
perror("ioctl[SIOCGMIIPHY]");
os_free(drv);
return NULL;
}
if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR) {
wpa_printf(MSG_INFO, "%s: Invalid phy address (not a "
"RoboSwitch?)", __func__);
os_free(drv);
return NULL;
}
/* set and read back to see if the register can be used */
_read[0] = ROBO_VLAN_MAX;
wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS_5350,
_read, 1);
wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS_5350,
_read + 1, 1);
drv->is_5350 = _read[0] == _read[1];
/* set the read bit */
vlan |= 1 << 13;
wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE,
drv->is_5350 ? ROBO_VLAN_ACCESS_5350
: ROBO_VLAN_ACCESS,
&vlan, 1);
wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_READ, _read,
drv->is_5350 ? 2 : 1);
if (!(drv->is_5350 ? _read[1] & (1 << 4) : _read[0] & (1 << 14))) {
wpa_printf(MSG_INFO, "%s: Could not get port information for "
"VLAN %d", __func__, vlan & ~(1 << 13));
os_free(drv);
return NULL;
}
drv->ports = _read[0] & 0x001F;
/* add the MII port */
drv->ports |= 1 << 8;
if (wpa_driver_roboswitch_join(drv, drv->ports, pae_group_addr) < 0) {
wpa_printf(MSG_INFO, "%s: Unable to join PAE group", __func__);
os_free(drv);
return NULL;
} else {
wpa_printf(MSG_DEBUG, "%s: Added PAE group address to "
"RoboSwitch ARL", __func__);
}
return drv;
}
static void wpa_driver_roboswitch_deinit(void *priv)
{
struct wpa_driver_roboswitch_data *drv = priv;
if (drv->l2) {
l2_packet_deinit(drv->l2);
drv->l2 = NULL;
}
if (wpa_driver_roboswitch_leave(drv, drv->ports, pae_group_addr) < 0) {
wpa_printf(MSG_DEBUG, "%s: Unable to leave PAE group",
__func__);
}
close(drv->fd);
os_free(drv);
}
const struct wpa_driver_ops wpa_driver_roboswitch_ops = {
.name = "roboswitch",
.desc = "wpa_supplicant roboswitch driver",
.get_ssid = wpa_driver_roboswitch_get_ssid,
.get_bssid = wpa_driver_roboswitch_get_bssid,
.init = wpa_driver_roboswitch_init,
.deinit = wpa_driver_roboswitch_deinit,
.set_param = wpa_driver_roboswitch_set_param,
.get_ifname = wpa_driver_roboswitch_get_ifname,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
/*
* WPA Supplicant - driver_wext exported functions
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef DRIVER_WEXT_H
#define DRIVER_WEXT_H
#include <net/if.h>
struct wpa_driver_wext_data {
void *ctx;
int event_sock;
int ioctl_sock;
int mlme_sock;
char ifname[IFNAMSIZ + 1];
int ifindex;
int ifindex2;
int if_removed;
u8 *assoc_req_ies;
size_t assoc_req_ies_len;
u8 *assoc_resp_ies;
size_t assoc_resp_ies_len;
struct wpa_driver_capa capa;
int has_capability;
int we_version_compiled;
/* for set_auth_alg fallback */
int use_crypt;
int auth_alg_fallback;
int operstate;
char mlmedev[IFNAMSIZ + 1];
int scan_complete_events;
};
int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags);
int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags);
int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);
int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid);
int wpa_driver_wext_get_ssid(void *priv, u8 *ssid);
int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len);
int wpa_driver_wext_set_freq(void *priv, int freq);
int wpa_driver_wext_set_mode(void *priv, int mode);
int wpa_driver_wext_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx,
int set_tx, const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len);
int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len);
struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv);
void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx);
int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv,
const char *ifname);
void * wpa_driver_wext_init(void *ctx, const char *ifname);
void wpa_driver_wext_deinit(void *priv);
int wpa_driver_wext_set_operstate(void *priv, int state);
int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv);
int wpa_driver_wext_associate(void *priv,
struct wpa_driver_associate_params *params);
int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa);
int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
int idx, u32 value);
int wpa_driver_wext_cipher2wext(int cipher);
int wpa_driver_wext_keymgmt2wext(int keymgmt);
#endif /* DRIVER_WEXT_H */

View File

@ -1,104 +0,0 @@
/*
* wpa_supplicant - Private copy of Linux netlink/rtnetlink definitions.
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef PRIV_NETLINK_H
#define PRIV_NETLINK_H
/*
* This should be replaced with user space header once one is available with C
* library, etc..
*/
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
#endif
#ifndef IFF_DORMANT
#define IFF_DORMANT 0x20000 /* driver signals dormant */
#endif
#ifndef IFLA_IFNAME
#define IFLA_IFNAME 3
#endif
#ifndef IFLA_WIRELESS
#define IFLA_WIRELESS 11
#endif
#ifndef IFLA_OPERSTATE
#define IFLA_OPERSTATE 16
#endif
#ifndef IFLA_LINKMODE
#define IFLA_LINKMODE 17
#define IF_OPER_DORMANT 5
#define IF_OPER_UP 6
#endif
#define NLM_F_REQUEST 1
#define NETLINK_ROUTE 0
#define RTMGRP_LINK 1
#define RTM_BASE 0x10
#define RTM_NEWLINK (RTM_BASE + 0)
#define RTM_DELLINK (RTM_BASE + 1)
#define RTM_SETLINK (RTM_BASE + 3)
#define NLMSG_ALIGNTO 4
#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1))
#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_DATA(nlh) ((void*) (((char*) nlh) + NLMSG_LENGTH(0)))
#define RTA_ALIGNTO 4
#define RTA_ALIGN(len) (((len) + RTA_ALIGNTO - 1) & ~(RTA_ALIGNTO - 1))
#define RTA_OK(rta,len) \
((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \
(rta)->rta_len <= (len))
#define RTA_NEXT(rta,attrlen) \
((attrlen) -= RTA_ALIGN((rta)->rta_len), \
(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len)))
#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0)))
struct sockaddr_nl
{
sa_family_t nl_family;
unsigned short nl_pad;
u32 nl_pid;
u32 nl_groups;
};
struct nlmsghdr
{
u32 nlmsg_len;
u16 nlmsg_type;
u16 nlmsg_flags;
u32 nlmsg_seq;
u32 nlmsg_pid;
};
struct ifinfomsg
{
unsigned char ifi_family;
unsigned char __ifi_pad;
unsigned short ifi_type;
int ifi_index;
unsigned ifi_flags;
unsigned ifi_change;
};
struct rtattr
{
unsigned short rta_len;
unsigned short rta_type;
};
#endif /* PRIV_NETLINK_H */

View File

@ -1,200 +0,0 @@
/*
* WPA Supplicant - Layer2 packet handling with Linux packet sockets
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/ioctl.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include "common.h"
#include "eloop.h"
#include "l2_packet.h"
struct l2_packet_data {
int fd; /* packet socket for EAPOL frames */
char ifname[IFNAMSIZ + 1];
int ifindex;
u8 own_addr[ETH_ALEN];
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len);
void *rx_callback_ctx;
int l2_hdr; /* whether to include layer 2 (Ethernet) header data
* buffers */
};
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
{
os_memcpy(addr, l2->own_addr, ETH_ALEN);
return 0;
}
int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
const u8 *buf, size_t len)
{
int ret;
if (l2 == NULL)
return -1;
if (l2->l2_hdr) {
ret = send(l2->fd, buf, len, 0);
if (ret < 0)
perror("l2_packet_send - send");
} else {
struct sockaddr_ll ll;
os_memset(&ll, 0, sizeof(ll));
ll.sll_family = AF_PACKET;
ll.sll_ifindex = l2->ifindex;
ll.sll_protocol = htons(proto);
ll.sll_halen = ETH_ALEN;
os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN);
ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll,
sizeof(ll));
if (ret < 0)
perror("l2_packet_send - sendto");
}
return ret;
}
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
struct l2_packet_data *l2 = eloop_ctx;
u8 buf[2300];
int res;
struct sockaddr_ll ll;
socklen_t fromlen;
os_memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
&fromlen);
if (res < 0) {
perror("l2_packet_receive - recvfrom");
return;
}
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}
struct l2_packet_data * l2_packet_init(
const char *ifname, const u8 *own_addr, unsigned short protocol,
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len),
void *rx_callback_ctx, int l2_hdr)
{
struct l2_packet_data *l2;
struct ifreq ifr;
struct sockaddr_ll ll;
l2 = os_zalloc(sizeof(struct l2_packet_data));
if (l2 == NULL)
return NULL;
os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname));
l2->rx_callback = rx_callback;
l2->rx_callback_ctx = rx_callback_ctx;
l2->l2_hdr = l2_hdr;
l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,
htons(protocol));
if (l2->fd < 0) {
perror("socket(PF_PACKET)");
os_free(l2);
return NULL;
}
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) {
perror("ioctl[SIOCGIFINDEX]");
close(l2->fd);
os_free(l2);
return NULL;
}
l2->ifindex = ifr.ifr_ifindex;
os_memset(&ll, 0, sizeof(ll));
ll.sll_family = PF_PACKET;
ll.sll_ifindex = ifr.ifr_ifindex;
ll.sll_protocol = htons(protocol);
if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
perror("bind[PF_PACKET]");
close(l2->fd);
os_free(l2);
return NULL;
}
if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) {
perror("ioctl[SIOCGIFHWADDR]");
close(l2->fd);
os_free(l2);
return NULL;
}
os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
return l2;
}
void l2_packet_deinit(struct l2_packet_data *l2)
{
if (l2 == NULL)
return;
if (l2->fd >= 0) {
eloop_unregister_read_sock(l2->fd);
close(l2->fd);
}
os_free(l2);
}
int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
{
int s;
struct ifreq ifr;
struct sockaddr_in *saddr;
size_t res;
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
return -1;
}
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
if (errno != EADDRNOTAVAIL)
perror("ioctl[SIOCGIFADDR]");
close(s);
return -1;
}
close(s);
saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in);
if (saddr->sin_family != AF_INET)
return -1;
res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len);
if (res >= len)
return -1;
return 0;
}
void l2_packet_notify_auth_start(struct l2_packet_data *l2)
{
}

View File

@ -1,386 +0,0 @@
/*
* WPA Supplicant - Layer2 packet handling with libpcap/libdnet and WinPcap
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#ifndef CONFIG_NATIVE_WINDOWS
#include <sys/ioctl.h>
#endif /* CONFIG_NATIVE_WINDOWS */
#include <pcap.h>
#ifndef CONFIG_WINPCAP
#include <dnet.h>
#endif /* CONFIG_WINPCAP */
#include "common.h"
#include "eloop.h"
#include "l2_packet.h"
static const u8 pae_group_addr[ETH_ALEN] =
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
struct l2_packet_data {
pcap_t *pcap;
#ifdef CONFIG_WINPCAP
unsigned int num_fast_poll;
#else /* CONFIG_WINPCAP */
eth_t *eth;
#endif /* CONFIG_WINPCAP */
char ifname[100];
u8 own_addr[ETH_ALEN];
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len);
void *rx_callback_ctx;
int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls
* to rx_callback */
};
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
{
os_memcpy(addr, l2->own_addr, ETH_ALEN);
return 0;
}
#ifndef CONFIG_WINPCAP
static int l2_packet_init_libdnet(struct l2_packet_data *l2)
{
eth_addr_t own_addr;
l2->eth = eth_open(l2->ifname);
if (!l2->eth) {
printf("Failed to open interface '%s'.\n", l2->ifname);
perror("eth_open");
return -1;
}
if (eth_get(l2->eth, &own_addr) < 0) {
printf("Failed to get own hw address from interface '%s'.\n",
l2->ifname);
perror("eth_get");
eth_close(l2->eth);
l2->eth = NULL;
return -1;
}
os_memcpy(l2->own_addr, own_addr.data, ETH_ALEN);
return 0;
}
#endif /* CONFIG_WINPCAP */
int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
const u8 *buf, size_t len)
{
int ret;
struct l2_ethhdr *eth;
if (l2 == NULL)
return -1;
if (l2->l2_hdr) {
#ifdef CONFIG_WINPCAP
ret = pcap_sendpacket(l2->pcap, buf, len);
#else /* CONFIG_WINPCAP */
ret = eth_send(l2->eth, buf, len);
#endif /* CONFIG_WINPCAP */
} else {
size_t mlen = sizeof(*eth) + len;
eth = os_malloc(mlen);
if (eth == NULL)
return -1;
os_memcpy(eth->h_dest, dst_addr, ETH_ALEN);
os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN);
eth->h_proto = htons(proto);
os_memcpy(eth + 1, buf, len);
#ifdef CONFIG_WINPCAP
ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen);
#else /* CONFIG_WINPCAP */
ret = eth_send(l2->eth, (u8 *) eth, mlen);
#endif /* CONFIG_WINPCAP */
os_free(eth);
}
return ret;
}
#ifndef CONFIG_WINPCAP
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
struct l2_packet_data *l2 = eloop_ctx;
pcap_t *pcap = sock_ctx;
struct pcap_pkthdr hdr;
const u_char *packet;
struct l2_ethhdr *ethhdr;
unsigned char *buf;
size_t len;
packet = pcap_next(pcap, &hdr);
if (packet == NULL || hdr.caplen < sizeof(*ethhdr))
return;
ethhdr = (struct l2_ethhdr *) packet;
if (l2->l2_hdr) {
buf = (unsigned char *) ethhdr;
len = hdr.caplen;
} else {
buf = (unsigned char *) (ethhdr + 1);
len = hdr.caplen - sizeof(*ethhdr);
}
l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
}
#endif /* CONFIG_WINPCAP */
#ifdef CONFIG_WINPCAP
static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr,
const u_char *pkt_data)
{
struct l2_packet_data *l2 = (struct l2_packet_data *) user;
struct l2_ethhdr *ethhdr;
unsigned char *buf;
size_t len;
if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr))
return;
ethhdr = (struct l2_ethhdr *) pkt_data;
if (l2->l2_hdr) {
buf = (unsigned char *) ethhdr;
len = hdr->caplen;
} else {
buf = (unsigned char *) (ethhdr + 1);
len = hdr->caplen - sizeof(*ethhdr);
}
l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
/*
* Use shorter poll interval for 3 seconds to reduce latency during key
* handshake.
*/
l2->num_fast_poll = 3 * 50;
}
static void l2_packet_receive_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct l2_packet_data *l2 = eloop_ctx;
pcap_t *pcap = timeout_ctx;
int timeout;
if (l2->num_fast_poll > 0) {
timeout = 20000;
l2->num_fast_poll--;
} else
timeout = 100000;
/* Register new timeout before calling l2_packet_receive() since
* receive handler may free this l2_packet instance (which will
* cancel this timeout). */
eloop_register_timeout(0, timeout, l2_packet_receive_timeout,
l2, pcap);
pcap_dispatch(pcap, 10, l2_packet_receive_cb, (u_char *) l2);
}
#endif /* CONFIG_WINPCAP */
static int l2_packet_init_libpcap(struct l2_packet_data *l2,
unsigned short protocol)
{
bpf_u_int32 pcap_maskp, pcap_netp;
char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE];
struct bpf_program pcap_fp;
#ifdef CONFIG_WINPCAP
char ifname[128];
os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", l2->ifname);
pcap_lookupnet(ifname, &pcap_netp, &pcap_maskp, pcap_err);
l2->pcap = pcap_open_live(ifname, 2500, 0, 10, pcap_err);
if (l2->pcap == NULL) {
fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
fprintf(stderr, "ifname='%s'\n", ifname);
return -1;
}
if (pcap_setnonblock(l2->pcap, 1, pcap_err) < 0)
fprintf(stderr, "pcap_setnonblock: %s\n",
pcap_geterr(l2->pcap));
#else /* CONFIG_WINPCAP */
pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err);
if (l2->pcap == NULL) {
fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
fprintf(stderr, "ifname='%s'\n", l2->ifname);
return -1;
}
if (pcap_datalink(l2->pcap) != DLT_EN10MB &&
pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) {
fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n",
pcap_geterr(l2->pcap));
return -1;
}
#endif /* CONFIG_WINPCAP */
os_snprintf(pcap_filter, sizeof(pcap_filter),
"not ether src " MACSTR " and "
"( ether dst " MACSTR " or ether dst " MACSTR " ) and "
"ether proto 0x%x",
MAC2STR(l2->own_addr), /* do not receive own packets */
MAC2STR(l2->own_addr), MAC2STR(pae_group_addr),
protocol);
if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
return -1;
}
if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap));
return -1;
}
pcap_freecode(&pcap_fp);
#ifdef BIOCIMMEDIATE
/*
* When libpcap uses BPF we must enable "immediate mode" to
* receive frames right away; otherwise the system may
* buffer them for us.
*/
{
unsigned int on = 1;
if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) {
fprintf(stderr, "%s: cannot enable immediate mode on "
"interface %s: %s\n",
__func__, l2->ifname, strerror(errno));
/* XXX should we fail? */
}
}
#endif /* BIOCIMMEDIATE */
#ifdef CONFIG_WINPCAP
eloop_register_timeout(0, 100000, l2_packet_receive_timeout,
l2, l2->pcap);
#else /* CONFIG_WINPCAP */
eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap),
l2_packet_receive, l2, l2->pcap);
#endif /* CONFIG_WINPCAP */
return 0;
}
struct l2_packet_data * l2_packet_init(
const char *ifname, const u8 *own_addr, unsigned short protocol,
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len),
void *rx_callback_ctx, int l2_hdr)
{
struct l2_packet_data *l2;
l2 = os_zalloc(sizeof(struct l2_packet_data));
if (l2 == NULL)
return NULL;
os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname));
l2->rx_callback = rx_callback;
l2->rx_callback_ctx = rx_callback_ctx;
l2->l2_hdr = l2_hdr;
#ifdef CONFIG_WINPCAP
if (own_addr)
os_memcpy(l2->own_addr, own_addr, ETH_ALEN);
#else /* CONFIG_WINPCAP */
if (l2_packet_init_libdnet(l2))
return NULL;
#endif /* CONFIG_WINPCAP */
if (l2_packet_init_libpcap(l2, protocol)) {
#ifndef CONFIG_WINPCAP
eth_close(l2->eth);
#endif /* CONFIG_WINPCAP */
os_free(l2);
return NULL;
}
return l2;
}
void l2_packet_deinit(struct l2_packet_data *l2)
{
if (l2 == NULL)
return;
#ifdef CONFIG_WINPCAP
eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap);
#else /* CONFIG_WINPCAP */
if (l2->eth)
eth_close(l2->eth);
eloop_unregister_read_sock(pcap_get_selectable_fd(l2->pcap));
#endif /* CONFIG_WINPCAP */
if (l2->pcap)
pcap_close(l2->pcap);
os_free(l2);
}
int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
{
pcap_if_t *devs, *dev;
struct pcap_addr *addr;
struct sockaddr_in *saddr;
int found = 0;
char err[PCAP_ERRBUF_SIZE + 1];
if (pcap_findalldevs(&devs, err) < 0) {
wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err);
return -1;
}
for (dev = devs; dev && !found; dev = dev->next) {
if (os_strcmp(dev->name, l2->ifname) != 0)
continue;
addr = dev->addresses;
while (addr) {
saddr = (struct sockaddr_in *) addr->addr;
if (saddr && saddr->sin_family == AF_INET) {
os_strlcpy(buf, inet_ntoa(saddr->sin_addr),
len);
found = 1;
break;
}
addr = addr->next;
}
}
pcap_freealldevs(devs);
return found ? 0 : -1;
}
void l2_packet_notify_auth_start(struct l2_packet_data *l2)
{
#ifdef CONFIG_WINPCAP
/*
* Use shorter poll interval for 3 seconds to reduce latency during key
* handshake.
*/
l2->num_fast_poll = 3 * 50;
eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap);
eloop_register_timeout(0, 10000, l2_packet_receive_timeout,
l2, l2->pcap);
#endif /* CONFIG_WINPCAP */
}

View File

@ -1,267 +0,0 @@
/*
* WPA Supplicant - Layer2 packet handling with privilege separation
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "includes.h"
#include <sys/un.h>
#include "common.h"
#include "eloop.h"
#include "l2_packet.h"
#include "privsep_commands.h"
struct l2_packet_data {
int fd; /* UNIX domain socket for privsep access */
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len);
void *rx_callback_ctx;
u8 own_addr[ETH_ALEN];
char *own_socket_path;
struct sockaddr_un priv_addr;
};
static int wpa_priv_cmd(struct l2_packet_data *l2, int cmd,
const void *data, size_t data_len)
{
struct msghdr msg;
struct iovec io[2];
io[0].iov_base = &cmd;
io[0].iov_len = sizeof(cmd);
io[1].iov_base = (u8 *) data;
io[1].iov_len = data_len;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
msg.msg_iovlen = data ? 2 : 1;
msg.msg_name = &l2->priv_addr;
msg.msg_namelen = sizeof(l2->priv_addr);
if (sendmsg(l2->fd, &msg, 0) < 0) {
perror("L2: sendmsg(cmd)");
return -1;
}
return 0;
}
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
{
os_memcpy(addr, l2->own_addr, ETH_ALEN);
return 0;
}
int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
const u8 *buf, size_t len)
{
struct msghdr msg;
struct iovec io[4];
int cmd = PRIVSEP_CMD_L2_SEND;
io[0].iov_base = &cmd;
io[0].iov_len = sizeof(cmd);
io[1].iov_base = &dst_addr;
io[1].iov_len = ETH_ALEN;
io[2].iov_base = &proto;
io[2].iov_len = 2;
io[3].iov_base = (u8 *) buf;
io[3].iov_len = len;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
msg.msg_iovlen = 4;
msg.msg_name = &l2->priv_addr;
msg.msg_namelen = sizeof(l2->priv_addr);
if (sendmsg(l2->fd, &msg, 0) < 0) {
perror("L2: sendmsg(packet_send)");
return -1;
}
return 0;
}
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
struct l2_packet_data *l2 = eloop_ctx;
u8 buf[2300];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
os_memset(&from, 0, sizeof(from));
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from,
&fromlen);
if (res < 0) {
perror("l2_packet_receive - recvfrom");
return;
}
if (res < ETH_ALEN) {
wpa_printf(MSG_DEBUG, "L2: Too show packet received");
return;
}
if (from.sun_family != AF_UNIX ||
os_strncmp(from.sun_path, l2->priv_addr.sun_path,
sizeof(from.sun_path)) != 0) {
wpa_printf(MSG_DEBUG, "L2: Received message from unexpected "
"source");
return;
}
l2->rx_callback(l2->rx_callback_ctx, buf, buf + ETH_ALEN,
res - ETH_ALEN);
}
struct l2_packet_data * l2_packet_init(
const char *ifname, const u8 *own_addr, unsigned short protocol,
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len),
void *rx_callback_ctx, int l2_hdr)
{
struct l2_packet_data *l2;
char *own_dir = "/tmp";
char *priv_dir = "/var/run/wpa_priv";
size_t len;
static unsigned int counter = 0;
struct sockaddr_un addr;
fd_set rfds;
struct timeval tv;
int res;
u8 reply[ETH_ALEN + 1];
int reg_cmd[2];
l2 = os_zalloc(sizeof(struct l2_packet_data));
if (l2 == NULL)
return NULL;
l2->rx_callback = rx_callback;
l2->rx_callback_ctx = rx_callback_ctx;
len = os_strlen(own_dir) + 50;
l2->own_socket_path = os_malloc(len);
if (l2->own_socket_path == NULL) {
os_free(l2);
return NULL;
}
os_snprintf(l2->own_socket_path, len, "%s/wpa_privsep-l2-%d-%d",
own_dir, getpid(), counter++);
l2->priv_addr.sun_family = AF_UNIX;
os_snprintf(l2->priv_addr.sun_path, sizeof(l2->priv_addr.sun_path),
"%s/%s", priv_dir, ifname);
l2->fd = socket(PF_UNIX, SOCK_DGRAM, 0);
if (l2->fd < 0) {
perror("socket(PF_UNIX)");
os_free(l2->own_socket_path);
l2->own_socket_path = NULL;
os_free(l2);
return NULL;
}
os_memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
os_strlcpy(addr.sun_path, l2->own_socket_path, sizeof(addr.sun_path));
if (bind(l2->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind(PF_UNIX)");
goto fail;
}
reg_cmd[0] = protocol;
reg_cmd[1] = l2_hdr;
if (wpa_priv_cmd(l2, PRIVSEP_CMD_L2_REGISTER, reg_cmd, sizeof(reg_cmd))
< 0) {
wpa_printf(MSG_ERROR, "L2: Failed to register with wpa_priv");
goto fail;
}
FD_ZERO(&rfds);
FD_SET(l2->fd, &rfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
res = select(l2->fd + 1, &rfds, NULL, NULL, &tv);
if (res < 0 && errno != EINTR) {
perror("select");
goto fail;
}
if (FD_ISSET(l2->fd, &rfds)) {
res = recv(l2->fd, reply, sizeof(reply), 0);
if (res < 0) {
perror("recv");
goto fail;
}
} else {
wpa_printf(MSG_DEBUG, "L2: Timeout while waiting for "
"registration reply");
goto fail;
}
if (res != ETH_ALEN) {
wpa_printf(MSG_DEBUG, "L2: Unexpected registration reply "
"(len=%d)", res);
}
os_memcpy(l2->own_addr, reply, ETH_ALEN);
eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
return l2;
fail:
close(l2->fd);
l2->fd = -1;
unlink(l2->own_socket_path);
os_free(l2->own_socket_path);
l2->own_socket_path = NULL;
os_free(l2);
return NULL;
}
void l2_packet_deinit(struct l2_packet_data *l2)
{
if (l2 == NULL)
return;
if (l2->fd >= 0) {
wpa_priv_cmd(l2, PRIVSEP_CMD_L2_UNREGISTER, NULL, 0);
eloop_unregister_read_sock(l2->fd);
close(l2->fd);
}
if (l2->own_socket_path) {
unlink(l2->own_socket_path);
os_free(l2->own_socket_path);
}
os_free(l2);
}
int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
{
/* TODO */
return -1;
}
void l2_packet_notify_auth_start(struct l2_packet_data *l2)
{
wpa_priv_cmd(l2, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, NULL, 0);
}

View File

@ -1,341 +0,0 @@
/*
* WPA Supplicant - Layer2 packet handling with WinPcap RX thread
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*
* This l2_packet implementation is explicitly for WinPcap and Windows events.
* l2_packet_pcap.c has support for WinPcap, but it requires polling to receive
* frames which means relatively long latency for EAPOL RX processing. The
* implementation here uses a separate thread to allow WinPcap to be receiving
* all the time to reduce latency for EAPOL receiving from about 100 ms to 3 ms
* when comparing l2_packet_pcap.c to l2_packet_winpcap.c. Extra sleep of 50 ms
* is added in to receive thread whenever no EAPOL frames has been received for
* a while. Whenever an EAPOL handshake is expected, this sleep is removed.
*
* The RX thread receives a frame and signals main thread through Windows event
* about the availability of a new frame. Processing the received frame is
* synchronized with pair of Windows events so that no extra buffer or queuing
* mechanism is needed. This implementation requires Windows specific event
* loop implementation, i.e., eloop_win.c.
*
* WinPcap has pcap_getevent() that could, in theory at least, be used to
* implement this kind of waiting with a simpler single-thread design. However,
* that event handle is not really signaled immediately when receiving each
* frame, so it does not really work for this kind of use.
*/
#include "includes.h"
#include <pcap.h>
#include "common.h"
#include "eloop.h"
#include "l2_packet.h"
static const u8 pae_group_addr[ETH_ALEN] =
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
/*
* Number of pcap_dispatch() iterations to do without extra wait after each
* received EAPOL packet or authentication notification. This is used to reduce
* latency for EAPOL receive.
*/
static const size_t no_wait_count = 750;
struct l2_packet_data {
pcap_t *pcap;
unsigned int num_fast_poll;
char ifname[100];
u8 own_addr[ETH_ALEN];
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len);
void *rx_callback_ctx;
int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to
* rx_callback and l2_packet_send() */
int running;
HANDLE rx_avail, rx_done, rx_thread, rx_thread_done, rx_notify;
u8 *rx_buf, *rx_src;
size_t rx_len;
size_t rx_no_wait;
};
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
{
os_memcpy(addr, l2->own_addr, ETH_ALEN);
return 0;
}
int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
const u8 *buf, size_t len)
{
int ret;
struct l2_ethhdr *eth;
if (l2 == NULL)
return -1;
if (l2->l2_hdr) {
ret = pcap_sendpacket(l2->pcap, buf, len);
} else {
size_t mlen = sizeof(*eth) + len;
eth = os_malloc(mlen);
if (eth == NULL)
return -1;
os_memcpy(eth->h_dest, dst_addr, ETH_ALEN);
os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN);
eth->h_proto = htons(proto);
os_memcpy(eth + 1, buf, len);
ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen);
os_free(eth);
}
return ret;
}
/* pcap_dispatch() callback for the RX thread */
static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr,
const u_char *pkt_data)
{
struct l2_packet_data *l2 = (struct l2_packet_data *) user;
struct l2_ethhdr *ethhdr;
if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr))
return;
ethhdr = (struct l2_ethhdr *) pkt_data;
if (l2->l2_hdr) {
l2->rx_buf = (u8 *) ethhdr;
l2->rx_len = hdr->caplen;
} else {
l2->rx_buf = (u8 *) (ethhdr + 1);
l2->rx_len = hdr->caplen - sizeof(*ethhdr);
}
l2->rx_src = ethhdr->h_source;
SetEvent(l2->rx_avail);
WaitForSingleObject(l2->rx_done, INFINITE);
ResetEvent(l2->rx_done);
l2->rx_no_wait = no_wait_count;
}
/* main RX loop that is running in a separate thread */
static DWORD WINAPI l2_packet_receive_thread(LPVOID arg)
{
struct l2_packet_data *l2 = arg;
while (l2->running) {
pcap_dispatch(l2->pcap, 1, l2_packet_receive_cb,
(u_char *) l2);
if (l2->rx_no_wait > 0)
l2->rx_no_wait--;
if (WaitForSingleObject(l2->rx_notify,
l2->rx_no_wait ? 0 : 50) ==
WAIT_OBJECT_0) {
l2->rx_no_wait = no_wait_count;
ResetEvent(l2->rx_notify);
}
}
SetEvent(l2->rx_thread_done);
ExitThread(0);
return 0;
}
/* main thread RX event handler */
static void l2_packet_rx_event(void *eloop_data, void *user_data)
{
struct l2_packet_data *l2 = eloop_data;
l2->rx_callback(l2->rx_callback_ctx, l2->rx_src, l2->rx_buf,
l2->rx_len);
ResetEvent(l2->rx_avail);
SetEvent(l2->rx_done);
}
static int l2_packet_init_libpcap(struct l2_packet_data *l2,
unsigned short protocol)
{
bpf_u_int32 pcap_maskp, pcap_netp;
char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE];
struct bpf_program pcap_fp;
pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 1, pcap_err);
if (l2->pcap == NULL) {
fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
fprintf(stderr, "ifname='%s'\n", l2->ifname);
return -1;
}
os_snprintf(pcap_filter, sizeof(pcap_filter),
"not ether src " MACSTR " and "
"( ether dst " MACSTR " or ether dst " MACSTR " ) and "
"ether proto 0x%x",
MAC2STR(l2->own_addr), /* do not receive own packets */
MAC2STR(l2->own_addr), MAC2STR(pae_group_addr),
protocol);
if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
return -1;
}
if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap));
return -1;
}
pcap_freecode(&pcap_fp);
return 0;
}
struct l2_packet_data * l2_packet_init(
const char *ifname, const u8 *own_addr, unsigned short protocol,
void (*rx_callback)(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len),
void *rx_callback_ctx, int l2_hdr)
{
struct l2_packet_data *l2;
DWORD thread_id;
l2 = os_zalloc(sizeof(struct l2_packet_data));
if (l2 == NULL)
return NULL;
if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0)
os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname));
else
os_snprintf(l2->ifname, sizeof(l2->ifname), "\\Device\\NPF_%s",
ifname);
l2->rx_callback = rx_callback;
l2->rx_callback_ctx = rx_callback_ctx;
l2->l2_hdr = l2_hdr;
if (own_addr)
os_memcpy(l2->own_addr, own_addr, ETH_ALEN);
if (l2_packet_init_libpcap(l2, protocol)) {
os_free(l2);
return NULL;
}
l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL);
l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL);
l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL);
if (l2->rx_avail == NULL || l2->rx_done == NULL ||
l2->rx_notify == NULL) {
CloseHandle(l2->rx_avail);
CloseHandle(l2->rx_done);
CloseHandle(l2->rx_notify);
pcap_close(l2->pcap);
os_free(l2);
return NULL;
}
eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail),
l2_packet_rx_event, l2, NULL);
l2->running = 1;
l2->rx_thread = CreateThread(NULL, 0, l2_packet_receive_thread, l2, 0,
&thread_id);
return l2;
}
static void l2_packet_deinit_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct l2_packet_data *l2 = eloop_ctx;
if (l2->rx_thread_done &&
WaitForSingleObject(l2->rx_thread_done, 2000) != WAIT_OBJECT_0) {
wpa_printf(MSG_DEBUG, "l2_packet_winpcap: RX thread did not "
"exit - kill it\n");
TerminateThread(l2->rx_thread, 0);
}
CloseHandle(l2->rx_thread_done);
CloseHandle(l2->rx_thread);
if (l2->pcap)
pcap_close(l2->pcap);
eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail));
CloseHandle(l2->rx_avail);
CloseHandle(l2->rx_done);
CloseHandle(l2->rx_notify);
os_free(l2);
}
void l2_packet_deinit(struct l2_packet_data *l2)
{
if (l2 == NULL)
return;
l2->rx_thread_done = CreateEvent(NULL, TRUE, FALSE, NULL);
l2->running = 0;
pcap_breakloop(l2->pcap);
/*
* RX thread may be waiting in l2_packet_receive_cb() for l2->rx_done
* event and this event is set in l2_packet_rx_event(). However,
* l2_packet_deinit() may end up being called from l2->rx_callback(),
* so we need to return from here and complete deinitialization in
* a registered timeout to avoid having to forcefully kill the RX
* thread.
*/
eloop_register_timeout(0, 0, l2_packet_deinit_timeout, l2, NULL);
}
int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
{
pcap_if_t *devs, *dev;
struct pcap_addr *addr;
struct sockaddr_in *saddr;
int found = 0;
char err[PCAP_ERRBUF_SIZE + 1];
if (pcap_findalldevs(&devs, err) < 0) {
wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err);
return -1;
}
for (dev = devs; dev && !found; dev = dev->next) {
if (os_strcmp(dev->name, l2->ifname) != 0)
continue;
addr = dev->addresses;
while (addr) {
saddr = (struct sockaddr_in *) addr->addr;
if (saddr && saddr->sin_family == AF_INET) {
os_strlcpy(buf, inet_ntoa(saddr->sin_addr),
len);
found = 1;
break;
}
addr = addr->next;
}
}
pcap_freealldevs(devs);
return found ? 0 : -1;
}
void l2_packet_notify_auth_start(struct l2_packet_data *l2)
{
if (l2)
SetEvent(l2->rx_notify);
}