struct nl80211_global {
struct dl_list interfaces;
int if_add_ifindex;
+ struct netlink_data *netlink;
};
+static void nl80211_global_deinit(void *priv);
+
struct i802_bss {
struct wpa_driver_nl80211_data *drv;
struct i802_bss *next;
u8 addr[ETH_ALEN];
char phyname[32];
void *ctx;
- struct netlink_data *netlink;
int ioctl_sock; /* socket for ioctl() use */
int ifindex;
int if_removed;
}
+static struct wpa_driver_nl80211_data *
+nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
+{
+ struct wpa_driver_nl80211_data *drv;
+ dl_list_for_each(drv, &global->interfaces,
+ struct wpa_driver_nl80211_data, list) {
+ if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
+ have_ifidx(drv, idx))
+ return drv;
+ }
+ return NULL;
+}
+
+
static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
struct ifinfomsg *ifi,
u8 *buf, size_t len)
{
- struct wpa_driver_nl80211_data *drv = ctx;
+ struct nl80211_global *global = ctx;
+ struct wpa_driver_nl80211_data *drv;
int attrlen, rta_len;
struct rtattr *attr;
u32 brid = 0;
- if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len) &&
- !have_ifidx(drv, ifi->ifi_index)) {
+ drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
+ if (!drv) {
wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign "
"ifindex %d", ifi->ifi_index);
return;
if (drv->operstate == 1 &&
(ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
!(ifi->ifi_flags & IFF_RUNNING))
- netlink_send_oper_ifla(drv->netlink, drv->ifindex,
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
-1, IF_OPER_UP);
attrlen = len;
struct ifinfomsg *ifi,
u8 *buf, size_t len)
{
- struct wpa_driver_nl80211_data *drv = ctx;
+ struct nl80211_global *global = ctx;
+ struct wpa_driver_nl80211_data *drv;
int attrlen, rta_len;
struct rtattr *attr;
u32 brid = 0;
+ drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
+ if (!drv) {
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore dellink event for "
+ "foreign ifindex %d", ifi->ifi_index);
+ return;
+ }
+
attrlen = len;
attr = (struct rtattr *) buf;
void *global_priv)
{
struct wpa_driver_nl80211_data *drv;
- struct netlink_config *cfg;
struct rfkill_config *rcfg;
struct i802_bss *bss;
goto failed;
}
- cfg = os_zalloc(sizeof(*cfg));
- if (cfg == NULL)
- goto failed;
- cfg->ctx = drv;
- cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
- cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
- drv->netlink = netlink_init(cfg);
- if (drv->netlink == NULL) {
- os_free(cfg);
- goto failed;
- }
-
rcfg = os_zalloc(sizeof(*rcfg));
if (rcfg == NULL)
goto failed;
failed:
rfkill_deinit(drv->rfkill);
- netlink_deinit(drv->netlink);
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
}
}
- netlink_send_oper_ifla(drv->netlink, drv->ifindex,
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
1, IF_OPER_DORMANT);
#endif /* HOSTAPD */
if (drv->disable_11b_rates)
nl80211_disable_11b_rates(drv, drv->ifindex, 0);
- netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
- netlink_deinit(drv->netlink);
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
+ IF_OPER_UP);
rfkill_deinit(drv->rfkill);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
__func__, drv->operstate, state, state ? "UP" : "DORMANT");
drv->operstate = state;
- return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
+ return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
state ? IF_OPER_UP : IF_OPER_DORMANT);
}
failed:
nl80211_remove_monitor_interface(drv);
rfkill_deinit(drv->rfkill);
- netlink_deinit(drv->netlink);
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
static void * nl80211_global_init(void)
{
struct nl80211_global *global;
+ struct netlink_config *cfg;
+
global = os_zalloc(sizeof(*global));
if (global == NULL)
return NULL;
dl_list_init(&global->interfaces);
global->if_add_ifindex = -1;
+
+ cfg = os_zalloc(sizeof(*cfg));
+ if (cfg == NULL)
+ goto err;
+
+ cfg->ctx = global;
+ cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
+ cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
+ global->netlink = netlink_init(cfg);
+ if (global->netlink == NULL) {
+ os_free(cfg);
+ goto err;
+ }
+
return global;
+
+err:
+ nl80211_global_deinit(global);
+ return NULL;
}
"nl80211_global_deinit",
dl_list_len(&global->interfaces));
}
+
+ if (global->netlink)
+ netlink_deinit(global->netlink);
+
os_free(global);
}