3 * Copyright (c) 2009-2010, Atheros Communications
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "common/ieee802_11_defs.h"
13 #include "wps/wps_i.h"
17 void p2p_buf_add_action_hdr(struct wpabuf
*buf
, u8 subtype
, u8 dialog_token
)
19 wpabuf_put_u8(buf
, WLAN_ACTION_VENDOR_SPECIFIC
);
20 wpabuf_put_be24(buf
, OUI_WFA
);
21 wpabuf_put_u8(buf
, P2P_OUI_TYPE
);
23 wpabuf_put_u8(buf
, subtype
); /* OUI Subtype */
24 wpabuf_put_u8(buf
, dialog_token
);
25 wpa_printf(MSG_DEBUG
, "P2P: * Dialog Token: %d", dialog_token
);
29 void p2p_buf_add_public_action_hdr(struct wpabuf
*buf
, u8 subtype
,
32 wpabuf_put_u8(buf
, WLAN_ACTION_PUBLIC
);
33 wpabuf_put_u8(buf
, WLAN_PA_VENDOR_SPECIFIC
);
34 wpabuf_put_be24(buf
, OUI_WFA
);
35 wpabuf_put_u8(buf
, P2P_OUI_TYPE
);
37 wpabuf_put_u8(buf
, subtype
); /* OUI Subtype */
38 wpabuf_put_u8(buf
, dialog_token
);
39 wpa_printf(MSG_DEBUG
, "P2P: * Dialog Token: %d", dialog_token
);
43 u8
* p2p_buf_add_ie_hdr(struct wpabuf
*buf
)
48 wpabuf_put_u8(buf
, WLAN_EID_VENDOR_SPECIFIC
);
49 len
= wpabuf_put(buf
, 1); /* IE length to be filled */
50 wpabuf_put_be24(buf
, OUI_WFA
);
51 wpabuf_put_u8(buf
, P2P_OUI_TYPE
);
52 wpa_printf(MSG_DEBUG
, "P2P: * P2P IE header");
57 void p2p_buf_update_ie_hdr(struct wpabuf
*buf
, u8
*len
)
59 /* Update P2P IE Length */
60 *len
= (u8
*) wpabuf_put(buf
, 0) - len
- 1;
64 void p2p_buf_add_capability(struct wpabuf
*buf
, u8 dev_capab
, u8 group_capab
)
67 wpabuf_put_u8(buf
, P2P_ATTR_CAPABILITY
);
68 wpabuf_put_le16(buf
, 2);
69 wpabuf_put_u8(buf
, dev_capab
); /* Device Capabilities */
70 wpabuf_put_u8(buf
, group_capab
); /* Group Capabilities */
71 wpa_printf(MSG_DEBUG
, "P2P: * Capability dev=%02x group=%02x",
72 dev_capab
, group_capab
);
76 void p2p_buf_add_go_intent(struct wpabuf
*buf
, u8 go_intent
)
78 /* Group Owner Intent */
79 wpabuf_put_u8(buf
, P2P_ATTR_GROUP_OWNER_INTENT
);
80 wpabuf_put_le16(buf
, 1);
81 wpabuf_put_u8(buf
, go_intent
);
82 wpa_printf(MSG_DEBUG
, "P2P: * GO Intent: Intent %u Tie breaker %u",
83 go_intent
>> 1, go_intent
& 0x01);
87 void p2p_buf_add_listen_channel(struct wpabuf
*buf
, const char *country
,
88 u8 reg_class
, u8 channel
)
91 wpabuf_put_u8(buf
, P2P_ATTR_LISTEN_CHANNEL
);
92 wpabuf_put_le16(buf
, 5);
93 wpabuf_put_data(buf
, country
, 3);
94 wpabuf_put_u8(buf
, reg_class
); /* Regulatory Class */
95 wpabuf_put_u8(buf
, channel
); /* Channel Number */
96 wpa_printf(MSG_DEBUG
, "P2P: * Listen Channel: Regulatory Class %u "
97 "Channel %u", reg_class
, channel
);
101 void p2p_buf_add_operating_channel(struct wpabuf
*buf
, const char *country
,
102 u8 reg_class
, u8 channel
)
104 /* Operating Channel */
105 wpabuf_put_u8(buf
, P2P_ATTR_OPERATING_CHANNEL
);
106 wpabuf_put_le16(buf
, 5);
107 wpabuf_put_data(buf
, country
, 3);
108 wpabuf_put_u8(buf
, reg_class
); /* Regulatory Class */
109 wpabuf_put_u8(buf
, channel
); /* Channel Number */
110 wpa_printf(MSG_DEBUG
, "P2P: * Operating Channel: Regulatory Class %u "
111 "Channel %u", reg_class
, channel
);
115 void p2p_buf_add_channel_list(struct wpabuf
*buf
, const char *country
,
116 struct p2p_channels
*chan
)
122 wpabuf_put_u8(buf
, P2P_ATTR_CHANNEL_LIST
);
123 len
= wpabuf_put(buf
, 2); /* IE length to be filled */
124 wpabuf_put_data(buf
, country
, 3); /* Country String */
126 for (i
= 0; i
< chan
->reg_classes
; i
++) {
127 struct p2p_reg_class
*c
= &chan
->reg_class
[i
];
128 wpabuf_put_u8(buf
, c
->reg_class
);
129 wpabuf_put_u8(buf
, c
->channels
);
130 wpabuf_put_data(buf
, c
->channel
, c
->channels
);
133 /* Update attribute length */
134 WPA_PUT_LE16(len
, (u8
*) wpabuf_put(buf
, 0) - len
- 2);
135 wpa_hexdump(MSG_DEBUG
, "P2P: * Channel List",
136 len
+ 2, (u8
*) wpabuf_put(buf
, 0) - len
- 2);
140 void p2p_buf_add_status(struct wpabuf
*buf
, u8 status
)
143 wpabuf_put_u8(buf
, P2P_ATTR_STATUS
);
144 wpabuf_put_le16(buf
, 1);
145 wpabuf_put_u8(buf
, status
);
146 wpa_printf(MSG_DEBUG
, "P2P: * Status: %d", status
);
150 void p2p_buf_add_device_info(struct wpabuf
*buf
, struct p2p_data
*p2p
,
151 struct p2p_device
*peer
)
157 /* P2P Device Info */
158 wpabuf_put_u8(buf
, P2P_ATTR_DEVICE_INFO
);
159 len
= wpabuf_put(buf
, 2); /* IE length to be filled */
161 /* P2P Device address */
162 wpabuf_put_data(buf
, p2p
->cfg
->dev_addr
, ETH_ALEN
);
166 if (peer
&& peer
->wps_method
!= WPS_NOT_READY
) {
167 if (peer
->wps_method
== WPS_PBC
)
168 methods
|= WPS_CONFIG_PUSHBUTTON
;
169 else if (peer
->wps_method
== WPS_PIN_DISPLAY
||
170 peer
->wps_method
== WPS_PIN_KEYPAD
)
171 methods
|= WPS_CONFIG_DISPLAY
| WPS_CONFIG_KEYPAD
;
172 } else if (p2p
->cfg
->config_methods
) {
173 methods
|= p2p
->cfg
->config_methods
&
174 (WPS_CONFIG_PUSHBUTTON
| WPS_CONFIG_DISPLAY
|
177 methods
|= WPS_CONFIG_PUSHBUTTON
;
178 methods
|= WPS_CONFIG_DISPLAY
| WPS_CONFIG_KEYPAD
;
180 wpabuf_put_be16(buf
, methods
);
182 /* Primary Device Type */
183 wpabuf_put_data(buf
, p2p
->cfg
->pri_dev_type
,
184 sizeof(p2p
->cfg
->pri_dev_type
));
186 /* Number of Secondary Device Types */
187 wpabuf_put_u8(buf
, p2p
->cfg
->num_sec_dev_types
);
189 /* Secondary Device Type List */
190 for (i
= 0; i
< p2p
->cfg
->num_sec_dev_types
; i
++)
191 wpabuf_put_data(buf
, p2p
->cfg
->sec_dev_type
[i
],
195 nlen
= p2p
->cfg
->dev_name
? os_strlen(p2p
->cfg
->dev_name
) : 0;
196 wpabuf_put_be16(buf
, ATTR_DEV_NAME
);
197 wpabuf_put_be16(buf
, nlen
);
198 wpabuf_put_data(buf
, p2p
->cfg
->dev_name
, nlen
);
200 /* Update attribute length */
201 WPA_PUT_LE16(len
, (u8
*) wpabuf_put(buf
, 0) - len
- 2);
202 wpa_printf(MSG_DEBUG
, "P2P: * Device Info");
206 void p2p_buf_add_device_id(struct wpabuf
*buf
, const u8
*dev_addr
)
209 wpabuf_put_u8(buf
, P2P_ATTR_DEVICE_ID
);
210 wpabuf_put_le16(buf
, ETH_ALEN
);
211 wpabuf_put_data(buf
, dev_addr
, ETH_ALEN
);
212 wpa_printf(MSG_DEBUG
, "P2P: * Device ID: " MACSTR
, MAC2STR(dev_addr
));
216 void p2p_buf_add_config_timeout(struct wpabuf
*buf
, u8 go_timeout
,
219 /* Configuration Timeout */
220 wpabuf_put_u8(buf
, P2P_ATTR_CONFIGURATION_TIMEOUT
);
221 wpabuf_put_le16(buf
, 2);
222 wpabuf_put_u8(buf
, go_timeout
);
223 wpabuf_put_u8(buf
, client_timeout
);
224 wpa_printf(MSG_DEBUG
, "P2P: * Configuration Timeout: GO %d (*10ms) "
225 "client %d (*10ms)", go_timeout
, client_timeout
);
229 void p2p_buf_add_intended_addr(struct wpabuf
*buf
, const u8
*interface_addr
)
231 /* Intended P2P Interface Address */
232 wpabuf_put_u8(buf
, P2P_ATTR_INTENDED_INTERFACE_ADDR
);
233 wpabuf_put_le16(buf
, ETH_ALEN
);
234 wpabuf_put_data(buf
, interface_addr
, ETH_ALEN
);
235 wpa_printf(MSG_DEBUG
, "P2P: * Intended P2P Interface Address " MACSTR
,
236 MAC2STR(interface_addr
));
240 void p2p_buf_add_group_bssid(struct wpabuf
*buf
, const u8
*bssid
)
242 /* P2P Group BSSID */
243 wpabuf_put_u8(buf
, P2P_ATTR_GROUP_BSSID
);
244 wpabuf_put_le16(buf
, ETH_ALEN
);
245 wpabuf_put_data(buf
, bssid
, ETH_ALEN
);
246 wpa_printf(MSG_DEBUG
, "P2P: * P2P Group BSSID " MACSTR
,
251 void p2p_buf_add_group_id(struct wpabuf
*buf
, const u8
*dev_addr
,
252 const u8
*ssid
, size_t ssid_len
)
255 wpabuf_put_u8(buf
, P2P_ATTR_GROUP_ID
);
256 wpabuf_put_le16(buf
, ETH_ALEN
+ ssid_len
);
257 wpabuf_put_data(buf
, dev_addr
, ETH_ALEN
);
258 wpabuf_put_data(buf
, ssid
, ssid_len
);
259 wpa_printf(MSG_DEBUG
, "P2P: * P2P Group ID " MACSTR
,
261 wpa_hexdump_ascii(MSG_DEBUG
, "P2P: P2P Group ID SSID", ssid
, ssid_len
);
265 void p2p_buf_add_invitation_flags(struct wpabuf
*buf
, u8 flags
)
267 /* Invitation Flags */
268 wpabuf_put_u8(buf
, P2P_ATTR_INVITATION_FLAGS
);
269 wpabuf_put_le16(buf
, 1);
270 wpabuf_put_u8(buf
, flags
);
271 wpa_printf(MSG_DEBUG
, "P2P: * Invitation Flags: bitmap 0x%x", flags
);
275 static void p2p_buf_add_noa_desc(struct wpabuf
*buf
, struct p2p_noa_desc
*desc
)
280 wpabuf_put_u8(buf
, desc
->count_type
);
281 wpabuf_put_le32(buf
, desc
->duration
);
282 wpabuf_put_le32(buf
, desc
->interval
);
283 wpabuf_put_le32(buf
, desc
->start_time
);
287 void p2p_buf_add_noa(struct wpabuf
*buf
, u8 noa_index
, u8 opp_ps
, u8 ctwindow
,
288 struct p2p_noa_desc
*desc1
, struct p2p_noa_desc
*desc2
)
290 /* Notice of Absence */
291 wpabuf_put_u8(buf
, P2P_ATTR_NOTICE_OF_ABSENCE
);
292 wpabuf_put_le16(buf
, 2 + (desc1
? 13 : 0) + (desc2
? 13 : 0));
293 wpabuf_put_u8(buf
, noa_index
);
294 wpabuf_put_u8(buf
, (opp_ps
? 0x80 : 0) | (ctwindow
& 0x7f));
295 p2p_buf_add_noa_desc(buf
, desc1
);
296 p2p_buf_add_noa_desc(buf
, desc2
);
297 wpa_printf(MSG_DEBUG
, "P2P: * Notice of Absence");
301 void p2p_buf_add_ext_listen_timing(struct wpabuf
*buf
, u16 period
,
304 /* Extended Listen Timing */
305 wpabuf_put_u8(buf
, P2P_ATTR_EXT_LISTEN_TIMING
);
306 wpabuf_put_le16(buf
, 4);
307 wpabuf_put_le16(buf
, period
);
308 wpabuf_put_le16(buf
, interval
);
309 wpa_printf(MSG_DEBUG
, "P2P: * Extended Listen Timing (period %u msec "
310 "interval %u msec)", period
, interval
);
314 void p2p_buf_add_p2p_interface(struct wpabuf
*buf
, struct p2p_data
*p2p
)
317 wpabuf_put_u8(buf
, P2P_ATTR_INTERFACE
);
318 wpabuf_put_le16(buf
, ETH_ALEN
+ 1 + ETH_ALEN
);
319 /* P2P Device address */
320 wpabuf_put_data(buf
, p2p
->cfg
->dev_addr
, ETH_ALEN
);
322 * FIX: Fetch interface address list from driver. Do not include
323 * the P2P Device address if it is never used as interface address.
325 /* P2P Interface Address Count */
326 wpabuf_put_u8(buf
, 1);
327 wpabuf_put_data(buf
, p2p
->cfg
->dev_addr
, ETH_ALEN
);
331 static int p2p_add_wps_string(struct wpabuf
*buf
, enum wps_attribute attr
,
336 len
= val
? os_strlen(val
) : 0;
337 if (wpabuf_tailroom(buf
) < 4 + len
)
339 wpabuf_put_be16(buf
, attr
);
340 #ifndef CONFIG_WPS_STRICT
343 * Some deployed WPS implementations fail to parse zeor-length
344 * attributes. As a workaround, send a space character if the
345 * device attribute string is empty.
347 if (wpabuf_tailroom(buf
) < 3)
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
);
361 int p2p_build_wps_ie(struct p2p_data
*p2p
, struct wpabuf
*buf
, int pw_id
,
367 if (wpabuf_tailroom(buf
) < 6)
369 wpabuf_put_u8(buf
, WLAN_EID_VENDOR_SPECIFIC
);
370 len
= wpabuf_put(buf
, 1);
371 wpabuf_put_be32(buf
, WPS_DEV_OUI_WFA
);
373 if (wps_build_version(buf
) < 0)
377 if (wpabuf_tailroom(buf
) < 5)
379 wpabuf_put_be16(buf
, ATTR_WPS_STATE
);
380 wpabuf_put_be16(buf
, 1);
381 wpabuf_put_u8(buf
, WPS_STATE_NOT_CONFIGURED
);
385 if (wpabuf_tailroom(buf
) < 6)
387 /* Device Password ID */
388 wpabuf_put_be16(buf
, ATTR_DEV_PASSWORD_ID
);
389 wpabuf_put_be16(buf
, 2);
390 wpa_printf(MSG_DEBUG
, "P2P: WPS IE Device Password ID: %d",
392 wpabuf_put_be16(buf
, pw_id
);
396 if (wpabuf_tailroom(buf
) < 5)
398 wpabuf_put_be16(buf
, ATTR_RESPONSE_TYPE
);
399 wpabuf_put_be16(buf
, 1);
400 wpabuf_put_u8(buf
, WPS_RESP_ENROLLEE_INFO
);
402 if (wps_build_uuid_e(buf
, p2p
->cfg
->uuid
) < 0 ||
403 p2p_add_wps_string(buf
, ATTR_MANUFACTURER
,
404 p2p
->cfg
->manufacturer
) < 0 ||
405 p2p_add_wps_string(buf
, ATTR_MODEL_NAME
,
406 p2p
->cfg
->model_name
) < 0 ||
407 p2p_add_wps_string(buf
, ATTR_MODEL_NUMBER
,
408 p2p
->cfg
->model_number
) < 0 ||
409 p2p_add_wps_string(buf
, ATTR_SERIAL_NUMBER
,
410 p2p
->cfg
->serial_number
) < 0)
413 if (wpabuf_tailroom(buf
) < 4 + WPS_DEV_TYPE_LEN
)
415 wpabuf_put_be16(buf
, ATTR_PRIMARY_DEV_TYPE
);
416 wpabuf_put_be16(buf
, WPS_DEV_TYPE_LEN
);
417 wpabuf_put_data(buf
, p2p
->cfg
->pri_dev_type
, WPS_DEV_TYPE_LEN
);
419 if (p2p_add_wps_string(buf
, ATTR_DEV_NAME
, p2p
->cfg
->dev_name
)
423 if (wpabuf_tailroom(buf
) < 6)
425 wpabuf_put_be16(buf
, ATTR_CONFIG_METHODS
);
426 wpabuf_put_be16(buf
, 2);
427 wpabuf_put_be16(buf
, p2p
->cfg
->config_methods
);
430 if (wps_build_wfa_ext(buf
, 0, NULL
, 0) < 0)
433 if (all_attr
&& p2p
->cfg
->num_sec_dev_types
) {
434 if (wpabuf_tailroom(buf
) <
435 4 + WPS_DEV_TYPE_LEN
* p2p
->cfg
->num_sec_dev_types
)
437 wpabuf_put_be16(buf
, ATTR_SECONDARY_DEV_TYPE_LIST
);
438 wpabuf_put_be16(buf
, WPS_DEV_TYPE_LEN
*
439 p2p
->cfg
->num_sec_dev_types
);
440 wpabuf_put_data(buf
, p2p
->cfg
->sec_dev_type
,
442 p2p
->cfg
->num_sec_dev_types
);
445 /* Add the WPS vendor extensions */
446 for (i
= 0; i
< P2P_MAX_WPS_VENDOR_EXT
; i
++) {
447 if (p2p
->wps_vendor_ext
[i
] == NULL
)
449 if (wpabuf_tailroom(buf
) <
450 4 + wpabuf_len(p2p
->wps_vendor_ext
[i
]))
452 wpabuf_put_be16(buf
, ATTR_VENDOR_EXT
);
453 wpabuf_put_be16(buf
, wpabuf_len(p2p
->wps_vendor_ext
[i
]));
454 wpabuf_put_buf(buf
, p2p
->wps_vendor_ext
[i
]);
457 p2p_buf_update_ie_hdr(buf
, len
);