2 * Generic advertisement service (GAS) (IEEE 802.11u)
3 * Copyright (c) 2009, Atheros Communications
4 * Copyright (c) 2011, Qualcomm Atheros
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
19 #include "ieee802_11_defs.h"
23 static struct wpabuf
*
24 gas_build_req(u8 action
, u8 dialog_token
, size_t size
)
28 buf
= wpabuf_alloc(100 + size
);
32 wpabuf_put_u8(buf
, WLAN_ACTION_PUBLIC
);
33 wpabuf_put_u8(buf
, action
);
34 wpabuf_put_u8(buf
, dialog_token
);
40 static struct wpabuf
* gas_build_initial_req(u8 dialog_token
, size_t size
)
42 return gas_build_req(WLAN_PA_GAS_INITIAL_REQ
, dialog_token
,
47 struct wpabuf
* gas_build_comeback_req(u8 dialog_token
)
49 return gas_build_req(WLAN_PA_GAS_COMEBACK_REQ
, dialog_token
, 0);
53 static struct wpabuf
*
54 gas_build_resp(u8 action
, u8 dialog_token
, u16 status_code
, u8 frag_id
,
55 u8 more
, u16 comeback_delay
, size_t size
)
59 buf
= wpabuf_alloc(100 + size
);
63 wpabuf_put_u8(buf
, WLAN_ACTION_PUBLIC
);
64 wpabuf_put_u8(buf
, action
);
65 wpabuf_put_u8(buf
, dialog_token
);
66 wpabuf_put_le16(buf
, status_code
);
67 if (action
== WLAN_PA_GAS_COMEBACK_RESP
)
68 wpabuf_put_u8(buf
, frag_id
| (more
? 0x80 : 0));
69 wpabuf_put_le16(buf
, comeback_delay
);
76 gas_build_initial_resp(u8 dialog_token
, u16 status_code
, u16 comeback_delay
,
79 return gas_build_resp(WLAN_PA_GAS_INITIAL_RESP
, dialog_token
,
80 status_code
, 0, 0, comeback_delay
, size
);
84 static struct wpabuf
*
85 gas_build_comeback_resp(u8 dialog_token
, u16 status_code
, u8 frag_id
, u8 more
,
86 u16 comeback_delay
, size_t size
)
88 return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP
, dialog_token
,
89 status_code
, frag_id
, more
, comeback_delay
,
95 * gas_add_adv_proto_anqp - Add an Advertisement Protocol element
96 * @buf: Buffer to which the element is added
97 * @query_resp_len_limit: Query Response Length Limit in units of 256 octets
98 * @pame_bi: Pre-Association Message Exchange BSSID Independent (0/1)
101 * @query_resp_len_limit is 0 for request and 1-0x7f for response. 0x7f means
102 * that the maximum limit is determined by the maximum allowable number of
103 * fragments in the GAS Query Response Fragment ID.
105 static void gas_add_adv_proto_anqp(struct wpabuf
*buf
, u8 query_resp_len_limit
,
108 /* Advertisement Protocol IE */
109 wpabuf_put_u8(buf
, WLAN_EID_ADV_PROTO
);
110 wpabuf_put_u8(buf
, 2); /* Length */
111 wpabuf_put_u8(buf
, (query_resp_len_limit
& 0x7f) |
112 (pame_bi
? 0x80 : 0));
113 /* Advertisement Protocol */
114 wpabuf_put_u8(buf
, ACCESS_NETWORK_QUERY_PROTOCOL
);
118 struct wpabuf
* gas_anqp_build_initial_req(u8 dialog_token
, size_t size
)
122 buf
= gas_build_initial_req(dialog_token
, 4 + size
);
126 gas_add_adv_proto_anqp(buf
, 0, 0);
128 wpabuf_put(buf
, 2); /* Query Request Length to be filled */
134 struct wpabuf
* gas_anqp_build_initial_resp(u8 dialog_token
, u16 status_code
,
135 u16 comeback_delay
, size_t size
)
139 buf
= gas_build_initial_resp(dialog_token
, status_code
, comeback_delay
,
144 gas_add_adv_proto_anqp(buf
, 0x7f, 0);
146 wpabuf_put(buf
, 2); /* Query Response Length to be filled */
152 struct wpabuf
* gas_anqp_build_initial_resp_buf(u8 dialog_token
,
155 struct wpabuf
*payload
)
159 buf
= gas_anqp_build_initial_resp(dialog_token
, status_code
,
161 payload
? wpabuf_len(payload
) : 0);
166 wpabuf_put_buf(buf
, payload
);
168 gas_anqp_set_len(buf
);
174 struct wpabuf
* gas_anqp_build_comeback_resp(u8 dialog_token
, u16 status_code
,
176 u16 comeback_delay
, size_t size
)
180 buf
= gas_build_comeback_resp(dialog_token
, status_code
,
181 frag_id
, more
, comeback_delay
, 4 + size
);
185 gas_add_adv_proto_anqp(buf
, 0x7f, 0);
187 wpabuf_put(buf
, 2); /* Query Response Length to be filled */
193 struct wpabuf
* gas_anqp_build_comeback_resp_buf(u8 dialog_token
,
197 struct wpabuf
*payload
)
201 buf
= gas_anqp_build_comeback_resp(dialog_token
, status_code
, frag_id
,
202 more
, comeback_delay
,
203 payload
? wpabuf_len(payload
) : 0);
208 wpabuf_put_buf(buf
, payload
);
210 gas_anqp_set_len(buf
);
217 * gas_anqp_set_len - Set Query Request/Response Length
220 * This function is used to update the Query Request/Response Length field once
221 * the payload has been filled.
223 void gas_anqp_set_len(struct wpabuf
*buf
)
229 if (buf
== NULL
|| wpabuf_len(buf
) < 2)
232 action
= *(wpabuf_head_u8(buf
) + 1);
234 case WLAN_PA_GAS_INITIAL_REQ
:
237 case WLAN_PA_GAS_INITIAL_RESP
:
240 case WLAN_PA_GAS_COMEBACK_RESP
:
247 if (wpabuf_len(buf
) < offset
+ 2)
250 len
= wpabuf_mhead_u8(buf
) + offset
;
251 WPA_PUT_LE16(len
, (u8
*) wpabuf_put(buf
, 0) - len
- 2);
256 * gas_anqp_add_element - Add ANQP element header
258 * @info_id: ANQP Info ID
259 * Returns: Pointer to the Length field for gas_anqp_set_element_len()
261 u8
* gas_anqp_add_element(struct wpabuf
*buf
, u16 info_id
)
263 wpabuf_put_le16(buf
, info_id
);
264 return wpabuf_put(buf
, 2); /* Length to be filled */
269 * gas_anqp_set_element_len - Update ANQP element Length field
271 * @len_pos: Length field position from gas_anqp_add_element()
273 * This function is called after the ANQP element payload has been added to the
276 void gas_anqp_set_element_len(struct wpabuf
*buf
, u8
*len_pos
)
278 WPA_PUT_LE16(len_pos
, (u8
*) wpabuf_put(buf
, 0) - len_pos
- 2);