~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to src/ap/sta_info.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * hostapd / Station table
 
3
 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
 
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 "common/ieee802_11_defs.h"
 
20
#include "radius/radius.h"
 
21
#include "radius/radius_client.h"
 
22
#include "drivers/driver.h"
 
23
#include "hostapd.h"
 
24
#include "accounting.h"
 
25
#include "ieee802_1x.h"
 
26
#include "ieee802_11.h"
 
27
#include "wpa_auth.h"
 
28
#include "preauth_auth.h"
 
29
#include "ap_config.h"
 
30
#include "beacon.h"
 
31
#include "ap_mlme.h"
 
32
#include "vlan_init.h"
 
33
#include "sta_info.h"
 
34
 
 
35
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
 
36
                                       struct sta_info *sta);
 
37
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
 
38
#ifdef CONFIG_IEEE80211W
 
39
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
 
40
#endif /* CONFIG_IEEE80211W */
 
41
 
 
42
int ap_for_each_sta(struct hostapd_data *hapd,
 
43
                    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
 
44
                              void *ctx),
 
45
                    void *ctx)
 
46
{
 
47
        struct sta_info *sta;
 
48
 
 
49
        for (sta = hapd->sta_list; sta; sta = sta->next) {
 
50
                if (cb(hapd, sta, ctx))
 
51
                        return 1;
 
52
        }
 
53
 
 
54
        return 0;
 
55
}
 
56
 
 
57
 
 
58
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
 
59
{
 
60
        struct sta_info *s;
 
61
 
 
62
        s = hapd->sta_hash[STA_HASH(sta)];
 
63
        while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
 
64
                s = s->hnext;
 
65
        return s;
 
66
}
 
67
 
 
68
 
 
69
static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
 
70
{
 
71
        struct sta_info *tmp;
 
72
 
 
73
        if (hapd->sta_list == sta) {
 
74
                hapd->sta_list = sta->next;
 
75
                return;
 
76
        }
 
77
 
 
78
        tmp = hapd->sta_list;
 
79
        while (tmp != NULL && tmp->next != sta)
 
80
                tmp = tmp->next;
 
81
        if (tmp == NULL) {
 
82
                wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
 
83
                           "list.", MAC2STR(sta->addr));
 
84
        } else
 
85
                tmp->next = sta->next;
 
86
}
 
87
 
 
88
 
 
89
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
 
90
{
 
91
        sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
 
92
        hapd->sta_hash[STA_HASH(sta->addr)] = sta;
 
93
}
 
94
 
 
95
 
 
96
static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
 
97
{
 
98
        struct sta_info *s;
 
99
 
 
100
        s = hapd->sta_hash[STA_HASH(sta->addr)];
 
101
        if (s == NULL) return;
 
102
        if (os_memcmp(s->addr, sta->addr, 6) == 0) {
 
103
                hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
 
104
                return;
 
105
        }
 
106
 
 
107
        while (s->hnext != NULL &&
 
108
               os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
 
109
                s = s->hnext;
 
110
        if (s->hnext != NULL)
 
111
                s->hnext = s->hnext->hnext;
 
112
        else
 
113
                wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
 
114
                           " from hash table", MAC2STR(sta->addr));
 
115
}
 
116
 
 
117
 
 
118
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 
119
{
 
120
        int set_beacon = 0;
 
121
 
 
122
        accounting_sta_stop(hapd, sta);
 
123
 
 
124
        if (sta->flags & WLAN_STA_WDS)
 
125
                hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0);
 
126
 
 
127
        if (!(sta->flags & WLAN_STA_PREAUTH))
 
128
                hapd->drv.sta_remove(hapd, sta->addr);
 
129
 
 
130
        ap_sta_hash_del(hapd, sta);
 
131
        ap_sta_list_del(hapd, sta);
 
132
 
 
133
        if (sta->aid > 0)
 
134
                hapd->sta_aid[(sta->aid - 1) / 32] &=
 
135
                        ~BIT((sta->aid - 1) % 32);
 
136
 
 
137
        hapd->num_sta--;
 
138
        if (sta->nonerp_set) {
 
139
                sta->nonerp_set = 0;
 
140
                hapd->iface->num_sta_non_erp--;
 
141
                if (hapd->iface->num_sta_non_erp == 0)
 
142
                        set_beacon++;
 
143
        }
 
144
 
 
145
        if (sta->no_short_slot_time_set) {
 
146
                sta->no_short_slot_time_set = 0;
 
147
                hapd->iface->num_sta_no_short_slot_time--;
 
148
                if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
 
149
                    && hapd->iface->num_sta_no_short_slot_time == 0)
 
150
                        set_beacon++;
 
151
        }
 
152
 
 
153
        if (sta->no_short_preamble_set) {
 
154
                sta->no_short_preamble_set = 0;
 
155
                hapd->iface->num_sta_no_short_preamble--;
 
156
                if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
 
157
                    && hapd->iface->num_sta_no_short_preamble == 0)
 
158
                        set_beacon++;
 
159
        }
 
160
 
 
161
        if (sta->no_ht_gf_set) {
 
162
                sta->no_ht_gf_set = 0;
 
163
                hapd->iface->num_sta_ht_no_gf--;
 
164
        }
 
165
 
 
166
        if (sta->no_ht_set) {
 
167
                sta->no_ht_set = 0;
 
168
                hapd->iface->num_sta_no_ht--;
 
169
        }
 
170
 
 
171
        if (sta->ht_20mhz_set) {
 
172
                sta->ht_20mhz_set = 0;
 
173
                hapd->iface->num_sta_ht_20mhz--;
 
174
        }
 
175
 
 
176
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
 
177
        if (hostapd_ht_operation_update(hapd->iface) > 0)
 
178
                set_beacon++;
 
179
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
 
180
 
 
181
        if (set_beacon)
 
182
                ieee802_11_set_beacons(hapd->iface);
 
183
 
 
184
        eloop_cancel_timeout(ap_handle_timer, hapd, sta);
 
185
        eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
 
186
 
 
187
        ieee802_1x_free_station(sta);
 
188
        wpa_auth_sta_deinit(sta->wpa_sm);
 
189
        rsn_preauth_free_station(hapd, sta);
 
190
#ifndef CONFIG_NO_RADIUS
 
191
        radius_client_flush_auth(hapd->radius, sta->addr);
 
192
#endif /* CONFIG_NO_RADIUS */
 
193
 
 
194
        os_free(sta->last_assoc_req);
 
195
        os_free(sta->challenge);
 
196
 
 
197
#ifdef CONFIG_IEEE80211W
 
198
        os_free(sta->sa_query_trans_id);
 
199
        eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
 
200
#endif /* CONFIG_IEEE80211W */
 
201
 
 
202
        wpabuf_free(sta->wps_ie);
 
203
 
 
204
        os_free(sta->ht_capabilities);
 
205
 
 
206
        os_free(sta);
 
207
}
 
208
 
 
209
 
 
210
void hostapd_free_stas(struct hostapd_data *hapd)
 
211
{
 
212
        struct sta_info *sta, *prev;
 
213
 
 
214
        sta = hapd->sta_list;
 
215
 
 
216
        while (sta) {
 
217
                prev = sta;
 
218
                if (sta->flags & WLAN_STA_AUTH) {
 
219
                        mlme_deauthenticate_indication(
 
220
                                hapd, sta, WLAN_REASON_UNSPECIFIED);
 
221
                }
 
222
                sta = sta->next;
 
223
                wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
 
224
                           MAC2STR(prev->addr));
 
225
                ap_free_sta(hapd, prev);
 
226
        }
 
227
}
 
228
 
 
229
 
 
230
/**
 
231
 * ap_handle_timer - Per STA timer handler
 
232
 * @eloop_ctx: struct hostapd_data *
 
233
 * @timeout_ctx: struct sta_info *
 
234
 *
 
235
 * This function is called to check station activity and to remove inactive
 
236
 * stations.
 
237
 */
 
238
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 
239
{
 
240
        struct hostapd_data *hapd = eloop_ctx;
 
241
        struct sta_info *sta = timeout_ctx;
 
242
        unsigned long next_time = 0;
 
243
 
 
244
        if (sta->timeout_next == STA_REMOVE) {
 
245
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
246
                               HOSTAPD_LEVEL_INFO, "deauthenticated due to "
 
247
                               "local deauth request");
 
248
                ap_free_sta(hapd, sta);
 
249
                return;
 
250
        }
 
251
 
 
252
        if ((sta->flags & WLAN_STA_ASSOC) &&
 
253
            (sta->timeout_next == STA_NULLFUNC ||
 
254
             sta->timeout_next == STA_DISASSOC)) {
 
255
                int inactive_sec;
 
256
                wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:",
 
257
                           MAC2STR(sta->addr));
 
258
                inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr);
 
259
                if (inactive_sec == -1) {
 
260
                        wpa_printf(MSG_DEBUG, "Could not get station info "
 
261
                                   "from kernel driver for " MACSTR ".",
 
262
                                   MAC2STR(sta->addr));
 
263
                } else if (inactive_sec < hapd->conf->ap_max_inactivity &&
 
264
                           sta->flags & WLAN_STA_ASSOC) {
 
265
                        /* station activity detected; reset timeout state */
 
266
                        wpa_printf(MSG_DEBUG, "  Station has been active");
 
267
                        sta->timeout_next = STA_NULLFUNC;
 
268
                        next_time = hapd->conf->ap_max_inactivity -
 
269
                                inactive_sec;
 
270
                }
 
271
        }
 
272
 
 
273
        if ((sta->flags & WLAN_STA_ASSOC) &&
 
274
            sta->timeout_next == STA_DISASSOC &&
 
275
            !(sta->flags & WLAN_STA_PENDING_POLL)) {
 
276
                wpa_printf(MSG_DEBUG, "  Station has ACKed data poll");
 
277
                /* data nullfunc frame poll did not produce TX errors; assume
 
278
                 * station ACKed it */
 
279
                sta->timeout_next = STA_NULLFUNC;
 
280
                next_time = hapd->conf->ap_max_inactivity;
 
281
        }
 
282
 
 
283
        if (next_time) {
 
284
                eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
 
285
                                       sta);
 
286
                return;
 
287
        }
 
288
 
 
289
        if (sta->timeout_next == STA_NULLFUNC &&
 
290
            (sta->flags & WLAN_STA_ASSOC)) {
 
291
#ifndef CONFIG_NATIVE_WINDOWS
 
292
                /* send data frame to poll STA and check whether this frame
 
293
                 * is ACKed */
 
294
                struct ieee80211_hdr hdr;
 
295
 
 
296
                wpa_printf(MSG_DEBUG, "  Polling STA with data frame");
 
297
                sta->flags |= WLAN_STA_PENDING_POLL;
 
298
 
 
299
                os_memset(&hdr, 0, sizeof(hdr));
 
300
                if (hapd->driver &&
 
301
                    os_strcmp(hapd->driver->name, "hostap") == 0) {
 
302
                        /*
 
303
                         * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
 
304
                         * but it is apparently not retried so TX Exc events
 
305
                         * are not received for it.
 
306
                         */
 
307
                        hdr.frame_control =
 
308
                                IEEE80211_FC(WLAN_FC_TYPE_DATA,
 
309
                                             WLAN_FC_STYPE_DATA);
 
310
                } else {
 
311
                        hdr.frame_control =
 
312
                                IEEE80211_FC(WLAN_FC_TYPE_DATA,
 
313
                                             WLAN_FC_STYPE_NULLFUNC);
 
314
                }
 
315
 
 
316
                hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
 
317
                os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
 
318
                os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
 
319
                          ETH_ALEN);
 
320
                os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
 
321
 
 
322
                if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
 
323
                        perror("ap_handle_timer: send");
 
324
#endif /* CONFIG_NATIVE_WINDOWS */
 
325
        } else if (sta->timeout_next != STA_REMOVE) {
 
326
                int deauth = sta->timeout_next == STA_DEAUTH;
 
327
 
 
328
                wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR,
 
329
                           deauth ? "deauthentication" : "disassociation",
 
330
                           MAC2STR(sta->addr));
 
331
 
 
332
                if (deauth) {
 
333
                        hapd->drv.sta_deauth(hapd, sta->addr,
 
334
                                             WLAN_REASON_PREV_AUTH_NOT_VALID);
 
335
                } else {
 
336
                        hapd->drv.sta_disassoc(
 
337
                                hapd, sta->addr,
 
338
                                WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
 
339
                }
 
340
        }
 
341
 
 
342
        switch (sta->timeout_next) {
 
343
        case STA_NULLFUNC:
 
344
                sta->timeout_next = STA_DISASSOC;
 
345
                eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
 
346
                                       hapd, sta);
 
347
                break;
 
348
        case STA_DISASSOC:
 
349
                sta->flags &= ~WLAN_STA_ASSOC;
 
350
                ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
 
351
                if (!sta->acct_terminate_cause)
 
352
                        sta->acct_terminate_cause =
 
353
                                RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
 
354
                accounting_sta_stop(hapd, sta);
 
355
                ieee802_1x_free_station(sta);
 
356
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
357
                               HOSTAPD_LEVEL_INFO, "disassociated due to "
 
358
                               "inactivity");
 
359
                sta->timeout_next = STA_DEAUTH;
 
360
                eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
 
361
                                       hapd, sta);
 
362
                mlme_disassociate_indication(
 
363
                        hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
 
364
                break;
 
365
        case STA_DEAUTH:
 
366
        case STA_REMOVE:
 
367
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
368
                               HOSTAPD_LEVEL_INFO, "deauthenticated due to "
 
369
                               "inactivity");
 
370
                if (!sta->acct_terminate_cause)
 
371
                        sta->acct_terminate_cause =
 
372
                                RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
 
373
                mlme_deauthenticate_indication(
 
374
                        hapd, sta,
 
375
                        WLAN_REASON_PREV_AUTH_NOT_VALID);
 
376
                ap_free_sta(hapd, sta);
 
377
                break;
 
378
        }
 
379
}
 
380
 
 
381
 
 
382
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
 
383
{
 
384
        struct hostapd_data *hapd = eloop_ctx;
 
385
        struct sta_info *sta = timeout_ctx;
 
386
        u8 addr[ETH_ALEN];
 
387
 
 
388
        if (!(sta->flags & WLAN_STA_AUTH))
 
389
                return;
 
390
 
 
391
        mlme_deauthenticate_indication(hapd, sta,
 
392
                                       WLAN_REASON_PREV_AUTH_NOT_VALID);
 
393
        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
394
                       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
 
395
                       "session timeout");
 
396
        sta->acct_terminate_cause =
 
397
                RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
 
398
        os_memcpy(addr, sta->addr, ETH_ALEN);
 
399
        ap_free_sta(hapd, sta);
 
400
        hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
 
401
}
 
402
 
 
403
 
 
404
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
 
405
                            u32 session_timeout)
 
406
{
 
407
        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
408
                       HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d "
 
409
                       "seconds", session_timeout);
 
410
        eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
 
411
        eloop_register_timeout(session_timeout, 0, ap_handle_session_timer,
 
412
                               hapd, sta);
 
413
}
 
414
 
 
415
 
 
416
void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta)
 
417
{
 
418
        eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
 
419
}
 
420
 
 
421
 
 
422
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
 
423
{
 
424
        struct sta_info *sta;
 
425
 
 
426
        sta = ap_get_sta(hapd, addr);
 
427
        if (sta)
 
428
                return sta;
 
429
 
 
430
        wpa_printf(MSG_DEBUG, "  New STA");
 
431
        if (hapd->num_sta >= hapd->conf->max_num_sta) {
 
432
                /* FIX: might try to remove some old STAs first? */
 
433
                wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
 
434
                           hapd->num_sta, hapd->conf->max_num_sta);
 
435
                return NULL;
 
436
        }
 
437
 
 
438
        sta = os_zalloc(sizeof(struct sta_info));
 
439
        if (sta == NULL) {
 
440
                wpa_printf(MSG_ERROR, "malloc failed");
 
441
                return NULL;
 
442
        }
 
443
        sta->acct_interim_interval = hapd->conf->acct_interim_interval;
 
444
 
 
445
        /* initialize STA info data */
 
446
        eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
 
447
                               ap_handle_timer, hapd, sta);
 
448
        os_memcpy(sta->addr, addr, ETH_ALEN);
 
449
        sta->next = hapd->sta_list;
 
450
        hapd->sta_list = sta;
 
451
        hapd->num_sta++;
 
452
        ap_sta_hash_add(hapd, sta);
 
453
        sta->ssid = &hapd->conf->ssid;
 
454
        ap_sta_remove_in_other_bss(hapd, sta);
 
455
 
 
456
        return sta;
 
457
}
 
458
 
 
459
 
 
460
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
 
461
{
 
462
        ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
 
463
 
 
464
        wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
 
465
                   MAC2STR(sta->addr));
 
466
        if (hapd->drv.sta_remove(hapd, sta->addr) &&
 
467
            sta->flags & WLAN_STA_ASSOC) {
 
468
                wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
 
469
                           " from kernel driver.", MAC2STR(sta->addr));
 
470
                return -1;
 
471
        }
 
472
        return 0;
 
473
}
 
474
 
 
475
 
 
476
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
 
477
                                       struct sta_info *sta)
 
478
{
 
479
        struct hostapd_iface *iface = hapd->iface;
 
480
        size_t i;
 
481
 
 
482
        for (i = 0; i < iface->num_bss; i++) {
 
483
                struct hostapd_data *bss = iface->bss[i];
 
484
                struct sta_info *sta2;
 
485
                /* bss should always be set during operation, but it may be
 
486
                 * NULL during reconfiguration. Assume the STA is not
 
487
                 * associated to another BSS in that case to avoid NULL pointer
 
488
                 * dereferences. */
 
489
                if (bss == hapd || bss == NULL)
 
490
                        continue;
 
491
                sta2 = ap_get_sta(bss, sta->addr);
 
492
                if (!sta2)
 
493
                        continue;
 
494
 
 
495
                ap_sta_disconnect(bss, sta2, sta2->addr,
 
496
                                  WLAN_REASON_PREV_AUTH_NOT_VALID);
 
497
        }
 
498
}
 
499
 
 
500
 
 
501
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
 
502
                         u16 reason)
 
503
{
 
504
        wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
 
505
                   hapd->conf->iface, MAC2STR(sta->addr));
 
506
        sta->flags &= ~WLAN_STA_ASSOC;
 
507
        ap_sta_remove(hapd, sta);
 
508
        sta->timeout_next = STA_DEAUTH;
 
509
        eloop_cancel_timeout(ap_handle_timer, hapd, sta);
 
510
        eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
 
511
                               ap_handle_timer, hapd, sta);
 
512
        accounting_sta_stop(hapd, sta);
 
513
        ieee802_1x_free_station(sta);
 
514
 
 
515
        mlme_disassociate_indication(hapd, sta, reason);
 
516
}
 
517
 
 
518
 
 
519
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
 
520
                           u16 reason)
 
521
{
 
522
        wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
 
523
                   hapd->conf->iface, MAC2STR(sta->addr));
 
524
        sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
 
525
        ap_sta_remove(hapd, sta);
 
526
        sta->timeout_next = STA_REMOVE;
 
527
        eloop_cancel_timeout(ap_handle_timer, hapd, sta);
 
528
        eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
 
529
                               ap_handle_timer, hapd, sta);
 
530
        accounting_sta_stop(hapd, sta);
 
531
        ieee802_1x_free_station(sta);
 
532
 
 
533
        mlme_deauthenticate_indication(hapd, sta, reason);
 
534
}
 
535
 
 
536
 
 
537
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
 
538
                     int old_vlanid)
 
539
{
 
540
#ifndef CONFIG_NO_VLAN
 
541
        const char *iface;
 
542
        struct hostapd_vlan *vlan = NULL;
 
543
        int ret;
 
544
 
 
545
        /*
 
546
         * Do not proceed furthur if the vlan id remains same. We do not want
 
547
         * duplicate dynamic vlan entries.
 
548
         */
 
549
        if (sta->vlan_id == old_vlanid)
 
550
                return 0;
 
551
 
 
552
        /*
 
553
         * During 1x reauth, if the vlan id changes, then remove the old id and
 
554
         * proceed furthur to add the new one.
 
555
         */
 
556
        if (old_vlanid > 0)
 
557
                vlan_remove_dynamic(hapd, old_vlanid);
 
558
 
 
559
        iface = hapd->conf->iface;
 
560
        if (sta->ssid->vlan[0])
 
561
                iface = sta->ssid->vlan;
 
562
 
 
563
        if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
 
564
                sta->vlan_id = 0;
 
565
        else if (sta->vlan_id > 0) {
 
566
                vlan = hapd->conf->vlan;
 
567
                while (vlan) {
 
568
                        if (vlan->vlan_id == sta->vlan_id ||
 
569
                            vlan->vlan_id == VLAN_ID_WILDCARD) {
 
570
                                iface = vlan->ifname;
 
571
                                break;
 
572
                        }
 
573
                        vlan = vlan->next;
 
574
                }
 
575
        }
 
576
 
 
577
        if (sta->vlan_id > 0 && vlan == NULL) {
 
578
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
579
                               HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
 
580
                               "binding station to (vlan_id=%d)",
 
581
                               sta->vlan_id);
 
582
                return -1;
 
583
        } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
 
584
                vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
 
585
                if (vlan == NULL) {
 
586
                        hostapd_logger(hapd, sta->addr,
 
587
                                       HOSTAPD_MODULE_IEEE80211,
 
588
                                       HOSTAPD_LEVEL_DEBUG, "could not add "
 
589
                                       "dynamic VLAN interface for vlan_id=%d",
 
590
                                       sta->vlan_id);
 
591
                        return -1;
 
592
                }
 
593
 
 
594
                iface = vlan->ifname;
 
595
                if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
 
596
                        hostapd_logger(hapd, sta->addr,
 
597
                                       HOSTAPD_MODULE_IEEE80211,
 
598
                                       HOSTAPD_LEVEL_DEBUG, "could not "
 
599
                                       "configure encryption for dynamic VLAN "
 
600
                                       "interface for vlan_id=%d",
 
601
                                       sta->vlan_id);
 
602
                }
 
603
 
 
604
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
605
                               HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
 
606
                               "interface '%s'", iface);
 
607
        } else if (vlan && vlan->vlan_id == sta->vlan_id) {
 
608
                if (sta->vlan_id > 0) {
 
609
                        vlan->dynamic_vlan++;
 
610
                        hostapd_logger(hapd, sta->addr,
 
611
                                       HOSTAPD_MODULE_IEEE80211,
 
612
                                       HOSTAPD_LEVEL_DEBUG, "updated existing "
 
613
                                       "dynamic VLAN interface '%s'", iface);
 
614
                }
 
615
 
 
616
                /*
 
617
                 * Update encryption configuration for statically generated
 
618
                 * VLAN interface. This is only used for static WEP
 
619
                 * configuration for the case where hostapd did not yet know
 
620
                 * which keys are to be used when the interface was added.
 
621
                 */
 
622
                if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
 
623
                        hostapd_logger(hapd, sta->addr,
 
624
                                       HOSTAPD_MODULE_IEEE80211,
 
625
                                       HOSTAPD_LEVEL_DEBUG, "could not "
 
626
                                       "configure encryption for VLAN "
 
627
                                       "interface for vlan_id=%d",
 
628
                                       sta->vlan_id);
 
629
                }
 
630
        }
 
631
 
 
632
        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
633
                       HOSTAPD_LEVEL_DEBUG, "binding station to interface "
 
634
                       "'%s'", iface);
 
635
 
 
636
        if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
 
637
                wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
 
638
 
 
639
        ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
 
640
        if (ret < 0) {
 
641
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
642
                               HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
 
643
                               "entry to vlan_id=%d", sta->vlan_id);
 
644
        }
 
645
        return ret;
 
646
#else /* CONFIG_NO_VLAN */
 
647
        return 0;
 
648
#endif /* CONFIG_NO_VLAN */
 
649
}
 
650
 
 
651
 
 
652
#ifdef CONFIG_IEEE80211W
 
653
 
 
654
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
 
655
{
 
656
        u32 tu;
 
657
        struct os_time now, passed;
 
658
        os_get_time(&now);
 
659
        os_time_sub(&now, &sta->sa_query_start, &passed);
 
660
        tu = (passed.sec * 1000000 + passed.usec) / 1024;
 
661
        if (hapd->conf->assoc_sa_query_max_timeout < tu) {
 
662
                hostapd_logger(hapd, sta->addr,
 
663
                               HOSTAPD_MODULE_IEEE80211,
 
664
                               HOSTAPD_LEVEL_DEBUG,
 
665
                               "association SA Query timed out");
 
666
                sta->sa_query_timed_out = 1;
 
667
                os_free(sta->sa_query_trans_id);
 
668
                sta->sa_query_trans_id = NULL;
 
669
                sta->sa_query_count = 0;
 
670
                eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
 
671
                return 1;
 
672
        }
 
673
 
 
674
        return 0;
 
675
}
 
676
 
 
677
 
 
678
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
 
679
{
 
680
        struct hostapd_data *hapd = eloop_ctx;
 
681
        struct sta_info *sta = timeout_ctx;
 
682
        unsigned int timeout, sec, usec;
 
683
        u8 *trans_id, *nbuf;
 
684
 
 
685
        if (sta->sa_query_count > 0 &&
 
686
            ap_check_sa_query_timeout(hapd, sta))
 
687
                return;
 
688
 
 
689
        nbuf = os_realloc(sta->sa_query_trans_id,
 
690
                          (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
 
691
        if (nbuf == NULL)
 
692
                return;
 
693
        if (sta->sa_query_count == 0) {
 
694
                /* Starting a new SA Query procedure */
 
695
                os_get_time(&sta->sa_query_start);
 
696
        }
 
697
        trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
 
698
        sta->sa_query_trans_id = nbuf;
 
699
        sta->sa_query_count++;
 
700
 
 
701
        os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
 
702
 
 
703
        timeout = hapd->conf->assoc_sa_query_retry_timeout;
 
704
        sec = ((timeout / 1000) * 1024) / 1000;
 
705
        usec = (timeout % 1000) * 1024;
 
706
        eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
 
707
 
 
708
        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 
709
                       HOSTAPD_LEVEL_DEBUG,
 
710
                       "association SA Query attempt %d", sta->sa_query_count);
 
711
 
 
712
#ifdef NEED_AP_MLME
 
713
        ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
 
714
#endif /* NEED_AP_MLME */
 
715
}
 
716
 
 
717
 
 
718
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
 
719
{
 
720
        ap_sa_query_timer(hapd, sta);
 
721
}
 
722
 
 
723
 
 
724
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
 
725
{
 
726
        eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
 
727
        os_free(sta->sa_query_trans_id);
 
728
        sta->sa_query_trans_id = NULL;
 
729
        sta->sa_query_count = 0;
 
730
}
 
731
 
 
732
#endif /* CONFIG_IEEE80211W */
 
733
 
 
734
 
 
735
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
 
736
                       const u8 *addr, u16 reason)
 
737
{
 
738
 
 
739
        if (sta == NULL && addr)
 
740
                sta = ap_get_sta(hapd, addr);
 
741
 
 
742
        if (addr)
 
743
                hapd->drv.sta_deauth(hapd, addr, reason);
 
744
 
 
745
        if (sta == NULL)
 
746
                return;
 
747
        sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
 
748
        eloop_cancel_timeout(ap_handle_timer, hapd, sta);
 
749
        eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
 
750
        sta->timeout_next = STA_REMOVE;
 
751
}