2 * hostapd / IEEE 802.11 Management
3 * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
17 #include "utils/common.h"
18 #include "common/ieee802_11_defs.h"
21 #include "ap_config.h"
22 #include "ap_drv_ops.h"
25 #ifdef CONFIG_IEEE80211W
27 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
28 struct sta_info *sta, u8 *eid)
32 struct os_time now, passed;
34 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
36 *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
38 os_time_sub(&now, &sta->sa_query_start, &passed);
39 tu = (passed.sec * 1000000 + passed.usec) / 1024;
40 if (hapd->conf->assoc_sa_query_max_timeout > tu)
41 timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
44 if (timeout < hapd->conf->assoc_sa_query_max_timeout)
45 timeout++; /* add some extra time for local timers */
46 WPA_PUT_LE32(pos, timeout);
53 /* MLME-SAQuery.request */
54 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
55 const u8 *addr, const u8 *trans_id)
57 struct ieee80211_mgmt mgmt;
60 wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
61 MACSTR, MAC2STR(addr));
62 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
63 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
65 os_memset(&mgmt, 0, sizeof(mgmt));
66 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
67 WLAN_FC_STYPE_ACTION);
68 os_memcpy(mgmt.da, addr, ETH_ALEN);
69 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
70 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
71 mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
72 mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
73 os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
74 WLAN_SA_QUERY_TR_ID_LEN);
75 end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
76 if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
77 perror("ieee802_11_send_sa_query_req: send");
81 void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
82 const u8 *sa, const u8 *trans_id)
85 struct ieee80211_mgmt resp;
88 wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
90 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
91 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
93 sta = ap_get_sta(hapd, sa);
94 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
95 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
96 "from unassociated STA " MACSTR, MAC2STR(sa));
100 wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
101 MACSTR, MAC2STR(sa));
103 os_memset(&resp, 0, sizeof(resp));
104 resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
105 WLAN_FC_STYPE_ACTION);
106 os_memcpy(resp.da, sa, ETH_ALEN);
107 os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
108 os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
109 resp.u.action.category = WLAN_ACTION_SA_QUERY;
110 resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
111 os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
112 WLAN_SA_QUERY_TR_ID_LEN);
113 end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
114 if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp) < 0)
115 perror("ieee80211_mgmt_sa_query_request: send");
119 void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
120 const u8 action_type, const u8 *trans_id)
122 struct sta_info *sta;
125 if (action_type == WLAN_SA_QUERY_REQUEST) {
126 ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
130 if (action_type != WLAN_SA_QUERY_RESPONSE) {
131 wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
132 "Action %d", action_type);
136 wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
137 MACSTR, MAC2STR(sa));
138 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
139 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
141 /* MLME-SAQuery.confirm */
143 sta = ap_get_sta(hapd, sa);
144 if (sta == NULL || sta->sa_query_trans_id == NULL) {
145 wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
146 "pending SA Query request found");
150 for (i = 0; i < sta->sa_query_count; i++) {
151 if (os_memcmp(sta->sa_query_trans_id +
152 i * WLAN_SA_QUERY_TR_ID_LEN,
153 trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
157 if (i >= sta->sa_query_count) {
158 wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
159 "transaction identifier found");
163 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
165 "Reply to pending SA Query received");
166 ap_sta_stop_sa_query(hapd, sta);
169 #endif /* CONFIG_IEEE80211W */
172 u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
177 if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
179 if (len < 4 && hapd->conf->interworking)
184 *pos++ = WLAN_EID_EXT_CAPAB;
191 if (hapd->conf->interworking)
192 *pos |= 0x80; /* Bit 31 - Interworking */
198 if (hapd->conf->tdls & TDLS_PROHIBIT)
199 *pos |= 0x40; /* Bit 38 - TDLS Prohibited */
200 if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH)
201 *pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
208 u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
211 #ifdef CONFIG_INTERWORKING
214 if (!hapd->conf->interworking)
217 *pos++ = WLAN_EID_INTERWORKING;
220 *pos = hapd->conf->access_network_type;
221 if (hapd->conf->internet)
222 *pos |= INTERWORKING_ANO_INTERNET;
223 if (hapd->conf->asra)
224 *pos |= INTERWORKING_ANO_ASRA;
226 *pos |= INTERWORKING_ANO_ESR;
227 if (hapd->conf->uesa)
228 *pos |= INTERWORKING_ANO_UESA;
231 if (hapd->conf->venue_info_set) {
232 *pos++ = hapd->conf->venue_group;
233 *pos++ = hapd->conf->venue_type;
236 if (!is_zero_ether_addr(hapd->conf->hessid)) {
237 os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
241 *len = pos - len - 1;
242 #endif /* CONFIG_INTERWORKING */