0c5335fd1925a90f03cb725cb1266f6bf9813bd9
[mech_eap.git] / src / rsn_supp / tdls.c
1 /*
2  * wpa_supplicant - TDLS
3  * Copyright (c) 2010-2011, 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 "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "utils/os.h"
20 #include "common/ieee802_11_defs.h"
21 #include "crypto/sha256.h"
22 #include "crypto/crypto.h"
23 #include "crypto/aes_wrap.h"
24 #include "rsn_supp/wpa.h"
25 #include "rsn_supp/wpa_ie.h"
26 #include "rsn_supp/wpa_i.h"
27 #include "drivers/driver.h"
28 #include "l2_packet/l2_packet.h"
29
30 #ifdef CONFIG_TDLS_TESTING
31 #define TDLS_TESTING_LONG_FRAME BIT(0)
32 #define TDLS_TESTING_ALT_RSN_IE BIT(1)
33 #define TDLS_TESTING_DIFF_BSSID BIT(2)
34 #define TDLS_TESTING_SHORT_LIFETIME BIT(3)
35 #define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4)
36 #define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5)
37 #define TDLS_TESTING_LONG_LIFETIME BIT(6)
38 #define TDLS_TESTING_CONCURRENT_INIT BIT(7)
39 #define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8)
40 #define TDLS_TESTING_DECLINE_RESP BIT(9)
41 #define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10)
42 unsigned int tdls_testing = 0;
43 #endif /* CONFIG_TDLS_TESTING */
44
45 #define TPK_LIFETIME 43200 /* 12 hours */
46 #define TPK_RETRY_COUNT 3
47 #define TPK_TIMEOUT 5000 /* in milliseconds */
48
49 #define TDLS_MIC_LEN            16
50
51 #define TDLS_TIMEOUT_LEN        4
52
53 struct wpa_tdls_ftie {
54         u8 ie_type; /* FTIE */
55         u8 ie_len;
56         u8 mic_ctrl[2];
57         u8 mic[TDLS_MIC_LEN];
58         u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */
59         u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */
60         /* followed by optional elements */
61 } STRUCT_PACKED;
62
63 struct wpa_tdls_timeoutie {
64         u8 ie_type; /* Timeout IE */
65         u8 ie_len;
66         u8 interval_type;
67         u8 value[TDLS_TIMEOUT_LEN];
68 } STRUCT_PACKED;
69
70 struct wpa_tdls_lnkid {
71         u8 ie_type; /* Link Identifier IE */
72         u8 ie_len;
73         u8 bssid[ETH_ALEN];
74         u8 init_sta[ETH_ALEN];
75         u8 resp_sta[ETH_ALEN];
76 } STRUCT_PACKED;
77
78 /* TDLS frame headers as per IEEE Std 802.11z-2010 */
79 struct wpa_tdls_frame {
80         u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */
81         u8 category; /* Category */
82         u8 action; /* Action (enum tdls_frame_type) */
83 } STRUCT_PACKED;
84
85 static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs);
86 static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx);
87 static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
88
89
90 #define TDLS_MAX_IE_LEN 80
91 struct wpa_tdls_peer {
92         struct wpa_tdls_peer *next;
93         int initiator; /* whether this end was initiator for TDLS setup */
94         u8 addr[ETH_ALEN]; /* other end MAC address */
95         u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
96         u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */
97         u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */
98         size_t rsnie_i_len;
99         u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */
100         size_t rsnie_p_len;
101         u32 lifetime;
102         int cipher; /* Selected cipher (WPA_CIPHER_*) */
103         u8 dtoken;
104
105         struct tpk {
106                 u8 kck[16]; /* TPK-KCK */
107                 u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
108         } tpk;
109         int tpk_set;
110         int tpk_success;
111
112         struct tpk_timer {
113                 u8 dest[ETH_ALEN];
114                 int count;      /* Retry Count */
115                 int timer;      /* Timeout in milliseconds */
116                 u8 action_code; /* TDLS frame type */
117                 u8 dialog_token;
118                 u16 status_code;
119                 int buf_len;    /* length of TPK message for retransmission */
120                 u8 *buf;        /* buffer for TPK message */
121         } sm_tmr;
122 };
123
124
125 static int wpa_tdls_get_privacy(struct wpa_sm *sm)
126 {
127         /*
128          * Get info needed from supplicant to check if the current BSS supports
129          * security. Other than OPEN mode, rest are considered secured
130          * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake.
131          */
132         return sm->pairwise_cipher != WPA_CIPHER_NONE;
133 }
134
135
136 static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
137 {
138         os_memcpy(pos, ie, ie_len);
139         return pos + ie_len;
140 }
141
142
143 static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
144 {
145         if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr,
146                            0, 0, NULL, 0, NULL, 0) < 0) {
147                 wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
148                            "the driver");
149                 return -1;
150         }
151
152         return 0;
153 }
154
155
156 static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
157 {
158         u8 key_len;
159         u8 rsc[6];
160         enum wpa_alg alg;
161
162         os_memset(rsc, 0, 6);
163
164         switch (peer->cipher) {
165         case WPA_CIPHER_CCMP:
166                 alg = WPA_ALG_CCMP;
167                 key_len = 16;
168                 break;
169         case WPA_CIPHER_NONE:
170                 wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: "
171                            "NONE - do not use pairwise keys");
172                 return -1;
173         default:
174                 wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d",
175                            sm->pairwise_cipher);
176                 return -1;
177         }
178
179         if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
180                            rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
181                 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
182                            "driver");
183                 return -1;
184         }
185         return 0;
186 }
187
188
189 static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
190                                  u8 action_code, u8 dialog_token,
191                                  u16 status_code, const u8 *buf, size_t len)
192 {
193         return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
194                                      status_code, buf, len);
195 }
196
197
198 static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
199                              u8 dialog_token, u16 status_code,
200                              const u8 *msg, size_t msg_len)
201 {
202         struct wpa_tdls_peer *peer;
203
204         wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
205                    "dialog_token=%u status_code=%u msg_len=%u",
206                    MAC2STR(dest), action_code, dialog_token, status_code,
207                    (unsigned int) msg_len);
208
209         if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
210                                   status_code, msg, msg_len)) {
211                 wpa_printf(MSG_INFO, "TDLS: Failed to send message "
212                            "(action_code=%u)", action_code);
213                 return -1;
214         }
215
216         if (action_code == WLAN_TDLS_SETUP_CONFIRM ||
217             action_code == WLAN_TDLS_TEARDOWN ||
218             action_code == WLAN_TDLS_DISCOVERY_REQUEST ||
219             action_code == WLAN_TDLS_DISCOVERY_RESPONSE)
220                 return 0; /* No retries */
221
222         for (peer = sm->tdls; peer; peer = peer->next) {
223                 if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
224                         break;
225         }
226
227         if (peer == NULL) {
228                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
229                            "retry " MACSTR, MAC2STR(dest));
230                 return 0;
231         }
232
233         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
234
235         peer->sm_tmr.count = TPK_RETRY_COUNT;
236         peer->sm_tmr.timer = TPK_TIMEOUT;
237
238         /* Copy message to resend on timeout */
239         os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
240         peer->sm_tmr.action_code = action_code;
241         peer->sm_tmr.dialog_token = dialog_token;
242         peer->sm_tmr.status_code = status_code;
243         peer->sm_tmr.buf_len = msg_len;
244         os_free(peer->sm_tmr.buf);
245         peer->sm_tmr.buf = os_malloc(msg_len);
246         if (peer->sm_tmr.buf == NULL)
247                 return -1;
248         os_memcpy(peer->sm_tmr.buf, msg, msg_len);
249
250         wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
251                    "(action_code=%u)", action_code);
252         eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
253                                wpa_tdls_tpk_retry_timeout, sm, peer);
254         return 0;
255 }
256
257
258 static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
259                                 u16 reason_code)
260 {
261         int ret;
262
263         if (sm->tdls_external_setup) {
264                 ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
265
266                 /* disable the link after teardown was sent */
267                 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
268         } else {
269                 ret = wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
270         }
271
272         wpa_tdls_peer_free(sm, peer);
273
274         return ret;
275 }
276
277
278 static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
279 {
280
281         struct wpa_sm *sm = eloop_ctx;
282         struct wpa_tdls_peer *peer = timeout_ctx;
283
284         if (peer->sm_tmr.count) {
285                 peer->sm_tmr.count--;
286                 peer->sm_tmr.timer = TPK_TIMEOUT;
287
288                 wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
289                            "(action_code=%u)",
290                            peer->sm_tmr.action_code);
291
292                 if (peer->sm_tmr.buf == NULL) {
293                         wpa_printf(MSG_INFO, "TDLS: No retry buffer available "
294                                    "for action_code=%u",
295                                    peer->sm_tmr.action_code);
296                         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm,
297                                              peer);
298                         return;
299                 }
300
301                 /* resend TPK Handshake Message to Peer */
302                 if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest,
303                                           peer->sm_tmr.action_code,
304                                           peer->sm_tmr.dialog_token,
305                                           peer->sm_tmr.status_code,
306                                           peer->sm_tmr.buf,
307                                           peer->sm_tmr.buf_len)) {
308                         wpa_printf(MSG_INFO, "TDLS: Failed to retry "
309                                    "transmission");
310                 }
311
312                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
313                 eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
314                                        wpa_tdls_tpk_retry_timeout, sm, peer);
315         } else {
316                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
317
318                 wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
319                 wpa_tdls_do_teardown(sm, peer,
320                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
321         }
322 }
323
324
325 static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm,
326                                               struct wpa_tdls_peer *peer,
327                                               u8 action_code)
328 {
329         if (action_code == peer->sm_tmr.action_code) {
330                 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for "
331                            "action_code=%u", action_code);
332
333                 /* Cancel Timeout registered */
334                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
335
336                 /* free all resources meant for retry */
337                 os_free(peer->sm_tmr.buf);
338                 peer->sm_tmr.buf = NULL;
339
340                 peer->sm_tmr.count = 0;
341                 peer->sm_tmr.timer = 0;
342                 peer->sm_tmr.buf_len = 0;
343                 peer->sm_tmr.action_code = 0xff;
344         } else {
345                 wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout "
346                            "(Unknown action_code=%u)", action_code);
347         }
348 }
349
350
351 static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer,
352                                   const u8 *own_addr, const u8 *bssid)
353 {
354         u8 key_input[SHA256_MAC_LEN];
355         const u8 *nonce[2];
356         size_t len[2];
357         u8 data[3 * ETH_ALEN];
358
359         /* IEEE Std 802.11z-2010 8.5.9.1:
360          * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
361          */
362         len[0] = WPA_NONCE_LEN;
363         len[1] = WPA_NONCE_LEN;
364         if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) {
365                 nonce[0] = peer->inonce;
366                 nonce[1] = peer->rnonce;
367         } else {
368                 nonce[0] = peer->rnonce;
369                 nonce[1] = peer->inonce;
370         }
371         wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN);
372         wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN);
373         sha256_vector(2, nonce, len, key_input);
374         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
375                         key_input, SHA256_MAC_LEN);
376
377         /*
378          * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
379          *      min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
380          * TODO: is N_KEY really included in KDF Context and if so, in which
381          * presentation format (little endian 16-bit?) is it used? It gets
382          * added by the KDF anyway..
383          */
384
385         if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) {
386                 os_memcpy(data, own_addr, ETH_ALEN);
387                 os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN);
388         } else {
389                 os_memcpy(data, peer->addr, ETH_ALEN);
390                 os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
391         }
392         os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
393         wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
394
395         sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
396                    (u8 *) &peer->tpk, sizeof(peer->tpk));
397         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
398                         peer->tpk.kck, sizeof(peer->tpk.kck));
399         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
400                         peer->tpk.tk, sizeof(peer->tpk.tk));
401         peer->tpk_set = 1;
402 }
403
404
405 /**
406  * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
407  * @kck: TPK-KCK
408  * @lnkid: Pointer to the beginning of Link Identifier IE
409  * @rsnie: Pointer to the beginning of RSN IE used for handshake
410  * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
411  * @ftie: Pointer to the beginning of FT IE
412  * @mic: Pointer for writing MIC
413  *
414  * Calculate MIC for TDLS frame.
415  */
416 static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid,
417                              const u8 *rsnie, const u8 *timeoutie,
418                              const u8 *ftie, u8 *mic)
419 {
420         u8 *buf, *pos;
421         struct wpa_tdls_ftie *_ftie;
422         const struct wpa_tdls_lnkid *_lnkid;
423         int ret;
424         int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] +
425                 2 + timeoutie[1] + 2 + ftie[1];
426         buf = os_zalloc(len);
427         if (!buf) {
428                 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
429                 return -1;
430         }
431
432         pos = buf;
433         _lnkid = (const struct wpa_tdls_lnkid *) lnkid;
434         /* 1) TDLS initiator STA MAC address */
435         os_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
436         pos += ETH_ALEN;
437         /* 2) TDLS responder STA MAC address */
438         os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
439         pos += ETH_ALEN;
440         /* 3) Transaction Sequence number */
441         *pos++ = trans_seq;
442         /* 4) Link Identifier IE */
443         os_memcpy(pos, lnkid, 2 + lnkid[1]);
444         pos += 2 + lnkid[1];
445         /* 5) RSN IE */
446         os_memcpy(pos, rsnie, 2 + rsnie[1]);
447         pos += 2 + rsnie[1];
448         /* 6) Timeout Interval IE */
449         os_memcpy(pos, timeoutie, 2 + timeoutie[1]);
450         pos += 2 + timeoutie[1];
451         /* 7) FTIE, with the MIC field of the FTIE set to 0 */
452         os_memcpy(pos, ftie, 2 + ftie[1]);
453         _ftie = (struct wpa_tdls_ftie *) pos;
454         os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
455         pos += 2 + ftie[1];
456
457         wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
458         wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
459         ret = omac1_aes_128(kck, buf, pos - buf, mic);
460         os_free(buf);
461         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
462         return ret;
463 }
464
465
466 /**
467  * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame
468  * @kck: TPK-KCK
469  * @trans_seq: Transaction Sequence Number (4 - Teardown)
470  * @rcode: Reason code for Teardown
471  * @dtoken: Dialog Token used for that particular link
472  * @lnkid: Pointer to the beginning of Link Identifier IE
473  * @ftie: Pointer to the beginning of FT IE
474  * @mic: Pointer for writing MIC
475  *
476  * Calculate MIC for TDLS frame.
477  */
478 static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode,
479                                      u8 dtoken, const u8 *lnkid,
480                                      const u8 *ftie, u8 *mic)
481 {
482         u8 *buf, *pos;
483         struct wpa_tdls_ftie *_ftie;
484         int ret;
485         int len;
486
487         if (lnkid == NULL)
488                 return -1;
489
490         len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) +
491                 sizeof(trans_seq) + 2 + ftie[1];
492
493         buf = os_zalloc(len);
494         if (!buf) {
495                 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
496                 return -1;
497         }
498
499         pos = buf;
500         /* 1) Link Identifier IE */
501         os_memcpy(pos, lnkid, 2 + lnkid[1]);
502         pos += 2 + lnkid[1];
503         /* 2) Reason Code */
504         WPA_PUT_LE16(pos, rcode);
505         pos += sizeof(rcode);
506         /* 3) Dialog token */
507         *pos++ = dtoken;
508         /* 4) Transaction Sequence number */
509         *pos++ = trans_seq;
510         /* 7) FTIE, with the MIC field of the FTIE set to 0 */
511         os_memcpy(pos, ftie, 2 + ftie[1]);
512         _ftie = (struct wpa_tdls_ftie *) pos;
513         os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
514         pos += 2 + ftie[1];
515
516         wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
517         wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
518         ret = omac1_aes_128(kck, buf, pos - buf, mic);
519         os_free(buf);
520         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
521         return ret;
522 }
523
524
525 static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
526                                           struct wpa_tdls_peer *peer,
527                                           const u8 *lnkid, const u8 *timeoutie,
528                                           const struct wpa_tdls_ftie *ftie)
529 {
530         u8 mic[16];
531
532         if (peer->tpk_set) {
533                 wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
534                                   peer->rsnie_p, timeoutie, (u8 *) ftie,
535                                   mic);
536                 if (os_memcmp(mic, ftie->mic, 16) != 0) {
537                         wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
538                                    "dropping packet");
539                         wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
540                                     ftie->mic, 16);
541                         wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC",
542                                     mic, 16);
543                         return -1;
544                 }
545         } else {
546                 wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, "
547                            "TPK not set - dropping packet");
548                 return -1;
549         }
550         return 0;
551 }
552
553
554 static int wpa_supplicant_verify_tdls_mic_teardown(
555         u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer,
556         const u8 *lnkid, const struct wpa_tdls_ftie *ftie)
557 {
558         u8 mic[16];
559
560         if (peer->tpk_set) {
561                 wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
562                                           dtoken, lnkid, (u8 *) ftie, mic);
563                 if (os_memcmp(mic, ftie->mic, 16) != 0) {
564                         wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
565                                    "dropping packet");
566                         return -1;
567                 }
568         } else {
569                 wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown "
570                            "MIC, TPK not set - dropping packet");
571                 return -1;
572         }
573         return 0;
574 }
575
576
577 static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
578 {
579         struct wpa_sm *sm = eloop_ctx;
580         struct wpa_tdls_peer *peer = timeout_ctx;
581
582         /*
583          * On TPK lifetime expiration, we have an option of either tearing down
584          * the direct link or trying to re-initiate it. The selection of what
585          * to do is not strictly speaking controlled by our role in the expired
586          * link, but for now, use that to select whether to renew or tear down
587          * the link.
588          */
589
590         if (peer->initiator) {
591                 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
592                            " - try to renew", MAC2STR(peer->addr));
593                 wpa_tdls_start(sm, peer->addr);
594         } else {
595                 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
596                            " - tear down", MAC2STR(peer->addr));
597                 wpa_tdls_do_teardown(sm, peer,
598                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
599         }
600 }
601
602
603 static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
604 {
605         wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
606                    MAC2STR(peer->addr));
607         eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
608         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
609         peer->initiator = 0;
610         os_free(peer->sm_tmr.buf);
611         peer->sm_tmr.buf = NULL;
612         peer->rsnie_i_len = peer->rsnie_p_len = 0;
613         peer->cipher = 0;
614         peer->tpk_set = peer->tpk_success = 0;
615         os_memset(&peer->tpk, 0, sizeof(peer->tpk));
616         os_memset(peer->inonce, 0, WPA_NONCE_LEN);
617         os_memset(peer->rnonce, 0, WPA_NONCE_LEN);
618 }
619
620
621 static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
622                             struct wpa_tdls_lnkid *lnkid)
623 {
624         lnkid->ie_type = WLAN_EID_LINK_ID;
625         lnkid->ie_len = 3 * ETH_ALEN;
626         os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN);
627         if (peer->initiator) {
628                 os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN);
629                 os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN);
630         } else {
631                 os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN);
632                 os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN);
633         }
634 }
635
636
637 int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
638 {
639         struct wpa_tdls_peer *peer;
640         struct wpa_tdls_ftie *ftie;
641         struct wpa_tdls_lnkid lnkid;
642         u8 dialog_token;
643         u8 *rbuf, *pos;
644         int ielen;
645
646         if (sm->tdls_disabled || !sm->tdls_supported)
647                 return -1;
648
649         /* Find the node and free from the list */
650         for (peer = sm->tdls; peer; peer = peer->next) {
651                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
652                         break;
653         }
654
655         if (peer == NULL) {
656                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
657                            "Teardown " MACSTR, MAC2STR(addr));
658                 return 0;
659         }
660
661         dialog_token = peer->dtoken;
662
663         wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR,
664                    MAC2STR(addr));
665
666         ielen = 0;
667         if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) {
668                 /* To add FTIE for Teardown request and compute MIC */
669                 ielen += sizeof(*ftie);
670 #ifdef CONFIG_TDLS_TESTING
671                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
672                         ielen += 170;
673 #endif /* CONFIG_TDLS_TESTING */
674         }
675
676         rbuf = os_zalloc(ielen + 1);
677         if (rbuf == NULL)
678                 return -1;
679         pos = rbuf;
680
681         if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
682                 goto skip_ies;
683
684         ftie = (struct wpa_tdls_ftie *) pos;
685         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
686         /* Using the recent nonce which should be for CONFIRM frame */
687         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
688         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
689         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
690         pos = (u8 *) (ftie + 1);
691 #ifdef CONFIG_TDLS_TESTING
692         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
693                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
694                            "FTIE");
695                 ftie->ie_len += 170;
696                 *pos++ = 255; /* FTIE subelem */
697                 *pos++ = 168; /* FTIE subelem length */
698         }
699 #endif /* CONFIG_TDLS_TESTING */
700         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake",
701                     (u8 *) ftie, sizeof(*ftie));
702
703         /* compute MIC before sending */
704         wpa_tdls_linkid(sm, peer, &lnkid);
705         wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code,
706                                   dialog_token, (u8 *) &lnkid, (u8 *) ftie,
707                                   ftie->mic);
708
709 skip_ies:
710         /* TODO: register for a Timeout handler, if Teardown is not received at
711          * the other end, then try again another time */
712
713         /* request driver to send Teardown using this FTIE */
714         wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
715                           WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, rbuf,
716                           pos - rbuf);
717         os_free(rbuf);
718
719         /* clear the Peerkey statemachine */
720         wpa_tdls_peer_free(sm, peer);
721
722         return 0;
723 }
724
725
726 int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
727 {
728         struct wpa_tdls_peer *peer;
729
730         if (sm->tdls_disabled || !sm->tdls_supported)
731                 return -1;
732
733         for (peer = sm->tdls; peer; peer = peer->next) {
734                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
735                         break;
736         }
737
738         if (peer == NULL) {
739                 wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
740                    " for link Teardown", MAC2STR(addr));
741                 return -1;
742         }
743
744         if (!peer->tpk_success) {
745                 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
746                    " not connected - cannot Teardown link", MAC2STR(addr));
747                 return -1;
748         }
749
750         return wpa_tdls_do_teardown(sm, peer, reason_code);
751 }
752
753
754 static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
755                                   const u8 *buf, size_t len)
756 {
757         struct wpa_tdls_peer *peer = NULL;
758         struct wpa_tdls_ftie *ftie;
759         struct wpa_tdls_lnkid *lnkid;
760         struct wpa_eapol_ie_parse kde;
761         u16 reason_code;
762         const u8 *pos;
763         int ielen;
764
765         /* Find the node and free from the list */
766         for (peer = sm->tdls; peer; peer = peer->next) {
767                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
768                         break;
769         }
770
771         if (peer == NULL) {
772                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
773                            "Teardown " MACSTR, MAC2STR(src_addr));
774                 return 0;
775         }
776
777         pos = buf;
778         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
779
780         reason_code = WPA_GET_LE16(pos);
781         pos += 2;
782
783         wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR
784                    " (reason code %u)", MAC2STR(src_addr), reason_code);
785
786         ielen = len - (pos - buf); /* start of IE in buf */
787         if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
788                 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown");
789                 return -1;
790         }
791
792         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
793                 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
794                            "Teardown");
795                 return -1;
796         }
797         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
798
799         if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
800                 goto skip_ftie;
801
802         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
803                 wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown");
804                 return -1;
805         }
806
807         ftie = (struct wpa_tdls_ftie *) kde.ftie;
808
809         /* Process MIC check to see if TDLS Teardown is right */
810         if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code,
811                                                     peer->dtoken, peer,
812                                                     (u8 *) lnkid, ftie) < 0) {
813                 wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS "
814                            "Teardown Request from " MACSTR, MAC2STR(src_addr));
815                 return -1;
816         }
817
818 skip_ftie:
819         /*
820          * Request the driver to disable the direct link and clear associated
821          * keys.
822          */
823         wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr);
824
825         /* clear the Peerkey statemachine */
826         wpa_tdls_peer_free(sm, peer);
827
828         return 0;
829 }
830
831
832 /**
833  * wpa_tdls_send_error - To send suitable TDLS status response with
834  *      appropriate status code mentioning reason for error/failure.
835  * @dst         - MAC addr of Peer station
836  * @tdls_action - TDLS frame type for which error code is sent
837  * @status      - status code mentioning reason
838  */
839
840 static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
841                                u8 tdls_action, u8 dialog_token, u16 status)
842 {
843         wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
844                    " (action=%u status=%u)",
845                    MAC2STR(dst), tdls_action, status);
846         return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
847                                  NULL, 0);
848 }
849
850
851 static struct wpa_tdls_peer *
852 wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr)
853 {
854         struct wpa_tdls_peer *peer;
855
856         wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
857                    MAC2STR(addr));
858
859         peer = os_zalloc(sizeof(*peer));
860         if (peer == NULL)
861                 return NULL;
862
863         os_memcpy(peer->addr, addr, ETH_ALEN);
864         peer->next = sm->tdls;
865         sm->tdls = peer;
866
867         return peer;
868 }
869
870
871 static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
872                                 struct wpa_tdls_peer *peer)
873 {
874         size_t buf_len;
875         struct wpa_tdls_timeoutie timeoutie;
876         u16 rsn_capab;
877         struct wpa_tdls_ftie *ftie;
878         u8 *rbuf, *pos, *count_pos;
879         u16 count;
880         struct rsn_ie_hdr *hdr;
881
882         if (!wpa_tdls_get_privacy(sm)) {
883                 wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
884                 peer->rsnie_i_len = 0;
885                 goto skip_rsnie;
886         }
887
888         /*
889          * TPK Handshake Message 1:
890          * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I,
891          * Timeout Interval IE))
892          */
893
894         /* Filling RSN IE */
895         hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
896         hdr->elem_id = WLAN_EID_RSN;
897         WPA_PUT_LE16(hdr->version, RSN_VERSION);
898
899         pos = (u8 *) (hdr + 1);
900         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
901         pos += RSN_SELECTOR_LEN;
902         count_pos = pos;
903         pos += 2;
904
905         count = 0;
906
907         /*
908          * AES-CCMP is the default Encryption preferred for TDLS, so
909          * RSN IE is filled only with CCMP CIPHER
910          * Note: TKIP is not used to encrypt TDLS link.
911          *
912          * Regardless of the cipher used on the AP connection, select CCMP
913          * here.
914          */
915         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
916         pos += RSN_SELECTOR_LEN;
917         count++;
918
919         WPA_PUT_LE16(count_pos, count);
920
921         WPA_PUT_LE16(pos, 1);
922         pos += 2;
923         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
924         pos += RSN_SELECTOR_LEN;
925
926         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
927         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
928 #ifdef CONFIG_TDLS_TESTING
929         if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
930                 wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
931                            "testing");
932                 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
933         }
934 #endif /* CONFIG_TDLS_TESTING */
935         WPA_PUT_LE16(pos, rsn_capab);
936         pos += 2;
937 #ifdef CONFIG_TDLS_TESTING
938         if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
939                 /* Number of PMKIDs */
940                 *pos++ = 0x00;
941                 *pos++ = 0x00;
942         }
943 #endif /* CONFIG_TDLS_TESTING */
944
945         hdr->len = (pos - peer->rsnie_i) - 2;
946         peer->rsnie_i_len = pos - peer->rsnie_i;
947         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
948                     peer->rsnie_i, peer->rsnie_i_len);
949
950 skip_rsnie:
951         buf_len = 0;
952         if (wpa_tdls_get_privacy(sm))
953                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
954                         sizeof(struct wpa_tdls_timeoutie);
955 #ifdef CONFIG_TDLS_TESTING
956         if (wpa_tdls_get_privacy(sm) &&
957             (tdls_testing & TDLS_TESTING_LONG_FRAME))
958                 buf_len += 170;
959         if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
960                 buf_len += sizeof(struct wpa_tdls_lnkid);
961 #endif /* CONFIG_TDLS_TESTING */
962         rbuf = os_zalloc(buf_len + 1);
963         if (rbuf == NULL) {
964                 wpa_tdls_peer_free(sm, peer);
965                 return -1;
966         }
967         pos = rbuf;
968
969         if (!wpa_tdls_get_privacy(sm))
970                 goto skip_ies;
971
972         /* Initiator RSN IE */
973         pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
974
975         ftie = (struct wpa_tdls_ftie *) pos;
976         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
977         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
978
979         if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
980                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
981                         "TDLS: Failed to get random data for initiator Nonce");
982                 os_free(rbuf);
983                 wpa_tdls_peer_free(sm, peer);
984                 return -1;
985         }
986         wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
987                     peer->inonce, WPA_NONCE_LEN);
988         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
989
990         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
991                     (u8 *) ftie, sizeof(struct wpa_tdls_ftie));
992
993         pos = (u8 *) (ftie + 1);
994
995 #ifdef CONFIG_TDLS_TESTING
996         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
997                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
998                            "FTIE");
999                 ftie->ie_len += 170;
1000                 *pos++ = 255; /* FTIE subelem */
1001                 *pos++ = 168; /* FTIE subelem length */
1002                 pos += 168;
1003         }
1004 #endif /* CONFIG_TDLS_TESTING */
1005
1006         /* Lifetime */
1007         peer->lifetime = TPK_LIFETIME;
1008 #ifdef CONFIG_TDLS_TESTING
1009         if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
1010                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
1011                            "lifetime");
1012                 peer->lifetime = 301;
1013         }
1014         if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) {
1015                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK "
1016                            "lifetime");
1017                 peer->lifetime = 0xffffffff;
1018         }
1019 #endif /* CONFIG_TDLS_TESTING */
1020         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1021                                      sizeof(timeoutie), peer->lifetime);
1022         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1023
1024 skip_ies:
1025
1026 #ifdef CONFIG_TDLS_TESTING
1027         if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
1028                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
1029                            "Link Identifier");
1030                 struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
1031                 wpa_tdls_linkid(sm, peer, l);
1032                 l->bssid[5] ^= 0x01;
1033                 pos += sizeof(*l);
1034         }
1035 #endif /* CONFIG_TDLS_TESTING */
1036
1037         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
1038                    "Handshake Message 1 (peer " MACSTR ")",
1039                    MAC2STR(peer->addr));
1040
1041         wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 1, 0,
1042                           rbuf, pos - rbuf);
1043         os_free(rbuf);
1044
1045         return 0;
1046 }
1047
1048
1049 static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
1050                                 const unsigned char *src_addr, u8 dtoken,
1051                                 struct wpa_tdls_lnkid *lnkid,
1052                                 const struct wpa_tdls_peer *peer)
1053 {
1054         u8 *rbuf, *pos;
1055         size_t buf_len;
1056         u32 lifetime;
1057         struct wpa_tdls_timeoutie timeoutie;
1058         struct wpa_tdls_ftie *ftie;
1059
1060         buf_len = 0;
1061         if (wpa_tdls_get_privacy(sm)) {
1062                 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1063                  * Lifetime */
1064                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1065                         sizeof(struct wpa_tdls_timeoutie);
1066 #ifdef CONFIG_TDLS_TESTING
1067                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1068                         buf_len += 170;
1069 #endif /* CONFIG_TDLS_TESTING */
1070         }
1071
1072         rbuf = os_zalloc(buf_len + 1);
1073         if (rbuf == NULL)
1074                 return -1;
1075         pos = rbuf;
1076
1077         if (!wpa_tdls_get_privacy(sm))
1078                 goto skip_ies;
1079
1080         /* Peer RSN IE */
1081         pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1082
1083         ftie = (struct wpa_tdls_ftie *) pos;
1084         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1085         /* TODO: ftie->mic_control to set 2-RESPONSE */
1086         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1087         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1088         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1089         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2",
1090                     (u8 *) ftie, sizeof(*ftie));
1091
1092         pos = (u8 *) (ftie + 1);
1093
1094 #ifdef CONFIG_TDLS_TESTING
1095         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1096                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1097                            "FTIE");
1098                 ftie->ie_len += 170;
1099                 *pos++ = 255; /* FTIE subelem */
1100                 *pos++ = 168; /* FTIE subelem length */
1101                 pos += 168;
1102         }
1103 #endif /* CONFIG_TDLS_TESTING */
1104
1105         /* Lifetime */
1106         lifetime = peer->lifetime;
1107 #ifdef CONFIG_TDLS_TESTING
1108         if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) {
1109                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1110                            "lifetime in response");
1111                 lifetime++;
1112         }
1113 #endif /* CONFIG_TDLS_TESTING */
1114         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1115                                      sizeof(timeoutie), lifetime);
1116         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator",
1117                    lifetime);
1118
1119         /* compute MIC before sending */
1120         wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p,
1121                           (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
1122
1123 skip_ies:
1124         wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
1125                           rbuf, pos - rbuf);
1126         os_free(rbuf);
1127
1128         return 0;
1129 }
1130
1131
1132 static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm,
1133                                 const unsigned char *src_addr, u8 dtoken,
1134                                 struct wpa_tdls_lnkid *lnkid,
1135                                 const struct wpa_tdls_peer *peer)
1136 {
1137         u8 *rbuf, *pos;
1138         size_t buf_len;
1139         struct wpa_tdls_ftie *ftie;
1140         struct wpa_tdls_timeoutie timeoutie;
1141         u32 lifetime;
1142
1143         buf_len = 0;
1144         if (wpa_tdls_get_privacy(sm)) {
1145                 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1146                  * Lifetime */
1147                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1148                         sizeof(struct wpa_tdls_timeoutie);
1149 #ifdef CONFIG_TDLS_TESTING
1150                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1151                         buf_len += 170;
1152 #endif /* CONFIG_TDLS_TESTING */
1153         }
1154
1155         rbuf = os_zalloc(buf_len + 1);
1156         if (rbuf == NULL)
1157                 return -1;
1158         pos = rbuf;
1159
1160         if (!wpa_tdls_get_privacy(sm))
1161                 goto skip_ies;
1162
1163         /* Peer RSN IE */
1164         pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1165
1166         ftie = (struct wpa_tdls_ftie *) pos;
1167         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1168         /*TODO: ftie->mic_control to set 3-CONFIRM */
1169         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1170         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1171         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1172
1173         pos = (u8 *) (ftie + 1);
1174
1175 #ifdef CONFIG_TDLS_TESTING
1176         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1177                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1178                            "FTIE");
1179                 ftie->ie_len += 170;
1180                 *pos++ = 255; /* FTIE subelem */
1181                 *pos++ = 168; /* FTIE subelem length */
1182                 pos += 168;
1183         }
1184 #endif /* CONFIG_TDLS_TESTING */
1185
1186         /* Lifetime */
1187         lifetime = peer->lifetime;
1188 #ifdef CONFIG_TDLS_TESTING
1189         if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) {
1190                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1191                            "lifetime in confirm");
1192                 lifetime++;
1193         }
1194 #endif /* CONFIG_TDLS_TESTING */
1195         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1196                                      sizeof(timeoutie), lifetime);
1197         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds",
1198                    lifetime);
1199
1200         /* compute MIC before sending */
1201         wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p,
1202                           (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
1203
1204 skip_ies:
1205         wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 0,
1206                           rbuf, pos - rbuf);
1207         os_free(rbuf);
1208
1209         return 0;
1210 }
1211
1212
1213 static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
1214                                             struct wpa_tdls_peer *peer,
1215                                             u8 dialog_token)
1216 {
1217         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
1218                    "(peer " MACSTR ")", MAC2STR(peer->addr));
1219
1220         return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
1221                                  dialog_token, 0, NULL, 0);
1222 }
1223
1224
1225 static int
1226 wpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr,
1227                                    const u8 *buf, size_t len)
1228 {
1229         struct wpa_eapol_ie_parse kde;
1230         const struct wpa_tdls_lnkid *lnkid;
1231         struct wpa_tdls_peer *peer;
1232         size_t min_req_len = sizeof(struct wpa_tdls_frame) +
1233                 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid);
1234         u8 dialog_token;
1235
1236         wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR,
1237                    MAC2STR(addr));
1238
1239         if (len < min_req_len) {
1240                 wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: "
1241                            "%d", (int) len);
1242                 return -1;
1243         }
1244
1245         dialog_token = buf[sizeof(struct wpa_tdls_frame)];
1246
1247         if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
1248                                      len - (sizeof(struct wpa_tdls_frame) + 1),
1249                                      &kde) < 0)
1250                 return -1;
1251
1252         if (!kde.lnkid) {
1253                 wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
1254                            "Request");
1255                 return -1;
1256         }
1257
1258         lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid;
1259
1260         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1261                 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different "
1262                            " BSS " MACSTR, MAC2STR(lnkid->bssid));
1263                 return -1;
1264         }
1265
1266         peer = wpa_tdls_add_peer(sm, addr);
1267         if (peer == NULL)
1268                 return -1;
1269
1270         return wpa_tdls_send_discovery_response(sm, peer, dialog_token);
1271 }
1272
1273
1274 int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
1275 {
1276         if (sm->tdls_disabled || !sm->tdls_supported)
1277                 return -1;
1278
1279         wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
1280                    MACSTR, MAC2STR(addr));
1281         return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
1282                                  1, 0, NULL, 0);
1283 }
1284
1285
1286 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
1287                                    const u8 *buf, size_t len)
1288 {
1289         struct wpa_tdls_peer *peer;
1290         struct wpa_eapol_ie_parse kde;
1291         struct wpa_ie_data ie;
1292         int cipher;
1293         const u8 *cpos;
1294         struct wpa_tdls_ftie *ftie = NULL;
1295         struct wpa_tdls_timeoutie *timeoutie;
1296         struct wpa_tdls_lnkid *lnkid;
1297         u32 lifetime = 0;
1298 #if 0
1299         struct rsn_ie_hdr *hdr;
1300         u8 *pos;
1301         u16 rsn_capab;
1302         u16 rsn_ver;
1303 #endif
1304         u8 dtoken;
1305         u16 ielen;
1306         u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1307         int tdls_prohibited = sm->tdls_prohibited;
1308
1309         if (len < 3 + 3)
1310                 return -1;
1311
1312         cpos = buf;
1313         cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1314
1315         /* driver had already verified the frame format */
1316         dtoken = *cpos++; /* dialog token */
1317
1318         wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
1319
1320         cpos += 2; /* capability information */
1321
1322         ielen = len - (cpos - buf); /* start of IE in buf */
1323         if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) {
1324                 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1");
1325                 goto error;
1326         }
1327
1328         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1329                 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1330                            "TPK M1");
1331                 goto error;
1332         }
1333         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1",
1334                     kde.lnkid, kde.lnkid_len);
1335         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1336         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1337                 wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
1338                 status = WLAN_STATUS_NOT_IN_SAME_BSS;
1339                 goto error;
1340         }
1341
1342         wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
1343                    MAC2STR(src_addr));
1344
1345 #ifdef CONFIG_TDLS_TESTING
1346         if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
1347                 for (peer = sm->tdls; peer; peer = peer->next) {
1348                         if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1349                                 break;
1350                 }
1351                 if (peer == NULL) {
1352                         peer = os_zalloc(sizeof(*peer));
1353                         if (peer == NULL)
1354                                 goto error;
1355                         os_memcpy(peer->addr, src_addr, ETH_ALEN);
1356                         peer->next = sm->tdls;
1357                         sm->tdls = peer;
1358                 }
1359                 wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
1360                            "TDLS setup - send own request");
1361                 peer->initiator = 1;
1362                 wpa_tdls_send_tpk_m1(sm, peer);
1363         }
1364
1365         if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
1366             tdls_prohibited) {
1367                 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
1368                            "on TDLS");
1369                 tdls_prohibited = 0;
1370         }
1371 #endif /* CONFIG_TDLS_TESTING */
1372
1373         if (tdls_prohibited) {
1374                 wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
1375                 status = WLAN_STATUS_REQUEST_DECLINED;
1376                 goto error;
1377         }
1378
1379         if (!wpa_tdls_get_privacy(sm)) {
1380                 if (kde.rsn_ie) {
1381                         wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
1382                                    "security is disabled");
1383                         status = WLAN_STATUS_SECURITY_DISABLED;
1384                         goto error;
1385                 }
1386                 goto skip_rsn;
1387         }
1388
1389         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
1390             kde.rsn_ie == NULL) {
1391                 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1");
1392                 status = WLAN_STATUS_INVALID_PARAMETERS;
1393                 goto error;
1394         }
1395
1396         if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
1397                 wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in "
1398                            "TPK M1");
1399                 status = WLAN_STATUS_INVALID_RSNIE;
1400                 goto error;
1401         }
1402
1403         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
1404                 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1");
1405                 status = WLAN_STATUS_INVALID_RSNIE;
1406                 goto error;
1407         }
1408
1409         cipher = ie.pairwise_cipher;
1410         if (cipher & WPA_CIPHER_CCMP) {
1411                 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
1412                 cipher = WPA_CIPHER_CCMP;
1413         } else {
1414                 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1");
1415                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1416                 goto error;
1417         }
1418
1419         if ((ie.capabilities &
1420              (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) !=
1421             WPA_CAPABILITY_PEERKEY_ENABLED) {
1422                 wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in "
1423                            "TPK M1");
1424                 status = WLAN_STATUS_INVALID_RSN_IE_CAPAB;
1425                 goto error;
1426         }
1427
1428         /* Lifetime */
1429         if (kde.key_lifetime == NULL) {
1430                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1");
1431                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1432                 goto error;
1433         }
1434         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1435         lifetime = WPA_GET_LE32(timeoutie->value);
1436         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime);
1437         if (lifetime < 300) {
1438                 wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime");
1439                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1440                 goto error;
1441         }
1442
1443 skip_rsn:
1444         /* Find existing entry and if found, use that instead of adding
1445          * a new one; how to handle the case where both ends initiate at the
1446          * same time? */
1447         for (peer = sm->tdls; peer; peer = peer->next) {
1448                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1449                         break;
1450         }
1451
1452         if (peer == NULL) {
1453                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
1454                            "peer, creating one for " MACSTR,
1455                            MAC2STR(src_addr));
1456                 peer = os_malloc(sizeof(*peer));
1457                 if (peer == NULL)
1458                         goto error;
1459                 os_memset(peer, 0, sizeof(*peer));
1460                 os_memcpy(peer->addr, src_addr, ETH_ALEN);
1461                 peer->next = sm->tdls;
1462                 sm->tdls = peer;
1463         } else {
1464                 if (peer->tpk_success) {
1465                         wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
1466                                    "direct link is enabled - tear down the "
1467                                    "old link first");
1468 #if 0
1469                         /* TODO: Disabling the link would be more proper
1470                          * operation here, but it seems to trigger a race with
1471                          * some drivers handling the new request frame. */
1472                         wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr);
1473 #else
1474                         wpa_tdls_del_key(sm, peer);
1475 #endif
1476                         wpa_tdls_peer_free(sm, peer);
1477                 }
1478
1479                 /*
1480                  * An entry is already present, so check if we already sent a
1481                  * TDLS Setup Request. If so, compare MAC addresses and let the
1482                  * STA with the lower MAC address continue as the initiator.
1483                  * The other negotiation is terminated.
1484                  */
1485                 if (peer->initiator) {
1486                         if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
1487                                 wpa_printf(MSG_DEBUG, "TDLS: Discard request "
1488                                            "from peer with higher address "
1489                                            MACSTR, MAC2STR(src_addr));
1490                                 return -1;
1491                         } else {
1492                                 wpa_printf(MSG_DEBUG, "TDLS: Accept request "
1493                                            "from peer with lower address "
1494                                            MACSTR " (terminate previously "
1495                                            "initiated negotiation",
1496                                            MAC2STR(src_addr));
1497                                 wpa_tdls_peer_free(sm, peer);
1498                         }
1499                 }
1500         }
1501
1502         peer->initiator = 0; /* Need to check */
1503         peer->dtoken = dtoken;
1504
1505         if (!wpa_tdls_get_privacy(sm)) {
1506                 peer->rsnie_i_len = 0;
1507                 peer->rsnie_p_len = 0;
1508                 peer->cipher = WPA_CIPHER_NONE;
1509                 goto skip_rsn_check;
1510         }
1511
1512         ftie = (struct wpa_tdls_ftie *) kde.ftie;
1513         os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN);
1514         os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
1515         peer->rsnie_i_len = kde.rsn_ie_len;
1516         peer->cipher = cipher;
1517
1518         if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
1519                 wpa_msg(sm->ctx->ctx, MSG_WARNING,
1520                         "TDLS: Failed to get random data for responder nonce");
1521                 wpa_tdls_peer_free(sm, peer);
1522                 goto error;
1523         }
1524
1525 #if 0
1526         /* get version info from RSNIE received from Peer */
1527         hdr = (struct rsn_ie_hdr *) kde.rsn_ie;
1528         rsn_ver = WPA_GET_LE16(hdr->version);
1529
1530         /* use min(peer's version, out version) */
1531         if (rsn_ver > RSN_VERSION)
1532                 rsn_ver = RSN_VERSION;
1533
1534         hdr = (struct rsn_ie_hdr *) peer->rsnie_p;
1535
1536         hdr->elem_id = WLAN_EID_RSN;
1537         WPA_PUT_LE16(hdr->version, rsn_ver);
1538         pos = (u8 *) (hdr + 1);
1539
1540         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1541         pos += RSN_SELECTOR_LEN;
1542         /* Include only the selected cipher in pairwise cipher suite */
1543         WPA_PUT_LE16(pos, 1);
1544         pos += 2;
1545         if (cipher == WPA_CIPHER_CCMP)
1546                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1547         pos += RSN_SELECTOR_LEN;
1548
1549         WPA_PUT_LE16(pos, 1);
1550         pos += 2;
1551         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1552         pos += RSN_SELECTOR_LEN;
1553
1554         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1555         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1556         WPA_PUT_LE16(pos, rsn_capab);
1557         pos += 2;
1558
1559         hdr->len = (pos - peer->rsnie_p) - 2;
1560         peer->rsnie_p_len = pos - peer->rsnie_p;
1561 #endif
1562
1563         /* temp fix: validation of RSNIE later */
1564         os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len);
1565         peer->rsnie_p_len = peer->rsnie_i_len;
1566
1567         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
1568                     peer->rsnie_p, peer->rsnie_p_len);
1569
1570         peer->lifetime = lifetime;
1571
1572         wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
1573
1574 skip_rsn_check:
1575         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
1576         wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer);
1577
1578         return 0;
1579
1580 error:
1581         wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken,
1582                             status);
1583         return -1;
1584 }
1585
1586
1587 static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
1588 {
1589         peer->tpk_success = 1;
1590         eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
1591         if (wpa_tdls_get_privacy(sm)) {
1592                 u32 lifetime = peer->lifetime;
1593                 /*
1594                  * Start the initiator process a bit earlier to avoid race
1595                  * condition with the responder sending teardown request.
1596                  */
1597                 if (lifetime > 3 && peer->initiator)
1598                         lifetime -= 3;
1599                 eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
1600                                        sm, peer);
1601 #ifdef CONFIG_TDLS_TESTING
1602         if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
1603                 wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK "
1604                            "expiration");
1605                 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
1606         }
1607 #endif /* CONFIG_TDLS_TESTING */
1608         }
1609         wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
1610 }
1611
1612
1613 static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
1614                                    const u8 *buf, size_t len)
1615 {
1616         struct wpa_tdls_peer *peer;
1617         struct wpa_eapol_ie_parse kde;
1618         struct wpa_ie_data ie;
1619         int cipher;
1620         struct wpa_tdls_ftie *ftie;
1621         struct wpa_tdls_timeoutie *timeoutie;
1622         struct wpa_tdls_lnkid *lnkid;
1623         u32 lifetime;
1624         u8 dtoken;
1625         int ielen;
1626         u16 status;
1627         const u8 *pos;
1628
1629         wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
1630                    "(Peer " MACSTR ")", MAC2STR(src_addr));
1631         for (peer = sm->tdls; peer; peer = peer->next) {
1632                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1633                         break;
1634         }
1635         if (peer == NULL) {
1636                 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
1637                            "TPK M2: " MACSTR, MAC2STR(src_addr));
1638                 return -1;
1639         }
1640         wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
1641
1642         if (len < 3 + 2 + 1)
1643                 return -1;
1644         pos = buf;
1645         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1646         status = WPA_GET_LE16(pos);
1647         pos += 2 /* status code */;
1648
1649         if (status != WLAN_STATUS_SUCCESS) {
1650                 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u",
1651                            status);
1652                 return -1;
1653         }
1654
1655         status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1656
1657         /* TODO: need to verify dialog token matches here or in kernel */
1658         dtoken = *pos++; /* dialog token */
1659
1660         wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken);
1661
1662         if (len < 3 + 2 + 1 + 2)
1663                 return -1;
1664         pos += 2; /* capability information */
1665
1666         ielen = len - (pos - buf); /* start of IE in buf */
1667         if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) {
1668                 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2");
1669                 goto error;
1670         }
1671
1672 #ifdef CONFIG_TDLS_TESTING
1673         if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
1674                 wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response");
1675                 status = WLAN_STATUS_REQUEST_DECLINED;
1676                 goto error;
1677         }
1678 #endif /* CONFIG_TDLS_TESTING */
1679
1680         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1681                 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1682                            "TPK M2");
1683                 goto error;
1684         }
1685         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2",
1686                     kde.lnkid, kde.lnkid_len);
1687         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1688
1689         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1690                 wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
1691                 status = WLAN_STATUS_NOT_IN_SAME_BSS;
1692                 goto error;
1693         }
1694
1695         if (!wpa_tdls_get_privacy(sm)) {
1696                 peer->rsnie_p_len = 0;
1697                 peer->cipher = WPA_CIPHER_NONE;
1698                 goto skip_rsn;
1699         }
1700
1701         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
1702             kde.rsn_ie == NULL) {
1703                 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2");
1704                 status = WLAN_STATUS_INVALID_PARAMETERS;
1705                 goto error;
1706         }
1707         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
1708                     kde.rsn_ie, kde.rsn_ie_len);
1709
1710         /*
1711          * FIX: bitwise comparison of RSN IE is not the correct way of
1712          * validation this. It can be different, but certain fields must
1713          * match. Since we list only a single pairwise cipher in TPK M1, the
1714          * memcmp is likely to work in most cases, though.
1715          */
1716         if (kde.rsn_ie_len != peer->rsnie_i_len ||
1717             os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) {
1718                 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does "
1719                            "not match with RSN IE used in TPK M1");
1720                 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1",
1721                             peer->rsnie_i, peer->rsnie_i_len);
1722                 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
1723                             kde.rsn_ie, kde.rsn_ie_len);
1724                 status = WLAN_STATUS_INVALID_RSNIE;
1725                 goto error;
1726         }
1727
1728         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
1729                 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2");
1730                 status = WLAN_STATUS_INVALID_RSNIE;
1731                 goto error;
1732         }
1733
1734         cipher = ie.pairwise_cipher;
1735         if (cipher == WPA_CIPHER_CCMP) {
1736                 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
1737                 cipher = WPA_CIPHER_CCMP;
1738         } else {
1739                 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2");
1740                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1741                 goto error;
1742         }
1743
1744         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2",
1745                     kde.ftie, sizeof(*ftie));
1746         ftie = (struct wpa_tdls_ftie *) kde.ftie;
1747
1748         if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
1749                 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
1750                            "not match with FTIE SNonce used in TPK M1");
1751                 /* Silently discard the frame */
1752                 return -1;
1753         }
1754
1755         /* Responder Nonce and RSN IE */
1756         os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN);
1757         os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
1758         peer->rsnie_p_len = kde.rsn_ie_len;
1759         peer->cipher = cipher;
1760
1761         /* Lifetime */
1762         if (kde.key_lifetime == NULL) {
1763                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2");
1764                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1765                 goto error;
1766         }
1767         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1768         lifetime = WPA_GET_LE32(timeoutie->value);
1769         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2",
1770                    lifetime);
1771         if (lifetime != peer->lifetime) {
1772                 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
1773                            "TPK M2 (expected %u)", lifetime, peer->lifetime);
1774                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1775                 goto error;
1776         }
1777
1778         wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
1779
1780         /* Process MIC check to see if TPK M2 is right */
1781         if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid,
1782                                            (u8 *) timeoutie, ftie) < 0) {
1783                 /* Discard the frame */
1784                 wpa_tdls_del_key(sm, peer);
1785                 wpa_tdls_peer_free(sm, peer);
1786                 return -1;
1787         }
1788
1789         wpa_tdls_set_key(sm, peer);
1790
1791 skip_rsn:
1792         peer->dtoken = dtoken;
1793
1794         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
1795                    "TPK Handshake Message 3");
1796         wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer);
1797
1798         wpa_tdls_enable_link(sm, peer);
1799
1800         return 0;
1801
1802 error:
1803         wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
1804                             status);
1805         return -1;
1806 }
1807
1808
1809 static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
1810                                    const u8 *buf, size_t len)
1811 {
1812         struct wpa_tdls_peer *peer;
1813         struct wpa_eapol_ie_parse kde;
1814         struct wpa_tdls_ftie *ftie;
1815         struct wpa_tdls_timeoutie *timeoutie;
1816         struct wpa_tdls_lnkid *lnkid;
1817         int ielen;
1818         u16 status;
1819         const u8 *pos;
1820         u32 lifetime;
1821
1822         wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
1823                    "(Peer " MACSTR ")", MAC2STR(src_addr));
1824         for (peer = sm->tdls; peer; peer = peer->next) {
1825                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1826                         break;
1827         }
1828         if (peer == NULL) {
1829                 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
1830                            "TPK M3: " MACSTR, MAC2STR(src_addr));
1831                 return -1;
1832         }
1833         wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE);
1834
1835         if (len < 3 + 3)
1836                 return -1;
1837         pos = buf;
1838         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1839
1840         status = WPA_GET_LE16(pos);
1841
1842         if (status != 0) {
1843                 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u",
1844                            status);
1845                 return -1;
1846         }
1847         pos += 2 /* status code */ + 1 /* dialog token */;
1848
1849         ielen = len - (pos - buf); /* start of IE in buf */
1850         if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
1851                 wpa_printf(MSG_INFO, "TDLS: Failed to parse KDEs in TPK M3");
1852                 return -1;
1853         }
1854
1855         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1856                 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3");
1857                 return -1;
1858         }
1859         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3",
1860                     (u8 *) kde.lnkid, kde.lnkid_len);
1861         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1862
1863         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1864                 wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
1865                 return -1;
1866         }
1867
1868         if (!wpa_tdls_get_privacy(sm))
1869                 goto skip_rsn;
1870
1871         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
1872                 wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3");
1873                 return -1;
1874         }
1875         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3",
1876                     kde.ftie, sizeof(*ftie));
1877         ftie = (struct wpa_tdls_ftie *) kde.ftie;
1878
1879         if (kde.rsn_ie == NULL) {
1880                 wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3");
1881                 return -1;
1882         }
1883         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3",
1884                     kde.rsn_ie, kde.rsn_ie_len);
1885         if (kde.rsn_ie_len != peer->rsnie_p_len ||
1886             os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) {
1887                 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match "
1888                            "with the one sent in TPK M2");
1889                 return -1;
1890         }
1891
1892         if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) {
1893                 wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
1894                            "not match with FTIE ANonce used in TPK M2");
1895                 return -1;
1896         }
1897
1898         if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
1899                 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
1900                            "match with FTIE SNonce used in TPK M1");
1901                 return -1;
1902         }
1903
1904         if (kde.key_lifetime == NULL) {
1905                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3");
1906                 return -1;
1907         }
1908         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1909         wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3",
1910                     (u8 *) timeoutie, sizeof(*timeoutie));
1911         lifetime = WPA_GET_LE32(timeoutie->value);
1912         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3",
1913                    lifetime);
1914         if (lifetime != peer->lifetime) {
1915                 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
1916                            "TPK M3 (expected %u)", lifetime, peer->lifetime);
1917                 return -1;
1918         }
1919
1920         if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid,
1921                                            (u8 *) timeoutie, ftie) < 0) {
1922                 wpa_tdls_del_key(sm, peer);
1923                 wpa_tdls_peer_free(sm, peer);
1924                 return -1;
1925         }
1926
1927         if (wpa_tdls_set_key(sm, peer) < 0)
1928                 return -1;
1929
1930 skip_rsn:
1931         wpa_tdls_enable_link(sm, peer);
1932
1933         return 0;
1934 }
1935
1936
1937 static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
1938 {
1939         struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie;
1940
1941         os_memset(lifetime, 0, ie_len);
1942         lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL;
1943         lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2;
1944         lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME;
1945         WPA_PUT_LE32(lifetime->value, tsecs);
1946         os_memcpy(pos, ie, ie_len);
1947         return pos + ie_len;
1948 }
1949
1950
1951 /**
1952  * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1)
1953  * @sm: Pointer to WPA state machine data from wpa_sm_init()
1954  * @peer: MAC address of the peer STA
1955  * Returns: 0 on success, or -1 on failure
1956  *
1957  * Send TPK Handshake Message 1 info to driver to start TDLS
1958  * handshake with the peer.
1959  */
1960 int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
1961 {
1962         struct wpa_tdls_peer *peer;
1963         int tdls_prohibited = sm->tdls_prohibited;
1964
1965         if (sm->tdls_disabled || !sm->tdls_supported)
1966                 return -1;
1967
1968 #ifdef CONFIG_TDLS_TESTING
1969         if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
1970             tdls_prohibited) {
1971                 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
1972                            "on TDLS");
1973                 tdls_prohibited = 0;
1974         }
1975 #endif /* CONFIG_TDLS_TESTING */
1976
1977         if (tdls_prohibited) {
1978                 wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
1979                            "reject request to start setup");
1980                 return -1;
1981         }
1982
1983         /* Find existing entry and if found, use that instead of adding
1984          * a new one */
1985         for (peer = sm->tdls; peer; peer = peer->next) {
1986                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
1987                         break;
1988         }
1989
1990         if (peer == NULL) {
1991                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
1992                            "peer, creating one for " MACSTR, MAC2STR(addr));
1993                 peer = os_malloc(sizeof(*peer));
1994                 if (peer == NULL)
1995                         return -1;
1996                 os_memset(peer, 0, sizeof(*peer));
1997                 os_memcpy(peer->addr, addr, ETH_ALEN);
1998                 peer->next = sm->tdls;
1999                 sm->tdls = peer;
2000         }
2001
2002         peer->initiator = 1;
2003
2004         return wpa_tdls_send_tpk_m1(sm, peer);
2005 }
2006
2007
2008 int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr)
2009 {
2010         struct wpa_tdls_peer *peer;
2011
2012         if (sm->tdls_disabled || !sm->tdls_supported)
2013                 return -1;
2014
2015         for (peer = sm->tdls; peer; peer = peer->next) {
2016                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2017                         break;
2018         }
2019
2020         if (peer == NULL || !peer->tpk_success)
2021                 return -1;
2022
2023         return wpa_tdls_start(sm, addr);
2024 }
2025
2026
2027 /**
2028  * wpa_supplicant_rx_tdls - Receive TDLS data frame
2029  *
2030  * This function is called to receive TDLS (ethertype = 0x890d) data frames.
2031  */
2032 static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
2033                                    const u8 *buf, size_t len)
2034 {
2035         struct wpa_sm *sm = ctx;
2036         struct wpa_tdls_frame *tf;
2037
2038         wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
2039                     buf, len);
2040
2041         if (sm->tdls_disabled || !sm->tdls_supported) {
2042                 wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
2043                            "or unsupported by driver");
2044                 return;
2045         }
2046
2047         if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
2048                 wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
2049                 return;
2050         }
2051
2052         if (len < sizeof(*tf)) {
2053                 wpa_printf(MSG_INFO, "TDLS: Drop too short frame");
2054                 return;
2055         }
2056
2057         /* Check to make sure its a valid encapsulated TDLS frame */
2058         tf = (struct wpa_tdls_frame *) buf;
2059         if (tf->payloadtype != 2 /* TDLS_RFTYPE */ ||
2060             tf->category != WLAN_ACTION_TDLS) {
2061                 wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u "
2062                            "category=%u action=%u",
2063                            tf->payloadtype, tf->category, tf->action);
2064                 return;
2065         }
2066
2067         switch (tf->action) {
2068         case WLAN_TDLS_SETUP_REQUEST:
2069                 wpa_tdls_process_tpk_m1(sm, src_addr, buf, len);
2070                 break;
2071         case WLAN_TDLS_SETUP_RESPONSE:
2072                 wpa_tdls_process_tpk_m2(sm, src_addr, buf, len);
2073                 break;
2074         case WLAN_TDLS_SETUP_CONFIRM:
2075                 wpa_tdls_process_tpk_m3(sm, src_addr, buf, len);
2076                 break;
2077         case WLAN_TDLS_TEARDOWN:
2078                 wpa_tdls_recv_teardown(sm, src_addr, buf, len);
2079                 break;
2080         case WLAN_TDLS_DISCOVERY_REQUEST:
2081                 wpa_tdls_process_discovery_request(sm, src_addr, buf, len);
2082                 break;
2083         default:
2084                 /* Kernel code will process remaining frames */
2085                 wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u",
2086                            tf->action);
2087                 break;
2088         }
2089 }
2090
2091
2092 /**
2093  * wpa_tdls_init - Initialize driver interface parameters for TDLS
2094  * @wpa_s: Pointer to wpa_supplicant data
2095  * Returns: 0 on success, -1 on failure
2096  *
2097  * This function is called to initialize driver interface parameters for TDLS.
2098  * wpa_drv_init() must have been called before this function to initialize the
2099  * driver interface.
2100  */
2101 int wpa_tdls_init(struct wpa_sm *sm)
2102 {
2103         if (sm == NULL)
2104                 return -1;
2105
2106         sm->l2_tdls = l2_packet_init(sm->ifname, sm->own_addr,
2107                                      ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
2108                                      sm, 0);
2109         if (sm->l2_tdls == NULL) {
2110                 wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
2111                            "connection");
2112                 return -1;
2113         }
2114
2115         /*
2116          * Drivers that support TDLS but don't implement the get_capa callback
2117          * are assumed to perform everything internally
2118          */
2119         if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
2120                                  &sm->tdls_external_setup) < 0) {
2121                 sm->tdls_supported = 1;
2122                 sm->tdls_external_setup = 0;
2123         }
2124
2125         wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
2126                    "driver", sm->tdls_supported ? "" : " not");
2127         wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
2128                    sm->tdls_external_setup ? "external" : "internal");
2129
2130         return 0;
2131 }
2132
2133
2134 static void wpa_tdls_remove_peers(struct wpa_sm *sm)
2135 {
2136         struct wpa_tdls_peer *peer, *tmp;
2137
2138         peer = sm->tdls;
2139         sm->tdls = NULL;
2140
2141         while (peer) {
2142                 int res;
2143                 tmp = peer->next;
2144                 res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
2145                 wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
2146                            MAC2STR(peer->addr), res);
2147                 wpa_tdls_peer_free(sm, peer);
2148                 os_free(peer);
2149                 peer = tmp;
2150         }
2151 }
2152
2153
2154 /**
2155  * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS
2156  *
2157  * This function is called to recover driver interface parameters for TDLS
2158  * and frees resources allocated for it.
2159  */
2160 void wpa_tdls_deinit(struct wpa_sm *sm)
2161 {
2162         if (sm == NULL)
2163                 return;
2164
2165         if (sm->l2_tdls)
2166                 l2_packet_deinit(sm->l2_tdls);
2167         sm->l2_tdls = NULL;
2168
2169         wpa_tdls_remove_peers(sm);
2170 }
2171
2172
2173 void wpa_tdls_assoc(struct wpa_sm *sm)
2174 {
2175         wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association");
2176         wpa_tdls_remove_peers(sm);
2177 }
2178
2179
2180 void wpa_tdls_disassoc(struct wpa_sm *sm)
2181 {
2182         wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
2183         wpa_tdls_remove_peers(sm);
2184 }
2185
2186
2187 static int wpa_tdls_prohibited(const u8 *ies, size_t len)
2188 {
2189         struct wpa_eapol_ie_parse elems;
2190
2191         if (ies == NULL)
2192                 return 0;
2193
2194         if (wpa_supplicant_parse_ies(ies, len, &elems) < 0)
2195                 return 0;
2196
2197         if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
2198                 return 0;
2199
2200          /* bit 38 - TDLS Prohibited */
2201         return !!(elems.ext_capab[2 + 4] & 0x40);
2202 }
2203
2204
2205 void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2206 {
2207         sm->tdls_prohibited = wpa_tdls_prohibited(ies, len);
2208         wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
2209                    sm->tdls_prohibited ? "prohibited" : "allowed");
2210 }
2211
2212
2213 void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2214 {
2215         if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) {
2216                 wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
2217                            "(Re)Association Response IEs");
2218                 sm->tdls_prohibited = 1;
2219         }
2220 }
2221
2222
2223 void wpa_tdls_enable(struct wpa_sm *sm, int enabled)
2224 {
2225         wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled");
2226         sm->tdls_disabled = !enabled;
2227 }