Browse Source

nl80211: Replace hostapd WEXT events with nl80211 events

This shares the nl80211 event processing with wpa_supplicant and removes
the old WEXT code from driver_nl80211.c.
Jouni Malinen 16 years ago
parent
commit
5b7b85f669
1 changed files with 46 additions and 266 deletions
  1. 46 266
      src/drivers/driver_nl80211.c

+ 46 - 266
src/drivers/driver_nl80211.c

@@ -119,7 +119,6 @@ struct wpa_driver_nl80211_data {
 #ifdef HOSTAPD
 #ifdef HOSTAPD
 	struct hostapd_data *hapd;
 	struct hostapd_data *hapd;
 
 
-	int wext_sock; /* socket for wireless events */
 	int eapol_sock; /* socket for EAPOL frames */
 	int eapol_sock; /* socket for EAPOL frames */
 	int monitor_sock; /* socket for monitor */
 	int monitor_sock; /* socket for monitor */
 	int monitor_ifidx;
 	int monitor_ifidx;
@@ -128,7 +127,6 @@ struct wpa_driver_nl80211_data {
 	int *if_indices;
 	int *if_indices;
 	int num_if_indices;
 	int num_if_indices;
 
 
-	int we_version;
 	int beacon_int;
 	int beacon_int;
 	struct i802_bss bss;
 	struct i802_bss bss;
 	unsigned int ht_40mhz_scan:1;
 	unsigned int ht_40mhz_scan:1;
@@ -154,10 +152,6 @@ static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
 #endif /* CONFIG_AP */
 #endif /* CONFIG_AP */
 
 
 
 
-#ifdef HOSTAPD
-#define wpa_supplicant_event(c, e, d) do { } while (0)
-#endif /* HOSTAPD */
-
 /* nl80211 code */
 /* nl80211 code */
 static int ack_handler(struct nl_msg *msg, void *arg)
 static int ack_handler(struct nl_msg *msg, void *arg)
 {
 {
@@ -181,6 +175,13 @@ static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
 	return NL_SKIP;
 	return NL_SKIP;
 }
 }
 
 
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+	return NL_OK;
+}
+
+
 static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
 static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
 			      struct nl_msg *msg,
 			      struct nl_msg *msg,
 			      int (*valid_handler)(struct nl_msg *, void *),
 			      int (*valid_handler)(struct nl_msg *, void *),
@@ -382,6 +383,7 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
 }
 }
 
 
 
 
+#ifndef HOSTAPD
 static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
 static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
 					  void *ctx, char *buf, size_t len,
 					  void *ctx, char *buf, size_t len,
 					  int del)
 					  int del)
@@ -621,12 +623,6 @@ try_again:
 }
 }
 
 
 
 
-static int no_seq_check(struct nl_msg *msg, void *arg)
-{
-	return NL_OK;
-}
-
-
 static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
 static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
 			    const u8 *frame, size_t len)
 			    const u8 *frame, size_t len)
 {
 {
@@ -729,10 +725,17 @@ static void mlme_event(struct wpa_driver_nl80211_data *drv,
 	}
 	}
 }
 }
 
 
+#endif /* HOSTAPD */
+
 
 
 static void mlme_event_michael_mic_failure(struct wpa_driver_nl80211_data *drv,
 static void mlme_event_michael_mic_failure(struct wpa_driver_nl80211_data *drv,
 					   struct nlattr *tb[])
 					   struct nlattr *tb[])
 {
 {
+#ifdef HOSTAPD
+	if (tb[NL80211_ATTR_MAC])
+		hostapd_michael_mic_failure(drv->hapd,
+					    nla_data(tb[NL80211_ATTR_MAC]));
+#else /* HOSTAPD */
 	union wpa_event_data data;
 	union wpa_event_data data;
 
 
 	wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
 	wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
@@ -762,6 +765,7 @@ static void mlme_event_michael_mic_failure(struct wpa_driver_nl80211_data *drv,
 	}
 	}
 
 
 	wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
 	wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
+#endif /* HOSTAPD */
 }
 }
 
 
 
 
@@ -785,6 +789,7 @@ static int process_event(struct nl_msg *msg, void *arg)
 	}
 	}
 
 
 	switch (gnlh->cmd) {
 	switch (gnlh->cmd) {
+#ifndef HOSTAPD
 	case NL80211_CMD_NEW_SCAN_RESULTS:
 	case NL80211_CMD_NEW_SCAN_RESULTS:
 		wpa_printf(MSG_DEBUG, "nl80211: New scan results available");
 		wpa_printf(MSG_DEBUG, "nl80211: New scan results available");
 		drv->scan_complete_events = 1;
 		drv->scan_complete_events = 1;
@@ -808,6 +813,7 @@ static int process_event(struct nl_msg *msg, void *arg)
 	case NL80211_CMD_DISASSOCIATE:
 	case NL80211_CMD_DISASSOCIATE:
 		mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME]);
 		mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME]);
 		break;
 		break;
+#endif /* HOSTAPD */
 	case NL80211_CMD_MICHAEL_MIC_FAILURE:
 	case NL80211_CMD_MICHAEL_MIC_FAILURE:
 		mlme_event_michael_mic_failure(drv, tb);
 		mlme_event_michael_mic_failure(drv, tb);
 		break;
 		break;
@@ -1116,8 +1122,10 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname)
 		goto err6;
 		goto err6;
 	}
 	}
 
 
+#ifndef HOSTAPD
 	eloop_register_read_sock(s, wpa_driver_nl80211_event_receive_link, drv,
 	eloop_register_read_sock(s, wpa_driver_nl80211_event_receive_link, drv,
 				 ctx);
 				 ctx);
+#endif /* HOSTAPD */
 	drv->link_event_sock = s;
 	drv->link_event_sock = s;
 
 
 	if (wpa_driver_nl80211_finish_drv_init(drv))
 	if (wpa_driver_nl80211_finish_drv_init(drv))
@@ -1234,7 +1242,9 @@ static void wpa_driver_nl80211_deinit(void *priv)
 static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 {
 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
+#ifndef HOSTAPD
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
+#endif /* HOSTAPD */
 }
 }
 
 
 
 
@@ -4757,6 +4767,7 @@ static int i802_ht_scan(struct wpa_driver_nl80211_data *drv)
 static int i802_init_sockets(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
 static int i802_init_sockets(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
 {
 {
 	struct ifreq ifr;
 	struct ifreq ifr;
+	int ret;
 
 
 	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
 	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
 	if (drv->ioctl_sock < 0) {
 	if (drv->ioctl_sock < 0) {
@@ -4820,6 +4831,28 @@ static int i802_init_sockets(struct wpa_driver_nl80211_data *drv, const u8 *bssi
 		return -1;
 		return -1;
 	}
 	}
 
 
+	ret = nl_get_multicast_id(drv, "nl80211", "scan");
+	if (ret >= 0)
+		ret = nl_socket_add_membership(drv->nl_handle, ret);
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
+			   "membership for scan events: %d (%s)",
+			   ret, strerror(-ret));
+	}
+
+	ret = nl_get_multicast_id(drv, "nl80211", "mlme");
+	if (ret >= 0)
+		ret = nl_socket_add_membership(drv->nl_handle, ret);
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
+			   "membership for mlme events: %d (%s)",
+			   ret, strerror(-ret));
+	}
+
+	eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle),
+				 wpa_driver_nl80211_event_receive, drv,
+				 drv->hapd);
+
 #ifdef CONFIG_IEEE80211N
 #ifdef CONFIG_IEEE80211N
 	if (drv->ht_40mhz_scan) {
 	if (drv->ht_40mhz_scan) {
 		if (nl80211_set_mode(drv, drv->ifname, NL80211_IFTYPE_STATION)
 		if (nl80211_set_mode(drv, drv->ifname, NL80211_IFTYPE_STATION)
@@ -4899,255 +4932,6 @@ static int i802_sta_clear_stats(void *priv, const u8 *addr)
 }
 }
 
 
 
 
-static void
-hostapd_wireless_event_wireless_custom(struct wpa_driver_nl80211_data *drv,
-				       char *custom)
-{
-	wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
-
-	if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
-		char *pos;
-		u8 addr[ETH_ALEN];
-		pos = strstr(custom, "addr=");
-		if (pos == NULL) {
-			wpa_printf(MSG_DEBUG,
-				   "MLME-MICHAELMICFAILURE.indication "
-				   "without sender address ignored");
-			return;
-		}
-		pos += 5;
-		if (hwaddr_aton(pos, addr) == 0) {
-			hostapd_michael_mic_failure(drv->hapd, addr);
-		} else {
-			wpa_printf(MSG_DEBUG,
-				   "MLME-MICHAELMICFAILURE.indication "
-				   "with invalid MAC address");
-		}
-	}
-}
-
-
-static void hostapd_wireless_event_wireless(struct wpa_driver_nl80211_data *drv,
-					    char *data, int len)
-{
-	struct iw_event iwe_buf, *iwe = &iwe_buf;
-	char *pos, *end, *custom, *buf;
-
-	pos = data;
-	end = data + len;
-
-	while (pos + IW_EV_LCP_LEN <= end) {
-		/* Event data may be unaligned, so make a local, aligned copy
-		 * before processing. */
-		memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
-		wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
-			   iwe->cmd, iwe->len);
-		if (iwe->len <= IW_EV_LCP_LEN)
-			return;
-
-		custom = pos + IW_EV_POINT_LEN;
-		if (drv->we_version > 18 &&
-		    (iwe->cmd == IWEVMICHAELMICFAILURE ||
-		     iwe->cmd == IWEVCUSTOM)) {
-			/* WE-19 removed the pointer from struct iw_point */
-			char *dpos = (char *) &iwe_buf.u.data.length;
-			int dlen = dpos - (char *) &iwe_buf;
-			memcpy(dpos, pos + IW_EV_LCP_LEN,
-			       sizeof(struct iw_event) - dlen);
-		} else {
-			memcpy(&iwe_buf, pos, sizeof(struct iw_event));
-			custom += IW_EV_POINT_OFF;
-		}
-
-		switch (iwe->cmd) {
-		case IWEVCUSTOM:
-			if (custom + iwe->u.data.length > end)
-				return;
-			buf = malloc(iwe->u.data.length + 1);
-			if (buf == NULL)
-				return;
-			memcpy(buf, custom, iwe->u.data.length);
-			buf[iwe->u.data.length] = '\0';
-			hostapd_wireless_event_wireless_custom(drv, buf);
-			free(buf);
-			break;
-		}
-
-		pos += iwe->len;
-	}
-}
-
-
-static void hostapd_wireless_event_rtm_newlink(struct wpa_driver_nl80211_data *drv,
-					       struct nlmsghdr *h, int len)
-{
-	struct ifinfomsg *ifi;
-	int attrlen, _nlmsg_len, rta_len;
-	struct rtattr *attr;
-
-	if (len < (int) sizeof(*ifi))
-		return;
-
-	ifi = NLMSG_DATA(h);
-
-	/* TODO: use ifi->ifi_index to filter out wireless events from other
-	 * interfaces */
-
-	_nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-	attrlen = h->nlmsg_len - _nlmsg_len;
-	if (attrlen < 0)
-		return;
-
-	attr = (struct rtattr *) (((char *) ifi) + _nlmsg_len);
-
-	rta_len = RTA_ALIGN(sizeof(struct rtattr));
-	while (RTA_OK(attr, attrlen)) {
-		if (attr->rta_type == IFLA_WIRELESS) {
-			hostapd_wireless_event_wireless(
-				drv, ((char *) attr) + rta_len,
-				attr->rta_len - rta_len);
-		}
-		attr = RTA_NEXT(attr, attrlen);
-	}
-}
-
-
-static void hostapd_wireless_event_receive(int sock, void *eloop_ctx,
-					   void *sock_ctx)
-{
-	char buf[256];
-	int left;
-	struct sockaddr_nl from;
-	socklen_t fromlen;
-	struct nlmsghdr *h;
-	struct wpa_driver_nl80211_data *drv = eloop_ctx;
-
-	fromlen = sizeof(from);
-	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
-			(struct sockaddr *) &from, &fromlen);
-	if (left < 0) {
-		if (errno != EINTR && errno != EAGAIN)
-			perror("recvfrom(netlink)");
-		return;
-	}
-
-	h = (struct nlmsghdr *) buf;
-	while (left >= (int) sizeof(*h)) {
-		int len, plen;
-
-		len = h->nlmsg_len;
-		plen = len - sizeof(*h);
-		if (len > left || plen < 0) {
-			printf("Malformed netlink message: "
-			       "len=%d left=%d plen=%d\n",
-			       len, left, plen);
-			break;
-		}
-
-		switch (h->nlmsg_type) {
-		case RTM_NEWLINK:
-			hostapd_wireless_event_rtm_newlink(drv, h, plen);
-			break;
-		}
-
-		len = NLMSG_ALIGN(len);
-		left -= len;
-		h = (struct nlmsghdr *) ((char *) h + len);
-	}
-
-	if (left > 0) {
-		printf("%d extra bytes in the end of netlink message\n", left);
-	}
-}
-
-
-static int hostap_get_we_version(struct wpa_driver_nl80211_data *drv)
-{
-	struct iw_range *range;
-	struct iwreq iwr;
-	int minlen;
-	size_t buflen;
-
-	drv->we_version = 0;
-
-	/*
-	 * Use larger buffer than struct iw_range in order to allow the
-	 * structure to grow in the future.
-	 */
-	buflen = sizeof(struct iw_range) + 500;
-	range = os_zalloc(buflen);
-	if (range == NULL)
-		return -1;
-
-	memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.data.pointer = (caddr_t) range;
-	iwr.u.data.length = buflen;
-
-	minlen = ((char *) &range->enc_capa) - (char *) range +
-		sizeof(range->enc_capa);
-
-	if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
-		perror("ioctl[SIOCGIWRANGE]");
-		free(range);
-		return -1;
-	} else if (iwr.u.data.length >= minlen &&
-		   range->we_version_compiled >= 18) {
-		wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
-			   "WE(source)=%d enc_capa=0x%x",
-			   range->we_version_compiled,
-			   range->we_version_source,
-			   range->enc_capa);
-		drv->we_version = range->we_version_compiled;
-	}
-
-	free(range);
-	return 0;
-}
-
-
-static int i802_wireless_event_init(struct wpa_driver_nl80211_data *drv)
-{
-	int s;
-	struct sockaddr_nl local;
-
-	hostap_get_we_version(drv);
-
-	drv->wext_sock = -1;
-
-	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-	if (s < 0) {
-		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
-		return -1;
-	}
-
-	memset(&local, 0, sizeof(local));
-	local.nl_family = AF_NETLINK;
-	local.nl_groups = RTMGRP_LINK;
-	if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
-		perror("bind(netlink)");
-		close(s);
-		return -1;
-	}
-
-	eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
-				 NULL);
-	drv->wext_sock = s;
-
-	return 0;
-}
-
-
-static void i802_wireless_event_deinit(struct wpa_driver_nl80211_data *drv)
-{
-	if (drv->wext_sock < 0)
-		return;
-	eloop_unregister_read_sock(drv->wext_sock);
-	close(drv->wext_sock);
-}
-
-
 static int i802_sta_deauth(void *priv, const u8 *addr, int reason)
 static int i802_sta_deauth(void *priv, const u8 *addr, int reason)
 {
 {
 	struct wpa_driver_nl80211_data *drv = priv;
 	struct wpa_driver_nl80211_data *drv = priv;
@@ -5219,9 +5003,6 @@ static void *i802_init_bssid(struct hostapd_data *hapd, const u8 *bssid)
 	if (i802_init_sockets(drv, bssid))
 	if (i802_init_sockets(drv, bssid))
 		goto failed;
 		goto failed;
 
 
-	if (i802_wireless_event_init(drv))
-		goto failed;
-
 	return drv;
 	return drv;
 
 
 failed:
 failed:
@@ -5241,8 +5022,6 @@ static void i802_deinit(void *priv)
 	struct wpa_driver_nl80211_data *drv = priv;
 	struct wpa_driver_nl80211_data *drv = priv;
 	struct i802_bss *bss, *prev;
 	struct i802_bss *bss, *prev;
 
 
-	i802_wireless_event_deinit(drv);
-
 	if (drv->last_freq_ht) {
 	if (drv->last_freq_ht) {
 		/* Clear HT flags from the driver */
 		/* Clear HT flags from the driver */
 		struct hostapd_freq_params freq;
 		struct hostapd_freq_params freq;
@@ -5269,6 +5048,7 @@ static void i802_deinit(void *priv)
 		close(drv->eapol_sock);
 		close(drv->eapol_sock);
 	}
 	}
 
 
+	eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle));
 	genl_family_put(drv->nl80211);
 	genl_family_put(drv->nl80211);
 	nl_cache_free(drv->nl_cache);
 	nl_cache_free(drv->nl_cache);
 	nl_handle_destroy(drv->nl_handle);
 	nl_handle_destroy(drv->nl_handle);