1e28a4053SRui Paulo /*
2e28a4053SRui Paulo * AP mode helper functions
3e28a4053SRui Paulo * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4e28a4053SRui Paulo *
5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo * See README for more details.
7e28a4053SRui Paulo */
8e28a4053SRui Paulo
9e28a4053SRui Paulo #include "includes.h"
10e28a4053SRui Paulo
11e28a4053SRui Paulo #include "common.h"
12e28a4053SRui Paulo #include "common/ieee802_11_defs.h"
13325151a3SRui Paulo #include "fst/fst.h"
14e28a4053SRui Paulo #include "sta_info.h"
15e28a4053SRui Paulo #include "hostapd.h"
16e28a4053SRui Paulo
17e28a4053SRui Paulo
hostapd_register_probereq_cb(struct hostapd_data * hapd,int (* cb)(void * ctx,const u8 * sa,const u8 * da,const u8 * bssid,const u8 * ie,size_t ie_len,int ssi_signal),void * ctx)18e28a4053SRui Paulo int hostapd_register_probereq_cb(struct hostapd_data *hapd,
19e28a4053SRui Paulo int (*cb)(void *ctx, const u8 *sa,
20f05cddf9SRui Paulo const u8 *da, const u8 *bssid,
21f05cddf9SRui Paulo const u8 *ie, size_t ie_len,
22f05cddf9SRui Paulo int ssi_signal),
23e28a4053SRui Paulo void *ctx)
24e28a4053SRui Paulo {
25e28a4053SRui Paulo struct hostapd_probereq_cb *n;
26e28a4053SRui Paulo
27f05cddf9SRui Paulo n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1,
28e28a4053SRui Paulo sizeof(struct hostapd_probereq_cb));
29e28a4053SRui Paulo if (n == NULL)
30e28a4053SRui Paulo return -1;
31e28a4053SRui Paulo
32e28a4053SRui Paulo hapd->probereq_cb = n;
33e28a4053SRui Paulo n = &hapd->probereq_cb[hapd->num_probereq_cb];
34e28a4053SRui Paulo hapd->num_probereq_cb++;
35e28a4053SRui Paulo
36e28a4053SRui Paulo n->cb = cb;
37e28a4053SRui Paulo n->ctx = ctx;
38e28a4053SRui Paulo
39e28a4053SRui Paulo return 0;
40e28a4053SRui Paulo }
41e28a4053SRui Paulo
42e28a4053SRui Paulo
43e28a4053SRui Paulo struct prune_data {
44e28a4053SRui Paulo struct hostapd_data *hapd;
45e28a4053SRui Paulo const u8 *addr;
46*a90b9d01SCy Schubert int mld_assoc_link_id;
47e28a4053SRui Paulo };
48e28a4053SRui Paulo
prune_associations(struct hostapd_iface * iface,void * ctx)49e28a4053SRui Paulo static int prune_associations(struct hostapd_iface *iface, void *ctx)
50e28a4053SRui Paulo {
51e28a4053SRui Paulo struct prune_data *data = ctx;
52e28a4053SRui Paulo struct sta_info *osta;
53e28a4053SRui Paulo struct hostapd_data *ohapd;
54e28a4053SRui Paulo size_t j;
55e28a4053SRui Paulo
56e28a4053SRui Paulo for (j = 0; j < iface->num_bss; j++) {
57e28a4053SRui Paulo ohapd = iface->bss[j];
58e28a4053SRui Paulo if (ohapd == data->hapd)
59e28a4053SRui Paulo continue;
60c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
61c1d255d3SCy Schubert if (ohapd->conf->skip_prune_assoc)
62c1d255d3SCy Schubert continue;
63c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
64325151a3SRui Paulo #ifdef CONFIG_FST
65325151a3SRui Paulo /* Don't prune STAs belong to same FST */
66325151a3SRui Paulo if (ohapd->iface->fst &&
67325151a3SRui Paulo data->hapd->iface->fst &&
68325151a3SRui Paulo fst_are_ifaces_aggregated(ohapd->iface->fst,
69325151a3SRui Paulo data->hapd->iface->fst))
70325151a3SRui Paulo continue;
71325151a3SRui Paulo #endif /* CONFIG_FST */
72e28a4053SRui Paulo osta = ap_get_sta(ohapd, data->addr);
73e28a4053SRui Paulo if (!osta)
74e28a4053SRui Paulo continue;
75e28a4053SRui Paulo
76*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE
77*a90b9d01SCy Schubert if (data->mld_assoc_link_id >= 0 &&
78*a90b9d01SCy Schubert osta->mld_assoc_link_id == data->mld_assoc_link_id)
79*a90b9d01SCy Schubert continue;
80*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */
81*a90b9d01SCy Schubert
82325151a3SRui Paulo wpa_printf(MSG_INFO, "%s: Prune association for " MACSTR,
83325151a3SRui Paulo ohapd->conf->iface, MAC2STR(osta->addr));
84e28a4053SRui Paulo ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
85e28a4053SRui Paulo }
86e28a4053SRui Paulo
87e28a4053SRui Paulo return 0;
88e28a4053SRui Paulo }
89e28a4053SRui Paulo
90e28a4053SRui Paulo /**
91e28a4053SRui Paulo * hostapd_prune_associations - Remove extraneous associations
92e28a4053SRui Paulo * @hapd: Pointer to BSS data for the most recent association
93e28a4053SRui Paulo * @addr: Associated STA address
94*a90b9d01SCy Schubert * @mld_assoc_link_id: MLD link id used for association or -1 for non MLO
95e28a4053SRui Paulo *
96e28a4053SRui Paulo * This function looks through all radios and BSS's for previous
97e28a4053SRui Paulo * (stale) associations of STA. If any are found they are removed.
98e28a4053SRui Paulo */
hostapd_prune_associations(struct hostapd_data * hapd,const u8 * addr,int mld_assoc_link_id)99*a90b9d01SCy Schubert void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr,
100*a90b9d01SCy Schubert int mld_assoc_link_id)
101e28a4053SRui Paulo {
102e28a4053SRui Paulo struct prune_data data;
103*a90b9d01SCy Schubert
104e28a4053SRui Paulo data.hapd = hapd;
105e28a4053SRui Paulo data.addr = addr;
106*a90b9d01SCy Schubert data.mld_assoc_link_id = mld_assoc_link_id;
107*a90b9d01SCy Schubert
108f05cddf9SRui Paulo if (hapd->iface->interfaces &&
109f05cddf9SRui Paulo hapd->iface->interfaces->for_each_interface)
110f05cddf9SRui Paulo hapd->iface->interfaces->for_each_interface(
111f05cddf9SRui Paulo hapd->iface->interfaces, prune_associations, &data);
112e28a4053SRui Paulo }
113