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 0000000000..f94ba42886 --- /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; + } + + |