nl80211: Merge handle_frame() implementations

This commit is contained in:
Jouni Malinen 2009-04-14 15:35:03 +03:00 committed by Jouni Malinen
parent f019981aee
commit 7da3abe711

View file

@ -111,25 +111,25 @@ struct wpa_driver_nl80211_data {
u8 ssid[32]; u8 ssid[32];
size_t ssid_len; size_t ssid_len;
#ifdef CONFIG_AP #if defined(CONFIG_AP) || defined(HOSTAPD)
int beacon_int; int beacon_int;
unsigned int beacon_set:1;
int monitor_sock; int monitor_sock;
int monitor_ifidx; int monitor_ifidx;
#endif /* CONFIG_AP || HOSTAPD */
#ifdef CONFIG_AP
unsigned int beacon_set:1;
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
#ifdef HOSTAPD #ifdef HOSTAPD
struct hostapd_data *hapd; struct hostapd_data *hapd;
int eapol_sock; /* socket for EAPOL frames */ int eapol_sock; /* socket for EAPOL frames */
int monitor_sock; /* socket for monitor */
int monitor_ifidx;
int default_if_indices[16]; int default_if_indices[16];
int *if_indices; int *if_indices;
int num_if_indices; int num_if_indices;
int beacon_int;
struct i802_bss bss; struct i802_bss bss;
unsigned int ht_40mhz_scan:1; unsigned int ht_40mhz_scan:1;
@ -154,10 +154,6 @@ static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
#ifdef HOSTAPD #ifdef HOSTAPD
static void handle_frame(struct wpa_driver_nl80211_data *drv,
u8 *buf, size_t len,
struct hostapd_frame_info *hfi,
enum ieee80211_msg_type msg_type);
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv, static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv,
@ -338,13 +334,13 @@ static int wpa_driver_nl80211_send_oper_ifla(
RTA_LENGTH(sizeof(char)); RTA_LENGTH(sizeof(char));
} }
wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d", wpa_printf(MSG_DEBUG, "nl80211: Operstate: linkmode=%d, operstate=%d",
linkmode, operstate); linkmode, operstate);
ret = send(drv->link_event_sock, &req, req.hdr.nlmsg_len, 0); ret = send(drv->link_event_sock, &req, req.hdr.nlmsg_len, 0);
if (ret < 0) { if (ret < 0) {
wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: " wpa_printf(MSG_DEBUG, "nl80211: Sending operstate IFLA failed:"
"%s (assume operstate is not supported)", " %s (assume operstate is not supported)",
strerror(errno)); strerror(errno));
} }
@ -2330,9 +2326,6 @@ static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)
} }
} }
#endif /* CONFIG_AP || HOSTAPD */
#ifdef CONFIG_AP
static void handle_frame(struct wpa_driver_nl80211_data *drv, static void handle_frame(struct wpa_driver_nl80211_data *drv,
u8 *buf, size_t len, u8 *buf, size_t len,
@ -2342,6 +2335,14 @@ static void handle_frame(struct wpa_driver_nl80211_data *drv,
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
u16 fc, type, stype; u16 fc, type, stype;
size_t data_len = len; size_t data_len = len;
u8 *bssid;
void *ctx = drv->ctx;
#ifdef HOSTAPD
struct hostapd_iface *iface = drv->hapd->iface;
struct hostapd_data *hapd = NULL;
int broadcast_bssid = 0;
size_t i;
#endif /* HOSTAPD */
/* /*
* PS-Poll frames are 16 bytes. All other frames are * PS-Poll frames are 16 bytes. All other frames are
@ -2362,8 +2363,10 @@ static void handle_frame(struct wpa_driver_nl80211_data *drv,
return; return;
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
case WLAN_FC_TODS: case WLAN_FC_TODS:
bssid = hdr->addr1;
break; break;
case WLAN_FC_FROMDS: case WLAN_FC_FROMDS:
bssid = hdr->addr2;
break; break;
default: default:
/* discard */ /* discard */
@ -2374,23 +2377,55 @@ static void handle_frame(struct wpa_driver_nl80211_data *drv,
/* discard non-ps-poll frames */ /* discard non-ps-poll frames */
if (stype != WLAN_FC_STYPE_PSPOLL) if (stype != WLAN_FC_STYPE_PSPOLL)
return; return;
bssid = hdr->addr1;
break; break;
case WLAN_FC_TYPE_MGMT: case WLAN_FC_TYPE_MGMT:
bssid = hdr->addr3;
break; break;
default: default:
/* discard */ /* discard */
return; return;
} }
#ifdef HOSTAPD
/* find interface frame belongs to */
for (i = 0; i < iface->num_bss; i++) {
if (memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) {
hapd = iface->bss[i];
break;
}
}
if (hapd == NULL) {
hapd = iface->bss[0];
if (bssid[0] != 0xff || bssid[1] != 0xff ||
bssid[2] != 0xff || bssid[3] != 0xff ||
bssid[4] != 0xff || bssid[5] != 0xff) {
/*
* Unknown BSSID - drop frame if this is not from
* passive scanning or a beacon (at least ProbeReq
* frames to other APs may be allowed through RX
* filtering in the wlan hw/driver)
*/
if ((type != WLAN_FC_TYPE_MGMT ||
stype != WLAN_FC_STYPE_BEACON))
return;
} else
broadcast_bssid = 1;
}
ctx = hapd;
#endif /* HOSTAPD */
switch (msg_type) { switch (msg_type) {
case ieee80211_msg_normal: case ieee80211_msg_normal:
/* continue processing */ /* continue processing */
break; break;
case ieee80211_msg_tx_callback_ack: case ieee80211_msg_tx_callback_ack:
handle_tx_callback(drv->ctx, buf, data_len, 1); handle_tx_callback(ctx, buf, data_len, 1);
return; return;
case ieee80211_msg_tx_callback_fail: case ieee80211_msg_tx_callback_fail:
handle_tx_callback(drv->ctx, buf, data_len, 0); handle_tx_callback(ctx, buf, data_len, 0);
return; return;
} }
@ -2399,22 +2434,36 @@ static void handle_frame(struct wpa_driver_nl80211_data *drv,
if (stype != WLAN_FC_STYPE_BEACON && if (stype != WLAN_FC_STYPE_BEACON &&
stype != WLAN_FC_STYPE_PROBE_REQ) stype != WLAN_FC_STYPE_PROBE_REQ)
wpa_printf(MSG_MSGDUMP, "MGMT"); wpa_printf(MSG_MSGDUMP, "MGMT");
#ifdef HOSTAPD
if (broadcast_bssid) {
for (i = 0; i < iface->num_bss; i++)
hostapd_mgmt_rx(iface->bss[i], buf, data_len,
stype, hfi);
} else
hostapd_mgmt_rx(hapd, buf, data_len, stype, hfi);
#else /* HOSTAPD */
ap_mgmt_rx(drv->ctx, buf, data_len, stype, hfi); ap_mgmt_rx(drv->ctx, buf, data_len, stype, hfi);
#endif /* HOSTAPD */
break; break;
case WLAN_FC_TYPE_CTRL: case WLAN_FC_TYPE_CTRL:
/* can only get here with PS-Poll frames */ /* can only get here with PS-Poll frames */
wpa_printf(MSG_DEBUG, "CTRL"); wpa_printf(MSG_DEBUG, "CTRL");
#ifdef HOSTAPD
hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2);
#else /* HOSTAPD */
ap_rx_from_unknown_sta(drv->ctx, hdr->addr2); ap_rx_from_unknown_sta(drv->ctx, hdr->addr2);
#endif /* HOSTAPD */
break; break;
case WLAN_FC_TYPE_DATA: case WLAN_FC_TYPE_DATA:
#ifdef HOSTAPD
hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2);
#else /* HOSTAPD */
ap_rx_from_unknown_sta(drv->ctx, hdr->addr2); ap_rx_from_unknown_sta(drv->ctx, hdr->addr2);
#endif /* HOSTAPD */
break; break;
} }
} }
#endif /* CONFIG_AP */
#if defined(CONFIG_AP) || defined(HOSTAPD)
static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
{ {
@ -3651,126 +3700,6 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
} }
static void handle_frame(struct wpa_driver_nl80211_data *drv,
u8 *buf, size_t len,
struct hostapd_frame_info *hfi,
enum ieee80211_msg_type msg_type)
{
struct hostapd_iface *iface = drv->hapd->iface;
struct ieee80211_hdr *hdr;
u16 fc, type, stype;
size_t data_len = len;
struct hostapd_data *hapd = NULL;
int broadcast_bssid = 0;
size_t i;
u8 *bssid;
/*
* PS-Poll frames are 16 bytes. All other frames are
* 24 bytes or longer.
*/
if (len < 16)
return;
hdr = (struct ieee80211_hdr *) buf;
fc = le_to_host16(hdr->frame_control);
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
switch (type) {
case WLAN_FC_TYPE_DATA:
if (len < 24)
return;
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
case WLAN_FC_TODS:
bssid = hdr->addr1;
break;
case WLAN_FC_FROMDS:
bssid = hdr->addr2;
break;
default:
/* discard */
return;
}
break;
case WLAN_FC_TYPE_CTRL:
/* discard non-ps-poll frames */
if (stype != WLAN_FC_STYPE_PSPOLL)
return;
bssid = hdr->addr1;
break;
case WLAN_FC_TYPE_MGMT:
bssid = hdr->addr3;
break;
default:
/* discard */
return;
}
/* find interface frame belongs to */
for (i = 0; i < iface->num_bss; i++) {
if (memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) {
hapd = iface->bss[i];
break;
}
}
if (hapd == NULL) {
hapd = iface->bss[0];
if (bssid[0] != 0xff || bssid[1] != 0xff ||
bssid[2] != 0xff || bssid[3] != 0xff ||
bssid[4] != 0xff || bssid[5] != 0xff) {
/*
* Unknown BSSID - drop frame if this is not from
* passive scanning or a beacon (at least ProbeReq
* frames to other APs may be allowed through RX
* filtering in the wlan hw/driver)
*/
if ((type != WLAN_FC_TYPE_MGMT ||
stype != WLAN_FC_STYPE_BEACON))
return;
} else
broadcast_bssid = 1;
}
switch (msg_type) {
case ieee80211_msg_normal:
/* continue processing */
break;
case ieee80211_msg_tx_callback_ack:
handle_tx_callback(hapd, buf, data_len, 1);
return;
case ieee80211_msg_tx_callback_fail:
handle_tx_callback(hapd, buf, data_len, 0);
return;
}
switch (type) {
case WLAN_FC_TYPE_MGMT:
if (stype != WLAN_FC_STYPE_BEACON &&
stype != WLAN_FC_STYPE_PROBE_REQ)
wpa_printf(MSG_MSGDUMP, "MGMT");
if (broadcast_bssid) {
for (i = 0; i < iface->num_bss; i++)
hostapd_mgmt_rx(iface->bss[i], buf, data_len,
stype, hfi);
} else
hostapd_mgmt_rx(hapd, buf, data_len, stype, hfi);
break;
case WLAN_FC_TYPE_CTRL:
/* can only get here with PS-Poll frames */
wpa_printf(MSG_DEBUG, "CTRL");
hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2);
break;
case WLAN_FC_TYPE_DATA:
hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2);
break;
}
}
static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
{ {
struct wpa_driver_nl80211_data *drv = eloop_ctx; struct wpa_driver_nl80211_data *drv = eloop_ctx;