Merge wpa_supplicant and hostapd driver wrapper implementations

This commit merges the driver_ops structures and implementations from
hostapd/driver*.[ch] into src/drivers. This is only an initial step and
there is room for number of cleanups to share code between the hostapd
and wpa_supplicant parts of the wrappers to avoid unnecessary source
code duplication.
This commit is contained in:
Jouni Malinen 2009-04-09 13:40:12 +03:00 committed by Jouni Malinen
parent c2220ec0b7
commit c51218372f
44 changed files with 9544 additions and 9899 deletions

View file

@ -41,11 +41,15 @@ endif
OBJS = hostapd.o main.o ieee802_1x.o eapol_sm.o \ OBJS = hostapd.o main.o ieee802_1x.o eapol_sm.o \
config.o ieee802_11_auth.o \ config.o ieee802_11_auth.o \
sta_info.o wpa.o \ sta_info.o wpa.o \
drivers.o preauth.o pmksa_cache.o \ preauth.o pmksa_cache.o \
drv_callbacks.o \ drv_callbacks.o \
tkip_countermeasures.o \ tkip_countermeasures.o \
mlme.o wpa_auth_ie.o mlme.o wpa_auth_ie.o
OBJS += ../src/drivers/drivers.o
OBJS += ../src/drivers/scan_helpers.o
CFLAGS += -DHOSTAPD
OBJS += ../src/utils/eloop.o OBJS += ../src/utils/eloop.o
OBJS += ../src/utils/common.o OBJS += ../src/utils/common.o
OBJS += ../src/utils/wpa_debug.o OBJS += ../src/utils/wpa_debug.o
@ -127,35 +131,35 @@ endif
ifdef CONFIG_DRIVER_HOSTAP ifdef CONFIG_DRIVER_HOSTAP
NEED_MLME=y NEED_MLME=y
CFLAGS += -DCONFIG_DRIVER_HOSTAP CFLAGS += -DCONFIG_DRIVER_HOSTAP
OBJS += driver_hostap.o OBJS += ../src/drivers/driver_hostap.o
endif endif
ifdef CONFIG_DRIVER_WIRED ifdef CONFIG_DRIVER_WIRED
CFLAGS += -DCONFIG_DRIVER_WIRED CFLAGS += -DCONFIG_DRIVER_WIRED
OBJS += driver_wired.o OBJS += ../src/drivers/driver_wired.o
endif endif
ifdef CONFIG_DRIVER_MADWIFI ifdef CONFIG_DRIVER_MADWIFI
CFLAGS += -DCONFIG_DRIVER_MADWIFI CFLAGS += -DCONFIG_DRIVER_MADWIFI
OBJS += driver_madwifi.o OBJS += ../src/drivers/driver_madwifi.o
CONFIG_L2_PACKET=y CONFIG_L2_PACKET=y
endif endif
ifdef CONFIG_DRIVER_ATHEROS ifdef CONFIG_DRIVER_ATHEROS
CFLAGS += -DCONFIG_DRIVER_ATHEROS CFLAGS += -DCONFIG_DRIVER_ATHEROS
OBJS += driver_atheros.o OBJS += ../src/drivers/driver_atheros.o
CONFIG_L2_PACKET=y CONFIG_L2_PACKET=y
endif endif
ifdef CONFIG_DRIVER_PRISM54 ifdef CONFIG_DRIVER_PRISM54
CFLAGS += -DCONFIG_DRIVER_PRISM54 CFLAGS += -DCONFIG_DRIVER_PRISM54
OBJS += driver_prism54.o OBJS += ../src/drivers/driver_prism54.o
endif endif
ifdef CONFIG_DRIVER_NL80211 ifdef CONFIG_DRIVER_NL80211
NEED_MLME=y NEED_MLME=y
CFLAGS += -DCONFIG_DRIVER_NL80211 CFLAGS += -DCONFIG_DRIVER_NL80211
OBJS += driver_nl80211.o OBJS += ../src/drivers/driver_nl80211.o
OBJS += ../src/utils/radiotap.o OBJS += ../src/utils/radiotap.o
LIBS += -lnl LIBS += -lnl
ifdef CONFIG_LIBNL20 ifdef CONFIG_LIBNL20
@ -166,7 +170,7 @@ endif
ifdef CONFIG_DRIVER_BSD ifdef CONFIG_DRIVER_BSD
CFLAGS += -DCONFIG_DRIVER_BSD CFLAGS += -DCONFIG_DRIVER_BSD
OBJS += driver_bsd.o OBJS += ../src/drivers/driver_bsd.o
CONFIG_L2_PACKET=y CONFIG_L2_PACKET=y
CONFIG_DNET_PCAP=y CONFIG_DNET_PCAP=y
CONFIG_L2_FREEBSD=y CONFIG_L2_FREEBSD=y
@ -175,12 +179,12 @@ endif
ifdef CONFIG_DRIVER_TEST ifdef CONFIG_DRIVER_TEST
NEED_MLME=y NEED_MLME=y
CFLAGS += -DCONFIG_DRIVER_TEST CFLAGS += -DCONFIG_DRIVER_TEST
OBJS += driver_test.o OBJS += ../src/drivers/driver_test.o
endif endif
ifdef CONFIG_DRIVER_NONE ifdef CONFIG_DRIVER_NONE
CFLAGS += -DCONFIG_DRIVER_NONE CFLAGS += -DCONFIG_DRIVER_NONE
OBJS += driver_none.o OBJS += ../src/drivers/driver_none.o
endif endif
ifdef CONFIG_L2_PACKET ifdef CONFIG_L2_PACKET

View file

@ -25,7 +25,7 @@
#include "ap_list.h" #include "ap_list.h"
#include "hw_features.h" #include "hw_features.h"
#include "beacon.h" #include "beacon.h"
#include "driver.h" #include "drivers/driver.h"
struct ieee80211_frame_info { struct ieee80211_frame_info {

View file

@ -19,7 +19,7 @@
#endif /* CONFIG_NATIVE_WINDOWS */ #endif /* CONFIG_NATIVE_WINDOWS */
#include "hostapd.h" #include "hostapd.h"
#include "driver.h" #include "drivers/driver.h"
#include "sha1.h" #include "sha1.h"
#include "eap_server/eap.h" #include "eap_server/eap.h"
#include "radius/radius_client.h" #include "radius/radius_client.h"
@ -33,7 +33,7 @@
#define MAX_STA_COUNT 2007 #define MAX_STA_COUNT 2007
extern struct hapd_driver_ops *hostapd_drivers[]; extern struct wpa_driver_ops *wpa_drivers[];
#ifndef CONFIG_NO_VLAN #ifndef CONFIG_NO_VLAN
@ -226,7 +226,7 @@ struct hostapd_config * hostapd_config_defaults(void)
} }
/* set default driver based on configuration */ /* set default driver based on configuration */
conf->driver = hostapd_drivers[0]; conf->driver = wpa_drivers[0];
if (conf->driver == NULL) { if (conf->driver == NULL) {
wpa_printf(MSG_ERROR, "No driver wrappers registered!"); wpa_printf(MSG_ERROR, "No driver wrappers registered!");
os_free(conf); os_free(conf);
@ -1461,10 +1461,10 @@ struct hostapd_config * hostapd_config_read(const char *fname)
int j; int j;
/* clear to get error below if setting is invalid */ /* clear to get error below if setting is invalid */
conf->driver = NULL; conf->driver = NULL;
for (j = 0; hostapd_drivers[j]; j++) { for (j = 0; wpa_drivers[j]; j++) {
if (os_strcmp(pos, hostapd_drivers[j]->name) == if (os_strcmp(pos, wpa_drivers[j]->name) == 0)
0) { {
conf->driver = hostapd_drivers[j]; conf->driver = wpa_drivers[j];
break; break;
} }
} }

View file

@ -339,7 +339,7 @@ struct hostapd_config {
int *supported_rates; int *supported_rates;
int *basic_rates; int *basic_rates;
const struct hapd_driver_ops *driver; const struct wpa_driver_ops *driver;
int passive_scan_interval; /* seconds, 0 = disabled */ int passive_scan_interval; /* seconds, 0 = disabled */
int passive_scan_listen; /* usec */ int passive_scan_listen; /* usec */

View file

@ -31,7 +31,7 @@
#include "sta_info.h" #include "sta_info.h"
#include "accounting.h" #include "accounting.h"
#include "wps_hostapd.h" #include "wps_hostapd.h"
#include "driver.h" #include "drivers/driver.h"
struct wpa_ctrl_dst { struct wpa_ctrl_dst {
@ -231,6 +231,7 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211W #ifdef CONFIG_IEEE80211W
#ifdef NEED_MLME
static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
const char *txtaddr) const char *txtaddr)
{ {
@ -247,6 +248,7 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
return 0; return 0;
} }
#endif /* NEED_MLME */
#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211W */
@ -370,9 +372,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
reply_len = -1; reply_len = -1;
#ifdef CONFIG_IEEE80211W #ifdef CONFIG_IEEE80211W
#ifdef NEED_MLME
} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
reply_len = -1; reply_len = -1;
#endif /* NEED_MLME */
#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS #ifdef CONFIG_WPS
} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {

View file

@ -1,243 +0,0 @@
/*
* hostapd - driver interface definition
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007-2008, Intel 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.
*/
#ifndef HOSTAPD_DRIVER_H
#define HOSTAPD_DRIVER_H
#include "defs.h"
#include "sta_flags.h"
struct hostapd_data;
struct hostap_sta_driver_data {
unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes;
unsigned long current_tx_rate;
unsigned long inactive_msec;
unsigned long flags;
unsigned long num_ps_buf_frames;
unsigned long tx_retry_failed;
unsigned long tx_retry_count;
int last_rssi;
int last_ack_rssi;
};
struct hostapd_sta_add_params {
const u8 *addr;
u16 aid;
u16 capability;
const u8 *supp_rates;
size_t supp_rates_len;
int flags;
u16 listen_interval;
const struct ht_cap_ie *ht_capabilities;
};
struct hostapd_freq_params {
int mode;
int freq;
int channel;
int ht_enabled;
int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
* secondary channel below primary, 1 = HT40
* enabled, secondary channel above primary */
};
enum hostapd_driver_if_type {
HOSTAPD_IF_VLAN, HOSTAPD_IF_WDS
};
struct hostapd_neighbor_bss {
u8 bssid[ETH_ALEN];
int freq; /* MHz */
unsigned int ht:1;
int pri_chan;
int sec_chan; /* 0 for 20 MHz channels */
};
struct hapd_driver_ops {
const char *name; /* as appears in the config file */
void * (*init)(struct hostapd_data *hapd);
void * (*init_bssid)(struct hostapd_data *hapd, const u8 *bssid);
void (*deinit)(void *priv);
/**
* set_8021x - enable/disable IEEE 802.1X support
* @ifname: Interface name (for multi-SSID/VLAN support)
* @priv: driver private data
* @enabled: 1 = enable, 0 = disable
*
* Returns: 0 on success, -1 on failure
*
* Configure the kernel driver to enable/disable 802.1X support.
* This may be an empty function if 802.1X support is always enabled.
*/
int (*set_ieee8021x)(const char *ifname, void *priv, int enabled);
/**
* set_privacy - enable/disable privacy
* @priv: driver private data
* @enabled: 1 = privacy enabled, 0 = disabled
*
* Return: 0 on success, -1 on failure
*
* Configure privacy.
*/
int (*set_privacy)(const char *ifname, void *priv, int enabled);
int (*set_key)(const char *ifname, 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 (*get_seqnum)(const char *ifname, void *priv, const u8 *addr,
int idx, u8 *seq);
int (*get_seqnum_igtk)(const char *ifname, void *priv, const u8 *addr,
int idx, u8 *seq);
int (*flush)(void *priv);
int (*set_generic_elem)(const char *ifname, void *priv, const u8 *elem,
size_t elem_len);
int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data,
const u8 *addr);
int (*send_eapol)(void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt, const u8 *own_addr);
int (*sta_deauth)(void *priv, const u8 *addr, int reason);
int (*sta_disassoc)(void *priv, const u8 *addr, int reason);
int (*sta_remove)(void *priv, const u8 *addr);
int (*get_ssid)(const char *ifname, void *priv, u8 *buf, int len);
int (*set_ssid)(const char *ifname, void *priv, const u8 *buf,
int len);
int (*set_countermeasures)(void *priv, int enabled);
int (*send_mgmt_frame)(void *priv, const void *msg, size_t len,
int flags);
int (*sta_add)(const char *ifname, void *priv,
struct hostapd_sta_add_params *params);
int (*get_inact_sec)(void *priv, const u8 *addr);
int (*sta_clear_stats)(void *priv, const u8 *addr);
int (*set_freq)(void *priv, struct hostapd_freq_params *freq);
int (*set_rts)(void *priv, int rts);
int (*set_frag)(void *priv, int frag);
int (*set_retry)(void *priv, int short_retry, int long_retry);
int (*sta_set_flags)(void *priv, const u8 *addr,
int total_flags, int flags_or, int flags_and);
int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates,
int mode);
int (*set_country)(void *priv, const char *country);
int (*set_ieee80211d)(void *priv, int enabled);
int (*set_beacon)(const char *ifname, void *priv,
const u8 *head, size_t head_len,
const u8 *tail, size_t tail_len, int dtim_period);
/* Configure internal bridge:
* 0 = disabled, i.e., client separation is enabled (no bridging of
* packets between associated STAs
* 1 = enabled, i.e., bridge packets between associated STAs (default)
*/
int (*set_internal_bridge)(void *priv, int value);
int (*set_beacon_int)(void *priv, int value);
/* Configure broadcast SSID mode:
* 0 = include SSID in Beacon frames and reply to Probe Request frames
* that use broadcast SSID
* 1 = hide SSID from Beacon frames and ignore Probe Request frames for
* broadcast SSID
*/
int (*set_broadcast_ssid)(void *priv, int value);
int (*set_cts_protect)(void *priv, int value);
int (*set_preamble)(void *priv, int value);
int (*set_short_slot_time)(void *priv, int value);
int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min,
int cw_max, int burst_time);
int (*bss_add)(void *priv, const char *ifname, const u8 *bssid);
int (*bss_remove)(void *priv, const char *ifname);
int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask);
int (*passive_scan)(void *priv, int now, int our_mode_only,
int interval, int _listen, int *channel,
int *last_rx);
struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
u16 *num_modes,
u16 *flags);
int (*if_add)(const char *iface, void *priv,
enum hostapd_driver_if_type type, char *ifname,
const u8 *addr);
int (*if_update)(void *priv, enum hostapd_driver_if_type type,
char *ifname, const u8 *addr);
int (*if_remove)(void *priv, enum hostapd_driver_if_type type,
const char *ifname, const u8 *addr);
int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname,
int vlan_id);
/**
* commit - Optional commit changes handler
* @priv: driver private data
* Returns: 0 on success, -1 on failure
*
* This optional handler function can be registered if the driver
* interface implementation needs to commit changes (e.g., by setting
* network interface up) at the end of initial configuration. If set,
* this handler will be called after initial setup has been completed.
*/
int (*commit)(void *priv);
int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto,
const u8 *data, size_t data_len);
int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted,
u32 session_timeout);
int (*set_radius_acl_expire)(void *priv, const u8 *mac);
int (*set_ht_params)(const char *ifname, void *priv,
const u8 *ht_capab, size_t ht_capab_len,
const u8 *ht_oper, size_t ht_oper_len);
int (*set_wps_beacon_ie)(const char *ifname, void *priv,
const u8 *ie, size_t len);
int (*set_wps_probe_resp_ie)(const char *ifname, void *priv,
const u8 *ie, size_t len);
const struct hostapd_neighbor_bss *
(*get_neighbor_bss)(void *priv, size_t *num);
};
struct sta_info;
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, const u8 *addr);
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa,
const u8 *buf, size_t len);
struct hostapd_frame_info {
u32 phytype;
u32 channel;
u32 datarate;
u32 ssi_signal;
unsigned int passive_scan:1;
};
void hostapd_mgmt_rx(struct hostapd_data *hapd, u8 *buf, size_t len,
u16 stype, struct hostapd_frame_info *fi);
void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
u16 stype, int ok);
void hostapd_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr);
struct hostapd_data * hostapd_sta_get_bss(struct hostapd_data *hapd,
const u8 *addr);
#endif /* HOSTAPD_DRIVER_H */

View file

@ -1,768 +0,0 @@
/*
* hostapd / Driver interaction with BSD net80211 layer
* Copyright (c) 2004, Sam Leffler <sam@errno.com>
* Copyright (c) 2004, 2Wire, Inc
*
* 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 <net/if.h>
#include <net80211/ieee80211.h>
#include <net80211/ieee80211_crypto.h>
#include <net80211/ieee80211_ioctl.h>
/*
* Avoid conflicts with hostapd definitions by undefining couple of defines
* from net80211 header files.
*/
#undef RSN_VERSION
#undef WPA_VERSION
#undef WPA_OUI_TYPE
#include "hostapd.h"
#include "config.h"
#include "driver.h"
#include "eloop.h"
#include "l2_packet/l2_packet.h"
#include "eapol_sm.h"
#include "common.h"
struct bsd_driver_data {
struct hostapd_data *hapd; /* back pointer */
char iface[IFNAMSIZ + 1];
struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
int ioctl_sock; /* socket for ioctl() use */
int wext_sock; /* socket for wireless events */
};
static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code);
static int
set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
{
struct ieee80211req ireq;
memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
ireq.i_type = op;
ireq.i_len = arg_len;
ireq.i_data = (void *) arg;
if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
perror("ioctl[SIOCS80211]");
return -1;
}
return 0;
}
static int
get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
{
struct ieee80211req ireq;
memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
ireq.i_type = op;
ireq.i_len = arg_len;
ireq.i_data = arg;
if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) {
perror("ioctl[SIOCG80211]");
return -1;
}
return ireq.i_len;
}
static int
set80211param(struct bsd_driver_data *drv, int op, int arg)
{
struct ieee80211req ireq;
memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
ireq.i_type = op;
ireq.i_val = arg;
if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
perror("ioctl[SIOCS80211]");
return -1;
}
return 0;
}
static const char *
ether_sprintf(const u8 *addr)
{
static char buf[sizeof(MACSTR)];
if (addr != NULL)
snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
else
snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
return buf;
}
/*
* Configure WPA parameters.
*/
static int
bsd_configure_wpa(struct bsd_driver_data *drv)
{
static const char *ciphernames[] =
{ "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
struct hostapd_data *hapd = drv->hapd;
struct hostapd_bss_config *conf = hapd->conf;
int v;
switch (conf->wpa_group) {
case WPA_CIPHER_CCMP:
v = IEEE80211_CIPHER_AES_CCM;
break;
case WPA_CIPHER_TKIP:
v = IEEE80211_CIPHER_TKIP;
break;
case WPA_CIPHER_WEP104:
v = IEEE80211_CIPHER_WEP;
break;
case WPA_CIPHER_WEP40:
v = IEEE80211_CIPHER_WEP;
break;
case WPA_CIPHER_NONE:
v = IEEE80211_CIPHER_NONE;
break;
default:
printf("Unknown group key cipher %u\n",
conf->wpa_group);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
__func__, ciphernames[v], v);
if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) {
printf("Unable to set group key cipher to %u (%s)\n",
v, ciphernames[v]);
return -1;
}
if (v == IEEE80211_CIPHER_WEP) {
/* key length is done only for specific ciphers */
v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) {
printf("Unable to set group key length to %u\n", v);
return -1;
}
}
v = 0;
if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
v |= 1<<IEEE80211_CIPHER_AES_CCM;
if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
v |= 1<<IEEE80211_CIPHER_TKIP;
if (conf->wpa_pairwise & WPA_CIPHER_NONE)
v |= 1<<IEEE80211_CIPHER_NONE;
wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
if (set80211param(drv, IEEE80211_IOC_UCASTCIPHERS, v)) {
printf("Unable to set pairwise key ciphers to 0x%x\n", v);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
__func__, conf->wpa_key_mgmt);
if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) {
printf("Unable to set key management algorithms to 0x%x\n",
conf->wpa_key_mgmt);
return -1;
}
v = 0;
if (conf->rsn_preauth)
v |= BIT(0);
wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
__func__, conf->rsn_preauth);
if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) {
printf("Unable to set RSN capabilities to 0x%x\n", v);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa);
if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) {
printf("Unable to set WPA to %u\n", conf->wpa);
return -1;
}
return 0;
}
static int
bsd_set_iface_flags(void *priv, int dev_up)
{
struct bsd_driver_data *drv = priv;
struct ifreq ifr;
wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
if (drv->ioctl_sock < 0)
return -1;
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
perror("ioctl[SIOCGIFFLAGS]");
return -1;
}
if (dev_up)
ifr.ifr_flags |= IFF_UP;
else
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
perror("ioctl[SIOCSIFFLAGS]");
return -1;
}
if (dev_up) {
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
ifr.ifr_mtu = HOSTAPD_MTU;
if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
perror("ioctl[SIOCSIFMTU]");
printf("Setting MTU failed - trying to survive with "
"current value\n");
}
}
return 0;
}
static int
bsd_set_ieee8021x(const char *ifname, void *priv, int enabled)
{
struct bsd_driver_data *drv = priv;
struct hostapd_data *hapd = drv->hapd;
struct hostapd_bss_config *conf = hapd->conf;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
if (!enabled) {
/* XXX restore state */
return set80211param(priv, IEEE80211_IOC_AUTHMODE,
IEEE80211_AUTH_AUTO);
}
if (!conf->wpa && !conf->ieee802_1x) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
return -1;
}
if (conf->wpa && bsd_configure_wpa(drv) != 0) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
return -1;
}
if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
(conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
return -1;
}
return bsd_set_iface_flags(priv, 1);
}
static int
bsd_set_privacy(const char *ifname, void *priv, int enabled)
{
struct bsd_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);
}
static int
bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d",
__func__, ether_sprintf(addr), authorized);
if (authorized)
mlme.im_op = IEEE80211_MLME_AUTHORIZE;
else
mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
mlme.im_reason = 0;
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or,
int flags_and)
{
/* For now, only support setting Authorized flag */
if (flags_or & WLAN_STA_AUTHORIZED)
return bsd_set_sta_authorized(priv, addr, 1);
if (!(flags_and & WLAN_STA_AUTHORIZED))
return bsd_set_sta_authorized(priv, addr, 0);
return 0;
}
static int
bsd_del_key(void *priv, const u8 *addr, int key_idx)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_del_key wk;
wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d",
__func__, ether_sprintf(addr), key_idx);
memset(&wk, 0, sizeof(wk));
if (addr != NULL) {
memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */
} else {
wk.idk_keyix = key_idx;
}
return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
}
static int
bsd_set_key(const char *ifname, 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 bsd_driver_data *drv = priv;
struct ieee80211req_key wk;
u_int8_t cipher;
if (alg == WPA_ALG_NONE)
return bsd_del_key(drv, addr, key_idx);
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d",
__func__, alg, ether_sprintf(addr), key_idx);
if (alg == WPA_ALG_WEP)
cipher = IEEE80211_CIPHER_WEP;
else if (alg == WPA_ALG_TKIP)
cipher = IEEE80211_CIPHER_TKIP;
else if (alg == WPA_ALG_CCMP)
cipher = IEEE80211_CIPHER_AES_CCM;
else {
printf("%s: unknown/unsupported algorithm %d\n",
__func__, alg);
return -1;
}
if (key_len > sizeof(wk.ik_keydata)) {
printf("%s: key length %d too big\n", __func__, key_len);
return -3;
}
memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
if (addr == NULL) {
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
} else {
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = IEEE80211_KEYIX_NONE;
}
wk.ik_keylen = key_len;
memcpy(wk.ik_keydata, key, key_len);
return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
}
static int
bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
u8 *seq)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_key wk;
wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
__func__, ether_sprintf(addr), idx);
memset(&wk, 0, sizeof(wk));
if (addr == NULL)
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
else
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = idx;
if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
printf("Failed to get encryption.\n");
return -1;
}
#ifdef WORDS_BIGENDIAN
{
/*
* wk.ik_keytsc is in host byte order (big endian), need to
* swap it to match with the byte order used in WPA.
*/
int i;
u8 tmp[WPA_KEY_RSC_LEN];
memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
}
}
#else /* WORDS_BIGENDIAN */
memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
#endif /* WORDS_BIGENDIAN */
return 0;
}
static int
bsd_flush(void *priv)
{
u8 allsta[IEEE80211_ADDR_LEN];
memset(allsta, 0xff, IEEE80211_ADDR_LEN);
return bsd_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE);
}
static int
bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
const u8 *addr)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_sta_stats stats;
memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) {
/* XXX? do packets counts include non-data frames? */
data->rx_packets = stats.is_stats.ns_rx_data;
data->rx_bytes = stats.is_stats.ns_rx_bytes;
data->tx_packets = stats.is_stats.ns_tx_data;
data->tx_bytes = stats.is_stats.ns_tx_bytes;
}
return 0;
}
static int
bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
{
/*
* Do nothing; we setup parameters at startup that define the
* contents of the beacon information element.
*/
return 0;
}
static int
bsd_sta_deauth(void *priv, const u8 *addr, int reason_code)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
__func__, ether_sprintf(addr), reason_code);
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = reason_code;
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
__func__, ether_sprintf(addr), reason_code);
mlme.im_op = IEEE80211_MLME_DISASSOC;
mlme.im_reason = reason_code;
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
struct hostapd_data *hapd = drv->hapd;
struct ieee80211req_wpaie ie;
int ielen = 0;
u8 *iebuf = NULL;
/*
* Fetch and validate any negotiated WPA/RSN parameters.
*/
memset(&ie, 0, sizeof(ie));
memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
printf("Failed to get WPA/RSN information element.\n");
goto no_ie;
}
iebuf = ie.wpa_ie;
ielen = ie.wpa_ie[1];
if (ielen == 0)
iebuf = NULL;
else
ielen += 2;
no_ie:
return hostapd_notif_assoc(hapd, addr, iebuf, ielen);
}
#include <net/route.h>
#include <net80211/ieee80211_freebsd.h>
static void
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = ctx;
struct hostapd_data *hapd = drv->hapd;
char buf[2048];
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
struct ieee80211_join_event *join;
struct ieee80211_leave_event *leave;
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;
}
ifan = (struct if_announcemsghdr *) rtm;
switch (rtm->rtm_type) {
case RTM_IEEE80211:
switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC:
case RTM_IEEE80211_DISASSOC:
case RTM_IEEE80211_SCAN:
break;
case RTM_IEEE80211_LEAVE:
leave = (struct ieee80211_leave_event *) &ifan[1];
hostapd_notif_disassoc(drv->hapd, leave->iev_addr);
break;
case RTM_IEEE80211_JOIN:
#ifdef RTM_IEEE80211_REJOIN
case RTM_IEEE80211_REJOIN:
#endif
join = (struct ieee80211_join_event *) &ifan[1];
bsd_new_sta(drv, join->iev_addr);
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));
hostapd_michael_mic_failure(hapd, mic->iev_src);
break;
}
break;
}
}
static int
bsd_wireless_event_init(struct bsd_driver_data *drv)
{
int s;
drv->wext_sock = -1;
s = socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0) {
perror("socket(PF_ROUTE,SOCK_RAW)");
return -1;
}
eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL);
drv->wext_sock = s;
return 0;
}
static void
bsd_wireless_event_deinit(struct bsd_driver_data *drv)
{
if (drv->wext_sock < 0)
return;
eloop_unregister_read_sock(drv->wext_sock);
close(drv->wext_sock);
}
static int
bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
{
struct bsd_driver_data *drv = priv;
unsigned char buf[3000];
unsigned char *bp = buf;
struct l2_ethhdr *eth;
size_t len;
int status;
/*
* Prepend the Etherent header. If the caller left us
* space at the front we could just insert it but since
* we don't know we copy to a local buffer. Given the frequency
* and size of frames this probably doesn't matter.
*/
len = data_len + sizeof(struct l2_ethhdr);
if (len > sizeof(buf)) {
bp = malloc(len);
if (bp == NULL) {
printf("EAPOL frame discarded, cannot malloc temp "
"buffer of size %u!\n", len);
return -1;
}
}
eth = (struct l2_ethhdr *) bp;
memcpy(eth->h_dest, addr, ETH_ALEN);
memcpy(eth->h_source, own_addr, ETH_ALEN);
eth->h_proto = htons(ETH_P_EAPOL);
memcpy(eth+1, data, data_len);
wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
if (bp != buf)
free(bp);
return status;
}
static void
handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
{
struct bsd_driver_data *drv = ctx;
hostapd_eapol_receive(drv->hapd, src_addr,
buf + sizeof(struct l2_ethhdr),
len - sizeof(struct l2_ethhdr));
}
static int
bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
{
struct bsd_driver_data *drv = priv;
int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len);
wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);
return ssid_len;
}
static int
bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
{
struct bsd_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf);
return set80211var(drv, IEEE80211_IOC_SSID, buf, len);
}
static void *
bsd_init(struct hostapd_data *hapd)
{
struct bsd_driver_data *drv;
drv = os_zalloc(sizeof(struct bsd_driver_data));
if (drv == NULL) {
printf("Could not allocate memory for bsd driver data\n");
goto bad;
}
drv->hapd = hapd;
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->ioctl_sock < 0) {
perror("socket[PF_INET,SOCK_DGRAM]");
goto bad;
}
memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
handle_read, drv, 1);
if (drv->sock_xmit == NULL)
goto bad;
if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr))
goto bad;
bsd_set_iface_flags(drv, 0); /* mark down during setup */
if (bsd_wireless_event_init(drv))
goto bad;
return drv;
bad:
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
if (drv != NULL)
free(drv);
return NULL;
}
static void
bsd_deinit(void *priv)
{
struct bsd_driver_data *drv = priv;
bsd_wireless_event_deinit(drv);
(void) bsd_set_iface_flags(drv, 0);
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
free(drv);
}
const struct hapd_driver_ops wpa_driver_bsd_ops = {
.name = "bsd",
.init = bsd_init,
.deinit = bsd_deinit,
.set_ieee8021x = bsd_set_ieee8021x,
.set_privacy = bsd_set_privacy,
.set_key = bsd_set_key,
.get_seqnum = bsd_get_seqnum,
.flush = bsd_flush,
.set_generic_elem = bsd_set_opt_ie,
.sta_set_flags = bsd_sta_set_flags,
.read_sta_data = bsd_read_sta_driver_data,
.send_eapol = bsd_send_eapol,
.sta_disassoc = bsd_sta_disassoc,
.sta_deauth = bsd_sta_deauth,
.set_ssid = bsd_set_ssid,
.get_ssid = bsd_get_ssid,
};

File diff suppressed because it is too large Load diff

View file

@ -16,15 +16,15 @@
#ifndef DRIVER_I_H #ifndef DRIVER_I_H
#define DRIVER_I_H #define DRIVER_I_H
#include "driver.h" #include "drivers/driver.h"
#include "config.h" #include "config.h"
static inline void * static inline void *
hostapd_driver_init(struct hostapd_data *hapd) hostapd_driver_init(struct hostapd_data *hapd)
{ {
if (hapd->driver == NULL || hapd->driver->init == NULL) if (hapd->driver == NULL || hapd->driver->hapd_init == NULL)
return NULL; return NULL;
return hapd->driver->init(hapd); return hapd->driver->hapd_init(hapd);
} }
static inline void * static inline void *
@ -38,9 +38,9 @@ hostapd_driver_init_bssid(struct hostapd_data *hapd, const u8 *bssid)
static inline void static inline void
hostapd_driver_deinit(struct hostapd_data *hapd) hostapd_driver_deinit(struct hostapd_data *hapd)
{ {
if (hapd->driver == NULL || hapd->driver->deinit == NULL) if (hapd->driver == NULL || hapd->driver->hapd_deinit == NULL)
return; return;
hapd->driver->deinit(hapd->drv_priv); hapd->driver->hapd_deinit(hapd->drv_priv);
} }
static inline int static inline int
@ -67,9 +67,9 @@ hostapd_set_key(const char *ifname, struct hostapd_data *hapd,
int set_tx, const u8 *seq, size_t seq_len, int set_tx, const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len) const u8 *key, size_t key_len)
{ {
if (hapd->driver == NULL || hapd->driver->set_key == NULL) if (hapd->driver == NULL || hapd->driver->hapd_set_key == NULL)
return 0; return 0;
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, return hapd->driver->hapd_set_key(ifname, hapd->drv_priv, alg, addr,
key_idx, set_tx, seq, seq_len, key, key_idx, set_tx, seq, seq_len, key,
key_len); key_len);
} }
@ -125,10 +125,11 @@ static inline int
hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, const u8 *data, hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, const u8 *data,
size_t data_len, int encrypt) size_t data_len, int encrypt)
{ {
if (hapd->driver == NULL || hapd->driver->send_eapol == NULL) if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
return 0; return 0;
return hapd->driver->send_eapol(hapd->drv_priv, addr, data, data_len, return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
encrypt, hapd->own_addr); data_len, encrypt,
hapd->own_addr);
} }
static inline int static inline int
@ -158,19 +159,19 @@ hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
static inline int static inline int
hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
{ {
if (hapd->driver == NULL || hapd->driver->get_ssid == NULL) if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
return 0; return 0;
return hapd->driver->get_ssid(hapd->conf->iface, hapd->drv_priv, buf, return hapd->driver->hapd_get_ssid(hapd->conf->iface, hapd->drv_priv,
len); buf, len);
} }
static inline int static inline int
hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
{ {
if (hapd->driver == NULL || hapd->driver->set_ssid == NULL) if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
return 0; return 0;
return hapd->driver->set_ssid(hapd->conf->iface, hapd->drv_priv, buf, return hapd->driver->hapd_set_ssid(hapd->conf->iface, hapd->drv_priv,
len); buf, len);
} }
static inline int static inline int
@ -185,9 +186,10 @@ hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, size_t len,
static inline int static inline int
hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled) hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
{ {
if (hapd->driver == NULL || hapd->driver->set_countermeasures == NULL) if (hapd->driver == NULL ||
hapd->driver->hapd_set_countermeasures == NULL)
return 0; return 0;
return hapd->driver->set_countermeasures(hapd->drv_priv, enabled); return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
} }
static inline int static inline int
@ -290,9 +292,9 @@ static inline int
hostapd_set_country(struct hostapd_data *hapd, const char *country) hostapd_set_country(struct hostapd_data *hapd, const char *country)
{ {
if (hapd->driver == NULL || if (hapd->driver == NULL ||
hapd->driver->set_country == NULL) hapd->driver->hapd_set_country == NULL)
return 0; return 0;
return hapd->driver->set_country(hapd->drv_priv, country); return hapd->driver->hapd_set_country(hapd->drv_priv, country);
} }
static inline int static inline int
@ -317,9 +319,10 @@ hostapd_set_beacon(const char *ifname, struct hostapd_data *hapd,
const u8 *head, size_t head_len, const u8 *head, size_t head_len,
const u8 *tail, size_t tail_len, int dtim_period) const u8 *tail, size_t tail_len, int dtim_period)
{ {
if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) if (hapd->driver == NULL || hapd->driver->hapd_set_beacon == NULL)
return 0; return 0;
return hapd->driver->set_beacon(ifname, hapd->drv_priv, head, head_len, return hapd->driver->hapd_set_beacon(ifname, hapd->drv_priv,
head, head_len,
tail, tail_len, dtim_period); tail, tail_len, dtim_period);
} }
@ -334,9 +337,9 @@ hostapd_set_internal_bridge(struct hostapd_data *hapd, int value)
static inline int static inline int
hostapd_set_beacon_int(struct hostapd_data *hapd, int value) hostapd_set_beacon_int(struct hostapd_data *hapd, int value)
{ {
if (hapd->driver == NULL || hapd->driver->set_beacon_int == NULL) if (hapd->driver == NULL || hapd->driver->hapd_set_beacon_int == NULL)
return 0; return 0;
return hapd->driver->set_beacon_int(hapd->drv_priv, value); return hapd->driver->hapd_set_beacon_int(hapd->drv_priv, value);
} }
static inline int static inline int
@ -449,9 +452,11 @@ static inline struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags) u16 *flags)
{ {
if (hapd->driver == NULL || hapd->driver->get_hw_feature_data == NULL) if (hapd->driver == NULL ||
hapd->driver->hapd_get_hw_feature_data == NULL)
return NULL; return NULL;
return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, return hapd->driver->hapd_get_hw_feature_data(hapd->drv_priv,
num_modes,
flags); flags);
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,374 +0,0 @@
/*
* hostapd / Kernel driver communication for wired (Ethernet) drivers
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
*
* 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>
#ifdef USE_KERNEL_HEADERS
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h> /* The L2 protocols */
#include <linux/if_arp.h>
#include <linux/if.h>
#else /* USE_KERNEL_HEADERS */
#include <net/if_arp.h>
#include <net/if.h>
#include <netpacket/packet.h>
#endif /* USE_KERNEL_HEADERS */
#include "hostapd.h"
#include "config.h"
#include "eloop.h"
#include "sta_info.h"
#include "driver.h"
#include "accounting.h"
struct wired_driver_data {
struct hostapd_data *hapd;
char iface[IFNAMSIZ + 1];
int sock; /* raw packet socket for driver access */
int dhcp_sock; /* socket for dhcp packets */
int use_pae_group_addr;
};
#define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03}
/* TODO: detecting new devices should eventually be changed from using DHCP
* snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
* based on ebtables, etc. */
struct dhcp_message {
u_int8_t op;
u_int8_t htype;
u_int8_t hlen;
u_int8_t hops;
u_int32_t xid;
u_int16_t secs;
u_int16_t flags;
u_int32_t ciaddr;
u_int32_t yiaddr;
u_int32_t siaddr;
u_int32_t giaddr;
u_int8_t chaddr[16];
u_int8_t sname[64];
u_int8_t file[128];
u_int32_t cookie;
u_int8_t options[308]; /* 312 - cookie */
};
static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr)
{
struct sta_info *sta;
sta = ap_get_sta(hapd, addr);
if (sta)
return;
wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
" - adding a new STA", MAC2STR(addr));
sta = ap_sta_add(hapd, addr);
if (sta) {
hostapd_new_assoc_sta(hapd, sta, 0);
} else {
wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
MAC2STR(addr));
}
}
static void handle_data(struct hostapd_data *hapd, unsigned char *buf,
size_t len)
{
struct ieee8023_hdr *hdr;
u8 *pos, *sa;
size_t left;
/* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
* 2 byte ethertype */
if (len < 14) {
wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
(unsigned long) len);
return;
}
hdr = (struct ieee8023_hdr *) buf;
switch (ntohs(hdr->ethertype)) {
case ETH_P_PAE:
wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
sa = hdr->src;
wired_possible_new_sta(hapd, sa);
pos = (u8 *) (hdr + 1);
left = len - sizeof(*hdr);
hostapd_eapol_receive(hapd, sa, pos, left);
break;
default:
wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
ntohs(hdr->ethertype));
break;
}
}
static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
{
struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
int len;
unsigned char buf[3000];
len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv");
return;
}
handle_data(hapd, buf, len);
}
static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
{
struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
int len;
unsigned char buf[3000];
struct dhcp_message *msg;
u8 *mac_address;
len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv");
return;
}
/* must contain at least dhcp_message->chaddr */
if (len < 44) {
wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
return;
}
msg = (struct dhcp_message *) buf;
mac_address = (u8 *) &(msg->chaddr);
wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
MAC2STR(mac_address));
wired_possible_new_sta(hapd, mac_address);
}
static int wired_init_sockets(struct wired_driver_data *drv)
{
struct hostapd_data *hapd = drv->hapd;
struct ifreq ifr;
struct sockaddr_ll addr;
struct sockaddr_in addr2;
struct packet_mreq mreq;
u8 multicastgroup_eapol[6] = WIRED_EAPOL_MULTICAST_GROUP;
int n = 1;
drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
if (drv->sock < 0) {
perror("socket[PF_PACKET,SOCK_RAW]");
return -1;
}
if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) {
printf("Could not register read socket\n");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
perror("ioctl(SIOCGIFINDEX)");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_ifindex = ifr.ifr_ifindex;
wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
addr.sll_ifindex);
if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
return -1;
}
/* filter multicast address */
memset(&mreq, 0, sizeof(mreq));
mreq.mr_ifindex = ifr.ifr_ifindex;
mreq.mr_type = PACKET_MR_MULTICAST;
mreq.mr_alen = 6;
memcpy(mreq.mr_address, multicastgroup_eapol, mreq.mr_alen);
if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0) {
perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
perror("ioctl(SIOCGIFHWADDR)");
return -1;
}
if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
printf("Invalid HW-addr family 0x%04x\n",
ifr.ifr_hwaddr.sa_family);
return -1;
}
memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
/* setup dhcp listen socket for sta detection */
if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket call failed for dhcp");
return -1;
}
if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL))
{
printf("Could not register read socket\n");
return -1;
}
memset(&addr2, 0, sizeof(addr2));
addr2.sin_family = AF_INET;
addr2.sin_port = htons(67);
addr2.sin_addr.s_addr = INADDR_ANY;
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
sizeof(n)) == -1) {
perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
return -1;
}
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
sizeof(n)) == -1) {
perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->iface, IFNAMSIZ);
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
(char *) &ifr, sizeof(ifr)) < 0) {
perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
return -1;
}
if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
sizeof(struct sockaddr)) == -1) {
perror("bind");
return -1;
}
return 0;
}
static int wired_send_eapol(void *priv, const u8 *addr,
const u8 *data, size_t data_len, int encrypt,
const u8 *own_addr)
{
struct wired_driver_data *drv = priv;
u8 pae_group_addr[ETH_ALEN] = WIRED_EAPOL_MULTICAST_GROUP;
struct ieee8023_hdr *hdr;
size_t len;
u8 *pos;
int res;
len = sizeof(*hdr) + data_len;
hdr = os_zalloc(len);
if (hdr == NULL) {
printf("malloc() failed for wired_send_eapol(len=%lu)\n",
(unsigned long) len);
return -1;
}
memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
ETH_ALEN);
memcpy(hdr->src, own_addr, ETH_ALEN);
hdr->ethertype = htons(ETH_P_PAE);
pos = (u8 *) (hdr + 1);
memcpy(pos, data, data_len);
res = send(drv->sock, (u8 *) hdr, len, 0);
free(hdr);
if (res < 0) {
perror("wired_send_eapol: send");
printf("wired_send_eapol - packet len: %lu - failed\n",
(unsigned long) len);
}
return res;
}
static void * wired_driver_init(struct hostapd_data *hapd)
{
struct wired_driver_data *drv;
drv = os_zalloc(sizeof(struct wired_driver_data));
if (drv == NULL) {
printf("Could not allocate memory for wired driver data\n");
return NULL;
}
drv->hapd = hapd;
os_strlcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
drv->use_pae_group_addr = hapd->conf->use_pae_group_addr;
if (wired_init_sockets(drv)) {
free(drv);
return NULL;
}
return drv;
}
static void wired_driver_deinit(void *priv)
{
struct wired_driver_data *drv = priv;
if (drv->sock >= 0)
close(drv->sock);
if (drv->dhcp_sock >= 0)
close(drv->dhcp_sock);
free(drv);
}
const struct hapd_driver_ops wpa_driver_wired_ops = {
.name = "wired",
.init = wired_driver_init,
.deinit = wired_driver_deinit,
.send_eapol = wired_send_eapol,
};

View file

@ -1,77 +0,0 @@
/*
* hostapd / driver interface list
* 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"
#ifdef CONFIG_DRIVER_HOSTAP
extern struct hapd_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_NL80211
extern struct hapd_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
#endif /* CONFIG_DRIVER_NL80211 */
#ifdef CONFIG_DRIVER_PRISM54
extern struct hapd_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */
#endif /* CONFIG_DRIVER_PRISM54 */
#ifdef CONFIG_DRIVER_MADWIFI
extern struct hapd_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
#endif /* CONFIG_DRIVER_MADWIFI */
#ifdef CONFIG_DRIVER_ATHEROS
extern struct hapd_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_BSD
extern struct hapd_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
#endif /* CONFIG_DRIVER_BSD */
#ifdef CONFIG_DRIVER_WIRED
extern struct hapd_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
#endif /* CONFIG_DRIVER_WIRED */
#ifdef CONFIG_DRIVER_TEST
extern struct hapd_driver_ops wpa_driver_test_ops; /* driver_test.c */
#endif /* CONFIG_DRIVER_TEST */
#ifdef CONFIG_DRIVER_NONE
extern struct hapd_driver_ops wpa_driver_none_ops; /* driver_none.c */
#endif /* CONFIG_DRIVER_NONE */
struct hapd_driver_ops *hostapd_drivers[] =
{
#ifdef CONFIG_DRIVER_HOSTAP
&wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_NL80211
&wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
#ifdef CONFIG_DRIVER_PRISM54
&wpa_driver_prism54_ops,
#endif /* CONFIG_DRIVER_PRISM54 */
#ifdef CONFIG_DRIVER_MADWIFI
&wpa_driver_madwifi_ops,
#endif /* CONFIG_DRIVER_MADWIFI */
#ifdef CONFIG_DRIVER_ATHEROS
&wpa_driver_atheros_ops,
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_BSD
&wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */
#ifdef CONFIG_DRIVER_WIRED
&wpa_driver_wired_ops,
#endif /* CONFIG_DRIVER_WIRED */
#ifdef CONFIG_DRIVER_TEST
&wpa_driver_test_ops,
#endif /* CONFIG_DRIVER_TEST */
#ifdef CONFIG_DRIVER_NONE
&wpa_driver_none_ops,
#endif /* CONFIG_DRIVER_NONE */
NULL
};

View file

@ -1,216 +0,0 @@
/*
* hostapd / Kernel driver communication with Linux Host AP driver
* Copyright (c) 2002-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.
*/
#ifndef HOSTAP_COMMON_H
#define HOSTAP_COMMON_H
/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
/* New wireless extensions API - SET/GET convention (even ioctl numbers are
* root only)
*/
#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
/* following are not in SIOCGIWPRIV list; check permission in the driver code
*/
#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
#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,
};
enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
AP_MAC_CMD_KICKALL = 4 };
/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
enum {
PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
/* Note! Old versions of prism2_srec have a fatal error in CRC-16
* calculation, which will corrupt all non-volatile downloads.
* PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
* prevent use of old versions of prism2_srec for non-volatile
* download. */
PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
/* Persistent versions of volatile download commands (keep firmware
* data in memory and automatically re-download after hw_reset */
PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
};
struct prism2_download_param {
u32 dl_cmd;
u32 start_addr;
u32 num_areas;
struct prism2_download_area {
u32 addr; /* wlan card address */
u32 len;
caddr_t ptr; /* pointer to data in user space */
} data[0];
};
#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
#define PRISM2_MAX_DOWNLOAD_LEN 262144
/* 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 BIT(0)
#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
#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_COMMON_H */

View file

@ -20,7 +20,7 @@
#include "common.h" #include "common.h"
#include "hostapd_defs.h" #include "hostapd_defs.h"
struct hapd_driver_ops; struct wpa_driver_ops;
struct wpa_ctrl_dst; struct wpa_ctrl_dst;
struct radius_server_data; struct radius_server_data;
struct upnp_wps_device_sm; struct upnp_wps_device_sm;
@ -54,7 +54,7 @@ struct hostapd_data {
#define AID_WORDS ((2008 + 31) / 32) #define AID_WORDS ((2008 + 31) / 32)
u32 sta_aid[AID_WORDS]; u32 sta_aid[AID_WORDS];
const struct hapd_driver_ops *driver; const struct wpa_driver_ops *driver;
void *drv_priv; void *drv_priv;
u8 *default_wep_key; u8 *default_wep_key;

View file

@ -1,71 +0,0 @@
#ifndef PRIV_NETLINK_H
#define PRIV_NETLINK_H
/* Private copy of needed Linux netlink/rtnetlink definitions.
*
* This should be replaced with user space header once one is available with C
* library, etc..
*/
#ifndef IFLA_IFNAME
#define IFLA_IFNAME 3
#endif
#ifndef IFLA_WIRELESS
#define IFLA_WIRELESS 11
#endif
#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 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)))
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

@ -171,8 +171,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
hapd->iface->num_sta_ht_20mhz--; hapd->iface->num_sta_ht_20mhz--;
} }
#ifdef NEED_MLME
if (hostapd_ht_operation_update(hapd->iface) > 0) if (hostapd_ht_operation_update(hapd->iface) > 0)
set_beacon++; set_beacon++;
#endif /* NEED_MLME */
#endif /* CONFIG_IEEE80211N */ #endif /* CONFIG_IEEE80211N */
if (set_beacon) if (set_beacon)
@ -695,7 +697,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
HOSTAPD_LEVEL_DEBUG, HOSTAPD_LEVEL_DEBUG,
"association SA Query attempt %d", sta->sa_query_count); "association SA Query attempt %d", sta->sa_query_count);
#ifdef NEED_MLME
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
#endif /* NEED_MLME */
} }

View file

@ -28,7 +28,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include "priv_netlink.h" #include "drivers/priv_netlink.h"
#include "eloop.h" #include "eloop.h"

View file

@ -526,6 +526,7 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
return pos; return pos;
} }
#ifdef NEED_MLME
if (parse.wmm_tspec) { if (parse.wmm_tspec) {
struct wmm_tspec_element *tspec; struct wmm_tspec_element *tspec;
int res; int res;
@ -561,6 +562,7 @@ static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
} }
return pos; return pos;
} }
#endif /* NEED_MLME */
wpa_printf(MSG_DEBUG, "FT: No supported resource requested"); wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);

View file

@ -213,34 +213,6 @@ enum mfp_options {
IEEE80211W_REQUIRED = 2 IEEE80211W_REQUIRED = 2
}; };
/* Hardware features */
#define HOSTAPD_CHAN_DISABLED 0x00000001
#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002
#define HOSTAPD_CHAN_NO_IBSS 0x00000004
#define HOSTAPD_CHAN_RADAR 0x00000008
struct hostapd_channel_data {
short chan; /* channel number (IEEE 802.11) */
short freq; /* frequency in MHz */
int flag; /* flag for hostapd use (HOSTAPD_CHAN_*) */
u8 max_tx_power; /* maximum transmit power in dBm */
};
#define HOSTAPD_RATE_ERP 0x00000001
#define HOSTAPD_RATE_BASIC 0x00000002
#define HOSTAPD_RATE_PREAMBLE2 0x00000004
#define HOSTAPD_RATE_SUPPORTED 0x00000010
#define HOSTAPD_RATE_OFDM 0x00000020
#define HOSTAPD_RATE_CCK 0x00000040
#define HOSTAPD_RATE_MANDATORY 0x00000100
struct hostapd_rate_data {
int rate; /* rate in 100 kbps */
int flags; /* HOSTAPD_RATE_ flags */
};
typedef enum { typedef enum {
HOSTAPD_MODE_IEEE80211B, HOSTAPD_MODE_IEEE80211B,
HOSTAPD_MODE_IEEE80211G, HOSTAPD_MODE_IEEE80211G,
@ -248,13 +220,4 @@ typedef enum {
NUM_HOSTAPD_MODES NUM_HOSTAPD_MODES
} hostapd_hw_mode; } hostapd_hw_mode;
struct hostapd_hw_modes {
hostapd_hw_mode mode;
int num_channels;
struct hostapd_channel_data *channels;
int num_rates;
struct hostapd_rate_data *rates;
u16 ht_capab;
};
#endif /* DEFS_H */ #endif /* DEFS_H */

View file

@ -19,6 +19,41 @@
#include "defs.h" #include "defs.h"
#define HOSTAPD_CHAN_DISABLED 0x00000001
#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002
#define HOSTAPD_CHAN_NO_IBSS 0x00000004
#define HOSTAPD_CHAN_RADAR 0x00000008
struct hostapd_channel_data {
short chan; /* channel number (IEEE 802.11) */
short freq; /* frequency in MHz */
int flag; /* flag for hostapd use (HOSTAPD_CHAN_*) */
u8 max_tx_power; /* maximum transmit power in dBm */
};
#define HOSTAPD_RATE_ERP 0x00000001
#define HOSTAPD_RATE_BASIC 0x00000002
#define HOSTAPD_RATE_PREAMBLE2 0x00000004
#define HOSTAPD_RATE_SUPPORTED 0x00000010
#define HOSTAPD_RATE_OFDM 0x00000020
#define HOSTAPD_RATE_CCK 0x00000040
#define HOSTAPD_RATE_MANDATORY 0x00000100
struct hostapd_rate_data {
int rate; /* rate in 100 kbps */
int flags; /* HOSTAPD_RATE_ flags */
};
struct hostapd_hw_modes {
hostapd_hw_mode mode;
int num_channels;
struct hostapd_channel_data *channels;
int num_rates;
struct hostapd_rate_data *rates;
u16 ht_capab;
};
#define AUTH_ALG_OPEN_SYSTEM 0x01 #define AUTH_ALG_OPEN_SYSTEM 0x01
#define AUTH_ALG_SHARED_KEY 0x02 #define AUTH_ALG_SHARED_KEY 0x02
#define AUTH_ALG_LEAP 0x04 #define AUTH_ALG_LEAP 0x04
@ -420,6 +455,54 @@ struct ieee80211_rx_status {
}; };
struct hostapd_data;
struct hostap_sta_driver_data {
unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes;
unsigned long current_tx_rate;
unsigned long inactive_msec;
unsigned long flags;
unsigned long num_ps_buf_frames;
unsigned long tx_retry_failed;
unsigned long tx_retry_count;
int last_rssi;
int last_ack_rssi;
};
struct hostapd_sta_add_params {
const u8 *addr;
u16 aid;
u16 capability;
const u8 *supp_rates;
size_t supp_rates_len;
int flags;
u16 listen_interval;
const struct ht_cap_ie *ht_capabilities;
};
struct hostapd_freq_params {
int mode;
int freq;
int channel;
int ht_enabled;
int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
* secondary channel below primary, 1 = HT40
* enabled, secondary channel above primary */
};
enum hostapd_driver_if_type {
HOSTAPD_IF_VLAN, HOSTAPD_IF_WDS
};
struct hostapd_neighbor_bss {
u8 bssid[ETH_ALEN];
int freq; /* MHz */
unsigned int ht:1;
int pri_chan;
int sec_chan; /* 0 for 20 MHz channels */
};
/** /**
* struct wpa_driver_ops - Driver interface API definition * struct wpa_driver_ops - Driver interface API definition
* *
@ -1113,6 +1196,149 @@ struct wpa_driver_ops {
const u8 *tail, size_t tail_len, int dtim_period); const u8 *tail, size_t tail_len, int dtim_period);
int (*set_beacon_int)(void *priv, int value); int (*set_beacon_int)(void *priv, int value);
void * (*hapd_init)(struct hostapd_data *hapd);
void * (*init_bssid)(struct hostapd_data *hapd, const u8 *bssid);
void (*hapd_deinit)(void *priv);
/**
* set_8021x - enable/disable IEEE 802.1X support
* @ifname: Interface name (for multi-SSID/VLAN support)
* @priv: driver private data
* @enabled: 1 = enable, 0 = disable
*
* Returns: 0 on success, -1 on failure
*
* Configure the kernel driver to enable/disable 802.1X support.
* This may be an empty function if 802.1X support is always enabled.
*/
int (*set_ieee8021x)(const char *ifname, void *priv, int enabled);
/**
* set_privacy - enable/disable privacy
* @priv: driver private data
* @enabled: 1 = privacy enabled, 0 = disabled
*
* Return: 0 on success, -1 on failure
*
* Configure privacy.
*/
int (*set_privacy)(const char *ifname, void *priv, int enabled);
int (*hapd_set_key)(const char *ifname, 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 (*get_seqnum)(const char *ifname, void *priv, const u8 *addr,
int idx, u8 *seq);
int (*get_seqnum_igtk)(const char *ifname, void *priv, const u8 *addr,
int idx, u8 *seq);
int (*flush)(void *priv);
int (*set_generic_elem)(const char *ifname, void *priv, const u8 *elem,
size_t elem_len);
int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data,
const u8 *addr);
int (*hapd_send_eapol)(void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt,
const u8 *own_addr);
int (*sta_deauth)(void *priv, const u8 *addr, int reason);
int (*sta_disassoc)(void *priv, const u8 *addr, int reason);
int (*sta_remove)(void *priv, const u8 *addr);
int (*hapd_get_ssid)(const char *ifname, void *priv, u8 *buf, int len);
int (*hapd_set_ssid)(const char *ifname, void *priv, const u8 *buf,
int len);
int (*hapd_set_countermeasures)(void *priv, int enabled);
int (*send_mgmt_frame)(void *priv, const void *msg, size_t len,
int flags);
int (*sta_add)(const char *ifname, void *priv,
struct hostapd_sta_add_params *params);
int (*get_inact_sec)(void *priv, const u8 *addr);
int (*sta_clear_stats)(void *priv, const u8 *addr);
int (*set_freq)(void *priv, struct hostapd_freq_params *freq);
int (*set_rts)(void *priv, int rts);
int (*set_frag)(void *priv, int frag);
int (*set_retry)(void *priv, int short_retry, int long_retry);
int (*sta_set_flags)(void *priv, const u8 *addr,
int total_flags, int flags_or, int flags_and);
int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates,
int mode);
int (*hapd_set_country)(void *priv, const char *country);
int (*set_ieee80211d)(void *priv, int enabled);
int (*hapd_set_beacon)(const char *ifname, void *priv,
const u8 *head, size_t head_len,
const u8 *tail, size_t tail_len,
int dtim_period);
/* Configure internal bridge:
* 0 = disabled, i.e., client separation is enabled (no bridging of
* packets between associated STAs
* 1 = enabled, i.e., bridge packets between associated STAs (default)
*/
int (*set_internal_bridge)(void *priv, int value);
int (*hapd_set_beacon_int)(void *priv, int value);
/* Configure broadcast SSID mode:
* 0 = include SSID in Beacon frames and reply to Probe Request frames
* that use broadcast SSID
* 1 = hide SSID from Beacon frames and ignore Probe Request frames for
* broadcast SSID
*/
int (*set_broadcast_ssid)(void *priv, int value);
int (*set_cts_protect)(void *priv, int value);
int (*set_preamble)(void *priv, int value);
int (*set_short_slot_time)(void *priv, int value);
int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min,
int cw_max, int burst_time);
int (*bss_add)(void *priv, const char *ifname, const u8 *bssid);
int (*bss_remove)(void *priv, const char *ifname);
int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask);
int (*passive_scan)(void *priv, int now, int our_mode_only,
int interval, int _listen, int *channel,
int *last_rx);
struct hostapd_hw_modes * (*hapd_get_hw_feature_data)(void *priv,
u16 *num_modes,
u16 *flags);
int (*if_add)(const char *iface, void *priv,
enum hostapd_driver_if_type type, char *ifname,
const u8 *addr);
int (*if_update)(void *priv, enum hostapd_driver_if_type type,
char *ifname, const u8 *addr);
int (*if_remove)(void *priv, enum hostapd_driver_if_type type,
const char *ifname, const u8 *addr);
int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname,
int vlan_id);
/**
* commit - Optional commit changes handler
* @priv: driver private data
* Returns: 0 on success, -1 on failure
*
* This optional handler function can be registered if the driver
* interface implementation needs to commit changes (e.g., by setting
* network interface up) at the end of initial configuration. If set,
* this handler will be called after initial setup has been completed.
*/
int (*commit)(void *priv);
int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto,
const u8 *data, size_t data_len);
int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted,
u32 session_timeout);
int (*set_radius_acl_expire)(void *priv, const u8 *mac);
int (*set_ht_params)(const char *ifname, void *priv,
const u8 *ht_capab, size_t ht_capab_len,
const u8 *ht_oper, size_t ht_oper_len);
int (*set_wps_beacon_ie)(const char *ifname, void *priv,
const u8 *ie, size_t len);
int (*set_wps_probe_resp_ie)(const char *ifname, void *priv,
const u8 *ie, size_t len);
const struct hostapd_neighbor_bss *
(*get_neighbor_bss)(void *priv, size_t *num);
}; };
/** /**
@ -1502,4 +1728,36 @@ int wpa_scan_get_max_rate(const struct wpa_scan_res *res);
void wpa_scan_results_free(struct wpa_scan_results *res); void wpa_scan_results_free(struct wpa_scan_results *res);
void wpa_scan_sort_results(struct wpa_scan_results *res); void wpa_scan_sort_results(struct wpa_scan_results *res);
/* hostapd functions for driver wrappers */
struct sta_info;
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, const u8 *addr);
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa,
const u8 *buf, size_t len);
struct hostapd_frame_info {
u32 phytype;
u32 channel;
u32 datarate;
u32 ssi_signal;
unsigned int passive_scan:1;
};
void hostapd_mgmt_rx(struct hostapd_data *hapd, u8 *buf, size_t len,
u16 stype, struct hostapd_frame_info *fi);
void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
u16 stype, int ok);
void hostapd_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr);
struct hostapd_data * hostapd_sta_get_bss(struct hostapd_data *hapd,
const u8 *addr);
#endif /* DRIVER_H */ #endif /* DRIVER_H */

View file

@ -58,14 +58,15 @@
#include "wireless_copy.h" #include "wireless_copy.h"
#include "hostapd.h" #include "../hostapd/hostapd.h"
#include "config.h" #include "../hostapd/config.h"
#include "../hostapd/sta_flags.h"
#include "driver.h" #include "driver.h"
#include "eloop.h" #include "eloop.h"
#include "priv_netlink.h" #include "priv_netlink.h"
#include "l2_packet/l2_packet.h" #include "l2_packet/l2_packet.h"
#include "wps_hostapd.h" #include "../hostapd/wps_hostapd.h"
#include "ieee802_11_defs.h" #include "ieee802_11_defs.h"
@ -1315,23 +1316,23 @@ madwifi_commit(void *priv)
return madwifi_set_iface_flags(priv, 1); return madwifi_set_iface_flags(priv, 1);
} }
const struct hapd_driver_ops wpa_driver_atheros_ops = { const struct wpa_driver_ops wpa_driver_atheros_ops = {
.name = "atheros", .name = "atheros",
.init = madwifi_init, .hapd_init = madwifi_init,
.deinit = madwifi_deinit, .deinit = madwifi_deinit,
.set_ieee8021x = madwifi_set_ieee8021x, .set_ieee8021x = madwifi_set_ieee8021x,
.set_privacy = madwifi_set_privacy, .set_privacy = madwifi_set_privacy,
.set_key = madwifi_set_key, .hapd_set_key = madwifi_set_key,
.get_seqnum = madwifi_get_seqnum, .get_seqnum = madwifi_get_seqnum,
.flush = madwifi_flush, .flush = madwifi_flush,
.set_generic_elem = madwifi_set_opt_ie, .set_generic_elem = madwifi_set_opt_ie,
.sta_set_flags = madwifi_sta_set_flags, .sta_set_flags = madwifi_sta_set_flags,
.read_sta_data = madwifi_read_sta_driver_data, .read_sta_data = madwifi_read_sta_driver_data,
.send_eapol = madwifi_send_eapol, .hapd_send_eapol = madwifi_send_eapol,
.sta_disassoc = madwifi_sta_disassoc, .sta_disassoc = madwifi_sta_disassoc,
.sta_deauth = madwifi_sta_deauth, .sta_deauth = madwifi_sta_deauth,
.set_ssid = madwifi_set_ssid, .hapd_set_ssid = madwifi_set_ssid,
.get_ssid = madwifi_get_ssid, .hapd_get_ssid = madwifi_get_ssid,
.set_countermeasures = madwifi_set_countermeasures, .set_countermeasures = madwifi_set_countermeasures,
.sta_clear_stats = madwifi_sta_clear_stats, .sta_clear_stats = madwifi_sta_clear_stats,
.commit = madwifi_commit, .commit = madwifi_commit,

View file

@ -1,6 +1,7 @@
/* /*
* WPA Supplicant - driver interaction with BSD net80211 layer * WPA Supplicant - driver interaction with BSD net80211 layer
* Copyright (c) 2004, Sam Leffler <sam@errno.com> * Copyright (c) 2004, Sam Leffler <sam@errno.com>
* Copyright (c) 2004, 2Wire, Inc
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@ -33,6 +34,752 @@
#include <net80211/ieee80211_crypto.h> #include <net80211/ieee80211_crypto.h>
#include <net80211/ieee80211_ioctl.h> #include <net80211/ieee80211_ioctl.h>
/*
* Avoid conflicts with hostapd definitions by undefining couple of defines
* from net80211 header files.
*/
#undef RSN_VERSION
#undef WPA_VERSION
#undef WPA_OUI_TYPE
#ifdef HOSTAPD
#include "l2_packet/l2_packet.h"
#include "../../hostapd/hostapd.h"
#include "../../hostapd/config.h"
#include "../../hostapd/eapol_sm.h"
struct bsd_driver_data {
struct hostapd_data *hapd; /* back pointer */
char iface[IFNAMSIZ + 1];
struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
int ioctl_sock; /* socket for ioctl() use */
int wext_sock; /* socket for wireless events */
};
static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code);
static int
set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
{
struct ieee80211req ireq;
memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
ireq.i_type = op;
ireq.i_len = arg_len;
ireq.i_data = (void *) arg;
if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
perror("ioctl[SIOCS80211]");
return -1;
}
return 0;
}
static int
get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
{
struct ieee80211req ireq;
memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
ireq.i_type = op;
ireq.i_len = arg_len;
ireq.i_data = arg;
if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) {
perror("ioctl[SIOCG80211]");
return -1;
}
return ireq.i_len;
}
static int
set80211param(struct bsd_driver_data *drv, int op, int arg)
{
struct ieee80211req ireq;
memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
ireq.i_type = op;
ireq.i_val = arg;
if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
perror("ioctl[SIOCS80211]");
return -1;
}
return 0;
}
static const char *
ether_sprintf(const u8 *addr)
{
static char buf[sizeof(MACSTR)];
if (addr != NULL)
snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
else
snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
return buf;
}
/*
* Configure WPA parameters.
*/
static int
bsd_configure_wpa(struct bsd_driver_data *drv)
{
static const char *ciphernames[] =
{ "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
struct hostapd_data *hapd = drv->hapd;
struct hostapd_bss_config *conf = hapd->conf;
int v;
switch (conf->wpa_group) {
case WPA_CIPHER_CCMP:
v = IEEE80211_CIPHER_AES_CCM;
break;
case WPA_CIPHER_TKIP:
v = IEEE80211_CIPHER_TKIP;
break;
case WPA_CIPHER_WEP104:
v = IEEE80211_CIPHER_WEP;
break;
case WPA_CIPHER_WEP40:
v = IEEE80211_CIPHER_WEP;
break;
case WPA_CIPHER_NONE:
v = IEEE80211_CIPHER_NONE;
break;
default:
printf("Unknown group key cipher %u\n",
conf->wpa_group);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
__func__, ciphernames[v], v);
if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) {
printf("Unable to set group key cipher to %u (%s)\n",
v, ciphernames[v]);
return -1;
}
if (v == IEEE80211_CIPHER_WEP) {
/* key length is done only for specific ciphers */
v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) {
printf("Unable to set group key length to %u\n", v);
return -1;
}
}
v = 0;
if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
v |= 1<<IEEE80211_CIPHER_AES_CCM;
if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
v |= 1<<IEEE80211_CIPHER_TKIP;
if (conf->wpa_pairwise & WPA_CIPHER_NONE)
v |= 1<<IEEE80211_CIPHER_NONE;
wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
if (set80211param(drv, IEEE80211_IOC_UCASTCIPHERS, v)) {
printf("Unable to set pairwise key ciphers to 0x%x\n", v);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
__func__, conf->wpa_key_mgmt);
if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) {
printf("Unable to set key management algorithms to 0x%x\n",
conf->wpa_key_mgmt);
return -1;
}
v = 0;
if (conf->rsn_preauth)
v |= BIT(0);
wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
__func__, conf->rsn_preauth);
if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) {
printf("Unable to set RSN capabilities to 0x%x\n", v);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa);
if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) {
printf("Unable to set WPA to %u\n", conf->wpa);
return -1;
}
return 0;
}
static int
bsd_set_iface_flags(void *priv, int dev_up)
{
struct bsd_driver_data *drv = priv;
struct ifreq ifr;
wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
if (drv->ioctl_sock < 0)
return -1;
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
perror("ioctl[SIOCGIFFLAGS]");
return -1;
}
if (dev_up)
ifr.ifr_flags |= IFF_UP;
else
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
perror("ioctl[SIOCSIFFLAGS]");
return -1;
}
if (dev_up) {
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
ifr.ifr_mtu = HOSTAPD_MTU;
if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
perror("ioctl[SIOCSIFMTU]");
printf("Setting MTU failed - trying to survive with "
"current value\n");
}
}
return 0;
}
static int
bsd_set_ieee8021x(const char *ifname, void *priv, int enabled)
{
struct bsd_driver_data *drv = priv;
struct hostapd_data *hapd = drv->hapd;
struct hostapd_bss_config *conf = hapd->conf;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
if (!enabled) {
/* XXX restore state */
return set80211param(priv, IEEE80211_IOC_AUTHMODE,
IEEE80211_AUTH_AUTO);
}
if (!conf->wpa && !conf->ieee802_1x) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
return -1;
}
if (conf->wpa && bsd_configure_wpa(drv) != 0) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
return -1;
}
if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
(conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
return -1;
}
return bsd_set_iface_flags(priv, 1);
}
static int
bsd_set_privacy(const char *ifname, void *priv, int enabled)
{
struct bsd_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);
}
static int
bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d",
__func__, ether_sprintf(addr), authorized);
if (authorized)
mlme.im_op = IEEE80211_MLME_AUTHORIZE;
else
mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
mlme.im_reason = 0;
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or,
int flags_and)
{
/* For now, only support setting Authorized flag */
if (flags_or & WLAN_STA_AUTHORIZED)
return bsd_set_sta_authorized(priv, addr, 1);
if (!(flags_and & WLAN_STA_AUTHORIZED))
return bsd_set_sta_authorized(priv, addr, 0);
return 0;
}
static int
bsd_del_key(void *priv, const u8 *addr, int key_idx)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_del_key wk;
wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d",
__func__, ether_sprintf(addr), key_idx);
memset(&wk, 0, sizeof(wk));
if (addr != NULL) {
memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */
} else {
wk.idk_keyix = key_idx;
}
return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
}
static int
bsd_set_key(const char *ifname, 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 bsd_driver_data *drv = priv;
struct ieee80211req_key wk;
u_int8_t cipher;
if (alg == WPA_ALG_NONE)
return bsd_del_key(drv, addr, key_idx);
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d",
__func__, alg, ether_sprintf(addr), key_idx);
if (alg == WPA_ALG_WEP)
cipher = IEEE80211_CIPHER_WEP;
else if (alg == WPA_ALG_TKIP)
cipher = IEEE80211_CIPHER_TKIP;
else if (alg == WPA_ALG_CCMP)
cipher = IEEE80211_CIPHER_AES_CCM;
else {
printf("%s: unknown/unsupported algorithm %d\n",
__func__, alg);
return -1;
}
if (key_len > sizeof(wk.ik_keydata)) {
printf("%s: key length %d too big\n", __func__, key_len);
return -3;
}
memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
if (addr == NULL) {
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
} else {
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = IEEE80211_KEYIX_NONE;
}
wk.ik_keylen = key_len;
memcpy(wk.ik_keydata, key, key_len);
return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
}
static int
bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
u8 *seq)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_key wk;
wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
__func__, ether_sprintf(addr), idx);
memset(&wk, 0, sizeof(wk));
if (addr == NULL)
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
else
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = idx;
if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
printf("Failed to get encryption.\n");
return -1;
}
#ifdef WORDS_BIGENDIAN
{
/*
* wk.ik_keytsc is in host byte order (big endian), need to
* swap it to match with the byte order used in WPA.
*/
int i;
u8 tmp[WPA_KEY_RSC_LEN];
memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
}
}
#else /* WORDS_BIGENDIAN */
memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
#endif /* WORDS_BIGENDIAN */
return 0;
}
static int
bsd_flush(void *priv)
{
u8 allsta[IEEE80211_ADDR_LEN];
memset(allsta, 0xff, IEEE80211_ADDR_LEN);
return bsd_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE);
}
static int
bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
const u8 *addr)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_sta_stats stats;
memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) {
/* XXX? do packets counts include non-data frames? */
data->rx_packets = stats.is_stats.ns_rx_data;
data->rx_bytes = stats.is_stats.ns_rx_bytes;
data->tx_packets = stats.is_stats.ns_tx_data;
data->tx_bytes = stats.is_stats.ns_tx_bytes;
}
return 0;
}
static int
bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
{
/*
* Do nothing; we setup parameters at startup that define the
* contents of the beacon information element.
*/
return 0;
}
static int
bsd_sta_deauth(void *priv, const u8 *addr, int reason_code)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
__func__, ether_sprintf(addr), reason_code);
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = reason_code;
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
__func__, ether_sprintf(addr), reason_code);
mlme.im_op = IEEE80211_MLME_DISASSOC;
mlme.im_reason = reason_code;
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
struct hostapd_data *hapd = drv->hapd;
struct ieee80211req_wpaie ie;
int ielen = 0;
u8 *iebuf = NULL;
/*
* Fetch and validate any negotiated WPA/RSN parameters.
*/
memset(&ie, 0, sizeof(ie));
memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
printf("Failed to get WPA/RSN information element.\n");
goto no_ie;
}
iebuf = ie.wpa_ie;
ielen = ie.wpa_ie[1];
if (ielen == 0)
iebuf = NULL;
else
ielen += 2;
no_ie:
return hostapd_notif_assoc(hapd, addr, iebuf, ielen);
}
#include <net/route.h>
#include <net80211/ieee80211_freebsd.h>
static void
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = ctx;
struct hostapd_data *hapd = drv->hapd;
char buf[2048];
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
struct ieee80211_join_event *join;
struct ieee80211_leave_event *leave;
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;
}
ifan = (struct if_announcemsghdr *) rtm;
switch (rtm->rtm_type) {
case RTM_IEEE80211:
switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC:
case RTM_IEEE80211_DISASSOC:
case RTM_IEEE80211_SCAN:
break;
case RTM_IEEE80211_LEAVE:
leave = (struct ieee80211_leave_event *) &ifan[1];
hostapd_notif_disassoc(drv->hapd, leave->iev_addr);
break;
case RTM_IEEE80211_JOIN:
#ifdef RTM_IEEE80211_REJOIN
case RTM_IEEE80211_REJOIN:
#endif
join = (struct ieee80211_join_event *) &ifan[1];
bsd_new_sta(drv, join->iev_addr);
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));
hostapd_michael_mic_failure(hapd, mic->iev_src);
break;
}
break;
}
}
static int
bsd_wireless_event_init(struct bsd_driver_data *drv)
{
int s;
drv->wext_sock = -1;
s = socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0) {
perror("socket(PF_ROUTE,SOCK_RAW)");
return -1;
}
eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL);
drv->wext_sock = s;
return 0;
}
static void
bsd_wireless_event_deinit(struct bsd_driver_data *drv)
{
if (drv->wext_sock < 0)
return;
eloop_unregister_read_sock(drv->wext_sock);
close(drv->wext_sock);
}
static int
bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
{
struct bsd_driver_data *drv = priv;
unsigned char buf[3000];
unsigned char *bp = buf;
struct l2_ethhdr *eth;
size_t len;
int status;
/*
* Prepend the Etherent header. If the caller left us
* space at the front we could just insert it but since
* we don't know we copy to a local buffer. Given the frequency
* and size of frames this probably doesn't matter.
*/
len = data_len + sizeof(struct l2_ethhdr);
if (len > sizeof(buf)) {
bp = malloc(len);
if (bp == NULL) {
printf("EAPOL frame discarded, cannot malloc temp "
"buffer of size %u!\n", len);
return -1;
}
}
eth = (struct l2_ethhdr *) bp;
memcpy(eth->h_dest, addr, ETH_ALEN);
memcpy(eth->h_source, own_addr, ETH_ALEN);
eth->h_proto = htons(ETH_P_EAPOL);
memcpy(eth+1, data, data_len);
wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
if (bp != buf)
free(bp);
return status;
}
static void
handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
{
struct bsd_driver_data *drv = ctx;
hostapd_eapol_receive(drv->hapd, src_addr,
buf + sizeof(struct l2_ethhdr),
len - sizeof(struct l2_ethhdr));
}
static int
bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
{
struct bsd_driver_data *drv = priv;
int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len);
wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);
return ssid_len;
}
static int
bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
{
struct bsd_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf);
return set80211var(drv, IEEE80211_IOC_SSID, buf, len);
}
static void *
bsd_init(struct hostapd_data *hapd)
{
struct bsd_driver_data *drv;
drv = os_zalloc(sizeof(struct bsd_driver_data));
if (drv == NULL) {
printf("Could not allocate memory for bsd driver data\n");
goto bad;
}
drv->hapd = hapd;
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->ioctl_sock < 0) {
perror("socket[PF_INET,SOCK_DGRAM]");
goto bad;
}
memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
handle_read, drv, 1);
if (drv->sock_xmit == NULL)
goto bad;
if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr))
goto bad;
bsd_set_iface_flags(drv, 0); /* mark down during setup */
if (bsd_wireless_event_init(drv))
goto bad;
return drv;
bad:
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
if (drv != NULL)
free(drv);
return NULL;
}
static void
bsd_deinit(void *priv)
{
struct bsd_driver_data *drv = priv;
bsd_wireless_event_deinit(drv);
(void) bsd_set_iface_flags(drv, 0);
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
free(drv);
}
const struct wpa_driver_ops wpa_driver_bsd_ops = {
.name = "bsd",
.hapd_init = bsd_init,
.hapd_deinit = bsd_deinit,
.set_ieee8021x = bsd_set_ieee8021x,
.set_privacy = bsd_set_privacy,
.hapd_set_key = bsd_set_key,
.get_seqnum = bsd_get_seqnum,
.flush = bsd_flush,
.set_generic_elem = bsd_set_opt_ie,
.sta_set_flags = bsd_sta_set_flags,
.read_sta_data = bsd_read_sta_driver_data,
.hapd_send_eapol = bsd_send_eapol,
.sta_disassoc = bsd_sta_disassoc,
.sta_deauth = bsd_sta_deauth,
.hapd_set_ssid = bsd_set_ssid,
.hapd_get_ssid = bsd_get_ssid,
};
#else /* HOSTAPD */
struct wpa_driver_bsd_data { struct wpa_driver_bsd_data {
int sock; /* open socket for 802.11 ioctls */ int sock; /* open socket for 802.11 ioctls */
int route; /* routing socket for events */ int route; /* routing socket for events */
@ -798,3 +1545,5 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.associate = wpa_driver_bsd_associate, .associate = wpa_driver_bsd_associate,
.set_auth_alg = wpa_driver_bsd_set_auth_alg, .set_auth_alg = wpa_driver_bsd_set_auth_alg,
}; };
#endif /* HOSTAPD */

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant - driver interaction with Linux Host AP driver * Driver interaction with Linux Host AP driver
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@ -15,10 +15,32 @@
#ifndef HOSTAP_DRIVER_H #ifndef HOSTAP_DRIVER_H
#define HOSTAP_DRIVER_H #define HOSTAP_DRIVER_H
/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
/* New wireless extensions API - SET/GET convention (even ioctl numbers are
* root only)
*/
#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) #define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) #define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
/* following are not in SIOCGIWPRIV list; check permission in the driver code
*/
#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) #define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ /* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
enum { enum {
/* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
@ -63,6 +85,47 @@ enum {
PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
}; };
enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
AP_MAC_CMD_KICKALL = 4 };
/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
enum {
PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
/* Note! Old versions of prism2_srec have a fatal error in CRC-16
* calculation, which will corrupt all non-volatile downloads.
* PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
* prevent use of old versions of prism2_srec for non-volatile
* download. */
PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
/* Persistent versions of volatile download commands (keep firmware
* data in memory and automatically re-download after hw_reset */
PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
};
struct prism2_download_param {
u32 dl_cmd;
u32 start_addr;
u32 num_areas;
struct prism2_download_area {
u32 addr; /* wlan card address */
u32 len;
caddr_t ptr; /* pointer to data in user space */
} data[0];
};
#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
#define PRISM2_MAX_DOWNLOAD_LEN 262144
/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ /* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
enum { enum {
PRISM2_HOSTAPD_FLUSH = 1, PRISM2_HOSTAPD_FLUSH = 1,
@ -140,8 +203,8 @@ struct prism2_hostapd_param {
} u; } u;
}; };
#define HOSTAP_CRYPT_FLAG_SET_TX_KEY 0x01 #define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
#define HOSTAP_CRYPT_FLAG_PERMANENT 0x02 #define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 #define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 #define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3

File diff suppressed because it is too large Load diff

View file

@ -3217,5 +3217,57 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
NULL /* scan2 */, NULL /* scan2 */,
NULL /* authenticate */, NULL /* authenticate */,
NULL /* set_beacon */, NULL /* set_beacon */,
NULL /* set_beacon_int */ NULL /* set_beacon_int */,
NULL /* set_ieee8021x */,
NULL /* set_privacy */,
NULL /* hapd_set_key */,
NULL /* get_seqnum */,
NULL /* get_seqnum_igtk */,
NULL /* flush */,
NULL /* set_generic_elem */,
NULL /* read_sta_data */,
NULL /* hapd_send_eapol */,
NULL /* sta_deauth */,
NULL /* sta_disassoc */,
NULL /* sta_remove */,
NULL /* hapd_get_ssid */,
NULL /* hapd_set_ssid */,
NULL /* hapd_set_countermeasures */,
NULL /* send_mgmt_frame */,
NULL /* sta_add */,
NULL /* get_inact_sec */,
NULL /* sta_clear_stats */,
NULL /* set_freq */,
NULL /* set_rts */,
NULL /* set_frag */,
NULL /* set_retry */,
NULL /* sta_set_flags */,
NULL /* set_rate_sets */,
NULL /* hapd_set_country */,
NULL /* set_ieee80211d */,
NULL /* hapd_set_beacon */,
NULL /* set_internal_bridge */,
NULL /* hapd_set_beacon_int */,
NULL /* set_broadcast_ssid */,
NULL /* set_cts_protect */,
NULL /* set_preamble */,
NULL /* set_short_slot_time */,
NULL /* set_tx_queue_params */,
NULL /* bss_add */,
NULL /* bss_remove */,
NULL /* valid_bss_mask */,
NULL /* passive_scan */,
NULL /* hapd_get_hw_feature_data */,
NULL /* if_add */,
NULL /* if_update */,
NULL /* if_remove */,
NULL /* set_sta_vlan */,
NULL /* commit */,
NULL /* send_ether */,
NULL /* set_radius_acl_auth */,
NULL /* set_radius_acl_expire */,
NULL /* set_ht_params */,
NULL /* set_wps_beacon_ie */,
NULL /* set_wps_probe_resp_ie */,
NULL /* get_neighbor_bss */
}; };

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,7 @@
#include "includes.h" #include "includes.h"
#include "hostapd.h" #include "../hostapd/hostapd.h"
#include "driver.h" #include "driver.h"
@ -54,9 +54,9 @@ static int none_driver_send_ether(void *priv, const u8 *dst, const u8 *src,
} }
const struct hapd_driver_ops wpa_driver_none_ops = { const struct wpa_driver_ops wpa_driver_none_ops = {
.name = "none", .name = "none",
.init = none_driver_init, .hapd_init = none_driver_init,
.deinit = none_driver_deinit, .hapd_deinit = none_driver_deinit,
.send_ether = none_driver_send_ether, .send_ether = none_driver_send_ether,
}; };

File diff suppressed because it is too large Load diff

View file

@ -813,11 +813,63 @@ struct wpa_driver_ops wpa_driver_privsep_ops = {
NULL /* scan2 */, NULL /* scan2 */,
NULL /* authenticate */, NULL /* authenticate */,
NULL /* set_beacon */, NULL /* set_beacon */,
NULL /* set_beacon_int */ NULL /* set_beacon_int */,
NULL /* set_ieee8021x */,
NULL /* set_privacy */,
NULL /* hapd_set_key */,
NULL /* get_seqnum */,
NULL /* get_seqnum_igtk */,
NULL /* flush */,
NULL /* set_generic_elem */,
NULL /* read_sta_data */,
NULL /* hapd_send_eapol */,
NULL /* sta_deauth */,
NULL /* sta_disassoc */,
NULL /* sta_remove */,
NULL /* hapd_get_ssid */,
NULL /* hapd_set_ssid */,
NULL /* hapd_set_countermeasures */,
NULL /* send_mgmt_frame */,
NULL /* sta_add */,
NULL /* get_inact_sec */,
NULL /* sta_clear_stats */,
NULL /* set_freq */,
NULL /* set_rts */,
NULL /* set_frag */,
NULL /* set_retry */,
NULL /* sta_set_flags */,
NULL /* set_rate_sets */,
NULL /* hapd_set_country */,
NULL /* set_ieee80211d */,
NULL /* hapd_set_beacon */,
NULL /* set_internal_bridge */,
NULL /* hapd_set_beacon_int */,
NULL /* set_broadcast_ssid */,
NULL /* set_cts_protect */,
NULL /* set_preamble */,
NULL /* set_short_slot_time */,
NULL /* set_tx_queue_params */,
NULL /* bss_add */,
NULL /* bss_remove */,
NULL /* valid_bss_mask */,
NULL /* passive_scan */,
NULL /* hapd_get_hw_feature_data */,
NULL /* if_add */,
NULL /* if_update */,
NULL /* if_remove */,
NULL /* set_sta_vlan */,
NULL /* commit */,
NULL /* send_ether */,
NULL /* set_radius_acl_auth */,
NULL /* set_radius_acl_expire */,
NULL /* set_ht_params */,
NULL /* set_wps_beacon_ie */,
NULL /* set_wps_probe_resp_ie */,
NULL /* get_neighbor_bss */
}; };
struct wpa_driver_ops *wpa_supplicant_drivers[] = struct wpa_driver_ops *wpa_drivers[] =
{ {
&wpa_driver_privsep_ops, &wpa_driver_privsep_ops,
NULL NULL

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
/* /*
* WPA Supplicant - wired Ethernet driver interface * WPA Supplicant - wired Ethernet driver interface
* Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@ -17,6 +18,8 @@
#include <net/if.h> #include <net/if.h>
#ifdef __linux__ #ifdef __linux__
#include <netpacket/packet.h> #include <netpacket/packet.h>
#include <net/if_arp.h>
#include <net/if.h>
#endif /* __linux__ */ #endif /* __linux__ */
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#include <net/if_dl.h> #include <net/if_dl.h>
@ -25,19 +28,352 @@
#include "common.h" #include "common.h"
#include "driver.h" #include "driver.h"
#ifdef HOSTAPD
#include "eloop.h"
#include "../../hostapd/hostapd.h"
#include "../../hostapd/config.h"
#include "../../hostapd/sta_info.h"
#include "../../hostapd/accounting.h"
#endif /* HOSTAPD */
static const u8 pae_group_addr[ETH_ALEN] = static const u8 pae_group_addr[ETH_ALEN] =
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
struct wpa_driver_wired_data { struct wpa_driver_wired_data {
#ifdef HOSTAPD
struct hostapd_data *hapd;
char iface[IFNAMSIZ + 1];
int sock; /* raw packet socket for driver access */
int dhcp_sock; /* socket for dhcp packets */
int use_pae_group_addr;
#else /* HOSTAPD */
void *ctx; void *ctx;
int pf_sock; int pf_sock;
char ifname[IFNAMSIZ + 1]; char ifname[IFNAMSIZ + 1];
int membership, multi, iff_allmulti, iff_up; int membership, multi, iff_allmulti, iff_up;
#endif /* HOSTAPD */
}; };
#ifdef HOSTAPD
/* TODO: detecting new devices should eventually be changed from using DHCP
* snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
* based on ebtables, etc. */
struct dhcp_message {
u_int8_t op;
u_int8_t htype;
u_int8_t hlen;
u_int8_t hops;
u_int32_t xid;
u_int16_t secs;
u_int16_t flags;
u_int32_t ciaddr;
u_int32_t yiaddr;
u_int32_t siaddr;
u_int32_t giaddr;
u_int8_t chaddr[16];
u_int8_t sname[64];
u_int8_t file[128];
u_int32_t cookie;
u_int8_t options[308]; /* 312 - cookie */
};
static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr)
{
struct sta_info *sta;
sta = ap_get_sta(hapd, addr);
if (sta)
return;
wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
" - adding a new STA", MAC2STR(addr));
sta = ap_sta_add(hapd, addr);
if (sta) {
hostapd_new_assoc_sta(hapd, sta, 0);
} else {
wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
MAC2STR(addr));
}
}
static void handle_data(struct hostapd_data *hapd, unsigned char *buf,
size_t len)
{
struct ieee8023_hdr *hdr;
u8 *pos, *sa;
size_t left;
/* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
* 2 byte ethertype */
if (len < 14) {
wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
(unsigned long) len);
return;
}
hdr = (struct ieee8023_hdr *) buf;
switch (ntohs(hdr->ethertype)) {
case ETH_P_PAE:
wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
sa = hdr->src;
wired_possible_new_sta(hapd, sa);
pos = (u8 *) (hdr + 1);
left = len - sizeof(*hdr);
hostapd_eapol_receive(hapd, sa, pos, left);
break;
default:
wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
ntohs(hdr->ethertype));
break;
}
}
static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
{
struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
int len;
unsigned char buf[3000];
len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv");
return;
}
handle_data(hapd, buf, len);
}
static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
{
struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
int len;
unsigned char buf[3000];
struct dhcp_message *msg;
u8 *mac_address;
len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv");
return;
}
/* must contain at least dhcp_message->chaddr */
if (len < 44) {
wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
return;
}
msg = (struct dhcp_message *) buf;
mac_address = (u8 *) &(msg->chaddr);
wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
MAC2STR(mac_address));
wired_possible_new_sta(hapd, mac_address);
}
static int wired_init_sockets(struct wpa_driver_wired_data *drv)
{
struct hostapd_data *hapd = drv->hapd;
struct ifreq ifr;
struct sockaddr_ll addr;
struct sockaddr_in addr2;
struct packet_mreq mreq;
int n = 1;
drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
if (drv->sock < 0) {
perror("socket[PF_PACKET,SOCK_RAW]");
return -1;
}
if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) {
printf("Could not register read socket\n");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
perror("ioctl(SIOCGIFINDEX)");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_ifindex = ifr.ifr_ifindex;
wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
addr.sll_ifindex);
if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
return -1;
}
/* filter multicast address */
memset(&mreq, 0, sizeof(mreq));
mreq.mr_ifindex = ifr.ifr_ifindex;
mreq.mr_type = PACKET_MR_MULTICAST;
mreq.mr_alen = 6;
memcpy(mreq.mr_address, pae_group_addr, mreq.mr_alen);
if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0) {
perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
perror("ioctl(SIOCGIFHWADDR)");
return -1;
}
if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
printf("Invalid HW-addr family 0x%04x\n",
ifr.ifr_hwaddr.sa_family);
return -1;
}
memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
/* setup dhcp listen socket for sta detection */
if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket call failed for dhcp");
return -1;
}
if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL))
{
printf("Could not register read socket\n");
return -1;
}
memset(&addr2, 0, sizeof(addr2));
addr2.sin_family = AF_INET;
addr2.sin_port = htons(67);
addr2.sin_addr.s_addr = INADDR_ANY;
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
sizeof(n)) == -1) {
perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
return -1;
}
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
sizeof(n)) == -1) {
perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->iface, IFNAMSIZ);
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
(char *) &ifr, sizeof(ifr)) < 0) {
perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
return -1;
}
if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
sizeof(struct sockaddr)) == -1) {
perror("bind");
return -1;
}
return 0;
}
static int wired_send_eapol(void *priv, const u8 *addr,
const u8 *data, size_t data_len, int encrypt,
const u8 *own_addr)
{
struct wpa_driver_wired_data *drv = priv;
struct ieee8023_hdr *hdr;
size_t len;
u8 *pos;
int res;
len = sizeof(*hdr) + data_len;
hdr = os_zalloc(len);
if (hdr == NULL) {
printf("malloc() failed for wired_send_eapol(len=%lu)\n",
(unsigned long) len);
return -1;
}
memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
ETH_ALEN);
memcpy(hdr->src, own_addr, ETH_ALEN);
hdr->ethertype = htons(ETH_P_PAE);
pos = (u8 *) (hdr + 1);
memcpy(pos, data, data_len);
res = send(drv->sock, (u8 *) hdr, len, 0);
free(hdr);
if (res < 0) {
perror("wired_send_eapol: send");
printf("wired_send_eapol - packet len: %lu - failed\n",
(unsigned long) len);
}
return res;
}
static void * wired_driver_hapd_init(struct hostapd_data *hapd)
{
struct wpa_driver_wired_data *drv;
drv = os_zalloc(sizeof(struct wpa_driver_wired_data));
if (drv == NULL) {
printf("Could not allocate memory for wired driver data\n");
return NULL;
}
drv->hapd = hapd;
os_strlcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
drv->use_pae_group_addr = hapd->conf->use_pae_group_addr;
if (wired_init_sockets(drv)) {
free(drv);
return NULL;
}
return drv;
}
static void wired_driver_hapd_deinit(void *priv)
{
struct wpa_driver_wired_data *drv = priv;
if (drv->sock >= 0)
close(drv->sock);
if (drv->dhcp_sock >= 0)
close(drv->dhcp_sock);
free(drv);
}
#else /* HOSTAPD */
static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid) static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
{ {
ssid[0] = 0; ssid[0] = 0;
@ -273,14 +609,21 @@ static void wpa_driver_wired_deinit(void *priv)
os_free(drv); os_free(drv);
} }
#endif /* HOSTAPD */
const struct wpa_driver_ops wpa_driver_wired_ops = { const struct wpa_driver_ops wpa_driver_wired_ops = {
.name = "wired", .name = "wired",
.desc = "wpa_supplicant wired Ethernet driver", .desc = "Wired Ethernet driver",
#ifdef HOSTAPD
.hapd_init = wired_driver_hapd_init,
.hapd_deinit = wired_driver_hapd_deinit,
.hapd_send_eapol = wired_send_eapol,
#else /* HOSTAPD */
.get_ssid = wpa_driver_wired_get_ssid, .get_ssid = wpa_driver_wired_get_ssid,
.get_bssid = wpa_driver_wired_get_bssid, .get_bssid = wpa_driver_wired_get_bssid,
.get_capa = wpa_driver_wired_get_capa, .get_capa = wpa_driver_wired_get_capa,
.init = wpa_driver_wired_init, .init = wpa_driver_wired_init,
.deinit = wpa_driver_wired_deinit, .deinit = wpa_driver_wired_deinit,
#endif /* HOSTAPD */
}; };

View file

@ -1,5 +1,5 @@
/* /*
* WPA Supplicant / driver interface list * Driver interface list
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -74,9 +74,18 @@ extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
/* driver_roboswitch.c */ /* driver_roboswitch.c */
extern struct wpa_driver_ops wpa_driver_roboswitch_ops; extern struct wpa_driver_ops wpa_driver_roboswitch_ops;
#endif /* CONFIG_DRIVER_ROBOSWITCH */ #endif /* CONFIG_DRIVER_ROBOSWITCH */
#ifdef CONFIG_DRIVER_ATHEROS
extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_NONE
extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
#endif /* CONFIG_DRIVER_NONE */
#ifdef CONFIG_AP
extern struct wpa_driver_ops ap_driver_ops; /* wpa_supplicant/ap.c */
#endif /* CONFIG_AP */
struct wpa_driver_ops *wpa_supplicant_drivers[] = struct wpa_driver_ops *wpa_drivers[] =
{ {
#ifdef CONFIG_DRIVER_WEXT #ifdef CONFIG_DRIVER_WEXT
&wpa_driver_wext_ops, &wpa_driver_wext_ops,
@ -135,5 +144,14 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] =
#ifdef CONFIG_DRIVER_ROBOSWITCH #ifdef CONFIG_DRIVER_ROBOSWITCH
&wpa_driver_roboswitch_ops, &wpa_driver_roboswitch_ops,
#endif /* CONFIG_DRIVER_ROBOSWITCH */ #endif /* CONFIG_DRIVER_ROBOSWITCH */
#ifdef CONFIG_DRIVER_ATHEROS
&wpa_driver_atheros_ops,
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_NONE
&wpa_driver_none_ops,
#endif /* CONFIG_DRIVER_NONE */
#ifdef CONFIG_AP
&ap_driver_ops,
#endif /* CONFIG_AP */
NULL NULL
}; };

View file

@ -18,7 +18,6 @@
#include "common.h" #include "common.h"
#include "../hostapd/hostapd.h" #include "../hostapd/hostapd.h"
#include "../hostapd/config.h" #include "../hostapd/config.h"
#include "../hostapd/driver.h"
#ifdef NEED_MLME #ifdef NEED_MLME
#include "../hostapd/ieee802_11.h" #include "../hostapd/ieee802_11.h"
#endif /* NEED_MLME */ #endif /* NEED_MLME */
@ -245,13 +244,13 @@ static struct hostapd_hw_modes *ap_driver_get_hw_feature_data(void *priv,
} }
static struct hapd_driver_ops ap_driver_ops = struct wpa_driver_ops ap_driver_ops =
{ {
.name = "wpa_supplicant", .name = "wpa_supplicant",
.init = ap_driver_init, .hapd_init = ap_driver_init,
.deinit = ap_driver_deinit, .hapd_deinit = ap_driver_deinit,
.send_ether = ap_driver_send_ether, .send_ether = ap_driver_send_ether,
.set_key = ap_driver_set_key, .hapd_set_key = ap_driver_set_key,
.get_seqnum = ap_driver_get_seqnum, .get_seqnum = ap_driver_get_seqnum,
.flush = ap_driver_flush, .flush = ap_driver_flush,
.read_sta_data = ap_driver_read_sta_data, .read_sta_data = ap_driver_read_sta_data,
@ -263,27 +262,35 @@ static struct hapd_driver_ops ap_driver_ops =
.sta_add = ap_driver_sta_add, .sta_add = ap_driver_sta_add,
.get_inact_sec = ap_driver_get_inact_sec, .get_inact_sec = ap_driver_get_inact_sec,
.set_freq = ap_driver_set_freq, .set_freq = ap_driver_set_freq,
.set_beacon = ap_driver_set_beacon, .hapd_set_beacon = ap_driver_set_beacon,
.set_beacon_int = ap_driver_set_beacon_int, .hapd_set_beacon_int = ap_driver_set_beacon_int,
.set_cts_protect = ap_driver_set_cts_protect, .set_cts_protect = ap_driver_set_cts_protect,
.set_preamble = ap_driver_set_preamble, .set_preamble = ap_driver_set_preamble,
.set_short_slot_time = ap_driver_set_short_slot_time, .set_short_slot_time = ap_driver_set_short_slot_time,
.set_tx_queue_params = ap_driver_set_tx_queue_params, .set_tx_queue_params = ap_driver_set_tx_queue_params,
.get_hw_feature_data = ap_driver_get_hw_feature_data, .hapd_get_hw_feature_data = ap_driver_get_hw_feature_data,
}; };
struct hapd_driver_ops *hostapd_drivers[] =
{
&ap_driver_ops,
NULL
};
extern struct wpa_driver_ops *wpa_drivers[];
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_ssid *ssid,
struct hostapd_config *conf) struct hostapd_config *conf)
{ {
struct hostapd_bss_config *bss = &conf->bss[0]; struct hostapd_bss_config *bss = &conf->bss[0];
int j;
for (j = 0; wpa_drivers[j]; j++) {
if (os_strcmp("wpa_supplicant", wpa_drivers[j]->name) == 0) {
conf->driver = wpa_drivers[j];
break;
}
}
if (conf->driver == NULL) {
wpa_printf(MSG_ERROR, "No AP driver ops found");
return -1;
}
os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface)); os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));

View file

@ -32,7 +32,7 @@
#include "wps/wps.h" #include "wps/wps.h"
#include "ibss_rsn.h" #include "ibss_rsn.h"
extern struct wpa_driver_ops *wpa_supplicant_drivers[]; extern struct wpa_driver_ops *wpa_drivers[];
static int wpa_supplicant_global_iface_list(struct wpa_global *global, static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len); char *buf, int len);
@ -1825,8 +1825,8 @@ static int wpa_supplicant_global_iface_list(struct wpa_global *global,
struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
char *pos, *end; char *pos, *end;
for (i = 0; wpa_supplicant_drivers[i]; i++) { for (i = 0; wpa_drivers[i]; i++) {
struct wpa_driver_ops *drv = wpa_supplicant_drivers[i]; struct wpa_driver_ops *drv = wpa_drivers[i];
if (drv->get_interfaces == NULL) if (drv->get_interfaces == NULL)
continue; continue;
tmp = drv->get_interfaces(global->drv_priv); tmp = drv->get_interfaces(global->drv_priv);

View file

@ -35,7 +35,7 @@
extern int wpa_debug_level; extern int wpa_debug_level;
extern int wpa_debug_show_keys; extern int wpa_debug_show_keys;
struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL }; struct wpa_driver_ops *wpa_drivers[] = { NULL };
struct extra_radius_attr { struct extra_radius_attr {

View file

@ -21,7 +21,7 @@
#include "wpa_supplicant_i.h" #include "wpa_supplicant_i.h"
#include "driver_i.h" #include "driver_i.h"
extern struct wpa_driver_ops *wpa_supplicant_drivers[]; extern struct wpa_driver_ops *wpa_drivers[];
static void usage(void) static void usage(void)
@ -41,10 +41,10 @@ static void usage(void)
"drivers:\n", "drivers:\n",
wpa_supplicant_version, wpa_supplicant_license); wpa_supplicant_version, wpa_supplicant_license);
for (i = 0; wpa_supplicant_drivers[i]; i++) { for (i = 0; wpa_drivers[i]; i++) {
printf(" %s = %s\n", printf(" %s = %s\n",
wpa_supplicant_drivers[i]->name, wpa_drivers[i]->name,
wpa_supplicant_drivers[i]->desc); wpa_drivers[i]->desc);
} }
#ifndef CONFIG_NO_STDOUT_DEBUG #ifndef CONFIG_NO_STDOUT_DEBUG
@ -79,8 +79,7 @@ static void usage(void)
printf("example:\n" printf("example:\n"
" wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n", " wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
wpa_supplicant_drivers[i] ? wpa_drivers[i] ? wpa_drivers[i]->name : "wext");
wpa_supplicant_drivers[i]->name : "wext");
#endif /* CONFIG_NO_STDOUT_DEBUG */ #endif /* CONFIG_NO_STDOUT_DEBUG */
} }

View file

@ -30,12 +30,13 @@
#include "pcsc_funcs.h" #include "pcsc_funcs.h"
#include "preauth.h" #include "preauth.h"
#include "pmksa_cache.h" #include "pmksa_cache.h"
#include "drivers/driver.h"
extern int wpa_debug_level; extern int wpa_debug_level;
extern int wpa_debug_show_keys; extern int wpa_debug_show_keys;
struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL }; struct wpa_driver_ops *wpa_drivers[] = { NULL };
struct preauth_test_data { struct preauth_test_data {

View file

@ -692,7 +692,7 @@ static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
} }
extern struct wpa_driver_ops *wpa_supplicant_drivers[]; extern struct wpa_driver_ops *wpa_drivers[];
static struct wpa_priv_interface * static struct wpa_priv_interface *
wpa_priv_interface_init(const char *dir, const char *params) wpa_priv_interface_init(const char *dir, const char *params)
@ -721,10 +721,10 @@ wpa_priv_interface_init(const char *dir, const char *params)
os_memcpy(iface->driver_name, params, len); os_memcpy(iface->driver_name, params, len);
iface->driver_name[len] = '\0'; iface->driver_name[len] = '\0';
for (i = 0; wpa_supplicant_drivers[i]; i++) { for (i = 0; wpa_drivers[i]; i++) {
if (os_strcmp(iface->driver_name, if (os_strcmp(iface->driver_name,
wpa_supplicant_drivers[i]->name) == 0) { wpa_drivers[i]->name) == 0) {
iface->driver = wpa_supplicant_drivers[i]; iface->driver = wpa_drivers[i];
break; break;
} }
} }

View file

@ -114,7 +114,7 @@ const char *wpa_supplicant_full_license5 =
extern int wpa_debug_level; extern int wpa_debug_level;
extern int wpa_debug_show_keys; extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp; extern int wpa_debug_timestamp;
extern struct wpa_driver_ops *wpa_supplicant_drivers[]; extern struct wpa_driver_ops *wpa_drivers[];
/* Configure default/group WEP keys for static WEP */ /* Configure default/group WEP keys for static WEP */
static int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, static int wpa_set_wep_keys(struct wpa_supplicant *wpa_s,
@ -1533,7 +1533,7 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
if (wpa_s == NULL) if (wpa_s == NULL)
return -1; return -1;
if (wpa_supplicant_drivers[0] == NULL) { if (wpa_drivers[0] == NULL) {
wpa_printf(MSG_ERROR, "No driver interfaces build into " wpa_printf(MSG_ERROR, "No driver interfaces build into "
"wpa_supplicant."); "wpa_supplicant.");
return -1; return -1;
@ -1541,7 +1541,7 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
if (name == NULL) { if (name == NULL) {
/* default to first driver in the list */ /* default to first driver in the list */
wpa_s->driver = wpa_supplicant_drivers[0]; wpa_s->driver = wpa_drivers[0];
return 0; return 0;
} }
@ -1550,11 +1550,11 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
len = pos - name; len = pos - name;
else else
len = os_strlen(name); len = os_strlen(name);
for (i = 0; wpa_supplicant_drivers[i]; i++) { for (i = 0; wpa_drivers[i]; i++) {
if (os_strlen(wpa_supplicant_drivers[i]->name) == len && if (os_strlen(wpa_drivers[i]->name) == len &&
os_strncmp(name, wpa_supplicant_drivers[i]->name, len) == os_strncmp(name, wpa_drivers[i]->name, len) ==
0) { 0) {
wpa_s->driver = wpa_supplicant_drivers[i]; wpa_s->driver = wpa_drivers[i];
return 0; return 0;
} }
} }
@ -2159,7 +2159,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
} }
} }
for (i = 0; wpa_supplicant_drivers[i]; i++) for (i = 0; wpa_drivers[i]; i++)
global->drv_count++; global->drv_count++;
if (global->drv_count == 0) { if (global->drv_count == 0) {
wpa_printf(MSG_ERROR, "No drivers enabled"); wpa_printf(MSG_ERROR, "No drivers enabled");
@ -2171,13 +2171,13 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
wpa_supplicant_deinit(global); wpa_supplicant_deinit(global);
return NULL; return NULL;
} }
for (i = 0; wpa_supplicant_drivers[i]; i++) { for (i = 0; wpa_drivers[i]; i++) {
if (!wpa_supplicant_drivers[i]->global_init) if (!wpa_drivers[i]->global_init)
continue; continue;
global->drv_priv[i] = wpa_supplicant_drivers[i]->global_init(); global->drv_priv[i] = wpa_drivers[i]->global_init();
if (global->drv_priv[i] == NULL) { if (global->drv_priv[i] == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize driver " wpa_printf(MSG_ERROR, "Failed to initialize driver "
"'%s'", wpa_supplicant_drivers[i]->name); "'%s'", wpa_drivers[i]->name);
wpa_supplicant_deinit(global); wpa_supplicant_deinit(global);
return NULL; return NULL;
} }
@ -2244,10 +2244,10 @@ void wpa_supplicant_deinit(struct wpa_global *global)
eap_peer_unregister_methods(); eap_peer_unregister_methods();
for (i = 0; wpa_supplicant_drivers[i] && global->drv_priv; i++) { for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
if (!global->drv_priv[i]) if (!global->drv_priv[i])
continue; continue;
wpa_supplicant_drivers[i]->global_deinit(global->drv_priv[i]); wpa_drivers[i]->global_deinit(global->drv_priv[i]);
} }
os_free(global->drv_priv); os_free(global->drv_priv);