[PATCH v2 6/6] nl80211: Use global netlink objects.
greearb at candelatech.com
greearb
Thu Oct 20 13:21:24 PDT 2011
From: Ben Greear <greearb at candelatech.com>
Netlink sockets can be shared among all driver instances,
saving lots of sockets, spurious log messages, memory,
and CPU usage when using multiple interfaces in a single
process.
Signed-off-by: Ben Greear <greearb at candelatech.com>
---
:100644 100644 971db78... 271cca5... M src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.c | 509 ++++++++++++++++++++++--------------------
1 files changed, 263 insertions(+), 246 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 971db78..271cca5 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -104,8 +104,10 @@ static void nl80211_handle_destroy(struct nl_handle *handle)
#define IF_OPER_UP 6
#endif
-#define DRVNL nl80211
-#define DRVPREQ nl_handle_preq
+#define DRVNL global->nl80211
+#define DRVPREQ global->nl_handle_preq
+static void nl80211_global_deinit(void *priv);
+static void wpa_driver_nl80211_deinit(void *priv);
/* TODO: Move this somewhere central and put struct_ids
* in all structs that are passed around as void* so that
@@ -156,7 +158,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;
@@ -170,18 +171,10 @@ struct wpa_driver_nl80211_data {
int scan_complete_events;
- struct nl_handle *nl_handle;
- struct nl_handle *nl_handle_event;
- struct nl_handle *nl_handle_preq;
- struct nl_cache *nl_cache;
- struct nl_cache *nl_cache_event;
- struct nl_cache *nl_cache_preq;
- struct nl_cb *nl_cb;
- struct genl_family *nl80211;
-
u8 auth_bssid[ETH_ALEN];
u8 bssid[ETH_ALEN];
int associated;
+ int probe_req_report; /* registered for this report or not? */
u8 ssid[32];
size_t ssid_len;
enum nl80211_iftype nlmode;
@@ -314,7 +307,7 @@ static int no_seq_check(struct nl_msg *msg, void *arg)
}
-static int send_and_recv(struct wpa_driver_nl80211_data *drv,
+static int send_and_recv(struct nl80211_global *global,
struct nl_handle *nl_handle, struct nl_msg *msg,
int (*valid_handler)(struct nl_msg *, void *),
void *valid_data)
@@ -322,7 +315,7 @@ static int send_and_recv(struct wpa_driver_nl80211_data *drv,
struct nl_cb *cb;
int err = -ENOMEM;
- cb = nl_cb_clone(drv->nl_cb);
+ cb = nl_cb_clone(global->nl_cb);
if (!cb)
goto out;
@@ -349,12 +342,21 @@ static int send_and_recv(struct wpa_driver_nl80211_data *drv,
}
+static int send_and_recv_msgs_g(struct nl80211_global *global,
+ struct nl_msg *msg,
+ int (*valid_handler)(struct nl_msg *, void *),
+ void *valid_data)
+{
+ return send_and_recv(global, global->nl_handle, msg, valid_handler,
+ valid_data);
+}
+
static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
struct nl_msg *msg,
int (*valid_handler)(struct nl_msg *, void *),
void *valid_data)
{
- return send_and_recv(drv, drv->nl_handle, msg, valid_handler,
+ return send_and_recv(drv->global, drv->global->nl_handle, msg, valid_handler,
valid_data);
}
@@ -396,7 +398,7 @@ static int family_handler(struct nl_msg *msg, void *arg)
}
-static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv,
+static int nl_get_multicast_id(struct nl80211_global *global,
const char *family, const char *group)
{
struct nl_msg *msg;
@@ -406,11 +408,11 @@ static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv,
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
- genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"),
+ genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl_handle, "nlctrl"),
0, 0, CTRL_CMD_GETFAMILY, 0);
NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
- ret = send_and_recv_msgs(drv, msg, family_handler, &res);
+ ret = send_and_recv_msgs_g(global, msg, family_handler, &res);
msg = NULL;
if (ret == 0)
ret = res.id;
@@ -533,13 +535,15 @@ 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;
int attrlen, rta_len;
struct rtattr *attr;
u32 brid = 0;
+ struct wpa_driver_nl80211_data *drv;
+
+ drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
- if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len) &&
- !have_ifidx(drv, ifi->ifi_index)) {
+ if (!drv) {
wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign "
"ifindex %d", ifi->ifi_index);
return;
@@ -581,7 +585,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;
@@ -615,10 +619,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;
int attrlen, rta_len;
struct rtattr *attr;
u32 brid = 0;
+ struct wpa_driver_nl80211_data *drv;
+
+ 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;
@@ -1550,25 +1563,11 @@ static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
}
-static int process_event(struct nl_msg *msg, void *arg)
+static void do_process_event(struct nl_msg *msg,
+ struct wpa_driver_nl80211_data *drv,
+ struct genlmsghdr *gnlh,
+ struct nlattr *tb[])
{
- struct wpa_driver_nl80211_data *drv = arg;
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *tb[NL80211_ATTR_MAX + 1];
-
- nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- if (tb[NL80211_ATTR_IFINDEX]) {
- int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
- if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {
- wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)"
- " for foreign interface (ifindex %d)",
- gnlh->cmd, ifindex);
- return NL_SKIP;
- }
- }
-
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
(gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) {
@@ -1677,7 +1676,29 @@ static int process_event(struct nl_msg *msg, void *arg)
"(cmd=%d)", gnlh->cmd);
break;
}
+}
+
+static int process_event(struct nl_msg *msg, void *arg)
+{
+ struct nl80211_global *global = arg;
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct wpa_driver_nl80211_data *drv = NULL;
+ int ifindex = -1;
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (tb[NL80211_ATTR_IFINDEX]) {
+ ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
+ }
+ dl_list_for_each(drv, &global->interfaces,
+ struct wpa_driver_nl80211_data, list) {
+ if ((ifindex == -1) ||
+ (ifindex == drv->ifindex || have_ifidx(drv, ifindex))) {
+ do_process_event(msg, drv, gnlh, tb);
+ }
+ }
return NL_SKIP;
}
@@ -1686,15 +1707,15 @@ static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
void *handle)
{
struct nl_cb *cb;
- struct wpa_driver_nl80211_data *drv = eloop_ctx;
+ struct nl80211_global *global = eloop_ctx;
- wpa_printf(MSG_DEBUG, "nl80211: Event message available");
+ wpa_msg(NULL, MSG_DEBUG, "nl80211: Event message available");
- cb = nl_cb_clone(drv->nl_cb);
+ cb = nl_cb_clone(global->nl_cb);
if (!cb)
return;
nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, global);
nl_recvmsgs(handle, cb);
nl_cb_put(cb);
}
@@ -1985,130 +2006,6 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
}
-static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
-{
- int ret;
-
- /* Initialize generic netlink and nl80211 */
-
- drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (drv->nl_cb == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
- "callbacks");
- goto err1;
- }
-
- drv->nl_handle = nl80211_handle_alloc(drv->nl_cb);
- if (drv->nl_handle == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
- "callbacks");
- goto err2;
- }
-
- drv->nl_handle_event = nl80211_handle_alloc(drv->nl_cb);
- if (drv->nl_handle_event == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
- "callbacks (event)");
- goto err2b;
- }
-
- if (genl_connect(drv->nl_handle)) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
- "netlink");
- goto err3;
- }
-
- if (genl_connect(drv->nl_handle_event)) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
- "netlink (event)");
- goto err3;
- }
-
-#ifdef CONFIG_LIBNL20
- if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
- "netlink cache");
- goto err3;
- }
- if (genl_ctrl_alloc_cache(drv->nl_handle_event, &drv->nl_cache_event) <
- 0) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
- "netlink cache (event)");
- goto err3b;
- }
-#else /* CONFIG_LIBNL20 */
- drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle);
- if (drv->nl_cache == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
- "netlink cache");
- goto err3;
- }
- drv->nl_cache_event = genl_ctrl_alloc_cache(drv->nl_handle_event);
- if (drv->nl_cache_event == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
- "netlink cache (event)");
- goto err3b;
- }
-#endif /* CONFIG_LIBNL20 */
-
- drv->DRVNL = genl_ctrl_search_by_name(drv->nl_cache, "nl80211");
- if (drv->DRVNL == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
- "found");
- goto err4;
- }
-
- ret = nl_get_multicast_id(drv, "nl80211", "scan");
- if (ret >= 0)
- ret = nl_socket_add_membership(drv->nl_handle_event, ret);
- if (ret < 0) {
- wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
- "membership for scan events: %d (%s)",
- ret, strerror(-ret));
- goto err4;
- }
-
- ret = nl_get_multicast_id(drv, "nl80211", "mlme");
- if (ret >= 0)
- ret = nl_socket_add_membership(drv->nl_handle_event, ret);
- if (ret < 0) {
- wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
- "membership for mlme events: %d (%s)",
- ret, strerror(-ret));
- goto err4;
- }
-
- ret = nl_get_multicast_id(drv, "nl80211", "regulatory");
- if (ret >= 0)
- ret = nl_socket_add_membership(drv->nl_handle_event, ret);
- if (ret < 0) {
- wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
- "membership for regulatory events: %d (%s)",
- ret, strerror(-ret));
- /* Continue without regulatory events */
- }
-
- eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event),
- wpa_driver_nl80211_event_receive, drv,
- drv->nl_handle_event);
-
- return 0;
-
-err4:
- nl_cache_free(drv->nl_cache_event);
-err3b:
- nl_cache_free(drv->nl_cache);
-err3:
- nl80211_handle_destroy(drv->nl_handle_event);
-err2b:
- nl80211_handle_destroy(drv->nl_handle);
-err2:
- nl_cb_put(drv->nl_cb);
-err1:
- return -1;
-}
-
-
static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
{
wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
@@ -2187,7 +2084,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;
@@ -2206,11 +2102,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
drv->ioctl_sock = -1;
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
- if (wpa_driver_nl80211_init_nl(drv)) {
- os_free(drv);
- return NULL;
- }
-
nl80211_get_phy_name(drv);
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
@@ -2219,18 +2110,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;
@@ -2258,18 +2137,7 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
return bss;
failed:
- rfkill_deinit(drv->rfkill);
- netlink_deinit(drv->netlink);
- if (drv->ioctl_sock >= 0)
- close(drv->ioctl_sock);
-
- genl_family_put(drv->DRVNL);
- nl_cache_free(drv->nl_cache);
- nl80211_handle_destroy(drv->nl_handle);
- nl_cb_put(drv->nl_cb);
- eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event));
-
- os_free(drv);
+ wpa_driver_nl80211_deinit(bss);
return NULL;
}
@@ -2292,7 +2160,7 @@ static int nl80211_register_frame(struct wpa_driver_nl80211_data *drv,
NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
- ret = send_and_recv(drv, nl_handle, msg, NULL, NULL);
+ ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
msg = NULL;
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
@@ -2313,7 +2181,7 @@ static int nl80211_register_action_frame(struct wpa_driver_nl80211_data *drv,
const u8 *match, size_t match_len)
{
u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
- return nl80211_register_frame(drv, drv->nl_handle_event,
+ return nl80211_register_frame(drv, drv->global->nl_handle_event,
type, match, match_len);
}
@@ -2409,7 +2277,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 */
@@ -2473,8 +2341,9 @@ static void wpa_driver_nl80211_deinit(void *priv)
l2_packet_deinit(drv->l2);
#endif /* CONFIG_AP */
- if (drv->DRVPREQ)
+ if (drv->probe_req_report)
wpa_driver_nl80211_probe_req_report(bss, 0);
+
if (bss->added_if_into_bridge) {
if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname)
< 0)
@@ -2515,9 +2384,9 @@ 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);
- rfkill_deinit(drv->rfkill);
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0, IF_OPER_UP);
+ if (drv->rfkill)
+ rfkill_deinit(drv->rfkill);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
@@ -2527,14 +2396,6 @@ static void wpa_driver_nl80211_deinit(void *priv)
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);
- eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event));
- genl_family_put(drv->DRVNL);
- nl_cache_free(drv->nl_cache);
- nl_cache_free(drv->nl_cache_event);
- nl80211_handle_destroy(drv->nl_handle);
- nl80211_handle_destroy(drv->nl_handle_event);
- nl_cb_put(drv->nl_cb);
-
os_free(drv->filter_ssids);
if (drv->global)
@@ -5828,7 +5689,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);
}
@@ -6456,7 +6317,9 @@ static void *i802_init(struct hostapd_data *hapd,
int ifindex, br_ifindex;
int br_added = 0;
- bss = wpa_driver_nl80211_init(hapd, params->ifname, NULL);
+ struct nl80211_global *global = nl80211_global_init();
+
+ bss = wpa_driver_nl80211_init(hapd, params->ifname, global);
if (bss == NULL)
return NULL;
@@ -6529,19 +6392,7 @@ static void *i802_init(struct hostapd_data *hapd,
return bss;
failed:
- nl80211_remove_monitor_interface(drv);
- rfkill_deinit(drv->rfkill);
- netlink_deinit(drv->netlink);
- if (drv->ioctl_sock >= 0)
- close(drv->ioctl_sock);
-
- genl_family_put(drv->DRVNL);
- nl_cache_free(drv->nl_cache);
- nl80211_handle_destroy(drv->nl_handle);
- nl_cb_put(drv->nl_cb);
- eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event));
-
- os_free(drv);
+ wpa_driver_nl80211_deinit(bss);
return NULL;
}
@@ -6969,6 +6820,17 @@ nla_put_failure:
return -1;
}
+static void nl80211_global_deinit_handle_preq(struct nl80211_global *global) {
+ if (global->nl_handle_preq)
+ eloop_unregister_read_sock(
+ nl_socket_get_fd(global->nl_handle_preq));
+ if (global->nl_cache_preq)
+ nl_cache_free(global->nl_cache_preq);
+ if (global->nl_handle_preq)
+ nl80211_handle_destroy(global->nl_handle_preq);
+ global->nl_handle_preq = NULL;
+ global->nl_cache_preq = NULL;
+}
static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
{
@@ -6976,24 +6838,26 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
struct wpa_driver_nl80211_data *drv = bss->drv;
if (!report) {
- if (drv->DRVPREQ) {
- eloop_unregister_read_sock(
- nl_socket_get_fd(drv->DRVPREQ));
- nl_cache_free(drv->nl_cache_preq);
- nl80211_handle_destroy(drv->DRVPREQ);
- drv->DRVPREQ = NULL;
+ if (!drv->probe_req_report)
+ return 0;
+ if (--drv->global->nl_handle_preq_refcnt <= 0) {
+ if (drv->global->nl_handle_preq_refcnt < 0) {
+ wpa_msg(NULL, MSG_ERROR,
+ "ERROR: preq_refcnt is negative: %i in driver_nl80211.c.\n",
+ drv->global->nl_handle_preq_refcnt);
+ drv->global->nl_handle_preq_refcnt = 0;
+ }
+ nl80211_global_deinit_handle_preq(drv->global);
}
+ drv->probe_req_report = 0;
return 0;
}
- if (drv->DRVPREQ) {
- wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
- "already on!");
+ if (drv->probe_req_report)
return 0;
- }
- { /* get ready for global pre-req */
- drv->DRVPREQ = nl80211_handle_alloc(drv->nl_cb);
+ if (! drv->DRVPREQ) {
+ drv->DRVPREQ = nl80211_handle_alloc(drv->global->nl_cb);
if (drv->DRVPREQ == NULL) {
wpa_printf(MSG_ERROR, "nl80211: Failed to allocate "
"netlink callbacks (preq)");
@@ -7009,14 +6873,14 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
#ifdef CONFIG_LIBNL20
if (genl_ctrl_alloc_cache(drv->DRVPREQ,
- &drv->nl_cache_preq) < 0) {
+ &drv->global->nl_cache_preq) < 0) {
wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
"netlink cache (preq)");
goto out_err2;
}
#else /* CONFIG_LIBNL20 */
- drv->nl_cache_preq = genl_ctrl_alloc_cache(drv->DRVPREQ);
- if (drv->nl_cache_preq == NULL) {
+ drv->global->nl_cache_preq = genl_ctrl_alloc_cache(drv->DRVPREQ);
+ if (drv->global->nl_cache_preq == NULL) {
wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
"netlink cache (preq)");
goto out_err2;
@@ -7031,14 +6895,17 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
}
eloop_register_read_sock(nl_socket_get_fd(drv->DRVPREQ),
- wpa_driver_nl80211_event_receive, drv,
+ wpa_driver_nl80211_event_receive, drv->global,
drv->DRVPREQ);
}
+ drv->global->nl_handle_preq_refcnt++;
+ drv->probe_req_report = 1;
return 0;
out_err3:
- nl_cache_free(drv->nl_cache_preq);
+ nl_cache_free(drv->global->nl_cache_preq);
+ drv->global->nl_cache_preq = NULL;
out_err2:
nl80211_handle_destroy(drv->DRVPREQ);
drv->DRVPREQ = NULL;
@@ -7263,13 +7130,141 @@ static int nl80211_set_param(void *priv, const char *param)
static void * nl80211_global_init(void)
{
struct nl80211_global *global;
+ struct netlink_config *cfg;
+ int ret;
+
+ /* already initailized? */
+ if (global_ptr)
+ return global_ptr;
+
global = os_zalloc(sizeof(*global));
if (global == NULL)
return NULL;
global->struct_id = HAP_DRV_NL80211_GLOBAL;
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;
+ }
+
+ global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (global->nl_cb == NULL) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate netlink "
+ "callbacks");
+ goto err;
+ }
+
+ global->nl_handle = nl80211_handle_alloc(global->nl_cb);
+ if (global->nl_handle == NULL) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate netlink "
+ "callbacks (nl_handle)");
+ goto err;
+ }
+
+ global->nl_handle_event = nl80211_handle_alloc(global->nl_cb);
+ if (global->nl_handle_event == NULL) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate netlink "
+ "callbacks (event)");
+ goto err;
+ }
+
+ if (genl_connect(global->nl_handle)) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to connect to generic "
+ "netlink");
+ goto err;
+ }
+
+ if (genl_connect(global->nl_handle_event)) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to connect to generic "
+ "netlink (event)");
+ goto err;
+ }
+
+#ifdef CONFIG_LIBNL20
+ if (genl_ctrl_alloc_cache(global->nl_handle, &global->nl_cache) < 0) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate generic "
+ "netlink cache");
+ goto err;
+ }
+ if (genl_ctrl_alloc_cache(global->nl_handle_event, &global->nl_cache_event) <
+ 0) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate generic "
+ "netlink cache (event)");
+ goto err;
+ }
+#else /* CONFIG_LIBNL20 */
+ global->nl_cache = genl_ctrl_alloc_cache(global->nl_handle);
+ if (global->nl_cache == NULL) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate generic "
+ "netlink cache");
+ goto err;
+ }
+ global->nl_cache_event = genl_ctrl_alloc_cache(global->nl_handle_event);
+ if (global->nl_cache_event == NULL) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Failed to allocate generic "
+ "netlink cache (event)");
+ goto err;
+ }
+#endif /* CONFIG_LIBNL20 */
+
+ global->nl80211 = genl_ctrl_search_by_name(global->nl_cache, "nl80211");
+ if (global->nl80211 == NULL) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
+ "found");
+ goto err;
+ }
+
+ ret = nl_get_multicast_id(global, "nl80211", "scan");
+ if (ret >= 0)
+ ret = nl_socket_add_membership(global->nl_handle_event, ret);
+ if (ret < 0) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Could not add multicast "
+ "membership for scan events: %d (%s)",
+ ret, strerror(-ret));
+ goto err;
+ }
+
+ ret = nl_get_multicast_id(global, "nl80211", "mlme");
+ if (ret >= 0)
+ ret = nl_socket_add_membership(global->nl_handle_event, ret);
+ if (ret < 0) {
+ wpa_msg(NULL, MSG_ERROR, "nl80211: Could not add multicast "
+ "membership for mlme events: %d (%s)",
+ ret, strerror(-ret));
+ goto err;
+ }
+
+ ret = nl_get_multicast_id(global, "nl80211", "regulatory");
+ if (ret >= 0)
+ ret = nl_socket_add_membership(global->nl_handle_event, ret);
+ if (ret < 0) {
+ wpa_msg(NULL, MSG_DEBUG, "nl80211: Could not add multicast "
+ "membership for regulatory events: %d (%s)",
+ ret, strerror(-ret));
+ /* Continue without regulatory events */
+ }
+
+ eloop_register_read_sock(nl_socket_get_fd(global->nl_handle_event),
+ wpa_driver_nl80211_event_receive, global,
+ global->nl_handle_event);
+
+ global_ptr = global;
+
return global;
+
+err:
+ nl80211_global_deinit(global);
+ return NULL;
}
@@ -7283,6 +7278,28 @@ static void nl80211_global_deinit(void *priv)
"nl80211_global_deinit",
dl_list_len(&global->interfaces));
}
+
+ nl80211_global_deinit_handle_preq(global);
+
+ if (global->netlink)
+ netlink_deinit(global->netlink);
+
+ if (global->nl_cache_event)
+ nl_cache_free(global->nl_cache_event);
+ if (global->nl_cache)
+ nl_cache_free(global->nl_cache);
+ if (global->nl_handle_event)
+ nl80211_handle_destroy(global->nl_handle_event);
+ if (global->nl_handle)
+ nl80211_handle_destroy(global->nl_handle);
+ if (global->nl_cb)
+ nl_cb_put(global->nl_cb);
+ if (global->nl80211)
+ genl_family_put(global->nl80211);
+
+ if (global == global_ptr)
+ global_ptr = NULL;
+
os_free(global);
}
--
1.7.3.4
More information about the Hostap
mailing list