|
@@ -119,8 +119,11 @@ static inline int __genl_ctrl_alloc_cache(struct nl_handle *h,
|
|
|
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;
|
|
@@ -138,7 +141,6 @@ struct wpa_driver_nl80211_data {
|
|
|
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;
|
|
@@ -504,17 +506,32 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
|
|
|
}
|
|
|
|
|
|
|
|
|
+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;
|
|
@@ -556,7 +573,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
|
|
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;
|
|
@@ -590,11 +607,19 @@ static void wpa_driver_nl80211_event_rtm_dellink(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;
|
|
|
|
|
|
+ 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;
|
|
|
|
|
@@ -2129,7 +2154,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
|
|
|
void *global_priv)
|
|
|
{
|
|
|
struct wpa_driver_nl80211_data *drv;
|
|
|
- struct netlink_config *cfg;
|
|
|
struct rfkill_config *rcfg;
|
|
|
struct i802_bss *bss;
|
|
|
|
|
@@ -2159,18 +2183,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
|
|
|
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;
|
|
@@ -2199,7 +2211,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
|
|
|
|
|
|
failed:
|
|
|
rfkill_deinit(drv->rfkill);
|
|
|
- netlink_deinit(drv->netlink);
|
|
|
if (drv->ioctl_sock >= 0)
|
|
|
close(drv->ioctl_sock);
|
|
|
|
|
@@ -2349,7 +2360,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- netlink_send_oper_ifla(drv->netlink, drv->ifindex,
|
|
|
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
|
|
|
1, IF_OPER_DORMANT);
|
|
|
#endif /* HOSTAPD */
|
|
|
|
|
@@ -2454,8 +2465,8 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
|
|
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);
|
|
@@ -5758,7 +5769,7 @@ static int wpa_driver_nl80211_set_operstate(void *priv, int state)
|
|
|
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);
|
|
|
}
|
|
|
|
|
@@ -6453,7 +6464,6 @@ static void *i802_init(struct hostapd_data *hapd,
|
|
|
failed:
|
|
|
nl80211_remove_monitor_interface(drv);
|
|
|
rfkill_deinit(drv->rfkill);
|
|
|
- netlink_deinit(drv->netlink);
|
|
|
if (drv->ioctl_sock >= 0)
|
|
|
close(drv->ioctl_sock);
|
|
|
|
|
@@ -7168,12 +7178,32 @@ static int nl80211_set_param(void *priv, const char *param)
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -7187,6 +7217,10 @@ static void nl80211_global_deinit(void *priv)
|
|
|
"nl80211_global_deinit",
|
|
|
dl_list_len(&global->interfaces));
|
|
|
}
|
|
|
+
|
|
|
+ if (global->netlink)
|
|
|
+ netlink_deinit(global->netlink);
|
|
|
+
|
|
|
os_free(global);
|
|
|
}
|
|
|
|