Merge with wpa_supplicant 1.0 stable release
[profile/ivi/wpa_supplicant.git] / src / p2p / p2p_build.c
1 /*
2  * P2P - IE builder
3  * Copyright (c) 2009-2010, Atheros Communications
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "common/ieee802_11_defs.h"
19 #include "wps/wps_i.h"
20 #include "p2p_i.h"
21
22
23 void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
24 {
25         wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
26         wpabuf_put_be24(buf, OUI_WFA);
27         wpabuf_put_u8(buf, P2P_OUI_TYPE);
28
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);
32 }
33
34
35 void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
36                                    u8 dialog_token)
37 {
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);
42
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);
46 }
47
48
49 u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
50 {
51         u8 *len;
52
53         /* P2P IE header */
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");
59         return len;
60 }
61
62
63 void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
64 {
65         /* Update P2P IE Length */
66         *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
67 }
68
69
70 void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
71 {
72         /* P2P Capability */
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);
79 }
80
81
82 void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent)
83 {
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);
90 }
91
92
93 void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
94                                 u8 reg_class, u8 channel)
95 {
96         /* Listen 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);
104 }
105
106
107 void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country,
108                                    u8 reg_class, u8 channel)
109 {
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);
118 }
119
120
121 void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
122                               struct p2p_channels *chan)
123 {
124         u8 *len;
125         size_t i;
126
127         /* Channel List */
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 */
131
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);
137         }
138
139         /* Update attribute length */
140         WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
141         wpa_printf(MSG_DEBUG, "P2P: * Channel List");
142 }
143
144
145 void p2p_buf_add_status(struct wpabuf *buf, u8 status)
146 {
147         /* 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);
152 }
153
154
155 void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
156                              struct p2p_device *peer)
157 {
158         u8 *len;
159         u16 methods;
160         size_t nlen, i;
161
162         /* P2P Device Info */
163         wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO);
164         len = wpabuf_put(buf, 2); /* IE length to be filled */
165
166         /* P2P Device address */
167         wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
168
169         /* Config Methods */
170         methods = 0;
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 |
180                          WPS_CONFIG_KEYPAD);
181         } else {
182                 methods |= WPS_CONFIG_PUSHBUTTON;
183                 methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
184         }
185         wpabuf_put_be16(buf, methods);
186
187         /* Primary Device Type */
188         wpabuf_put_data(buf, p2p->cfg->pri_dev_type,
189                         sizeof(p2p->cfg->pri_dev_type));
190
191         /* Number of Secondary Device Types */
192         wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types);
193
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],
197                                 WPS_DEV_TYPE_LEN);
198
199         /* Device Name */
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);
204
205         /* Update attribute length */
206         WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
207         wpa_printf(MSG_DEBUG, "P2P: * Device Info");
208 }
209
210
211 void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr)
212 {
213         /* P2P Device ID */
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));
218 }
219
220
221 void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout,
222                                 u8 client_timeout)
223 {
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);
231 }
232
233
234 void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr)
235 {
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));
242 }
243
244
245 void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid)
246 {
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,
252                    MAC2STR(bssid));
253 }
254
255
256 void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr,
257                           const u8 *ssid, size_t ssid_len)
258 {
259         /* P2P Group ID */
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,
265                    MAC2STR(dev_addr));
266 }
267
268
269 void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags)
270 {
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);
276 }
277
278
279 static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc)
280 {
281         if (desc == NULL)
282                 return;
283
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);
288 }
289
290
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)
293 {
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");
302 }
303
304
305 void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
306                                    u16 interval)
307 {
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);
315 }
316
317
318 void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p)
319 {
320         /* P2P Interface */
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);
325         /*
326          * FIX: Fetch interface address list from driver. Do not include
327          * the P2P Device address if it is never used as interface address.
328          */
329         /* P2P Interface Address Count */
330         wpabuf_put_u8(buf, 1);
331         wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
332 }
333
334
335 static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
336                                const char *val)
337 {
338         size_t len;
339
340         wpabuf_put_be16(buf, attr);
341         len = val ? os_strlen(val) : 0;
342 #ifndef CONFIG_WPS_STRICT
343         if (len == 0) {
344                 /*
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.
348                  */
349                 wpabuf_put_be16(buf, 1);
350                 wpabuf_put_u8(buf, ' ');
351                 return;
352         }
353 #endif /* CONFIG_WPS_STRICT */
354         wpabuf_put_be16(buf, len);
355         if (val)
356                 wpabuf_put_data(buf, val, len);
357 }
358
359
360 void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id,
361                       int all_attr)
362 {
363         u8 *len;
364         int i;
365
366         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
367         len = wpabuf_put(buf, 1);
368         wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
369
370         wps_build_version(buf);
371
372         if (all_attr) {
373                 wpabuf_put_be16(buf, ATTR_WPS_STATE);
374                 wpabuf_put_be16(buf, 1);
375                 wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
376         }
377
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);
383
384         if (all_attr) {
385                 wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
386                 wpabuf_put_be16(buf, 1);
387                 wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
388
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);
397
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);
401
402                 p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name);
403
404                 wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
405                 wpabuf_put_be16(buf, 2);
406                 wpabuf_put_be16(buf, p2p->cfg->config_methods);
407         }
408
409         wps_build_wfa_ext(buf, 0, NULL, 0);
410
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,
416                                 WPS_DEV_TYPE_LEN *
417                                 p2p->cfg->num_sec_dev_types);
418         }
419
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)
423                         break;
424                 if (wpabuf_tailroom(buf) <
425                     4 + wpabuf_len(p2p->wps_vendor_ext[i]))
426                         continue;
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]);
430         }
431
432         p2p_buf_update_ie_hdr(buf, len);
433 }