diff options
Diffstat (limited to 'package/hostapd/patches/006-use-nl80211-for-sta.patch')
| -rw-r--r-- | package/hostapd/patches/006-use-nl80211-for-sta.patch | 411 | 
1 files changed, 411 insertions, 0 deletions
diff --git a/package/hostapd/patches/006-use-nl80211-for-sta.patch b/package/hostapd/patches/006-use-nl80211-for-sta.patch new file mode 100644 index 000000000..f94ba4288 --- /dev/null +++ b/package/hostapd/patches/006-use-nl80211-for-sta.patch @@ -0,0 +1,411 @@ +--- + hostapd/driver_devicescape.c |  330 ++++++++++++++++++++++++++++++++----------- + 1 file changed, 249 insertions(+), 81 deletions(-) + +--- hostap.orig/hostapd/driver_devicescape.c	2007-11-09 13:41:15.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c	2007-11-09 13:41: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; +  +-	memset(data, 0, sizeof(*data)); ++	msg = nlmsg_alloc(); ++	if (!msg) ++		goto out; +  +-	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; +-	} ++	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++		    0, NL80211_CMD_GET_STATION, 0); ++ ++	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,68 @@ 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 = 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 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 +894,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 +1408,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; + } +  +  +@@ -1750,17 +1921,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; + } +  +   | 
