mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-04 06:54:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			414 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
---
 | 
						|
 hostapd/driver_devicescape.c |  332 ++++++++++++++++++++++++++++++++-----------
 | 
						|
 1 file changed, 251 insertions(+), 81 deletions(-)
 | 
						|
 | 
						|
--- hostap.orig/hostapd/driver_devicescape.c	2007-11-14 17:31:15.000000000 +0100
 | 
						|
+++ hostap/hostapd/driver_devicescape.c	2007-11-14 17:31:16.000000000 +0100
 | 
						|
@@ -75,8 +75,14 @@ struct i802_driver_data {
 | 
						|
 
 | 
						|
 #define HAPD_DECL	struct hostapd_data *hapd = iface->bss[0]
 | 
						|
 
 | 
						|
-static int i802_sta_set_flags(void *priv, const u8 *addr,
 | 
						|
-			      int total_flags, int flags_or, int flags_and);
 | 
						|
+/* helper for netlink get routines */
 | 
						|
+static int ack_wait_handler(struct nl_msg *msg, void *arg)
 | 
						|
+{
 | 
						|
+	int *finished = arg;
 | 
						|
+
 | 
						|
+	*finished = 1;
 | 
						|
+	return NL_STOP;
 | 
						|
+}
 | 
						|
 
 | 
						|
 
 | 
						|
 static int hostapd_set_iface_flags(struct i802_driver_data *drv, int dev_up)
 | 
						|
@@ -255,14 +261,6 @@ static int get_key_handler(struct nl_msg
 | 
						|
 	return NL_SKIP;
 | 
						|
 }
 | 
						|
 
 | 
						|
-static int ack_wait_handler(struct nl_msg *msg, void *arg)
 | 
						|
-{
 | 
						|
-	int *finished = arg;
 | 
						|
-
 | 
						|
-	*finished = 1;
 | 
						|
-	return NL_STOP;
 | 
						|
-}
 | 
						|
-
 | 
						|
 static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
 | 
						|
 			   int idx, u8 *seq)
 | 
						|
 {
 | 
						|
@@ -629,43 +627,126 @@ static int i802_get_retry(void *priv, in
 | 
						|
 static int i802_flush(void *priv)
 | 
						|
 {
 | 
						|
 	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
+	struct nl_msg *msg;
 | 
						|
+	int ret = -1;
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_FLUSH;
 | 
						|
-	return hostapd_ioctl(drv, ¶m, sizeof(param));
 | 
						|
+	msg = nlmsg_alloc();
 | 
						|
+	if (!msg)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 | 
						|
+		    0, NL80211_CMD_NEW_STATION, 0);
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * XXX: FIX! this needs to flush all VLANs too
 | 
						|
+	 */
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 | 
						|
+		    if_nametoindex(drv->iface));
 | 
						|
+
 | 
						|
+	ret = 0;
 | 
						|
+
 | 
						|
+	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
 | 
						|
+	    nl_wait_for_ack(drv->nl_handle) < 0) {
 | 
						|
+		ret = -1;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+ nla_put_failure:
 | 
						|
+	nlmsg_free(msg);
 | 
						|
+
 | 
						|
+ out:
 | 
						|
+	return ret;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
+static int get_sta_handler(struct nl_msg *msg, void *arg)
 | 
						|
+{
 | 
						|
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
 | 
						|
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 | 
						|
+	struct hostap_sta_driver_data *data = arg;
 | 
						|
+	struct nlattr *stats[NL80211_STA_STAT_MAX + 1];
 | 
						|
+	static struct nla_policy stats_policy[NL80211_STA_STAT_MAX + 1] = {
 | 
						|
+		[NL80211_STA_STAT_INACTIVE_TIME] = { .type = NLA_U32 },
 | 
						|
+		[NL80211_STA_STAT_RX_BYTES] = { .type = NLA_U32 },
 | 
						|
+		[NL80211_STA_STAT_TX_BYTES] = { .type = NLA_U32 },
 | 
						|
+	};
 | 
						|
+
 | 
						|
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 | 
						|
+		  genlmsg_attrlen(gnlh, 0), NULL);
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * TODO: validate the interface and mac address!
 | 
						|
+	 * Otherwise, there's a race condition as soon as
 | 
						|
+	 * the kernel starts sending station notifications.
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	if (!tb[NL80211_ATTR_STA_STATS]) {
 | 
						|
+		printf("sta stats missing!\n");
 | 
						|
+		return NL_SKIP;
 | 
						|
+	}
 | 
						|
+	if (nla_parse_nested(stats, NL80211_STA_STAT_MAX,
 | 
						|
+			     tb[NL80211_ATTR_STA_STATS],
 | 
						|
+			     stats_policy)) {
 | 
						|
+		printf("failed to parse nested attributes!\n");
 | 
						|
+		return NL_SKIP;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	if (stats[NL80211_STA_STAT_INACTIVE_TIME])
 | 
						|
+		data->inactive_msec =
 | 
						|
+			nla_get_u32(stats[NL80211_STA_STAT_INACTIVE_TIME]);
 | 
						|
+	if (stats[NL80211_STA_STAT_RX_BYTES])
 | 
						|
+		data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_RX_BYTES]);
 | 
						|
+	if (stats[NL80211_STA_STAT_TX_BYTES])
 | 
						|
+		data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_TX_BYTES]);
 | 
						|
+
 | 
						|
+	return NL_SKIP;
 | 
						|
+}
 | 
						|
+
 | 
						|
 static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
 | 
						|
 			      const u8 *addr)
 | 
						|
 {
 | 
						|
 	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
+	struct nl_msg *msg;
 | 
						|
+	struct nl_cb *cb = NULL;
 | 
						|
+	int ret = -1;
 | 
						|
+	int err = 0;
 | 
						|
+	int finished = 0;
 | 
						|
+
 | 
						|
+	msg = nlmsg_alloc();
 | 
						|
+	if (!msg)
 | 
						|
+		goto out;
 | 
						|
 
 | 
						|
-	memset(data, 0, sizeof(*data));
 | 
						|
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 | 
						|
+		    0, NL80211_CMD_GET_STATION, 0);
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
 | 
						|
-	memcpy(param.sta_addr, addr, ETH_ALEN);
 | 
						|
-	if (hostapd_ioctl(drv, ¶m, sizeof(param))) {
 | 
						|
-		printf("  Could not get station info from kernel driver.\n");
 | 
						|
-		return -1;
 | 
						|
-	}
 | 
						|
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
 | 
						|
+
 | 
						|
+	cb = nl_cb_alloc(NL_CB_CUSTOM);
 | 
						|
+	if (!cb)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_sta_handler, data);
 | 
						|
+	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
 | 
						|
+
 | 
						|
+	err = nl_recvmsgs(drv->nl_handle, cb);
 | 
						|
+
 | 
						|
+	if (!finished)
 | 
						|
+		err = nl_wait_for_ack(drv->nl_handle);
 | 
						|
+
 | 
						|
+	if (err < 0)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	ret = 0;
 | 
						|
+
 | 
						|
+ out:
 | 
						|
+	nl_cb_put(cb);
 | 
						|
+ nla_put_failure:
 | 
						|
+	nlmsg_free(msg);
 | 
						|
+	return ret;
 | 
						|
 
 | 
						|
-	data->inactive_msec = param.u.get_info_sta.inactive_msec;
 | 
						|
-	data->rx_packets = param.u.get_info_sta.rx_packets;
 | 
						|
-	data->tx_packets = param.u.get_info_sta.tx_packets;
 | 
						|
-	data->rx_bytes = param.u.get_info_sta.rx_bytes;
 | 
						|
-	data->tx_bytes = param.u.get_info_sta.tx_bytes;
 | 
						|
-	data->current_tx_rate = param.u.get_info_sta.current_tx_rate;
 | 
						|
-	data->flags = param.u.get_info_sta.flags;
 | 
						|
-	data->num_ps_buf_frames = param.u.get_info_sta.num_ps_buf_frames;
 | 
						|
-	data->tx_retry_failed = param.u.get_info_sta.tx_retry_failed;
 | 
						|
-	data->tx_retry_count = param.u.get_info_sta.tx_retry_count;
 | 
						|
-	data->last_rssi = param.u.get_info_sta.last_rssi;
 | 
						|
-	data->last_ack_rssi = param.u.get_info_sta.last_ack_rssi;
 | 
						|
-	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
@@ -744,35 +825,70 @@ static int i802_sta_add(const char *ifna
 | 
						|
 			size_t supp_rates_len, int flags)
 | 
						|
 {
 | 
						|
 	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
-	size_t len;
 | 
						|
+	struct nl_msg *msg;
 | 
						|
+	int ret = -1;
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_ADD_STA;
 | 
						|
-	memcpy(param.sta_addr, addr, ETH_ALEN);
 | 
						|
-	param.u.add_sta.aid = aid;
 | 
						|
-	param.u.add_sta.capability = capability;
 | 
						|
-	len = supp_rates_len;
 | 
						|
-	if (len > sizeof(param.u.add_sta.supp_rates))
 | 
						|
-		len = sizeof(param.u.add_sta.supp_rates);
 | 
						|
-	memcpy(param.u.add_sta.supp_rates, supp_rates, len);
 | 
						|
-	return hostapd_ioctl_iface(ifname, drv, ¶m, sizeof(param));
 | 
						|
+	msg = nlmsg_alloc();
 | 
						|
+	if (!msg)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 | 
						|
+		    0, NL80211_CMD_NEW_STATION, 0);
 | 
						|
+
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 | 
						|
+		    if_nametoindex(drv->iface));
 | 
						|
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 | 
						|
+	NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, aid);
 | 
						|
+	NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, supp_rates_len,
 | 
						|
+		supp_rates);
 | 
						|
+	NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 0);
 | 
						|
+
 | 
						|
+	ret = nl_send_auto_complete(drv->nl_handle, msg);
 | 
						|
+	if (ret < 0)
 | 
						|
+		goto nla_put_failure;
 | 
						|
+
 | 
						|
+	ret = nl_wait_for_ack(drv->nl_handle);
 | 
						|
+	/* ignore EEXIST, this happens if a STA associates while associated */
 | 
						|
+	if (ret == -EEXIST || ret >= 0)
 | 
						|
+		ret = 0;
 | 
						|
+
 | 
						|
+ nla_put_failure:
 | 
						|
+	nlmsg_free(msg);
 | 
						|
+
 | 
						|
+ out:
 | 
						|
+	return ret;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
 static int i802_sta_remove(void *priv, const u8 *addr)
 | 
						|
 {
 | 
						|
 	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
+	struct nl_msg *msg;
 | 
						|
+	int ret = -1;
 | 
						|
 
 | 
						|
-	i802_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
 | 
						|
+	msg = nlmsg_alloc();
 | 
						|
+	if (!msg)
 | 
						|
+		goto out;
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
 | 
						|
-	memcpy(param.sta_addr, addr, ETH_ALEN);
 | 
						|
-	if (hostapd_ioctl(drv, ¶m, sizeof(param)))
 | 
						|
-		return -1;
 | 
						|
-	return 0;
 | 
						|
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 | 
						|
+		    0, NL80211_CMD_DEL_STATION, 0);
 | 
						|
+
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 | 
						|
+		    if_nametoindex(drv->iface));
 | 
						|
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 | 
						|
+
 | 
						|
+	ret = 0;
 | 
						|
+
 | 
						|
+	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
 | 
						|
+	    nl_wait_for_ack(drv->nl_handle) < 0) {
 | 
						|
+		ret = -1;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+ nla_put_failure:
 | 
						|
+	nlmsg_free(msg);
 | 
						|
+
 | 
						|
+ out:
 | 
						|
+	return ret;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
@@ -780,14 +896,51 @@ static int i802_sta_set_flags(void *priv
 | 
						|
 			      int total_flags, int flags_or, int flags_and)
 | 
						|
 {
 | 
						|
 	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
+	struct nl_msg *msg, *flags = NULL;
 | 
						|
+	int ret = -1;
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
 | 
						|
-	memcpy(param.sta_addr, addr, ETH_ALEN);
 | 
						|
-	param.u.set_flags_sta.flags_or = flags_or;
 | 
						|
-	param.u.set_flags_sta.flags_and = flags_and;
 | 
						|
-	return hostapd_ioctl(drv, ¶m, sizeof(param));
 | 
						|
+	msg = nlmsg_alloc();
 | 
						|
+	if (!msg)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	flags = nlmsg_alloc();
 | 
						|
+	if (!flags)
 | 
						|
+		goto free_msg;
 | 
						|
+
 | 
						|
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 | 
						|
+		    0, NL80211_CMD_SET_STATION, 0);
 | 
						|
+
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 | 
						|
+		    if_nametoindex(drv->iface));
 | 
						|
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 | 
						|
+
 | 
						|
+	if (total_flags & WLAN_STA_AUTHORIZED)
 | 
						|
+		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
 | 
						|
+
 | 
						|
+	if (total_flags & WLAN_STA_WME)
 | 
						|
+		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
 | 
						|
+
 | 
						|
+	if (total_flags & WLAN_STA_SHORT_PREAMBLE)
 | 
						|
+		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
 | 
						|
+
 | 
						|
+	if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
 | 
						|
+		goto nla_put_failure;
 | 
						|
+
 | 
						|
+	ret = 0;
 | 
						|
+
 | 
						|
+	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
 | 
						|
+	    nl_wait_for_ack(drv->nl_handle) < 0) {
 | 
						|
+		ret = -1;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+ nla_put_failure:
 | 
						|
+	nlmsg_free(flags);
 | 
						|
+
 | 
						|
+ free_msg:
 | 
						|
+	nlmsg_free(msg);
 | 
						|
+
 | 
						|
+ out:
 | 
						|
+	return ret;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
@@ -1257,18 +1410,38 @@ static struct hostapd_hw_modes * i802_ge
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
-static int i802_set_sta_vlan(void *priv, const u8 *addr, const char *ifname,
 | 
						|
-			     int vlan_id)
 | 
						|
+static int i802_set_sta_vlan(void *priv, const u8 *addr,
 | 
						|
+			     const char *ifname, int vlan_id)
 | 
						|
 {
 | 
						|
 	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
+	struct nl_msg *msg;
 | 
						|
+	int ret = -1;
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_SET_STA_VLAN;
 | 
						|
-	memcpy(param.sta_addr, addr, ETH_ALEN);
 | 
						|
-	os_strlcpy(param.u.set_sta_vlan.vlan_name, ifname, IFNAMSIZ);
 | 
						|
-	param.u.set_sta_vlan.vlan_id = vlan_id;
 | 
						|
-	return hostapd_ioctl(drv, ¶m, sizeof(param));
 | 
						|
+	msg = nlmsg_alloc();
 | 
						|
+	if (!msg)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 | 
						|
+		    0, NL80211_CMD_SET_STATION, 0);
 | 
						|
+
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 | 
						|
+		    if_nametoindex(drv->iface));
 | 
						|
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 | 
						|
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 | 
						|
+		    if_nametoindex(ifname));
 | 
						|
+
 | 
						|
+	ret = 0;
 | 
						|
+
 | 
						|
+	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
 | 
						|
+	    nl_wait_for_ack(drv->nl_handle) < 0) {
 | 
						|
+		ret = -1;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+ nla_put_failure:
 | 
						|
+	nlmsg_free(msg);
 | 
						|
+
 | 
						|
+ out:
 | 
						|
+	return ret;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 | 
						|
@@ -1752,17 +1925,14 @@ static int i802_init_sockets(struct i802
 | 
						|
 
 | 
						|
 static int i802_get_inact_sec(void *priv, const u8 *addr)
 | 
						|
 {
 | 
						|
-	struct i802_driver_data *drv = priv;
 | 
						|
-	struct prism2_hostapd_param param;
 | 
						|
+	struct hostap_sta_driver_data data;
 | 
						|
+	int ret;
 | 
						|
 
 | 
						|
-	memset(¶m, 0, sizeof(param));
 | 
						|
-	param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
 | 
						|
-	memcpy(param.sta_addr, addr, ETH_ALEN);
 | 
						|
-	if (hostapd_ioctl(drv, ¶m, sizeof(param))) {
 | 
						|
+	data.inactive_msec = -1;
 | 
						|
+	ret = i802_read_sta_data(priv, &data, addr);
 | 
						|
+	if (ret || data.inactive_msec == -1)
 | 
						|
 		return -1;
 | 
						|
-	}
 | 
						|
-
 | 
						|
-	return param.u.get_info_sta.inactive_msec / 1000;
 | 
						|
+	return data.inactive_msec / 1000;
 | 
						|
 }
 | 
						|
 
 | 
						|
 
 |