This patch makes the nl80211 driver use nl80211 for beacons rather than the prism2 ioctl. Signed-off-by: Johannes Berg --- hostapd/driver_nl80211.c | 145 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 35 deletions(-) --- hostap.orig/hostapd/driver_nl80211.c 2007-12-24 12:09:59.000000000 +0100 +++ hostap/hostapd/driver_nl80211.c 2007-12-24 12:10:01.000000000 +0100 @@ -103,11 +103,6 @@ struct prism2_hostapd_param { u32 flags_or; } set_flags_sta; struct { - u16 head_len; - u16 tail_len; - u8 data[0] ALIGNED; /* head_len + tail_len bytes */ - } beacon; - struct { u16 num_modes; u16 flags; u8 data[0] ALIGNED; /* num_modes * feature data */ @@ -152,7 +147,6 @@ enum { PRISM2_HOSTAPD_GET_INFO_STA = 4, PRISM2_GET_ENCRYPTION = 7, PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_SET_BEACON = 1001, PRISM2_HOSTAPD_SET_RATE_SETS = 1005, PRISM2_HOSTAPD_SET_STA_VLAN = 1010, PRISM2_HOSTAPD_SET_CHANNEL_FLAG = 1012, @@ -242,6 +236,8 @@ struct i802_driver_data { struct nl_handle *nl_handle; struct nl_cache *nl_cache; struct genl_family *nl80211; + int dtim_period; + unsigned int beacon_set:1; }; static void add_ifidx(struct i802_driver_data *drv, int ifidx) @@ -1153,37 +1149,70 @@ static int i802_bss_remove(void *priv, c } -static int i802_set_beacon(const char *ifname, void *priv, +static int i802_set_beacon(const char *iface, void *priv, u8 *head, size_t head_len, u8 *tail, size_t tail_len) { struct i802_driver_data *drv = priv; - struct prism2_hostapd_param *param; - int len, ret = 0; + struct nl_msg *msg; + u8 cmd = NL80211_CMD_NEW_BEACON; + int ret = -1; - param = os_zalloc(sizeof(*param) + head_len + tail_len); - if (param == NULL) { - printf("Failed to alloc memory for beacon ioctl\n"); - return -1; - } - len = (¶m->u.beacon.data[0] - (u8 *) param) + head_len + tail_len; - param->cmd = PRISM2_HOSTAPD_SET_BEACON; - param->u.beacon.head_len = head_len; - param->u.beacon.tail_len = tail_len; - memcpy(¶m->u.beacon.data[0], head, head_len); - memcpy(¶m->u.beacon.data[0] + head_len, tail, tail_len); - - if (len < (int) sizeof(*param)) - len = sizeof(*param); - if (hostapd_ioctl_iface(ifname, drv, param, len)) { - printf("Could not set beacon data to kernel driver.\n"); - printf("ifname='%s' head=%p head_len=%d tail=%p tail_len=%d " - "cmd=%d\n", - ifname, head, head_len, tail, tail_len, param->cmd); - ret = -1; - } + msg = nlmsg_alloc(); + if (!msg) + goto out; - free(param); + if (drv->beacon_set) + cmd = NL80211_CMD_SET_BEACON; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, cmd, 0); + NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head); + NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); + NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, 1000); + + if (!drv->dtim_period) + drv->dtim_period = 2; + NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period); + + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || + nl_wait_for_ack(drv->nl_handle) < 0) + goto out; + + ret = 0; + + drv->beacon_set = 1; + + out: + nla_put_failure: + nlmsg_free(msg); + return ret; +} + + +static int i802_del_beacon(struct i802_driver_data *drv) +{ + struct nl_msg *msg; + int ret = -1; + + msg = nlmsg_alloc(); + if (!msg) + goto out; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_DEL_BEACON, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); + + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || + nl_wait_for_ack(drv->nl_handle) < 0) + goto out; + + ret = 0; + + out: + nla_put_failure: + nlmsg_free(msg); return ret; } @@ -1232,15 +1261,59 @@ static int i802_set_internal_bridge(void static int i802_set_beacon_int(void *priv, int value) { struct i802_driver_data *drv = priv; - return hostap_ioctl_prism2param(drv, PRISM2_PARAM_BEACON_INT, value); + struct nl_msg *msg; + int ret = -1; + + msg = nlmsg_alloc(); + if (!msg) + goto out; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_BEACON, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); + + NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value); + + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || + nl_wait_for_ack(drv->nl_handle) < 0) + goto out; + + ret = 0; + + out: + nla_put_failure: + nlmsg_free(msg); + return ret; } -static int i802_set_dtim_period(const char *ifname, void *priv, int value) +static int i802_set_dtim_period(const char *iface, void *priv, int value) { struct i802_driver_data *drv = priv; - return hostap_ioctl_prism2param_iface(ifname, drv, - PRISM2_PARAM_DTIM_PERIOD, value); + struct nl_msg *msg; + int ret = -1; + + msg = nlmsg_alloc(); + if (!msg) + goto out; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_BEACON, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); + + drv->dtim_period = value; + NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period); + + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || + nl_wait_for_ack(drv->nl_handle) < 0) + goto out; + + ret = 0; + + out: + nla_put_failure: + nlmsg_free(msg); + return ret; } @@ -2268,6 +2341,8 @@ static void i802_deinit(void *priv) { struct i802_driver_data *drv = priv; + i802_del_beacon(drv); + /* Disable management interface */ (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_MGMT_IF, 0); --