Find correct driver for interface additions/removals
authorRoy Marples <roy@marples.name>
Tue, 15 Mar 2016 13:02:08 +0000 (13:02 +0000)
committerJouni Malinen <j@w1.fi>
Tue, 22 Mar 2016 15:41:37 +0000 (17:41 +0200)
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>
hostapd/main.c
src/ap/drv_callbacks.c
src/ap/hostapd.c
src/drivers/driver.h
src/drivers/driver_bsd.c
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
wpa_supplicant/events.c
wpa_supplicant/wpa_priv.c
wpa_supplicant/wpa_supplicant.c

index 25dc20b..1d9e63e 100644 (file)
@@ -171,7 +171,8 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
 
                if (global.drv_priv[i] == NULL &&
                    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) {
                                wpa_printf(MSG_ERROR, "Failed to initialize "
                                           "driver '%s'",
index f54d1ad..3ab5bf3 100644 (file)
@@ -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 */
index 55ca9e8..ee80f4f 100644 (file)
@@ -3090,6 +3090,8 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
        hostapd_enable_iface(iface);
 }
 
+#endif /* NEED_AP_MLME */
+
 
 struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
                                        const char *ifname)
@@ -3110,8 +3112,6 @@ struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
        return NULL;
 }
 
-#endif /* NEED_AP_MLME */
-
 
 void hostapd_periodic_iface(struct hostapd_iface *iface)
 {
index 642276c..b7e0d16 100644 (file)
@@ -1958,6 +1958,14 @@ struct wpa_driver_ops {
        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
         * @priv: private driver interface data
         *
@@ -2091,6 +2099,7 @@ struct wpa_driver_ops {
 
        /**
         * global_init - Global driver initialization
+        * @ctx: wpa_global pointer
         * Returns: Pointer to private data (global), %NULL on failure
         *
         * 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
         * data available to per-interface initializer.
         */
-       void * (*global_init)(void);
+       void * (*global_init)(void *ctx);
 
        /**
         * global_deinit - Global driver deinitialization
@@ -4269,6 +4278,7 @@ union wpa_event_data {
         * struct interface_status - Data for EVENT_INTERFACE_STATUS
         */
        struct interface_status {
+               unsigned int ifindex;
                char ifname[100];
                enum {
                        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,
                          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
index a6ca9a8..fd73f2e 100644 (file)
@@ -48,6 +48,7 @@
 #include "l2_packet/l2_packet.h"
 
 struct bsd_driver_global {
+       void            *ctx;
        int             sock;                   /* socket for 802.11 ioctls */
        int             route;                  /* routing socket for events */
        char            *event_buf;
@@ -64,6 +65,7 @@ struct bsd_driver_data {
        char    ifname[IFNAMSIZ+1];     /* interface name */
        int     flags;
        unsigned int ifindex;           /* interface index */
+       int     if_removed;             /* has the interface been removed? */
        void    *ctx;
        struct wpa_driver_capa capa;    /* driver capability */
        int     is_ap;                  /* Access point mode */
@@ -88,13 +90,28 @@ bsd_get_drvindex(void *priv, unsigned int ifindex)
        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
 bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
 {
        struct bsd_driver_data *drv = priv;
        struct ieee80211req ireq;
 
-       if (drv->ifindex == 0)
+       if (drv->ifindex == 0 || drv->if_removed)
                return -1;
 
        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) {
        case RTM_IFANNOUNCE:
                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) {
                case IFAN_DEPARTURE:
+                       drv = bsd_get_drvindex(global, ifan->ifan_index);
+                       if (drv)
+                               drv->if_removed = 1;
                        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;
                default:
+                       wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
                        return;
                }
                wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
-                          event.interface_status.ifname,
+                          ifan->ifan_name,
                           ifan->ifan_what == IFAN_DEPARTURE ?
                                "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;
        case RTM_IEEE80211:
                ifan = (struct if_announcemsghdr *) rtm;
@@ -1582,7 +1620,7 @@ wpa_driver_bsd_deinit(void *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);
 
                /* NB: mark interface down */
@@ -1615,7 +1653,7 @@ wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
 #endif /* HOSTAPD */
 
 static void *
-bsd_global_init(void)
+bsd_global_init(void *ctx)
 {
        struct bsd_driver_global *global;
 
@@ -1623,6 +1661,7 @@ bsd_global_init(void)
        if (global == NULL)
                return NULL;
 
+       global->ctx = ctx;
        dl_list_init(&global->ifaces);
 
        global->sock = socket(PF_INET, SOCK_DGRAM, 0);
index b93721c..8bd2c24 100644 (file)
@@ -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)
 {
        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(
-       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;
 
-       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) {
                        wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
                                   drv->first_bss->ifname);
@@ -804,19 +814,25 @@ static void wpa_driver_nl80211_event_newlink(
        }
 
        os_memset(&event, 0, sizeof(event));
+       event.interface_status.ifindex = ifindex;
        os_strlcpy(event.interface_status.ifname, ifname,
                   sizeof(event.interface_status.ifname));
        event.interface_status.ievent = EVENT_INTERFACE_ADDED;
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+       if (drv)
+               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(
-       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;
 
-       if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
+       if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
                if (drv->if_removed) {
                        wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
                                   ifname);
@@ -831,10 +847,15 @@ static void wpa_driver_nl80211_event_dellink(
        }
 
        os_memset(&event, 0, sizeof(event));
+       event.interface_status.ifindex = ifindex;
        os_strlcpy(event.interface_status.ifname, ifname,
                   sizeof(event.interface_status.ifname));
        event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+       if (drv)
+               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 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';
        pos = 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_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)) {
                namebuf[0] = '\0';
                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);
        }
 
+event_newlink:
        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;
 
                /* 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 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';
        pos = 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_DORMANT) ? "[DORMANT]" : "");
 
-       if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
-               wpa_driver_nl80211_event_dellink(drv, ifname);
+       drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
 
-       if (ifi->ifi_family == AF_BRIDGE && brid) {
+       if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
                /* device has been removed from bridge */
                char namebuf[IFNAMSIZ];
 
@@ -1156,6 +1168,10 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
                }
                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 netlink_config *cfg;
@@ -6866,6 +6882,7 @@ static void * nl80211_global_init(void)
        global = os_zalloc(sizeof(*global));
        if (global == NULL)
                return NULL;
+       global->ctx = ctx;
        global->ioctl_sock = -1;
        dl_list_init(&global->interfaces);
        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,
        .add_tx_ts = nl80211_add_ts,
        .del_tx_ts = nl80211_del_ts,
+       .get_ifindex = nl80211_get_ifindex,
 #ifdef CONFIG_DRIVER_NL80211_QCA
        .do_acs = wpa_driver_do_acs,
        .set_band = nl80211_set_band,
index 430369f..3f65569 100644 (file)
@@ -25,6 +25,7 @@
 #endif /* CONFIG_LIBNL20 */
 
 struct nl80211_global {
+       void *ctx;
        struct dl_list interfaces;
        int if_add_ifindex;
        u64 if_add_wdevid;
index d770107..833f5a0 100644 (file)
@@ -4008,3 +4008,29 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                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);
+}
index 3f91cc1..511df4f 100644 (file)
@@ -29,6 +29,8 @@ struct wpa_priv_interface {
        char *sock_name;
        int fd;
 
+       void *ctx;
+
        const struct wpa_driver_ops *driver;
        void *drv_priv;
        void *drv_global_priv;
@@ -40,6 +42,10 @@ struct wpa_priv_interface {
        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,
                                  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->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) {
                                wpa_printf(MSG_INFO,
                                           "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 *
-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;
        char *pos;
@@ -654,6 +661,7 @@ wpa_priv_interface_init(const char *dir, const char *params)
        if (iface == NULL)
                return NULL;
        iface->fd = -1;
+       iface->ctx = ctx;
 
        len = pos - params;
        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,
                             const u8 *buf, size_t len)
 {
@@ -1077,13 +1116,17 @@ int main(int argc, char *argv[])
        char *pid_file = NULL;
        int daemonize = 0;
        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())
                return -1;
 
        wpa_priv_fd_workaround();
 
+       os_memset(&global, 0, sizeof(global));
+       global.interfaces = NULL;
+
        for (;;) {
                c = getopt(argc, argv, "Bc:dP:");
                if (c < 0)
@@ -1121,11 +1164,11 @@ int main(int argc, char *argv[])
 
        for (i = optind; i < argc; 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)
                        goto out;
-               iface->next = interfaces;
-               interfaces = iface;
+               iface->next = global.interfaces;
+               global.interfaces = iface;
        }
 
        if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
@@ -1137,7 +1180,7 @@ int main(int argc, char *argv[])
        ret = 0;
 
 out:
-       iface = interfaces;
+       iface = global.interfaces;
        while (iface) {
                struct wpa_priv_interface *prev = iface;
                iface = iface->next;
index 136cb58..7b43600 100644 (file)
@@ -3143,7 +3143,7 @@ static int select_driver(struct wpa_supplicant *wpa_s, int i)
        struct wpa_global *global = wpa_s->global;
 
        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) {
                        wpa_printf(MSG_ERROR, "Failed to initialize driver "
                                   "'%s'", wpa_drivers[i]->name);