X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;ds=sidebyside;f=hostapd%2Fdriver_nl80211.c;h=508a37922aada2b62eac933e1b98427daf69be14;hb=6fa68a0ee550c6659ff426290ecdee4d425155b1;hp=515af765e99346588f37774114f7ce88a4c9dedb;hpb=6773de39b1f2ca33300af469bf28ad150202de89;p=wpasupplicant diff --git a/hostapd/driver_nl80211.c b/hostapd/driver_nl80211.c index 515af76..508a379 100644 --- a/hostapd/driver_nl80211.c +++ b/hostapd/driver_nl80211.c @@ -23,23 +23,28 @@ #include #include #include -#include +#include "nl80211_copy.h" #include -#include -#include /* The L2 protocols */ +#include #include "wireless_copy.h" #include #include "hostapd.h" #include "driver.h" -#include "ieee802_1x.h" #include "eloop.h" -#include "ieee802_11.h" -#include "sta_info.h" #include "hw_features.h" #include "mlme.h" #include "radiotap.h" #include "radiotap_iter.h" +#include "ieee802_11_defs.h" + +#ifdef CONFIG_LIBNL20 +/* libnl 2.0 compatibility code */ +#define nl_handle_alloc_cb nl_socket_alloc_cb +#define nl_handle_destroy nl_socket_free +#endif /* CONFIG_LIBNL20 */ + +static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; enum ieee80211_msg_type { ieee80211_msg_normal = 0, @@ -70,9 +75,16 @@ struct i802_driver_data { int dtim_period, beacon_int; unsigned int beacon_set:1; unsigned int ieee802_1x_active:1; + + int last_freq; + int last_freq_ht; }; +static int i802_sta_deauth(void *priv, const u8 *addr, int reason); +static int i802_sta_disassoc(void *priv, const u8 *addr, int reason); + + static void add_ifidx(struct i802_driver_data *drv, int ifidx) { int i; @@ -135,15 +147,62 @@ static int have_ifidx(struct i802_driver_data *drv, int ifidx) } -/* helper for netlink get routines */ -static int ack_wait_handler(struct nl_msg *msg, void *arg) +/* nl80211 code */ +static int ack_handler(struct nl_msg *msg, void *arg) { - int *finished = arg; - - *finished = 1; + int *err = arg; + *err = 0; return NL_STOP; } +static int finish_handler(struct nl_msg *msg, void *arg) +{ + int *ret = arg; + *ret = 0; + return NL_SKIP; +} + +static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, + void *arg) +{ + int *ret = arg; + *ret = err->error; + return NL_SKIP; +} + +static int send_and_recv_msgs(struct i802_driver_data *drv, + struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) +{ + struct nl_cb *cb; + int err = -ENOMEM; + + cb = nl_cb_clone(drv->nl_cb); + if (!cb) + goto out; + + err = nl_send_auto_complete(drv->nl_handle, msg); + if (err < 0) + goto out; + + err = 1; + + nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + + if (valid_handler) + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, + valid_handler, valid_data); + + while (err > 0) + nl_recvmsgs(drv->nl_handle, cb); + out: + nl_cb_put(cb); + nlmsg_free(msg); + return err; +} static int hostapd_set_iface_flags(struct i802_driver_data *drv, const char *ifname, int dev_up) @@ -182,12 +241,11 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv, size_t key_len, int txkey) { struct nl_msg *msg; - int ret = -1; - int err = 0; + int ret; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; if (strcmp(alg, "none") == 0) { genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, @@ -212,7 +270,8 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv, else { wpa_printf(MSG_ERROR, "%s: Unsupported encryption " "algorithm '%s'", __func__, alg); - goto out; + nlmsg_free(msg); + return -1; } } @@ -221,56 +280,36 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv, NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - (err = nl_wait_for_ack(drv->nl_handle)) < 0) { - if (err != -ENOENT) { - ret = 0; - goto out; - } - } + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret == -ENOENT) + ret = 0; /* - * If we need to set the default TX key we do that below, - * otherwise we're done here. + * If we failed or don't need to set the default TX key (below), + * we're done here. */ - if (!txkey || addr) { - ret = 0; - goto out; - } - - nlmsg_free(msg); + if (ret || !txkey || addr) + return ret; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_KEY, 0); NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); -#ifdef NL80211_MFP_PENDING if (strcmp(alg, "IGTK") == 0) NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT); else NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); -#else /* NL80211_MFP_PENDING */ - NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); -#endif /* NL80211_MFP_PENDING */ - - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - (err = nl_wait_for_ack(drv->nl_handle)) < 0) { - if (err != -ENOENT) { - ret = 0; - goto out; - } - } - - ret = 0; - out: - nla_put_failure: - nlmsg_free(msg); + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret == -ENOENT) + ret = 0; return ret; + nla_put_failure: + return -ENOBUFS; } @@ -286,11 +325,6 @@ static int i802_set_encryption(const char *iface, void *priv, const char *alg, if (ret < 0) return ret; - if (strcmp(alg, "IGTK") == 0) { - ret = nl_set_encr(drv->monitor_ifidx, drv, alg, addr, idx, key, - key_len, txkey); - } - return ret; } @@ -329,14 +363,10 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, { struct i802_driver_data *drv = priv; struct nl_msg *msg; - struct nl_cb *cb = NULL; - int ret = -1; - int err = 0; - int finished = 0; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_GET_KEY, 0); @@ -346,62 +376,41 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); - cb = nl_cb_clone(drv->nl_cb); - if (!cb) - goto out; - memset(seq, 0, 6); - if (nl_send_auto_complete(drv->nl_handle, msg) < 0) - goto out; - - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_key_handler, seq); - 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); + return send_and_recv_msgs(drv, msg, get_key_handler, seq); nla_put_failure: - nlmsg_free(msg); - return ret; + return -ENOBUFS; } static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, int mode) { - return -1; -} + struct i802_driver_data *drv = priv; + struct nl_msg *msg; + u8 rates[NL80211_MAX_SUPP_RATES]; + u8 rates_len = 0; + int i; + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; -static int i802_set_ssid(const char *ifname, void *priv, const u8 *buf, - int len) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, + NL80211_CMD_SET_BSS, 0); - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len; + for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++) + rates[rates_len++] = basic_rates[i] / 5; - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } + NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); - return 0; + /* TODO: multi-BSS support */ + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + return -ENOBUFS; } @@ -447,26 +456,70 @@ static int i802_send_frame(void *priv, const void *data, size_t len, static int i802_send_mgmt_frame(void *priv, const void *data, size_t len, int flags) { - return i802_send_frame(priv, data, len, 1, flags); + struct ieee80211_mgmt *mgmt; + int do_not_encrypt = 0; + u16 fc; + + mgmt = (struct ieee80211_mgmt *) data; + fc = le_to_host16(mgmt->frame_control); + + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { + /* + * Only one of the authentication frame types is encrypted. + * In order for static WEP encryption to work properly (i.e., + * to not encrypt the frame), we need to tell mac80211 about + * the frames that must not be encrypted. + */ + u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg); + u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction); + if (auth_alg == WLAN_AUTH_OPEN || + (auth_alg == WLAN_AUTH_SHARED_KEY && auth_trans != 3)) + do_not_encrypt = 1; + } + + return i802_send_frame(priv, data, len, !do_not_encrypt, flags); } /* Set kernel driver on given frequency (MHz) */ -static int i802_set_freq(void *priv, int mode, int freq) +static int i802_set_freq2(void *priv, struct hostapd_freq_params *freq) { struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - iwr.u.freq.m = freq; - iwr.u.freq.e = 6; + struct nl_msg *msg; - if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { - perror("ioctl[SIOCSIWFREQ]"); + msg = nlmsg_alloc(); + if (!msg) return -1; + + drv->last_freq = freq->freq; + drv->last_freq_ht = freq->ht_enabled; + + 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->iface)); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq); + if (freq->ht_enabled) { + switch (freq->sec_channel_offset) { + case -1: + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + NL80211_CHAN_HT40MINUS); + break; + case 1: + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + NL80211_CHAN_HT40PLUS); + break; + default: + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + NL80211_CHAN_HT20); + break; + } } - return 0; + if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) + return 0; + nla_put_failure: + return -1; } @@ -476,7 +529,7 @@ static int i802_set_rts(void *priv, int rts) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); iwr.u.rts.value = rts; iwr.u.rts.fixed = 1; @@ -495,7 +548,7 @@ static int i802_get_rts(void *priv, int *rts) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &iwr) < 0) { perror("ioctl[SIOCGIWRTS]"); @@ -514,7 +567,7 @@ static int i802_set_frag(void *priv, int frag) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); iwr.u.frag.value = frag; iwr.u.frag.fixed = 1; @@ -533,7 +586,7 @@ static int i802_get_frag(void *priv, int *frag) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIWFRAG, &iwr) < 0) { perror("ioctl[SIOCGIWFRAG]"); @@ -552,18 +605,18 @@ static int i802_set_retry(void *priv, int short_retry, int long_retry) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); iwr.u.retry.value = short_retry; iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) { + if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { perror("ioctl[SIOCSIWRETRY(short)]"); return -1; } iwr.u.retry.value = long_retry; iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) { + if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { perror("ioctl[SIOCSIWRETRY(long)]"); return -1; } @@ -578,7 +631,7 @@ static int i802_get_retry(void *priv, int *short_retry, int *long_retry) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) { @@ -602,11 +655,10 @@ static int i802_flush(void *priv) { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; msg = nlmsg_alloc(); if (!msg) - goto out; + return -1; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_STATION, 0); @@ -617,18 +669,9 @@ static int i802_flush(void *priv) 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; - } - + return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: - nlmsg_free(msg); - - out: - return ret; + return -ENOBUFS; } @@ -680,14 +723,10 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, { struct i802_driver_data *drv = priv; struct nl_msg *msg; - struct nl_cb *cb = NULL; - int ret = -1; - int err = 0; - int finished = 0; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_GET_STATION, 0); @@ -695,32 +734,9 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - cb = nl_cb_clone(drv->nl_cb); - 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); + return send_and_recv_msgs(drv, msg, get_sta_handler, data); nla_put_failure: - nlmsg_free(msg); - return ret; - + return -ENOBUFS; } @@ -797,11 +813,11 @@ static int i802_sta_add2(const char *ifname, void *priv, { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; + int ret = -ENOBUFS; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_NEW_STATION, 0); @@ -816,28 +832,17 @@ static int i802_sta_add2(const char *ifname, void *priv, params->listen_interval); #ifdef CONFIG_IEEE80211N -#ifdef NL80211_ATTR_HT_CAPABILITY if (params->ht_capabilities) { NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, params->ht_capabilities->length, ¶ms->ht_capabilities->data); } -#endif /* NL80211_ATTR_HT_CAPABILITY */ #endif /* CONFIG_IEEE80211N */ - ret = nl_send_auto_complete(drv->nl_handle, msg); - if (ret < 0) - goto nla_put_failure; - - ret = nl_wait_for_ack(drv->nl_handle); - /* ignore EEXIST, this happens if a STA associates while associated */ - if (ret == -EEXIST || ret >= 0) + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret == -EEXIST) ret = 0; - nla_put_failure: - nlmsg_free(msg); - - out: return ret; } @@ -846,11 +851,11 @@ static int i802_sta_remove(void *priv, const u8 *addr) { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; + int ret; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_STATION, 0); @@ -859,18 +864,12 @@ static int i802_sta_remove(void *priv, const u8 *addr) 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: + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret == -ENOENT) + return 0; return ret; + nla_put_failure: + return -ENOBUFS; } @@ -879,15 +878,16 @@ static int i802_sta_set_flags(void *priv, const u8 *addr, { struct i802_driver_data *drv = priv; struct nl_msg *msg, *flags = NULL; - int ret = -1; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; flags = nlmsg_alloc(); - if (!flags) - goto free_msg; + if (!flags) { + nlmsg_free(msg); + return -ENOMEM; + } genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_STATION, 0); @@ -905,49 +905,61 @@ static int i802_sta_set_flags(void *priv, const u8 *addr, if (total_flags & WLAN_STA_SHORT_PREAMBLE) NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); -#ifdef NL80211_MFP_PENDING if (total_flags & WLAN_STA_MFP) NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); -#endif /* NL80211_MFP_PENDING */ 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; + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + nlmsg_free(flags); + return -ENOBUFS; } -static int i802_set_channel_flag(void *priv, int mode, int chan, int flag, - unsigned char power_level, - unsigned char antenna_max) +static int i802_set_tx_queue_params(void *priv, int queue, int aifs, + int cw_min, int cw_max, int burst_time) { - return -1; -} + struct i802_driver_data *drv = priv; + struct nl_msg *msg; + struct nlattr *txq, *params; + msg = nlmsg_alloc(); + if (!msg) + return -1; -static int i802_set_regulatory_domain(void *priv, unsigned int rd) -{ - return -1; -} + 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->iface)); -static int i802_set_tx_queue_params(void *priv, int queue, int aifs, - int cw_min, int cw_max, int burst_time) -{ + txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); + if (!txq) + goto nla_put_failure; + + /* We are only sending parameters for a single TXQ at a time */ + params = nla_nest_start(msg, 1); + if (!params) + goto nla_put_failure; + + NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, queue); + /* Burst time is configured in units of 0.1 msec and TXOP parameter in + * 32 usec, so need to convert the value here. */ + NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32); + NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min); + NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max); + NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs); + + nla_nest_end(msg, params); + + nla_nest_end(msg, txq); + + if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) + return 0; + nla_put_failure: return -1; } @@ -966,11 +978,11 @@ static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx) genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_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); + + if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) + return; + nla_put_failure: + printf("Failed to remove interface.\n"); } @@ -983,6 +995,7 @@ static int nl80211_create_iface(struct i802_driver_data *drv, int ifidx; struct ifreq ifreq; struct iwreq iwr; + int ret = -ENOBUFS; msg = nlmsg_alloc(); if (!msg) @@ -990,8 +1003,7 @@ static int nl80211_create_iface(struct i802_driver_data *drv, genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_NEW_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->hapd->conf->iface)); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); @@ -1012,16 +1024,13 @@ static int nl80211_create_iface(struct i802_driver_data *drv, goto nla_put_failure; } - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - nl_wait_for_ack(drv->nl_handle) < 0) { + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) { nla_put_failure: printf("Failed to create interface %s.\n", ifname); - nlmsg_free(msg); - return -1; + return ret; } - nlmsg_free(msg); - ifidx = if_nametoindex(ifname); if (ifidx <= 0) @@ -1096,11 +1105,11 @@ static int i802_set_beacon(const char *iface, void *priv, struct i802_driver_data *drv = priv; struct nl_msg *msg; u8 cmd = NL80211_CMD_NEW_BEACON; - int ret = -1; + int ret; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; if (drv->beacon_set) cmd = NL80211_CMD_SET_BEACON; @@ -1116,44 +1125,30 @@ static int i802_set_beacon(const char *iface, void *priv, 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); + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (!ret) + drv->beacon_set = 1; return ret; + nla_put_failure: + return -ENOBUFS; } static int i802_del_beacon(struct i802_driver_data *drv) { struct nl_msg *msg; - int ret = -1; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; 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: + return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: - nlmsg_free(msg); - return ret; + return -ENOBUFS; } @@ -1197,7 +1192,6 @@ static int i802_set_beacon_int(void *priv, int value) { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; drv->beacon_int = value; @@ -1206,7 +1200,7 @@ static int i802_set_beacon_int(void *priv, int value) msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_BEACON, 0); @@ -1214,16 +1208,9 @@ static int i802_set_beacon_int(void *priv, int value) 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: + return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: - nlmsg_free(msg); - return ret; + return -ENOBUFS; } @@ -1231,11 +1218,10 @@ static int i802_set_dtim_period(const char *iface, void *priv, int value) { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_BEACON, 0); @@ -1244,29 +1230,20 @@ static int i802_set_dtim_period(const char *iface, void *priv, int value) 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: + return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: - nlmsg_free(msg); - return ret; + return -ENOBUFS; } static int i802_set_bss(void *priv, int cts, int preamble, int slot) { -#ifdef NL80211_CMD_SET_BSS struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_BSS, 0); @@ -1278,24 +1255,12 @@ static int i802_set_bss(void *priv, int cts, int preamble, int slot) if (slot >= 0) NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); - ret = 0; - /* TODO: multi-BSS support */ 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) { - ret = -1; - } - -nla_put_failure: - nlmsg_free(msg); - -out: - return ret; -#else /* NL80211_CMD_SET_BSS */ - return -1; -#endif /* NL80211_CMD_SET_BSS */ + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + return -ENOBUFS; } @@ -1358,7 +1323,6 @@ static int i802_if_remove(void *priv, enum hostapd_driver_if_type type, struct phy_info_arg { u16 *num_modes; struct hostapd_hw_modes *modes; - int error; }; static int phy_info_handler(struct nl_msg *msg, void *arg) @@ -1376,6 +1340,7 @@ static int phy_info_handler(struct nl_msg *msg, void *arg) [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, }; struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; @@ -1433,9 +1398,7 @@ static int phy_info_handler(struct nl_msg *msg, void *arg) continue; mode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - mode->channels[idx].flag |= HOSTAPD_CHAN_W_SCAN | - HOSTAPD_CHAN_W_ACTIVE_SCAN | - HOSTAPD_CHAN_W_IBSS; + mode->channels[idx].flag = 0; if (!mode_is_set) { /* crude heuristic */ @@ -1456,11 +1419,23 @@ static int phy_info_handler(struct nl_msg *msg, void *arg) mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000; if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) - mode->channels[idx].flag &= ~HOSTAPD_CHAN_W_SCAN; + mode->channels[idx].flag |= + HOSTAPD_CHAN_DISABLED; if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) - mode->channels[idx].flag &= ~HOSTAPD_CHAN_W_ACTIVE_SCAN; + mode->channels[idx].flag |= + HOSTAPD_CHAN_PASSIVE_SCAN; if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS]) - mode->channels[idx].flag &= ~HOSTAPD_CHAN_W_IBSS; + mode->channels[idx].flag |= + HOSTAPD_CHAN_NO_IBSS; + if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) + mode->channels[idx].flag |= + HOSTAPD_CHAN_RADAR; + + if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && + !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) + mode->channels[idx].max_tx_power = + nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100; + idx++; } @@ -1497,24 +1472,92 @@ static int phy_info_handler(struct nl_msg *msg, void *arg) } } - phy_info->error = 0; - return NL_SKIP; } +static struct hostapd_hw_modes *i802_add_11b(struct hostapd_hw_modes *modes, + u16 *num_modes) +{ + u16 m; + struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; + int i, mode11g_idx = -1; + + /* If only 802.11g mode is included, use it to construct matching + * 802.11b mode data. */ + + for (m = 0; m < *num_modes; m++) { + if (modes[m].mode == HOSTAPD_MODE_IEEE80211B) + return modes; /* 802.11b already included */ + if (modes[m].mode == HOSTAPD_MODE_IEEE80211G) + mode11g_idx = m; + } + + if (mode11g_idx < 0) + return modes; /* 2.4 GHz band not supported at all */ + + nmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes)); + if (nmodes == NULL) + return modes; /* Could not add 802.11b mode */ + + mode = &nmodes[*num_modes]; + os_memset(mode, 0, sizeof(*mode)); + (*num_modes)++; + modes = nmodes; + + mode->mode = HOSTAPD_MODE_IEEE80211B; + + mode11g = &modes[mode11g_idx]; + mode->num_channels = mode11g->num_channels; + mode->channels = os_malloc(mode11g->num_channels * + sizeof(struct hostapd_channel_data)); + if (mode->channels == NULL) { + (*num_modes)--; + return modes; /* Could not add 802.11b mode */ + } + os_memcpy(mode->channels, mode11g->channels, + mode11g->num_channels * sizeof(struct hostapd_channel_data)); + + mode->num_rates = 0; + mode->rates = os_malloc(4 * sizeof(struct hostapd_rate_data)); + if (mode->rates == NULL) { + os_free(mode->channels); + (*num_modes)--; + return modes; /* Could not add 802.11b mode */ + } + + for (i = 0; i < mode11g->num_rates; i++) { + if (mode11g->rates[i].rate > 110 || + mode11g->rates[i].flags & + (HOSTAPD_RATE_ERP | HOSTAPD_RATE_OFDM)) + continue; + mode->rates[mode->num_rates] = mode11g->rates[i]; + mode->num_rates++; + if (mode->num_rates == 4) + break; + } + + if (mode->num_rates == 0) { + os_free(mode->channels); + os_free(mode->rates); + (*num_modes)--; + return modes; /* No 802.11b rates */ + } + + wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g " + "information"); + + return modes; +} + static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int err = -1; - struct nl_cb *cb = NULL; - int finished = 0; struct phy_info_arg result = { .num_modes = num_modes, .modes = NULL, - .error = 1, }; *num_modes = 0; @@ -1529,33 +1572,10 @@ static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv, NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - cb = nl_cb_clone(drv->nl_cb); - 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, phy_info_handler, &result); - 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 || result.error) { - hostapd_free_hw_features(result.modes, *num_modes); - result.modes = NULL; - } - - out: - nl_cb_put(cb); + if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) + return i802_add_11b(result.modes, num_modes); nla_put_failure: - if (err) - fprintf(stderr, "failed to get information: %d\n", err); - nlmsg_free(msg); - return result.modes; + return NULL; } @@ -1564,11 +1584,10 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr, { struct i802_driver_data *drv = priv; struct nl_msg *msg; - int ret = -1; msg = nlmsg_alloc(); if (!msg) - goto out; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_STATION, 0); @@ -1579,38 +1598,33 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr, NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(ifname)); - ret = 0; - - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - (errno = nl_wait_for_ack(drv->nl_handle) < 0)) { - ret = -1; - } - + return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: - nlmsg_free(msg); - - out: - return ret; + return -ENOBUFS; } -static void handle_unknown_sta(struct hostapd_data *hapd, u8 *ta) +static int i802_set_country(void *priv, const char *country) { - struct sta_info *sta; + struct i802_driver_data *drv = priv; + struct nl_msg *msg; + char alpha2[3]; - sta = ap_get_sta(hapd, ta); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data/PS-poll frame from not associated STA " - MACSTR "\n", MAC2STR(ta)); - if (sta && (sta->flags & WLAN_STA_AUTH)) - hostapd_sta_disassoc( - hapd, ta, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - else - hostapd_sta_deauth( - hapd, ta, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_REQ_SET_REG, 0); + + alpha2[0] = country[0]; + alpha2[1] = country[1]; + alpha2[2] = '\0'; + NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + return -ENOBUFS; } @@ -1619,7 +1633,6 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, { struct ieee80211_hdr *hdr; u16 fc, type, stype; - struct sta_info *sta; hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); @@ -1631,7 +1644,7 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, case WLAN_FC_TYPE_MGMT: wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s", ok ? "ACK" : "fail"); - ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); + hostapd_mgmt_tx_cb(hapd, buf, len, stype, ok); break; case WLAN_FC_TYPE_CTRL: wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s", @@ -1640,16 +1653,7 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, case WLAN_FC_TYPE_DATA: wpa_printf(MSG_DEBUG, "DATA (TX callback) %s", ok ? "ACK" : "fail"); - sta = ap_get_sta(hapd, hdr->addr1); - if (sta && sta->flags & WLAN_STA_PENDING_POLL) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " - "activity poll", MAC2STR(sta->addr), - ok ? "ACKed" : "did not ACK"); - if (ok) - sta->flags &= ~WLAN_STA_PENDING_POLL; - } - if (sta) - ieee802_1x_tx_status(hapd, sta, buf, len, ok); + hostapd_tx_status(hapd, hdr->addr1, buf, len, ok); break; default: printf("unknown TX callback frame type %d\n", type); @@ -1658,7 +1662,8 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, } -static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len, +static void handle_frame(struct i802_driver_data *drv, + struct hostapd_iface *iface, u8 *buf, size_t len, struct hostapd_frame_info *hfi, enum ieee80211_msg_type msg_type) { @@ -1756,19 +1761,18 @@ static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len, wpa_printf(MSG_MSGDUMP, "MGMT"); if (broadcast_bssid) { for (i = 0; i < iface->num_bss; i++) - ieee802_11_mgmt(iface->bss[i], buf, data_len, + hostapd_mgmt_rx(iface->bss[i], buf, data_len, stype, hfi); } else - ieee802_11_mgmt(hapd, buf, data_len, stype, hfi); + hostapd_mgmt_rx(hapd, buf, data_len, stype, hfi); break; case WLAN_FC_TYPE_CTRL: /* can only get here with PS-Poll frames */ wpa_printf(MSG_DEBUG, "CTRL"); - handle_unknown_sta(hapd, hdr->addr2); + hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2); break; case WLAN_FC_TYPE_DATA: - wpa_printf(MSG_DEBUG, "DATA"); - handle_unknown_sta(hapd, hdr->addr2); + hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2); break; } } @@ -1791,7 +1795,7 @@ static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) } if (have_ifidx(drv, lladdr.sll_ifindex)) - ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len); + hostapd_eapol_receive(hapd, lladdr.sll_addr, buf, len); } @@ -1867,7 +1871,7 @@ static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) else msg_type = ieee80211_msg_tx_callback_ack; - handle_frame(hapd->iface, buf + iter.max_length, + handle_frame(drv, hapd->iface, buf + iter.max_length, len - iter.max_length, &hfi, msg_type); } @@ -1931,10 +1935,11 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv, const char *ifname) { struct nl_msg *msg; + int ret = -ENOBUFS; msg = nlmsg_alloc(); if (!msg) - return -1; + return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_INTERFACE, 0); @@ -1942,18 +1947,13 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv, if_nametoindex(ifname)); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP); - if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || - nl_wait_for_ack(drv->nl_handle) < 0) { + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (!ret) + return 0; nla_put_failure: - wpa_printf(MSG_ERROR, "Failed to set interface %s to master " - "mode.", ifname); - nlmsg_free(msg); - return -1; - } - - nlmsg_free(msg); - - return 0; + wpa_printf(MSG_ERROR, "Failed to set interface %s to master " + "mode.", ifname); + return ret; } @@ -1962,8 +1962,6 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid) struct ifreq ifr; struct sockaddr_ll addr; - drv->ioctl_sock = -1; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); if (drv->ioctl_sock < 0) { perror("socket[PF_INET,SOCK_DGRAM]"); @@ -2007,11 +2005,18 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid) return -1; } +#ifdef CONFIG_LIBNL20 + if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) { + printf("Failed to allocate generic netlink cache.\n"); + return -1; + } +#else /* CONFIG_LIBNL20 */ drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); if (!drv->nl_cache) { printf("Failed to allocate generic netlink cache.\n"); return -1; } +#endif /* CONFIG_LIBNL20 */ drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); if (!drv->nl80211) { @@ -2024,10 +2029,10 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid) return -1; if (nl80211_set_master_mode(drv, drv->iface)) - return -1; + goto fail1; if (hostapd_set_iface_flags(drv, drv->iface, 1)) - return -1; + goto fail1; memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; @@ -2038,7 +2043,7 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid) drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); if (drv->eapol_sock < 0) { perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)"); - return -1; + goto fail1; } if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL)) @@ -2051,17 +2056,21 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid) os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); if (ioctl(drv->ioctl_sock, SIOCGIFHWADDR, &ifr) != 0) { perror("ioctl(SIOCGIFHWADDR)"); - return -1; + goto fail1; } if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { printf("Invalid HW-addr family 0x%04x\n", ifr.ifr_hwaddr.sa_family); - return -1; + goto fail1; } memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); return 0; + +fail1: + nl80211_remove_iface(drv, drv->monitor_ifidx); + return -1; } @@ -2105,7 +2114,7 @@ hostapd_wireless_event_wireless_custom(struct i802_driver_data *drv, } pos += 5; if (hwaddr_aton(pos, addr) == 0) { - ieee80211_michael_mic_failure(drv->hapd, addr, 1); + hostapd_michael_mic_failure(drv->hapd, addr); } else { wpa_printf(MSG_DEBUG, "MLME-MICHAELMICFAILURE.indication " @@ -2410,6 +2419,14 @@ static void i802_deinit(void *priv) { struct i802_driver_data *drv = priv; + if (drv->last_freq_ht) { + /* Clear HT flags from the driver */ + struct hostapd_freq_params freq; + os_memset(&freq, 0, sizeof(freq)); + freq.freq = drv->last_freq; + i802_set_freq2(priv, &freq); + } + i802_del_beacon(drv); /* remove monitor interface */ @@ -2458,12 +2475,11 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .sta_deauth = i802_sta_deauth, .sta_disassoc = i802_sta_disassoc, .sta_remove = i802_sta_remove, - .set_ssid = i802_set_ssid, .send_mgmt_frame = i802_send_mgmt_frame, .sta_add2 = i802_sta_add2, .get_inact_sec = i802_get_inact_sec, .sta_clear_stats = i802_sta_clear_stats, - .set_freq = i802_set_freq, + .set_freq2 = i802_set_freq2, .set_rts = i802_set_rts, .get_rts = i802_get_rts, .set_frag = i802_set_frag, @@ -2471,8 +2487,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .set_retry = i802_set_retry, .get_retry = i802_get_retry, .set_rate_sets = i802_set_rate_sets, - .set_channel_flag = i802_set_channel_flag, - .set_regulatory_domain = i802_set_regulatory_domain, .set_beacon = i802_set_beacon, .set_internal_bridge = i802_set_internal_bridge, .set_beacon_int = i802_set_beacon_int, @@ -2488,4 +2502,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .if_remove = i802_if_remove, .get_hw_feature_data = i802_get_hw_feature_data, .set_sta_vlan = i802_set_sta_vlan, + .set_country = i802_set_country, };