Find correct driver for interface additions/removals
Interface additions/removals are not guaranteed to be for the driver listening to the kernel events. As such, send the events to wpa_supplicant_event_global() which can then pick the correct interface registered with wpa_supplicant to send the event to. Signed-off-by: Roy Marples <roy@marples.name>
This commit is contained in:
parent
90377029c6
commit
45e3fc72c6
10 changed files with 226 additions and 49 deletions
|
@ -171,7 +171,8 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||||
|
|
||||||
if (global.drv_priv[i] == NULL &&
|
if (global.drv_priv[i] == NULL &&
|
||||||
wpa_drivers[i]->global_init) {
|
wpa_drivers[i]->global_init) {
|
||||||
global.drv_priv[i] = wpa_drivers[i]->global_init();
|
global.drv_priv[i] =
|
||||||
|
wpa_drivers[i]->global_init(iface->interfaces);
|
||||||
if (global.drv_priv[i] == NULL) {
|
if (global.drv_priv[i] == NULL) {
|
||||||
wpa_printf(MSG_ERROR, "Failed to initialize "
|
wpa_printf(MSG_ERROR, "Failed to initialize "
|
||||||
"driver '%s'",
|
"driver '%s'",
|
||||||
|
|
|
@ -1353,4 +1353,31 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
||||||
|
union wpa_event_data *data)
|
||||||
|
{
|
||||||
|
struct hapd_interfaces *interfaces = ctx;
|
||||||
|
struct hostapd_data *hapd;
|
||||||
|
|
||||||
|
if (event != EVENT_INTERFACE_STATUS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hapd = hostapd_get_iface(interfaces, data->interface_status.ifname);
|
||||||
|
if (hapd && hapd->driver && hapd->driver->get_ifindex &&
|
||||||
|
hapd->drv_priv) {
|
||||||
|
unsigned int ifindex;
|
||||||
|
|
||||||
|
ifindex = hapd->driver->get_ifindex(hapd->drv_priv);
|
||||||
|
if (ifindex != data->interface_status.ifindex) {
|
||||||
|
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
|
||||||
|
"interface status ifindex %d mismatch (%d)",
|
||||||
|
ifindex, data->interface_status.ifindex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hapd)
|
||||||
|
wpa_supplicant_event(hapd, event, data);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
|
|
@ -3090,6 +3090,8 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
||||||
hostapd_enable_iface(iface);
|
hostapd_enable_iface(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
||||||
|
|
||||||
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
|
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
|
||||||
const char *ifname)
|
const char *ifname)
|
||||||
|
@ -3110,8 +3112,6 @@ struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NEED_AP_MLME */
|
|
||||||
|
|
||||||
|
|
||||||
void hostapd_periodic_iface(struct hostapd_iface *iface)
|
void hostapd_periodic_iface(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1957,6 +1957,14 @@ struct wpa_driver_ops {
|
||||||
*/
|
*/
|
||||||
void (*poll)(void *priv);
|
void (*poll)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_ifindex - Get interface index
|
||||||
|
* @priv: private driver interface data
|
||||||
|
*
|
||||||
|
* Returns: Interface index
|
||||||
|
*/
|
||||||
|
unsigned int (*get_ifindex)(void *priv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_ifname - Get interface name
|
* get_ifname - Get interface name
|
||||||
* @priv: private driver interface data
|
* @priv: private driver interface data
|
||||||
|
@ -2091,6 +2099,7 @@ struct wpa_driver_ops {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* global_init - Global driver initialization
|
* global_init - Global driver initialization
|
||||||
|
* @ctx: wpa_global pointer
|
||||||
* Returns: Pointer to private data (global), %NULL on failure
|
* Returns: Pointer to private data (global), %NULL on failure
|
||||||
*
|
*
|
||||||
* This optional function is called to initialize the driver wrapper
|
* This optional function is called to initialize the driver wrapper
|
||||||
|
@ -2100,7 +2109,7 @@ struct wpa_driver_ops {
|
||||||
* use init2() function instead of init() to get the pointer to global
|
* use init2() function instead of init() to get the pointer to global
|
||||||
* data available to per-interface initializer.
|
* data available to per-interface initializer.
|
||||||
*/
|
*/
|
||||||
void * (*global_init)(void);
|
void * (*global_init)(void *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* global_deinit - Global driver deinitialization
|
* global_deinit - Global driver deinitialization
|
||||||
|
@ -4269,6 +4278,7 @@ union wpa_event_data {
|
||||||
* struct interface_status - Data for EVENT_INTERFACE_STATUS
|
* struct interface_status - Data for EVENT_INTERFACE_STATUS
|
||||||
*/
|
*/
|
||||||
struct interface_status {
|
struct interface_status {
|
||||||
|
unsigned int ifindex;
|
||||||
char ifname[100];
|
char ifname[100];
|
||||||
enum {
|
enum {
|
||||||
EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED
|
EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED
|
||||||
|
@ -4745,6 +4755,18 @@ union wpa_event_data {
|
||||||
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
union wpa_event_data *data);
|
union wpa_event_data *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_supplicant_event_global - Report a driver event for wpa_supplicant
|
||||||
|
* @ctx: Context pointer (wpa_s); this is the ctx variable registered
|
||||||
|
* with struct wpa_driver_ops::init()
|
||||||
|
* @event: event type (defined above)
|
||||||
|
* @data: possible extra data for the event
|
||||||
|
*
|
||||||
|
* Same as wpa_supplicant_event(), but we search for the interface in
|
||||||
|
* wpa_global.
|
||||||
|
*/
|
||||||
|
void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
||||||
|
union wpa_event_data *data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following inline functions are provided for convenience to simplify
|
* The following inline functions are provided for convenience to simplify
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "l2_packet/l2_packet.h"
|
#include "l2_packet/l2_packet.h"
|
||||||
|
|
||||||
struct bsd_driver_global {
|
struct bsd_driver_global {
|
||||||
|
void *ctx;
|
||||||
int sock; /* socket for 802.11 ioctls */
|
int sock; /* socket for 802.11 ioctls */
|
||||||
int route; /* routing socket for events */
|
int route; /* routing socket for events */
|
||||||
char *event_buf;
|
char *event_buf;
|
||||||
|
@ -64,6 +65,7 @@ struct bsd_driver_data {
|
||||||
char ifname[IFNAMSIZ+1]; /* interface name */
|
char ifname[IFNAMSIZ+1]; /* interface name */
|
||||||
int flags;
|
int flags;
|
||||||
unsigned int ifindex; /* interface index */
|
unsigned int ifindex; /* interface index */
|
||||||
|
int if_removed; /* has the interface been removed? */
|
||||||
void *ctx;
|
void *ctx;
|
||||||
struct wpa_driver_capa capa; /* driver capability */
|
struct wpa_driver_capa capa; /* driver capability */
|
||||||
int is_ap; /* Access point mode */
|
int is_ap; /* Access point mode */
|
||||||
|
@ -88,13 +90,28 @@ bsd_get_drvindex(void *priv, unsigned int ifindex)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HOSTAPD
|
||||||
|
static struct bsd_driver_data *
|
||||||
|
bsd_get_drvname(void *priv, const char *ifname)
|
||||||
|
{
|
||||||
|
struct bsd_driver_global *global = priv;
|
||||||
|
struct bsd_driver_data *drv;
|
||||||
|
|
||||||
|
dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
|
||||||
|
if (os_strcmp(drv->ifname, ifname) == 0)
|
||||||
|
return drv;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
|
bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
|
||||||
{
|
{
|
||||||
struct bsd_driver_data *drv = priv;
|
struct bsd_driver_data *drv = priv;
|
||||||
struct ieee80211req ireq;
|
struct ieee80211req ireq;
|
||||||
|
|
||||||
if (drv->ifindex == 0)
|
if (drv->ifindex == 0 || drv->if_removed)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
os_memset(&ireq, 0, sizeof(ireq));
|
os_memset(&ireq, 0, sizeof(ireq));
|
||||||
|
@ -1222,24 +1239,45 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||||
switch (rtm->rtm_type) {
|
switch (rtm->rtm_type) {
|
||||||
case RTM_IFANNOUNCE:
|
case RTM_IFANNOUNCE:
|
||||||
ifan = (struct if_announcemsghdr *) rtm;
|
ifan = (struct if_announcemsghdr *) rtm;
|
||||||
drv = bsd_get_drvindex(global, ifan->ifan_index);
|
|
||||||
if (drv == NULL)
|
|
||||||
return;
|
|
||||||
os_strlcpy(event.interface_status.ifname, drv->ifname,
|
|
||||||
sizeof(event.interface_status.ifname));
|
|
||||||
switch (ifan->ifan_what) {
|
switch (ifan->ifan_what) {
|
||||||
case IFAN_DEPARTURE:
|
case IFAN_DEPARTURE:
|
||||||
|
drv = bsd_get_drvindex(global, ifan->ifan_index);
|
||||||
|
if (drv)
|
||||||
|
drv->if_removed = 1;
|
||||||
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
||||||
drv->ifindex = 0;
|
break;
|
||||||
|
case IFAN_ARRIVAL:
|
||||||
|
drv = bsd_get_drvname(global, ifan->ifan_name);
|
||||||
|
if (drv) {
|
||||||
|
drv->ifindex = ifan->ifan_index;
|
||||||
|
drv->if_removed = 0;
|
||||||
|
}
|
||||||
|
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
|
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
|
||||||
event.interface_status.ifname,
|
ifan->ifan_name,
|
||||||
ifan->ifan_what == IFAN_DEPARTURE ?
|
ifan->ifan_what == IFAN_DEPARTURE ?
|
||||||
"removed" : "added");
|
"removed" : "added");
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
os_strlcpy(event.interface_status.ifname, ifan->ifan_name,
|
||||||
|
sizeof(event.interface_status.ifname));
|
||||||
|
if (drv) {
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
|
||||||
|
&event);
|
||||||
|
/*
|
||||||
|
* Set ifindex to zero after sending the event as the
|
||||||
|
* event might query the driver to ensure a match.
|
||||||
|
*/
|
||||||
|
if (ifan->ifan_what == IFAN_DEPARTURE)
|
||||||
|
drv->ifindex = 0;
|
||||||
|
} else {
|
||||||
|
wpa_supplicant_event_global(global->ctx,
|
||||||
|
EVENT_INTERFACE_STATUS,
|
||||||
|
&event);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case RTM_IEEE80211:
|
case RTM_IEEE80211:
|
||||||
ifan = (struct if_announcemsghdr *) rtm;
|
ifan = (struct if_announcemsghdr *) rtm;
|
||||||
|
@ -1582,7 +1620,7 @@ wpa_driver_bsd_deinit(void *priv)
|
||||||
{
|
{
|
||||||
struct bsd_driver_data *drv = priv;
|
struct bsd_driver_data *drv = priv;
|
||||||
|
|
||||||
if (drv->ifindex != 0) {
|
if (drv->ifindex != 0 && !drv->if_removed) {
|
||||||
wpa_driver_bsd_set_wpa(drv, 0);
|
wpa_driver_bsd_set_wpa(drv, 0);
|
||||||
|
|
||||||
/* NB: mark interface down */
|
/* NB: mark interface down */
|
||||||
|
@ -1615,7 +1653,7 @@ wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
bsd_global_init(void)
|
bsd_global_init(void *ctx)
|
||||||
{
|
{
|
||||||
struct bsd_driver_global *global;
|
struct bsd_driver_global *global;
|
||||||
|
|
||||||
|
@ -1623,6 +1661,7 @@ bsd_global_init(void)
|
||||||
if (global == NULL)
|
if (global == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
global->ctx = ctx;
|
||||||
dl_list_init(&global->ifaces);
|
dl_list_init(&global->ifaces);
|
||||||
|
|
||||||
global->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
global->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
|
@ -763,6 +763,15 @@ static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int nl80211_get_ifindex(void *priv)
|
||||||
|
{
|
||||||
|
struct i802_bss *bss = priv;
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
|
||||||
|
return drv->ifindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
|
static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
|
@ -786,11 +795,12 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
|
||||||
|
|
||||||
|
|
||||||
static void wpa_driver_nl80211_event_newlink(
|
static void wpa_driver_nl80211_event_newlink(
|
||||||
struct wpa_driver_nl80211_data *drv, const char *ifname)
|
struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
|
||||||
|
int ifindex, const char *ifname)
|
||||||
{
|
{
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
|
|
||||||
if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
|
if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
|
||||||
if (if_nametoindex(drv->first_bss->ifname) == 0) {
|
if (if_nametoindex(drv->first_bss->ifname) == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
|
wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
|
||||||
drv->first_bss->ifname);
|
drv->first_bss->ifname);
|
||||||
|
@ -804,19 +814,25 @@ static void wpa_driver_nl80211_event_newlink(
|
||||||
}
|
}
|
||||||
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
event.interface_status.ifindex = ifindex;
|
||||||
os_strlcpy(event.interface_status.ifname, ifname,
|
os_strlcpy(event.interface_status.ifname, ifname,
|
||||||
sizeof(event.interface_status.ifname));
|
sizeof(event.interface_status.ifname));
|
||||||
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
||||||
|
if (drv)
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
||||||
|
else
|
||||||
|
wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
|
||||||
|
&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpa_driver_nl80211_event_dellink(
|
static void wpa_driver_nl80211_event_dellink(
|
||||||
struct wpa_driver_nl80211_data *drv, const char *ifname)
|
struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
|
||||||
|
int ifindex, const char *ifname)
|
||||||
{
|
{
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
|
|
||||||
if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
|
if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
|
||||||
if (drv->if_removed) {
|
if (drv->if_removed) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
|
wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
|
||||||
ifname);
|
ifname);
|
||||||
|
@ -831,10 +847,15 @@ static void wpa_driver_nl80211_event_dellink(
|
||||||
}
|
}
|
||||||
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
event.interface_status.ifindex = ifindex;
|
||||||
os_strlcpy(event.interface_status.ifname, ifname,
|
os_strlcpy(event.interface_status.ifname, ifname,
|
||||||
sizeof(event.interface_status.ifname));
|
sizeof(event.interface_status.ifname));
|
||||||
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
||||||
|
if (drv)
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
||||||
|
else
|
||||||
|
wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
|
||||||
|
&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -908,13 +929,6 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
char ifname[IFNAMSIZ + 1];
|
char ifname[IFNAMSIZ + 1];
|
||||||
char extra[100], *pos, *end;
|
char extra[100], *pos, *end;
|
||||||
|
|
||||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
|
||||||
if (!drv) {
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
|
|
||||||
ifi->ifi_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
extra[0] = '\0';
|
extra[0] = '\0';
|
||||||
pos = extra;
|
pos = extra;
|
||||||
end = pos + sizeof(extra);
|
end = pos + sizeof(extra);
|
||||||
|
@ -958,6 +972,10 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
||||||
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
|
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
|
||||||
|
|
||||||
|
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
||||||
|
if (!drv)
|
||||||
|
goto event_newlink;
|
||||||
|
|
||||||
if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
|
if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
|
||||||
namebuf[0] = '\0';
|
namebuf[0] = '\0';
|
||||||
if (if_indextoname(ifi->ifi_index, namebuf) &&
|
if (if_indextoname(ifi->ifi_index, namebuf) &&
|
||||||
|
@ -1052,10 +1070,12 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
-1, IF_OPER_UP);
|
-1, IF_OPER_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event_newlink:
|
||||||
if (ifname[0])
|
if (ifname[0])
|
||||||
wpa_driver_nl80211_event_newlink(drv, ifname);
|
wpa_driver_nl80211_event_newlink(global, drv, ifi->ifi_index,
|
||||||
|
ifname);
|
||||||
|
|
||||||
if (ifi->ifi_family == AF_BRIDGE && brid) {
|
if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
|
||||||
struct i802_bss *bss;
|
struct i802_bss *bss;
|
||||||
|
|
||||||
/* device has been added to bridge */
|
/* device has been added to bridge */
|
||||||
|
@ -1091,13 +1111,6 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
|
||||||
char ifname[IFNAMSIZ + 1];
|
char ifname[IFNAMSIZ + 1];
|
||||||
char extra[100], *pos, *end;
|
char extra[100], *pos, *end;
|
||||||
|
|
||||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
|
||||||
if (!drv) {
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
|
|
||||||
ifi->ifi_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
extra[0] = '\0';
|
extra[0] = '\0';
|
||||||
pos = extra;
|
pos = extra;
|
||||||
end = pos + sizeof(extra);
|
end = pos + sizeof(extra);
|
||||||
|
@ -1138,10 +1151,9 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
|
||||||
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
||||||
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
|
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
|
||||||
|
|
||||||
if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
|
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
||||||
wpa_driver_nl80211_event_dellink(drv, ifname);
|
|
||||||
|
|
||||||
if (ifi->ifi_family == AF_BRIDGE && brid) {
|
if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
|
||||||
/* device has been removed from bridge */
|
/* device has been removed from bridge */
|
||||||
char namebuf[IFNAMSIZ];
|
char namebuf[IFNAMSIZ];
|
||||||
|
|
||||||
|
@ -1156,6 +1168,10 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
|
||||||
}
|
}
|
||||||
del_ifidx(drv, brid, ifi->ifi_index);
|
del_ifidx(drv, brid, ifi->ifi_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifi->ifi_family != AF_BRIDGE || !brid)
|
||||||
|
wpa_driver_nl80211_event_dellink(global, drv, ifi->ifi_index,
|
||||||
|
ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6858,7 +6874,7 @@ static int nl80211_set_param(void *priv, const char *param)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void * nl80211_global_init(void)
|
static void * nl80211_global_init(void *ctx)
|
||||||
{
|
{
|
||||||
struct nl80211_global *global;
|
struct nl80211_global *global;
|
||||||
struct netlink_config *cfg;
|
struct netlink_config *cfg;
|
||||||
|
@ -6866,6 +6882,7 @@ static void * nl80211_global_init(void)
|
||||||
global = os_zalloc(sizeof(*global));
|
global = os_zalloc(sizeof(*global));
|
||||||
if (global == NULL)
|
if (global == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
global->ctx = ctx;
|
||||||
global->ioctl_sock = -1;
|
global->ioctl_sock = -1;
|
||||||
dl_list_init(&global->interfaces);
|
dl_list_init(&global->interfaces);
|
||||||
global->if_add_ifindex = -1;
|
global->if_add_ifindex = -1;
|
||||||
|
@ -9143,6 +9160,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.br_set_net_param = wpa_driver_br_set_net_param,
|
.br_set_net_param = wpa_driver_br_set_net_param,
|
||||||
.add_tx_ts = nl80211_add_ts,
|
.add_tx_ts = nl80211_add_ts,
|
||||||
.del_tx_ts = nl80211_del_ts,
|
.del_tx_ts = nl80211_del_ts,
|
||||||
|
.get_ifindex = nl80211_get_ifindex,
|
||||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
.do_acs = wpa_driver_do_acs,
|
.do_acs = wpa_driver_do_acs,
|
||||||
.set_band = nl80211_set_band,
|
.set_band = nl80211_set_band,
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#endif /* CONFIG_LIBNL20 */
|
#endif /* CONFIG_LIBNL20 */
|
||||||
|
|
||||||
struct nl80211_global {
|
struct nl80211_global {
|
||||||
|
void *ctx;
|
||||||
struct dl_list interfaces;
|
struct dl_list interfaces;
|
||||||
int if_add_ifindex;
|
int if_add_ifindex;
|
||||||
u64 if_add_wdevid;
|
u64 if_add_wdevid;
|
||||||
|
|
|
@ -4008,3 +4008,29 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
||||||
|
union wpa_event_data *data)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s;
|
||||||
|
|
||||||
|
if (event != EVENT_INTERFACE_STATUS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_s = wpa_supplicant_get_iface(ctx, data->interface_status.ifname);
|
||||||
|
if (wpa_s && wpa_s->driver->get_ifindex) {
|
||||||
|
unsigned int ifindex;
|
||||||
|
|
||||||
|
ifindex = wpa_s->driver->get_ifindex(wpa_s->drv_priv);
|
||||||
|
if (ifindex != data->interface_status.ifindex) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"interface status ifindex %d mismatch (%d)",
|
||||||
|
ifindex, data->interface_status.ifindex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_s)
|
||||||
|
wpa_supplicant_event(wpa_s, event, data);
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ struct wpa_priv_interface {
|
||||||
char *sock_name;
|
char *sock_name;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
void *ctx;
|
||||||
|
|
||||||
const struct wpa_driver_ops *driver;
|
const struct wpa_driver_ops *driver;
|
||||||
void *drv_priv;
|
void *drv_priv;
|
||||||
void *drv_global_priv;
|
void *drv_global_priv;
|
||||||
|
@ -40,6 +42,10 @@ struct wpa_priv_interface {
|
||||||
struct sockaddr_un l2_addr;
|
struct sockaddr_un l2_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wpa_priv_global {
|
||||||
|
struct wpa_priv_interface *interfaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
|
static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
|
||||||
struct sockaddr_un *from)
|
struct sockaddr_un *from)
|
||||||
|
@ -65,7 +71,8 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
|
||||||
|
|
||||||
if (iface->driver->init2) {
|
if (iface->driver->init2) {
|
||||||
if (iface->driver->global_init) {
|
if (iface->driver->global_init) {
|
||||||
iface->drv_global_priv = iface->driver->global_init();
|
iface->drv_global_priv =
|
||||||
|
iface->driver->global_init(iface->ctx);
|
||||||
if (!iface->drv_global_priv) {
|
if (!iface->drv_global_priv) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"Failed to initialize driver global context");
|
"Failed to initialize driver global context");
|
||||||
|
@ -638,7 +645,7 @@ static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
|
||||||
|
|
||||||
|
|
||||||
static struct wpa_priv_interface *
|
static struct wpa_priv_interface *
|
||||||
wpa_priv_interface_init(const char *dir, const char *params)
|
wpa_priv_interface_init(void *ctx, const char *dir, const char *params)
|
||||||
{
|
{
|
||||||
struct wpa_priv_interface *iface;
|
struct wpa_priv_interface *iface;
|
||||||
char *pos;
|
char *pos;
|
||||||
|
@ -654,6 +661,7 @@ wpa_priv_interface_init(const char *dir, const char *params)
|
||||||
if (iface == NULL)
|
if (iface == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
iface->fd = -1;
|
iface->fd = -1;
|
||||||
|
iface->ctx = ctx;
|
||||||
|
|
||||||
len = pos - params;
|
len = pos - params;
|
||||||
iface->driver_name = dup_binstr(params, len);
|
iface->driver_name = dup_binstr(params, len);
|
||||||
|
@ -1002,6 +1010,37 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
||||||
|
union wpa_event_data *data)
|
||||||
|
{
|
||||||
|
struct wpa_priv_global *global = ctx;
|
||||||
|
struct wpa_priv_interface *iface;
|
||||||
|
|
||||||
|
if (event != EVENT_INTERFACE_STATUS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (iface = global->interfaces; iface; iface = iface->next) {
|
||||||
|
if (os_strcmp(iface->ifname, data->interface_status.ifname) ==
|
||||||
|
0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (iface && iface->driver->get_ifindex) {
|
||||||
|
unsigned int ifindex;
|
||||||
|
|
||||||
|
ifindex = iface->driver->get_ifindex(iface->drv_priv);
|
||||||
|
if (ifindex != data->interface_status.ifindex) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"%s: interface status ifindex %d mismatch (%d)",
|
||||||
|
iface->ifname, ifindex,
|
||||||
|
data->interface_status.ifindex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iface)
|
||||||
|
wpa_supplicant_event(iface, event, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
|
void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
|
||||||
const u8 *buf, size_t len)
|
const u8 *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -1077,13 +1116,17 @@ int main(int argc, char *argv[])
|
||||||
char *pid_file = NULL;
|
char *pid_file = NULL;
|
||||||
int daemonize = 0;
|
int daemonize = 0;
|
||||||
char *ctrl_dir = "/var/run/wpa_priv";
|
char *ctrl_dir = "/var/run/wpa_priv";
|
||||||
struct wpa_priv_interface *interfaces = NULL, *iface;
|
struct wpa_priv_global global;
|
||||||
|
struct wpa_priv_interface *iface;
|
||||||
|
|
||||||
if (os_program_init())
|
if (os_program_init())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wpa_priv_fd_workaround();
|
wpa_priv_fd_workaround();
|
||||||
|
|
||||||
|
os_memset(&global, 0, sizeof(global));
|
||||||
|
global.interfaces = NULL;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = getopt(argc, argv, "Bc:dP:");
|
c = getopt(argc, argv, "Bc:dP:");
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
|
@ -1121,11 +1164,11 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
for (i = optind; i < argc; i++) {
|
for (i = optind; i < argc; i++) {
|
||||||
wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
|
wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
|
||||||
iface = wpa_priv_interface_init(ctrl_dir, argv[i]);
|
iface = wpa_priv_interface_init(&global, ctrl_dir, argv[i]);
|
||||||
if (iface == NULL)
|
if (iface == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
iface->next = interfaces;
|
iface->next = global.interfaces;
|
||||||
interfaces = iface;
|
global.interfaces = iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
|
if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
|
||||||
|
@ -1137,7 +1180,7 @@ int main(int argc, char *argv[])
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
iface = interfaces;
|
iface = global.interfaces;
|
||||||
while (iface) {
|
while (iface) {
|
||||||
struct wpa_priv_interface *prev = iface;
|
struct wpa_priv_interface *prev = iface;
|
||||||
iface = iface->next;
|
iface = iface->next;
|
||||||
|
|
|
@ -3143,7 +3143,7 @@ static int select_driver(struct wpa_supplicant *wpa_s, int i)
|
||||||
struct wpa_global *global = wpa_s->global;
|
struct wpa_global *global = wpa_s->global;
|
||||||
|
|
||||||
if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
|
if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
|
||||||
global->drv_priv[i] = wpa_drivers[i]->global_init();
|
global->drv_priv[i] = wpa_drivers[i]->global_init(global);
|
||||||
if (global->drv_priv[i] == NULL) {
|
if (global->drv_priv[i] == NULL) {
|
||||||
wpa_printf(MSG_ERROR, "Failed to initialize driver "
|
wpa_printf(MSG_ERROR, "Failed to initialize driver "
|
||||||
"'%s'", wpa_drivers[i]->name);
|
"'%s'", wpa_drivers[i]->name);
|
||||||
|
|
Loading…
Reference in a new issue