Module Name: src Committed By: roy Date: Thu Jan 14 21:19:41 UTC 2016
Modified Files: src/external/bsd/wpa/dist/src/drivers: driver_bsd.c Log Message: Create global init to handle socket calls and route messages. Register each interface inside the global driver so that routing messages can find the interface based on rtm_ifindex. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/external/bsd/wpa/dist/src/drivers/driver_bsd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/wpa/dist/src/drivers/driver_bsd.c diff -u src/external/bsd/wpa/dist/src/drivers/driver_bsd.c:1.11 src/external/bsd/wpa/dist/src/drivers/driver_bsd.c:1.12 --- src/external/bsd/wpa/dist/src/drivers/driver_bsd.c:1.11 Wed Apr 1 19:45:14 2015 +++ src/external/bsd/wpa/dist/src/drivers/driver_bsd.c Thu Jan 14 21:19:41 2016 @@ -47,12 +47,20 @@ #include "l2_packet/l2_packet.h" +struct bsd_driver_global { + int sock; /* socket for 802.11 ioctls */ + int route; /* routing socket for events */ + char *event_buf; + size_t event_buf_len; + struct dl_list ifaces; /* list of interfaces */ +}; + struct bsd_driver_data { + struct dl_list list; + struct bsd_driver_global *global; struct hostapd_data *hapd; /* back pointer */ - int sock; /* open socket for 802.11 ioctls */ struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ - int route; /* routing socket for events */ char ifname[IFNAMSIZ+1]; /* interface name */ int flags; unsigned int ifindex; /* interface index */ @@ -63,12 +71,23 @@ struct bsd_driver_data { int prev_privacy; /* privacy state to restore on deinit */ int prev_wpa; /* wpa state to restore on deinit */ enum ieee80211_opmode opmode; /* operation mode */ - char *event_buf; - size_t event_buf_len; }; /* Generic functions for hostapd and wpa_supplicant */ +static struct bsd_driver_data * +bsd_get_drvindex(void *priv, unsigned int ifindex) +{ + struct bsd_driver_global *global = priv; + struct bsd_driver_data *drv; + + dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { + if (drv->ifindex == ifindex) + return drv; + } + return NULL; +} + static int bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len) { @@ -82,7 +101,7 @@ bsd_set80211(void *priv, int op, int val ireq.i_data = (void *) arg; ireq.i_len = arg_len; - if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) { + if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, " "arg_len=%u]: %s", op, val, arg_len, strerror(errno)); @@ -103,7 +122,7 @@ bsd_get80211(void *priv, struct ieee8021 ireq->i_len = arg_len; ireq->i_data = arg; - if (ioctl(drv->sock, SIOCG80211, ireq) < 0) { + if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, " "arg_len=%u]: %s", op, arg_len, strerror(errno)); return -1; @@ -144,7 +163,7 @@ bsd_get_ssid(void *priv, u8 *ssid, int l os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); ifr.ifr_data = (void *)&nwid; - if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 || + if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 || nwid.i_len > IEEE80211_NWID_LEN) return -1; os_memcpy(ssid, nwid.i_nwid, nwid.i_len); @@ -167,7 +186,7 @@ bsd_set_ssid(void *priv, const u8 *ssid, os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); ifr.ifr_data = (void *)&nwid; - return ioctl(drv->sock, SIOCS80211NWID, &ifr); + return ioctl(drv->global->sock, SIOCS80211NWID, &ifr); #else return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); #endif @@ -182,7 +201,7 @@ bsd_get_if_media(void *priv) os_memset(&ifmr, 0, sizeof(ifmr)); os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); - if (ioctl(drv->sock, SIOCGIFMEDIA, &ifmr) < 0) { + if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) { wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__, strerror(errno)); return -1; @@ -201,7 +220,7 @@ bsd_set_if_media(void *priv, int media) os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); ifr.ifr_media = media; - if (ioctl(drv->sock, SIOCSIFMEDIA, &ifr) < 0) { + if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) { wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__, strerror(errno)); return -1; @@ -264,7 +283,7 @@ bsd_ctrl_iface(void *priv, int enable) os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFFLAGS, &ifr) < 0) { + if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) { wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", strerror(errno)); return -1; @@ -280,7 +299,7 @@ bsd_ctrl_iface(void *priv, int enable) ifr.ifr_flags &= ~IFF_UP; } - if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) { + if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) { wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s", strerror(errno)); return -1; @@ -577,7 +596,7 @@ bsd_set_freq(void *priv, struct hostapd_ os_memset(&creq, 0, sizeof(creq)); os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); creq.i_channel = (u_int16_t)channel; - return ioctl(drv->sock, SIOCS80211CHANNEL, &creq); + return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq); #else /* SIOCS80211CHANNEL */ return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); #endif /* SIOCS80211CHANNEL */ @@ -734,7 +753,8 @@ bsd_sta_disassoc(void *priv, const u8 *o static void bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) { - struct bsd_driver_data *drv = ctx; + struct bsd_driver_global *global = sock_ctx; + struct bsd_driver_data *drv; struct if_announcemsghdr *ifan; struct rt_msghdr *rtm; struct ieee80211_michael_event *mic; @@ -743,7 +763,7 @@ bsd_wireless_event_receive(int sock, voi int n; union wpa_event_data data; - n = read(sock, drv->event_buf, drv->event_buf_len); + n = read(sock, global->event_buf, global->event_buf_len); if (n < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_ERROR, "%s read() failed: %s", @@ -751,15 +771,18 @@ bsd_wireless_event_receive(int sock, voi return; } - rtm = (struct rt_msghdr *) drv->event_buf; + rtm = (struct rt_msghdr *) global->event_buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", rtm->rtm_version); return; } - ifan = (struct if_announcemsghdr *) rtm; + drv = bsd_get_drvindex(global, rtm->rtm_index); + if (drv == NULL) + return; switch (rtm->rtm_type) { case RTM_IEEE80211: + ifan = (struct if_announcemsghdr *) rtm; switch (ifan->ifan_what) { case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_REASSOC: @@ -815,21 +838,15 @@ bsd_init(struct hostapd_data *hapd, stru return NULL; } - drv->event_buf_len = rtbuf_len(); - - drv->event_buf = os_malloc(drv->event_buf_len); - if (drv->event_buf == NULL) { - wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); + drv->ifindex = if_nametoindex(params->ifname); + if (drv->ifindex == 0) { + wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", + __func__, params->ifname); goto bad; } drv->hapd = hapd; - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", - strerror(errno)); - goto bad; - } + drv->global = params->global_priv; os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, @@ -843,29 +860,19 @@ bsd_init(struct hostapd_data *hapd, stru if (bsd_ctrl_iface(drv, 0) < 0) goto bad; - drv->route = socket(PF_ROUTE, SOCK_RAW, 0); - if (drv->route < 0) { - wpa_printf(MSG_ERROR, "socket(PF_ROUTE,SOCK_RAW): %s", - strerror(errno)); - goto bad; - } - eloop_register_read_sock(drv->route, bsd_wireless_event_receive, drv, - NULL); - if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) { wpa_printf(MSG_ERROR, "%s: failed to set operation mode", __func__); goto bad; } + dl_list_add(&drv->global->ifaces, &drv->list); + return drv; bad: if (drv != NULL) { if (drv->sock_xmit != NULL) l2_packet_deinit(drv->sock_xmit); - if (drv->sock >= 0) - close(drv->sock); - os_free(drv->event_buf); os_free(drv); } return NULL; @@ -877,16 +884,9 @@ bsd_deinit(void *priv) { struct bsd_driver_data *drv = priv; - if (drv->route >= 0) { - eloop_unregister_read_sock(drv->route); - close(drv->route); - } bsd_ctrl_iface(drv, 0); - if (drv->sock >= 0) - close(drv->sock); if (drv->sock_xmit != NULL) l2_packet_deinit(drv->sock_xmit); - os_free(drv->event_buf); os_free(drv); } @@ -937,7 +937,7 @@ wpa_driver_bsd_get_bssid(void *priv, u8 struct ieee80211_bssid bs; os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); - if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0) + if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0) return -1; os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); return 0; @@ -1191,7 +1191,8 @@ wpa_driver_bsd_scan(void *priv, struct w static void wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) { - struct bsd_driver_data *drv = sock_ctx; + struct bsd_driver_global *global = sock_ctx; + struct bsd_driver_data *drv; struct if_announcemsghdr *ifan; struct if_msghdr *ifm; struct rt_msghdr *rtm; @@ -1201,7 +1202,7 @@ wpa_driver_bsd_event_receive(int sock, v struct ieee80211_join_event *join; int n; - n = read(sock, drv->event_buf, drv->event_buf_len); + n = read(sock, global->event_buf, global->event_buf_len); if (n < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_ERROR, "%s read() failed: %s", @@ -1209,18 +1210,20 @@ wpa_driver_bsd_event_receive(int sock, v return; } - rtm = (struct rt_msghdr *) drv->event_buf; + rtm = (struct rt_msghdr *) global->event_buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", rtm->rtm_version); return; } + drv = bsd_get_drvindex(global, rtm->rtm_index); + if (drv == NULL) + return; + ctx = drv->ctx; os_memset(&event, 0, sizeof(event)); switch (rtm->rtm_type) { case RTM_IFANNOUNCE: ifan = (struct if_announcemsghdr *) rtm; - if (ifan->ifan_index != drv->ifindex) - break; os_strlcpy(event.interface_status.ifname, drv->ifname, sizeof(event.interface_status.ifname)); switch (ifan->ifan_what) { @@ -1242,8 +1245,6 @@ wpa_driver_bsd_event_receive(int sock, v return; case RTM_IEEE80211: ifan = (struct if_announcemsghdr *) rtm; - if (ifan->ifan_index != drv->ifindex) - break; switch (ifan->ifan_what) { case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_REASSOC: @@ -1304,8 +1305,6 @@ wpa_driver_bsd_event_receive(int sock, v break; case RTM_IFINFO: ifm = (struct if_msghdr *) rtm; - if (ifm->ifm_index != drv->ifindex) - break; if ((ifm->ifm_flags & IFF_UP) == 0 && (drv->flags & IFF_UP) != 0) { os_strlcpy(event.interface_status.ifname, drv->ifname, @@ -1538,7 +1537,7 @@ get80211opmode(struct bsd_driver_data *d (void) memset(&ifmr, 0, sizeof(ifmr)); (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); - if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { + if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { if (ifmr.ifm_current & IFM_FLAG0) return IEEE80211_M_AHDEMO; @@ -1558,7 +1557,7 @@ get80211opmode(struct bsd_driver_data *d } static void * -wpa_driver_bsd_init(void *ctx, const char *ifname) +wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) { #define GETPARAM(drv, param, v) \ (((v) = get80211param(drv, param)) != -1) @@ -1568,14 +1567,6 @@ wpa_driver_bsd_init(void *ctx, const cha if (drv == NULL) return NULL; - drv->event_buf_len = rtbuf_len(); - - drv->event_buf = os_malloc(drv->event_buf_len); - if (drv->event_buf == NULL) { - wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); - goto fail1; - } - /* * NB: We require the interface name be mappable to an index. * This implies we do not support having wpa_supplicant @@ -1586,25 +1577,17 @@ wpa_driver_bsd_init(void *ctx, const cha if (drv->ifindex == 0) { wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", __func__, ifname); - goto fail1; + goto fail; } - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) - goto fail1; + + drv->ctx = ctx; + drv->global = priv; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); /* Down interface during setup. */ if (bsd_ctrl_iface(drv, 0) < 0) goto fail; - drv->route = socket(PF_ROUTE, SOCK_RAW, 0); - if (drv->route < 0) - goto fail; - eloop_register_read_sock(drv->route, - wpa_driver_bsd_event_receive, ctx, drv); - - drv->ctx = ctx; - if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", __func__, strerror(errno)); @@ -1625,12 +1608,10 @@ wpa_driver_bsd_init(void *ctx, const cha goto fail; drv->opmode = get80211opmode(drv); + dl_list_add(&drv->global->ifaces, &drv->list); return drv; fail: - close(drv->sock); -fail1: - os_free(drv->event_buf); os_free(drv); return NULL; #undef GETPARAM @@ -1642,21 +1623,19 @@ wpa_driver_bsd_deinit(void *priv) struct bsd_driver_data *drv = priv; wpa_driver_bsd_set_wpa(drv, 0); - eloop_unregister_read_sock(drv->route); /* NB: mark interface down */ bsd_ctrl_iface(drv, 0); wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy); + if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0) wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state", __func__); if (drv->sock_xmit != NULL) l2_packet_deinit(drv->sock_xmit); - (void) close(drv->route); /* ioctl socket */ - (void) close(drv->sock); /* event socket */ - os_free(drv->event_buf); + dl_list_del(&drv->list); os_free(drv); } @@ -1670,10 +1649,73 @@ wpa_driver_bsd_get_capa(void *priv, stru } #endif /* HOSTAPD */ +static void * +bsd_global_init() +{ + struct bsd_driver_global *global; + + global = os_zalloc(sizeof(*global)); + if (global == NULL) + return NULL; + + dl_list_init(&global->ifaces); + + global->sock = socket(PF_INET, SOCK_DGRAM, 0); + if (global->sock < 0) { + wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", + strerror(errno)); + goto fail1; + } + + global->route = socket(PF_ROUTE, SOCK_RAW, 0); + if (global->route < 0) { + wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s", + strerror(errno)); + goto fail; + } + + global->event_buf_len = rtbuf_len(); + global->event_buf = os_malloc(global->event_buf_len); + if (global->event_buf == NULL) { + wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); + goto fail; + } + +#ifdef HOSTAPD + eloop_register_read_sock(global->route, bsd_wireless_event_receive, + NULL, global); + +#else /* HOSTAPD */ + eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive, + NULL, global); +#endif /* HOSTAPD */ + + return global; + +fail: + close(global->sock); +fail1: + os_free(global); + return NULL; +} + +static void +bsd_global_deinit(void *priv) +{ + struct bsd_driver_global *global = priv; + + eloop_unregister_read_sock(global->route); + (void) close(global->route); + (void) close(global->sock); + os_free(global); +} + const struct wpa_driver_ops wpa_driver_bsd_ops = { .name = "bsd", .desc = "BSD 802.11 support", + .global_init = bsd_global_init, + .global_deinit = bsd_global_deinit, #ifdef HOSTAPD .hapd_init = bsd_init, .hapd_deinit = bsd_deinit, @@ -1686,7 +1728,7 @@ const struct wpa_driver_ops wpa_driver_b .sta_set_flags = bsd_set_sta_authorized, .commit = bsd_commit, #else /* HOSTAPD */ - .init = wpa_driver_bsd_init, + .init2 = wpa_driver_bsd_init, .deinit = wpa_driver_bsd_deinit, .get_bssid = wpa_driver_bsd_get_bssid, .get_ssid = wpa_driver_bsd_get_ssid,