diff options
| author | Dmitry Shmidt <dimitrysh@google.com> | 2014-04-02 12:59:59 -0700 |
|---|---|---|
| committer | Dmitry Shmidt <dimitrysh@google.com> | 2014-04-02 12:59:59 -0700 |
| commit | df5a7e4c5c64890c2425bb47d665bbce4992b676 (patch) | |
| tree | 84790cf1aabc02c4795347440e61eb3e2581ae12 /src | |
| parent | 15907098d1f67c24bb000e593e279af173cf57d7 (diff) | |
| download | android_external_wpa_supplicant_8-df5a7e4c5c64890c2425bb47d665bbce4992b676.tar.gz android_external_wpa_supplicant_8-df5a7e4c5c64890c2425bb47d665bbce4992b676.tar.bz2 android_external_wpa_supplicant_8-df5a7e4c5c64890c2425bb47d665bbce4992b676.zip | |
Cumulative patch from commit 39a5800f7c2a9de743c673a78929ac46a099b1a4
39a5800 wpa_supplicant: Allow disabling LDPC
7230040 Interworking: Read IMSI if not read at supplicant start
62f736d Interworking: Init scard when a credential requires SIM access
729897a Interworking: Fix incorrect compile PCSC flag
21611ea edit: Increase buffer size to 4096 bytes
0b2c59e OSU server: Add example scripts for Hotspot 2.0 PKI
0f27c20 HS 2.0R2: Add example OSU SPP server implementation
1e03c6c XML: Remove forgotten, unused definition of debug_print_func
5cfc87b Make hs20_wan_metrics parser error print more helpful
4be20bf Fix validation of anqp_3gpp_cell_net configuration parameter
23587e3 Remove duplicated vht_capab parser entry
18a8e55 Notify STA of disconnection based on ACL change
8943cc9 RADIUS server: Add support for MAC ACL
dc87541 Clean up debug print for PSK file search
bbbacbf DFS: Print CAC info in ctrl_iface STATUS command
ace0fbd P2P: Fix segfault when PBC overlap is detected
cf15b15 Add writing of network block ocsp parameter
5c9da16 nl80211: Set all BSS interfaces down when tearing down AP in MBSS mode
f1c4dbf wpa_supplicant: Remove pending sme-connect radio work
4f560cd wpa_supplicant: Override HT A-MPDU size if VHT A-MPDU was overridden
3ae8b7b hostapd: Add vendor command support
782e2f7 P2P: Do not initiate scan on P2P Device when enabled
74a1319 Fix issue with incorrect secondary_channel in HT40/HT80
96ecea5 Pass TDLS peer capability information in tdls_mgmt
78cd7e6 Sync with wireless-testing.git include/uapi/linux/nl80211.h
b36935b nl80211: Fix EAPOL frames not being delivered
6997f8b nl80211: Set interface address even if using old interface
9b4d9c8 nl80211: Print if_indices list in debug log
762c41a eloop: Add assert() on negative fd when using select() code path
978c673 Add a note on using 'iw list' to determine multi-BSS support
Change-Id: I89af7f8d92ed706c8909ed3cc9c49d6e1277a2b0
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/ap/ap_config.c | 5 | ||||
| -rw-r--r-- | src/ap/ap_config.h | 1 | ||||
| -rw-r--r-- | src/ap/ap_drv_ops.c | 4 | ||||
| -rw-r--r-- | src/ap/ap_drv_ops.h | 11 | ||||
| -rw-r--r-- | src/ap/authsrv.c | 1 | ||||
| -rw-r--r-- | src/ap/ctrl_iface_ap.c | 22 | ||||
| -rw-r--r-- | src/ap/dfs.c | 31 | ||||
| -rw-r--r-- | src/ap/hostapd.c | 1 | ||||
| -rw-r--r-- | src/ap/hostapd.h | 3 | ||||
| -rw-r--r-- | src/ap/ieee802_1x.c | 1 | ||||
| -rw-r--r-- | src/drivers/driver.h | 13 | ||||
| -rw-r--r-- | src/drivers/driver_nl80211.c | 65 | ||||
| -rw-r--r-- | src/drivers/nl80211_copy.h | 48 | ||||
| -rw-r--r-- | src/eap_server/eap.h | 1 | ||||
| -rw-r--r-- | src/radius/radius.c | 45 | ||||
| -rw-r--r-- | src/radius/radius.h | 4 | ||||
| -rw-r--r-- | src/radius/radius_server.c | 91 | ||||
| -rw-r--r-- | src/rsn_supp/tdls.c | 40 | ||||
| -rw-r--r-- | src/rsn_supp/wpa.h | 3 | ||||
| -rw-r--r-- | src/rsn_supp/wpa_i.h | 6 | ||||
| -rw-r--r-- | src/utils/edit.c | 2 | ||||
| -rw-r--r-- | src/utils/edit_simple.c | 2 | ||||
| -rw-r--r-- | src/utils/eloop.c | 7 | ||||
| -rw-r--r-- | src/utils/xml-utils.h | 3 |
24 files changed, 354 insertions, 56 deletions
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 5a8e67e9..0a143d39 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -651,12 +651,11 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, struct hostapd_wpa_psk *psk; int next_ok = prev_psk == NULL; - if (p2p_dev_addr) { + if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) { wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR " p2p_dev_addr=" MACSTR " prev_psk=%p", MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk); - if (!is_zero_ether_addr(p2p_dev_addr)) - addr = NULL; /* Use P2P Device Address for matching */ + addr = NULL; /* Use P2P Device Address for matching */ } else { wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR " prev_psk=%p", diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 25eb4903..dfbe6260 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -127,6 +127,7 @@ struct hostapd_eap_user { unsigned int password_hash:1; /* whether password is hashed with * nt_password_hash() */ unsigned int remediation:1; + unsigned int macacl:1; int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */ struct hostapd_radius_attr *accept_attr; }; diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 9abcd7c9..6d3ae5a7 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -774,8 +774,10 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, int mode, int freq, } res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); - if (!res) + if (!res) { iface->cac_started = 1; + os_get_reltime(&iface->dfs_cac_start); + } return res; } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 9edaf7d7..7cc9d7de 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -280,4 +280,15 @@ static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf, return hapd->driver->status(hapd->drv_priv, buf, buflen); } +static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, + int vendor_id, int subcmd, + const u8 *data, size_t data_len, + struct wpabuf *buf) +{ + if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL) + return -1; + return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data, + data_len, buf); +} + #endif /* AP_DRV_OPS */ diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index 6e3decd8..86f1cbe1 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -79,6 +79,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, user->password_hash = eap_user->password_hash; } user->force_version = eap_user->force_version; + user->macacl = eap_user->macacl; user->ttls_auth = eap_user->ttls_auth; user->remediation = eap_user->remediation; user->accept_attr = eap_user->accept_attr; diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index e1020a67..97609334 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -423,6 +423,28 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, return len; len += ret; + if (!iface->cac_started || !iface->dfs_cac_ms) { + ret = os_snprintf(buf + len, buflen - len, + "cac_time_seconds=%d\n" + "cac_time_left_seconds=N/A\n", + iface->dfs_cac_ms / 1000); + } else { + /* CAC started and CAC time set - calculate remaining time */ + struct os_reltime now; + unsigned int left_time; + + os_reltime_age(&iface->dfs_cac_start, &now); + left_time = iface->dfs_cac_ms / 1000 - now.sec; + ret = os_snprintf(buf + len, buflen - len, + "cac_time_seconds=%u\n" + "cac_time_left_seconds=%u\n", + iface->dfs_cac_ms / 1000, + left_time); + } + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + ret = os_snprintf(buf + len, buflen - len, "channel=%u\n" "secondary_channel=%d\n" diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 0f262ceb..3fb18810 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -573,6 +573,28 @@ static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq, } +static unsigned int dfs_get_cac_time(struct hostapd_iface *iface, + int start_chan_idx, int n_chans) +{ + struct hostapd_channel_data *channel; + struct hostapd_hw_modes *mode; + int i; + unsigned int cac_time_ms = 0; + + mode = iface->current_mode; + + for (i = 0; i < n_chans; i++) { + channel = &mode->channels[start_chan_idx + i]; + if (!(channel->flag & HOSTAPD_CHAN_RADAR)) + continue; + if (channel->dfs_cac_ms > cac_time_ms) + cac_time_ms = channel->dfs_cac_ms; + } + + return cac_time_ms; +} + + /* * Main DFS handler * 1 - continue channel/ap setup @@ -596,6 +618,10 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) /* Get number of used channels, depend on width */ n_chans = dfs_get_used_n_chans(iface); + /* Setup CAC time */ + iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx, + n_chans); + /* Check if any of configured channels require DFS */ res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); wpa_printf(MSG_DEBUG, @@ -640,12 +666,13 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) hostapd_set_state(iface, HAPD_IFACE_DFS); wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START - "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d", + "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", iface->freq, iface->conf->channel, iface->conf->secondary_channel, iface->conf->vht_oper_chwidth, iface->conf->vht_oper_centr_freq_seg0_idx, - iface->conf->vht_oper_centr_freq_seg1_idx); + iface->conf->vht_oper_centr_freq_seg1_idx, + iface->dfs_cac_ms / 1000); res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode, iface->freq, diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index ed2226ca..614a5bf4 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -172,6 +172,7 @@ int hostapd_reload_config(struct hostapd_iface *iface) hapd = iface->bss[j]; hapd->iconf = newconf; hapd->iconf->channel = oldconf->channel; + hapd->iconf->secondary_channel = oldconf->secondary_channel; hapd->iconf->ieee80211n = oldconf->ieee80211n; hapd->iconf->ieee80211ac = oldconf->ieee80211ac; hapd->iconf->ht_capab = oldconf->ht_capab; diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 9a705a45..090544d5 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -348,6 +348,9 @@ struct hostapd_iface { unsigned int cs_c_off_proberesp; int csa_in_progress; + unsigned int dfs_cac_ms; + struct os_reltime dfs_cac_start; + #ifdef CONFIG_ACS unsigned int acs_num_completed_scans; #endif /* CONFIG_ACS */ diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index b12c9d6c..035415f2 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -1787,6 +1787,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, user->password_hash = eap_user->password_hash; } user->force_version = eap_user->force_version; + user->macacl = eap_user->macacl; user->ttls_auth = eap_user->ttls_auth; user->remediation = eap_user->remediation; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 59352739..02ade125 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -93,6 +93,9 @@ struct hostapd_channel_data { */ long double interference_factor; #endif /* CONFIG_ACS */ + + /* DFS CAC time in milliseconds */ + unsigned int dfs_cac_ms; }; #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) @@ -1269,6 +1272,13 @@ struct csa_settings { u16 counter_offset_presp; }; +/* TDLS peer capabilities for send_tdls_mgmt() */ +enum tdls_peer_capability { + TDLS_PEER_HT = BIT(0), + TDLS_PEER_VHT = BIT(1), + TDLS_PEER_WMM = BIT(2), +}; + /** * struct wpa_driver_ops - Driver interface API definition * @@ -2449,6 +2459,7 @@ struct wpa_driver_ops { * @action_code: TDLS action code for the mssage * @dialog_token: Dialog Token to use in the message (if needed) * @status_code: Status Code or Reason Code to use (if needed) + * @peer_capab: TDLS peer capability (TDLS_PEER_* bitfield) * @buf: TDLS IEs to add to the message * @len: Length of buf in octets * Returns: 0 on success, negative (<0) on failure @@ -2457,7 +2468,7 @@ struct wpa_driver_ops { * responsible for receiving and sending all TDLS packets. */ int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code, - u8 dialog_token, u16 status_code, + u8 dialog_token, u16 status_code, u32 peer_capab, const u8 *buf, size_t len); /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 3ecce191..27b4c48e 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6200,6 +6200,7 @@ static void phy_info_freq(struct hostapd_hw_modes *mode, u8 channel; chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); chan->flag = 0; + chan->dfs_cac_ms = 0; if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES) chan->chan = channel; @@ -6226,6 +6227,11 @@ static void phy_info_freq(struct hostapd_hw_modes *mode, break; } } + + if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) { + chan->dfs_cac_ms = nla_get_u32( + tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]); + } } @@ -7660,6 +7666,16 @@ static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, if (use_existing) { wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s", ifname); + if (addr && iftype != NL80211_IFTYPE_MONITOR && + linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, + addr) < 0 && + (linux_set_iface_flags(drv->global->ioctl_sock, + ifname, 0) < 0 || + linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, + addr) < 0 || + linux_set_iface_flags(drv->global->ioctl_sock, + ifname, 1) < 0)) + return -1; return -ENFILE; } wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname); @@ -9446,6 +9462,29 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, } +static void dump_ifidx(struct wpa_driver_nl80211_data *drv) +{ + char buf[200], *pos, *end; + int i, res; + + pos = buf; + end = pos + sizeof(buf); + + for (i = 0; i < drv->num_if_indices; i++) { + if (!drv->if_indices[i]) + continue; + res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]); + if (res < 0 || res >= end - pos) + break; + pos += res; + } + *pos = '\0'; + + wpa_printf(MSG_DEBUG, "nl80211: if_indices[%d]:%s", + drv->num_if_indices, buf); +} + + static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) { int i; @@ -9453,9 +9492,15 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d", ifidx); + if (have_ifidx(drv, ifidx)) { + wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list", + ifidx); + return; + } for (i = 0; i < drv->num_if_indices; i++) { if (drv->if_indices[i] == 0) { drv->if_indices[i] = ifidx; + dump_ifidx(drv); return; } } @@ -9481,6 +9526,7 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) sizeof(drv->default_if_indices)); drv->if_indices[drv->num_if_indices] = ifidx; drv->num_if_indices++; + dump_ifidx(drv); } @@ -9494,6 +9540,7 @@ static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) break; } } + dump_ifidx(drv); } @@ -9929,6 +9976,9 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, if (drv->global) drv->global->if_add_ifindex = ifidx; + if (ifidx > 0) + add_ifidx(drv, ifidx); + return 0; } @@ -9944,6 +9994,8 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss, __func__, type, ifname, ifindex, bss->added_if); if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex)) nl80211_remove_iface(drv, ifindex); + else if (ifindex > 0 && !bss->added_if) + del_ifidx(drv, ifindex); if (type != WPA_IF_AP_BSS) return 0; @@ -9972,6 +10024,8 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss, /* Unsubscribe management frames */ nl80211_teardown_ap(bss); nl80211_destroy_bss(bss); + if (!bss->added_if) + i802_set_iface_flags(bss, 0); os_free(bss); bss = NULL; break; @@ -11176,7 +11230,7 @@ nla_put_failure: static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, u8 dialog_token, u16 status_code, - const u8 *buf, size_t len) + u32 peer_capab, const u8 *buf, size_t len) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -11198,6 +11252,15 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, NLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code); NLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token); NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code); + if (peer_capab) { + /* + * The internal enum tdls_peer_capability definition is + * currently identical with the nl80211 enum + * nl80211_tdls_peer_capability, so no conversion is needed + * here. + */ + NLA_PUT_U32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, peer_capab); + } NLA_PUT(msg, NL80211_ATTR_IE, len, buf); return send_and_recv_msgs(drv, msg, NULL, NULL); diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index a12e6cae..1ba9d626 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -303,8 +303,9 @@ * passed, all channels allowed for the current regulatory domain * are used. Extra IEs can also be passed from the userspace by * using the %NL80211_ATTR_IE attribute. - * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT - * if scheduled scan is not running. + * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT if + * scheduled scan is not running. The caller may assume that as soon + * as the call returns, it is safe to start a new scheduled scan again. * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan * results available. * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has @@ -1575,6 +1576,9 @@ enum nl80211_commands { * advertise values that cannot always be met. In such cases, an attempt * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. * + * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. + * As specified in the &enum nl80211_tdls_peer_capability. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1908,6 +1912,8 @@ enum nl80211_attrs { NL80211_ATTR_MAX_AP_ASSOC_STA, + NL80211_ATTR_TDLS_PEER_CAPABILITY, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2329,6 +2335,7 @@ enum nl80211_band_attr { * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel * using this channel as the primary or any of the secondary channels * isn't possible + * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -2347,6 +2354,7 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, NL80211_FREQUENCY_ATTR_NO_80MHZ, NL80211_FREQUENCY_ATTR_NO_160MHZ, + NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -2437,15 +2445,14 @@ enum nl80211_reg_type { * in KHz. This is not a center a frequency but an actual regulatory * band edge. * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this - * frequency range, in KHz. If not present or 0, maximum available - * bandwidth should be calculated base on contiguous rules and wider - * channels will be allowed to cross multiple contiguous/overlapping - * frequency ranges. + * frequency range, in KHz. * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain * for a given frequency range. The value is in mBi (100 * dBi). * If you don't have one then don't send this. * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for * a given frequency range. The value is in mBm (100 * dBm). + * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. + * If not present or 0 default CAC time will be used. * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number * currently defined * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use @@ -2461,6 +2468,8 @@ enum nl80211_reg_rule_attr { NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, NL80211_ATTR_POWER_RULE_MAX_EIRP, + NL80211_ATTR_DFS_CAC_TIME, + /* keep last */ __NL80211_REG_RULE_ATTR_AFTER_LAST, NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 @@ -2511,6 +2520,9 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, * this includes probe requests or modes of operation that require * beaconing. + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, @@ -2522,6 +2534,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_PTMP_ONLY = 1<<6, NL80211_RRF_NO_IR = 1<<7, __NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR @@ -3843,11 +3856,6 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested * to work properly to suppport receiving regulatory hints from * cellular base stations. - * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: If this is set, an active - * P2P Device (%NL80211_IFTYPE_P2P_DEVICE) requires its own channel - * in the interface combinations, even when it's only used for scan - * and remain-on-channel. This could be due to, for example, the - * remain-on-channel implementation requiring a channel context. * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station * mode @@ -3889,7 +3897,7 @@ enum nl80211_feature_flags { NL80211_FEATURE_HT_IBSS = 1 << 1, NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, - NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, + /* bit 4 is reserved - don't use */ NL80211_FEATURE_SAE = 1 << 5, NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6, NL80211_FEATURE_SCAN_FLUSH = 1 << 7, @@ -4079,4 +4087,20 @@ struct nl80211_vendor_cmd_info { __u32 subcmd; }; +/** + * enum nl80211_tdls_peer_capability - TDLS peer flags. + * + * Used by tdls_mgmt() to determine which conditional elements need + * to be added to TDLS Setup frames. + * + * @NL80211_TDLS_PEER_HT: TDLS peer is HT capable. + * @NL80211_TDLS_PEER_VHT: TDLS peer is VHT capable. + * @NL80211_TDLS_PEER_WMM: TDLS peer is WMM capable. + */ +enum nl80211_tdls_peer_capability { + NL80211_TDLS_PEER_HT = 1<<0, + NL80211_TDLS_PEER_VHT = 1<<1, + NL80211_TDLS_PEER_WMM = 1<<2, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index 698a5ac0..1253bd6e 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -33,6 +33,7 @@ struct eap_user { int phase2; int force_version; unsigned int remediation:1; + unsigned int macacl:1; int ttls_auth; /* bitfield of * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */ struct hostapd_radius_attr *accept_attr; diff --git a/src/radius/radius.c b/src/radius/radius.c index 370b517f..47b4f8af 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -1247,30 +1247,28 @@ int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data, } -/* Add User-Password attribute to a RADIUS message and encrypt it as specified - * in RFC 2865, Chap. 5.2 */ -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - const u8 *data, size_t data_len, - const u8 *secret, size_t secret_len) +int radius_user_password_hide(struct radius_msg *msg, + const u8 *data, size_t data_len, + const u8 *secret, size_t secret_len, + u8 *buf, size_t buf_len) { - u8 buf[128]; - size_t padlen, i, buf_len, pos; + size_t padlen, i, pos; const u8 *addr[2]; size_t len[2]; u8 hash[16]; - if (data_len > 128) - return NULL; + if (data_len + 16 > buf_len) + return -1; os_memcpy(buf, data, data_len); - buf_len = data_len; padlen = data_len % 16; - if (padlen && data_len < sizeof(buf)) { + if (padlen && data_len < buf_len) { padlen = 16 - padlen; os_memset(buf + data_len, 0, padlen); - buf_len += padlen; + buf_len = data_len + padlen; + } else { + buf_len = data_len; } addr[0] = secret; @@ -1296,8 +1294,27 @@ radius_msg_add_attr_user_password(struct radius_msg *msg, pos += 16; } + return buf_len; +} + + +/* Add User-Password attribute to a RADIUS message and encrypt it as specified + * in RFC 2865, Chap. 5.2 */ +struct radius_attr_hdr * +radius_msg_add_attr_user_password(struct radius_msg *msg, + const u8 *data, size_t data_len, + const u8 *secret, size_t secret_len) +{ + u8 buf[128]; + int res; + + res = radius_user_password_hide(msg, data, data_len, + secret, secret_len, buf, sizeof(buf)); + if (res < 0) + return NULL; + return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD, - buf, buf_len); + buf, res); } diff --git a/src/radius/radius.h b/src/radius/radius.h index d8bf21eb..d388f717 100644 --- a/src/radius/radius.h +++ b/src/radius/radius.h @@ -251,6 +251,10 @@ int radius_msg_add_mppe_keys(struct radius_msg *msg, const u8 *recv_key, size_t recv_key_len); int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data, size_t len); +int radius_user_password_hide(struct radius_msg *msg, + const u8 *data, size_t data_len, + const u8 *secret, size_t secret_len, + u8 *buf, size_t buf_len); struct radius_attr_hdr * radius_msg_add_attr_user_password(struct radius_msg *msg, const u8 *data, size_t data_len, diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index f2ea3932..bd358ae9 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -86,6 +86,7 @@ struct radius_session { u8 last_authenticator[16]; unsigned int remediation:1; + unsigned int macacl:1; struct hostapd_radius_attr *accept_attr; }; @@ -636,6 +637,7 @@ radius_server_get_new_session(struct radius_server_data *data, return NULL; } sess->accept_attr = tmp.accept_attr; + sess->macacl = tmp.macacl; sess->username = os_malloc(user_len * 2 + 1); if (sess->username == NULL) { @@ -823,6 +825,87 @@ radius_server_encapsulate_eap(struct radius_server_data *data, } +static struct radius_msg * +radius_server_macacl(struct radius_server_data *data, + struct radius_client *client, + struct radius_session *sess, + struct radius_msg *request) +{ + struct radius_msg *msg; + int code; + struct radius_hdr *hdr = radius_msg_get_hdr(request); + u8 *pw; + size_t pw_len; + + code = RADIUS_CODE_ACCESS_ACCEPT; + + if (radius_msg_get_attr_ptr(request, RADIUS_ATTR_USER_PASSWORD, &pw, + &pw_len, NULL) < 0) { + RADIUS_DEBUG("Could not get User-Password"); + code = RADIUS_CODE_ACCESS_REJECT; + } else { + int res; + struct eap_user tmp; + + os_memset(&tmp, 0, sizeof(tmp)); + res = data->get_eap_user(data->conf_ctx, (u8 *) sess->username, + os_strlen(sess->username), 0, &tmp); + if (res || !tmp.macacl || tmp.password == NULL) { + RADIUS_DEBUG("No MAC ACL user entry"); + os_free(tmp.password); + code = RADIUS_CODE_ACCESS_REJECT; + } else { + u8 buf[128]; + res = radius_user_password_hide( + request, tmp.password, tmp.password_len, + (u8 *) client->shared_secret, + client->shared_secret_len, + buf, sizeof(buf)); + os_free(tmp.password); + + if (res < 0 || pw_len != (size_t) res || + os_memcmp(pw, buf, res) != 0) { + RADIUS_DEBUG("Incorrect User-Password"); + code = RADIUS_CODE_ACCESS_REJECT; + } + } + } + + msg = radius_msg_new(code, hdr->identifier); + if (msg == NULL) { + RADIUS_DEBUG("Failed to allocate reply message"); + return NULL; + } + + if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { + RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); + radius_msg_free(msg); + return NULL; + } + + if (code == RADIUS_CODE_ACCESS_ACCEPT) { + struct hostapd_radius_attr *attr; + for (attr = sess->accept_attr; attr; attr = attr->next) { + if (!radius_msg_add_attr(msg, attr->type, + wpabuf_head(attr->val), + wpabuf_len(attr->val))) { + wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); + radius_msg_free(msg); + return NULL; + } + } + } + + if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, + client->shared_secret_len, + hdr->authenticator) < 0) { + RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); + } + + return msg; +} + + static int radius_server_reject(struct radius_server_data *data, struct radius_client *client, struct radius_msg *request, @@ -958,6 +1041,12 @@ static int radius_server_request(struct radius_server_data *data, } eap = radius_msg_get_eap(msg); + if (eap == NULL && sess->macacl) { + reply = radius_server_macacl(data, client, sess, msg); + if (reply == NULL) + return -1; + goto send_reply; + } if (eap == NULL) { RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", from_addr); @@ -1015,6 +1104,7 @@ static int radius_server_request(struct radius_server_data *data, reply = radius_server_encapsulate_eap(data, client, sess, msg); +send_reply: if (reply) { struct wpabuf *buf; struct radius_hdr *hdr; @@ -1904,6 +1994,7 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity, if (ret == 0 && user) { sess->accept_attr = user->accept_attr; sess->remediation = user->remediation; + sess->macacl = user->macacl; } return ret; } diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 9b8ca6b8..62a2a591 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -118,6 +118,7 @@ struct wpa_tdls_peer { u8 action_code; /* TDLS frame type */ u8 dialog_token; u16 status_code; + u32 peer_capab; int buf_len; /* length of TPK message for retransmission */ u8 *buf; /* buffer for TPK message */ } sm_tmr; @@ -142,6 +143,8 @@ struct wpa_tdls_peer { u8 *supp_oper_classes; size_t supp_oper_classes_len; + + u8 wmm_capable; }; @@ -211,15 +214,16 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst, u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, size_t len) + u16 status_code, u32 peer_capab, + const u8 *buf, size_t len) { return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token, - status_code, buf, len); + status_code, peer_capab, buf, len); } static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, - u8 dialog_token, u16 status_code, + u8 dialog_token, u16 status_code, u32 peer_capab, const u8 *msg, size_t msg_len) { struct wpa_tdls_peer *peer; @@ -230,7 +234,7 @@ static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, (unsigned int) msg_len); if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token, - status_code, msg, msg_len)) { + status_code, peer_capab, msg, msg_len)) { wpa_printf(MSG_INFO, "TDLS: Failed to send message " "(action_code=%u)", action_code); return -1; @@ -268,6 +272,7 @@ static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, peer->sm_tmr.action_code = action_code; peer->sm_tmr.dialog_token = dialog_token; peer->sm_tmr.status_code = status_code; + peer->sm_tmr.peer_capab = peer_capab; peer->sm_tmr.buf_len = msg_len; os_free(peer->sm_tmr.buf); peer->sm_tmr.buf = os_malloc(msg_len); @@ -324,6 +329,7 @@ static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx) peer->sm_tmr.action_code, peer->sm_tmr.dialog_token, peer->sm_tmr.status_code, + peer->sm_tmr.peer_capab, peer->sm_tmr.buf, peer->sm_tmr.buf_len)) { wpa_printf(MSG_INFO, "TDLS: Failed to retry " @@ -645,6 +651,8 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) peer->supp_oper_classes = NULL; peer->rsnie_i_len = peer->rsnie_p_len = 0; peer->cipher = 0; + peer->qos_info = 0; + peer->wmm_capable = 0; peer->tpk_set = peer->tpk_success = 0; os_memset(&peer->tpk, 0, sizeof(peer->tpk)); os_memset(peer->inonce, 0, WPA_NONCE_LEN); @@ -747,7 +755,7 @@ skip_ies: /* request driver to send Teardown using this FTIE */ wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0, - reason_code, rbuf, pos - rbuf); + reason_code, 0, rbuf, pos - rbuf); os_free(rbuf); /* clear the Peerkey statemachine */ @@ -918,7 +926,7 @@ static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst, " (action=%u status=%u)", MAC2STR(dst), tdls_action, status); return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status, - NULL, 0); + 0, NULL, 0); } @@ -1124,7 +1132,7 @@ skip_ies: MAC2STR(peer->addr)); status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, - 1, 0, rbuf, pos - rbuf); + 1, 0, 0, rbuf, pos - rbuf); os_free(rbuf); return status; @@ -1208,7 +1216,7 @@ static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm, skip_ies: status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, - dtoken, 0, rbuf, pos - rbuf); + dtoken, 0, 0, rbuf, pos - rbuf); os_free(rbuf); return status; @@ -1226,6 +1234,7 @@ static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm, struct wpa_tdls_timeoutie timeoutie; u32 lifetime; int status; + u32 peer_capab = 0; buf_len = 0; if (wpa_tdls_get_privacy(sm)) { @@ -1288,9 +1297,16 @@ static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm, wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p, (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); + if (peer->vht_capabilities) + peer_capab |= TDLS_PEER_VHT; + else if (peer->ht_capabilities) + peer_capab |= TDLS_PEER_HT; + else if (peer->wmm_capable) + peer_capab |= TDLS_PEER_WMM; + skip_ies: status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, - dtoken, 0, rbuf, pos - rbuf); + dtoken, 0, peer_capab, rbuf, pos - rbuf); os_free(rbuf); return status; @@ -1305,7 +1321,7 @@ static int wpa_tdls_send_discovery_response(struct wpa_sm *sm, "(peer " MACSTR ")", MAC2STR(peer->addr)); return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE, - dialog_token, 0, NULL, 0); + dialog_token, 0, 0, NULL, 0); } @@ -1366,7 +1382,7 @@ int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr) wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer " MACSTR, MAC2STR(addr)); return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST, - 1, 0, NULL, 0); + 1, 0, 0, NULL, 0); } @@ -1484,6 +1500,8 @@ static int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde, wmm = (struct wmm_information_element *) kde->wmm; peer->qos_info = wmm->qos_info; + peer->wmm_capable = 1; + wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info); return 0; } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 20b3f621..df103422 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -54,7 +54,8 @@ struct wpa_sm_ctx { int *tdls_ext_setup); int (*send_tdls_mgmt)(void *ctx, const u8 *dst, u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, size_t len); + u16 status_code, u32 peer_capab, + const u8 *buf, size_t len); int (*tdls_oper)(void *ctx, int oper, const u8 *peer); int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid, u16 capability, const u8 *supp_rates, diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 75cfb479..f2fd2857 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -267,13 +267,13 @@ static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm, static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst, u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, - size_t len) + u16 status_code, u32 peer_capab, + const u8 *buf, size_t len) { if (sm->ctx->send_tdls_mgmt) return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code, dialog_token, status_code, - buf, len); + peer_capab, buf, len); return -1; } diff --git a/src/utils/edit.c b/src/utils/edit.c index 177ecf41..d340bfad 100644 --- a/src/utils/edit.c +++ b/src/utils/edit.c @@ -14,7 +14,7 @@ #include "list.h" #include "edit.h" -#define CMD_BUF_LEN 256 +#define CMD_BUF_LEN 4096 static char cmdbuf[CMD_BUF_LEN]; static int cmdbuf_pos = 0; static int cmdbuf_len = 0; diff --git a/src/utils/edit_simple.c b/src/utils/edit_simple.c index a095ea6a..13173cb1 100644 --- a/src/utils/edit_simple.c +++ b/src/utils/edit_simple.c @@ -13,7 +13,7 @@ #include "edit.h" -#define CMD_BUF_LEN 256 +#define CMD_BUF_LEN 4096 static char cmdbuf[CMD_BUF_LEN]; static int cmdbuf_pos = 0; static const char *ps2 = NULL; diff --git a/src/utils/eloop.c b/src/utils/eloop.c index f83a2327..2667c8c9 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -7,6 +7,7 @@ */ #include "includes.h" +#include <assert.h> #include "common.h" #include "trace.h" @@ -14,7 +15,6 @@ #include "eloop.h" #ifdef CONFIG_ELOOP_POLL -#include <assert.h> #include <poll.h> #endif /* CONFIG_ELOOP_POLL */ @@ -374,8 +374,10 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table, if (table->table == NULL) return; - for (i = 0; i < table->count; i++) + for (i = 0; i < table->count; i++) { + assert(table->table[i].sock >= 0); FD_SET(table->table[i].sock, fds); + } } @@ -459,6 +461,7 @@ int eloop_register_sock(int sock, eloop_event_type type, { struct eloop_sock_table *table; + assert(sock >= 0); table = eloop_get_sock_table(type); return eloop_sock_table_add_sock(table, sock, handler, eloop_data, user_data); diff --git a/src/utils/xml-utils.h b/src/utils/xml-utils.h index 0d8e0cb8..fb6208cd 100644 --- a/src/utils/xml-utils.h +++ b/src/utils/xml-utils.h @@ -73,9 +73,6 @@ for (; \ if (!xml_node_is_element(ctx, child)) \ continue -typedef void (*debug_print_func)(void *ctx, int print, const char *fmt, ...) - __attribute__ ((format (printf, 3, 4))); - struct xml_node_ctx * xml_node_init_ctx(void *upper_ctx, const void *env); |
