Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx> --- hostapd/driver_devicescape.c | 217 +++++++++++++++++++------------------------ 1 file changed, 99 insertions(+), 118 deletions(-) --- hostap.orig/hostapd/driver_devicescape.c 2007-08-14 11:32:35.000000000 +0200 +++ hostap/hostapd/driver_devicescape.c 2007-08-14 11:32:35.000000000 +0200 @@ -786,56 +786,108 @@ static int i802_set_tx_queue_params(void } -static int i802_bss_add(void *priv, const char *ifname, const u8 *bssid) +static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx) { - struct i802_driver_data *drv = priv; - struct prism2_hostapd_param *param; + struct nl_msg *msg; - param = os_zalloc(sizeof(struct prism2_hostapd_param) + ETH_ALEN); - if (param == NULL) + msg = nlmsg_alloc(); + if (!msg) + goto nla_put_failure; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_DEL_VIRTUAL_INTERFACE, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || + nl_wait_for_ack(drv->nl_handle) < 0) + nla_put_failure: + printf("Failed to remove interface.\n"); + nlmsg_free(msg); +} + + +static int nl80211_create_iface(struct i802_driver_data *drv, + const char *ifname, + enum nl80211_iftype iftype, + const u8 *addr) +{ + struct nl_msg *msg; + int ifidx; + struct ifreq ifreq; + struct iwreq iwr; + + msg = nlmsg_alloc(); + if (!msg) return -1; - param->cmd = PRISM2_HOSTAPD_ADD_IF; - param->u.if_info.type = HOSTAP_IF_BSS; - memcpy(param->u.if_info.data, bssid, ETH_ALEN); - os_strlcpy((char *) param->u.if_info.name, ifname, IFNAMSIZ); - - if (hostapd_ioctl(drv, param, - sizeof(struct prism2_hostapd_param) + ETH_ALEN)) { - printf("Could not add bss iface: %s.\n", ifname); - free(param); + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_ADD_VIRTUAL_INTERFACE, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, + if_nametoindex(drv->hapd->conf->iface)); + NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); + + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || + nl_wait_for_ack(drv->nl_handle) < 0) { + nla_put_failure: + printf("Failed to create interface %s.\n", ifname); + nlmsg_free(msg); return -1; } - free(param); + nlmsg_free(msg); - return 0; + ifidx = if_nametoindex(ifname); + + if (ifidx <= 0) + return -1; + + if (addr) switch (iftype) { + case NL80211_IFTYPE_AP: + /* + * This is how it works in mac80211 right now, but who gets to + * handle multiple AP devices with different BSSIDs but the + * same MAC? + * In fact, I think we should be changing the BSSID here and + * not the MAC address... but mac80211 doesn't support that! + */ + os_strlcpy(ifreq.ifr_name, ifname, IFNAMSIZ); + memcpy(ifreq.ifr_hwaddr.sa_data, addr, ETH_ALEN); + ifreq.ifr_hwaddr.sa_family = ARPHRD_ETHER; + + if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq)) { + nl80211_remove_iface(drv, ifidx); + return -1; + } + break; + case NL80211_IFTYPE_WDS: + memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); + iwr.u.addr.sa_family = ARPHRD_ETHER; + memcpy(iwr.u.addr.sa_data, addr, ETH_ALEN); + if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr)) + return -1; + break; + default: + /* nothing */ + break; + } + + return ifidx; } -static int i802_bss_remove(void *priv, const char *ifname) +static int i802_bss_add(void *priv, const char *ifname, const u8 *bssid) { - struct i802_driver_data *drv = priv; - struct prism2_hostapd_param *param; - int ret = 0; - - param = os_zalloc(sizeof(struct prism2_hostapd_param) + ETH_ALEN); - if (param == NULL) + if (nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid) < 0) return -1; + return 0; +} - param->cmd = PRISM2_HOSTAPD_REMOVE_IF; - param->u.if_info.type = HOSTAP_IF_BSS; - os_strlcpy((char *) param->u.if_info.name, ifname, IFNAMSIZ); - - if (hostapd_ioctl(drv, param, - sizeof(struct prism2_hostapd_param) + ETH_ALEN)) { - printf("Could not remove iface: %s.\n", ifname); - ret = -1; - } - - free(param); - return ret; +static int i802_bss_remove(void *priv, const char *ifname) +{ + nl80211_remove_iface(priv, if_nametoindex(ifname)); + return 0; } @@ -970,13 +1022,13 @@ static int i802_set_short_slot_time(void } -static int i802_if_type(enum hostapd_driver_if_type type) +static enum nl80211_iftype i802_if_type(enum hostapd_driver_if_type type) { switch (type) { case HOSTAPD_IF_VLAN: - return HOSTAP_IF_VLAN; + return NL80211_IFTYPE_AP_VLAN; case HOSTAPD_IF_WDS: - return HOSTAP_IF_WDS; + return NL80211_IFTYPE_WDS; } return -1; } @@ -986,32 +1038,8 @@ static int i802_if_add(const char *iface enum hostapd_driver_if_type type, char *ifname, const u8 *addr) { - struct i802_driver_data *drv = priv; - struct prism2_hostapd_param *param; - - param = malloc(sizeof(struct prism2_hostapd_param) + ETH_ALEN); - if (!param) + if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0) return -1; - memset(param, 0, sizeof(param)); - - param->cmd = PRISM2_HOSTAPD_ADD_IF; - param->u.if_info.type = i802_if_type(type); - if (addr) - memcpy(param->u.if_info.data, addr, ETH_ALEN); - else - memset(param->u.if_info.data, 0, ETH_ALEN); - os_strlcpy((char *) param->u.if_info.name, ifname, IFNAMSIZ); - - /* FIX: should the size have + ETH_ALEN ? */ - if (hostapd_ioctl_iface(iface, drv, param, - sizeof(struct prism2_hostapd_param))) { - printf("Could not add iface: %s.\n", ifname); - free(param); - return -1; - } - - os_strlcpy(ifname, (char *) param->u.if_info.name, IFNAMSIZ); - free(param); return 0; } @@ -1027,28 +1055,7 @@ static int i802_if_update(void *priv, en static int i802_if_remove(void *priv, enum hostapd_driver_if_type type, const char *ifname, const u8 *addr) { - struct i802_driver_data *drv = priv; - struct prism2_hostapd_param *param; - - param = malloc(sizeof(struct prism2_hostapd_param) + ETH_ALEN); - if (!param) - return -1; - memset(param, 0, sizeof(param)); - - param->cmd = PRISM2_HOSTAPD_REMOVE_IF; - param->u.if_info.type = i802_if_type(type); - if (addr) - memcpy(param->u.if_info.data, addr, ETH_ALEN); - else - memset(param->u.if_info.data, 0, ETH_ALEN); - os_strlcpy((char *) param->u.if_info.name, ifname, IFNAMSIZ); - if (hostapd_ioctl(drv, param, sizeof(struct prism2_hostapd_param))) { - printf("Could not remove iface: %s.\n", ifname); - free(param); - return -1; - } - - free(param); + nl80211_remove_iface(priv, if_nametoindex(ifname)); return 0; } @@ -1546,7 +1553,6 @@ static int i802_init_sockets(struct i802 struct sockaddr_ll addr; struct iwreq iwr; char buf[IFNAMSIZ]; - struct nl_msg *msg; socklen_t optlen; int optval; int idx; @@ -1584,28 +1590,14 @@ static int i802_init_sockets(struct i802 return -1; } - /* conjure a monitor interface */ - msg = nlmsg_alloc(); - if (!msg) { - printf("Failed to allocate netlink message.\n"); - return -1; - } snprintf(buf, IFNAMSIZ, "mon.%s", hapd->conf->iface); buf[IFNAMSIZ-1] = '\0'; - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_ADD_VIRTUAL_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(hapd->conf->iface)); - NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, buf); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR); - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - nl_wait_for_ack(drv->nl_handle) < 0) { - nla_put_failure: - nlmsg_free(msg); - printf("Failed to create monitor interface %s.\n", buf); + + drv->monitor_ifidx = nl80211_create_iface(drv, buf, + NL80211_IFTYPE_MONITOR, + NULL); + if (drv->monitor_ifidx < 0) return -1; - } - nlmsg_free(msg); /* * TODO: try disabling receiving control frames on the monitor iface, @@ -1631,7 +1623,7 @@ static int i802_init_sockets(struct i802 memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; - drv->monitor_ifidx = addr.sll_ifindex = if_nametoindex(buf); + addr.sll_ifindex = drv->monitor_ifidx; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Opening raw packet socket for monitor (%d)\n", addr.sll_ifindex); @@ -2078,7 +2070,6 @@ failed: static void i802_deinit(void *priv) { struct i802_driver_data *drv = priv; - struct nl_msg *msg; (void) hostapd_set_iface_flags(drv, 0); @@ -2088,17 +2079,7 @@ static void i802_deinit(void *priv) eloop_unregister_read_sock(drv->monitor_sock); close(drv->monitor_sock); - msg = nlmsg_alloc(); - if (msg) { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_VIRTUAL_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->monitor_ifidx); - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - nl_wait_for_ack(drv->nl_handle) < 0) - nla_put_failure: - printf("Failed to remove monitor interface.\n"); - nlmsg_free(msg); - } + nl80211_remove_iface(drv, drv->monitor_ifidx); nl_cache_free(drv->nl_cache); nl_handle_destroy(drv->nl_handle); -- - To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html