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.master
parent
c2220ec0b7
commit
c51218372f
@ -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 */
|
@ -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
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
@ -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,
|
||||
};
|
@ -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
|
||||
};
|
@ -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 */
|
@ -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 */
|
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
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue