mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-29 02:38:22 -05:00
nl80211: Clean up ifidx properly if interface in a bridge is removed
When an interface is removed while it was in a bridge, the bridge was not removed from the local ifidx list. Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
This commit is contained in:
parent
170c545ab4
commit
732b1d20ec
@ -181,9 +181,14 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
|
|||||||
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
|
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
|
||||||
int report);
|
int report);
|
||||||
|
|
||||||
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
|
#define IFIDX_ANY -1
|
||||||
static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
|
|
||||||
static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
|
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
|
||||||
|
int ifidx_reason);
|
||||||
|
static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
|
||||||
|
int ifidx_reason);
|
||||||
|
static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
|
||||||
|
int ifidx_reason);
|
||||||
|
|
||||||
static int nl80211_set_channel(struct i802_bss *bss,
|
static int nl80211_set_channel(struct i802_bss *bss,
|
||||||
struct hostapd_freq_params *freq, int set_chan);
|
struct hostapd_freq_params *freq, int set_chan);
|
||||||
@ -883,7 +888,7 @@ nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
|
|||||||
dl_list_for_each(drv, &global->interfaces,
|
dl_list_for_each(drv, &global->interfaces,
|
||||||
struct wpa_driver_nl80211_data, list) {
|
struct wpa_driver_nl80211_data, list) {
|
||||||
if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
|
if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
|
||||||
have_ifidx(drv, idx))
|
have_ifidx(drv, idx, IFIDX_ANY))
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1062,7 +1067,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
|||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
|
wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
|
||||||
brid, namebuf);
|
brid, namebuf);
|
||||||
add_ifidx(drv, brid);
|
add_ifidx(drv, brid, ifi->ifi_index);
|
||||||
|
|
||||||
for (bss = drv->first_bss; bss; bss = bss->next) {
|
for (bss = drv->first_bss; bss; bss = bss->next) {
|
||||||
if (os_strcmp(ifname, bss->ifname) == 0) {
|
if (os_strcmp(ifname, bss->ifname) == 0) {
|
||||||
@ -1149,7 +1154,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
|
|||||||
"nl80211: Remove ifindex %u for bridge %s",
|
"nl80211: Remove ifindex %u for bridge %s",
|
||||||
brid, namebuf);
|
brid, namebuf);
|
||||||
}
|
}
|
||||||
del_ifidx(drv, brid);
|
del_ifidx(drv, brid, ifi->ifi_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1716,6 +1721,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
|
|||||||
|
|
||||||
drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
|
drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
|
||||||
drv->if_indices = drv->default_if_indices;
|
drv->if_indices = drv->default_if_indices;
|
||||||
|
drv->if_indices_reason = drv->default_if_indices_reason;
|
||||||
|
|
||||||
drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
|
drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
|
||||||
if (!drv->first_bss) {
|
if (!drv->first_bss) {
|
||||||
@ -2390,6 +2396,9 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
|
|||||||
if (drv->if_indices != drv->default_if_indices)
|
if (drv->if_indices != drv->default_if_indices)
|
||||||
os_free(drv->if_indices);
|
os_free(drv->if_indices);
|
||||||
|
|
||||||
|
if (drv->if_indices_reason != drv->default_if_indices_reason)
|
||||||
|
os_free(drv->if_indices_reason);
|
||||||
|
|
||||||
if (drv->disabled_11b_rates)
|
if (drv->disabled_11b_rates)
|
||||||
nl80211_disable_11b_rates(drv, drv->ifindex, 0);
|
nl80211_disable_11b_rates(drv, drv->ifindex, 0);
|
||||||
|
|
||||||
@ -4069,7 +4078,11 @@ void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx)
|
|||||||
/* stop listening for EAPOL on this interface */
|
/* stop listening for EAPOL on this interface */
|
||||||
dl_list_for_each(drv2, &drv->global->interfaces,
|
dl_list_for_each(drv2, &drv->global->interfaces,
|
||||||
struct wpa_driver_nl80211_data, list)
|
struct wpa_driver_nl80211_data, list)
|
||||||
del_ifidx(drv2, ifidx);
|
{
|
||||||
|
del_ifidx(drv2, ifidx, IFIDX_ANY);
|
||||||
|
/* Remove all bridges learned for this iface */
|
||||||
|
del_ifidx(drv2, IFIDX_ANY, ifidx);
|
||||||
|
}
|
||||||
|
|
||||||
msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
|
msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
|
||||||
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
|
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
|
||||||
@ -4177,7 +4190,7 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
|
|||||||
iftype == NL80211_IFTYPE_WDS ||
|
iftype == NL80211_IFTYPE_WDS ||
|
||||||
iftype == NL80211_IFTYPE_MONITOR) {
|
iftype == NL80211_IFTYPE_MONITOR) {
|
||||||
/* start listening for EAPOL on this interface */
|
/* start listening for EAPOL on this interface */
|
||||||
add_ifidx(drv, ifidx);
|
add_ifidx(drv, ifidx, IFIDX_ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr && iftype != NL80211_IFTYPE_MONITOR &&
|
if (addr && iftype != NL80211_IFTYPE_MONITOR &&
|
||||||
@ -5635,7 +5648,9 @@ static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
|
|||||||
for (i = 0; i < drv->num_if_indices; i++) {
|
for (i = 0; i < drv->num_if_indices; i++) {
|
||||||
if (!drv->if_indices[i])
|
if (!drv->if_indices[i])
|
||||||
continue;
|
continue;
|
||||||
res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
|
res = os_snprintf(pos, end - pos, " %d(%d)",
|
||||||
|
drv->if_indices[i],
|
||||||
|
drv->if_indices_reason[i]);
|
||||||
if (os_snprintf_error(end - pos, res))
|
if (os_snprintf_error(end - pos, res))
|
||||||
break;
|
break;
|
||||||
pos += res;
|
pos += res;
|
||||||
@ -5647,14 +5662,16 @@ static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
|
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
|
||||||
|
int ifidx_reason)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int *old;
|
int *old, *old_reason;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
|
wpa_printf(MSG_DEBUG,
|
||||||
ifidx);
|
"nl80211: Add own interface ifindex %d (ifidx_reason %d)",
|
||||||
if (have_ifidx(drv, ifidx)) {
|
ifidx, ifidx_reason);
|
||||||
|
if (have_ifidx(drv, ifidx, ifidx_reason)) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
|
wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
|
||||||
ifidx);
|
ifidx);
|
||||||
return;
|
return;
|
||||||
@ -5662,6 +5679,7 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
|
|||||||
for (i = 0; i < drv->num_if_indices; i++) {
|
for (i = 0; i < drv->num_if_indices; i++) {
|
||||||
if (drv->if_indices[i] == 0) {
|
if (drv->if_indices[i] == 0) {
|
||||||
drv->if_indices[i] = ifidx;
|
drv->if_indices[i] = ifidx;
|
||||||
|
drv->if_indices_reason[i] = ifidx_reason;
|
||||||
dump_ifidx(drv);
|
dump_ifidx(drv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -5672,32 +5690,57 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
|
|||||||
else
|
else
|
||||||
old = NULL;
|
old = NULL;
|
||||||
|
|
||||||
|
if (drv->if_indices_reason != drv->default_if_indices_reason)
|
||||||
|
old_reason = drv->if_indices_reason;
|
||||||
|
else
|
||||||
|
old_reason = NULL;
|
||||||
|
|
||||||
drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
|
drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
|
||||||
sizeof(int));
|
sizeof(int));
|
||||||
|
drv->if_indices_reason = os_realloc_array(old_reason,
|
||||||
|
drv->num_if_indices + 1,
|
||||||
|
sizeof(int));
|
||||||
if (!drv->if_indices) {
|
if (!drv->if_indices) {
|
||||||
if (!old)
|
if (!old)
|
||||||
drv->if_indices = drv->default_if_indices;
|
drv->if_indices = drv->default_if_indices;
|
||||||
else
|
else
|
||||||
drv->if_indices = old;
|
drv->if_indices = old;
|
||||||
|
}
|
||||||
|
if (!drv->if_indices_reason) {
|
||||||
|
if (!old_reason)
|
||||||
|
drv->if_indices_reason = drv->default_if_indices_reason;
|
||||||
|
else
|
||||||
|
drv->if_indices = old_reason;
|
||||||
|
}
|
||||||
|
if (!drv->if_indices || !drv->if_indices_reason) {
|
||||||
wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
|
wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
|
||||||
"interfaces");
|
"interfaces");
|
||||||
wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
|
wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
|
||||||
return;
|
return;
|
||||||
} else if (!old)
|
}
|
||||||
|
if (!old)
|
||||||
os_memcpy(drv->if_indices, drv->default_if_indices,
|
os_memcpy(drv->if_indices, drv->default_if_indices,
|
||||||
sizeof(drv->default_if_indices));
|
sizeof(drv->default_if_indices));
|
||||||
|
if (!old_reason)
|
||||||
|
os_memcpy(drv->if_indices_reason,
|
||||||
|
drv->default_if_indices_reason,
|
||||||
|
sizeof(drv->default_if_indices_reason));
|
||||||
drv->if_indices[drv->num_if_indices] = ifidx;
|
drv->if_indices[drv->num_if_indices] = ifidx;
|
||||||
|
drv->if_indices_reason[drv->num_if_indices] = ifidx_reason;
|
||||||
drv->num_if_indices++;
|
drv->num_if_indices++;
|
||||||
dump_ifidx(drv);
|
dump_ifidx(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
|
static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
|
||||||
|
int ifidx_reason)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < drv->num_if_indices; i++) {
|
for (i = 0; i < drv->num_if_indices; i++) {
|
||||||
if (drv->if_indices[i] == ifidx) {
|
if ((drv->if_indices[i] == ifidx || ifidx == IFIDX_ANY) &&
|
||||||
|
(drv->if_indices_reason[i] == ifidx_reason ||
|
||||||
|
ifidx_reason == IFIDX_ANY)) {
|
||||||
drv->if_indices[i] = 0;
|
drv->if_indices[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5706,12 +5749,15 @@ static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
|
static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
|
||||||
|
int ifidx_reason)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < drv->num_if_indices; i++)
|
for (i = 0; i < drv->num_if_indices; i++)
|
||||||
if (drv->if_indices[i] == ifidx)
|
if (drv->if_indices[i] == ifidx &&
|
||||||
|
(drv->if_indices_reason[i] == ifidx_reason ||
|
||||||
|
ifidx_reason == IFIDX_ANY))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -5776,7 +5822,7 @@ static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_ifidx(drv, lladdr.sll_ifindex))
|
if (have_ifidx(drv, lladdr.sll_ifindex, IFIDX_ANY))
|
||||||
drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
|
drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5803,7 +5849,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
|
|||||||
}
|
}
|
||||||
bss->added_bridge = 1;
|
bss->added_bridge = 1;
|
||||||
br_ifindex = if_nametoindex(brname);
|
br_ifindex = if_nametoindex(brname);
|
||||||
add_ifidx(drv, br_ifindex);
|
add_ifidx(drv, br_ifindex, drv->ifindex);
|
||||||
}
|
}
|
||||||
bss->br_ifindex = br_ifindex;
|
bss->br_ifindex = br_ifindex;
|
||||||
|
|
||||||
@ -5865,7 +5911,7 @@ static void *i802_init(struct hostapd_data *hapd,
|
|||||||
wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
|
wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
|
||||||
params->ifname, master_ifname);
|
params->ifname, master_ifname);
|
||||||
/* start listening for EAPOL on the master interface */
|
/* start listening for EAPOL on the master interface */
|
||||||
add_ifidx(drv, if_nametoindex(master_ifname));
|
add_ifidx(drv, if_nametoindex(master_ifname), drv->ifindex);
|
||||||
} else {
|
} else {
|
||||||
master_ifname[0] = '\0';
|
master_ifname[0] = '\0';
|
||||||
}
|
}
|
||||||
@ -5876,14 +5922,14 @@ static void *i802_init(struct hostapd_data *hapd,
|
|||||||
if (params->bridge[i]) {
|
if (params->bridge[i]) {
|
||||||
ifindex = if_nametoindex(params->bridge[i]);
|
ifindex = if_nametoindex(params->bridge[i]);
|
||||||
if (ifindex)
|
if (ifindex)
|
||||||
add_ifidx(drv, ifindex);
|
add_ifidx(drv, ifindex, drv->ifindex);
|
||||||
if (ifindex == br_ifindex)
|
if (ifindex == br_ifindex)
|
||||||
br_added = 1;
|
br_added = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start listening for EAPOL on the default AP interface */
|
/* start listening for EAPOL on the default AP interface */
|
||||||
add_ifidx(drv, drv->ifindex);
|
add_ifidx(drv, drv->ifindex, IFIDX_ANY);
|
||||||
|
|
||||||
if (params->num_bridge && params->bridge[0]) {
|
if (params->num_bridge && params->bridge[0]) {
|
||||||
if (i802_check_bridge(drv, bss, params->bridge[0],
|
if (i802_check_bridge(drv, bss, params->bridge[0],
|
||||||
@ -5895,7 +5941,7 @@ static void *i802_init(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
if (!br_added && br_ifindex &&
|
if (!br_added && br_ifindex &&
|
||||||
(params->num_bridge == 0 || !params->bridge[0]))
|
(params->num_bridge == 0 || !params->bridge[0]))
|
||||||
add_ifidx(drv, br_ifindex);
|
add_ifidx(drv, br_ifindex, drv->ifindex);
|
||||||
|
|
||||||
#ifdef CONFIG_LIBNL3_ROUTE
|
#ifdef CONFIG_LIBNL3_ROUTE
|
||||||
if (bss->added_if_into_bridge) {
|
if (bss->added_if_into_bridge) {
|
||||||
@ -6181,7 +6227,7 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
|
|||||||
nlmode == NL80211_IFTYPE_AP_VLAN ||
|
nlmode == NL80211_IFTYPE_AP_VLAN ||
|
||||||
nlmode == NL80211_IFTYPE_WDS ||
|
nlmode == NL80211_IFTYPE_WDS ||
|
||||||
nlmode == NL80211_IFTYPE_MONITOR))
|
nlmode == NL80211_IFTYPE_MONITOR))
|
||||||
add_ifidx(drv, ifidx);
|
add_ifidx(drv, ifidx, IFIDX_ANY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -6201,8 +6247,10 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
|
|||||||
else if (ifindex > 0 && !bss->added_if) {
|
else if (ifindex > 0 && !bss->added_if) {
|
||||||
struct wpa_driver_nl80211_data *drv2;
|
struct wpa_driver_nl80211_data *drv2;
|
||||||
dl_list_for_each(drv2, &drv->global->interfaces,
|
dl_list_for_each(drv2, &drv->global->interfaces,
|
||||||
struct wpa_driver_nl80211_data, list)
|
struct wpa_driver_nl80211_data, list) {
|
||||||
del_ifidx(drv2, ifindex);
|
del_ifidx(drv2, ifindex, IFIDX_ANY);
|
||||||
|
del_ifidx(drv2, IFIDX_ANY, ifindex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != WPA_IF_AP_BSS)
|
if (type != WPA_IF_AP_BSS)
|
||||||
|
@ -172,7 +172,10 @@ struct wpa_driver_nl80211_data {
|
|||||||
struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
|
struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
|
||||||
|
|
||||||
int default_if_indices[16];
|
int default_if_indices[16];
|
||||||
|
/* the AP/AP_VLAN iface that is in this bridge */
|
||||||
|
int default_if_indices_reason[16];
|
||||||
int *if_indices;
|
int *if_indices;
|
||||||
|
int *if_indices_reason;
|
||||||
int num_if_indices;
|
int num_if_indices;
|
||||||
|
|
||||||
/* From failed authentication command */
|
/* From failed authentication command */
|
||||||
|
Loading…
Reference in New Issue
Block a user