--- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -59,8 +59,10 @@ #endif struct i802_bss { + struct wpa_driver_nl80211_data *drv; struct i802_bss *next; int ifindex; + char ifname[IFNAMSIZ + 1]; unsigned int beacon_set:1; }; @@ -68,7 +70,6 @@ struct wpa_driver_nl80211_data { void *ctx; struct netlink_data *netlink; int ioctl_sock; /* socket for ioctl() use */ - char ifname[IFNAMSIZ + 1]; char brname[IFNAMSIZ]; int ifindex; int if_removed; @@ -107,6 +108,8 @@ struct wpa_driver_nl80211_data { u64 remain_on_chan_cookie; + struct i802_bss first_bss; + #ifdef HOSTAPD int eapol_sock; /* socket for EAPOL frames */ @@ -114,8 +117,6 @@ struct wpa_driver_nl80211_data { int *if_indices; int num_if_indices; - struct i802_bss bss; - int last_freq; int last_freq_ht; #endif /* HOSTAPD */ @@ -135,8 +136,6 @@ static void nl80211_remove_monitor_inter #ifdef HOSTAPD static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); -static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv, - int ifindex); static int i802_set_freq(void *priv, struct hostapd_freq_params *freq); static int wpa_driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type, @@ -278,7 +277,8 @@ nla_put_failure: static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (!drv->associated) return -1; os_memcpy(bssid, drv->bssid, ETH_ALEN); @@ -288,7 +288,8 @@ static int wpa_driver_nl80211_get_bssid( static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (!drv->associated) return -1; os_memcpy(ssid, drv->ssid, drv->ssid_len); @@ -313,7 +314,7 @@ static void wpa_driver_nl80211_event_lin event.interface_status.ifname, del ? "removed" : "added"); - if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { + if (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) { if (del) drv->if_removed = 1; else @@ -336,7 +337,7 @@ static int wpa_driver_nl80211_own_ifname rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_IFNAME) { - if (os_strcmp(((char *) attr) + rta_len, drv->ifname) + if (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname) == 0) return 1; else @@ -356,7 +357,7 @@ static int wpa_driver_nl80211_own_ifinde return 1; if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) { - drv->ifindex = if_nametoindex(drv->ifname); + drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname); wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed " "interface"); wpa_driver_nl80211_finish_drv_init(drv); @@ -785,7 +786,7 @@ static int process_event(struct nl_msg * if (drv->ap_scan_as_station && (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS || gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) { - wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_AP); + wpa_driver_nl80211_set_mode(&drv->first_bss, IEEE80211_MODE_AP); drv->ap_scan_as_station = 0; } @@ -889,7 +890,8 @@ static void wpa_driver_nl80211_event_rec */ static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; char alpha2[3]; struct nl_msg *msg; @@ -978,7 +980,7 @@ static int wpa_driver_nl80211_get_info(s genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_GET_WIPHY, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex); if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info) == 0) return 0; @@ -1152,15 +1154,18 @@ static void * wpa_driver_nl80211_init(vo { struct wpa_driver_nl80211_data *drv; struct netlink_config *cfg; + struct i802_bss *bss; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + bss = &drv->first_bss; + os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname)); drv->monitor_ifidx = -1; drv->monitor_sock = -1; drv->ioctl_sock = -1; + drv->first_bss.drv = drv; if (wpa_driver_nl80211_init_nl(drv, ctx)) { os_free(drv); @@ -1187,7 +1192,7 @@ static void * wpa_driver_nl80211_init(vo if (wpa_driver_nl80211_finish_drv_init(drv)) goto failed; - return drv; + return bss; failed: netlink_deinit(drv->netlink); @@ -1207,17 +1212,19 @@ failed: static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) { - drv->ifindex = if_nametoindex(drv->ifname); + struct i802_bss *bss = &drv->first_bss; + + drv->ifindex = if_nametoindex(drv->first_bss.ifname); #ifndef HOSTAPD - if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA) < 0) { + if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) { wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to " "use managed mode"); } - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) { + if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) { wpa_printf(MSG_ERROR, "Could not set interface '%s' UP", - drv->ifname); + bss->ifname); return -1; } @@ -1232,20 +1239,6 @@ wpa_driver_nl80211_finish_drv_init(struc } -#ifdef HOSTAPD -static void wpa_driver_nl80211_free_bss(struct wpa_driver_nl80211_data *drv) -{ - struct i802_bss *bss, *prev; - bss = drv->bss.next; - while (bss) { - prev = bss; - bss = bss->next; - os_free(bss); - } -} -#endif /* HOSTAPD */ - - static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv) { struct nl_msg *msg; @@ -1273,14 +1266,15 @@ static int wpa_driver_nl80211_del_beacon */ static void wpa_driver_nl80211_deinit(void *priv) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (drv->added_if_into_bridge) { - if (linux_br_del_if(drv->ioctl_sock, drv->brname, drv->ifname) + if (linux_br_del_if(drv->ioctl_sock, drv->brname, bss->ifname) < 0) wpa_printf(MSG_INFO, "nl80211: Failed to remove " "interface %s from bridge %s: %s", - drv->ifname, drv->brname, strerror(errno)); + bss->ifname, drv->brname, strerror(errno)); } if (drv->added_bridge) { if (linux_br_del(drv->ioctl_sock, drv->brname) < 0) @@ -1310,8 +1304,6 @@ static void wpa_driver_nl80211_deinit(vo if (drv->if_indices != drv->default_if_indices) os_free(drv->if_indices); - - wpa_driver_nl80211_free_bss(drv); #endif /* HOSTAPD */ if (drv->disable_11b_rates) @@ -1322,8 +1314,8 @@ static void wpa_driver_nl80211_deinit(vo eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); - (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); - wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA); + (void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0); + wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA); if (drv->ioctl_sock >= 0) close(drv->ioctl_sock); @@ -1355,7 +1347,7 @@ static void wpa_driver_nl80211_scan_time { struct wpa_driver_nl80211_data *drv = eloop_ctx; if (drv->ap_scan_as_station) { - wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_AP); + wpa_driver_nl80211_set_mode(&drv->first_bss, IEEE80211_MODE_AP); drv->ap_scan_as_station = 0; } wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); @@ -1372,7 +1364,8 @@ static void wpa_driver_nl80211_scan_time static int wpa_driver_nl80211_scan(void *priv, struct wpa_driver_scan_params *params) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ret = 0, timeout; struct nl_msg *msg, *ssids, *freqs; size_t i; @@ -1421,12 +1414,12 @@ static int wpa_driver_nl80211_scan(void * mac80211 does not allow scan requests in AP mode, so * try to do this in station mode. */ - if (wpa_driver_nl80211_set_mode(drv, + if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA)) goto nla_put_failure; if (wpa_driver_nl80211_scan(drv, params)) { - wpa_driver_nl80211_set_mode(drv, + wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP); goto nla_put_failure; } @@ -1662,7 +1655,8 @@ static void wpa_scan_results_free(struct static struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; struct wpa_scan_results *res; int ret; @@ -1701,7 +1695,8 @@ static int wpa_driver_nl80211_set_key(co const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ifindex = if_nametoindex(ifname); struct nl_msg *msg; int ret; @@ -1958,7 +1953,8 @@ static int wpa_driver_nl80211_disconnect static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, int reason_code) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) return wpa_driver_nl80211_disconnect(drv, addr, reason_code); wpa_printf(MSG_DEBUG, "%s", __func__); @@ -1971,7 +1967,8 @@ static int wpa_driver_nl80211_deauthenti static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, int reason_code) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) return wpa_driver_nl80211_disconnect(drv, addr, reason_code); wpa_printf(MSG_DEBUG, "%s", __func__); @@ -1984,7 +1981,8 @@ static int wpa_driver_nl80211_disassocia static int wpa_driver_nl80211_authenticate( void *priv, struct wpa_driver_auth_params *params) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ret = -1, i; struct nl_msg *msg; enum nl80211_auth_type type; @@ -1996,7 +1994,7 @@ static int wpa_driver_nl80211_authentica if (drv->nlmode != NL80211_IFTYPE_STATION) wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); - if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA) < 0) + if (wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0) return -1; retry: @@ -2013,7 +2011,7 @@ retry: for (i = 0; i < 4; i++) { if (!params->wep_key[i]) continue; - wpa_driver_nl80211_set_key(drv->ifname, drv, WPA_ALG_WEP, NULL, + wpa_driver_nl80211_set_key(bss->ifname, drv, WPA_ALG_WEP, NULL, i, i == params->wep_tx_keyidx, NULL, 0, params->wep_key[i], @@ -2348,7 +2346,8 @@ wpa_driver_nl80211_add_11b(struct hostap static struct hostapd_hw_modes * wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; struct phy_info_arg result = { .num_modes = num_modes, @@ -2417,7 +2416,8 @@ static int wpa_driver_nl80211_send_frame static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, size_t data_len) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct ieee80211_mgmt *mgmt; int encrypt = 1; u16 fc; @@ -2448,23 +2448,15 @@ static int wpa_driver_nl80211_set_beacon const u8 *tail, size_t tail_len, int dtim_period, int beacon_int) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; u8 cmd = NL80211_CMD_NEW_BEACON; int ret; int beacon_set; int ifindex = if_nametoindex(ifname); -#ifdef HOSTAPD - struct i802_bss *bss; - bss = get_bss(drv, ifindex); - if (bss == NULL) - return -ENOENT; beacon_set = bss->beacon_set; -#else /* HOSTAPD */ - beacon_set = drv->beacon_set; -#endif /* HOSTAPD */ - msg = nlmsg_alloc(); if (!msg) return -ENOMEM; @@ -2487,11 +2479,7 @@ static int wpa_driver_nl80211_set_beacon wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", ret, strerror(-ret)); } else { -#ifdef HOSTAPD bss->beacon_set = 1; -#else /* HOSTAPD */ - drv->beacon_set = 1; -#endif /* HOSTAPD */ } return ret; nla_put_failure: @@ -2545,7 +2533,8 @@ nla_put_failure: static int wpa_driver_nl80211_sta_add(const char *ifname, void *priv, struct hostapd_sta_add_params *params) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret = -ENOBUFS; @@ -2582,7 +2571,8 @@ static int wpa_driver_nl80211_sta_add(co static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret; @@ -2594,7 +2584,7 @@ static int wpa_driver_nl80211_sta_remove 0, NL80211_CMD_DEL_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); + if_nametoindex(bss->ifname)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ret = send_and_recv_msgs(drv, msg, NULL, NULL); @@ -3032,7 +3022,7 @@ nl80211_create_monitor_interface(struct int optval; socklen_t optlen; - snprintf(buf, IFNAMSIZ, "mon.%s", drv->ifname); + snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname); buf[IFNAMSIZ - 1] = '\0'; drv->monitor_ifidx = @@ -3092,7 +3082,8 @@ static int wpa_driver_nl80211_hapd_send_ void *priv, const u8 *addr, const u8 *data, size_t data_len, int encrypt, const u8 *own_addr) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct ieee80211_hdr *hdr; size_t len; u8 *pos; @@ -3177,7 +3168,8 @@ static int wpa_driver_nl80211_sta_set_fl int total_flags, int flags_or, int flags_and) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg, *flags = NULL; struct nl80211_sta_flag_update upd; @@ -3195,7 +3187,7 @@ static int wpa_driver_nl80211_sta_set_fl 0, NL80211_CMD_SET_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); + if_nametoindex(bss->ifname)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); /* @@ -3234,7 +3226,7 @@ static int wpa_driver_nl80211_sta_set_fl static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { - if (wpa_driver_nl80211_set_mode(drv, params->mode) || + if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) || wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { nl80211_remove_monitor_interface(drv); return -1; @@ -3285,7 +3277,7 @@ static int wpa_driver_nl80211_ibss(struc wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); - if (wpa_driver_nl80211_set_mode(drv, params->mode)) { + if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) { wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " "IBSS mode"); return -1; @@ -3499,7 +3491,8 @@ nla_put_failure: static int wpa_driver_nl80211_associate( void *priv, struct wpa_driver_associate_params *params) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ret = -1; struct nl_msg *msg; @@ -3510,7 +3503,7 @@ static int wpa_driver_nl80211_associate( return wpa_driver_nl80211_ibss(drv, params); if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { - if (wpa_driver_nl80211_set_mode(drv, params->mode) < 0) + if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0) return -1; return wpa_driver_nl80211_connect(drv, params); } @@ -3611,7 +3604,8 @@ nla_put_failure: static int wpa_driver_nl80211_set_mode(void *priv, int mode) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ret = -1; int nlmode; @@ -3646,10 +3640,10 @@ static int wpa_driver_nl80211_set_mode(v * take the device down, try to set the mode again, and bring the * device back up. */ - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) { + if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0) == 0) { /* Try to set the mode again while the interface is down */ ret = nl80211_set_mode(drv, drv->ifindex, nlmode); - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) + if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) ret = -1; } @@ -3684,7 +3678,8 @@ done: static int wpa_driver_nl80211_get_capa(void *priv, struct wpa_driver_capa *capa) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (!drv->has_capability) return -1; os_memcpy(capa, &drv->capa, sizeof(*capa)); @@ -3694,7 +3689,8 @@ static int wpa_driver_nl80211_get_capa(v static int wpa_driver_nl80211_set_operstate(void *priv, int state) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", __func__, drv->operstate, state, state ? "UP" : "DORMANT"); @@ -3706,7 +3702,8 @@ static int wpa_driver_nl80211_set_operst static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; struct nl80211_sta_flag_update upd; @@ -3718,7 +3715,7 @@ static int wpa_driver_nl80211_set_supp_p 0, NL80211_CMD_SET_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); + if_nametoindex(bss->ifname)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid); os_memset(&upd, 0, sizeof(upd)); @@ -3735,20 +3732,6 @@ static int wpa_driver_nl80211_set_supp_p #ifdef HOSTAPD -static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv, - int ifindex) -{ - struct i802_bss *bss = &drv->bss; - while (bss) { - if (ifindex == bss->ifindex) - return bss; - bss = bss->next; - } - wpa_printf(MSG_DEBUG, "nl80211: get_bss(%d) failed", ifindex); - return NULL; -} - - static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) { int i; @@ -3842,7 +3825,8 @@ static int get_key_handler(struct nl_msg static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, int idx, u8 *seq) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; msg = nlmsg_alloc(); @@ -3868,7 +3852,8 @@ static int i802_get_seqnum(const char *i static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, int mode) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; u8 rates[NL80211_MAX_SUPP_RATES]; u8 rates_len = 0; @@ -3887,7 +3872,7 @@ static int i802_set_rate_sets(void *priv NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); /* TODO: multi-BSS support */ - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: @@ -3898,7 +3883,8 @@ static int i802_set_rate_sets(void *priv /* Set kernel driver on given frequency (MHz) */ static int i802_set_freq(void *priv, struct hostapd_freq_params *freq) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; return wpa_driver_nl80211_set_freq(drv, freq->freq, freq->ht_enabled, freq->sec_channel_offset); } @@ -3906,7 +3892,8 @@ static int i802_set_freq(void *priv, str static int i802_set_rts(void *priv, int rts) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret = -ENOBUFS; u32 val; @@ -3937,7 +3924,8 @@ nla_put_failure: static int i802_set_frag(void *priv, int frag) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret = -ENOBUFS; u32 val; @@ -3968,7 +3956,8 @@ nla_put_failure: static int i802_flush(void *priv) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; msg = nlmsg_alloc(); @@ -3982,7 +3971,7 @@ static int i802_flush(void *priv) * XXX: FIX! this needs to flush all VLANs too */ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); + if_nametoindex(bss->ifname)); return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: @@ -4044,7 +4033,8 @@ static int get_sta_handler(struct nl_msg static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, const u8 *addr) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; os_memset(data, 0, sizeof(*data)); @@ -4056,7 +4046,7 @@ static int i802_read_sta_data(void *priv 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->ifname)); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); return send_and_recv_msgs(drv, msg, get_sta_handler, data); nla_put_failure: @@ -4067,7 +4057,8 @@ static int i802_read_sta_data(void *priv static int i802_set_tx_queue_params(void *priv, int queue, int aifs, int cw_min, int cw_max, int burst_time) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; struct nlattr *txq, *params; @@ -4078,7 +4069,7 @@ static int i802_set_tx_queue_params(void genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_WIPHY, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); if (!txq) @@ -4110,7 +4101,8 @@ static int i802_set_tx_queue_params(void static int i802_set_bss(void *priv, int cts, int preamble, int slot) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; msg = nlmsg_alloc(); @@ -4128,7 +4120,7 @@ static int i802_set_bss(void *priv, int NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); /* TODO: multi-BSS support */ - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: @@ -4157,7 +4149,8 @@ static int i802_set_short_slot_time(void static int i802_set_sta_vlan(void *priv, const u8 *addr, const char *ifname, int vlan_id) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; msg = nlmsg_alloc(); @@ -4168,7 +4161,7 @@ static int i802_set_sta_vlan(void *priv, 0, NL80211_CMD_SET_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); + if_nametoindex(bss->ifname)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname)); @@ -4181,18 +4174,19 @@ static int i802_set_sta_vlan(void *priv, static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; char name[16]; - os_snprintf(name, sizeof(name), "%s.sta%d", drv->ifname, aid); + os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); if (val) { - if (nl80211_create_iface(priv, name, NL80211_IFTYPE_AP_VLAN, + if (nl80211_create_iface(drv, name, NL80211_IFTYPE_AP_VLAN, NULL, 1) < 0) return -1; linux_set_iface_flags(drv->ioctl_sock, name, 1); return i802_set_sta_vlan(priv, addr, name, 0); } else { - i802_set_sta_vlan(priv, addr, drv->ifname, 0); + i802_set_sta_vlan(priv, addr, bss->ifname, 0); return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN, name); } @@ -4244,7 +4238,8 @@ static int i802_sta_clear_stats(void *pr static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct ieee80211_mgmt mgmt; memset(&mgmt, 0, sizeof(mgmt)); @@ -4254,7 +4249,7 @@ static int i802_sta_deauth(void *priv, c memcpy(mgmt.sa, own_addr, ETH_ALEN); memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.deauth.reason_code = host_to_le16(reason); - return wpa_driver_nl80211_send_mlme(drv, (u8 *) &mgmt, + return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, IEEE80211_HDRLEN + sizeof(mgmt.u.deauth)); } @@ -4263,7 +4258,8 @@ static int i802_sta_deauth(void *priv, c static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, int reason) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct ieee80211_mgmt mgmt; memset(&mgmt, 0, sizeof(mgmt)); @@ -4273,7 +4269,7 @@ static int i802_sta_disassoc(void *priv, memcpy(mgmt.sa, own_addr, ETH_ALEN); memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.disassoc.reason_code = host_to_le16(reason); - return wpa_driver_nl80211_send_mlme(drv, (u8 *) &mgmt, + return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, IEEE80211_HDRLEN + sizeof(mgmt.u.disassoc)); } @@ -4335,17 +4331,17 @@ static void *i802_init(struct hostapd_da struct wpa_init_params *params) { struct wpa_driver_nl80211_data *drv; + struct i802_bss *bss; size_t i; char brname[IFNAMSIZ]; int ifindex, br_ifindex; int br_added = 0; - drv = wpa_driver_nl80211_init(hapd, params->ifname); - if (drv == NULL) + bss = wpa_driver_nl80211_init(hapd, params->ifname); + if (bss == NULL) return NULL; - drv->bss.ifindex = drv->ifindex; - + drv = bss->drv; if (linux_br_get(brname, params->ifname) == 0) { wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s", params->ifname, brname); @@ -4373,18 +4369,18 @@ static void *i802_init(struct hostapd_da /* start listening for EAPOL on the default AP interface */ add_ifidx(drv, drv->ifindex); - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0)) + if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0)) goto failed; if (params->bssid) { - if (linux_set_ifhwaddr(drv->ioctl_sock, drv->ifname, + if (linux_set_ifhwaddr(drv->ioctl_sock, bss->ifname, params->bssid)) goto failed; } - if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_AP)) { + if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) { wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " - "into AP mode", drv->ifname); + "into AP mode", bss->ifname); goto failed; } @@ -4392,7 +4388,7 @@ static void *i802_init(struct hostapd_da i802_check_bridge(drv, params->bridge[0], params->ifname) < 0) goto failed; - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) + if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) goto failed; drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); @@ -4407,10 +4403,10 @@ static void *i802_init(struct hostapd_da goto failed; } - if (linux_get_ifhwaddr(drv->ioctl_sock, drv->ifname, params->own_addr)) + if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, params->own_addr)) goto failed; - return drv; + return bss; failed: nl80211_remove_monitor_interface(drv); @@ -4453,27 +4449,30 @@ static enum nl80211_iftype wpa_driver_nl static int wpa_driver_nl80211_if_add(const char *iface, void *priv, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, - void *bss_ctx) + void *bss_ctx, void **drv_priv) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ifidx; #ifdef HOSTAPD - struct i802_bss *bss = NULL; + struct i802_bss *new_bss = NULL; if (type == WPA_IF_AP_BSS) { - bss = os_zalloc(sizeof(*bss)); - if (bss == NULL) + new_bss = os_zalloc(sizeof(*new_bss)); + if (new_bss == NULL) return -1; } -#endif /* HOSTAPD */ +#endif ifidx = nl80211_create_iface(drv, ifname, wpa_driver_nl80211_if_type(type), addr, 0); + if (ifidx < 0) { #ifdef HOSTAPD - os_free(bss); -#endif /* HOSTAPD */ + if (type == WPA_IF_AP_BSS) + os_free(new_bss); +#endif return -1; } @@ -4481,12 +4480,15 @@ static int wpa_driver_nl80211_if_add(con if (type == WPA_IF_AP_BSS) { if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) { nl80211_remove_iface(drv, ifidx); - os_free(bss); + os_free(new_bss); return -1; } - bss->ifindex = ifidx; - bss->next = drv->bss.next; - drv->bss.next = bss; + strncpy(new_bss->ifname, ifname, IFNAMSIZ); + new_bss->ifindex = ifidx; + new_bss->drv = drv; + new_bss->next = drv->first_bss.next; + drv->first_bss.next = new_bss; + *drv_priv = new_bss; } #endif /* HOSTAPD */ @@ -4498,27 +4500,27 @@ static int wpa_driver_nl80211_if_remove( enum wpa_driver_if_type type, const char *ifname) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; int ifindex = if_nametoindex(ifname); nl80211_remove_iface(drv, ifindex); -#ifdef HOSTAPD - if (type == WPA_IF_AP_BSS) { - struct i802_bss *bss, *prev; - prev = &drv->bss; - bss = drv->bss.next; - while (bss) { - if (ifindex == bss->ifindex) { - prev->next = bss->next; - os_free(bss); - break; - } - prev = bss; - bss = bss->next; + if (type != WPA_IF_AP_BSS) + return 0; + + if (bss != &drv->first_bss) { + struct i802_bss *tbss = &drv->first_bss; + + while (tbss) { + if (tbss->next != bss) + continue; + + tbss->next = bss->next; + os_free(bss); + break; } } -#endif /* HOSTAPD */ return 0; } @@ -4540,7 +4542,8 @@ static int cookie_handler(struct nl_msg static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, unsigned int duration) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret; u64 cookie; @@ -4574,7 +4577,8 @@ nla_put_failure: static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret; @@ -4629,7 +4633,8 @@ static void wpa_driver_nl80211_probe_req static int wpa_driver_nl80211_probe_req_report(void *priv, int report) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (drv->nlmode != NL80211_IFTYPE_STATION) { wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only " @@ -4666,9 +4671,10 @@ static int wpa_driver_nl80211_probe_req_ static int wpa_driver_nl80211_alloc_interface_addr(void *priv, u8 *addr) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; - if (linux_get_ifhwaddr(drv->ioctl_sock, drv->ifname, addr) < 0) + if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, addr) < 0) return -1; if (addr[0] & 0x02) { @@ -4738,7 +4744,8 @@ nla_put_failure: static int wpa_driver_nl80211_disable_11b_rates(void *priv, int disabled) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; drv->disable_11b_rates = disabled; return nl80211_disable_11b_rates(drv, drv->ifindex, disabled); } @@ -4746,11 +4753,12 @@ static int wpa_driver_nl80211_disable_11 static int wpa_driver_nl80211_deinit_ap(void *priv) { - struct wpa_driver_nl80211_data *drv = priv; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; if (drv->nlmode != NL80211_IFTYPE_AP) return -1; wpa_driver_nl80211_del_beacon(drv); - return wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA); + return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); } --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1472,11 +1472,12 @@ struct wpa_driver_ops { * @addr: Local address to use for the interface or %NULL to use the * parent interface address * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces + * @drv_priv: Pointer for overwriting the driver context * Returns: 0 on success, -1 on failure */ int (*if_add)(const char *iface, void *priv, enum wpa_driver_if_type type, const char *ifname, - const u8 *addr, void *bss_ctx); + const u8 *addr, void *bss_ctx, void **drv_priv); /** * if_remove - Remove a virtual interface --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -1030,7 +1030,7 @@ static int test_driver_bss_remove(void * static int test_driver_if_add(const char *iface, void *priv, enum wpa_driver_if_type type, const char *ifname, - const u8 *addr, void *bss_ctx) + const u8 *addr, void *bss_ctx, void **drv_priv) { wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s bss_ctx=%p)", __func__, iface, type, ifname, bss_ctx); --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -242,7 +242,8 @@ static int hostapd_set_beacon(const char static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) { - return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL); + return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, + &hapd->drv_priv); } static int hostapd_vlan_if_remove(struct hostapd_data *hapd, @@ -407,12 +408,13 @@ int hostapd_set_ssid(struct hostapd_data int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, void *bss_ctx) + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv) { if (hapd->driver == NULL || hapd->driver->if_add == NULL) return -1; return hapd->driver->if_add(hapd->conf->iface, hapd->drv_priv, type, - ifname, addr, bss_ctx); + ifname, addr, bss_ctx, drv_priv); } --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -26,7 +26,8 @@ int hostapd_set_generic_elem(struct host int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, void *bss_ctx); + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv); int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, const char *ifname); int hostapd_set_ieee8021x(struct hostapd_data *hapd, --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -484,7 +484,8 @@ static int hostapd_setup_bss(struct host hapd->interface_added = 1; if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, - hapd->conf->iface, hapd->own_addr, hapd)) { + hapd->conf->iface, hapd->own_addr, hapd, + &hapd->drv_priv)) { wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" MACSTR ")", MAC2STR(hapd->own_addr)); return -1;