bsd: Optimize socket use

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.

Signed-off-by: Roy Marples <roy@marples.name>
This commit is contained in:
Roy Marples 2016-01-09 01:39:43 +00:00 committed by Jouni Malinen
parent 4653ceb750
commit 449a31662d

View file

@ -47,12 +47,20 @@
#include "l2_packet/l2_packet.h" #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 bsd_driver_data {
struct dl_list list;
struct bsd_driver_global *global;
struct hostapd_data *hapd; /* back pointer */ struct hostapd_data *hapd; /* back pointer */
int sock; /* open socket for 802.11 ioctls */
struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
int route; /* routing socket for events */
char ifname[IFNAMSIZ+1]; /* interface name */ char ifname[IFNAMSIZ+1]; /* interface name */
unsigned int ifindex; /* interface index */ unsigned int ifindex; /* interface index */
void *ctx; void *ctx;
@ -62,12 +70,23 @@ struct bsd_driver_data {
int prev_privacy; /* privacy state to restore on deinit */ int prev_privacy; /* privacy state to restore on deinit */
int prev_wpa; /* wpa state to restore on deinit */ int prev_wpa; /* wpa state to restore on deinit */
enum ieee80211_opmode opmode; /* operation mode */ enum ieee80211_opmode opmode; /* operation mode */
char *event_buf;
size_t event_buf_len;
}; };
/* Generic functions for hostapd and wpa_supplicant */ /* 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 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)
{ {
@ -81,7 +100,7 @@ bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
ireq.i_data = (void *) arg; ireq.i_data = (void *) arg;
ireq.i_len = arg_len; 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, " wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
"arg_len=%u]: %s", op, val, arg_len, "arg_len=%u]: %s", op, val, arg_len,
strerror(errno)); strerror(errno));
@ -102,7 +121,7 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
ireq->i_len = arg_len; ireq->i_len = arg_len;
ireq->i_data = arg; 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, " wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, "
"arg_len=%u]: %s", op, arg_len, strerror(errno)); "arg_len=%u]: %s", op, arg_len, strerror(errno));
return -1; return -1;
@ -143,7 +162,7 @@ bsd_get_ssid(void *priv, u8 *ssid, int len)
os_memset(&ifr, 0, sizeof(ifr)); os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&nwid; 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) nwid.i_len > IEEE80211_NWID_LEN)
return -1; return -1;
os_memcpy(ssid, nwid.i_nwid, nwid.i_len); os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
@ -166,7 +185,7 @@ bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len)
os_memset(&ifr, 0, sizeof(ifr)); os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&nwid; ifr.ifr_data = (void *)&nwid;
return ioctl(drv->sock, SIOCS80211NWID, &ifr); return ioctl(drv->global->sock, SIOCS80211NWID, &ifr);
#else #else
return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
#endif #endif
@ -181,7 +200,7 @@ bsd_get_if_media(void *priv)
os_memset(&ifmr, 0, sizeof(ifmr)); os_memset(&ifmr, 0, sizeof(ifmr));
os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); 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__, wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__,
strerror(errno)); strerror(errno));
return -1; return -1;
@ -200,7 +219,7 @@ bsd_set_if_media(void *priv, int media)
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_media = media; 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__, wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__,
strerror(errno)); strerror(errno));
return -1; return -1;
@ -263,7 +282,7 @@ bsd_ctrl_iface(void *priv, int enable)
os_memset(&ifr, 0, sizeof(ifr)); os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 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", wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
strerror(errno)); strerror(errno));
return -1; return -1;
@ -279,7 +298,7 @@ bsd_ctrl_iface(void *priv, int enable)
ifr.ifr_flags &= ~IFF_UP; 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", wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
strerror(errno)); strerror(errno));
return -1; return -1;
@ -576,7 +595,7 @@ bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
os_memset(&creq, 0, sizeof(creq)); os_memset(&creq, 0, sizeof(creq));
os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
creq.i_channel = (u_int16_t)channel; creq.i_channel = (u_int16_t)channel;
return ioctl(drv->sock, SIOCS80211CHANNEL, &creq); return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq);
#else /* SIOCS80211CHANNEL */ #else /* SIOCS80211CHANNEL */
return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); return set80211param(priv, IEEE80211_IOC_CHANNEL, channel);
#endif /* SIOCS80211CHANNEL */ #endif /* SIOCS80211CHANNEL */
@ -730,7 +749,8 @@ bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
static void static void
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) 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 if_announcemsghdr *ifan;
struct rt_msghdr *rtm; struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic; struct ieee80211_michael_event *mic;
@ -739,7 +759,7 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
int n; int n;
union wpa_event_data data; 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 (n < 0) {
if (errno != EINTR && errno != EAGAIN) if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s", wpa_printf(MSG_ERROR, "%s read() failed: %s",
@ -747,15 +767,18 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
return; return;
} }
rtm = (struct rt_msghdr *) drv->event_buf; rtm = (struct rt_msghdr *) global->event_buf;
if (rtm->rtm_version != RTM_VERSION) { if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version); rtm->rtm_version);
return; return;
} }
ifan = (struct if_announcemsghdr *) rtm; drv = bsd_get_drvindex(global, rtm->rtm_index);
if (drv == NULL)
return;
switch (rtm->rtm_type) { switch (rtm->rtm_type) {
case RTM_IEEE80211: case RTM_IEEE80211:
ifan = (struct if_announcemsghdr *) rtm;
switch (ifan->ifan_what) { switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC: case RTM_IEEE80211_REASSOC:
@ -811,21 +834,15 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
return NULL; return NULL;
} }
drv->event_buf_len = rtbuf_len(); drv->ifindex = if_nametoindex(params->ifname);
if (drv->ifindex == 0) {
drv->event_buf = os_malloc(drv->event_buf_len); wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
if (drv->event_buf == NULL) { __func__, params->ifname);
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
goto bad; goto bad;
} }
drv->hapd = hapd; drv->hapd = hapd;
drv->sock = socket(PF_INET, SOCK_DGRAM, 0); drv->global = params->global_priv;
if (drv->sock < 0) {
wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
strerror(errno));
goto bad;
}
os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL,
@ -839,28 +856,18 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
if (bsd_ctrl_iface(drv, 0) < 0) if (bsd_ctrl_iface(drv, 0) < 0)
goto bad; 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) { if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to set operation mode", wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
__func__); __func__);
goto bad; goto bad;
} }
dl_list_add(&drv->global->ifaces, &drv->list);
return drv; return drv;
bad: bad:
if (drv->sock_xmit != NULL) if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit); l2_packet_deinit(drv->sock_xmit);
if (drv->sock >= 0)
close(drv->sock);
os_free(drv->event_buf);
os_free(drv); os_free(drv);
return NULL; return NULL;
} }
@ -871,16 +878,9 @@ bsd_deinit(void *priv)
{ {
struct bsd_driver_data *drv = 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); bsd_ctrl_iface(drv, 0);
if (drv->sock >= 0)
close(drv->sock);
if (drv->sock_xmit != NULL) if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit); l2_packet_deinit(drv->sock_xmit);
os_free(drv->event_buf);
os_free(drv); os_free(drv);
} }
@ -932,7 +932,7 @@ wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
struct ieee80211_bssid bs; struct ieee80211_bssid bs;
os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); 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; return -1;
os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
return 0; return 0;
@ -1186,9 +1186,9 @@ wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
static void static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) 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_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm; struct rt_msghdr *rtm;
union wpa_event_data event; union wpa_event_data event;
struct ieee80211_michael_event *mic; struct ieee80211_michael_event *mic;
@ -1196,7 +1196,7 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
struct ieee80211_join_event *join; struct ieee80211_join_event *join;
int n; 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 (n < 0) {
if (errno != EINTR && errno != EAGAIN) if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s", wpa_printf(MSG_ERROR, "%s read() failed: %s",
@ -1204,18 +1204,20 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
return; return;
} }
rtm = (struct rt_msghdr *) drv->event_buf; rtm = (struct rt_msghdr *) global->event_buf;
if (rtm->rtm_version != RTM_VERSION) { if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version); rtm->rtm_version);
return; return;
} }
drv = bsd_get_drvindex(global, rtm->rtm_index);
if (drv == NULL)
return;
ctx = drv->ctx;
os_memset(&event, 0, sizeof(event)); os_memset(&event, 0, sizeof(event));
switch (rtm->rtm_type) { switch (rtm->rtm_type) {
case RTM_IFANNOUNCE: case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *) rtm; ifan = (struct if_announcemsghdr *) rtm;
if (ifan->ifan_index != drv->ifindex)
break;
os_strlcpy(event.interface_status.ifname, drv->ifname, os_strlcpy(event.interface_status.ifname, drv->ifname,
sizeof(event.interface_status.ifname)); sizeof(event.interface_status.ifname));
switch (ifan->ifan_what) { switch (ifan->ifan_what) {
@ -1232,8 +1234,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
break; break;
case RTM_IEEE80211: case RTM_IEEE80211:
ifan = (struct if_announcemsghdr *) rtm; ifan = (struct if_announcemsghdr *) rtm;
if (ifan->ifan_index != drv->ifindex)
break;
switch (ifan->ifan_what) { switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC: case RTM_IEEE80211_REASSOC:
@ -1281,9 +1281,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
} }
break; break;
case RTM_IFINFO: case RTM_IFINFO:
ifm = (struct if_msghdr *) rtm;
if (ifm->ifm_index != drv->ifindex)
break;
if ((rtm->rtm_flags & RTF_UP) == 0) { if ((rtm->rtm_flags & RTF_UP) == 0) {
os_strlcpy(event.interface_status.ifname, drv->ifname, os_strlcpy(event.interface_status.ifname, drv->ifname,
sizeof(event.interface_status.ifname)); sizeof(event.interface_status.ifname));
@ -1477,7 +1474,7 @@ get80211opmode(struct bsd_driver_data *drv)
(void) memset(&ifmr, 0, sizeof(ifmr)); (void) memset(&ifmr, 0, sizeof(ifmr));
(void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); (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_IEEE80211_ADHOC) {
if (ifmr.ifm_current & IFM_FLAG0) if (ifmr.ifm_current & IFM_FLAG0)
return IEEE80211_M_AHDEMO; return IEEE80211_M_AHDEMO;
@ -1497,7 +1494,7 @@ get80211opmode(struct bsd_driver_data *drv)
} }
static void * 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) \ #define GETPARAM(drv, param, v) \
(((v) = get80211param(drv, param)) != -1) (((v) = get80211param(drv, param)) != -1)
@ -1507,14 +1504,6 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (drv == NULL) if (drv == NULL)
return 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. * NB: We require the interface name be mappable to an index.
* This implies we do not support having wpa_supplicant * This implies we do not support having wpa_supplicant
@ -1525,25 +1514,17 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (drv->ifindex == 0) { if (drv->ifindex == 0) {
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
__func__, ifname); __func__, ifname);
goto fail1; goto fail;
} }
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0) drv->ctx = ctx;
goto fail1; drv->global = priv;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
/* Down interface during setup. */ /* Down interface during setup. */
if (bsd_ctrl_iface(drv, 0) < 0) if (bsd_ctrl_iface(drv, 0) < 0)
goto fail; 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)) { if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
__func__, strerror(errno)); __func__, strerror(errno));
@ -1564,12 +1545,10 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
goto fail; goto fail;
drv->opmode = get80211opmode(drv); drv->opmode = get80211opmode(drv);
dl_list_add(&drv->global->ifaces, &drv->list);
return drv; return drv;
fail: fail:
close(drv->sock);
fail1:
os_free(drv->event_buf);
os_free(drv); os_free(drv);
return NULL; return NULL;
#undef GETPARAM #undef GETPARAM
@ -1581,21 +1560,19 @@ wpa_driver_bsd_deinit(void *priv)
struct bsd_driver_data *drv = priv; struct bsd_driver_data *drv = priv;
wpa_driver_bsd_set_wpa(drv, 0); wpa_driver_bsd_set_wpa(drv, 0);
eloop_unregister_read_sock(drv->route);
/* NB: mark interface down */ /* NB: mark interface down */
bsd_ctrl_iface(drv, 0); bsd_ctrl_iface(drv, 0);
wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy); wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0) if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state", wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
__func__); __func__);
if (drv->sock_xmit != NULL) if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit); l2_packet_deinit(drv->sock_xmit);
(void) close(drv->route); /* ioctl socket */ dl_list_del(&drv->list);
(void) close(drv->sock); /* event socket */
os_free(drv->event_buf);
os_free(drv); os_free(drv);
} }
@ -1609,10 +1586,73 @@ wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
} }
#endif /* HOSTAPD */ #endif /* HOSTAPD */
static void *
bsd_global_init(void)
{
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 = { const struct wpa_driver_ops wpa_driver_bsd_ops = {
.name = "bsd", .name = "bsd",
.desc = "BSD 802.11 support", .desc = "BSD 802.11 support",
.global_init = bsd_global_init,
.global_deinit = bsd_global_deinit,
#ifdef HOSTAPD #ifdef HOSTAPD
.hapd_init = bsd_init, .hapd_init = bsd_init,
.hapd_deinit = bsd_deinit, .hapd_deinit = bsd_deinit,
@ -1625,7 +1665,7 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.sta_set_flags = bsd_set_sta_authorized, .sta_set_flags = bsd_set_sta_authorized,
.commit = bsd_commit, .commit = bsd_commit,
#else /* HOSTAPD */ #else /* HOSTAPD */
.init = wpa_driver_bsd_init, .init2 = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit, .deinit = wpa_driver_bsd_deinit,
.get_bssid = wpa_driver_bsd_get_bssid, .get_bssid = wpa_driver_bsd_get_bssid,
.get_ssid = wpa_driver_bsd_get_ssid, .get_ssid = wpa_driver_bsd_get_ssid,