3 * Copyright (c) 2009-2010, Atheros Communications
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.
18 #include "common/ieee802_11_defs.h"
19 #include "wps/wps_i.h"
23 void p2p_buf_add_action_hdr(struct wpabuf
*buf
, u8 subtype
, u8 dialog_token
)
25 wpabuf_put_u8(buf
, WLAN_ACTION_VENDOR_SPECIFIC
);
26 wpabuf_put_be24(buf
, OUI_WFA
);
27 wpabuf_put_u8(buf
, P2P_OUI_TYPE
);
29 wpabuf_put_u8(buf
, subtype
); /* OUI Subtype */
30 wpabuf_put_u8(buf
, dialog_token
);
31 wpa_printf(MSG_DEBUG
, "P2P: * Dialog Token: %d", dialog_token
);
35 void p2p_buf_add_public_action_hdr(struct wpabuf
*buf
, u8 subtype
,
38 wpabuf_put_u8(buf
, WLAN_ACTION_PUBLIC
);
39 wpabuf_put_u8(buf
, WLAN_PA_VENDOR_SPECIFIC
);
40 wpabuf_put_be24(buf
, OUI_WFA
);
41 wpabuf_put_u8(buf
, P2P_OUI_TYPE
);
43 wpabuf_put_u8(buf
, subtype
); /* OUI Subtype */
44 wpabuf_put_u8(buf
, dialog_token
);
45 wpa_printf(MSG_DEBUG
, "P2P: * Dialog Token: %d", dialog_token
);
49 u8
* p2p_buf_add_ie_hdr(struct wpabuf
*buf
)
54 wpabuf_put_u8(buf
, WLAN_EID_VENDOR_SPECIFIC
);
55 len
= wpabuf_put(buf
, 1); /* IE length to be filled */
56 wpabuf_put_be24(buf
, OUI_WFA
);
57 wpabuf_put_u8(buf
, P2P_OUI_TYPE
);
58 wpa_printf(MSG_DEBUG
, "P2P: * P2P IE header");
63 void p2p_buf_update_ie_hdr(struct wpabuf
*buf
, u8
*len
)
65 /* Update P2P IE Length */
66 *len
= (u8
*) wpabuf_put(buf
, 0) - len
- 1;
70 void p2p_buf_add_capability(struct wpabuf
*buf
, u8 dev_capab
, u8 group_capab
)
73 wpabuf_put_u8(buf
, P2P_ATTR_CAPABILITY
);
74 wpabuf_put_le16(buf
, 2);
75 wpabuf_put_u8(buf
, dev_capab
); /* Device Capabilities */
76 wpabuf_put_u8(buf
, group_capab
); /* Group Capabilities */
77 wpa_printf(MSG_DEBUG
, "P2P: * Capability dev=%02x group=%02x",
78 dev_capab
, group_capab
);
82 void p2p_buf_add_go_intent(struct wpabuf
*buf
, u8 go_intent
)
84 /* Group Owner Intent */
85 wpabuf_put_u8(buf
, P2P_ATTR_GROUP_OWNER_INTENT
);
86 wpabuf_put_le16(buf
, 1);
87 wpabuf_put_u8(buf
, go_intent
);
88 wpa_printf(MSG_DEBUG
, "P2P: * GO Intent: Intent %u Tie breaker %u",
89 go_intent
>> 1, go_intent
& 0x01);
93 void p2p_buf_add_listen_channel(struct wpabuf
*buf
, const char *country
,
94 u8 reg_class
, u8 channel
)
97 wpabuf_put_u8(buf
, P2P_ATTR_LISTEN_CHANNEL
);
98 wpabuf_put_le16(buf
, 5);
99 wpabuf_put_data(buf
, country
, 3);
100 wpabuf_put_u8(buf
, reg_class
); /* Regulatory Class */
101 wpabuf_put_u8(buf
, channel
); /* Channel Number */
102 wpa_printf(MSG_DEBUG
, "P2P: * Listen Channel: Regulatory Class %u "
103 "Channel %u", reg_class
, channel
);
107 void p2p_buf_add_operating_channel(struct wpabuf
*buf
, const char *country
,
108 u8 reg_class
, u8 channel
)
110 /* Operating Channel */
111 wpabuf_put_u8(buf
, P2P_ATTR_OPERATING_CHANNEL
);
112 wpabuf_put_le16(buf
, 5);
113 wpabuf_put_data(buf
, country
, 3);
114 wpabuf_put_u8(buf
, reg_class
); /* Regulatory Class */
115 wpabuf_put_u8(buf
, channel
); /* Channel Number */
116 wpa_printf(MSG_DEBUG
, "P2P: * Operating Channel: Regulatory Class %u "
117 "Channel %u", reg_class
, channel
);
121 void p2p_buf_add_channel_list(struct wpabuf
*buf
, const char *country
,
122 struct p2p_channels
*chan
)
128 wpabuf_put_u8(buf
, P2P_ATTR_CHANNEL_LIST
);
129 len
= wpabuf_put(buf
, 2); /* IE length to be filled */
130 wpabuf_put_data(buf
, country
, 3); /* Country String */
132 for (i
= 0; i
< chan
->reg_classes
; i
++) {
133 struct p2p_reg_class
*c
= &chan
->reg_class
[i
];
134 wpabuf_put_u8(buf
, c
->reg_class
);
135 wpabuf_put_u8(buf
, c
->channels
);
136 wpabuf_put_data(buf
, c
->channel
, c
->channels
);
139 /* Update attribute length */
140 WPA_PUT_LE16(len
, (u8
*) wpabuf_put(buf
, 0) - len
- 2);
141 wpa_printf(MSG_DEBUG
, "P2P: * Channel List");
145 void p2p_buf_add_status(struct wpabuf
*buf
, u8 status
)
148 wpabuf_put_u8(buf
, P2P_ATTR_STATUS
);
149 wpabuf_put_le16(buf
, 1);
150 wpabuf_put_u8(buf
, status
);
151 wpa_printf(MSG_DEBUG
, "P2P: * Status: %d", status
);
155 void p2p_buf_add_device_info(struct wpabuf
*buf
, struct p2p_data
*p2p
,
156 struct p2p_device
*peer
)
162 /* P2P Device Info */
163 wpabuf_put_u8(buf
, P2P_ATTR_DEVICE_INFO
);
164 len
= wpabuf_put(buf
, 2); /* IE length to be filled */
166 /* P2P Device address */
167 wpabuf_put_data(buf
, p2p
->cfg
->dev_addr
, ETH_ALEN
);
171 if (peer
&& peer
->wps_method
!= WPS_NOT_READY
) {
172 if (peer
->wps_method
== WPS_PBC
)
173 methods
|= WPS_CONFIG_PUSHBUTTON
;
174 else if (peer
->wps_method
== WPS_PIN_DISPLAY
||
175 peer
->wps_method
== WPS_PIN_KEYPAD
)
176 methods
|= WPS_CONFIG_DISPLAY
| WPS_CONFIG_KEYPAD
;
177 } else if (p2p
->cfg
->config_methods
) {
178 methods
|= p2p
->cfg
->config_methods
&
179 (WPS_CONFIG_PUSHBUTTON
| WPS_CONFIG_DISPLAY
|
182 methods
|= WPS_CONFIG_PUSHBUTTON
;
183 methods
|= WPS_CONFIG_DISPLAY
| WPS_CONFIG_KEYPAD
;
185 wpabuf_put_be16(buf
, methods
);
187 /* Primary Device Type */
188 wpabuf_put_data(buf
, p2p
->cfg
->pri_dev_type
,
189 sizeof(p2p
->cfg
->pri_dev_type
));
191 /* Number of Secondary Device Types */
192 wpabuf_put_u8(buf
, p2p
->cfg
->num_sec_dev_types
);
194 /* Secondary Device Type List */
195 for (i
= 0; i
< p2p
->cfg
->num_sec_dev_types
; i
++)
196 wpabuf_put_data(buf
, p2p
->cfg
->sec_dev_type
[i
],
200 nlen
= p2p
->cfg
->dev_name
? os_strlen(p2p
->cfg
->dev_name
) : 0;
201 wpabuf_put_be16(buf
, ATTR_DEV_NAME
);
202 wpabuf_put_be16(buf
, nlen
);
203 wpabuf_put_data(buf
, p2p
->cfg
->dev_name
, nlen
);
205 /* Update attribute length */
206 WPA_PUT_LE16(len
, (u8
*) wpabuf_put(buf
, 0) - len
- 2);
207 wpa_printf(MSG_DEBUG
, "P2P: * Device Info");
211 void p2p_buf_add_device_id(struct wpabuf
*buf
, const u8
*dev_addr
)
214 wpabuf_put_u8(buf
, P2P_ATTR_DEVICE_ID
);
215 wpabuf_put_le16(buf
, ETH_ALEN
);
216 wpabuf_put_data(buf
, dev_addr
, ETH_ALEN
);
217 wpa_printf(MSG_DEBUG
, "P2P: * Device ID: " MACSTR
, MAC2STR(dev_addr
));
221 void p2p_buf_add_config_timeout(struct wpabuf
*buf
, u8 go_timeout
,
224 /* Configuration Timeout */
225 wpabuf_put_u8(buf
, P2P_ATTR_CONFIGURATION_TIMEOUT
);
226 wpabuf_put_le16(buf
, 2);
227 wpabuf_put_u8(buf
, go_timeout
);
228 wpabuf_put_u8(buf
, client_timeout
);
229 wpa_printf(MSG_DEBUG
, "P2P: * Configuration Timeout: GO %d (*10ms) "
230 "client %d (*10ms)", go_timeout
, client_timeout
);
234 void p2p_buf_add_intended_addr(struct wpabuf
*buf
, const u8
*interface_addr
)
236 /* Intended P2P Interface Address */
237 wpabuf_put_u8(buf
, P2P_ATTR_INTENDED_INTERFACE_ADDR
);
238 wpabuf_put_le16(buf
, ETH_ALEN
);
239 wpabuf_put_data(buf
, interface_addr
, ETH_ALEN
);
240 wpa_printf(MSG_DEBUG
, "P2P: * Intended P2P Interface Address " MACSTR
,
241 MAC2STR(interface_addr
));
245 void p2p_buf_add_group_bssid(struct wpabuf
*buf
, const u8
*bssid
)
247 /* P2P Group BSSID */
248 wpabuf_put_u8(buf
, P2P_ATTR_GROUP_BSSID
);
249 wpabuf_put_le16(buf
, ETH_ALEN
);
250 wpabuf_put_data(buf
, bssid
, ETH_ALEN
);
251 wpa_printf(MSG_DEBUG
, "P2P: * P2P Group BSSID " MACSTR
,
256 void p2p_buf_add_group_id(struct wpabuf
*buf
, const u8
*dev_addr
,
257 const u8
*ssid
, size_t ssid_len
)
260 wpabuf_put_u8(buf
, P2P_ATTR_GROUP_ID
);
261 wpabuf_put_le16(buf
, ETH_ALEN
+ ssid_len
);
262 wpabuf_put_data(buf
, dev_addr
, ETH_ALEN
);
263 wpabuf_put_data(buf
, ssid
, ssid_len
);
264 wpa_printf(MSG_DEBUG
, "P2P: * P2P Group ID " MACSTR
,
269 void p2p_buf_add_invitation_flags(struct wpabuf
*buf
, u8 flags
)
271 /* Invitation Flags */
272 wpabuf_put_u8(buf
, P2P_ATTR_INVITATION_FLAGS
);
273 wpabuf_put_le16(buf
, 1);
274 wpabuf_put_u8(buf
, flags
);
275 wpa_printf(MSG_DEBUG
, "P2P: * Invitation Flags: bitmap 0x%x", flags
);
279 static void p2p_buf_add_noa_desc(struct wpabuf
*buf
, struct p2p_noa_desc
*desc
)
284 wpabuf_put_u8(buf
, desc
->count_type
);
285 wpabuf_put_le32(buf
, desc
->duration
);
286 wpabuf_put_le32(buf
, desc
->interval
);
287 wpabuf_put_le32(buf
, desc
->start_time
);
291 void p2p_buf_add_noa(struct wpabuf
*buf
, u8 noa_index
, u8 opp_ps
, u8 ctwindow
,
292 struct p2p_noa_desc
*desc1
, struct p2p_noa_desc
*desc2
)
294 /* Notice of Absence */
295 wpabuf_put_u8(buf
, P2P_ATTR_NOTICE_OF_ABSENCE
);
296 wpabuf_put_le16(buf
, 2 + (desc1
? 13 : 0) + (desc2
? 13 : 0));
297 wpabuf_put_u8(buf
, noa_index
);
298 wpabuf_put_u8(buf
, (opp_ps
? 0x80 : 0) | (ctwindow
& 0x7f));
299 p2p_buf_add_noa_desc(buf
, desc1
);
300 p2p_buf_add_noa_desc(buf
, desc2
);
301 wpa_printf(MSG_DEBUG
, "P2P: * Notice of Absence");
305 void p2p_buf_add_ext_listen_timing(struct wpabuf
*buf
, u16 period
,
308 /* Extended Listen Timing */
309 wpabuf_put_u8(buf
, P2P_ATTR_EXT_LISTEN_TIMING
);
310 wpabuf_put_le16(buf
, 4);
311 wpabuf_put_le16(buf
, period
);
312 wpabuf_put_le16(buf
, interval
);
313 wpa_printf(MSG_DEBUG
, "P2P: * Extended Listen Timing (period %u msec "
314 "interval %u msec)", period
, interval
);
318 void p2p_buf_add_p2p_interface(struct wpabuf
*buf
, struct p2p_data
*p2p
)
321 wpabuf_put_u8(buf
, P2P_ATTR_INTERFACE
);
322 wpabuf_put_le16(buf
, ETH_ALEN
+ 1 + ETH_ALEN
);
323 /* P2P Device address */
324 wpabuf_put_data(buf
, p2p
->cfg
->dev_addr
, ETH_ALEN
);
326 * FIX: Fetch interface address list from driver. Do not include
327 * the P2P Device address if it is never used as interface address.
329 /* P2P Interface Address Count */
330 wpabuf_put_u8(buf
, 1);
331 wpabuf_put_data(buf
, p2p
->cfg
->dev_addr
, ETH_ALEN
);
335 static void p2p_add_wps_string(struct wpabuf
*buf
, enum wps_attribute attr
,
340 wpabuf_put_be16(buf
, attr
);
341 len
= val
? os_strlen(val
) : 0;
342 #ifndef CONFIG_WPS_STRICT
345 * Some deployed WPS implementations fail to parse zeor-length
346 * attributes. As a workaround, send a space character if the
347 * device attribute string is empty.
349 wpabuf_put_be16(buf
, 1);
350 wpabuf_put_u8(buf
, ' ');
353 #endif /* CONFIG_WPS_STRICT */
354 wpabuf_put_be16(buf
, len
);
356 wpabuf_put_data(buf
, val
, len
);
360 void p2p_build_wps_ie(struct p2p_data
*p2p
, struct wpabuf
*buf
, u16 pw_id
,
366 wpabuf_put_u8(buf
, WLAN_EID_VENDOR_SPECIFIC
);
367 len
= wpabuf_put(buf
, 1);
368 wpabuf_put_be32(buf
, WPS_DEV_OUI_WFA
);
370 wps_build_version(buf
);
373 wpabuf_put_be16(buf
, ATTR_WPS_STATE
);
374 wpabuf_put_be16(buf
, 1);
375 wpabuf_put_u8(buf
, WPS_STATE_NOT_CONFIGURED
);
378 /* Device Password ID */
379 wpabuf_put_be16(buf
, ATTR_DEV_PASSWORD_ID
);
380 wpabuf_put_be16(buf
, 2);
381 wpa_printf(MSG_DEBUG
, "P2P: WPS IE Device Password ID: %d", pw_id
);
382 wpabuf_put_be16(buf
, pw_id
);
385 wpabuf_put_be16(buf
, ATTR_RESPONSE_TYPE
);
386 wpabuf_put_be16(buf
, 1);
387 wpabuf_put_u8(buf
, WPS_RESP_ENROLLEE_INFO
);
389 wps_build_uuid_e(buf
, p2p
->cfg
->uuid
);
390 p2p_add_wps_string(buf
, ATTR_MANUFACTURER
,
391 p2p
->cfg
->manufacturer
);
392 p2p_add_wps_string(buf
, ATTR_MODEL_NAME
, p2p
->cfg
->model_name
);
393 p2p_add_wps_string(buf
, ATTR_MODEL_NUMBER
,
394 p2p
->cfg
->model_number
);
395 p2p_add_wps_string(buf
, ATTR_SERIAL_NUMBER
,
396 p2p
->cfg
->serial_number
);
398 wpabuf_put_be16(buf
, ATTR_PRIMARY_DEV_TYPE
);
399 wpabuf_put_be16(buf
, WPS_DEV_TYPE_LEN
);
400 wpabuf_put_data(buf
, p2p
->cfg
->pri_dev_type
, WPS_DEV_TYPE_LEN
);
402 p2p_add_wps_string(buf
, ATTR_DEV_NAME
, p2p
->cfg
->dev_name
);
404 wpabuf_put_be16(buf
, ATTR_CONFIG_METHODS
);
405 wpabuf_put_be16(buf
, 2);
406 wpabuf_put_be16(buf
, p2p
->cfg
->config_methods
);
409 wps_build_wfa_ext(buf
, 0, NULL
, 0);
411 if (all_attr
&& p2p
->cfg
->num_sec_dev_types
) {
412 wpabuf_put_be16(buf
, ATTR_SECONDARY_DEV_TYPE_LIST
);
413 wpabuf_put_be16(buf
, WPS_DEV_TYPE_LEN
*
414 p2p
->cfg
->num_sec_dev_types
);
415 wpabuf_put_data(buf
, p2p
->cfg
->sec_dev_type
,
417 p2p
->cfg
->num_sec_dev_types
);
420 /* Add the WPS vendor extensions */
421 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
422 if (p2p
->wps_vendor_ext
[i
] == NULL
)
424 if (wpabuf_tailroom(buf
) <
425 4 + wpabuf_len(p2p
->wps_vendor_ext
[i
]))
427 wpabuf_put_be16(buf
, ATTR_VENDOR_EXT
);
428 wpabuf_put_be16(buf
, wpabuf_len(p2p
->wps_vendor_ext
[i
]));
429 wpabuf_put_buf(buf
, p2p
->wps_vendor_ext
[i
]);
432 p2p_buf_update_ie_hdr(buf
, len
);