Skip to content

Commit

Permalink
mac80211: 802.11w - SA Query processing
Browse files Browse the repository at this point in the history
Process SA Query Requests for client mode in mac80211. AP side
processing of SA Query Response frames is in user space (hostapd).

Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Jouni Malinen authored and John W. Linville committed Jan 29, 2009
1 parent fdfacf0 commit fea1473
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
14 changes: 14 additions & 0 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,8 @@ struct ieee80211_tim_ie {
u8 virtual_map[0];
} __attribute__ ((packed));

#define WLAN_SA_QUERY_TR_ID_LEN 16

struct ieee80211_mgmt {
__le16 frame_control;
__le16 duration;
Expand Down Expand Up @@ -646,6 +648,10 @@ struct ieee80211_mgmt {
u8 action_code;
u8 variable[0];
} __attribute__((packed)) mesh_action;
struct {
u8 action;
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} __attribute__ ((packed)) sa_query;
} u;
} __attribute__ ((packed)) action;
} u;
Expand Down Expand Up @@ -1041,6 +1047,7 @@ enum ieee80211_category {
WLAN_CATEGORY_DLS = 2,
WLAN_CATEGORY_BACK = 3,
WLAN_CATEGORY_PUBLIC = 4,
WLAN_CATEGORY_SA_QUERY = 8,
WLAN_CATEGORY_WMM = 17,
};

Expand Down Expand Up @@ -1129,6 +1136,13 @@ enum ieee80211_back_parties {
WLAN_BACK_TIMER = 2,
};

/* SA Query action */
enum ieee80211_sa_query_action {
WLAN_ACTION_SA_QUERY_REQUEST = 0,
WLAN_ACTION_SA_QUERY_RESPONSE = 1,
};


/* A-MSDU 802.11n */
#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080

Expand Down
69 changes: 69 additions & 0 deletions net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,57 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
}

void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len)
{
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *resp;

if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) {
/* Not to own unicast address */
return;
}

if (compare_ether_addr(mgmt->sa, sdata->u.sta.bssid) != 0 ||
compare_ether_addr(mgmt->bssid, sdata->u.sta.bssid) != 0) {
/* Not from the current AP. */
return;
}

if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATE) {
/* Association in progress; ignore SA Query */
return;
}

if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) {
/* Too short SA Query request frame */
return;
}

skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom);
if (skb == NULL)
return;

skb_reserve(skb, local->hw.extra_tx_headroom);
resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(resp, 0, 24);
memcpy(resp->da, mgmt->sa, ETH_ALEN);
memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(resp->bssid, sdata->u.sta.bssid, ETH_ALEN);
resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));
resp->u.action.category = WLAN_CATEGORY_SA_QUERY;
resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE;
memcpy(resp->u.action.u.sa_query.trans_id,
mgmt->u.action.u.sa_query.trans_id,
WLAN_SA_QUERY_TR_ID_LEN);

ieee80211_tx_skb(sdata, skb, 1);
}

static ieee80211_rx_result debug_noinline
ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
{
Expand Down Expand Up @@ -1743,6 +1794,24 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
}
break;
case WLAN_CATEGORY_SA_QUERY:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.sa_query)))
return RX_DROP_MONITOR;
switch (mgmt->u.action.u.sa_query.action) {
case WLAN_ACTION_SA_QUERY_REQUEST:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return RX_DROP_MONITOR;
ieee80211_process_sa_query_req(sdata, mgmt, len);
break;
case WLAN_ACTION_SA_QUERY_RESPONSE:
/*
* SA Query response is currently only used in AP mode
* and it is processed in user space.
*/
return RX_CONTINUE;
}
break;
default:
return RX_CONTINUE;
}
Expand Down

0 comments on commit fea1473

Please sign in to comment.