c309fe191c9756c4dd970dfcdaea31a6513ed403
[libeap.git] / src / p2p / p2p_invitation.c
1 /*
2  * Wi-Fi Direct - P2P Invitation procedure
3  * Copyright (c) 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 "p2p_i.h"
20 #include "p2p.h"
21
22
23 static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
24                                                 struct p2p_device *peer,
25                                                 const u8 *go_dev_addr)
26 {
27         struct wpabuf *buf;
28         u8 *len;
29         const u8 *dev_addr;
30
31         buf = wpabuf_alloc(1000);
32         if (buf == NULL)
33                 return NULL;
34
35         peer->dialog_token++;
36         if (peer->dialog_token == 0)
37                 peer->dialog_token = 1;
38         p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_REQ,
39                                       peer->dialog_token);
40
41         len = p2p_buf_add_ie_hdr(buf);
42         if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO || !p2p->inv_persistent)
43                 p2p_buf_add_config_timeout(buf, 0, 0);
44         else
45                 p2p_buf_add_config_timeout(buf, 100, 20);
46         p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
47                                      P2P_INVITATION_FLAGS_TYPE : 0);
48         p2p_buf_add_operating_channel(buf, p2p->cfg->country,
49                                       p2p->op_reg_class, p2p->op_channel);
50         if (p2p->inv_bssid_set)
51                 p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
52         p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
53         if (go_dev_addr)
54                 dev_addr = go_dev_addr;
55         else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
56                 dev_addr = peer->p2p_device_addr;
57         else
58                 dev_addr = p2p->cfg->dev_addr;
59         p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len);
60         p2p_buf_add_device_info(buf, p2p, peer);
61         p2p_buf_update_ie_hdr(buf, len);
62
63         return buf;
64 }
65
66
67 static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
68                                                  struct p2p_device *peer,
69                                                  u8 dialog_token, u8 status,
70                                                  const u8 *group_bssid,
71                                                  u8 reg_class, u8 channel,
72                                                  struct p2p_channels *channels)
73 {
74         struct wpabuf *buf;
75         u8 *len;
76
77         buf = wpabuf_alloc(1000);
78         if (buf == NULL)
79                 return NULL;
80
81         p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP,
82                                       dialog_token);
83
84         len = p2p_buf_add_ie_hdr(buf);
85         p2p_buf_add_status(buf, status);
86         p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */
87         if (reg_class && channel)
88                 p2p_buf_add_operating_channel(buf, p2p->cfg->country,
89                                               reg_class, channel);
90         if (group_bssid)
91                 p2p_buf_add_group_bssid(buf, group_bssid);
92         if (channels)
93                 p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
94         p2p_buf_update_ie_hdr(buf, len);
95
96         return buf;
97 }
98
99
100 void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
101                                 const u8 *data, size_t len, int rx_freq)
102 {
103         struct p2p_device *dev;
104         struct p2p_message msg;
105         struct wpabuf *resp = NULL;
106         u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
107         int freq;
108         int go = 0;
109         u8 group_bssid[ETH_ALEN], *bssid;
110         int op_freq = 0;
111         u8 reg_class = 0, channel = 0;
112         struct p2p_channels intersection, *channels = NULL;
113         int persistent;
114
115         os_memset(group_bssid, 0, sizeof(group_bssid));
116
117         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
118                 "P2P: Received Invitation Request from " MACSTR " (freq=%d)",
119                 MAC2STR(sa), rx_freq);
120
121         if (p2p_parse(data, len, &msg))
122                 return;
123
124         dev = p2p_get_device(p2p, sa);
125         if (dev == NULL) {
126                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
127                         "P2P: Reject Invitation Request from unknown peer "
128                         MACSTR, MAC2STR(sa));
129                 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
130                 goto fail;
131         }
132
133         if (!msg.group_id || !msg.channel_list) {
134                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
135                         "P2P: Mandatory attribute missing in Invitation "
136                         "Request from " MACSTR, MAC2STR(sa));
137                 status = P2P_SC_FAIL_INVALID_PARAMS;
138                 goto fail;
139         }
140
141         if (msg.invitation_flags)
142                 persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE;
143         else {
144                 /* Invitation Flags is a mandatory attribute starting from P2P
145                  * spec 1.06. As a backwards compatibility mechanism, assume
146                  * the request was for a persistent group if the attribute is
147                  * missing.
148                  */
149                 wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags "
150                            "attribute missing from Invitation Request");
151                 persistent = 1;
152         }
153
154         if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev,
155                                     msg.channel_list, msg.channel_list_len) <
156             0) {
157                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
158                         "P2P: No common channels found");
159                 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
160                 goto fail;
161         }
162
163         if (p2p->cfg->invitation_process) {
164                 status = p2p->cfg->invitation_process(
165                         p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
166                         msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
167                         &go, group_bssid, &op_freq, persistent);
168         }
169
170         if (op_freq) {
171                 if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
172                                         &reg_class, &channel) < 0) {
173                         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
174                                 "P2P: Unknown forced freq %d MHz from "
175                                 "invitation_process()", op_freq);
176                         status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
177                         goto fail;
178                 }
179
180                 p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
181                                        &intersection);
182                 if (!p2p_channels_includes(&intersection, reg_class, channel))
183                 {
184                         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
185                                 "P2P: forced freq %d MHz not in the supported "
186                                 "channels interaction", op_freq);
187                         status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
188                         goto fail;
189                 }
190
191                 if (status == P2P_SC_SUCCESS)
192                         channels = &intersection;
193         } else {
194                 op_freq = p2p_channel_to_freq(p2p->cfg->country,
195                                               p2p->cfg->op_reg_class,
196                                               p2p->cfg->op_channel);
197                 if (op_freq < 0) {
198                         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
199                                 "P2P: Unknown operational channel "
200                                 "(country=%c%c reg_class=%u channel=%u)",
201                                 p2p->cfg->country[0], p2p->cfg->country[1],
202                                 p2p->cfg->op_reg_class, p2p->cfg->op_channel);
203                         status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
204                         goto fail;
205                 }
206
207                 p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
208                                        &intersection);
209                 if (status == P2P_SC_SUCCESS) {
210                         reg_class = p2p->cfg->op_reg_class;
211                         channel = p2p->cfg->op_channel;
212                         channels = &intersection;
213                 }
214         }
215
216 fail:
217         if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid))
218                 bssid = group_bssid;
219         else
220                 bssid = NULL;
221         resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
222                                          bssid, reg_class, channel, channels);
223
224         if (resp == NULL)
225                 goto out;
226
227         if (rx_freq > 0)
228                 freq = rx_freq;
229         else
230                 freq = p2p_channel_to_freq(p2p->cfg->country,
231                                            p2p->cfg->reg_class,
232                                            p2p->cfg->channel);
233         if (freq < 0) {
234                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
235                         "P2P: Unknown regulatory class/channel");
236                 goto out;
237         }
238
239         /*
240          * Store copy of invitation data to be used when processing TX status
241          * callback for the Acton frame.
242          */
243         os_memcpy(p2p->inv_sa, sa, ETH_ALEN);
244         if (msg.group_bssid) {
245                 os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN);
246                 p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
247         } else
248                 p2p->inv_group_bssid_ptr = NULL;
249         if (msg.group_id_len - ETH_ALEN <= 32) {
250                 os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
251                           msg.group_id_len - ETH_ALEN);
252                 p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN;
253         }
254         os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN);
255         p2p->inv_status = status;
256         p2p->inv_op_freq = op_freq;
257
258         p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
259         if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, sa,
260                                   p2p->cfg->dev_addr, p2p->cfg->dev_addr,
261                                   wpabuf_head(resp), wpabuf_len(resp), 200) <
262             0) {
263                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
264                         "P2P: Failed to send Action frame");
265         }
266
267 out:
268         wpabuf_free(resp);
269         p2p_parse_free(&msg);
270 }
271
272
273 void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
274                                  const u8 *data, size_t len)
275 {
276         struct p2p_device *dev;
277         struct p2p_message msg;
278
279         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
280                 "P2P: Received Invitation Response from " MACSTR,
281                 MAC2STR(sa));
282
283         dev = p2p_get_device(p2p, sa);
284         if (dev == NULL) {
285                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
286                         "P2P: Ignore Invitation Response from unknown peer "
287                         MACSTR, MAC2STR(sa));
288                 return;
289         }
290
291         if (dev != p2p->invite_peer) {
292                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
293                         "P2P: Ignore unexpected Invitation Response from peer "
294                         MACSTR, MAC2STR(sa));
295                 return;
296         }
297
298         if (p2p_parse(data, len, &msg))
299                 return;
300
301         if (!msg.status) {
302                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
303                         "P2P: Mandatory Status attribute missing in "
304                         "Invitation Response from " MACSTR, MAC2STR(sa));
305                 p2p_parse_free(&msg);
306                 return;
307         }
308
309         if (p2p->cfg->invitation_result)
310                 p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
311                                             msg.group_bssid);
312
313         p2p_parse_free(&msg);
314
315         p2p_clear_timeout(p2p);
316         p2p_set_state(p2p, P2P_IDLE);
317         p2p->invite_peer = NULL;
318 }
319
320
321 int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
322                     const u8 *go_dev_addr)
323 {
324         struct wpabuf *req;
325         int freq;
326
327         freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
328         if (freq <= 0) {
329                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
330                         "P2P: No Listen/Operating frequency known for the "
331                         "peer " MACSTR " to send Invitation Request",
332                         MAC2STR(dev->p2p_device_addr));
333                 return -1;
334         }
335
336         req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
337         if (req == NULL)
338                 return -1;
339         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
340                 "P2P: Sending Invitation Request");
341         p2p_set_state(p2p, P2P_INVITE);
342         p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
343         p2p->invite_peer = dev;
344         dev->invitation_reqs++;
345         if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
346                                   dev->p2p_device_addr, p2p->cfg->dev_addr,
347                                   dev->p2p_device_addr,
348                                   wpabuf_head(req), wpabuf_len(req), 200) < 0)
349         {
350                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
351                         "P2P: Failed to send Action frame");
352                 /* Use P2P find to recover and retry */
353                 p2p_set_timeout(p2p, 0, 0);
354         }
355
356         wpabuf_free(req);
357
358         return 0;
359 }
360
361
362 void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
363 {
364         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
365                 "P2P: Invitation Request TX callback: success=%d", success);
366
367         if (p2p->invite_peer == NULL) {
368                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
369                         "P2P: No pending Invite");
370                 return;
371         }
372
373         /*
374          * Use P2P find, if needed, to find the other device from its listen
375          * channel.
376          */
377         p2p_set_state(p2p, P2P_INVITE);
378         p2p_set_timeout(p2p, 0, 100000);
379 }
380
381
382 void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
383 {
384         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
385                 "P2P: Invitation Response TX callback: success=%d", success);
386         p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
387
388         if (success && p2p->cfg->invitation_received) {
389                 p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
390                                               p2p->inv_sa,
391                                               p2p->inv_group_bssid,
392                                               p2p->inv_ssid, p2p->inv_ssid_len,
393                                               p2p->inv_go_dev_addr,
394                                               p2p->inv_status,
395                                               p2p->inv_op_freq);
396         }
397 }
398
399
400 int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
401                const u8 *bssid, const u8 *ssid, size_t ssid_len,
402                unsigned int force_freq, const u8 *go_dev_addr,
403                int persistent_group)
404 {
405         struct p2p_device *dev;
406
407         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
408                 "P2P: Request to invite peer " MACSTR " role=%d persistent=%d "
409                 "force_freq=%u",
410                 MAC2STR(peer), role, persistent_group, force_freq);
411         if (bssid)
412                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
413                         "P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid));
414         if (go_dev_addr) {
415                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
416                         "P2P: Invitation for GO Device Address " MACSTR,
417                         MAC2STR(go_dev_addr));
418                 os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
419                 p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
420         } else
421                 p2p->invite_go_dev_addr = NULL;
422         wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID",
423                           ssid, ssid_len);
424
425         dev = p2p_get_device(p2p, peer);
426         if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
427                 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
428                         "P2P: Cannot invite unknown P2P Device " MACSTR,
429                         MAC2STR(peer));
430                 return -1;
431         }
432
433         if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
434                 if (!(dev->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
435                         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
436                                 "P2P: Cannot invite a P2P Device " MACSTR
437                                 " that is in a group and is not discoverable",
438                                 MAC2STR(peer));
439                 }
440                 /* TODO: use device discoverability request through GO */
441         }
442
443         dev->invitation_reqs = 0;
444
445         if (force_freq) {
446                 if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
447                                         &p2p->op_reg_class, &p2p->op_channel) <
448                     0) {
449                         wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
450                                 "P2P: Unsupported frequency %u MHz",
451                                 force_freq);
452                         return -1;
453                 }
454                 p2p->channels.reg_classes = 1;
455                 p2p->channels.reg_class[0].channels = 1;
456                 p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
457                 p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
458         } else {
459                 p2p->op_reg_class = p2p->cfg->op_reg_class;
460                 p2p->op_channel = p2p->cfg->op_channel;
461                 os_memcpy(&p2p->channels, &p2p->cfg->channels,
462                           sizeof(struct p2p_channels));
463         }
464
465         if (p2p->state != P2P_IDLE)
466                 p2p_stop_find(p2p);
467
468         p2p->inv_role = role;
469         p2p->inv_bssid_set = bssid != NULL;
470         if (bssid)
471                 os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN);
472         os_memcpy(p2p->inv_ssid, ssid, ssid_len);
473         p2p->inv_ssid_len = ssid_len;
474         p2p->inv_persistent = persistent_group;
475         return p2p_invite_send(p2p, dev, go_dev_addr);
476 }