aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore31
-rw-r--r--doc/dbus.doxygen32
-rw-r--r--doc/doxygen.conf2
-rw-r--r--doc/driver_wrapper.doxygen2
-rw-r--r--doc/p2p.doxygen2
-rw-r--r--eap_example/Makefile65
-rw-r--r--eap_example/eap_example_peer.c35
-rw-r--r--eap_example/eap_example_server.c6
-rw-r--r--hostapd/.gitignore5
-rw-r--r--hostapd/Android.mk35
-rw-r--r--hostapd/ChangeLog4
-rw-r--r--hostapd/Makefile143
-rw-r--r--hostapd/android.config13
-rw-r--r--hostapd/config_file.c274
-rw-r--r--hostapd/ctrl_iface.c657
-rw-r--r--hostapd/defconfig20
-rw-r--r--hostapd/hostapd.conf153
-rw-r--r--hostapd/hostapd.wpa_psk6
-rw-r--r--hostapd/hostapd_cli.c85
-rw-r--r--hostapd/main.c19
-rw-r--r--hostapd/sae_pk_gen.c196
-rw-r--r--hs20/client/Makefile55
-rw-r--r--hs20/client/est.c7
-rw-r--r--hs20/client/oma_dm_client.c2
-rw-r--r--hs20/client/osu_client.c27
-rw-r--r--hs20/client/osu_client.h2
-rw-r--r--hs20/client/spp_client.c2
-rw-r--r--hs20/server/.gitignore1
-rw-r--r--hs20/server/Makefile26
-rwxr-xr-xhs20/server/ca/ocsp-responder.sh2
-rwxr-xr-xhs20/server/ca/ocsp-update-cache.sh1
-rw-r--r--hs20/server/hs20_spp_server.c2
-rw-r--r--hs20/server/spp_server.c5
-rw-r--r--radius_example/Makefile36
-rw-r--r--src/Makefile4
-rw-r--r--src/ap/Makefile15
-rw-r--r--src/ap/acs.c299
-rw-r--r--src/ap/airtime_policy.c8
-rw-r--r--src/ap/ap_config.c153
-rw-r--r--src/ap/ap_config.h61
-rw-r--r--src/ap/ap_drv_ops.c135
-rw-r--r--src/ap/ap_drv_ops.h21
-rw-r--r--src/ap/ap_list.c4
-rw-r--r--src/ap/beacon.c289
-rw-r--r--src/ap/ctrl_iface_ap.c77
-rw-r--r--src/ap/dfs.c277
-rw-r--r--src/ap/dfs.h3
-rw-r--r--src/ap/dhcp_snoop.c8
-rw-r--r--src/ap/dpp_hostapd.c843
-rw-r--r--src/ap/dpp_hostapd.h11
-rw-r--r--src/ap/drv_callbacks.c302
-rw-r--r--src/ap/fils_hlp.c36
-rw-r--r--src/ap/gas_serv.c10
-rw-r--r--src/ap/hostapd.c181
-rw-r--r--src/ap/hostapd.h33
-rw-r--r--src/ap/hw_features.c222
-rw-r--r--src/ap/hw_features.h10
-rw-r--r--src/ap/ieee802_11.c707
-rw-r--r--src/ap/ieee802_11.h23
-rw-r--r--src/ap/ieee802_11_auth.c172
-rw-r--r--src/ap/ieee802_11_auth.h17
-rw-r--r--src/ap/ieee802_11_he.c95
-rw-r--r--src/ap/ieee802_11_ht.c26
-rw-r--r--src/ap/ieee802_11_shared.c128
-rw-r--r--src/ap/ieee802_11_vht.c57
-rw-r--r--src/ap/ieee802_1x.c114
-rw-r--r--src/ap/ieee802_1x.h7
-rw-r--r--src/ap/neighbor_db.c56
-rw-r--r--src/ap/neighbor_db.h1
-rw-r--r--src/ap/pmksa_cache_auth.c5
-rw-r--r--src/ap/preauth_auth.c2
-rw-r--r--src/ap/sta_info.c68
-rw-r--r--src/ap/sta_info.h6
-rw-r--r--src/ap/utils.c4
-rw-r--r--src/ap/vlan_init.c5
-rw-r--r--src/ap/wmm.c14
-rw-r--r--src/ap/wnm_ap.c78
-rw-r--r--src/ap/wpa_auth.c1258
-rw-r--r--src/ap/wpa_auth.h72
-rw-r--r--src/ap/wpa_auth_ft.c346
-rw-r--r--src/ap/wpa_auth_glue.c272
-rw-r--r--src/ap/wpa_auth_i.h66
-rw-r--r--src/ap/wpa_auth_ie.c87
-rw-r--r--src/ap/wpa_auth_kay.c12
-rw-r--r--src/ap/wps_hostapd.c119
-rw-r--r--src/build.rules109
-rw-r--r--src/common/Makefile15
-rw-r--r--src/common/common_module_tests.c209
-rw-r--r--src/common/defs.h74
-rw-r--r--src/common/dhcp.h2
-rw-r--r--src/common/dpp.c8420
-rw-r--r--src/common/dpp.h195
-rw-r--r--src/common/dpp_auth.c1976
-rw-r--r--src/common/dpp_backup.c1292
-rw-r--r--src/common/dpp_crypto.c3326
-rw-r--r--src/common/dpp_i.h160
-rw-r--r--src/common/dpp_pkex.c1324
-rw-r--r--src/common/dpp_reconfig.c958
-rw-r--r--src/common/dpp_tcp.c1794
-rw-r--r--src/common/gas_server.c125
-rw-r--r--src/common/gas_server.h8
-rw-r--r--src/common/hw_features_common.c332
-rw-r--r--src/common/hw_features_common.h20
-rw-r--r--src/common/ieee802_11_common.c567
-rw-r--r--src/common/ieee802_11_common.h50
-rw-r--r--src/common/ieee802_11_defs.h110
-rw-r--r--src/common/ocv.c37
-rw-r--r--src/common/ocv.h13
-rw-r--r--src/common/privsep_commands.h1
-rw-r--r--src/common/qca-vendor.h2171
-rw-r--r--src/common/sae.c273
-rw-r--r--src/common/sae.h72
-rw-r--r--src/common/sae_pk.c884
-rw-r--r--src/common/wpa_common.c138
-rw-r--r--src/common/wpa_common.h47
-rw-r--r--src/common/wpa_ctrl.c5
-rw-r--r--src/common/wpa_ctrl.h32
-rw-r--r--src/crypto/.gitignore1
-rw-r--r--src/crypto/Makefile19
-rw-r--r--src/crypto/crypto.h26
-rw-r--r--src/crypto/crypto_module_tests.c150
-rw-r--r--src/crypto/crypto_openssl.c196
-rw-r--r--src/crypto/crypto_wolfssl.c27
-rw-r--r--src/crypto/sha256.c6
-rw-r--r--src/crypto/sha384.c6
-rw-r--r--src/crypto/sha512.c6
-rw-r--r--src/crypto/tls.h14
-rw-r--r--src/crypto/tls_openssl.c213
-rw-r--r--src/crypto/tls_wolfssl.c51
-rw-r--r--src/drivers/.gitignore2
-rw-r--r--src/drivers/driver.h508
-rw-r--r--src/drivers/driver_atheros.c15
-rw-r--r--src/drivers/driver_bsd.c482
-rw-r--r--src/drivers/driver_common.c21
-rw-r--r--src/drivers/driver_hostap.c24
-rw-r--r--src/drivers/driver_macsec_linux.c87
-rw-r--r--src/drivers/driver_macsec_qca.c34
-rw-r--r--src/drivers/driver_ndis.c20
-rw-r--r--src/drivers/driver_nl80211.c1497
-rw-r--r--src/drivers/driver_nl80211.h46
-rw-r--r--src/drivers/driver_nl80211_android.c4
-rw-r--r--src/drivers/driver_nl80211_capa.c497
-rw-r--r--src/drivers/driver_nl80211_event.c274
-rw-r--r--src/drivers/driver_nl80211_monitor.c3
-rw-r--r--src/drivers/driver_nl80211_scan.c51
-rw-r--r--src/drivers/driver_none.c8
-rw-r--r--src/drivers/driver_openbsd.c10
-rw-r--r--src/drivers/driver_privsep.c18
-rw-r--r--src/drivers/driver_wext.c91
-rw-r--r--src/drivers/driver_wext.h4
-rw-r--r--src/drivers/drivers.mak18
-rw-r--r--src/drivers/drivers.mk21
-rw-r--r--src/drivers/nl80211_copy.h409
-rw-r--r--src/eap_common/Makefile15
-rw-r--r--src/eap_common/eap_sim_common.c4
-rw-r--r--src/eap_peer/.gitignore1
-rw-r--r--src/eap_peer/Makefile22
-rw-r--r--src/eap_peer/eap.c108
-rw-r--r--src/eap_peer/eap.h13
-rw-r--r--src/eap_peer/eap_aka.c14
-rw-r--r--src/eap_peer/eap_eke.c16
-rw-r--r--src/eap_peer/eap_fast.c4
-rw-r--r--src/eap_peer/eap_gpsk.c14
-rw-r--r--src/eap_peer/eap_gtc.c8
-rw-r--r--src/eap_peer/eap_i.h34
-rw-r--r--src/eap_peer/eap_ikev2.c28
-rw-r--r--src/eap_peer/eap_leap.c44
-rw-r--r--src/eap_peer/eap_md5.c12
-rw-r--r--src/eap_peer/eap_mschapv2.c32
-rw-r--r--src/eap_peer/eap_otp.c8
-rw-r--r--src/eap_peer/eap_pax.c50
-rw-r--r--src/eap_peer/eap_peap.c16
-rw-r--r--src/eap_peer/eap_psk.c22
-rw-r--r--src/eap_peer/eap_pwd.c22
-rw-r--r--src/eap_peer/eap_sake.c26
-rw-r--r--src/eap_peer/eap_sim.c31
-rw-r--r--src/eap_peer/eap_teap.c13
-rw-r--r--src/eap_peer/eap_tls.c8
-rw-r--r--src/eap_peer/eap_tls_common.c18
-rw-r--r--src/eap_peer/eap_tnc.c32
-rw-r--r--src/eap_peer/eap_ttls.c6
-rw-r--r--src/eap_peer/eap_vendor_test.c16
-rw-r--r--src/eap_peer/eap_wsc.c24
-rw-r--r--src/eap_peer/tncc.c5
-rw-r--r--src/eap_server/Makefile15
-rw-r--r--src/eap_server/eap.h34
-rw-r--r--src/eap_server/eap_i.h23
-rw-r--r--src/eap_server/eap_server.c130
-rw-r--r--src/eap_server/eap_server_aka.c28
-rw-r--r--src/eap_server/eap_server_eke.c20
-rw-r--r--src/eap_server/eap_server_fast.c12
-rw-r--r--src/eap_server/eap_server_gpsk.c16
-rw-r--r--src/eap_server/eap_server_gtc.c12
-rw-r--r--src/eap_server/eap_server_identity.c14
-rw-r--r--src/eap_server/eap_server_ikev2.c12
-rw-r--r--src/eap_server/eap_server_md5.c14
-rw-r--r--src/eap_server/eap_server_mschapv2.c18
-rw-r--r--src/eap_server/eap_server_pax.c32
-rw-r--r--src/eap_server/eap_server_peap.c12
-rw-r--r--src/eap_server/eap_server_psk.c18
-rw-r--r--src/eap_server/eap_server_pwd.c18
-rw-r--r--src/eap_server/eap_server_sake.c24
-rw-r--r--src/eap_server/eap_server_sim.c30
-rw-r--r--src/eap_server/eap_server_teap.c36
-rw-r--r--src/eap_server/eap_server_tls.c12
-rw-r--r--src/eap_server/eap_server_tnc.c20
-rw-r--r--src/eap_server/eap_server_ttls.c12
-rw-r--r--src/eap_server/eap_server_vendor_test.c12
-rw-r--r--src/eap_server/eap_server_wsc.c14
-rw-r--r--src/eap_server/tncs.c5
-rw-r--r--src/eapol_auth/Makefile16
-rw-r--r--src/eapol_auth/eapol_auth_sm.c117
-rw-r--r--src/eapol_auth/eapol_auth_sm_i.h40
-rw-r--r--src/eapol_supp/Makefile15
-rw-r--r--src/eapol_supp/eapol_supp_sm.c218
-rw-r--r--src/eapol_supp/eapol_supp_sm.h29
-rw-r--r--src/fst/fst.c16
-rw-r--r--src/fst/fst.h16
-rw-r--r--src/fst/fst_ctrl_aux.h4
-rw-r--r--src/fst/fst_ctrl_iface.c48
-rw-r--r--src/fst/fst_ctrl_iface.h2
-rw-r--r--src/fst/fst_group.c10
-rw-r--r--src/fst/fst_group.h4
-rw-r--r--src/fst/fst_iface.c8
-rw-r--r--src/fst/fst_iface.h8
-rw-r--r--src/fst/fst_session.c96
-rw-r--r--src/fst/fst_session.h12
-rw-r--r--src/l2_packet/Makefile15
-rw-r--r--src/l2_packet/l2_packet.h4
-rw-r--r--src/l2_packet/l2_packet_freebsd.c2
-rw-r--r--src/l2_packet/l2_packet_linux.c11
-rw-r--r--src/l2_packet/l2_packet_ndis.c3
-rw-r--r--src/l2_packet/l2_packet_none.c4
-rw-r--r--src/l2_packet/l2_packet_pcap.c4
-rw-r--r--src/l2_packet/l2_packet_privsep.c3
-rw-r--r--src/l2_packet/l2_packet_winpcap.c3
-rw-r--r--src/lib.rules38
-rw-r--r--src/objs.mk3
-rw-r--r--src/p2p/Makefile15
-rw-r--r--src/p2p/p2p.c18
-rw-r--r--src/p2p/p2p.h4
-rw-r--r--src/p2p/p2p_go_neg.c9
-rw-r--r--src/pae/ieee802_1x_cp.c144
-rw-r--r--src/pae/ieee802_1x_cp.h10
-rw-r--r--src/pae/ieee802_1x_kay.c389
-rw-r--r--src/pae/ieee802_1x_kay.h68
-rw-r--r--src/pae/ieee802_1x_kay_i.h40
-rw-r--r--src/pae/ieee802_1x_secy_ops.c22
-rw-r--r--src/pae/ieee802_1x_secy_ops.h8
-rw-r--r--src/radius/.gitignore1
-rw-r--r--src/radius/Makefile16
-rw-r--r--src/radius/radius.c2
-rw-r--r--src/radius/radius_client.c6
-rw-r--r--src/radius/radius_server.c14
-rw-r--r--src/rsn_supp/Makefile15
-rw-r--r--src/rsn_supp/pmksa_cache.c43
-rw-r--r--src/rsn_supp/pmksa_cache.h1
-rw-r--r--src/rsn_supp/preauth.c24
-rw-r--r--src/rsn_supp/tdls.c12
-rw-r--r--src/rsn_supp/wpa.c437
-rw-r--r--src/rsn_supp/wpa.h33
-rw-r--r--src/rsn_supp/wpa_ft.c248
-rw-r--r--src/rsn_supp/wpa_i.h39
-rw-r--r--src/rsn_supp/wpa_ie.c36
-rw-r--r--src/rsn_supp/wpa_ie.h1
-rw-r--r--src/tls/.gitignore1
-rw-r--r--src/tls/Makefile17
-rw-r--r--src/tls/asn1.c313
-rw-r--r--src/tls/asn1.h39
-rw-r--r--src/tls/pkcs1.c4
-rw-r--r--src/tls/rsa.c2
-rw-r--r--src/tls/tlsv1_client_read.c10
-rw-r--r--src/tls/tlsv1_cred.c8
-rw-r--r--src/tls/x509v3.c136
-rw-r--r--src/tls/x509v3.h7
-rw-r--r--src/utils/.gitignore1
-rw-r--r--src/utils/Makefile16
-rw-r--r--src/utils/base64.c59
-rw-r--r--src/utils/base64.h13
-rw-r--r--src/utils/browser-android.c2
-rw-r--r--src/utils/browser-system.c2
-rw-r--r--src/utils/browser-wpadebug.c2
-rw-r--r--src/utils/browser.c210
-rw-r--r--src/utils/browser.h4
-rw-r--r--src/utils/common.c38
-rw-r--r--src/utils/common.h5
-rw-r--r--src/utils/eloop.c47
-rw-r--r--src/utils/eloop_win.c8
-rw-r--r--src/utils/http-utils.h6
-rw-r--r--src/utils/includes.h1
-rw-r--r--src/utils/json.c122
-rw-r--r--src/utils/json.h15
-rw-r--r--src/utils/os_unix.c5
-rw-r--r--src/utils/state_machine.h8
-rw-r--r--src/utils/trace.c11
-rw-r--r--src/utils/utils_module_tests.c39
-rw-r--r--src/utils/wpa_debug.c147
-rw-r--r--src/utils/wpa_debug.h2
-rw-r--r--src/utils/wpabuf.h15
-rw-r--r--src/utils/xml_libxml2.c2
-rw-r--r--src/wps/Makefile15
-rw-r--r--src/wps/upnp_xml.c2
-rw-r--r--src/wps/wps.h14
-rw-r--r--src/wps/wps_attr_build.c6
-rw-r--r--src/wps/wps_dev_attr.c17
-rw-r--r--src/wps/wps_dev_attr.h1
-rw-r--r--src/wps/wps_enrollee.c11
-rw-r--r--src/wps/wps_er.c6
-rw-r--r--src/wps/wps_registrar.c68
-rw-r--r--src/wps/wps_upnp.c70
-rw-r--r--src/wps/wps_upnp_ap.c4
-rw-r--r--src/wps/wps_upnp_event.c34
-rw-r--r--src/wps/wps_upnp_i.h12
-rw-r--r--src/wps/wps_upnp_web.c4
-rw-r--r--tests/.gitignore19
-rw-r--r--tests/Makefile132
-rw-r--r--tests/ap-mgmt-fuzzer/.gitignore1
-rw-r--r--tests/ap-mgmt-fuzzer/Makefile82
-rw-r--r--tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c194
-rw-r--r--tests/ap-mgmt-fuzzer/auth.datbin30 -> 0 bytes
-rw-r--r--tests/ap-mgmt-fuzzer/multi.datbin246 -> 0 bytes
-rw-r--r--tests/ap-mgmt-fuzzer/probe-req.datbin83 -> 0 bytes
-rw-r--r--tests/build/build-hostapd-internal.config1
-rw-r--r--tests/build/build-hostapd-minimal.config2
-rw-r--r--tests/build/build-wpa_supplicant-internal.config1
-rw-r--r--tests/eapol-fuzzer/Makefile64
-rw-r--r--tests/eapol-fuzzer/eap-req-identity.datbin9 -> 0 bytes
-rw-r--r--tests/eapol-fuzzer/eap-req-sim.datbin24 -> 0 bytes
-rw-r--r--tests/eapol-fuzzer/eapol-fuzzer.c215
-rw-r--r--tests/eapol-fuzzer/eapol-key-m1.datbin99 -> 0 bytes
-rw-r--r--tests/fuzzing/ap-mgmt/.gitignore1
-rw-r--r--tests/fuzzing/ap-mgmt/Makefile22
-rw-r--r--tests/fuzzing/asn1/.gitignore1
-rw-r--r--tests/fuzzing/asn1/Makefile18
-rw-r--r--tests/fuzzing/dpp-uri/.gitignore1
-rw-r--r--tests/fuzzing/dpp-uri/Makefile43
-rw-r--r--tests/fuzzing/dpp-uri/corpus/1.dat1
-rw-r--r--tests/fuzzing/dpp-uri/corpus/2.dat1
-rw-r--r--tests/fuzzing/dpp-uri/corpus/3.dat1
-rw-r--r--tests/fuzzing/dpp-uri/dpp-uri.c51
-rw-r--r--tests/fuzzing/eap-aka-peer/.gitignore1
-rw-r--r--tests/fuzzing/eap-aka-peer/Makefile17
-rw-r--r--tests/fuzzing/eap-mschapv2-peer/.gitignore1
-rw-r--r--tests/fuzzing/eap-mschapv2-peer/Makefile25
-rw-r--r--tests/fuzzing/eap-mschapv2-peer/corpus/server.msgbin0 -> 304 bytes
-rw-r--r--tests/fuzzing/eap-mschapv2-peer/eap-mschapv2-peer.c152
-rw-r--r--tests/fuzzing/eap-sim-peer/.gitignore1
-rw-r--r--tests/fuzzing/eap-sim-peer/Makefile17
-rw-r--r--tests/fuzzing/eapol-key-auth/.gitignore1
-rw-r--r--tests/fuzzing/eapol-key-auth/Makefile19
-rw-r--r--tests/fuzzing/eapol-key-auth/eapol-key-auth.c7
-rw-r--r--tests/fuzzing/eapol-key-supp/.gitignore1
-rw-r--r--tests/fuzzing/eapol-key-supp/Makefile17
-rw-r--r--tests/fuzzing/eapol-key-supp/eapol-key-supp.c6
-rw-r--r--tests/fuzzing/eapol-supp/.gitignore1
-rw-r--r--tests/fuzzing/eapol-supp/Makefile17
-rw-r--r--tests/fuzzing/eapol-supp/eapol-supp.c2
-rw-r--r--tests/fuzzing/json/.gitignore1
-rw-r--r--tests/fuzzing/json/Makefile18
-rw-r--r--tests/fuzzing/p2p/.gitignore1
-rw-r--r--tests/fuzzing/p2p/Makefile17
-rw-r--r--tests/fuzzing/rules.include72
-rw-r--r--tests/fuzzing/sae/.gitignore1
-rw-r--r--tests/fuzzing/sae/Makefile28
-rw-r--r--tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.datbin0 -> 102 bytes
-rw-r--r--tests/fuzzing/sae/corpus/sae-commit-h2e-token.datbin0 -> 101 bytes
-rw-r--r--tests/fuzzing/sae/corpus/sae-commit-pw-id.datbin0 -> 101 bytes
-rw-r--r--tests/fuzzing/sae/corpus/sae-commit-token.datbin0 -> 130 bytes
-rw-r--r--tests/fuzzing/sae/corpus/sae-commit-valid.datbin0 -> 98 bytes
-rw-r--r--tests/fuzzing/sae/sae.c39
-rw-r--r--tests/fuzzing/tls-client/.gitignore1
-rw-r--r--tests/fuzzing/tls-client/Makefile21
-rw-r--r--tests/fuzzing/tls-server/.gitignore1
-rw-r--r--tests/fuzzing/tls-server/Makefile21
-rw-r--r--tests/fuzzing/wnm/.gitignore1
-rw-r--r--tests/fuzzing/wnm/Makefile22
-rw-r--r--tests/fuzzing/x509/.gitignore1
-rw-r--r--tests/fuzzing/x509/Makefile21
-rw-r--r--tests/hwsim/auth_serv/as.conf2
-rw-r--r--tests/hwsim/auth_serv/as2.conf2
-rw-r--r--tests/hwsim/auth_serv/ca-and-crl-expired.pem117
-rw-r--r--tests/hwsim/auth_serv/ca-and-crl.pem118
-rw-r--r--tests/hwsim/auth_serv/ca-incorrect-key.pem28
-rw-r--r--tests/hwsim/auth_serv/ca-incorrect.derbin0 -> 902 bytes
-rw-r--r--tests/hwsim/auth_serv/ca-incorrect.pem102
-rw-r--r--tests/hwsim/auth_serv/ca-key.pem43
-rw-r--r--tests/hwsim/auth_serv/ca.derbin560 -> 868 bytes
-rw-r--r--tests/hwsim/auth_serv/ca.pem102
-rw-r--r--tests/hwsim/auth_serv/dh.conf9
-rw-r--r--tests/hwsim/auth_serv/dsaparam.pem21
-rw-r--r--tests/hwsim/auth_serv/eap_user.conf2
-rw-r--r--tests/hwsim/auth_serv/iCA-server/ca-and-root.pem213
-rw-r--r--tests/hwsim/auth_serv/iCA-server/cacert.pem111
-rw-r--r--tests/hwsim/auth_serv/iCA-server/careq.pem24
-rw-r--r--tests/hwsim/auth_serv/iCA-server/index.txt4
-rw-r--r--tests/hwsim/auth_serv/iCA-server/index.txt.attr2
-rw-r--r--tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB8.pem84
-rw-r--r--tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB9.pem85
-rw-r--r--tests/hwsim/auth_serv/iCA-server/private/cakey.pem52
-rw-r--r--tests/hwsim/auth_serv/iCA-server/serial2
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server-revoked.key52
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server-revoked.pem121
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server-revoked.req24
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server-revoked_and_ica.pem232
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server.key52
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server.pem120
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server.req24
-rw-r--r--tests/hwsim/auth_serv/iCA-server/server_and_ica.pem261
-rw-r--r--tests/hwsim/auth_serv/iCA-user/ca-and-root.pem213
-rw-r--r--tests/hwsim/auth_serv/iCA-user/cacert.pem111
-rw-r--r--tests/hwsim/auth_serv/iCA-user/careq.pem24
-rw-r--r--tests/hwsim/auth_serv/iCA-user/index.txt2
-rw-r--r--tests/hwsim/auth_serv/iCA-user/index.txt.attr2
-rw-r--r--tests/hwsim/auth_serv/iCA-user/newcerts/E153BA3A7605DA1E.pem84
-rw-r--r--tests/hwsim/auth_serv/iCA-user/private/cakey.pem52
-rw-r--r--tests/hwsim/auth_serv/iCA-user/serial2
-rw-r--r--tests/hwsim/auth_serv/iCA-user/user.key52
-rw-r--r--tests/hwsim/auth_serv/iCA-user/user.pem119
-rw-r--r--tests/hwsim/auth_serv/iCA-user/user.req24
-rw-r--r--tests/hwsim/auth_serv/iCA-user/user_and_ica.pem230
-rw-r--r--tests/hwsim/auth_serv/index.txt2
-rw-r--r--tests/hwsim/auth_serv/ocsp-multi-server-cache.derbin346 -> 493 bytes
-rw-r--r--tests/hwsim/auth_serv/ocsp-req.derbin76 -> 76 bytes
-rw-r--r--tests/hwsim/auth_serv/ocsp-responder.csr16
-rw-r--r--tests/hwsim/auth_serv/ocsp-responder.key40
-rw-r--r--tests/hwsim/auth_serv/ocsp-responder.pem92
-rw-r--r--tests/hwsim/auth_serv/ocsp-server-cache.derbin343 -> 490 bytes
-rw-r--r--tests/hwsim/auth_serv/openssl2.cnf2
-rw-r--r--tests/hwsim/auth_serv/rootCA/index.txt4
-rw-r--r--tests/hwsim/auth_serv/rootCA/serial2
-rw-r--r--tests/hwsim/auth_serv/server-certpol.pem78
-rw-r--r--tests/hwsim/auth_serv/server-certpol2.pem78
-rw-r--r--tests/hwsim/auth_serv/server-eku-client-server.csr23
-rw-r--r--tests/hwsim/auth_serv/server-eku-client-server.key40
-rw-r--r--tests/hwsim/auth_serv/server-eku-client-server.pem98
-rw-r--r--tests/hwsim/auth_serv/server-eku-client.csr23
-rw-r--r--tests/hwsim/auth_serv/server-eku-client.key40
-rw-r--r--tests/hwsim/auth_serv/server-eku-client.pem98
-rw-r--r--tests/hwsim/auth_serv/server-expired.csr16
-rw-r--r--tests/hwsim/auth_serv/server-expired.key40
-rw-r--r--tests/hwsim/auth_serv/server-expired.pem103
-rw-r--r--tests/hwsim/auth_serv/server-extra.pkcs12bin2426 -> 3418 bytes
-rw-r--r--tests/hwsim/auth_serv/server-long-duration.csr27
-rw-r--r--tests/hwsim/auth_serv/server-long-duration.key100
-rw-r--r--tests/hwsim/auth_serv/server-long-duration.pem157
-rw-r--r--tests/hwsim/auth_serv/server-no-dnsname.csr23
-rw-r--r--tests/hwsim/auth_serv/server-no-dnsname.key40
-rw-r--r--tests/hwsim/auth_serv/server-no-dnsname.pem98
-rw-r--r--tests/hwsim/auth_serv/server.csr23
-rw-r--r--tests/hwsim/auth_serv/server.key40
-rw-r--r--tests/hwsim/auth_serv/server.pem98
-rw-r--r--tests/hwsim/auth_serv/server.pkcs12bin1685 -> 2549 bytes
-rw-r--r--tests/hwsim/auth_serv/test-ca/cacert.pem102
-rw-r--r--tests/hwsim/auth_serv/test-ca/crlnumber1
-rw-r--r--tests/hwsim/auth_serv/test-ca/index.txt67
-rw-r--r--tests/hwsim/auth_serv/test-ca/private/cakey.pem43
-rw-r--r--tests/hwsim/auth_serv/test-ca/serial2
-rwxr-xr-xtests/hwsim/auth_serv/update.sh96
-rw-r--r--tests/hwsim/auth_serv/user.csr23
-rw-r--r--tests/hwsim/auth_serv/user.key40
-rw-r--r--tests/hwsim/auth_serv/user.key.pkcs843
-rw-r--r--tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v1542
-rw-r--r--tests/hwsim/auth_serv/user.pem98
-rw-r--r--tests/hwsim/auth_serv/user.pkcs12bin1653 -> 2517 bytes
-rw-r--r--tests/hwsim/auth_serv/user.rsa-key38
-rw-r--r--tests/hwsim/auth_serv/user2.pkcs12bin2414 -> 3558 bytes
-rw-r--r--tests/hwsim/auth_serv/user3.pkcs12bin2356 -> 3524 bytes
-rw-r--r--tests/hwsim/bss-1.conf11
-rw-r--r--tests/hwsim/bss-2-dup.conf11
-rw-r--r--tests/hwsim/bss-2.conf11
-rw-r--r--tests/hwsim/bss-3.conf11
-rw-r--r--tests/hwsim/bss-4.conf11
-rw-r--r--tests/hwsim/bss-5.conf11
-rw-r--r--tests/hwsim/bss-6.conf11
-rw-r--r--tests/hwsim/bss-ht40-1.conf12
-rw-r--r--tests/hwsim/bss-ht40-2.conf12
-rwxr-xr-xtests/hwsim/build.sh13
-rw-r--r--tests/hwsim/example-hostapd.config3
-rw-r--r--tests/hwsim/example-wpa_supplicant.config3
-rw-r--r--tests/hwsim/hostapd.accept2
-rw-r--r--tests/hwsim/hostapd.accept23
-rw-r--r--tests/hwsim/hostapd.macaddr7
-rw-r--r--tests/hwsim/hostapd.py114
-rw-r--r--tests/hwsim/hwsim_utils.py173
-rw-r--r--tests/hwsim/multi-bss-acs.conf8
-rw-r--r--tests/hwsim/p2p_utils.py20
-rw-r--r--tests/hwsim/remotehost.py87
-rwxr-xr-xtests/hwsim/run-all.sh8
-rwxr-xr-xtests/hwsim/run-tests.py32
-rwxr-xr-xtests/hwsim/start.sh47
-rw-r--r--tests/hwsim/test_ap_acs.py157
-rw-r--r--tests/hwsim/test_ap_ciphers.py310
-rw-r--r--tests/hwsim/test_ap_config.py39
-rw-r--r--tests/hwsim/test_ap_csa.py9
-rw-r--r--tests/hwsim/test_ap_dynamic.py109
-rw-r--r--tests/hwsim/test_ap_eap.py305
-rw-r--r--tests/hwsim/test_ap_ft.py484
-rw-r--r--tests/hwsim/test_ap_hs20.py217
-rw-r--r--tests/hwsim/test_ap_ht.py169
-rw-r--r--tests/hwsim/test_ap_mixed.py3
-rw-r--r--tests/hwsim/test_ap_open.py98
-rw-r--r--tests/hwsim/test_ap_params.py64
-rw-r--r--tests/hwsim/test_ap_pmf.py453
-rw-r--r--tests/hwsim/test_ap_psk.py298
-rw-r--r--tests/hwsim/test_ap_roam.py136
-rw-r--r--tests/hwsim/test_ap_tdls.py20
-rw-r--r--tests/hwsim/test_ap_vht.py122
-rw-r--r--tests/hwsim/test_ap_vlan.py48
-rw-r--r--tests/hwsim/test_ap_wps.py272
-rw-r--r--tests/hwsim/test_bgscan.py44
-rw-r--r--tests/hwsim/test_cfg80211.py2
-rw-r--r--tests/hwsim/test_connect_cmd.py13
-rw-r--r--tests/hwsim/test_dbus.py317
-rw-r--r--tests/hwsim/test_dfs.py211
-rw-r--r--tests/hwsim/test_dpp.py1460
-rw-r--r--tests/hwsim/test_eap.py26
-rw-r--r--tests/hwsim/test_eap_proto.py11
-rw-r--r--tests/hwsim/test_fils.py102
-rw-r--r--tests/hwsim/test_gas.py20
-rw-r--r--tests/hwsim/test_hapd_ctrl.py33
-rw-r--r--tests/hwsim/test_he.py1010
-rw-r--r--tests/hwsim/test_hostapd_oom.py7
-rw-r--r--tests/hwsim/test_hs20_filter.py6
-rw-r--r--tests/hwsim/test_hs20_pps_mo.py3
-rw-r--r--tests/hwsim/test_ibss.py12
-rw-r--r--tests/hwsim/test_ieee8021x.py11
-rw-r--r--tests/hwsim/test_macsec.py99
-rw-r--r--tests/hwsim/test_monitor_interface.py19
-rw-r--r--tests/hwsim/test_multi_ap.py2
-rw-r--r--tests/hwsim/test_nfc_wps.py8
-rw-r--r--tests/hwsim/test_oce.py21
-rw-r--r--tests/hwsim/test_ocv.py218
-rw-r--r--tests/hwsim/test_owe.py311
-rw-r--r--tests/hwsim/test_p2p_autogo.py35
-rw-r--r--tests/hwsim/test_p2p_channel.py12
-rw-r--r--tests/hwsim/test_p2p_concurrency.py3
-rw-r--r--tests/hwsim/test_p2p_discovery.py16
-rw-r--r--tests/hwsim/test_p2p_grpform.py51
-rw-r--r--tests/hwsim/test_p2p_persistent.py2
-rw-r--r--tests/hwsim/test_pmksa_cache.py90
-rw-r--r--tests/hwsim/test_radius.py26
-rw-r--r--tests/hwsim/test_rrm.py68
-rw-r--r--tests/hwsim/test_sae.py1073
-rw-r--r--tests/hwsim/test_sae_pk.py462
-rw-r--r--tests/hwsim/test_scan.py136
-rw-r--r--tests/hwsim/test_sigma_dut.py3027
-rw-r--r--tests/hwsim/test_ssid.py8
-rw-r--r--tests/hwsim/test_sta_dynamic.py49
-rw-r--r--tests/hwsim/test_suite_b.py65
-rw-r--r--tests/hwsim/test_wep.py11
-rw-r--r--tests/hwsim/test_wext.py5
-rw-r--r--tests/hwsim/test_wmediumd.py16
-rw-r--r--tests/hwsim/test_wnm.py32
-rw-r--r--tests/hwsim/test_wpas_ap.py115
-rw-r--r--tests/hwsim/test_wpas_config.py64
-rw-r--r--tests/hwsim/test_wpas_ctrl.py39
-rw-r--r--tests/hwsim/test_wpas_mesh.py193
-rw-r--r--tests/hwsim/tshark.py8
-rw-r--r--tests/hwsim/utils.py109
-rw-r--r--tests/hwsim/vm/README24
-rw-r--r--tests/hwsim/vm/kernel-config2180
-rw-r--r--tests/hwsim/vm/kernel-config.uml131
-rwxr-xr-xtests/hwsim/vm/parallel-vm.py328
-rwxr-xr-xtests/hwsim/vm/vm-run.sh13
-rw-r--r--tests/hwsim/wlantest.py37
-rw-r--r--tests/hwsim/wpasupplicant.py102
-rw-r--r--tests/p2p-fuzzer/Makefile51
-rw-r--r--tests/p2p-fuzzer/go-neg-req.datbin155 -> 0 bytes
-rw-r--r--tests/p2p-fuzzer/invitation-req.datbin123 -> 0 bytes
-rw-r--r--tests/p2p-fuzzer/p2p-fuzzer.c215
-rw-r--r--tests/p2p-fuzzer/p2ps-pd-req.datbin189 -> 0 bytes
-rw-r--r--tests/p2p-fuzzer/proberesp-go.datbin306 -> 0 bytes
-rw-r--r--tests/p2p-fuzzer/proberesp.datbin209 -> 0 bytes
-rw-r--r--tests/remote/config.py6
-rw-r--r--tests/remote/hwsim_wrapper.py14
-rw-r--r--tests/remote/monitor.py24
-rwxr-xr-xtests/remote/run-tests.py45
-rw-r--r--tests/remote/rutils.py22
-rw-r--r--tests/remote/test_monitor.py52
-rw-r--r--tests/test-asn1.c195
-rw-r--r--tests/test-base64.c4
-rw-r--r--tests/test-eapol.c608
-rw-r--r--tests/test-json.c64
-rw-r--r--tests/test-tls.c243
-rw-r--r--tests/test-x509.c47
-rw-r--r--tests/test-x509v3.c1
-rw-r--r--tests/wnm-fuzzer/Makefile94
-rw-r--r--tests/wnm-fuzzer/bss-tm-req.datbin31 -> 0 bytes
-rw-r--r--tests/wnm-fuzzer/wnm-fuzzer.c116
-rw-r--r--tests/wnm-fuzzer/wnm-notif.datbin56 -> 0 bytes
-rw-r--r--wlantest/.gitignore4
-rw-r--r--wlantest/Makefile94
-rw-r--r--wlantest/bss.c27
-rw-r--r--wlantest/monitor.c24
-rw-r--r--wlantest/process.c5
-rw-r--r--wlantest/readpcap.c1
-rw-r--r--wlantest/rx_data.c271
-rw-r--r--wlantest/rx_eapol.c187
-rw-r--r--wlantest/rx_ip.c46
-rw-r--r--wlantest/rx_mgmt.c744
-rw-r--r--wlantest/sta.c3
-rw-r--r--wlantest/wired.c35
-rw-r--r--wlantest/wlantest.c9
-rw-r--r--wlantest/wlantest.h30
-rw-r--r--wlantest/writepcap.c12
-rw-r--r--wpa_supplicant/.gitignore14
-rw-r--r--wpa_supplicant/Android.mk40
-rw-r--r--wpa_supplicant/ChangeLog10
-rw-r--r--wpa_supplicant/Makefile160
-rw-r--r--wpa_supplicant/README4
-rw-r--r--wpa_supplicant/README-DPP69
-rw-r--r--wpa_supplicant/README-HS202
-rw-r--r--wpa_supplicant/android.config12
-rw-r--r--wpa_supplicant/ap.c140
-rw-r--r--wpa_supplicant/binder/binder.h2
-rw-r--r--wpa_supplicant/blacklist.c98
-rw-r--r--wpa_supplicant/blacklist.h9
-rw-r--r--wpa_supplicant/bss.c2
-rw-r--r--wpa_supplicant/bss.h1
-rw-r--r--wpa_supplicant/config.c137
-rw-r--r--wpa_supplicant/config.h34
-rw-r--r--wpa_supplicant/config_file.c76
-rw-r--r--wpa_supplicant/config_ssid.h122
-rw-r--r--wpa_supplicant/config_winreg.c25
-rw-r--r--wpa_supplicant/ctrl_iface.c765
-rw-r--r--wpa_supplicant/ctrl_iface.h6
-rw-r--r--wpa_supplicant/ctrl_iface_named_pipe.c2
-rw-r--r--wpa_supplicant/ctrl_iface_udp.c57
-rw-r--r--wpa_supplicant/ctrl_iface_unix.c30
-rw-r--r--wpa_supplicant/dbus/dbus_new.c76
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c388
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.h6
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers_p2p.c77
-rw-r--r--wpa_supplicant/dbus/dbus_new_introspect.c2
-rw-r--r--wpa_supplicant/defconfig31
-rw-r--r--wpa_supplicant/doc/docbook/.gitignore1
-rw-r--r--wpa_supplicant/dpp_supplicant.c1342
-rw-r--r--wpa_supplicant/dpp_supplicant.h11
-rw-r--r--wpa_supplicant/driver_i.h99
-rw-r--r--wpa_supplicant/eapol_test.c8
-rw-r--r--wpa_supplicant/events.c1315
-rwxr-xr-xwpa_supplicant/examples/dpp-nfc.py1186
-rwxr-xr-xwpa_supplicant/examples/p2p-action-udhcp.sh4
-rwxr-xr-xwpa_supplicant/examples/p2p-action.sh4
-rw-r--r--wpa_supplicant/examples/p2p/p2p_connect.py18
-rw-r--r--wpa_supplicant/examples/p2p/p2p_disconnect.py2
-rw-r--r--wpa_supplicant/examples/p2p/p2p_find.py2
-rw-r--r--wpa_supplicant/examples/p2p/p2p_flush.py2
-rw-r--r--wpa_supplicant/examples/p2p/p2p_group_add.py14
-rw-r--r--wpa_supplicant/examples/p2p/p2p_invite.py10
-rw-r--r--wpa_supplicant/examples/p2p/p2p_listen.py2
-rw-r--r--wpa_supplicant/examples/p2p/p2p_stop_find.py2
-rw-r--r--wpa_supplicant/examples/udhcpd-p2p.conf12
-rw-r--r--wpa_supplicant/gas_query.c62
-rw-r--r--wpa_supplicant/gas_query.h2
-rw-r--r--wpa_supplicant/hs20_supplicant.c5
-rw-r--r--wpa_supplicant/ibss_rsn.c42
-rw-r--r--wpa_supplicant/interworking.c42
-rw-r--r--wpa_supplicant/interworking.h2
-rw-r--r--wpa_supplicant/mesh.c62
-rw-r--r--wpa_supplicant/mesh_mpm.c49
-rw-r--r--wpa_supplicant/mesh_rsn.c16
-rw-r--r--wpa_supplicant/offchannel.c6
-rw-r--r--wpa_supplicant/op_classes.c46
-rw-r--r--wpa_supplicant/p2p_supplicant.c339
-rw-r--r--wpa_supplicant/p2p_supplicant.h16
-rw-r--r--wpa_supplicant/preauth_test.c14
-rw-r--r--wpa_supplicant/robust_av.c160
-rw-r--r--wpa_supplicant/rrm.c43
-rw-r--r--wpa_supplicant/scan.c370
-rw-r--r--wpa_supplicant/scan.h27
-rw-r--r--wpa_supplicant/sme.c362
-rw-r--r--wpa_supplicant/sme.h6
-rw-r--r--wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in2
-rw-r--r--wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in2
-rw-r--r--wpa_supplicant/systemd/wpa_supplicant.service.arg.in2
-rw-r--r--wpa_supplicant/wmm_ac.c2
-rw-r--r--wpa_supplicant/wnm_sta.c23
-rw-r--r--wpa_supplicant/wpa_cli.c210
-rw-r--r--wpa_supplicant/wpa_gui-qt4/icons/.gitignore2
-rw-r--r--wpa_supplicant/wpa_gui-qt4/icons/Makefile18
-rw-r--r--wpa_supplicant/wpa_gui-qt4/peers.cpp4
-rw-r--r--wpa_supplicant/wpa_gui-qt4/wpagui.cpp19
-rw-r--r--wpa_supplicant/wpa_passphrase.c8
-rw-r--r--wpa_supplicant/wpa_priv.c32
-rw-r--r--wpa_supplicant/wpa_supplicant.c711
-rw-r--r--wpa_supplicant/wpa_supplicant.conf112
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h127
-rw-r--r--wpa_supplicant/wpas_glue.c173
-rw-r--r--wpa_supplicant/wpas_kay.c12
-rw-r--r--wpa_supplicant/wpas_module_tests.c17
-rw-r--r--wpa_supplicant/wps_supplicant.c45
-rw-r--r--wpaspy/Makefile1
-rw-r--r--wpaspy/wpaspy.c35
-rw-r--r--wpaspy/wpaspy.py3
695 files changed, 55075 insertions, 24246 deletions
diff --git a/.gitignore b/.gitignore
index 6a985a7..b064303 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,35 +1,8 @@
-*.a
-*.o
-*.d
-*.gcno
-*.gcda
-*.gcov
*.pyc
*~
-.config
tests/hwsim/logs
tests/remote/logs
wpaspy/build
-wpa_supplicant/eapol_test
-wpa_supplicant/nfc_pw_token
-wpa_supplicant/preauth_test
-wpa_supplicant/wpa_cli
-wpa_supplicant/wpa_passphrase
-wpa_supplicant/wpa_supplicant
-wpa_supplicant/wpa_priv
-wpa_supplicant/wpa_gui/Makefile
-wpa_supplicant/wpa_gui/wpa_gui
-wpa_supplicant/wpa_gui-qt4/Makefile
-wpa_supplicant/wpa_gui-qt4/wpa_gui
-wpa_supplicant/libwpa_test1
-wpa_supplicant/libwpa_test2
-hostapd/hostapd
-hostapd/hostapd_cli
-hostapd/hlr_auc_gw
-hostapd/nt_password_hash
-mac80211_hwsim/tools/hwsim_test
-wlantest/libwlantest.a
-wlantest/test_vectors
-wlantest/wlantest
-wlantest/wlantest_cli
**/parallel-vm.log
+tags
+build/
diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen
index 072ed34..06e53b9 100644
--- a/doc/dbus.doxygen
+++ b/doc/dbus.doxygen
@@ -323,6 +323,24 @@ fi.w1.wpa_supplicant1.CreateInterface.
</li>
<li>
+ <h3>Roam ( s : addr ) --> nothing</h3>
+ <p>Initiate a roam to another BSS within the current ESS.</p>
+ <h4>Possible errors</h4>
+ <dl>
+ <dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
+ <dd>Missing address argument.</dd>
+ <dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
+ <dd>Invalid hardware address format.</dd>
+ <dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
+ <dd>Target BSS not found.</dd>
+ <dt>fi.w1.wpa_supplicant1.NotConnected</dt>
+ <dd>Interface is not connected to any network.</dd>
+ <dt>fi.w1.wpa_supplicant1.UnknownError</dt>
+ <dd>Scan processing was not included in the build.</dd>
+ </dl>
+ </li>
+
+ <li>
<h3>AddBlob ( s : name, ay : data ) --> nothing</h3>
<p>Adds a blob to the interface.</p>
<h4>Arguments</h4>
@@ -651,7 +669,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
<tr><td>Pairwise</td><td>as</td><td>Possible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "none"</td>
<tr><td>Group</td><td>as</td><td>Possible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "wep104", "wep40"</td>
<tr><td>GroupMgmt</td><td>as</td><td>Possible array elements: "aes-128-cmac", "bip-gmac-128", "bip-gmac-256", "bip-cmac-256"</td>
- <tr><td>KeyMgmt</td><td>as</td><td>Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "ieee8021x", "wpa-none", "wps", "none"</td>
+ <tr><td>KeyMgmt</td><td>as</td><td>Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "sae", "ieee8021x", "wpa-none", "wps", "none"</td>
<tr><td>Protocol</td><td>as</td><td>Possible array elements: "rsn", "wpa"</td>
<tr><td>AuthAlg</td><td>as</td><td>Possible array elements: "open", "shared", "leap"</td>
<tr><td>Scan</td><td>as</td><td>Possible array elements: "active", "passive", "ssid"</td>
@@ -891,7 +909,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
<li>
<h3>Hessid - s - (read/write)</h3>
- <p>Homogenous ESS identifier</p>
+ <p>Homogeneous ESS identifier</p>
</li>
<li>
@@ -1043,6 +1061,12 @@ fi.w1.wpa_supplicant1.CreateInterface.
<h3>WpsPriority - s - (read/write)</h3>
<p>Priority for the networks added through WPS</p>
</li>
+
+ <li>
+ <h3>MACAddressRandomizationMask - a{say} - (read/write)</h3>
+ <p>Masks to show which bits not to randomize with MAC address randomization. Possible keys are "scan", "sched_scan", and "pno". Values must be an array of 6 bytes.</p>
+ <p>When this property is set, the new dictionary replaces the old value, rather than merging them together. Leaving a key out of the dictionary will turn off MAC address randomization for that scan type.</p>
+ </li>
</ul>
\subsection dbus_interface_signals Signals
@@ -2031,7 +2055,7 @@ scan results.
<tr><td>KeyMgmt</td><td>as</td><td>Key management suite. Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "wpa-eap-suite-b", "wpa-eap-suite-b-192", "wpa-fils-sha256", "wpa-fils-sha384", "wpa-ft-fils-sha256", "wpa-ft-fils-sha384", "sae", "ft-sae", "wpa-none"</td>
<tr><td>Pairwise</td><td>as</td><td>Pairwise cipher suites. Possible array elements: "ccmp", "tkip"</td>
<tr><td>Group</td><td>s</td><td>Group cipher suite. Possible values are: "ccmp", "tkip", "wep104", "wep40"</td>
- <tr><td>MgmtGroup</td><td>s</td><td>Mangement frames cipher suite. Possible values are: "aes128cmac"</td>
+ <tr><td>MgmtGroup</td><td>s</td><td>Management frames cipher suite. Possible values are: "aes128cmac"</td>
</table>
</li>
<li>
@@ -2101,7 +2125,7 @@ i.e., returned by fi.w1.wpa_supplicant1.Interface.AddNetwork.
<li>
<h3>Properties - a{sv} - (read/write)</h3>
- <p>Properties of the configured network. Dictionary contains entries from "network" block of wpa_supplicant configuration file. All values are string type, e.g., frequency is "2437", not 2437.
+ <p>Properties of the configured network. Dictionary contains entries from "network" block of wpa_supplicant configuration file. All values are string type, e.g., frequency is "2437", not 2437. When setting the properties, use the same format as for the AddNetwork() function.</p>
</li>
</ul>
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
index cf28790..3f01173 100644
--- a/doc/doxygen.conf
+++ b/doc/doxygen.conf
@@ -278,7 +278,7 @@ TYPEDEF_HIDES_STRUCT = NO
# For small to medium size projects (<1000 input files) the default value is
# probably good enough. For larger projects a too small cache size can cause
# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penality.
+# causing a significant performance penalty.
# If the system has enough physical memory increasing the cache will improve the
# performance by keeping more symbols in memory. Note that the value works on
# a logarithmic scale so increasing the size by one will roughly double the
diff --git a/doc/driver_wrapper.doxygen b/doc/driver_wrapper.doxygen
index a3b470a..66211b3 100644
--- a/doc/driver_wrapper.doxygen
+++ b/doc/driver_wrapper.doxygen
@@ -156,7 +156,7 @@ ap_scan=1:
- wpa_supplicant requests scan with SIOCSIWSCAN
- driver reports scan complete with wireless event SIOCGIWSCAN
- wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if
- a larget buffer is needed)
+ a larger buffer is needed)
- wpa_supplicant decides which AP to use based on scan results
- wpa_supplicant configures driver to associate with the selected BSS
(SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ,
diff --git a/doc/p2p.doxygen b/doc/p2p.doxygen
index f46d1b8..d4d86e3 100644
--- a/doc/p2p.doxygen
+++ b/doc/p2p.doxygen
@@ -283,7 +283,7 @@ service discovery. The user of the P2P module is responsible for
providing P2P specific Service Request TLV(s) for queries and Service
Response TLV(s) for responses.
-\subsection p2p_sd_query Quering services of peers
+\subsection p2p_sd_query Querying services of peers
Service discovery is implemented by processing pending queries as a
part of the device discovery phase. \ref p2p_sd_request() function is used
diff --git a/eap_example/Makefile b/eap_example/Makefile
index 0cc19bd..691466f 100644
--- a/eap_example/Makefile
+++ b/eap_example/Makefile
@@ -1,28 +1,15 @@
ALL=eap_example
-all: $(ALL)
-
-ifndef CC
-CC=gcc
-endif
-
-ifndef RANLIB
-RANLIB=ranlib
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
-
+include ../src/build.rules
CFLAGS += -I.
CFLAGS += -I../src
CFLAGS += -I../src/utils
-OBJS_both += ../src/utils/libutils.a
-OBJS_both += ../src/crypto/libcrypto.a
-OBJS_both += ../src/tls/libtls.a
+EAP_LIBS += ../src/utils/libutils.a
+EAP_LIBS += ../src/crypto/libcrypto.a
+EAP_LIBS += ../src/tls/libtls.a
OBJS_both += ../src/eap_common/eap_peap_common.o
OBJS_both += ../src/eap_common/eap_psk_common.o
@@ -95,41 +82,22 @@ OBJS_server += ../src/eap_server/eap_server_tls_common.o
CFLAGS += -DEAP_SERVER
-ifndef LDO
-LDO=$(CC)
-endif
-
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-
-%.o: %.c
- $(Q)$(CC) -c -o $@ $(CFLAGS) $<
- @$(E) " CC " $<
-
-
OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server)
+_OBJS_VAR := OBJS_lib
+include ../src/objs.mk
OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o
+_OBJS_VAR := OBJS_ex
+include ../src/objs.mk
-
-../src/utils/libutils.a:
- $(MAKE) -C ../src/utils
-
-../src/crypto/libcrypto.a:
- $(MAKE) -C ../src/crypto
-
-../src/tls/libtls.a:
- $(MAKE) -C ../src/tls
+_OBJS_VAR := EAP_LIBS
+include ../src/objs.mk
ifneq ($(CONFIG_SOLIB), yes)
LIBEAP = libeap.a
-libeap.a: $(OBJS_lib)
- $(AR) crT libeap.a $(OBJS_lib)
+libeap.a: $(EAP_LIBS) $(OBJS_lib)
+ $(AR) crT libeap.a $^
$(RANLIB) libeap.a
else
@@ -137,16 +105,15 @@ CFLAGS += -fPIC -DPIC
LDFLAGS += -shared
LIBEAP = libeap.so
-libeap.so: $(OBJS_lib)
- $(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBEAP)
+libeap.so: $(EAP_LIBS) $(OBJS_lib)
+ $(LDO) $(LDFLAGS) $^ -o $(LIBEAP)
endif
eap_example: $(OBJS_ex) $(LIBEAP)
$(LDO) $(LDFLAGS) -o eap_example $(OBJS_ex) -L. -leap $(LIBS)
-clean:
- $(MAKE) -C ../src clean
- rm -f core *~ *.o *.d libeap.a libeap.so $(ALL)
+clean: common-clean
+ rm -f core *~ *.o *.d libeap.a libeap.so
-include $(OBJS:%.o=%.d)
diff --git a/eap_example/eap_example_peer.c b/eap_example/eap_example_peer.c
index fcbfb12..5fe0cb7 100644
--- a/eap_example/eap_example_peer.c
+++ b/eap_example/eap_example_peer.c
@@ -18,16 +18,16 @@ void eap_example_server_rx(const u8 *data, size_t data_len);
struct eap_peer_ctx {
- Boolean eapSuccess;
- Boolean eapRestart;
- Boolean eapFail;
- Boolean eapResp;
- Boolean eapNoResp;
- Boolean eapReq;
- Boolean portEnabled;
- Boolean altAccept; /* for EAP */
- Boolean altReject; /* for EAP */
- Boolean eapTriggerStart;
+ bool eapSuccess;
+ bool eapRestart;
+ bool eapFail;
+ bool eapResp;
+ bool eapNoResp;
+ bool eapReq;
+ bool portEnabled;
+ bool altAccept; /* for EAP */
+ bool altReject; /* for EAP */
+ bool eapTriggerStart;
struct wpabuf *eapReqData; /* for EAP */
@@ -48,11 +48,11 @@ static struct eap_peer_config * peer_get_config(void *ctx)
}
-static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable)
+static bool peer_get_bool(void *ctx, enum eapol_bool_var variable)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL)
- return FALSE;
+ return false;
switch (variable) {
case EAPOL_eapSuccess:
return peer->eapSuccess;
@@ -75,12 +75,11 @@ static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable)
case EAPOL_eapTriggerStart:
return peer->eapTriggerStart;
}
- return FALSE;
+ return false;
}
-static void peer_set_bool(void *ctx, enum eapol_bool_var variable,
- Boolean value)
+static void peer_set_bool(void *ctx, enum eapol_bool_var variable, bool value)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL)
@@ -319,7 +318,7 @@ int eap_example_peer_init(void)
return -1;
/* Enable "port" to allow authentication */
- eap_ctx.portEnabled = TRUE;
+ eap_ctx.portEnabled = true;
return 0;
}
@@ -344,7 +343,7 @@ int eap_example_peer_step(void)
if (eap_ctx.eapResp) {
struct wpabuf *resp;
printf("==> Response\n");
- eap_ctx.eapResp = FALSE;
+ eap_ctx.eapResp = false;
resp = eap_get_eapRespData(eap_ctx.eap);
if (resp) {
/* Send EAP response to the server */
@@ -372,7 +371,7 @@ int eap_example_peer_step(void)
void eap_example_peer_rx(const u8 *data, size_t data_len)
{
/* Make received EAP message available to the EAP library */
- eap_ctx.eapReq = TRUE;
+ eap_ctx.eapReq = true;
wpabuf_free(eap_ctx.eapReqData);
eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len);
}
diff --git a/eap_example/eap_example_server.c b/eap_example/eap_example_server.c
index 1e91fa8..3a132bb 100644
--- a/eap_example/eap_example_server.c
+++ b/eap_example/eap_example_server.c
@@ -234,8 +234,8 @@ int eap_example_server_init(void)
eap_ctx.eap_if = eap_get_interface(eap_ctx.eap);
/* Enable "port" and request EAP to start authentication. */
- eap_ctx.eap_if->portEnabled = TRUE;
- eap_ctx.eap_if->eapRestart = TRUE;
+ eap_ctx.eap_if->portEnabled = true;
+ eap_ctx.eap_if->eapRestart = true;
return 0;
}
@@ -296,5 +296,5 @@ void eap_example_server_rx(const u8 *data, size_t data_len)
wpabuf_free(eap_ctx.eap_if->eapRespData);
eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
if (eap_ctx.eap_if->eapRespData)
- eap_ctx.eap_if->eapResp = TRUE;
+ eap_ctx.eap_if->eapResp = true;
}
diff --git a/hostapd/.gitignore b/hostapd/.gitignore
new file mode 100644
index 0000000..857f3dc
--- /dev/null
+++ b/hostapd/.gitignore
@@ -0,0 +1,5 @@
+.config
+hostapd
+hostapd_cli
+hlr_auc_gw
+nt_password_hash
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index a87ac81..6c95617 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -145,6 +145,7 @@ OBJS += src/utils/wpa_debug.c
OBJS += src/utils/wpabuf.c
OBJS += src/utils/os_$(CONFIG_OS).c
OBJS += src/utils/ip_addr.c
+OBJS += src/utils/crc32.c
OBJS += src/common/ieee802_11_common.c
OBJS += src/common/wpa_common.c
@@ -249,8 +250,13 @@ endif
ifdef CONFIG_SAE
L_CFLAGS += -DCONFIG_SAE
OBJS += src/common/sae.c
+ifdef CONFIG_SAE_PK
+L_CFLAGS += -DCONFIG_SAE_PK
+OBJS += src/common/sae_pk.c
+endif
NEED_ECC=y
NEED_DH_GROUPS=y
+NEED_HMAC_SHA256_KDF=y
NEED_DRAGONFLY=y
endif
@@ -280,10 +286,6 @@ L_CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP
OBJS += src/ap/wnm_ap.c
endif
-ifdef CONFIG_IEEE80211N
-L_CFLAGS += -DCONFIG_IEEE80211N
-endif
-
ifdef CONFIG_IEEE80211AC
L_CFLAGS += -DCONFIG_IEEE80211AC
endif
@@ -312,6 +314,14 @@ OBJS += src/fst/fst_ctrl_iface.c
endif
endif
+ifdef CONFIG_WEP
+L_CFLAGS += -DCONFIG_WEP
+endif
+
+ifdef CONFIG_NO_TKIP
+L_CFLAGS += -DCONFIG_NO_TKIP
+endif
+
include $(LOCAL_PATH)/src/drivers/drivers.mk
@@ -404,7 +414,7 @@ endif
ifdef CONFIG_EAP_SIM_COMMON
OBJS += src/eap_common/eap_sim_common.c
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
-# replaced with another file implementating the interface specified in
+# replaced with another file implementing the interface specified in
# eap_sim_db.h.
OBJS += src/eap_server/eap_sim_db.c
NEED_FIPS186_2_PRF=y
@@ -531,6 +541,12 @@ endif
ifdef CONFIG_DPP
L_CFLAGS += -DCONFIG_DPP
OBJS += src/common/dpp.c
+OBJS += src/common/dpp_auth.c
+OBJS += src/common/dpp_backup.c
+OBJS += src/common/dpp_crypto.c
+OBJS += src/common/dpp_pkex.c
+OBJS += src/common/dpp_reconfig.c
+OBJS += src/common/dpp_tcp.c
OBJS += src/ap/dpp_hostapd.c
OBJS += src/ap/gas_query_ap.c
NEED_AES_SIV=y
@@ -543,6 +559,7 @@ NEED_ECC=y
NEED_JSON=y
NEED_GAS=y
NEED_BASE64=y
+NEED_ASN1=y
ifdef CONFIG_DPP2
L_CFLAGS += -DCONFIG_DPP2
endif
@@ -680,12 +697,12 @@ OBJS += src/tls/tlsv1_cred.c
OBJS += src/tls/tlsv1_server.c
OBJS += src/tls/tlsv1_server_write.c
OBJS += src/tls/tlsv1_server_read.c
-OBJS += src/tls/asn1.c
OBJS += src/tls/rsa.c
OBJS += src/tls/x509v3.c
OBJS += src/tls/pkcs1.c
OBJS += src/tls/pkcs5.c
OBJS += src/tls/pkcs8.c
+NEED_ASN1=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
@@ -935,6 +952,10 @@ L_CFLAGS += -DCONFIG_INTERNAL_SHA512
OBJS += src/crypto/sha512-internal.c
endif
+ifdef NEED_ASN1
+OBJS += src/tls/asn1.c
+endif
+
ifdef NEED_DH_GROUPS
OBJS += src/crypto/dh_groups.c
endif
@@ -993,9 +1014,7 @@ OBJS += src/ap/hw_features.c
OBJS += src/ap/dfs.c
L_CFLAGS += -DNEED_AP_MLME
endif
-ifdef CONFIG_IEEE80211N
OBJS += src/ap/ieee802_11_ht.c
-endif
ifdef CONFIG_IEEE80211AC
OBJS += src/ap/ieee802_11_vht.c
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
index 6c4410e..34a8a08 100644
--- a/hostapd/ChangeLog
+++ b/hostapd/ChangeLog
@@ -362,7 +362,7 @@ ChangeLog for hostapd
* RADIUS server functionality
- add minimal RADIUS accounting server support (hostapd-as-server);
this is mainly to enable testing coverage with hwsim scripts
- - allow authentication log to be written into SQLite databse
+ - allow authentication log to be written into SQLite database
- added option for TLS protocol testing of an EAP peer by simulating
various misbehaviors/known attacks
- MAC ACL support for testing purposes
@@ -668,7 +668,7 @@ ChangeLog for hostapd
* fixed HT Capabilities IE with nl80211 drivers
* moved generic AP functionality code into src/ap
* WPS: handle Selected Registrar as union of info from all Registrars
- * remove obsolte Prism54.org driver wrapper
+ * remove obsolete Prism54.org driver wrapper
* added internal debugging mechanism with backtrace support and memory
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 42bb9e4..456fb18 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -1,10 +1,7 @@
-ifndef CC
-CC=gcc
-endif
+ALL=hostapd hostapd_cli
+CONFIG_FILE = .config
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../src/build.rules
ifdef LIBS
# If LIBS is set with some global build system defaults, clone those for
@@ -19,6 +16,9 @@ endif
ifndef LIBS_n
LIBS_n := $(LIBS)
endif
+ifndef LIBS_s
+LIBS_s := $(LIBS)
+endif
endif
CFLAGS += $(EXTRA_CFLAGS)
@@ -27,8 +27,6 @@ CFLAGS += -I$(abspath ../src/utils)
export BINDIR ?= /usr/local/bin/
--include .config
-
ifndef CONFIG_NO_GITVER
# Add VERSION_STR postfix for builds from a git repository
ifeq ($(wildcard ../.git),../.git)
@@ -121,6 +119,8 @@ CFLAGS += -DPACKAGE="hostapd" -DWPA_TRACE_BFD
LIBS += -lbfd -ldl -liberty -lz
LIBS_c += -lbfd -ldl -liberty -lz
LIBS_h += -lbfd -ldl -liberty -lz
+LIBS_n += -lbfd -ldl -liberty -lz
+LIBS_s += -lbfd -ldl -liberty -lz
endif
endif
@@ -157,6 +157,7 @@ OBJS_c += ../src/utils/wpa_debug.o
OBJS += ../src/utils/wpabuf.o
OBJS += ../src/utils/os_$(CONFIG_OS).o
OBJS += ../src/utils/ip_addr.o
+OBJS += ../src/utils/crc32.o
OBJS += ../src/common/ieee802_11_common.o
OBJS += ../src/common/wpa_common.o
@@ -292,8 +293,13 @@ endif
ifdef CONFIG_SAE
CFLAGS += -DCONFIG_SAE
OBJS += ../src/common/sae.o
+ifdef CONFIG_SAE_PK
+CFLAGS += -DCONFIG_SAE_PK
+OBJS += ../src/common/sae_pk.o
+endif
NEED_ECC=y
NEED_DH_GROUPS=y
+NEED_HMAC_SHA256_KDF=y
NEED_AP_MLME=y
NEED_DRAGONFLY=y
endif
@@ -329,10 +335,6 @@ CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP
OBJS += ../src/ap/wnm_ap.o
endif
-ifdef CONFIG_IEEE80211N
-CFLAGS += -DCONFIG_IEEE80211N
-endif
-
ifdef CONFIG_IEEE80211AC
CFLAGS += -DCONFIG_IEEE80211AC
endif
@@ -442,7 +444,7 @@ endif
ifdef CONFIG_EAP_SIM_COMMON
OBJS += ../src/eap_common/eap_sim_common.o
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
-# replaced with another file implementating the interface specified in
+# replaced with another file implementing the interface specified in
# eap_sim_db.h.
OBJS += ../src/eap_server/eap_sim_db.o
NEED_FIPS186_2_PRF=y
@@ -569,6 +571,12 @@ endif
ifdef CONFIG_DPP
CFLAGS += -DCONFIG_DPP
OBJS += ../src/common/dpp.o
+OBJS += ../src/common/dpp_auth.o
+OBJS += ../src/common/dpp_backup.o
+OBJS += ../src/common/dpp_crypto.o
+OBJS += ../src/common/dpp_pkex.o
+OBJS += ../src/common/dpp_reconfig.o
+OBJS += ../src/common/dpp_tcp.o
OBJS += ../src/ap/dpp_hostapd.o
OBJS += ../src/ap/gas_query_ap.o
NEED_AES_SIV=y
@@ -581,6 +589,7 @@ NEED_ECC=y
NEED_JSON=y
NEED_GAS=y
NEED_BASE64=y
+NEED_ASN1=y
ifdef CONFIG_DPP2
CFLAGS += -DCONFIG_DPP2
endif
@@ -694,6 +703,7 @@ LIBS += -lssl
endif
OBJS += ../src/crypto/crypto_openssl.o
HOBJS += ../src/crypto/crypto_openssl.o
+SOBJS += ../src/crypto/crypto_openssl.o
ifdef NEED_FIPS186_2_PRF
OBJS += ../src/crypto/fips_prf_openssl.o
endif
@@ -701,9 +711,11 @@ NEED_TLS_PRF_SHA256=y
LIBS += -lcrypto
LIBS_h += -lcrypto
LIBS_n += -lcrypto
+LIBS_s += -lcrypto
ifdef CONFIG_TLS_ADD_DL
LIBS += -ldl
LIBS_h += -ldl
+LIBS_s += -ldl
endif
ifndef CONFIG_TLS_DEFAULT_CIPHERS
CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
@@ -754,12 +766,12 @@ OBJS += ../src/tls/tlsv1_cred.o
OBJS += ../src/tls/tlsv1_server.o
OBJS += ../src/tls/tlsv1_server_write.o
OBJS += ../src/tls/tlsv1_server_read.o
-OBJS += ../src/tls/asn1.o
OBJS += ../src/tls/rsa.o
OBJS += ../src/tls/x509v3.o
OBJS += ../src/tls/pkcs1.o
OBJS += ../src/tls/pkcs5.o
OBJS += ../src/tls/pkcs8.o
+NEED_ASN1=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
@@ -830,12 +842,12 @@ OBJS += ../src/tls/tlsv1_cred.o
OBJS += ../src/tls/tlsv1_server.o
OBJS += ../src/tls/tlsv1_server_write.o
OBJS += ../src/tls/tlsv1_server_read.o
-OBJS += ../src/tls/asn1.o
OBJS += ../src/tls/rsa.o
OBJS += ../src/tls/x509v3.o
OBJS += ../src/tls/pkcs1.o
OBJS += ../src/tls/pkcs5.o
OBJS += ../src/tls/pkcs8.o
+NEED_ASN1=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
@@ -1083,6 +1095,10 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512
OBJS += ../src/crypto/sha512-internal.o
endif
+ifdef NEED_ASN1
+OBJS += ../src/tls/asn1.o
+endif
+
ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_groups.o
endif
@@ -1148,9 +1164,7 @@ OBJS += ../src/ap/hw_features.o
OBJS += ../src/ap/dfs.o
CFLAGS += -DNEED_AP_MLME
endif
-ifdef CONFIG_IEEE80211N
OBJS += ../src/ap/ieee802_11_ht.o
-endif
ifdef CONFIG_IEEE80211AC
OBJS += ../src/ap/ieee802_11_vht.o
@@ -1237,60 +1251,33 @@ OBJS += ../src/fst/fst_ctrl_iface.o
endif
endif
-ALL=hostapd hostapd_cli
-
-all: verify_config $(ALL)
-
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-ifeq ($(QUIET), 1)
-Q=@
-E=true
+ifdef CONFIG_WEP
+CFLAGS += -DCONFIG_WEP
endif
-ifdef CONFIG_CODE_COVERAGE
-%.o: %.c
- @$(E) " CC " $<
- $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
-else
-%.o: %.c
- $(Q)$(CC) -c -o $@ $(CFLAGS) $<
- @$(E) " CC " $<
+ifdef CONFIG_NO_TKIP
+CFLAGS += -DCONFIG_NO_TKIP
endif
-verify_config:
- @if [ ! -r .config ]; then \
- echo 'Building hostapd requires a configuration file'; \
- echo '(.config). See README for more instructions. You can'; \
- echo 'run "cp defconfig .config" to create an example'; \
- echo 'configuration.'; \
- exit 1; \
- fi
-
$(DESTDIR)$(BINDIR)/%: %
install -D $(<) $(@)
install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
-../src/drivers/build.hostapd:
- @if [ -f ../src/drivers/build.wpa_supplicant ]; then \
- $(MAKE) -C ../src/drivers clean; \
- fi
- @touch ../src/drivers/build.hostapd
-
-BCHECK=../src/drivers/build.hostapd
+_OBJS_VAR := OBJS
+include ../src/objs.mk
-hostapd: $(BCHECK) $(OBJS)
+hostapd: $(OBJS)
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
@$(E) " LD " $@
ifdef CONFIG_WPA_TRACE
OBJS_c += ../src/utils/trace.o
endif
+
+_OBJS_VAR := OBJS_c
+include ../src/objs.mk
+
hostapd_cli: $(OBJS_c)
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
@$(E) " LD " $@
@@ -1313,7 +1300,6 @@ NOBJS += ../src/utils/wpa_debug.o
NOBJS += ../src/utils/wpabuf.o
ifdef CONFIG_WPA_TRACE
NOBJS += ../src/utils/trace.o
-LIBS_n += -lbfd
endif
HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o
@@ -1326,6 +1312,35 @@ ifeq ($(CONFIG_TLS), linux)
HOBJS += ../src/crypto/crypto_linux.o
endif
+SOBJS += sae_pk_gen.o
+SOBJS += ../src/utils/common.o
+SOBJS += ../src/utils/os_$(CONFIG_OS).o
+SOBJS += ../src/utils/base64.o
+SOBJS += ../src/utils/wpa_debug.o
+SOBJS += ../src/utils/wpabuf.o
+ifdef CONFIG_WPA_TRACE
+SOBJS += ../src/utils/trace.o
+endif
+SOBJS += ../src/common/ieee802_11_common.o
+SOBJS += ../src/common/sae.o
+SOBJS += ../src/common/sae_pk.o
+SOBJS += ../src/common/dragonfly.o
+SOBJS += $(AESOBJS)
+SOBJS += ../src/crypto/sha256-prf.o
+SOBJS += ../src/crypto/sha384-prf.o
+SOBJS += ../src/crypto/sha512-prf.o
+SOBJS += ../src/crypto/dh_groups.o
+SOBJS += ../src/crypto/sha256-kdf.o
+SOBJS += ../src/crypto/sha384-kdf.o
+SOBJS += ../src/crypto/sha512-kdf.o
+
+_OBJS_VAR := NOBJS
+include ../src/objs.mk
+_OBJS_VAR := HOBJS
+include ../src/objs.mk
+_OBJS_VAR := SOBJS
+include ../src/objs.mk
+
nt_password_hash: $(NOBJS)
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
@$(E) " LD " $@
@@ -1334,15 +1349,17 @@ hlr_auc_gw: $(HOBJS)
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
@$(E) " LD " $@
+sae_pk_gen: $(SOBJS)
+ $(Q)$(CC) $(LDFLAGS) -o sae_pk_gen $(SOBJS) $(LIBS_s)
+ @$(E) " LD " $@
+
+.PHONY: lcov-html
lcov-html:
- lcov -c -d .. > lcov.info
+ lcov -c -d $(BUILDDIR) > lcov.info
genhtml lcov.info --output-directory lcov-html
-clean:
- $(MAKE) -C ../src clean
- rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
- rm -f *.d *.gcno *.gcda *.gcov
+clean: common-clean
+ rm -f core *~ nt_password_hash hlr_auc_gw
+ rm -f sae_pk_gen
rm -f lcov.info
rm -rf lcov-html
-
--include $(OBJS:%.o=%.d)
diff --git a/hostapd/android.config b/hostapd/android.config
index e2e6c78..7bd792e 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -125,9 +125,6 @@ CONFIG_IPV6=y
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
#CONFIG_DRIVER_RADIUS_ACL=y
-# IEEE 802.11n (High Throughput) support
-CONFIG_IEEE80211N=y
-
# Remove debugging code that is printing out debug messages to stdout.
# This can be used to reduce the size of the hostapd considerably if debugging
# code is not needed.
@@ -187,7 +184,7 @@ CONFIG_AP=y
#CONFIG_FST=y
# Multiband Operation support
-# These extentions facilitate efficient use of multiple frequency bands
+# These extensions facilitate efficient use of multiple frequency bands
# available to the AP and the devices that may associate with it.
#CONFIG_MBO=y
@@ -204,3 +201,11 @@ CONFIG_WPA_CLI_EDIT=y
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
# either wpa_supplicant or hostapd are run.
CONFIG_NO_RANDOM_POOL=y
+
+# Wired equivalent privacy (WEP)
+# WEP is an obsolete cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used for anything anymore. The
+# functionality needed to use WEP is available in the current hostapd
+# release under this optional build parameter. This functionality is subject to
+# be completely removed in a future release.
+CONFIG_WEP=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 40066ad..ce32f3c 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -14,6 +14,7 @@
#include "utils/common.h"
#include "utils/uuid.h"
#include "common/ieee802_11_defs.h"
+#include "common/sae.h"
#include "crypto/sha256.h"
#include "crypto/tls.h"
#include "drivers/driver.h"
@@ -340,7 +341,7 @@ static int hostapd_config_read_eap_user(const char *fname,
struct hostapd_radius_attr *attr, *a;
attr = hostapd_parse_radius_attr(buf + 19);
if (attr == NULL) {
- wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
+ wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s",
buf + 19);
user = NULL; /* already in the BSS list */
goto failed;
@@ -793,6 +794,7 @@ static int hostapd_config_parse_cipher(int line, const char *value)
}
+#ifdef CONFIG_WEP
static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
char *val)
{
@@ -843,6 +845,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
return 0;
}
+#endif /* CONFIG_WEP */
static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
@@ -940,104 +943,6 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
}
-/* convert floats with one decimal place to value*10 int, i.e.,
- * "1.5" will return 15 */
-static int hostapd_config_read_int10(const char *value)
-{
- int i, d;
- char *pos;
-
- i = atoi(value);
- pos = os_strchr(value, '.');
- d = 0;
- if (pos) {
- pos++;
- if (*pos >= '0' && *pos <= '9')
- d = *pos - '0';
- }
-
- return i * 10 + d;
-}
-
-
-static int valid_cw(int cw)
-{
- return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
- cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
- cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
- cw == 32767);
-}
-
-
-enum {
- IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
- IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
- IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
- IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
-};
-
-static int hostapd_config_tx_queue(struct hostapd_config *conf,
- const char *name, const char *val)
-{
- int num;
- const char *pos;
- struct hostapd_tx_queue_params *queue;
-
- /* skip 'tx_queue_' prefix */
- pos = name + 9;
- if (os_strncmp(pos, "data", 4) == 0 &&
- pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
- num = pos[4] - '0';
- pos += 6;
- } else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
- os_strncmp(pos, "beacon_", 7) == 0) {
- wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
- return 0;
- } else {
- wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
- return -1;
- }
-
- if (num >= NUM_TX_QUEUES) {
- /* for backwards compatibility, do not trigger failure */
- wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
- return 0;
- }
-
- queue = &conf->tx_queue[num];
-
- if (os_strcmp(pos, "aifs") == 0) {
- queue->aifs = atoi(val);
- if (queue->aifs < 0 || queue->aifs > 255) {
- wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
- queue->aifs);
- return -1;
- }
- } else if (os_strcmp(pos, "cwmin") == 0) {
- queue->cwmin = atoi(val);
- if (!valid_cw(queue->cwmin)) {
- wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
- queue->cwmin);
- return -1;
- }
- } else if (os_strcmp(pos, "cwmax") == 0) {
- queue->cwmax = atoi(val);
- if (!valid_cw(queue->cwmax)) {
- wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
- queue->cwmax);
- return -1;
- }
- } else if (os_strcmp(pos, "burst") == 0) {
- queue->burst = hostapd_config_read_int10(val);
- } else {
- wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
- return -1;
- }
-
- return 0;
-}
-
-
#ifdef CONFIG_IEEE80211R_AP
static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
@@ -1151,7 +1056,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value)
#endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211N
static int hostapd_config_ht_capab(struct hostapd_config *conf,
const char *capab)
{
@@ -1171,14 +1075,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
}
if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
conf->secondary_channel = 0;
- if (os_strstr(capab, "[SMPS-STATIC]")) {
- conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
- conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
- }
- if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
- conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
- conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
- }
if (os_strstr(capab, "[GF]"))
conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
if (os_strstr(capab, "[SHORT-GI-20]"))
@@ -1212,7 +1108,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
return 0;
}
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
@@ -2298,6 +2193,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
pw->vlan_id = atoi(pos2);
}
+#ifdef CONFIG_SAE_PK
+ pos2 = os_strstr(pos, "|pk=");
+ if (pos2) {
+ const char *epos;
+ char *tmp;
+
+ if (!end)
+ end = pos2;
+ pos2 += 4;
+ epos = os_strchr(pos2, '|');
+ if (epos) {
+ tmp = os_malloc(epos - pos2 + 1);
+ if (!tmp)
+ goto fail;
+ os_memcpy(tmp, pos2, epos - pos2);
+ tmp[epos - pos2] = '\0';
+ } else {
+ tmp = os_strdup(pos2);
+ if (!tmp)
+ goto fail;
+ }
+
+ pw->pk = sae_parse_pk(tmp);
+ str_clear_free(tmp);
+ if (!pw->pk)
+ goto fail;
+ }
+#endif /* CONFIG_SAE_PK */
+
pos2 = os_strstr(pos, "|id=");
if (pos2) {
if (!end)
@@ -2320,6 +2244,18 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
pw->password[end - val] = '\0';
}
+#ifdef CONFIG_SAE_PK
+ if (pw->pk &&
+#ifdef CONFIG_TESTING_OPTIONS
+ !bss->sae_pk_password_check_skip &&
+#endif /* CONFIG_TESTING_OPTIONS */
+ !sae_pk_valid_password(pw->password)) {
+ wpa_printf(MSG_INFO,
+ "Invalid SAE password for a SAE-PK sae_password entry");
+ goto fail;
+ }
+#endif /* CONFIG_SAE_PK */
+
pw->next = bss->sae_passwords;
bss->sae_passwords = pw;
@@ -2327,6 +2263,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
fail:
str_clear_free(pw->password);
os_free(pw->identifier);
+#ifdef CONFIG_SAE_PK
+ sae_deinit_pk(pw->pk);
+#endif /* CONFIG_SAE_PK */
os_free(pw);
return -1;
}
@@ -2471,6 +2410,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
bss->skip_inactivity_poll = atoi(pos);
} else if (os_strcmp(buf, "country_code") == 0) {
+ if (pos[0] < 'A' || pos[0] > 'Z' ||
+ pos[1] < 'A' || pos[1] > 'Z') {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid country_code '%s'",
+ line, pos);
+ return 1;
+ }
os_memcpy(conf->country, pos, 2);
} else if (os_strcmp(buf, "country3") == 0) {
conf->country[2] = strtol(pos, NULL, 16);
@@ -2613,7 +2559,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
int val = atoi(pos);
- if (val < 0 || val > 1) {
+ if (val < 0 || val > 2) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid eap_teap_auth value",
line);
@@ -2674,6 +2620,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "erp_domain") == 0) {
os_free(bss->erp_domain);
bss->erp_domain = os_strdup(pos);
+#ifdef CONFIG_WEP
} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
int val = atoi(pos);
@@ -2701,6 +2648,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, bss->wep_rekeying_period);
return 1;
}
+#endif /* CONFIG_WEP */
} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
bss->eap_reauth_period = atoi(pos);
if (bss->eap_reauth_period < 0) {
@@ -2875,6 +2823,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "wpa") == 0) {
bss->wpa = atoi(pos);
+ } else if (os_strcmp(buf, "extended_key_id") == 0) {
+ int val = atoi(pos);
+
+ if (val < 0 || val > 2) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid extended_key_id=%d; allowed range 0..2",
+ line, val);
+ return 1;
+ }
+ bss->extended_key_id = val;
} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
bss->wpa_group_rekey = atoi(pos);
bss->wpa_group_rekey_set = 1;
@@ -2884,6 +2842,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->wpa_gmk_rekey = atoi(pos);
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
bss->wpa_ptk_rekey = atoi(pos);
+ } else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
+ bss->wpa_deny_ptk0_rekey = atoi(pos);
+ if (bss->wpa_deny_ptk0_rekey < 0 ||
+ bss->wpa_deny_ptk0_rekey > 2) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
+ line, bss->wpa_deny_ptk0_rekey);
+ return 1;
+ }
} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
char *endp;
unsigned long val = strtoul(pos, &endp, 0);
@@ -3162,6 +3129,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
return 1;
}
+ } else if (os_strcmp(buf, "freqlist") == 0) {
+ if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
+ line);
+ return 1;
+ }
+ conf->acs_freq_list_present = 1;
+ } else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
+ conf->acs_exclude_6ghz_non_psc = atoi(pos);
} else if (os_strcmp(buf, "beacon_int") == 0) {
int val = atoi(pos);
/* MIB defines range as 1..65535, but very small values
@@ -3303,6 +3279,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->ignore_broadcast_ssid = atoi(pos);
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
bss->no_probe_resp_if_max_sta = atoi(pos);
+#ifdef CONFIG_WEP
} else if (os_strcmp(buf, "wep_default_key") == 0) {
bss->ssid.wep.idx = atoi(pos);
if (bss->ssid.wep.idx > 3) {
@@ -3321,6 +3298,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, buf);
return 1;
}
+#endif /* CONFIG_WEP */
#ifndef CONFIG_NO_VLAN
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
bss->ssid.dynamic_vlan = atoi(pos);
@@ -3352,7 +3330,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
conf->ap_table_expiration_time = atoi(pos);
} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
- if (hostapd_config_tx_queue(conf, buf, pos)) {
+ if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
line);
return 1;
@@ -3399,6 +3377,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
+ } else if (os_strcmp(buf, "beacon_prot") == 0) {
+ bss->beacon_prot = atoi(pos);
} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
bss->assoc_sa_query_max_timeout = atoi(pos);
if (bss->assoc_sa_query_max_timeout == 0) {
@@ -3419,7 +3399,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
if (bss->ocv && !bss->ieee80211w)
bss->ieee80211w = 1;
#endif /* CONFIG_OCV */
-#ifdef CONFIG_IEEE80211N
} else if (os_strcmp(buf, "ieee80211n") == 0) {
conf->ieee80211n = atoi(pos);
} else if (os_strcmp(buf, "ht_capab") == 0) {
@@ -3432,7 +3411,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->require_ht = atoi(pos);
} else if (os_strcmp(buf, "obss_interval") == 0) {
conf->obss_interval = atoi(pos);
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
} else if (os_strcmp(buf, "ieee80211ac") == 0) {
conf->ieee80211ac = atoi(pos);
@@ -3465,7 +3443,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
conf->he_phy_capab.he_mu_beamformer = atoi(pos);
} else if (os_strcmp(buf, "he_bss_color") == 0) {
- conf->he_op.he_bss_color = atoi(pos);
+ conf->he_op.he_bss_color = atoi(pos) & 0x3f;
+ conf->he_op.he_bss_color_disabled = 0;
+ } else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
+ conf->he_op.he_bss_color_partial = atoi(pos);
} else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
conf->he_op.he_default_pe_duration = atoi(pos);
} else if (os_strcmp(buf, "he_twt_required") == 0) {
@@ -3753,6 +3734,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "server_id") == 0) {
os_free(bss->server_id);
bss->server_id = os_strdup(pos);
+ } else if (os_strcmp(buf, "wps_application_ext") == 0) {
+ wpabuf_free(bss->wps_application_ext);
+ bss->wps_application_ext = wpabuf_parse_bin(pos);
#ifdef CONFIG_WPS_NFC
} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
bss->wps_nfc_dev_pw_id = atoi(pos);
@@ -4153,9 +4137,53 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->own_ie_override = tmp;
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
bss->sae_reflection_attack = atoi(pos);
+ } else if (os_strcmp(buf, "sae_commit_status") == 0) {
+ bss->sae_commit_status = atoi(pos);
+ } else if (os_strcmp(buf, "sae_pk_omit") == 0) {
+ bss->sae_pk_omit = atoi(pos);
+ } else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) {
+ bss->sae_pk_password_check_skip = atoi(pos);
} else if (os_strcmp(buf, "sae_commit_override") == 0) {
wpabuf_free(bss->sae_commit_override);
bss->sae_commit_override = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rsne_override_eapol") == 0) {
+ wpabuf_free(bss->rsne_override_eapol);
+ bss->rsne_override_eapol = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
+ wpabuf_free(bss->rsnxe_override_eapol);
+ bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rsne_override_ft") == 0) {
+ wpabuf_free(bss->rsne_override_ft);
+ bss->rsne_override_ft = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rsnxe_override_ft") == 0) {
+ wpabuf_free(bss->rsnxe_override_ft);
+ bss->rsnxe_override_ft = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
+ wpabuf_free(bss->gtk_rsc_override);
+ bss->gtk_rsc_override = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
+ wpabuf_free(bss->igtk_rsc_override);
+ bss->igtk_rsc_override = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) {
+ bss->no_beacon_rsnxe = atoi(pos);
+ } else if (os_strcmp(buf, "skip_prune_assoc") == 0) {
+ bss->skip_prune_assoc = atoi(pos);
+ } else if (os_strcmp(buf, "ft_rsnxe_used") == 0) {
+ bss->ft_rsnxe_used = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) {
+ bss->oci_freq_override_eapol_m3 = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) {
+ bss->oci_freq_override_eapol_g1 = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) {
+ bss->oci_freq_override_saquery_req = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) {
+ bss->oci_freq_override_saquery_resp = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) {
+ bss->oci_freq_override_ft_assoc = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) {
+ bss->oci_freq_override_fils_assoc = atoi(pos);
+ } else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
+ bss->oci_freq_override_wnm_sleep = atoi(pos);
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) {
@@ -4358,6 +4386,18 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "dpp_controller") == 0) {
if (hostapd_dpp_controller_parse(bss, pos))
return 1;
+ } else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) {
+ bss->dpp_configurator_connectivity = atoi(pos);
+ } else if (os_strcmp(buf, "dpp_pfs") == 0) {
+ int val = atoi(pos);
+
+ if (val < 0 || val > 2) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid dpp_pfs value '%s'",
+ line, pos);
+ return -1;
+ }
+ bss->dpp_pfs = val;
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
#ifdef CONFIG_OWE
@@ -4391,9 +4431,11 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
+ } else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
+ bss->owe_ptk_workaround = atoi(pos);
+#endif /* CONFIG_OWE */
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
bss->coloc_intf_reporting = atoi(pos);
-#endif /* CONFIG_OWE */
} else if (os_strcmp(buf, "multi_ap") == 0) {
int val = atoi(pos);
@@ -4410,6 +4452,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->rssi_reject_assoc_timeout = atoi(pos);
} else if (os_strcmp(buf, "pbss") == 0) {
bss->pbss = atoi(pos);
+ } else if (os_strcmp(buf, "transition_disable") == 0) {
+ bss->transition_disable = strtol(pos, NULL, 16);
#ifdef CONFIG_AIRTIME_POLICY
} else if (os_strcmp(buf, "airtime_mode") == 0) {
int val = atoi(pos);
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2c44d1e..30fa47f 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -11,7 +11,11 @@
#ifndef CONFIG_NATIVE_WINDOWS
#ifdef CONFIG_TESTING_OPTIONS
+#ifdef __NetBSD__
+#include <net/if_ether.h>
+#else
#include <net/ethernet.h>
+#endif
#include <netinet/ip.h>
#endif /* CONFIG_TESTING_OPTIONS */
@@ -43,6 +47,7 @@
#include "ap/ap_config.h"
#include "ap/ieee802_1x.h"
#include "ap/wpa_auth.h"
+#include "ap/pmksa_cache_auth.h"
#include "ap/ieee802_11.h"
#include "ap/sta_info.h"
#include "ap/wps_hostapd.h"
@@ -55,6 +60,7 @@
#include "ap/neighbor_db.h"
#include "ap/rrm.h"
#include "ap/dpp_hostapd.h"
+#include "ap/dfs.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
#include "fst/fst_ctrl_iface.h"
@@ -65,9 +71,6 @@
#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
#ifdef CONFIG_CTRL_IFACE_UDP
-#define COOKIE_LEN 8
-static unsigned char cookie[COOKIE_LEN];
-static unsigned char gcookie[COOKIE_LEN];
#define HOSTAPD_CTRL_IFACE_PORT 8877
#define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
@@ -1286,6 +1289,22 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
pos += ret;
}
+ if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) {
+ ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n",
+ hapd->conf->wpa_deny_ptk0_rekey);
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
+ if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) {
+ ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n",
+ hapd->conf->extended_key_id);
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
return pos - buf;
}
@@ -1326,6 +1345,33 @@ static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
}
}
+
+static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
+ const char *band)
+{
+ union wpa_event_data event;
+ enum set_band setband;
+
+ if (os_strcmp(band, "AUTO") == 0)
+ setband = WPA_SETBAND_AUTO;
+ else if (os_strcmp(band, "5G") == 0)
+ setband = WPA_SETBAND_5G;
+ else if (os_strcmp(band, "2G") == 0)
+ setband = WPA_SETBAND_2G;
+ else
+ return -1;
+
+ if (hostapd_drv_set_band(hapd, setband) == 0) {
+ os_memset(&event, 0, sizeof(event));
+ event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+ event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+ wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event);
+ }
+
+ return 0;
+}
+
+
static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
{
char *value;
@@ -1383,6 +1429,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
hapd->dpp_ignore_netaccesskey_mismatch = atoi(value);
} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
dpp_test = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
+ dpp_version_override = atoi(value);
#endif /* CONFIG_DPP */
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO
@@ -1409,6 +1457,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
os_free(hapd->dpp_configurator_params);
hapd->dpp_configurator_params = os_strdup(value);
#endif /* CONFIG_DPP */
+ } else if (os_strcasecmp(cmd, "setband") == 0) {
+ ret = hostapd_ctrl_iface_set_band(hapd, value);
} else {
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
if (ret)
@@ -1429,7 +1479,32 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
os_strcmp(cmd, "sae_pwe") == 0) {
if (hapd->started)
hostapd_setup_sae_pt(hapd->conf);
+ } else if (os_strcasecmp(cmd, "transition_disable") == 0) {
+ wpa_auth_set_transition_disable(hapd->wpa_auth,
+ hapd->conf->transition_disable);
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (os_strcmp(cmd, "ft_rsnxe_used") == 0)
+ wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth,
+ hapd->conf->ft_rsnxe_used);
+ else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0)
+ wpa_auth_set_ocv_override_freq(
+ hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
+ atoi(value));
+ else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0)
+ wpa_auth_set_ocv_override_freq(
+ hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
+ atoi(value));
+ else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0)
+ wpa_auth_set_ocv_override_freq(
+ hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
+ atoi(value));
+ else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0)
+ wpa_auth_set_ocv_override_freq(
+ hapd->wpa_auth,
+ WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
+#endif /* CONFIG_TESTING_OPTIONS */
}
return ret;
@@ -1629,7 +1704,7 @@ static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
return -1;
}
- res = hostapd_drv_send_mlme(hapd, buf, len, 0);
+ res = hostapd_drv_send_mlme(hapd, buf, len, 0, NULL, 0, 0);
os_free(buf);
return res;
}
@@ -1828,7 +1903,7 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
{
struct hostapd_data *hapd = ctx;
const struct ether_header *eth;
- struct iphdr ip;
+ struct ip ip;
const u8 *pos;
unsigned int i;
char extra[30];
@@ -1844,14 +1919,14 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
os_memcpy(&ip, eth + 1, sizeof(ip));
pos = &buf[sizeof(*eth) + sizeof(ip)];
- if (ip.ihl != 5 || ip.version != 4 ||
- ntohs(ip.tot_len) > HWSIM_IP_LEN) {
+ if (ip.ip_hl != 5 || ip.ip_v != 4 ||
+ ntohs(ip.ip_len) > HWSIM_IP_LEN) {
wpa_printf(MSG_DEBUG,
- "test data: RX - ignore unexpect IP header");
+ "test data: RX - ignore unexpected IP header");
return;
}
- for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
+ for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
if (*pos != (u8) i) {
wpa_printf(MSG_DEBUG,
"test data: RX - ignore mismatching payload");
@@ -1861,8 +1936,8 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
}
extra[0] = '\0';
- if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
- os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
+ if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
+ os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
}
@@ -1915,7 +1990,7 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
u8 tos;
u8 buf[2 + HWSIM_PACKETLEN];
struct ether_header *eth;
- struct iphdr *ip;
+ struct ip *ip;
u8 *dpos;
unsigned int i;
size_t send_len = HWSIM_IP_LEN;
@@ -1954,17 +2029,17 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
os_memcpy(eth->ether_shost, src, ETH_ALEN);
eth->ether_type = htons(ETHERTYPE_IP);
- ip = (struct iphdr *) (eth + 1);
+ ip = (struct ip *) (eth + 1);
os_memset(ip, 0, sizeof(*ip));
- ip->ihl = 5;
- ip->version = 4;
- ip->ttl = 64;
- ip->tos = tos;
- ip->tot_len = htons(send_len);
- ip->protocol = 1;
- ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
- ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
- ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
+ ip->ip_hl = 5;
+ ip->ip_v = 4;
+ ip->ip_ttl = 64;
+ ip->ip_tos = tos;
+ ip->ip_len = htons(send_len);
+ ip->ip_p = 1;
+ ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
+ ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
+ ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
dpos = (u8 *) (ip + 1);
for (i = 0; i < send_len - sizeof(*ip); i++)
*dpos++ = i;
@@ -2110,6 +2185,32 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
if (hwaddr_aton(cmd, addr))
return -1;
+ if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) {
+ if (hapd->last_bigtk_alg == WPA_ALG_NONE)
+ return -1;
+
+ wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK");
+
+ /* First, use a zero key to avoid any possible duplicate key
+ * avoidance in the driver. */
+ if (hostapd_drv_set_key(hapd->conf->iface, hapd,
+ hapd->last_bigtk_alg,
+ broadcast_ether_addr,
+ hapd->last_bigtk_key_idx, 0, 1, NULL, 0,
+ zero, hapd->last_bigtk_len,
+ KEY_FLAG_GROUP_TX_DEFAULT) < 0)
+ return -1;
+
+ /* Set the previously configured key to reset its TSC */
+ return hostapd_drv_set_key(hapd->conf->iface, hapd,
+ hapd->last_bigtk_alg,
+ broadcast_ether_addr,
+ hapd->last_bigtk_key_idx, 0, 1, NULL,
+ 0, hapd->last_bigtk,
+ hapd->last_bigtk_len,
+ KEY_FLAG_GROUP_TX_DEFAULT);
+ }
+
if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
if (hapd->last_igtk_alg == WPA_ALG_NONE)
return -1;
@@ -2121,17 +2222,19 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
if (hostapd_drv_set_key(hapd->conf->iface, hapd,
hapd->last_igtk_alg,
broadcast_ether_addr,
- hapd->last_igtk_key_idx, 1, NULL, 0,
- zero, hapd->last_igtk_len) < 0)
+ hapd->last_igtk_key_idx, 0, 1, NULL, 0,
+ zero, hapd->last_igtk_len,
+ KEY_FLAG_GROUP_TX_DEFAULT) < 0)
return -1;
/* Set the previously configured key to reset its TSC */
return hostapd_drv_set_key(hapd->conf->iface, hapd,
hapd->last_igtk_alg,
broadcast_ether_addr,
- hapd->last_igtk_key_idx, 1, NULL, 0,
- hapd->last_igtk,
- hapd->last_igtk_len);
+ hapd->last_igtk_key_idx, 0, 1, NULL,
+ 0, hapd->last_igtk,
+ hapd->last_igtk_len,
+ KEY_FLAG_GROUP_TX_DEFAULT);
}
if (is_broadcast_ether_addr(addr)) {
@@ -2145,16 +2248,19 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
if (hostapd_drv_set_key(hapd->conf->iface, hapd,
hapd->last_gtk_alg,
broadcast_ether_addr,
- hapd->last_gtk_key_idx, 1, NULL, 0,
- zero, hapd->last_gtk_len) < 0)
+ hapd->last_gtk_key_idx, 0, 1, NULL, 0,
+ zero, hapd->last_gtk_len,
+ KEY_FLAG_GROUP_TX_DEFAULT) < 0)
return -1;
/* Set the previously configured key to reset its TSC */
return hostapd_drv_set_key(hapd->conf->iface, hapd,
hapd->last_gtk_alg,
broadcast_ether_addr,
- hapd->last_gtk_key_idx, 1, NULL, 0,
- hapd->last_gtk, hapd->last_gtk_len);
+ hapd->last_gtk_key_idx, 0, 1, NULL,
+ 0, hapd->last_gtk,
+ hapd->last_gtk_len,
+ KEY_FLAG_GROUP_TX_DEFAULT);
}
sta = ap_get_sta(hapd, addr);
@@ -2170,14 +2276,16 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
/* First, use a zero key to avoid any possible duplicate key avoidance
* in the driver. */
if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
- sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
- zero, sta->last_tk_len) < 0)
+ sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
+ zero, sta->last_tk_len,
+ KEY_FLAG_PAIRWISE_RX_TX) < 0)
return -1;
/* Set the previously configured key to reset its TSC/RSC */
return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
- sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
- sta->last_tk, sta->last_tk_len);
+ sta->addr, sta->last_tk_key_idx, 0, 1, NULL,
+ 0, sta->last_tk, sta->last_tk_len,
+ KEY_FLAG_PAIRWISE_RX_TX);
}
@@ -2186,11 +2294,12 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
u8 addr[ETH_ALEN];
const char *pos = cmd;
enum wpa_alg alg;
+ enum key_flag key_flag;
int idx, set_tx;
u8 seq[6], key[WPA_TK_MAX_LEN];
size_t key_len;
- /* parameters: alg addr idx set_tx seq key */
+ /* parameters: alg addr idx set_tx seq key key_flag */
alg = atoi(pos);
pos = os_strchr(pos, ' ');
@@ -2219,13 +2328,24 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
if (*pos != ' ')
return -1;
pos++;
- key_len = os_strlen(pos) / 2;
+ if (!os_strchr(pos, ' '))
+ return -1;
+ key_len = (os_strchr(pos, ' ') - pos) / 2;
if (hexstr2bin(pos, key, key_len) < 0)
return -1;
+ pos += 2 * key_len;
+ if (*pos != ' ')
+ return -1;
+
+ pos++;
+ key_flag = atoi(pos);
+ pos = os_strchr(pos, ' ');
+ if (pos)
+ return -1;
wpa_printf(MSG_INFO, "TESTING: Set key");
- return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx,
- set_tx, seq, 6, key, key_len);
+ return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx, 0,
+ set_tx, seq, 6, key, key_len, key_flag);
}
@@ -2240,8 +2360,9 @@ static void restore_tk(void *ctx1, void *ctx2)
* in replay protection issues for now since there is no clean way of
* preventing encryption of a single EAPOL frame. */
hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
- sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
- sta->last_tk, sta->last_tk_len);
+ sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
+ sta->last_tk, sta->last_tk_len,
+ KEY_FLAG_PAIRWISE_RX_TX);
}
@@ -2264,8 +2385,8 @@ static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
MAC2STR(sta->addr));
hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
- sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
- NULL, 0);
+ sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
+ 0, NULL, 0, KEY_FLAG_PAIRWISE);
}
wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
@@ -2294,8 +2415,8 @@ static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
MAC2STR(sta->addr));
hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
- sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
- NULL, 0);
+ sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
+ 0, NULL, 0, KEY_FLAG_PAIRWISE);
}
wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
@@ -2324,8 +2445,8 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
MAC2STR(sta->addr));
hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
- sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
- NULL, 0);
+ sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
+ 0, NULL, 0, KEY_FLAG_PAIRWISE);
}
wpa_printf(MSG_INFO,
@@ -2335,21 +2456,219 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
plain ? restore_tk : NULL, hapd, sta);
}
+
+static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr,
+ char *buf, size_t buflen)
+{
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL);
+ if (!pmksa)
+ return -1;
+
+ return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len);
+}
+
+
+static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
+ char *buf, size_t buflen)
+{
+ struct sta_info *sta;
+ u8 addr[ETH_ALEN];
+ const u8 *pmk;
+ int pmk_len;
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !sta->wpa_sm) {
+ wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR,
+ MAC2STR(addr));
+ return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
+ }
+ pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
+ if (!pmk || !pmk_len) {
+ wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR,
+ MAC2STR(addr));
+ return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
+ }
+
+ return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
+}
+
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef NEED_AP_MLME
+static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params)
+{
+ switch (params->bandwidth) {
+ case 0:
+ /* bandwidth not specified: use 20 MHz by default */
+ /* fall-through */
+ case 20:
+ if (params->center_freq1 &&
+ params->center_freq1 != params->freq)
+ return -1;
+
+ if (params->center_freq2 || params->sec_channel_offset)
+ return -1;
+ break;
+ case 40:
+ if (params->center_freq2 || !params->sec_channel_offset)
+ return -1;
+
+ if (!params->center_freq1)
+ break;
+ switch (params->sec_channel_offset) {
+ case 1:
+ if (params->freq + 10 != params->center_freq1)
+ return -1;
+ break;
+ case -1:
+ if (params->freq - 10 != params->center_freq1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case 80:
+ if (!params->center_freq1 || !params->sec_channel_offset)
+ return 1;
+
+ switch (params->sec_channel_offset) {
+ case 1:
+ if (params->freq - 10 != params->center_freq1 &&
+ params->freq + 30 != params->center_freq1)
+ return 1;
+ break;
+ case -1:
+ if (params->freq + 10 != params->center_freq1 &&
+ params->freq - 30 != params->center_freq1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+
+ /* Adjacent and overlapped are not allowed for 80+80 */
+ if (params->center_freq2 &&
+ params->center_freq1 - params->center_freq2 <= 80 &&
+ params->center_freq2 - params->center_freq1 <= 80)
+ return 1;
+ break;
+ case 160:
+ if (!params->center_freq1 || params->center_freq2 ||
+ !params->sec_channel_offset)
+ return -1;
+
+ switch (params->sec_channel_offset) {
+ case 1:
+ if (params->freq + 70 != params->center_freq1 &&
+ params->freq + 30 != params->center_freq1 &&
+ params->freq - 10 != params->center_freq1 &&
+ params->freq - 50 != params->center_freq1)
+ return -1;
+ break;
+ case -1:
+ if (params->freq + 50 != params->center_freq1 &&
+ params->freq + 10 != params->center_freq1 &&
+ params->freq - 30 != params->center_freq1 &&
+ params->freq - 70 != params->center_freq1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* NEED_AP_MLME */
+
+
static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
char *pos)
{
#ifdef NEED_AP_MLME
struct csa_settings settings;
int ret;
+ int dfs_range = 0;
unsigned int i;
+ int bandwidth;
+ u8 chan;
ret = hostapd_parse_csa_settings(pos, &settings);
if (ret)
return ret;
+ ret = hostapd_ctrl_check_freq_params(&settings.freq_params);
+ if (ret) {
+ wpa_printf(MSG_INFO,
+ "chanswitch: invalid frequency settings provided");
+ return ret;
+ }
+
+ switch (settings.freq_params.bandwidth) {
+ case 40:
+ bandwidth = CHAN_WIDTH_40;
+ break;
+ case 80:
+ if (settings.freq_params.center_freq2)
+ bandwidth = CHAN_WIDTH_80P80;
+ else
+ bandwidth = CHAN_WIDTH_80;
+ break;
+ case 160:
+ bandwidth = CHAN_WIDTH_160;
+ break;
+ default:
+ bandwidth = CHAN_WIDTH_20;
+ break;
+ }
+
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+ else
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.freq);
+
+ if (settings.freq_params.center_freq2)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq2);
+
+ if (dfs_range) {
+ ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan);
+ if (ret == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_ERROR,
+ "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)",
+ settings.freq_params.freq,
+ settings.freq_params.sec_channel_offset,
+ settings.freq_params.bandwidth);
+ return -1;
+ }
+
+ settings.freq_params.channel = chan;
+
+ wpa_printf(MSG_DEBUG,
+ "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)",
+ settings.freq_params.channel,
+ settings.freq_params.freq,
+ settings.freq_params.sec_channel_offset,
+ settings.freq_params.bandwidth,
+ settings.freq_params.center_freq1);
+
+ /* Perform CAC and switch channel */
+ hostapd_switch_channel_fallback(iface, &settings.freq_params);
+ return 0;
+ }
+
for (i = 0; i < iface->num_bss; i++) {
/* Save CHAN_SWITCH VHT config */
@@ -2678,6 +2997,20 @@ static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
}
+static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+ if (!(hapd->conf->radio_measurements[0] &
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled");
+ return -1;
+ }
+
+ return hostapd_neighbor_show(hapd, buf, buflen);
+}
+
+
static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
{
struct wpa_ssid_value ssid;
@@ -2784,6 +3117,7 @@ static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
char *buf)
{
struct wpa_ssid_value ssid;
+ struct wpa_ssid_value *ssidp = NULL;
u8 bssid[ETH_ALEN];
char *tmp;
@@ -2793,13 +3127,16 @@ static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
}
tmp = os_strstr(buf, "ssid=");
- if (!tmp || ssid_parse(tmp + 5, &ssid)) {
- wpa_printf(MSG_ERROR,
- "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
- return -1;
+ if (tmp) {
+ ssidp = &ssid;
+ if (ssid_parse(tmp + 5, &ssid)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: REMOVE_NEIGHBOR: Bad SSID");
+ return -1;
+ }
}
- return hostapd_neighbor_remove(hapd, bssid, &ssid);
+ return hostapd_neighbor_remove(hapd, bssid, ssidp);
}
@@ -2831,6 +3168,34 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
}
+static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf,
+ size_t buflen)
+{
+ int ret, i;
+ char *pos, *end;
+
+ ret = os_snprintf(buf, buflen, "%016llX:\n",
+ (long long unsigned) iface->drv_flags2);
+ if (os_snprintf_error(buflen, ret))
+ return -1;
+
+ pos = buf + ret;
+ end = buf + buflen;
+
+ for (i = 0; i < 64; i++) {
+ if (iface->drv_flags2 & (1LLU << i)) {
+ ret = os_snprintf(pos, end - pos, "%s\n",
+ driver_flag2_to_string(1LLU << i));
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ }
+
+ return pos - buf;
+}
+
+
static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
const char *txtaddr)
{
@@ -3185,6 +3550,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strcmp(buf, "REKEY_GTK") == 0) {
if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
+ reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
+ reply_size);
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
@@ -3222,6 +3590,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
reply_len = -1;
+ } else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) {
+ reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply,
+ reply_size);
} else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
reply_len = -1;
@@ -3237,6 +3608,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
reply_size);
+ } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
+ reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply,
+ reply_size);
} else if (os_strcmp(buf, "TERMINATE") == 0) {
eloop_terminate();
} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
@@ -3289,6 +3663,33 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
+ } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
+ res = hostapd_dpp_nfc_uri(hapd, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
+ res = hostapd_dpp_nfc_handover_req(hapd, buf + 20);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
+ res = hostapd_dpp_nfc_handover_sel(hapd, buf + 20);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
if (res < 0) {
@@ -3318,6 +3719,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
atoi(buf + 19),
reply, reply_size);
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
+ if (dpp_bootstrap_set(hapd->iface->interfaces->dpp,
+ atoi(buf + 18),
+ os_strchr(buf + 18, ' ')) < 0)
+ reply_len = -1;
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
reply_len = -1;
@@ -3361,6 +3767,21 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
reply_len = -1;
+#ifdef CONFIG_DPP2
+ } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
+ if (hostapd_dpp_controller_start(hapd, buf + 20) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
+ if (hostapd_dpp_controller_start(hapd, NULL) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
+ dpp_controller_stop(hapd->iface->interfaces->dpp);
+ } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
+ if (hostapd_dpp_chirp(hapd, buf + 9) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
+ hostapd_dpp_chirp_stop(hapd);
+#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
#ifdef RADIUS_SERVER
} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
@@ -3397,7 +3818,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
int reply_len;
int level = MSG_DEBUG;
#ifdef CONFIG_CTRL_IFACE_UDP
- unsigned char lcookie[COOKIE_LEN];
+ unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
#endif /* CONFIG_CTRL_IFACE_UDP */
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
@@ -3422,28 +3843,30 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
#ifdef CONFIG_CTRL_IFACE_UDP
if (os_strcmp(buf, "GET_COOKIE") == 0) {
os_memcpy(reply, "COOKIE=", 7);
- wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
- cookie, COOKIE_LEN);
- reply_len = 7 + 2 * COOKIE_LEN;
+ wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
+ hapd->ctrl_iface_cookie,
+ CTRL_IFACE_COOKIE_LEN);
+ reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
goto done;
}
if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
- hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+ hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
wpa_printf(MSG_DEBUG,
"CTRL: No cookie in the request - drop request");
os_free(reply);
return;
}
- if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
+ if (os_memcmp(hapd->ctrl_iface_cookie, lcookie,
+ CTRL_IFACE_COOKIE_LEN) != 0) {
wpa_printf(MSG_DEBUG,
"CTRL: Invalid cookie in the request - drop request");
os_free(reply);
return;
}
- pos = buf + 7 + 2 * COOKIE_LEN;
+ pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN;
while (*pos == ' ')
pos++;
#endif /* CONFIG_CTRL_IFACE_UDP */
@@ -3532,7 +3955,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
dl_list_init(&hapd->ctrl_dst);
hapd->ctrl_sock = -1;
- os_get_random(cookie, COOKIE_LEN);
+ os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
hints.ai_flags = AI_PASSIVE;
@@ -3846,6 +4269,11 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
#ifdef CONFIG_TESTING_OPTIONS
#ifdef CONFIG_DPP
dpp_test = DPP_TEST_DISABLED;
+#ifdef CONFIG_DPP2
+ dpp_version_override = 2;
+#else /* CONFIG_DPP2 */
+ dpp_version_override = 1;
+#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
#endif /* CONFIG_TESTING_OPTIONS */
@@ -4111,7 +4539,7 @@ static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
- void *interfaces = eloop_ctx;
+ struct hapd_interfaces *interfaces = eloop_ctx;
char buffer[256], *buf = buffer;
int res;
struct sockaddr_storage from;
@@ -4120,7 +4548,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
int reply_len;
const int reply_size = 4096;
#ifdef CONFIG_CTRL_IFACE_UDP
- unsigned char lcookie[COOKIE_LEN];
+ unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
#endif /* CONFIG_CTRL_IFACE_UDP */
res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
@@ -4149,28 +4577,30 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
#ifdef CONFIG_CTRL_IFACE_UDP
if (os_strcmp(buf, "GET_COOKIE") == 0) {
os_memcpy(reply, "COOKIE=", 7);
- wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
- gcookie, COOKIE_LEN);
- reply_len = 7 + 2 * COOKIE_LEN;
+ wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
+ interfaces->ctrl_iface_cookie,
+ CTRL_IFACE_COOKIE_LEN);
+ reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
goto send_reply;
}
if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
- hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+ hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
wpa_printf(MSG_DEBUG,
"CTRL: No cookie in the request - drop request");
os_free(reply);
return;
}
- if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
+ if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie,
+ CTRL_IFACE_COOKIE_LEN) != 0) {
wpa_printf(MSG_DEBUG,
"CTRL: Invalid cookie in the request - drop request");
os_free(reply);
return;
}
- buf += 7 + 2 * COOKIE_LEN;
+ buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN;
while (*buf == ' ')
buf++;
#endif /* CONFIG_CTRL_IFACE_UDP */
@@ -4314,7 +4744,7 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
}
}
- os_get_random(gcookie, COOKIE_LEN);
+ os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
hints.ai_flags = AI_PASSIVE;
@@ -4364,6 +4794,8 @@ try_again:
return -1;
}
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
return 0;
fail:
@@ -4466,6 +4898,8 @@ fail:
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
interface, NULL);
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
return 0;
fail:
@@ -4535,37 +4969,43 @@ static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst,
}
-static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
- enum wpa_msg_type type,
- const char *buf, size_t len)
+static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
+ const char *ifname, int level,
+ const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
- struct dl_list *ctrl_dst;
struct msghdr msg;
- int idx;
- struct iovec io[2];
+ int idx, res;
+ struct iovec io[5];
char levelstr[10];
- int s;
- if (type != WPA_MSG_ONLY_GLOBAL) {
- s = hapd->ctrl_sock;
- ctrl_dst = &hapd->ctrl_dst;
- } else {
- s = hapd->iface->interfaces->global_ctrl_sock;
- ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
- }
-
- if (s < 0 || dl_list_empty(ctrl_dst))
+ if (sock < 0 || dl_list_empty(ctrl_dst))
return;
- os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
- io[0].iov_base = levelstr;
- io[0].iov_len = os_strlen(levelstr);
- io[1].iov_base = (char *) buf;
- io[1].iov_len = len;
+ res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
+ if (os_snprintf_error(sizeof(levelstr), res))
+ return;
+ idx = 0;
+ if (ifname) {
+ io[idx].iov_base = "IFNAME=";
+ io[idx].iov_len = 7;
+ idx++;
+ io[idx].iov_base = (char *) ifname;
+ io[idx].iov_len = os_strlen(ifname);
+ idx++;
+ io[idx].iov_base = " ";
+ io[idx].iov_len = 1;
+ idx++;
+ }
+ io[idx].iov_base = levelstr;
+ io[idx].iov_len = os_strlen(levelstr);
+ idx++;
+ io[idx].iov_base = (char *) buf;
+ io[idx].iov_len = len;
+ idx++;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
- msg.msg_iovlen = 2;
+ msg.msg_iovlen = idx;
idx = 0;
dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
@@ -4575,22 +5015,16 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
&dst->addr, dst->addrlen);
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
- if (sendmsg(s, &msg, 0) < 0) {
+ if (sendmsg(sock, &msg, 0) < 0) {
int _errno = errno;
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
"%d - %s",
idx, errno, strerror(errno));
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT) {
- if (type != WPA_MSG_ONLY_GLOBAL)
- hostapd_ctrl_iface_detach(
- hapd, &dst->addr,
- dst->addrlen);
- else
- hostapd_global_ctrl_iface_detach(
- hapd->iface->interfaces,
- &dst->addr,
- dst->addrlen);
+ ctrl_iface_detach(ctrl_dst,
+ &dst->addr,
+ dst->addrlen);
}
} else
dst->errors = 0;
@@ -4599,4 +5033,25 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
}
}
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ enum wpa_msg_type type,
+ const char *buf, size_t len)
+{
+ if (type != WPA_MSG_NO_GLOBAL) {
+ hostapd_ctrl_iface_send_internal(
+ hapd->iface->interfaces->global_ctrl_sock,
+ &hapd->iface->interfaces->global_ctrl_dst,
+ type != WPA_MSG_PER_INTERFACE ?
+ NULL : hapd->conf->iface,
+ level, buf, len);
+ }
+
+ if (type != WPA_MSG_ONLY_GLOBAL) {
+ hostapd_ctrl_iface_send_internal(
+ hapd->ctrl_sock, &hapd->ctrl_dst,
+ NULL, level, buf, len);
+ }
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 1a3d9f9..e9f5de7 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -148,9 +148,6 @@ CONFIG_IPV6=y
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
#CONFIG_DRIVER_RADIUS_ACL=y
-# IEEE 802.11n (High Throughput) support
-#CONFIG_IEEE80211N=y
-
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
#CONFIG_WNM=y
@@ -354,7 +351,7 @@ CONFIG_IPV6=y
#CONFIG_ACS=y
# Multiband Operation support
-# These extentions facilitate efficient use of multiple frequency bands
+# These extensions facilitate efficient use of multiple frequency bands
# available to the AP and the devices that may associate with it.
#CONFIG_MBO=y
@@ -383,3 +380,18 @@ CONFIG_IPV6=y
# Override default value for the wpa_disable_eapol_key_retries configuration
# parameter. See that parameter in hostapd.conf for more details.
#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
+
+# Wired equivalent privacy (WEP)
+# WEP is an obsolete cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used for anything anymore. The
+# functionality needed to use WEP is available in the current hostapd
+# release under this optional build parameter. This functionality is subject to
+# be completely removed in a future release.
+#CONFIG_WEP=y
+
+# Remove all TKIP functionality
+# TKIP is an old cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used anymore. For now, the default hostapd
+# build includes this to allow mixed mode WPA+WPA2 networks to be enabled, but
+# that functionality is subject to be removed in the future.
+#CONFIG_NO_TKIP=y
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 4cbe451..bf89fbc 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -72,7 +72,7 @@ ctrl_interface=/var/run/hostapd
# run as non-root users. However, since the control interface can be used to
# change the network configuration, this access needs to be protected in many
# cases. By default, hostapd is configured to use gid 0 (root). If you
-# want to allow non-root users to use the contron interface, add a new group
+# want to allow non-root users to use the control interface, add a new group
# and change this value to match with that group. Add users that should have
# control interface access to this group.
#
@@ -205,11 +205,26 @@ channel=1
#chanlist=100 104 108 112 116
#chanlist=1 6 11-13
+# Frequency list restriction. This option allows hostapd to select one of the
+# provided frequencies when a frequency should be automatically selected.
+# Frequency list can be provided as range using hyphen ('-') or individual
+# frequencies can be specified by comma (',') separated values
+# Default: all frequencies allowed in selected hw_mode
+#freqlist=2437,5955,5975
+#freqlist=2437,5985-6105
+
# Exclude DFS channels from ACS
# This option can be used to exclude all DFS channels from the ACS channel list
# in cases where the driver supports DFS channels.
#acs_exclude_dfs=1
+# Include only preferred scan channels from 6 GHz band for ACS
+# This option can be used to include only preferred scan channels in the 6 GHz
+# band. This can be useful in particular for devices that operate only a 6 GHz
+# BSS without a collocated 2.4/5 GHz BSS.
+# Default behavior is to include all PSC and non-PSC channels.
+#acs_exclude_6ghz_non_psc=1
+
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@@ -583,8 +598,6 @@ wmm_ac_vo_acm=0
# channels if needed or creation of 40 MHz channel maybe rejected based
# on overlapping BSSes. These changes are done automatically when hostapd
# is setting up the 40 MHz channel.
-# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]
-# (SMPS disabled if neither is set)
# HT-greenfield: [GF] (disabled if not set)
# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)
# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)
@@ -791,6 +804,9 @@ wmm_ac_vo_acm=0
# he_bss_color: BSS color (1-63)
#he_bss_color=1
+# he_bss_color_partial: BSS color AID equation
+#he_bss_color_partial=0
+
#he_default_pe_duration: The duration of PE field in an HE PPDU in us
# Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us
#he_default_pe_duration=0
@@ -806,11 +822,11 @@ wmm_ac_vo_acm=0
#he_rts_threshold=0
# HE operating channel information; see matching vht_* parameters for details.
-# On the 6 GHz band the center freq calculation starts from 5.940 GHz offset.
-# For example idx=3 would result in 5955 MHz center frequency. In addition,
+# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset.
+# For example idx=3 would result in 5965 MHz center frequency. In addition,
# he_oper_chwidth is ignored, and the channel width is derived from the
# configured operating class or center frequency indexes (see
-# IEEE P802.11ax/D4.3 Annex E, Table E-4).
+# IEEE P802.11ax/D6.1 Annex E, Table E-4).
#he_oper_chwidth
#he_oper_centr_freq_seg0_idx
#he_oper_centr_freq_seg1_idx
@@ -888,6 +904,8 @@ eapol_key_index_workaround=0
# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
# reauthentication).
+# Note: Reauthentications may enforce a disconnection, check the related
+# parameter wpa_deny_ptk0_rekey for details.
#eap_reauth_period=3600
# Use PAE group address (01:80:c2:00:00:03) instead of individual target
@@ -1184,7 +1202,7 @@ eap_server=0
# should be unique across all issuing servers. In theory, this is a variable
# length field, but due to some existing implementations requiring A-ID to be
# 16 octets in length, it is strongly recommended to use that length for the
-# field to provid interoperability with deployed peer implementations. This
+# field to provide interoperability with deployed peer implementations. This
# field is configured in hex format.
#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
@@ -1211,6 +1229,8 @@ eap_server=0
# EAP-TEAP authentication type
# 0 = inner EAP (default)
# 1 = Basic-Password-Auth
+# 2 = Do not require Phase 2 authentication if client can be authenticated
+# during Phase 1
#eap_teap_auth=0
# EAP-TEAP authentication behavior when using PAC
@@ -1492,6 +1512,17 @@ own_ip_addr=127.0.0.1
# wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK).
#wpa=2
+# Extended Key ID support for Individually Addressed frames
+#
+# Extended Key ID allows to rekey PTK keys without the impacts the "normal"
+# PTK rekeying with only a single Key ID 0 has. It can only be used when the
+# driver supports it and RSN/WPA2 is used with a CCMP/GCMP pairwise cipher.
+#
+# 0 = force off, i.e., use only Key ID 0 (default)
+# 1 = enable and use Extended Key ID support when possible
+# 2 = identical to 1 but start with Key ID 1 when possible
+#extended_key_id=0
+
# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
@@ -1592,8 +1623,26 @@ own_ip_addr=127.0.0.1
# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
# PTK to mitigate some attacks against TKIP deficiencies.
+# Warning: PTK rekeying is buggy with many drivers/devices and with such
+# devices, the only secure method to rekey the PTK without Extended Key ID
+# support requires a disconnection. Check the related parameter
+# wpa_deny_ptk0_rekey for details.
#wpa_ptk_rekey=600
+# Workaround for PTK rekey issues
+#
+# PTK0 rekeys (rekeying the PTK without "Extended Key ID for Individually
+# Addressed Frames") can degrade the security and stability with some cards.
+# To avoid such issues hostapd can replace those PTK rekeys (including EAP
+# reauthentications) with disconnects.
+#
+# Available options:
+# 0 = always rekey when configured/instructed (default)
+# 1 = only rekey when the local driver is explicitly indicating it can perform
+# this operation without issues
+# 2 = never allow PTK0 rekeys
+#wpa_deny_ptk0_rekey=0
+
# The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way
# Handshake are retried per 4-Way Handshake attempt.
# (dot11RSNAConfigPairwiseUpdateCount)
@@ -1644,6 +1693,12 @@ own_ip_addr=127.0.0.1
# 1 = optional
# 2 = required
#ieee80211w=0
+# The most common configuration options for this based on the PMF (protected
+# management frames) certification program are:
+# PMF enabled: ieee80211w=1 and wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256
+# PMF required: ieee80211w=2 and wpa_key_mgmt=WPA-EAP-SHA256
+# (and similarly for WPA-PSK and WPA-PSK-SHA256 if WPA2-Personal is used)
+# WPA3-Personal-only mode: ieee80211w=2 and wpa_key_mgmt=SAE
# Group management cipher suite
# Default: AES-128-CMAC (BIP)
@@ -1656,6 +1711,12 @@ own_ip_addr=127.0.0.1
# available in deployed devices.
#group_mgmt_cipher=AES-128-CMAC
+# Beacon Protection (management frame protection for Beacon frames)
+# This depends on management frame protection being enabled (ieee80211w != 0).
+# 0 = disabled (default)
+# 1 = enabled
+#beacon_prot=0
+
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
# (maximum time to wait for a SA Query response)
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
@@ -1671,6 +1732,19 @@ own_ip_addr=127.0.0.1
# Enabling this automatically also enables ieee80211w, if not yet enabled.
# 0 = disabled (default)
# 1 = enabled
+# 2 = enabled in workaround mode - Allow STA that claims OCV capability to
+# connect even if the STA doesn't send OCI or negotiate PMF. This
+# workaround is to improve interoperability with legacy STAs which are
+# wrongly copying reserved bits of RSN capabilities from the AP's
+# RSNE into (Re)Association Request frames. When this configuration is
+# enabled, the AP considers STA is OCV capable only when the STA indicates
+# MFP capability in (Re)Association Request frames and sends OCI in
+# EAPOL-Key msg 2/4/FT Reassociation Request frame/FILS (Re)Association
+# Request frame; otherwise, the AP disables OCV for the current connection
+# with the STA. Enabling this workaround mode reduced OCV protection to
+# some extend since it allows misbehavior to go through. As such, this
+# should be enabled only if interoperability with misbehaving STAs is
+# needed.
#ocv=1
# disable_pmksa_caching: Disable PMKSA caching
@@ -1702,7 +1776,7 @@ own_ip_addr=127.0.0.1
# be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and
# by optional password identifier (dot11RSNAConfigPasswordIdentifier). In
# addition, an optional VLAN ID specification can be used to bind the station
-# to the specified VLAN whenver the specific SAE password entry is used.
+# to the specified VLAN whenever the specific SAE password entry is used.
#
# If the peer MAC address is not included or is set to the wildcard address
# (ff:ff:ff:ff:ff:ff), the entry is available for any station to use. If a
@@ -1717,7 +1791,8 @@ own_ip_addr=127.0.0.1
# special meaning of removing all previously added entries.
#
# sae_password uses the following encoding:
-#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>][|id=<identifier>]
+#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>]
+#[|pk=<m:ECPrivateKey-base64>][|id=<identifier>]
# Examples:
#sae_password=secret
#sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
@@ -1763,11 +1838,13 @@ own_ip_addr=127.0.0.1
#sae_confirm_immediate=0
# SAE mechanism for PWE derivation
-# 0 = hunting-and-pecking loop only (default)
-# 1 = hash-to-element only
+# 0 = hunting-and-pecking loop only (default without password identifier)
+# 1 = hash-to-element only (default with password identifier)
# 2 = both hunting-and-pecking loop and hash-to-element enabled
# Note: The default value is likely to change from 0 to 2 once the new
# hash-to-element mechanism has received more interoperability testing.
+# When using SAE password identifier, the hash-to-element mechanism is used
+# regardless of the sae_pwe parameter value.
#sae_pwe=0
# FILS Cache Identifier (16-bit value in hexdump format)
@@ -1794,6 +1871,19 @@ own_ip_addr=127.0.0.1
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
#owe_groups=19 20 21
+# OWE PTK derivation workaround
+# Initial OWE implementation used SHA256 when deriving the PTK for all OWE
+# groups. This was supposed to change to SHA384 for group 20 and SHA512 for
+# group 21. This parameter can be used to enable workaround for interoperability
+# with stations that use SHA256 with groups 20 and 21. By default (0) only the
+# appropriate hash function is accepted. When workaround is enabled (1), the
+# appropriate hash function is tried first and if that fails, SHA256-based PTK
+# derivation is attempted. This workaround can result in reduced security for
+# groups 20 and 21, but is required for interoperability with older
+# implementations. There is no impact to group 19 behavior. The workaround is
+# disabled by default and can be enabled by uncommenting the following line.
+#owe_ptk_workaround=1
+
# OWE transition mode configuration
# Pointer to the matching open/OWE BSS
#owe_transition_bssid=<bssid>
@@ -1831,6 +1921,23 @@ own_ip_addr=127.0.0.1
# default: 30 TUs (= 30.72 milliseconds)
#fils_hlp_wait_time=30
+# Transition Disable indication
+# The AP can notify authenticated stations to disable transition mode in their
+# network profiles when the network has completed transition steps, i.e., once
+# sufficiently large number of APs in the ESS have been updated to support the
+# more secure alternative. When this indication is used, the stations are
+# expected to automatically disable transition mode and less secure security
+# options. This includes use of WEP, TKIP (including use of TKIP as the group
+# cipher), and connections without PMF.
+# Bitmap bits:
+# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK and only
+# allow SAE to be used)
+# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK)
+# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF)
+# bit 3 (0x08): Enhanced Open (disable use of open network; require OWE)
+# (default: 0 = do not include Transition Disable KDE)
+#transition_disable=0x01
+
##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
@@ -1874,7 +1981,7 @@ own_ip_addr=127.0.0.1
# Wildcard entry:
# Upon receiving a response from R0KH, it will be added to this list, so
# subsequent requests won't be broadcast. If R0KH does not reply, it will be
-# blacklisted.
+# temporarily blocked (see rkh_neg_timeout).
#r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff
# List of R1KHs in the same Mobility Domain
@@ -1930,7 +2037,7 @@ own_ip_addr=127.0.0.1
#ft_psk_generate_local=0
##### Neighbor table ##########################################################
-# Maximum number of entries kept in AP table (either for neigbor table or for
+# Maximum number of entries kept in AP table (either for neighbor table or for
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
# removed when adding a new entry that would make the list grow over this
# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is
@@ -2184,6 +2291,13 @@ own_ip_addr=127.0.0.1
#wps_nfc_dh_privkey: Hexdump of DH Private Key
#wps_nfc_dev_pw: Hexdump of Device Password
+# Application Extension attribute for Beacon and Probe Response frames
+# This parameter can be used to add application extension into WPS IE. The
+# contents of this parameter starts with 16-octet (32 hexdump characters) of
+# UUID to identify the specific application and that is followed by the actual
+# application specific data.
+#wps_application_ext=<hexdump>
+
##### Wi-Fi Direct (P2P) ######################################################
# Enable P2P Device management
@@ -2206,6 +2320,17 @@ own_ip_addr=127.0.0.1
#dpp_csign
#dpp_controller
+# Configurator Connectivity indication
+# 0: no Configurator is currently connected (default)
+# 1: advertise that a Configurator is available
+#dpp_configurator_connectivity=0
+
+# DPP PFS
+# 0: allow PFS to be used or not used (default)
+# 1: require PFS to be used (note: not compatible with DPP R1)
+# 2: do not allow PFS to be used
+#dpp_pfs=0
+
#### TDLS (IEEE 802.11z-2010) #################################################
# Prohibit use of TDLS in this BSS
@@ -2586,7 +2711,7 @@ own_ip_addr=127.0.0.1
# Default is 0 = OCE disabled
#oce=0
-# RSSI-based assocition rejection
+# RSSI-based association rejection
#
# Reject STA association if RSSI is below given threshold (in dBm)
# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled)
diff --git a/hostapd/hostapd.wpa_psk b/hostapd/hostapd.wpa_psk
index 166e59e..2ce5ff2 100644
--- a/hostapd/hostapd.wpa_psk
+++ b/hostapd/hostapd.wpa_psk
@@ -7,9 +7,15 @@
# keyid=<keyid_string>
# An optional VLAN ID can be specified by prefixing the line with
# vlanid=<VLAN ID>.
+# An optional WPS tag can be added by prefixing the line with
+# wps=<0/1> (default: 0). Any matching entry with that tag will be used when
+# generating a PSK for a WPS Enrollee instead of generating a new random
+# per-Enrollee PSK.
00:00:00:00:00:00 secret passphrase
00:11:22:33:44:55 another passphrase
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
keyid=example_id 00:11:22:33:44:77 passphrase with keyid
vlanid=3 00:00:00:00:00:00 passphrase with vlanid
+wps=1 00:00:00:00:00:00 passphrase for WPS
+wps=1 11:22:33:44:55:00 dev-specific passphrase for WPS
00:00:00:00:00:00 another passphrase for all STAs
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 42edb7b..ad43981 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -54,7 +54,7 @@ static void usage(void)
fprintf(stderr, "%s\n", hostapd_cli_version);
fprintf(stderr,
"\n"
- "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
+ "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
"[-a<path>] \\\n"
" [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
@@ -68,6 +68,9 @@ static void usage(void)
" -a<file> run in daemon mode executing the action file "
"based on events\n"
" from hostapd\n"
+ " -r try to reconnect when client socket is "
+ "disconnected.\n"
+ " This is useful only when used with -a.\n"
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
@@ -972,7 +975,7 @@ static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
dir = opendir(ctrl_iface_dir);
if (dir == NULL) {
printf("Control interface directory '%s' could not be "
- "openned.\n", ctrl_iface_dir);
+ "opened.\n", ctrl_iface_dir);
return;
}
@@ -1309,24 +1312,17 @@ static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
}
-static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
+static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
{
- char cmd[400];
- int res;
+ return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR");
+}
- if (argc != 2) {
- printf("Invalid remove_neighbor command: needs 2 arguments\n");
- return -1;
- }
- res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
- argv[0], argv[1]);
- if (os_snprintf_error(sizeof(cmd), res)) {
- printf("Too long REMOVE_NEIGHBOR command.\n");
- return -1;
- }
- return wpa_ctrl_command(ctrl, cmd);
+static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return hostapd_cli_cmd(ctrl, "REMOVE_NEIGHBOR", 1, argc, argv);
}
@@ -1406,6 +1402,13 @@ static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv);
+}
+
+
static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1468,6 +1471,23 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv);
}
+
+#ifdef CONFIG_DPP2
+
+static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv);
+}
+
+
+static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP");
+}
+
+#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
@@ -1633,8 +1653,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL,
"<addr> <ssid=> <nr=> [lci=] [civic=] [stat]\n"
" = add AP to neighbor database" },
+ { "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL,
+ " = show neighbor database entries" },
{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL,
- "<addr> <ssid=> = remove AP from neighbor database" },
+ "<addr> [ssid=<hex>] = remove AP from neighbor database" },
{ "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations,
"<addr> = send LCI request to a station"},
{ "req_range", hostapd_cli_cmd_req_range, NULL,
@@ -1652,6 +1674,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"<id> = get DPP bootstrap URI" },
{ "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL,
"<id> = show DPP bootstrap information" },
+ { "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL,
+ "<id> [conf=..] [ssid=<SSID>] [ssid_charset=#] [psk=<PSK>] [pass=<passphrase>] [configurator=<id>] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" },
{ "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL,
"peer=<id> [own=<id>] = initiate DPP bootstrapping" },
{ "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL,
@@ -1672,6 +1696,12 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"add PKEX code" },
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
"*|<id> = remove DPP pkex information" },
+#ifdef CONFIG_DPP2
+ { "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL,
+ "own=<BI ID> iter=<count> = start DPP chirp" },
+ { "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL,
+ "= stop DPP chirp" },
+#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
"=Add/Delete/Show/Clear accept MAC ACL" },
@@ -2007,12 +2037,13 @@ int main(int argc, char *argv[])
int warning_displayed = 0;
int c;
int daemonize = 0;
+ int reconnect = 0;
if (os_program_init())
return -1;
for (;;) {
- c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
+ c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
if (c < 0)
break;
switch (c) {
@@ -2041,6 +2072,9 @@ int main(int argc, char *argv[])
case 'P':
pid_file = optarg;
break;
+ case 'r':
+ reconnect = 1;
+ break;
case 's':
client_socket_dir = optarg;
break;
@@ -2083,8 +2117,7 @@ int main(int argc, char *argv[])
printf("Connection established.\n");
break;
}
-
- if (!interactive) {
+ if (!interactive && !reconnect) {
perror("Failed to connect to hostapd - "
"wpa_ctrl_open");
return -1;
@@ -2102,8 +2135,14 @@ int main(int argc, char *argv[])
return -1;
if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
return -1;
-
- if (interactive)
+ if (reconnect && action_file && ctrl_ifname) {
+ while (!hostapd_cli_quit) {
+ if (ctrl_conn)
+ hostapd_cli_action(ctrl_conn);
+ os_sleep(1, 0);
+ hostapd_cli_reconnect(ctrl_ifname);
+ }
+ } else if (interactive)
hostapd_cli_interactive();
else if (action_file)
hostapd_cli_action(ctrl_conn);
diff --git a/hostapd/main.c b/hostapd/main.c
index 8bfe242..4f2d1f2 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -218,7 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
struct wowlan_triggers *triggs;
iface->drv_flags = capa.flags;
- iface->smps_modes = capa.smps_modes;
+ iface->drv_flags2 = capa.flags2;
iface->probe_resp_offloads = capa.probe_resp_offloads;
/*
* Use default extended capa values from per-radio information
@@ -260,7 +260,7 @@ hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
struct hostapd_iface *iface;
int k;
- wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
+ wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname);
iface = hostapd_init(interfaces, config_fname);
if (!iface)
return NULL;
@@ -451,11 +451,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
static void show_version(void)
{
fprintf(stderr,
- "hostapd v" VERSION_STR "\n"
+ "hostapd v%s\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
"Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> "
- "and contributors\n");
+ "and contributors\n",
+ VERSION_STR);
}
@@ -673,7 +674,10 @@ int main(int argc, char *argv[])
#endif /* CONFIG_ETH_P_OUI */
#ifdef CONFIG_DPP
os_memset(&dpp_conf, 0, sizeof(dpp_conf));
- /* TODO: dpp_conf.msg_ctx? */
+ dpp_conf.cb_ctx = &interfaces;
+#ifdef CONFIG_DPP2
+ dpp_conf.remove_bi = hostapd_dpp_remove_bi;
+#endif /* CONFIG_DPP2 */
interfaces.dpp = dpp_global_init(&dpp_conf);
if (!interfaces.dpp)
return -1;
@@ -768,7 +772,7 @@ int main(int argc, char *argv[])
if (log_file)
wpa_debug_open_file(log_file);
- else
+ if (!log_file && !wpa_debug_syslog)
wpa_debug_setup_stdout();
#ifdef CONFIG_DEBUG_SYSLOG
if (wpa_debug_syslog)
@@ -902,8 +906,11 @@ int main(int argc, char *argv[])
!!(interfaces.iface[i]->drv_flags &
WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
hostapd_interface_deinit_free(interfaces.iface[i]);
+ interfaces.iface[i] = NULL;
}
os_free(interfaces.iface);
+ interfaces.iface = NULL;
+ interfaces.count = 0;
#ifdef CONFIG_DPP
dpp_global_deinit(interfaces.dpp);
diff --git a/hostapd/sae_pk_gen.c b/hostapd/sae_pk_gen.c
new file mode 100644
index 0000000..c31eff7
--- /dev/null
+++ b/hostapd/sae_pk_gen.c
@@ -0,0 +1,196 @@
+/*
+ * SAE-PK password/modifier generator
+ * Copyright (c) 2020, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/base64.h"
+#include "crypto/crypto.h"
+#include "common/sae.h"
+
+
+int main(int argc, char *argv[])
+{
+ char *der = NULL;
+ size_t der_len;
+ struct crypto_ec_key *key = NULL;
+ struct wpabuf *pub = NULL;
+ u8 *data = NULL, *m;
+ size_t data_len;
+ char *b64 = NULL, *pw = NULL, *pos, *src;
+ int sec, j;
+ int ret = -1;
+ u8 hash[SAE_MAX_HASH_LEN];
+ char hash_hex[2 * SAE_MAX_HASH_LEN + 1];
+ u8 pw_base_bin[SAE_MAX_HASH_LEN];
+ u8 *dst;
+ int group;
+ size_t hash_len;
+ unsigned long long i, expected;
+ char m_hex[2 * SAE_PK_M_LEN + 1];
+ u32 sec_1b, val20;
+
+ wpa_debug_level = MSG_INFO;
+ if (os_program_init() < 0)
+ goto fail;
+
+ if (argc != 4) {
+ fprintf(stderr,
+ "usage: sae_pk_gen <DER ECPrivateKey file> <Sec:3|5> <SSID>\n");
+ goto fail;
+ }
+
+ sec = atoi(argv[2]);
+ if (sec != 3 && sec != 5) {
+ fprintf(stderr,
+ "Invalid Sec value (allowed values: 3 and 5)\n");
+ goto fail;
+ }
+ sec_1b = sec == 3;
+ expected = 1;
+ for (j = 0; j < sec; j++)
+ expected *= 256;
+
+ der = os_readfile(argv[1], &der_len);
+ if (!der) {
+ fprintf(stderr, "Could not read %s: %s\n",
+ argv[1], strerror(errno));
+ goto fail;
+ }
+
+ key = crypto_ec_key_parse_priv((u8 *) der, der_len);
+ if (!key) {
+ fprintf(stderr, "Could not parse ECPrivateKey\n");
+ goto fail;
+ }
+
+ pub = crypto_ec_key_get_subject_public_key(key);
+ if (!pub) {
+ fprintf(stderr, "Failed to build SubjectPublicKey\n");
+ goto fail;
+ }
+
+ group = crypto_ec_key_group(key);
+ switch (group) {
+ case 19:
+ hash_len = 32;
+ break;
+ case 20:
+ hash_len = 48;
+ break;
+ case 21:
+ hash_len = 64;
+ break;
+ default:
+ fprintf(stderr, "Unsupported private key group\n");
+ goto fail;
+ }
+
+ data_len = os_strlen(argv[3]) + SAE_PK_M_LEN + wpabuf_len(pub);
+ data = os_malloc(data_len);
+ if (!data) {
+ fprintf(stderr, "No memory for data buffer\n");
+ goto fail;
+ }
+ os_memcpy(data, argv[3], os_strlen(argv[3]));
+ m = data + os_strlen(argv[3]);
+ if (os_get_random(m, SAE_PK_M_LEN) < 0) {
+ fprintf(stderr, "Could not generate random Modifier M\n");
+ goto fail;
+ }
+ os_memcpy(m + SAE_PK_M_LEN, wpabuf_head(pub), wpabuf_len(pub));
+
+ fprintf(stderr, "Searching for a suitable Modifier M value\n");
+ for (i = 0;; i++) {
+ if (sae_hash(hash_len, data, data_len, hash) < 0) {
+ fprintf(stderr, "Hash failed\n");
+ goto fail;
+ }
+ if (hash[0] == 0 && hash[1] == 0) {
+ if ((hash[2] & 0xf0) == 0)
+ fprintf(stderr, "\r%3.2f%%",
+ 100.0 * (double) i / (double) expected);
+ for (j = 2; j < sec; j++) {
+ if (hash[j])
+ break;
+ }
+ if (j == sec)
+ break;
+ }
+ inc_byte_array(m, SAE_PK_M_LEN);
+ }
+
+ if (wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0 ||
+ wpa_snprintf_hex(hash_hex, sizeof(hash_hex), hash, hash_len) < 0)
+ goto fail;
+ fprintf(stderr, "\nFound a valid hash in %llu iterations: %s\n",
+ i + 1, hash_hex);
+
+ b64 = base64_encode(der, der_len, NULL);
+ if (!b64)
+ goto fail;
+ src = pos = b64;
+ while (*src) {
+ if (*src != '\n')
+ *pos++ = *src;
+ src++;
+ }
+ *pos = '\0';
+
+ /* Skip 8*Sec bits and add Sec_1b as the every 20th bit starting with
+ * one. */
+ os_memset(pw_base_bin, 0, sizeof(pw_base_bin));
+ dst = pw_base_bin;
+ for (j = 0; j < 8 * (int) hash_len / 20; j++) {
+ val20 = sae_pk_get_be19(hash + sec);
+ val20 |= sec_1b << 19;
+ sae_pk_buf_shift_left_19(hash + sec, hash_len - sec);
+
+ if (j & 1) {
+ *dst |= (val20 >> 16) & 0x0f;
+ dst++;
+ *dst++ = (val20 >> 8) & 0xff;
+ *dst++ = val20 & 0xff;
+ } else {
+ *dst++ = (val20 >> 12) & 0xff;
+ *dst++ = (val20 >> 4) & 0xff;
+ *dst = (val20 << 4) & 0xf0;
+ }
+ }
+ if (wpa_snprintf_hex(hash_hex, sizeof(hash_hex),
+ pw_base_bin, hash_len - sec) >= 0)
+ fprintf(stderr, "PasswordBase binary data for base32: %s",
+ hash_hex);
+
+ pw = sae_pk_base32_encode(pw_base_bin, 20 * 3 - 5);
+ if (!pw)
+ goto fail;
+
+ printf("# SAE-PK password/M/private key for Sec=%d.\n", sec);
+ printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64);
+ printf("# Longer passwords can be used for improved security at the cost of usability:\n");
+ for (j = 4; j <= ((int) hash_len * 8 + 5 - 8 * sec) / 19; j++) {
+ os_free(pw);
+ pw = sae_pk_base32_encode(pw_base_bin, 20 * j - 5);
+ if (pw)
+ printf("# %s\n", pw);
+ }
+
+ ret = 0;
+fail:
+ os_free(der);
+ wpabuf_free(pub);
+ crypto_ec_key_deinit(key);
+ os_free(data);
+ os_free(b64);
+ os_free(pw);
+
+ os_program_deinit();
+
+ return ret;
+}
diff --git a/hs20/client/Makefile b/hs20/client/Makefile
index 67f6f55..4dcfe2d 100644
--- a/hs20/client/Makefile
+++ b/hs20/client/Makefile
@@ -1,28 +1,6 @@
-all: hs20-osu-client
+ALL=hs20-osu-client
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifeq ($(QUIET), 1)
-Q=@
-E=true
-else
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../../src/build.rules
CFLAGS += -I../../src/utils
CFLAGS += -I../../src/common
@@ -30,8 +8,17 @@ CFLAGS += -I../../src
ifndef CONFIG_NO_BROWSER
ifndef CONFIG_BROWSER_SYSTEM
+TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0)
+ifeq ($(TEST_WK),)
+# Try webkit2
+GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0)
+GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0)
+CFLAGS += -DUSE_WEBKIT2
+else
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0)
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
+endif
+
CFLAGS += $(GTKCFLAGS)
LIBS += $(GTKLIBS)
endif
@@ -84,23 +71,11 @@ CFLAGS += -DEAP_TLS_OPENSSL
OBJS += ../../src/crypto/tls_openssl_ocsp.o
LIBS += -lssl -lcrypto
+_OBJS_VAR := OBJS
+include ../../src/objs.mk
hs20-osu-client: $(OBJS)
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
@$(E) " LD " $@
-%.o: %.c
- $(Q)$(CC) -c -o $@ $(CFLAGS) $<
- @$(E) " CC " $<
-
-clean:
- rm -f core *~ *.o *.d hs20-osu-client
- rm -f ../../src/utils/*.o
- rm -f ../../src/utils/*.d
- rm -f ../../src/common/*.o
- rm -f ../../src/common/*.d
- rm -f ../../src/crypto/*.o
- rm -f ../../src/crypto/*.d
- rm -f ../../src/wps/*.o
- rm -f ../../src/wps/*.d
-
--include $(OBJS:%.o=%.d)
+clean: common-clean
+ rm -f core *~
diff --git a/hs20/client/est.c b/hs20/client/est.c
index db65334..97f9132 100644
--- a/hs20/client/est.c
+++ b/hs20/client/est.c
@@ -158,7 +158,7 @@ int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
return -1;
}
- pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
+ pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 && pkcs7_len < resp_len / 2) {
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
(unsigned int) pkcs7_len, (unsigned int) resp_len);
@@ -639,8 +639,7 @@ int est_build_csr(struct hs20_osu_client *ctx, const char *url)
return -1;
}
- attrs = base64_decode((unsigned char *) resp, resp_len,
- &attrs_len);
+ attrs = base64_decode(resp, resp_len, &attrs_len);
os_free(resp);
if (attrs == NULL) {
@@ -734,7 +733,7 @@ int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
}
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
- pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
+ pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
diff --git a/hs20/client/oma_dm_client.c b/hs20/client/oma_dm_client.c
index d75c845..bcd68b8 100644
--- a/hs20/client/oma_dm_client.c
+++ b/hs20/client/oma_dm_client.c
@@ -407,7 +407,7 @@ static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec)
wpa_printf(MSG_INFO, "Data: %s", data);
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data);
write_summary(ctx, "Launch browser to URI '%s'", data);
- res = hs20_web_browser(data);
+ res = hs20_web_browser(data, 1);
xml_node_get_text_free(ctx->xml, data);
if (res > 0) {
wpa_printf(MSG_INFO, "User response in browser completed successfully");
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index fd99600..11bf0db 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -310,7 +310,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
size_t len;
u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN];
int res;
- unsigned char *b64;
+ char *b64;
FILE *f;
url_node = get_node(ctx->xml, params, "CertURL");
@@ -364,7 +364,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
return -1;
}
- b64 = base64_encode((unsigned char *) cert, len, NULL);
+ b64 = base64_encode(cert, len, NULL);
os_free(cert);
if (b64 == NULL)
return -1;
@@ -2233,7 +2233,7 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
wpa_ctrl_close(mon);
if (res < 0) {
- wpa_printf(MSG_INFO, "Could not connect");
+ wpa_printf(MSG_INFO, "Could not connect to OSU network");
write_summary(ctx, "Could not connect to OSU network");
wpa_printf(MSG_INFO, "Remove OSU network connection");
snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id);
@@ -2406,7 +2406,7 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir);
write_summary(ctx, "Start web browser with OSU provider selection page");
- ret = hs20_web_browser(fname);
+ ret = hs20_web_browser(fname, 0);
selected:
if (ret > 0 && (size_t) ret <= osu_count) {
@@ -2907,7 +2907,7 @@ static char * get_hostname(const char *url)
static int osu_cert_cb(void *_ctx, struct http_cert *cert)
{
struct hs20_osu_client *ctx = _ctx;
- unsigned int i, j;
+ size_t i, j;
int found;
char *host = NULL;
@@ -3002,7 +3002,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
size_t name_len = os_strlen(name);
wpa_printf(MSG_INFO,
- "[%i] Looking for icon file name '%s' match",
+ "[%zu] Looking for icon file name '%s' match",
j, name);
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
@@ -3010,7 +3010,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
char *pos;
wpa_printf(MSG_INFO,
- "[%i] Comparing to '%s' uri_len=%d name_len=%d",
+ "[%zu] Comparing to '%s' uri_len=%d name_len=%d",
i, logo->uri, (int) uri_len, (int) name_len);
if (uri_len < 1 + name_len) {
wpa_printf(MSG_INFO, "URI Length is too short");
@@ -3044,7 +3044,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
if (logo->hash_len != 32) {
wpa_printf(MSG_INFO,
- "[%i][%i] Icon hash length invalid (should be 32): %d",
+ "[%zu][%zu] Icon hash length invalid (should be 32): %d",
j, i, (int) logo->hash_len);
continue;
}
@@ -3054,7 +3054,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
}
wpa_printf(MSG_DEBUG,
- "[%u][%u] Icon hash did not match", j, i);
+ "[%zu][%zu] Icon hash did not match", j, i);
wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
logo->hash, 32);
wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
@@ -3152,7 +3152,7 @@ static void check_workarounds(struct hs20_osu_client *ctx)
static void usage(void)
{
- printf("usage: hs20-osu-client [-dddqqKt] [-S<station ifname>] \\\n"
+ printf("usage: hs20-osu-client [-dddqqKtT] [-S<station ifname>] \\\n"
" [-w<wpa_supplicant ctrl_iface dir>] "
"[-r<result file>] [-f<debug file>] \\\n"
" [-s<summary file>] \\\n"
@@ -3198,7 +3198,7 @@ int main(int argc, char *argv[])
return -1;
for (;;) {
- c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tw:x:");
+ c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:");
if (c < 0)
break;
switch (c) {
@@ -3236,6 +3236,9 @@ int main(int argc, char *argv[])
case 't':
wpa_debug_timestamp++;
break;
+ case 'T':
+ ctx.ignore_tls = 1;
+ break;
case 'w':
wpas_ctrl_path = optarg;
break;
@@ -3403,7 +3406,7 @@ int main(int argc, char *argv[])
wpa_printf(MSG_INFO, "Launch web browser to URL %s",
argv[optind + 1]);
- ret = hs20_web_browser(argv[optind + 1]);
+ ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls);
wpa_printf(MSG_INFO, "Web browser result: %d", ret);
} else if (strcmp(argv[optind], "parse_cert") == 0) {
if (argc - optind < 2) {
diff --git a/hs20/client/osu_client.h b/hs20/client/osu_client.h
index 5c8e6d0..9b45b03 100644
--- a/hs20/client/osu_client.h
+++ b/hs20/client/osu_client.h
@@ -50,6 +50,8 @@ struct hs20_osu_client {
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
unsigned long int workarounds;
+ int ignore_tls; /* whether to ignore TLS validation issues with HTTPS
+ * server certificate */
};
diff --git a/hs20/client/spp_client.c b/hs20/client/spp_client.c
index c619541..39d10e0 100644
--- a/hs20/client/spp_client.c
+++ b/hs20/client/spp_client.c
@@ -547,7 +547,7 @@ static int hs20_spp_exec(struct hs20_osu_client *ctx, xml_node_t *exec,
}
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri);
write_summary(ctx, "Launch browser to URI '%s'", uri);
- res = hs20_web_browser(uri);
+ res = hs20_web_browser(uri, 1);
xml_node_get_text_free(ctx->xml, uri);
if (res > 0) {
wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'",
diff --git a/hs20/server/.gitignore b/hs20/server/.gitignore
new file mode 100644
index 0000000..fecb096
--- /dev/null
+++ b/hs20/server/.gitignore
@@ -0,0 +1 @@
+hs20_spp_server
diff --git a/hs20/server/Makefile b/hs20/server/Makefile
index 9b73727..0cab6d6 100644
--- a/hs20/server/Makefile
+++ b/hs20/server/Makefile
@@ -1,16 +1,6 @@
-all: hs20_spp_server
+ALL=hs20_spp_server
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../../src/build.rules
CFLAGS += -I../../src
CFLAGS += -I../../src/utils
@@ -43,14 +33,10 @@ CFLAGS += $(shell xml2-config --cflags)
LIBS += $(shell xml2-config --libs)
OBJS += ../../src/utils/xml_libxml2.o
+_OBJS_VAR := OBJS
+include ../../src/objs.mk
hs20_spp_server: $(OBJS)
$(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS)
-clean:
- rm -f core *~ *.o *.d hs20_spp_server
- rm -f ../../src/utils/*.o
- rm -f ../../src/utils/*.d
- rm -f ../../src/crypto/*.o
- rm -f ../../src/crypto/*.d
-
--include $(OBJS:%.o=%.d)
+clean: common-clean
+ rm -f core *~
diff --git a/hs20/server/ca/ocsp-responder.sh b/hs20/server/ca/ocsp-responder.sh
index 8cebd74..620947d 100755
--- a/hs20/server/ca/ocsp-responder.sh
+++ b/hs20/server/ca/ocsp-responder.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text
+openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err
diff --git a/hs20/server/ca/ocsp-update-cache.sh b/hs20/server/ca/ocsp-update-cache.sh
index 8ddef9b..f2b2325 100755
--- a/hs20/server/ca/ocsp-update-cache.sh
+++ b/hs20/server/ca/ocsp-update-cache.sh
@@ -1,5 +1,6 @@
#!/bin/sh
+# NOTE: You may need to replace 'localhost' with your OCSP server hostname.
openssl ocsp \
-no_nonce \
-CAfile ca.pem \
diff --git a/hs20/server/hs20_spp_server.c b/hs20/server/hs20_spp_server.c
index 6c74f54..347c40a 100644
--- a/hs20/server/hs20_spp_server.c
+++ b/hs20/server/hs20_spp_server.c
@@ -176,7 +176,7 @@ int main(int argc, char *argv[])
ctx.root_dir = optarg;
break;
case 'v':
- printf("hs20_spp_server v" VERSION_STR "\n");
+ printf("hs20_spp_server v%s\n", VERSION_STR);
return 0;
default:
usage();
diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c
index 4bef0ff..a50e907 100644
--- a/hs20/server/spp_server.c
+++ b/hs20/server/spp_server.c
@@ -633,7 +633,7 @@ static xml_node_t * build_username_password(struct hs20_svc *ctx,
add_text_node(ctx, node, "Username", user);
- b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL);
+ b64 = base64_encode(pw, strlen(pw), NULL);
if (b64 == NULL)
return NULL;
len = os_strlen(b64);
@@ -1602,8 +1602,7 @@ static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx,
xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user);
- b64 = (char *) base64_encode((unsigned char *) password,
- strlen(password), NULL);
+ b64 = base64_encode(password, strlen(password), NULL);
if (b64 == NULL) {
xml_node_free(ctx->xml, spp_node);
return NULL;
diff --git a/radius_example/Makefile b/radius_example/Makefile
index 883e2f2..d58a82c 100644
--- a/radius_example/Makefile
+++ b/radius_example/Makefile
@@ -1,18 +1,6 @@
ALL=radius_example
-all: $(ALL)
-
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../src/build.rules
CFLAGS += -I.
CFLAGS += -I../src
@@ -23,24 +11,18 @@ LIBS += ../src/crypto/libcrypto.a
LIBS += ../src/utils/libutils.a
LLIBS = -lrt
-../src/utils/libutils.a:
- $(MAKE) -C ../src/utils
-
-../src/crypto/libcrypto.a:
- $(MAKE) -C ../src/crypto
-
-../src/radius/libradius.a:
- $(MAKE) -C ../src/radius
-
#CLAGS += -DCONFIG_IPV6
OBJS_ex = radius_example.o
+_OBJS_VAR := OBJS_ex
+include ../src/objs.mk
+
+_OBJS_VAR := LIBS
+include ../src/objs.mk
+
radius_example: $(OBJS_ex) $(LIBS)
$(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS)
-clean:
- $(MAKE) -C ../src clean
- rm -f core *~ *.o *.d $(ALL)
-
--include $(OBJS:%.o=%.d)
+clean: common-clean
+ rm -f core *~ *.o *.d
diff --git a/src/Makefile b/src/Makefile
index c9e84c1..6eb7f2a 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -5,8 +5,8 @@ all:
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
clean:
- for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
- rm -f *~
+ $(Q)for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
+ $(Q)rm -f *~
install:
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done
diff --git a/src/ap/Makefile b/src/ap/Makefile
index 54e48a0..a1e9b7c 100644
--- a/src/ap/Makefile
+++ b/src/ap/Makefile
@@ -1,13 +1,3 @@
-all: libap.a
-
-clean:
- rm -f *~ *.o *.d *.gcno *.gcda *.gcov libap.a
-
-install:
- @echo Nothing to be made.
-
-include ../lib.rules
-
CFLAGS += -DHOSTAPD
CFLAGS += -DNEED_AP_MLME
CFLAGS += -DCONFIG_ETH_P_OUI
@@ -67,7 +57,4 @@ LIB_OBJS= \
wps_hostapd.o \
x_snoop.o
-libap.a: $(LIB_OBJS)
- $(AR) crT $@ $?
-
--include $(OBJS:%.o=%.d)
+include ../lib.rules
diff --git a/src/ap/acs.c b/src/ap/acs.c
index f12539f..aa2ceb0 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -261,13 +261,13 @@ static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
}
-void acs_cleanup(struct hostapd_iface *iface)
+static void acs_cleanup_mode(struct hostapd_hw_modes *mode)
{
int i;
struct hostapd_channel_data *chan;
- for (i = 0; i < iface->current_mode->num_channels; i++) {
- chan = &iface->current_mode->channels[i];
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
acs_clean_chan_surveys(chan);
@@ -276,6 +276,15 @@ void acs_cleanup(struct hostapd_iface *iface)
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
chan->min_nf = 0;
}
+}
+
+
+void acs_cleanup(struct hostapd_iface *iface)
+{
+ int i;
+
+ for (i = 0; i < iface->num_hw_features; i++)
+ acs_cleanup_mode(&iface->hw_features[i]);
iface->chans_surveyed = 0;
iface->acs_num_completed_scans = 0;
@@ -453,21 +462,35 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
}
-static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
+static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode)
{
int i;
struct hostapd_channel_data *chan;
- int valid = 0;
- for (i = 0; i < iface->current_mode->num_channels; i++) {
- chan = &iface->current_mode->channels[i];
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
acs_survey_list_is_sufficient(chan))
- valid++;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
+{
+ int i;
+ struct hostapd_hw_modes *mode;
+
+ for (i = 0; i < iface->num_hw_features; i++) {
+ mode = &iface->hw_features[i];
+ if (!hostapd_hw_skip_mode(iface, mode) &&
+ acs_surveys_are_sufficient_mode(mode))
+ return 1;
}
- /* We need at least survey data for one channel */
- return !!valid;
+ return 0;
}
@@ -489,14 +512,25 @@ static int is_in_chanlist(struct hostapd_iface *iface,
}
-static void acs_survey_all_chans_intereference_factor(
- struct hostapd_iface *iface)
+static int is_in_freqlist(struct hostapd_iface *iface,
+ struct hostapd_channel_data *chan)
+{
+ if (!iface->conf->acs_freq_list.num)
+ return 1;
+
+ return freq_range_list_includes(&iface->conf->acs_freq_list,
+ chan->freq);
+}
+
+
+static void acs_survey_mode_interference_factor(
+ struct hostapd_iface *iface, struct hostapd_hw_modes *mode)
{
int i;
struct hostapd_channel_data *chan;
- for (i = 0; i < iface->current_mode->num_channels; i++) {
- chan = &iface->current_mode->channels[i];
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
if (!acs_usable_chan(chan))
continue;
@@ -504,6 +538,9 @@ static void acs_survey_all_chans_intereference_factor(
if (!is_in_chanlist(iface, chan))
continue;
+ if (!is_in_freqlist(iface, chan))
+ continue;
+
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
chan->chan, chan->freq);
@@ -515,14 +552,28 @@ static void acs_survey_all_chans_intereference_factor(
}
-static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
- int freq)
+static void acs_survey_all_chans_interference_factor(
+ struct hostapd_iface *iface)
+{
+ int i;
+ struct hostapd_hw_modes *mode;
+
+ for (i = 0; i < iface->num_hw_features; i++) {
+ mode = &iface->hw_features[i];
+ if (!hostapd_hw_skip_mode(iface, mode))
+ acs_survey_mode_interference_factor(iface, mode);
+ }
+}
+
+
+static struct hostapd_channel_data *
+acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq)
{
struct hostapd_channel_data *chan;
int i;
- for (i = 0; i < iface->current_mode->num_channels; i++) {
- chan = &iface->current_mode->channels[i];
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
@@ -535,6 +586,26 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
}
+static struct hostapd_channel_data *
+acs_find_chan(struct hostapd_iface *iface, int freq)
+{
+ int i;
+ struct hostapd_hw_modes *mode;
+ struct hostapd_channel_data *chan;
+
+ for (i = 0; i < iface->num_hw_features; i++) {
+ mode = &iface->hw_features[i];
+ if (!hostapd_hw_skip_mode(iface, mode)) {
+ chan = acs_find_chan_mode(mode, freq);
+ if (chan)
+ return chan;
+ }
+ }
+
+ return NULL;
+}
+
+
static int is_24ghz_mode(enum hostapd_hw_mode mode)
{
return mode == HOSTAPD_MODE_IEEE80211B ||
@@ -565,58 +636,24 @@ static int is_common_24ghz_chan(int chan)
#define ACS_24GHZ_PREFER_1_6_11 0.8
#endif /* ACS_24GHZ_PREFER_1_6_11 */
-/*
- * At this point it's assumed chan->interface_factor has been computed.
- * This function should be reusable regardless of interference computation
- * option (survey, BSS, spectral, ...). chan->interference factor must be
- * summable (i.e., must be always greater than zero).
- */
-static struct hostapd_channel_data *
-acs_find_ideal_chan(struct hostapd_iface *iface)
+static void
+acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode,
+ int n_chans, u32 bw,
+ struct hostapd_channel_data **rand_chan,
+ struct hostapd_channel_data **ideal_chan,
+ long double *ideal_factor)
{
- struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
- *rand_chan = NULL;
- long double factor, ideal_factor = 0;
+ struct hostapd_channel_data *chan, *adj_chan = NULL;
+ long double factor;
int i, j;
- int n_chans = 1;
- u32 bw;
unsigned int k;
- /* TODO: HT40- support */
-
- if (iface->conf->ieee80211n &&
- iface->conf->secondary_channel == -1) {
- wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
- return NULL;
- }
-
- if (iface->conf->ieee80211n &&
- iface->conf->secondary_channel)
- n_chans = 2;
-
- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
- switch (hostapd_get_oper_chwidth(iface->conf)) {
- case CHANWIDTH_80MHZ:
- n_chans = 4;
- break;
- case CHANWIDTH_160MHZ:
- n_chans = 8;
- break;
- }
- }
-
- bw = num_chan_to_bw(n_chans);
-
- /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
-
- wpa_printf(MSG_DEBUG,
- "ACS: Survey analysis for selected bandwidth %d MHz", bw);
-
- for (i = 0; i < iface->current_mode->num_channels; i++) {
+ for (i = 0; i < mode->num_channels; i++) {
double total_weight;
struct acs_bias *bias, tmp_bias;
- chan = &iface->current_mode->channels[i];
+ chan = &mode->channels[i];
/* Since in the current ACS implementation the first channel is
* always a primary channel, skip channels not available as
@@ -628,6 +665,9 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
if (!is_in_chanlist(iface, chan))
continue;
+ if (!is_in_freqlist(iface, chan))
+ continue;
+
if (!chan_bw_allowed(chan, bw, 1, 1)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: BW %u is not supported",
@@ -637,7 +677,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
/* HT40 on 5 GHz has a limited set of primary channels as per
* 11n Annex J */
- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+ if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
iface->conf->ieee80211n &&
iface->conf->secondary_channel &&
!acs_usable_ht40_chan(chan)) {
@@ -646,7 +686,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
continue;
}
- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+ if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
if (hostapd_get_oper_chwidth(iface->conf) ==
CHANWIDTH_80MHZ &&
@@ -698,7 +738,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
* channel interference factor. */
- if (is_24ghz_mode(iface->current_mode->mode)) {
+ if (is_24ghz_mode(mode->mode)) {
for (j = 0; j < n_chans; j++) {
adj_chan = acs_find_chan(iface, chan->freq +
(j * 20) - 5);
@@ -744,7 +784,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
break;
bias = NULL;
}
- } else if (is_24ghz_mode(iface->current_mode->mode) &&
+ } else if (is_24ghz_mode(mode->mode) &&
is_common_24ghz_chan(chan->chan)) {
tmp_bias.channel = chan->chan;
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
@@ -763,14 +803,71 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
}
if (acs_usable_chan(chan) &&
- (!ideal_chan || factor < ideal_factor)) {
- ideal_factor = factor;
- ideal_chan = chan;
+ (!*ideal_chan || factor < *ideal_factor)) {
+ *ideal_factor = factor;
+ *ideal_chan = chan;
}
/* This channel would at least be usable */
- if (!rand_chan)
- rand_chan = chan;
+ if (!(*rand_chan))
+ *rand_chan = chan;
+ }
+}
+
+
+/*
+ * At this point it's assumed chan->interference_factor has been computed.
+ * This function should be reusable regardless of interference computation
+ * option (survey, BSS, spectral, ...). chan->interference factor must be
+ * summable (i.e., must be always greater than zero).
+ */
+static struct hostapd_channel_data *
+acs_find_ideal_chan(struct hostapd_iface *iface)
+{
+ struct hostapd_channel_data *ideal_chan = NULL,
+ *rand_chan = NULL;
+ long double ideal_factor = 0;
+ int i;
+ int n_chans = 1;
+ u32 bw;
+ struct hostapd_hw_modes *mode;
+
+ /* TODO: HT40- support */
+
+ if (iface->conf->ieee80211n &&
+ iface->conf->secondary_channel == -1) {
+ wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
+ return NULL;
+ }
+
+ if (iface->conf->ieee80211n &&
+ iface->conf->secondary_channel)
+ n_chans = 2;
+
+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
+ switch (hostapd_get_oper_chwidth(iface->conf)) {
+ case CHANWIDTH_80MHZ:
+ n_chans = 4;
+ break;
+ case CHANWIDTH_160MHZ:
+ n_chans = 8;
+ break;
+ }
+ }
+
+ bw = num_chan_to_bw(n_chans);
+
+ /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
+
+ wpa_printf(MSG_DEBUG,
+ "ACS: Survey analysis for selected bandwidth %d MHz", bw);
+
+ for (i = 0; i < iface->num_hw_features; i++) {
+ mode = &iface->hw_features[i];
+ if (!hostapd_hw_skip_mode(iface, mode))
+ acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
+ &rand_chan, &ideal_chan,
+ &ideal_factor);
}
if (ideal_chan) {
@@ -826,7 +923,7 @@ static int acs_study_survey_based(struct hostapd_iface *iface)
return -1;
}
- acs_survey_all_chans_intereference_factor(iface);
+ acs_survey_all_chans_interference_factor(iface);
return 0;
}
@@ -862,6 +959,7 @@ static void acs_study(struct hostapd_iface *iface)
}
iface->conf->channel = ideal_chan->chan;
+ iface->freq = ideal_chan->freq;
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
acs_adjust_center_freq(iface);
@@ -917,29 +1015,59 @@ fail:
}
+static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode,
+ int *freq)
+{
+ struct hostapd_channel_data *chan;
+ int i;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
+ if (chan->flag & HOSTAPD_CHAN_DISABLED)
+ continue;
+
+ if (!is_in_chanlist(iface, chan))
+ continue;
+
+ if (!is_in_freqlist(iface, chan))
+ continue;
+
+ *freq++ = chan->freq;
+ }
+
+ return freq;
+}
+
+
static int acs_request_scan(struct hostapd_iface *iface)
{
struct wpa_driver_scan_params params;
- struct hostapd_channel_data *chan;
int i, *freq;
+ int num_channels;
+ struct hostapd_hw_modes *mode;
os_memset(&params, 0, sizeof(params));
- params.freqs = os_calloc(iface->current_mode->num_channels + 1,
- sizeof(params.freqs[0]));
+
+ num_channels = 0;
+ for (i = 0; i < iface->num_hw_features; i++) {
+ mode = &iface->hw_features[i];
+ if (!hostapd_hw_skip_mode(iface, mode))
+ num_channels += mode->num_channels;
+ }
+
+ params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0]));
if (params.freqs == NULL)
return -1;
freq = params.freqs;
- for (i = 0; i < iface->current_mode->num_channels; i++) {
- chan = &iface->current_mode->channels[i];
- if (chan->flag & HOSTAPD_CHAN_DISABLED)
- continue;
- if (!is_in_chanlist(iface, chan))
- continue;
-
- *freq++ = chan->freq;
+ for (i = 0; i < iface->num_hw_features; i++) {
+ mode = &iface->hw_features[i];
+ if (!hostapd_hw_skip_mode(iface, mode))
+ freq = acs_request_scan_add_freqs(iface, mode, freq);
}
+
*freq = 0;
if (params.freqs == freq) {
@@ -977,7 +1105,8 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
return HOSTAPD_CHAN_ACS;
}
- if (!iface->current_mode)
+ if (!iface->current_mode &&
+ iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
return HOSTAPD_CHAN_INVALID;
acs_cleanup(iface);
diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c
index f56ca5b..1e67f0d 100644
--- a/src/ap/airtime_policy.c
+++ b/src/ap/airtime_policy.c
@@ -134,8 +134,8 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
unsigned int num_sta_min = 0, num_sta_prod = 1, num_sta_sum = 0,
wt_sum = 0;
unsigned int quantum;
- Boolean all_div_min = TRUE;
- Boolean apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
+ bool all_div_min = true;
+ bool apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
int wt, num_bss = 0, max_wt = 0;
size_t i;
@@ -169,7 +169,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
* integers. */
if (bss->num_backlogged_sta &&
bss->num_backlogged_sta % num_sta_min > 0)
- all_div_min = FALSE;
+ all_div_min = false;
/* If we're in LIMIT mode, we only apply the weight
* scaling when the BSS(es) marked as limited would a
@@ -178,7 +178,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
if (!apply_limit && bss->conf->airtime_limit) {
if (bss->num_backlogged_sta * wt_sum >
bss->conf->airtime_weight * num_sta_sum)
- apply_limit = TRUE;
+ apply_limit = true;
}
}
if (all_div_min)
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 58fc3e9..04535a1 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -54,23 +54,33 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->logger_syslog = (unsigned int) -1;
bss->logger_stdout = (unsigned int) -1;
+#ifdef CONFIG_WEP
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
bss->wep_rekeying_period = 300;
/* use key0 in individual key and key1 in broadcast key */
bss->broadcast_key_idx_min = 1;
bss->broadcast_key_idx_max = 2;
+#else /* CONFIG_WEP */
+ bss->auth_algs = WPA_AUTH_ALG_OPEN;
+#endif /* CONFIG_WEP */
bss->eap_reauth_period = 3600;
bss->wpa_group_rekey = 600;
bss->wpa_gmk_rekey = 86400;
+ bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
bss->wpa_group_update_count = 4;
bss->wpa_pairwise_update_count = 4;
bss->wpa_disable_eapol_key_retries =
DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
+#ifdef CONFIG_NO_TKIP
+ bss->wpa_pairwise = WPA_CIPHER_CCMP;
+ bss->wpa_group = WPA_CIPHER_CCMP;
+#else /* CONFIG_NO_TKIP */
bss->wpa_pairwise = WPA_CIPHER_TKIP;
bss->wpa_group = WPA_CIPHER_TKIP;
+#endif /* CONFIG_NO_TKIP */
bss->rsn_pairwise = 0;
bss->max_num_sta = MAX_STA_COUNT;
@@ -150,6 +160,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
/* Default to strict CRL checking. */
bss->check_crl_strict = 1;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ bss->sae_commit_status = -1;
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -251,6 +265,9 @@ struct hostapd_config * hostapd_config_defaults(void)
HE_OPERATION_RTS_THRESHOLD_OFFSET;
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
conf->he_op.he_basic_mcs_nss_set = 0xfffc;
+ conf->he_op.he_bss_color_disabled = 1;
+ conf->he_op.he_bss_color_partial = 0;
+ conf->he_op.he_bss_color = 1;
#endif /* CONFIG_IEEE80211AX */
/* The third octet of the country string uses an ASCII space character
@@ -301,6 +318,7 @@ static int hostapd_config_read_wpa_psk(const char *fname,
while (fgets(buf, sizeof(buf), f)) {
int vlan_id = 0;
+ int wps = 0;
line++;
@@ -331,6 +349,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
value = "";
if (!os_strcmp(name, "keyid")) {
keyid = value;
+ } else if (!os_strcmp(name, "wps")) {
+ wps = atoi(value);
} else if (!os_strcmp(name, "vlanid")) {
vlan_id = atoi(value);
} else {
@@ -348,8 +368,9 @@ static int hostapd_config_read_wpa_psk(const char *fname,
if (!token)
token = "";
if (hwaddr_aton(token, addr)) {
- wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
- "line %d in '%s'", token, line, fname);
+ wpa_printf(MSG_ERROR,
+ "Invalid MAC address '%s' on line %d in '%s'",
+ token, line, fname);
ret = -1;
break;
}
@@ -377,16 +398,17 @@ static int hostapd_config_read_wpa_psk(const char *fname,
ok = 0;
len = os_strlen(pos);
- if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
+ if (len == 2 * PMK_LEN &&
+ hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
ok = 1;
- else if (len >= 8 && len < 64) {
- pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
- 4096, psk->psk, PMK_LEN);
+ else if (len >= 8 && len < 64 &&
+ pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
+ 4096, psk->psk, PMK_LEN) == 0)
ok = 1;
- }
if (!ok) {
- wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
- "'%s'", pos, line, fname);
+ wpa_printf(MSG_ERROR,
+ "Invalid PSK '%s' on line %d in '%s'",
+ pos, line, fname);
os_free(psk);
ret = -1;
break;
@@ -404,6 +426,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
}
}
+ psk->wps = wps;
+
psk->next = ssid->wpa_psk;
ssid->wpa_psk = psk;
}
@@ -441,7 +465,10 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
struct hostapd_ssid *ssid = &conf->ssid;
struct sae_password_entry *pw;
- if (conf->sae_pwe == 0)
+ if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) &&
+ !hostapd_sae_pk_in_use(conf)) ||
+ conf->sae_pwe == 3 ||
+ !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
return 0; /* PT not needed */
sae_deinit_pt(ssid->pt);
@@ -623,6 +650,7 @@ void hostapd_config_free_eap_users(struct hostapd_eap_user *user)
}
+#ifdef CONFIG_WEP
static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
{
int i;
@@ -631,6 +659,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
keys->key[i] = NULL;
}
}
+#endif /* CONFIG_WEP */
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
@@ -687,6 +716,9 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
#ifdef CONFIG_SAE
sae_deinit_pt(tmp->pt);
#endif /* CONFIG_SAE */
+#ifdef CONFIG_SAE_PK
+ sae_deinit_pk(tmp->pk);
+#endif /* CONFIG_SAE_PK */
os_free(tmp);
}
}
@@ -719,7 +751,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
str_clear_free(conf->ssid.wpa_passphrase);
os_free(conf->ssid.wpa_psk_file);
+#ifdef CONFIG_WEP
hostapd_config_free_wep(&conf->ssid.wep);
+#endif /* CONFIG_WEP */
#ifdef CONFIG_FULL_DYNAMIC_VLAN
os_free(conf->ssid.vlan_tagged_interface);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
@@ -813,6 +847,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->upc);
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
wpabuf_free(conf->wps_vendor_ext[i]);
+ wpabuf_free(conf->wps_application_ext);
wpabuf_free(conf->wps_nfc_dh_pubkey);
wpabuf_free(conf->wps_nfc_dh_privkey);
wpabuf_free(conf->wps_nfc_dev_pw);
@@ -880,6 +915,12 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->sae_commit_override);
+ wpabuf_free(conf->rsne_override_eapol);
+ wpabuf_free(conf->rsnxe_override_eapol);
+ wpabuf_free(conf->rsne_override_ft);
+ wpabuf_free(conf->rsnxe_override_ft);
+ wpabuf_free(conf->gtk_rsc_override);
+ wpabuf_free(conf->igtk_rsc_override);
#endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on);
@@ -935,6 +976,7 @@ void hostapd_config_free(struct hostapd_config *conf)
os_free(conf->supported_rates);
os_free(conf->basic_rates);
os_free(conf->acs_ch_list.range);
+ os_free(conf->acs_freq_list.range);
os_free(conf->driver_params);
#ifdef CONFIG_ACS
os_free(conf->acs_chan_bias);
@@ -1077,6 +1119,37 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
}
+#ifdef CONFIG_SAE_PK
+static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss)
+{
+ struct sae_password_entry *pw;
+ bool res = false;
+
+ if (bss->ssid.wpa_passphrase &&
+#ifdef CONFIG_TESTING_OPTIONS
+ !bss->sae_pk_password_check_skip &&
+#endif /* CONFIG_TESTING_OPTIONS */
+ sae_pk_valid_password(bss->ssid.wpa_passphrase))
+ res = true;
+
+ for (pw = bss->sae_passwords; pw; pw = pw->next) {
+ if (!pw->pk &&
+#ifdef CONFIG_TESTING_OPTIONS
+ !bss->sae_pk_password_check_skip &&
+#endif /* CONFIG_TESTING_OPTIONS */
+ sae_pk_valid_password(pw->password))
+ return true;
+
+ if (bss->ssid.wpa_passphrase && res && pw->pk &&
+ os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0)
+ res = false;
+ }
+
+ return res;
+}
+#endif /* CONFIG_SAE_PK */
+
+
static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
struct hostapd_config *conf,
int full_config)
@@ -1088,6 +1161,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
return -1;
}
+#ifdef CONFIG_WEP
if (bss->wpa) {
int wep, i;
@@ -1105,6 +1179,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
return -1;
}
}
+#endif /* CONFIG_WEP */
if (full_config && bss->wpa &&
bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
@@ -1152,7 +1227,6 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
}
#endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211N
if (full_config && conf->ieee80211n &&
conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
bss->disable_11n = 1;
@@ -1160,12 +1234,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
"allowed, disabling HT capabilities");
}
+#ifdef CONFIG_WEP
if (full_config && conf->ieee80211n &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
"allowed, disabling HT capabilities");
}
+#endif /* CONFIG_WEP */
if (full_config && conf->ieee80211n && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
@@ -1177,15 +1253,16 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
"requires CCMP/GCMP to be enabled, disabling HT "
"capabilities");
}
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
+#ifdef CONFIG_WEP
if (full_config && conf->ieee80211ac &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11ac = 1;
wpa_printf(MSG_ERROR,
"VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
}
+#endif /* CONFIG_WEP */
if (full_config && conf->ieee80211ac && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
@@ -1205,12 +1282,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
bss->wps_state = 0;
}
+#ifdef CONFIG_WEP
if (full_config && bss->wps_state &&
bss->ssid.wep.keys_set && bss->wpa == 0) {
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
"disabled");
bss->wps_state = 0;
}
+#endif /* CONFIG_WEP */
if (full_config && bss->wps_state && bss->wpa &&
(!(bss->wpa & 2) ||
@@ -1254,6 +1333,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
}
#endif /* CONFIG_OCV */
+#ifdef CONFIG_SAE_PK
+ if (full_config && hostapd_sae_pk_in_use(bss) &&
+ hostapd_sae_pk_password_without_pk(bss)) {
+ wpa_printf(MSG_ERROR,
+ "SAE-PK: SAE password uses SAE-PK style, but does not have PK configured");
+ return -1;
+ }
+#endif /* CONFIG_SAE_PK */
+
return 0;
}
@@ -1334,11 +1422,13 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
void hostapd_set_security_params(struct hostapd_bss_config *bss,
int full_config)
{
+#ifdef CONFIG_WEP
if (bss->individual_wep_key_len == 0) {
/* individual keys are not use; can use key idx0 for
* broadcast keys */
bss->broadcast_key_idx_min = 0;
}
+#endif /* CONFIG_WEP */
if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
bss->rsn_pairwise = bss->wpa_pairwise;
@@ -1364,6 +1454,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
} else if (bss->ieee802_1x) {
int cipher = WPA_CIPHER_NONE;
bss->ssid.security_policy = SECURITY_IEEE_802_1X;
+#ifdef CONFIG_WEP
bss->ssid.wep.default_len = bss->default_wep_key_len;
if (full_config && bss->default_wep_key_len) {
cipher = bss->default_wep_key_len >= 13 ?
@@ -1374,11 +1465,13 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
else
cipher = WPA_CIPHER_WEP40;
}
+#endif /* CONFIG_WEP */
bss->wpa_group = cipher;
bss->wpa_pairwise = cipher;
bss->rsn_pairwise = cipher;
if (full_config)
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
+#ifdef CONFIG_WEP
} else if (bss->ssid.wep.keys_set) {
int cipher = WPA_CIPHER_WEP40;
if (bss->ssid.wep.len[0] >= 13)
@@ -1389,6 +1482,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
bss->rsn_pairwise = cipher;
if (full_config)
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
+#endif /* CONFIG_WEP */
} else if (bss->osen) {
bss->ssid.security_policy = SECURITY_OSEN;
bss->wpa_group = WPA_CIPHER_CCMP;
@@ -1427,3 +1521,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
return 2;
return with_id;
}
+
+
+bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf)
+{
+#ifdef CONFIG_SAE_PK
+ struct sae_password_entry *pw;
+
+ for (pw = conf->sae_passwords; pw; pw = pw->next) {
+ if (pw->pk)
+ return true;
+ }
+#endif /* CONFIG_SAE_PK */
+
+ return false;
+}
+
+
+#ifdef CONFIG_SAE_PK
+bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf)
+{
+ bool with_pk = false;
+ struct sae_password_entry *pw;
+
+ if (conf->ssid.wpa_passphrase)
+ return false;
+
+ for (pw = conf->sae_passwords; pw; pw = pw->next) {
+ if (!pw->pk)
+ return false;
+ with_pk = true;
+ }
+
+ return with_pk;
+}
+#endif /* CONFIG_SAE_PK */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2a0c984..bada04c 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -67,6 +67,7 @@ struct hostapd_radius_servers;
struct ft_remote_r0kh;
struct ft_remote_r1kh;
+#ifdef CONFIG_WEP
#define NUM_WEP_KEYS 4
struct hostapd_wep_keys {
u8 idx;
@@ -75,10 +76,13 @@ struct hostapd_wep_keys {
int keys_set;
size_t default_len; /* key length used for dynamic key generation */
};
+#endif /* CONFIG_WEP */
typedef enum hostap_security_policy {
SECURITY_PLAINTEXT = 0,
+#ifdef CONFIG_WEP
SECURITY_STATIC_WEP = 1,
+#endif /* CONFIG_WEP */
SECURITY_IEEE_802_1X = 2,
SECURITY_WPA_PSK = 3,
SECURITY_WPA = 4,
@@ -88,6 +92,7 @@ typedef enum hostap_security_policy {
struct hostapd_ssid {
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
+ u32 short_ssid;
unsigned int ssid_set:1;
unsigned int utf8_ssid:1;
unsigned int wpa_passphrase_set:1;
@@ -101,7 +106,9 @@ struct hostapd_ssid {
char *wpa_psk_file;
struct sae_pt *pt;
+#ifdef CONFIG_WEP
struct hostapd_wep_keys wep;
+#endif /* CONFIG_WEP */
#define DYNAMIC_VLAN_DISABLED 0
#define DYNAMIC_VLAN_OPTIONAL 1
@@ -151,6 +158,7 @@ struct hostapd_wpa_psk {
struct hostapd_wpa_psk *next;
int group;
char keyid[KEYID_LEN];
+ int wps;
u8 psk[PMK_LEN];
u8 addr[ETH_ALEN];
u8 p2p_dev_addr[ETH_ALEN];
@@ -189,15 +197,6 @@ struct hostapd_radius_attr {
#define NUM_TX_QUEUES 4
-
-struct hostapd_tx_queue_params {
- int aifs;
- int cwmin;
- int cwmax;
- int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
-};
-
-
#define MAX_ROAMING_CONSORTIUM_LEN 15
struct hostapd_roaming_consortium {
@@ -253,6 +252,7 @@ struct sae_password_entry {
u8 peer_addr[ETH_ALEN];
int vlan_id;
struct sae_pt *pt;
+ struct sae_pk *pk;
};
struct dpp_controller_conf {
@@ -319,10 +319,12 @@ struct hostapd_bss_config {
size_t eap_req_id_text_len;
int eapol_key_index_workaround;
+#ifdef CONFIG_WEP
size_t default_wep_key_len;
int individual_wep_key_len;
int wep_rekeying_period;
int broadcast_key_idx_min, broadcast_key_idx_max;
+#endif /* CONFIG_WEP */
int eap_reauth_period;
int erp_send_reauth_start;
char *erp_domain;
@@ -344,9 +346,11 @@ struct hostapd_bss_config {
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
+ int extended_key_id;
int wpa_key_mgmt;
enum mfp_options ieee80211w;
int group_mgmt_cipher;
+ int beacon_prot;
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
unsigned int assoc_sa_query_max_timeout;
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
@@ -367,6 +371,7 @@ struct hostapd_bss_config {
int wpa_strict_rekey;
int wpa_gmk_rekey;
int wpa_ptk_rekey;
+ enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
u32 wpa_group_update_count;
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;
@@ -497,6 +502,7 @@ struct hostapd_bss_config {
char *model_url;
char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+ struct wpabuf *wps_application_ext;
int wps_nfc_pw_from_config;
int wps_nfc_dev_pw_id;
struct wpabuf *wps_nfc_dh_pubkey;
@@ -663,7 +669,26 @@ struct hostapd_bss_config {
u8 bss_load_test_set;
struct wpabuf *own_ie_override;
int sae_reflection_attack;
+ int sae_commit_status;
+ int sae_pk_omit;
+ int sae_pk_password_check_skip;
struct wpabuf *sae_commit_override;
+ struct wpabuf *rsne_override_eapol;
+ struct wpabuf *rsnxe_override_eapol;
+ struct wpabuf *rsne_override_ft;
+ struct wpabuf *rsnxe_override_ft;
+ struct wpabuf *gtk_rsc_override;
+ struct wpabuf *igtk_rsc_override;
+ int no_beacon_rsnxe;
+ int skip_prune_assoc;
+ int ft_rsnxe_used;
+ unsigned int oci_freq_override_eapol_m3;
+ unsigned int oci_freq_override_eapol_g1;
+ unsigned int oci_freq_override_saquery_req;
+ unsigned int oci_freq_override_saquery_resp;
+ unsigned int oci_freq_override_ft_assoc;
+ unsigned int oci_freq_override_fils_assoc;
+ unsigned int oci_freq_override_wnm_sleep;
#endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0)
@@ -719,6 +744,8 @@ struct hostapd_bss_config {
struct wpabuf *dpp_csign;
#ifdef CONFIG_DPP2
struct dpp_controller_conf *dpp_controller;
+ int dpp_configurator_connectivity;
+ int dpp_pfs;
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
@@ -728,12 +755,15 @@ struct hostapd_bss_config {
size_t owe_transition_ssid_len;
char owe_transition_ifname[IFNAMSIZ + 1];
int *owe_groups;
+ int owe_ptk_workaround;
#endif /* CONFIG_OWE */
int coloc_intf_reporting;
u8 send_probe_response;
+ u8 transition_disable;
+
#define BACKHAUL_BSS 1
#define FRONTHAUL_BSS 2
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
@@ -837,9 +867,9 @@ struct hostapd_bss_config {
* struct he_phy_capabilities_info - HE PHY capabilities
*/
struct he_phy_capabilities_info {
- Boolean he_su_beamformer;
- Boolean he_su_beamformee;
- Boolean he_mu_beamformer;
+ bool he_su_beamformer;
+ bool he_su_beamformee;
+ bool he_mu_beamformer;
};
/**
@@ -847,6 +877,8 @@ struct he_phy_capabilities_info {
*/
struct he_operation {
u8 he_bss_color;
+ u8 he_bss_color_disabled;
+ u8 he_bss_color_partial;
u8 he_default_pe_duration;
u8 he_twt_required;
u16 he_rts_threshold;
@@ -881,8 +913,11 @@ struct hostapd_config {
u8 edmg_channel;
u8 acs;
struct wpa_freq_range_list acs_ch_list;
+ struct wpa_freq_range_list acs_freq_list;
+ u8 acs_freq_list_present;
int acs_exclude_dfs;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
+ int acs_exclude_6ghz_non_psc;
enum {
LONG_PREAMBLE = 0,
SHORT_PREAMBLE = 1
@@ -1107,6 +1142,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config);
void hostapd_set_security_params(struct hostapd_bss_config *bss,
int full_config);
int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
+bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf);
+bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf);
int hostapd_setup_sae_pt(struct hostapd_bss_config *conf);
#endif /* HOSTAPD_CONFIG_H */
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index de60c79..f157659 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "common/hw_features_common.h"
#include "wps/wps.h"
#include "p2p/p2p.h"
@@ -350,7 +351,7 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg)
{
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
- return 0;
+ return -EOPNOTSUPP;
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
}
@@ -417,6 +418,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const struct ieee80211_vht_capabilities *vht_capab,
const struct ieee80211_he_capabilities *he_capab,
size_t he_capab_len,
+ const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
int set)
{
@@ -438,6 +440,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.vht_capabilities = vht_capab;
params.he_capab = he_capab;
params.he_capab_len = he_capab_len;
+ params.he_6ghz_capab = he_6ghz_capab;
params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
params.vht_opmode = vht_opmode;
params.flags = hostapd_sta_flags_to_drv(flags);
@@ -587,7 +590,7 @@ int hostapd_set_frag(struct hostapd_data *hapd, int frag)
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
int total_flags, int flags_or, int flags_and)
{
- if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
+ if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags)
return 0;
return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
flags_or, flags_and);
@@ -649,6 +652,12 @@ int hostapd_drv_none(struct hostapd_data *hapd)
}
+bool hostapd_drv_nl80211(struct hostapd_data *hapd)
+{
+ return hapd->driver && os_strcmp(hapd->driver->name, "nl80211") == 0;
+}
+
+
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params)
{
@@ -679,36 +688,41 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr,
- int key_idx, int set_tx,
+ int key_idx, int vlan_id, int set_tx,
const u8 *seq, size_t seq_len,
- const u8 *key, size_t key_len)
+ const u8 *key, size_t key_len, enum key_flag key_flag)
{
+ struct wpa_driver_set_key_params params;
+
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
return 0;
- return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
- key_idx, set_tx, seq, seq_len, key,
- key_len);
-}
+ os_memset(&params, 0, sizeof(params));
+ params.ifname = ifname;
+ params.alg = alg;
+ params.addr = addr;
+ params.key_idx = key_idx;
+ params.set_tx = set_tx;
+ params.seq = seq;
+ params.seq_len = seq_len;
+ params.key = key;
+ params.key_len = key_len;
+ params.vlan_id = vlan_id;
+ params.key_flag = key_flag;
-int hostapd_drv_send_mlme(struct hostapd_data *hapd,
- const void *msg, size_t len, int noack)
-{
- if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
- return 0;
- return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
- NULL, 0);
+ return hapd->driver->set_key(hapd->drv_priv, &params);
}
-int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
- const void *msg, size_t len, int noack,
- const u16 *csa_offs, size_t csa_offs_len)
+int hostapd_drv_send_mlme(struct hostapd_data *hapd,
+ const void *msg, size_t len, int noack,
+ const u16 *csa_offs, size_t csa_offs_len,
+ int no_encrypt)
{
- if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
+ if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
- csa_offs, csa_offs_len);
+ csa_offs, csa_offs_len, no_encrypt, 0);
}
@@ -855,10 +869,24 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
- if ((acs_ch_list_all ||
- freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
- chan->chan)) &&
- !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+ if (!acs_ch_list_all &&
+ (hapd->iface->conf->acs_freq_list.num &&
+ !freq_range_list_includes(
+ &hapd->iface->conf->acs_freq_list,
+ chan->freq)))
+ continue;
+ if (!acs_ch_list_all &&
+ (!hapd->iface->conf->acs_freq_list_present &&
+ hapd->iface->conf->acs_ch_list.num &&
+ !freq_range_list_includes(
+ &hapd->iface->conf->acs_ch_list,
+ chan->chan)))
+ continue;
+ if (is_6ghz_freq(chan->freq) &&
+ hapd->iface->conf->acs_exclude_6ghz_non_psc &&
+ !is_6ghz_psc_frequency(chan->freq))
+ continue;
+ if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
!(hapd->iface->conf->acs_exclude_dfs &&
(chan->flag & HOSTAPD_CHAN_RADAR)))
int_array_add_unique(freq_list, chan->freq);
@@ -884,10 +912,9 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
{
struct drv_acs_params params;
int ret, i, acs_ch_list_all = 0;
- u8 *channels = NULL;
- unsigned int num_channels = 0;
struct hostapd_hw_modes *mode;
int *freq_list = NULL;
+ enum hostapd_hw_mode selected_mode;
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
return 0;
@@ -899,42 +926,27 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
* If no chanlist config parameter is provided, include all enabled
* channels of the selected hw_mode.
*/
- if (!hapd->iface->conf->acs_ch_list.num)
- acs_ch_list_all = 1;
-
- mode = hapd->iface->current_mode;
- if (mode) {
- channels = os_malloc(mode->num_channels);
- if (channels == NULL)
- return -1;
-
- for (i = 0; i < mode->num_channels; i++) {
- struct hostapd_channel_data *chan = &mode->channels[i];
- if (!acs_ch_list_all &&
- !freq_range_list_includes(
- &hapd->iface->conf->acs_ch_list,
- chan->chan))
- continue;
- if (hapd->iface->conf->acs_exclude_dfs &&
- (chan->flag & HOSTAPD_CHAN_RADAR))
- continue;
- if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
- channels[num_channels++] = chan->chan;
- int_array_add_unique(&freq_list, chan->freq);
- }
- }
- } else {
- for (i = 0; i < hapd->iface->num_hw_features; i++) {
- mode = &hapd->iface->hw_features[i];
- hostapd_get_hw_mode_any_channels(hapd, mode,
- acs_ch_list_all,
- &freq_list);
- }
+ if (hapd->iface->conf->acs_freq_list_present)
+ acs_ch_list_all = !hapd->iface->conf->acs_freq_list.num;
+ else
+ acs_ch_list_all = !hapd->iface->conf->acs_ch_list.num;
+
+ if (hapd->iface->current_mode)
+ selected_mode = hapd->iface->current_mode->mode;
+ else
+ selected_mode = HOSTAPD_MODE_IEEE80211ANY;
+
+ for (i = 0; i < hapd->iface->num_hw_features; i++) {
+ mode = &hapd->iface->hw_features[i];
+ if (selected_mode != HOSTAPD_MODE_IEEE80211ANY &&
+ selected_mode != mode->mode)
+ continue;
+ hostapd_get_hw_mode_any_channels(hapd, mode, acs_ch_list_all,
+ &freq_list);
}
- params.ch_list = channels;
- params.ch_list_len = num_channels;
params.freq_list = freq_list;
+ params.edmg_enabled = hapd->iface->conf->enable_edmg;
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
@@ -958,8 +970,11 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
params.ch_width = 160;
}
+ if (hapd->iface->conf->op_class)
+ params.ch_width = op_class_to_bandwidth(
+ hapd->iface->conf->op_class);
ret = hapd->driver->do_acs(hapd->drv_priv, &params);
- os_free(channels);
+ os_free(freq_list);
return ret;
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 79b1302..5738c1c 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -43,6 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const struct ieee80211_vht_capabilities *vht_capab,
const struct ieee80211_he_capabilities *he_capab,
size_t he_capab_len,
+ const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
int set);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
@@ -80,6 +81,7 @@ hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags, u8 *dfs_domain);
int hostapd_driver_commit(struct hostapd_data *hapd);
int hostapd_drv_none(struct hostapd_data *hapd);
+bool hostapd_drv_nl80211(struct hostapd_data *hapd);
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params);
struct wpa_scan_results * hostapd_driver_get_scan_results(
@@ -89,14 +91,13 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
int hostapd_drv_set_key(const char *ifname,
struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr,
- int key_idx, int set_tx,
+ int key_idx, int vlan_id, int set_tx,
const u8 *seq, size_t seq_len,
- const u8 *key, size_t key_len);
+ const u8 *key, size_t key_len, enum key_flag key_flag);
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
- const void *msg, size_t len, int noack);
-int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
- const void *msg, size_t len, int noack,
- const u16 *csa_offs, size_t csa_offs_len);
+ const void *msg, size_t len, int noack,
+ const u16 *csa_offs, size_t csa_offs_len,
+ int no_encrypt);
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
@@ -382,4 +383,12 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
}
+static inline int
+hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band)
+{
+ if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
+ return -1;
+ return hapd->driver->set_band(hapd->drv_priv, band);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c
index 8bf6dde..20be7f8 100644
--- a/src/ap/ap_list.c
+++ b/src/ap/ap_list.c
@@ -228,7 +228,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
set_beacon++;
}
-#ifdef CONFIG_IEEE80211N
if (!iface->olbc_ht && !ap->ht_support &&
(ap->channel == 0 ||
ap->channel == iface->conf->channel ||
@@ -241,7 +240,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
MAC2STR(ap->addr), ap->channel);
set_beacon++;
}
-#endif /* CONFIG_IEEE80211N */
if (set_beacon)
ieee802_11_update_beacons(iface);
@@ -285,14 +283,12 @@ void ap_list_timer(struct hostapd_iface *iface)
iface->olbc = 0;
set_beacon++;
}
-#ifdef CONFIG_IEEE80211N
if (!olbc_ht && iface->olbc_ht) {
wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
iface->olbc_ht = 0;
hostapd_ht_operation_update(iface);
set_beacon++;
}
-#endif /* CONFIG_IEEE80211N */
}
if (set_beacon)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 331c09b..b3b33b7 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -36,27 +36,6 @@
#ifdef NEED_AP_MLME
-static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
- size_t len)
-{
- size_t i;
-
- for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
- if (hapd->conf->radio_measurements[i])
- break;
- }
-
- if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
- return eid;
-
- *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
- *eid++ = RRM_CAPABILITIES_IE_LEN;
- os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
-
- return eid + RRM_CAPABILITIES_IE_LEN;
-}
-
-
static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
{
if (len < 2 + 5)
@@ -287,17 +266,101 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
}
-static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
+static const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid)
+{
+ const u8 *ies;
+ size_t ies_len;
+
+ ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len);
+ if (!ies)
+ return NULL;
+
+ return get_ie(ies, ies_len, eid);
+}
+
+
+static const u8 * hostapd_vendor_wpa_ie(struct hostapd_data *hapd,
+ u32 vendor_type)
+{
+ const u8 *ies;
+ size_t ies_len;
+
+ ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len);
+ if (!ies)
+ return NULL;
+
+ return get_vendor_ie(ies, ies_len, vendor_type);
+}
+
+
+static u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len)
{
const u8 *ie;
- size_t ielen;
- ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
- if (ie == NULL || ielen > len)
- return eid;
+ ie = hostapd_wpa_ie(hapd, WLAN_EID_RSN);
+ if (!ie || 2U + ie[1] > len)
+ return pos;
+
+ os_memcpy(pos, ie, 2 + ie[1]);
+ return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_mde(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+ const u8 *ie;
+
+ ie = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN);
+ if (!ie || 2U + ie[1] > len)
+ return pos;
+
+ os_memcpy(pos, ie, 2 + ie[1]);
+ return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+ const u8 *ie;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->no_beacon_rsnxe) {
+ wpa_printf(MSG_INFO, "TESTING: Do not add RSNXE into Beacon");
+ return pos;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
+ if (!ie || 2U + ie[1] > len)
+ return pos;
+
+ os_memcpy(pos, ie, 2 + ie[1]);
+ return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_wpa_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+ const u8 *ie;
+
+ ie = hostapd_vendor_wpa_ie(hapd, WPA_IE_VENDOR_TYPE);
+ if (!ie || 2U + ie[1] > len)
+ return pos;
- os_memcpy(eid, ie, ielen);
- return eid + ielen;
+ os_memcpy(pos, ie, 2 + ie[1]);
+ return pos + 2 + ie[1];
+}
+
+
+static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
+{
+ const u8 *ie;
+
+ ie = hostapd_vendor_wpa_ie(hapd, OSEN_IE_VENDOR_TYPE);
+ if (!ie || 2U + ie[1] > len)
+ return pos;
+
+ os_memcpy(pos, ie, 2 + ie[1]);
+ return pos + 2 + ie[1];
}
@@ -400,11 +463,15 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
3 + sizeof(struct ieee80211_he_operation) +
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
3 + sizeof(struct ieee80211_spatial_reuse);
+ if (is_6ghz_op_class(hapd->iconf->op_class))
+ buflen += sizeof(struct ieee80211_he_6ghz_oper_info) +
+ 3 + sizeof(struct ieee80211_he_6ghz_band_cap);
}
#endif /* CONFIG_IEEE80211AX */
buflen += hostapd_mbo_ie_len(hapd);
buflen += hostapd_eid_owe_trans_len(hapd);
+ buflen += hostapd_eid_dpp_cc_len(hapd);
resp = os_zalloc(buflen);
if (resp == NULL)
@@ -455,14 +522,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
/* Extended supported rates */
pos = hostapd_eid_ext_supp_rates(hapd, pos);
- /* RSN, MDIE */
- if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
- (hapd->conf->osen && !hapd->conf->wpa)))
- pos = hostapd_eid_wpa(hapd, pos, epos - pos);
-
+ pos = hostapd_get_rsne(hapd, pos, epos - pos);
pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
-
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
+ pos = hostapd_get_mde(hapd, pos, epos - pos);
/* eCSA IE */
csa_pos = hostapd_eid_ecsa(hapd, pos);
@@ -471,15 +534,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = csa_pos;
pos = hostapd_eid_supported_op_classes(hapd, pos);
-
-#ifdef CONFIG_IEEE80211N
- /* Secondary Channel Offset element */
- /* TODO: The standard doesn't specify a position for this element. */
- pos = hostapd_eid_secondary_channel(hapd, pos);
-
pos = hostapd_eid_ht_capabilities(hapd, pos);
pos = hostapd_eid_ht_operation(hapd, pos);
-#endif /* CONFIG_IEEE80211N */
pos = hostapd_eid_ext_capab(hapd, pos);
@@ -504,18 +560,23 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
pos = hostapd_eid_vht_operation(hapd, pos);
pos = hostapd_eid_txpower_envelope(hapd, pos);
- pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
}
#endif /* CONFIG_IEEE80211AC */
+ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
+ hapd->iconf->ieee80211ax)
+ pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
+
pos = hostapd_eid_fils_indic(hapd, pos, 0);
+ pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax) {
pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP);
pos = hostapd_eid_he_operation(hapd, pos);
- pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
pos = hostapd_eid_spatial_reuse(hapd, pos);
+ pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
+ pos = hostapd_eid_he_6ghz_band_cap(hapd, pos);
}
#endif /* CONFIG_IEEE80211AX */
@@ -524,10 +585,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_vendor_vht(hapd, pos);
#endif /* CONFIG_IEEE80211AC */
- /* WPA */
- if (hapd->conf->wpa == WPA_PROTO_WPA ||
- (hapd->conf->osen && !hapd->conf->wpa))
- pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+ /* WPA / OSEN */
+ pos = hostapd_get_wpa_ie(hapd, pos, epos - pos);
+ pos = hostapd_get_osen_ie(hapd, pos, epos - pos);
/* Wi-Fi Alliance WMM */
pos = hostapd_eid_wmm(hapd, pos);
@@ -560,6 +620,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos);
+ pos = hostapd_eid_dpp_cc(hapd, pos, (u8 *) resp + buflen - pos);
if (hapd->conf->vendor_elements) {
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
@@ -581,7 +642,9 @@ enum ssid_match_result {
static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
const u8 *ssid, size_t ssid_len,
const u8 *ssid_list,
- size_t ssid_list_len)
+ size_t ssid_list_len,
+ const u8 *short_ssid_list,
+ size_t short_ssid_list_len)
{
const u8 *pos, *end;
int wildcard = 0;
@@ -592,20 +655,30 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
return EXACT_SSID_MATCH;
- if (ssid_list == NULL)
- return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
+ if (ssid_list) {
+ pos = ssid_list;
+ end = ssid_list + ssid_list_len;
+ while (end - pos >= 2) {
+ if (2 + pos[1] > end - pos)
+ break;
+ if (pos[1] == 0)
+ wildcard = 1;
+ if (pos[1] == hapd->conf->ssid.ssid_len &&
+ os_memcmp(pos + 2, hapd->conf->ssid.ssid,
+ pos[1]) == 0)
+ return EXACT_SSID_MATCH;
+ pos += 2 + pos[1];
+ }
+ }
- pos = ssid_list;
- end = ssid_list + ssid_list_len;
- while (end - pos >= 2) {
- if (2 + pos[1] > end - pos)
- break;
- if (pos[1] == 0)
- wildcard = 1;
- if (pos[1] == hapd->conf->ssid.ssid_len &&
- os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
- return EXACT_SSID_MATCH;
- pos += 2 + pos[1];
+ if (short_ssid_list) {
+ pos = short_ssid_list;
+ end = short_ssid_list + short_ssid_list_len;
+ while (end - pos >= 4) {
+ if (hapd->conf->ssid.short_ssid == WPA_GET_LE32(pos))
+ return EXACT_SSID_MATCH;
+ pos += 4;
+ }
}
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
@@ -743,11 +816,7 @@ void handle_probe_req(struct hostapd_data *hapd,
int ret;
u16 csa_offs[2];
size_t csa_offs_len;
- u32 session_timeout, acct_interim_interval;
- struct vlan_description vlan_id;
- struct hostapd_sta_wpa_psk_short *psk = NULL;
- char *identity = NULL;
- char *radius_cui = NULL;
+ struct radius_sta rad_info;
if (len < IEEE80211_HDRLEN)
return;
@@ -756,10 +825,8 @@ void handle_probe_req(struct hostapd_data *hapd,
sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
ie_len = len - IEEE80211_HDRLEN;
- ret = ieee802_11_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
- &session_timeout,
- &acct_interim_interval, &vlan_id,
- &psk, &identity, &radius_cui, 1);
+ ret = hostapd_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
+ &rad_info, 1);
if (ret == HOSTAPD_ACL_REJECT) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Ignore Probe Request frame from " MACSTR
@@ -838,7 +905,7 @@ void handle_probe_req(struct hostapd_data *hapd,
#endif /* CONFIG_P2P */
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
- elems.ssid_list_len == 0) {
+ elems.ssid_list_len == 0 && elems.short_ssid_list_len == 0) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
"broadcast SSID ignored", MAC2STR(mgmt->sa));
return;
@@ -870,7 +937,8 @@ void handle_probe_req(struct hostapd_data *hapd,
#endif /* CONFIG_TAXONOMY */
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
- elems.ssid_list, elems.ssid_list_len);
+ elems.ssid_list, elems.ssid_list_len,
+ elems.short_ssid_list, elems.short_ssid_list_len);
if (res == NO_SSID_MATCH) {
if (!(mgmt->da[0] & 0x01)) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
@@ -883,6 +951,12 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
+ if (hapd->conf->ignore_broadcast_ssid && res == WILDCARD_SSID_MATCH) {
+ wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
+ "broadcast SSID ignored", MAC2STR(mgmt->sa));
+ return;
+ }
+
#ifdef CONFIG_INTERWORKING
if (hapd->conf->interworking &&
elems.interworking && elems.interworking_len >= 1) {
@@ -987,9 +1061,9 @@ void handle_probe_req(struct hostapd_data *hapd,
hapd->cs_c_off_ecsa_proberesp;
}
- ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack,
- csa_offs_len ? csa_offs : NULL,
- csa_offs_len);
+ ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
+ csa_offs_len ? csa_offs : NULL,
+ csa_offs_len, 0);
if (ret < 0)
wpa_printf(MSG_INFO, "handle_probe_req: send failed");
@@ -1060,7 +1134,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
size_t resp_len = 0;
#ifdef NEED_AP_MLME
u16 capab_info;
- u8 *pos, *tailpos, *csa_pos;
+ u8 *pos, *tailpos, *tailend, *csa_pos;
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
@@ -1094,11 +1168,15 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
3 + sizeof(struct ieee80211_he_operation) +
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
3 + sizeof(struct ieee80211_spatial_reuse);
+ if (is_6ghz_op_class(hapd->iconf->op_class))
+ tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) +
+ 3 + sizeof(struct ieee80211_he_6ghz_band_cap);
}
#endif /* CONFIG_IEEE80211AX */
tail_len += hostapd_mbo_ie_len(hapd);
tail_len += hostapd_eid_owe_trans_len(hapd);
+ tail_len += hostapd_eid_dpp_cc_len(hapd);
tailpos = tail = os_malloc(tail_len);
if (head == NULL || tail == NULL) {
@@ -1107,6 +1185,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
os_free(tail);
return -1;
}
+ tailend = tail + tail_len;
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_BEACON);
@@ -1147,8 +1226,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
head_len = pos - (u8 *) head;
- tailpos = hostapd_eid_country(hapd, tailpos,
- tail + BEACON_TAIL_BUF_SIZE - tailpos);
+ tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos);
/* Power Constraint element */
tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
@@ -1165,19 +1243,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
/* Extended supported rates */
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
- /* RSN, MDIE */
- if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
- (hapd->conf->osen && !hapd->conf->wpa)))
- tailpos = hostapd_eid_wpa(hapd, tailpos,
- tail + BEACON_TAIL_BUF_SIZE -
- tailpos);
-
+ tailpos = hostapd_get_rsne(hapd, tailpos, tailend - tailpos);
+ tailpos = hostapd_eid_bss_load(hapd, tailpos, tailend - tailpos);
tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
- tail + BEACON_TAIL_BUF_SIZE -
- tailpos);
-
- tailpos = hostapd_eid_bss_load(hapd, tailpos,
- tail + BEACON_TAIL_BUF_SIZE - tailpos);
+ tailend - tailpos);
+ tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos);
/* eCSA IE */
csa_pos = hostapd_eid_ecsa(hapd, tailpos);
@@ -1186,15 +1256,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = csa_pos;
tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
-
-#ifdef CONFIG_IEEE80211N
- /* Secondary Channel Offset element */
- /* TODO: The standard doesn't specify a position for this element. */
- tailpos = hostapd_eid_secondary_channel(hapd, tailpos);
-
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
-#endif /* CONFIG_IEEE80211N */
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
@@ -1221,19 +1284,24 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
- tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
}
#endif /* CONFIG_IEEE80211AC */
+ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
+ hapd->iconf->ieee80211ax)
+ tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
+
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
+ tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax) {
tailpos = hostapd_eid_he_capab(hapd, tailpos,
IEEE80211_MODE_AP);
tailpos = hostapd_eid_he_operation(hapd, tailpos);
- tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
tailpos = hostapd_eid_spatial_reuse(hapd, tailpos);
+ tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
+ tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos);
}
#endif /* CONFIG_IEEE80211AX */
@@ -1242,12 +1310,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
#endif /* CONFIG_IEEE80211AC */
- /* WPA */
- if (hapd->conf->wpa == WPA_PROTO_WPA ||
- (hapd->conf->osen && !hapd->conf->wpa))
- tailpos = hostapd_eid_wpa(hapd, tailpos,
- tail + BEACON_TAIL_BUF_SIZE -
- tailpos);
+ /* WPA / OSEN */
+ tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos);
+ tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos);
/* Wi-Fi Alliance WMM */
tailpos = hostapd_eid_wmm(hapd, tailpos);
@@ -1280,6 +1345,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
tailpos = hostapd_eid_owe_trans(hapd, tailpos,
tail + tail_len - tailpos);
+ tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
if (hapd->conf->vendor_elements) {
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
@@ -1318,10 +1384,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
params->auth_algs = hapd->conf->auth_algs;
params->wpa_version = hapd->conf->wpa;
- params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
+ params->privacy = hapd->conf->wpa;
+#ifdef CONFIG_WEP
+ params->privacy |= hapd->conf->ssid.wep.keys_set ||
(hapd->conf->ieee802_1x &&
(hapd->conf->default_wep_key_len ||
hapd->conf->individual_wep_key_len));
+#endif /* CONFIG_WEP */
switch (hapd->conf->ignore_broadcast_ssid) {
case 0:
params->hide_ssid = NO_SSID_HIDING;
@@ -1334,7 +1403,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
break;
}
params->isolate = hapd->conf->isolate;
- params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
#ifdef NEED_AP_MLME
params->cts_protect = !!(ieee802_11_erp_info(hapd) &
ERP_INFO_USE_PROTECTION);
@@ -1430,6 +1498,13 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
hapd->iface->conf->spr.srg_obss_pd_min_offset;
params.he_spr_srg_obss_pd_max_offset =
hapd->iface->conf->spr.srg_obss_pd_max_offset;
+ params.he_bss_color_disabled =
+ hapd->iface->conf->he_op.he_bss_color_disabled;
+ params.he_bss_color_partial =
+ hapd->iface->conf->he_op.he_bss_color_partial;
+ params.he_bss_color = hapd->iface->conf->he_op.he_bss_color;
+ params.twt_responder = hostapd_get_he_twt_responder(hapd,
+ IEEE80211_MODE_AP);
#endif /* CONFIG_IEEE80211AX */
hapd->reenable_beacon = 0;
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 676a4c7..ef53a82 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -273,6 +273,36 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
if (!os_snprintf_error(buflen - len, res))
len += res;
}
+
+ if (sta->sae && sta->sae->tmp) {
+ const u8 *pos;
+ unsigned int j, count;
+ struct wpabuf *groups = sta->sae->tmp->peer_rejected_groups;
+
+ res = os_snprintf(buf + len, buflen - len,
+ "sae_rejected_groups=");
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+
+ if (groups) {
+ pos = wpabuf_head(groups);
+ count = wpabuf_len(groups) / 2;
+ } else {
+ pos = NULL;
+ count = 0;
+ }
+ for (j = 0; pos && j < count; j++) {
+ res = os_snprintf(buf + len, buflen - len, "%s%d",
+ j == 0 ? "" : " ", WPA_GET_LE16(pos));
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+ pos += 2;
+ }
+
+ res = os_snprintf(buf + len, buflen - len, "\n");
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+ }
#endif /* CONFIG_SAE */
if (sta->vlan_id > 0) {
@@ -315,7 +345,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
}
#endif /* CONFIG_IEEE80211AC */
-#ifdef CONFIG_IEEE80211N
if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
res = os_snprintf(buf + len, buflen - len,
"ht_caps_info=0x%04x\n",
@@ -324,7 +353,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
if (!os_snprintf_error(buflen - len, res))
len += res;
}
-#endif /* CONFIG_IEEE80211N */
if (sta->ext_capability &&
buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
@@ -432,9 +460,6 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
int ret;
u8 *pos;
- if (!hapd->drv_priv || !hapd->driver->send_frame)
- return -1;
-
mgmt = os_zalloc(sizeof(*mgmt) + 100);
if (mgmt == NULL)
return -1;
@@ -468,8 +493,8 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
pos += 2;
*pos++ = minor_reason_code;
- ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
- pos - (u8 *) mgmt, 1);
+ ret = hostapd_drv_send_mlme(hapd, mgmt, pos - (u8 *) mgmt, 0, NULL, 0,
+ 0);
os_free(mgmt);
return ret < 0 ? -1 : 0;
@@ -499,8 +524,7 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
- if (!hapd->drv_priv || !hapd->driver->send_frame)
- return -1;
+
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
@@ -510,10 +534,10 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.deauth.reason_code = host_to_le16(reason);
- if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
- IEEE80211_HDRLEN +
- sizeof(mgmt.u.deauth),
- encrypt) < 0)
+ if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
+ IEEE80211_HDRLEN +
+ sizeof(mgmt.u.deauth),
+ 0, NULL, 0, !encrypt) < 0)
return -1;
return 0;
}
@@ -562,8 +586,7 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
- if (!hapd->drv_priv || !hapd->driver->send_frame)
- return -1;
+
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
@@ -573,10 +596,10 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.disassoc.reason_code = host_to_le16(reason);
- if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
- IEEE80211_HDRLEN +
- sizeof(mgmt.u.deauth),
- encrypt) < 0)
+ if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
+ IEEE80211_HDRLEN +
+ sizeof(mgmt.u.deauth),
+ 0, NULL, 0, !encrypt) < 0)
return -1;
return 0;
}
@@ -731,6 +754,22 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
+
+#ifdef CONFIG_IEEE80211AX
+ if (iface->conf->ieee80211ax) {
+ ret = os_snprintf(buf + len, buflen - len,
+ "he_oper_chwidth=%d\n"
+ "he_oper_centr_freq_seg0_idx=%d\n"
+ "he_oper_centr_freq_seg1_idx=%d\n",
+ iface->conf->he_oper_chwidth,
+ iface->conf->he_oper_centr_freq_seg0_idx,
+ iface->conf->he_oper_centr_freq_seg1_idx);
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
+ }
+#endif /* CONFIG_IEEE80211AX */
+
if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
ret = os_snprintf(buf + len, buflen - len,
"vht_oper_chwidth=%d\n"
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index c4c00fc..f04a00a 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -144,30 +144,44 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
int i;
u32 bw = num_chan_to_bw(num_chans);
- if (first_chan_idx + num_chans > mode->num_channels)
+ if (first_chan_idx + num_chans > mode->num_channels) {
+ wpa_printf(MSG_DEBUG,
+ "DFS: some channels in range not defined");
return 0;
+ }
first_chan = &mode->channels[first_chan_idx];
/* hostapd DFS implementation assumes the first channel as primary.
* If it's not allowed to use the first channel as primary, decline the
* whole channel range. */
- if (!chan_pri_allowed(first_chan))
+ if (!chan_pri_allowed(first_chan)) {
+ wpa_printf(MSG_DEBUG, "DFS: primary chanenl not allowed");
return 0;
+ }
for (i = 0; i < num_chans; i++) {
chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
first_chan_idx);
- if (!chan)
+ if (!chan) {
+ wpa_printf(MSG_DEBUG, "DFS: no channel data for %d",
+ first_chan->freq + i * 20);
return 0;
+ }
/* HT 40 MHz secondary channel availability checked only for
* primary channel */
- if (!chan_bw_allowed(chan, bw, 1, !i))
+ if (!chan_bw_allowed(chan, bw, 1, !i)) {
+ wpa_printf(MSG_DEBUG, "DFS: bw now allowed for %d",
+ first_chan->freq + i * 20);
return 0;
+ }
- if (!dfs_channel_available(chan, skip_radar))
+ if (!dfs_channel_available(chan, skip_radar)) {
+ wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
+ first_chan->freq + i * 20);
return 0;
+ }
}
return 1;
@@ -210,22 +224,36 @@ static int dfs_find_channel(struct hostapd_iface *iface,
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel &&
(!dfs_is_chan_allowed(chan, n_chans) ||
- !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)))
+ !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) {
+ wpa_printf(MSG_DEBUG,
+ "DFS: channel %d (%d) is incompatible",
+ chan->freq, chan->chan);
continue;
+ }
/* Skip incompatible chandefs */
- if (!dfs_chan_range_available(mode, i, n_chans, skip_radar))
+ if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) {
+ wpa_printf(MSG_DEBUG,
+ "DFS: range not available for %d (%d)",
+ chan->freq, chan->chan);
continue;
+ }
- if (!is_in_chanlist(iface, chan))
+ if (!is_in_chanlist(iface, chan)) {
+ wpa_printf(MSG_DEBUG,
+ "DFS: channel %d (%d) not in chanlist",
+ chan->freq, chan->chan);
continue;
+ }
if (ret_chan && idx == channel_idx) {
- wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
+ wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
+ chan->freq, chan->chan);
*ret_chan = chan;
return idx;
}
- wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan);
+ wpa_printf(MSG_DEBUG, "Adding channel %d (%d)",
+ chan->freq, chan->chan);
channel_idx++;
}
return channel_idx;
@@ -235,6 +263,7 @@ static int dfs_find_channel(struct hostapd_iface *iface,
static void dfs_adjust_center_freq(struct hostapd_iface *iface,
struct hostapd_channel_data *chan,
int secondary_channel,
+ int sec_chan_idx_80p80,
u8 *oper_centr_freq_seg0_idx,
u8 *oper_centr_freq_seg1_idx)
{
@@ -261,8 +290,14 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface,
case CHANWIDTH_160MHZ:
*oper_centr_freq_seg0_idx = chan->chan + 14;
break;
+ case CHANWIDTH_80P80MHZ:
+ *oper_centr_freq_seg0_idx = chan->chan + 6;
+ *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6;
+ break;
+
default:
- wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now");
+ wpa_printf(MSG_INFO,
+ "DFS: Unsupported channel width configuration");
*oper_centr_freq_seg0_idx = 0;
break;
}
@@ -441,8 +476,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
{
struct hostapd_hw_modes *mode;
struct hostapd_channel_data *chan = NULL;
+ struct hostapd_channel_data *chan2 = NULL;
int num_available_chandefs;
- int chan_idx;
+ int chan_idx, chan_idx2;
+ int sec_chan_idx_80p80 = -1;
+ int i;
u32 _rand;
wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
@@ -459,6 +497,8 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
/* Get the count first */
num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
+ wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d",
+ num_available_chandefs);
if (num_available_chandefs == 0)
return NULL;
@@ -466,6 +506,12 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
return NULL;
chan_idx = _rand % num_available_chandefs;
dfs_find_channel(iface, &chan, chan_idx, skip_radar);
+ if (!chan) {
+ wpa_printf(MSG_DEBUG, "DFS: no random channel found");
+ return NULL;
+ }
+ wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)",
+ chan->freq, chan->chan);
/* dfs_find_channel() calculations assume HT40+ */
if (iface->conf->secondary_channel)
@@ -473,8 +519,45 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
else
*secondary_channel = 0;
+ /* Get secondary channel for HT80P80 */
+ if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80P80MHZ) {
+ if (num_available_chandefs <= 1) {
+ wpa_printf(MSG_ERROR,
+ "only 1 valid chan, can't support 80+80");
+ return NULL;
+ }
+
+ /*
+ * Loop all channels except channel1 to find a valid channel2
+ * that is not adjacent to channel1.
+ */
+ for (i = 0; i < num_available_chandefs - 1; i++) {
+ /* start from chan_idx + 1, end when chan_idx - 1 */
+ chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs;
+ dfs_find_channel(iface, &chan2, chan_idx2, skip_radar);
+ if (chan2 && abs(chan2->chan - chan->chan) > 12) {
+ /* two channels are not adjacent */
+ sec_chan_idx_80p80 = chan2->chan;
+ wpa_printf(MSG_DEBUG,
+ "DFS: got second chan: %d (%d)",
+ chan2->freq, chan2->chan);
+ break;
+ }
+ }
+
+ /* Check if we got a valid secondary channel which is not
+ * adjacent to the first channel.
+ */
+ if (sec_chan_idx_80p80 == -1) {
+ wpa_printf(MSG_INFO,
+ "DFS: failed to get chan2 for 80+80");
+ return NULL;
+ }
+ }
+
dfs_adjust_center_freq(iface, chan,
*secondary_channel,
+ sec_chan_idx_80p80,
oper_centr_freq_seg0_idx,
oper_centr_freq_seg1_idx);
@@ -515,6 +598,7 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
int n_chans = 1, i;
struct hostapd_hw_modes *mode;
int frequency = freq;
+ int frequency2 = 0;
int ret = 0;
mode = iface->current_mode;
@@ -542,6 +626,11 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
n_chans = 4;
frequency = cf1 - 30;
break;
+ case CHAN_WIDTH_80P80:
+ n_chans = 4;
+ frequency = cf1 - 30;
+ frequency2 = cf2 - 30;
+ break;
case CHAN_WIDTH_160:
n_chans = 8;
frequency = cf1 - 70;
@@ -557,6 +646,11 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
for (i = 0; i < n_chans; i++) {
ret += set_dfs_state_freq(iface, frequency, state);
frequency = frequency + 20;
+
+ if (chan_width == CHAN_WIDTH_80P80) {
+ ret += set_dfs_state_freq(iface, frequency2, state);
+ frequency2 = frequency2 + 20;
+ }
}
return ret;
@@ -662,6 +756,9 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
int skip_radar = 0;
+ if (is_6ghz_freq(iface->freq))
+ return 1;
+
if (!iface->current_mode) {
/*
* This can happen with drivers that do not provide mode
@@ -759,7 +856,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
}
-static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface)
+int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
{
int n_chans, n_chans1, start_chan_idx, start_chan_idx1;
@@ -807,7 +904,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
* another radio.
*/
if (iface->state != HAPD_IFACE_ENABLED &&
- hostapd_config_dfs_chan_available(iface)) {
+ hostapd_is_dfs_chan_available(iface)) {
hostapd_setup_interface_complete(iface, 0);
iface->cac_started = 0;
}
@@ -837,6 +934,44 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
}
+static struct hostapd_channel_data *
+dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+ u8 *oper_centr_freq_seg0_idx,
+ u8 *oper_centr_freq_seg1_idx, int *skip_radar)
+{
+ struct hostapd_channel_data *channel;
+
+ for (;;) {
+ channel = dfs_get_valid_channel(iface, secondary_channel,
+ oper_centr_freq_seg0_idx,
+ oper_centr_freq_seg1_idx,
+ *skip_radar);
+ if (channel) {
+ wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d",
+ channel->chan);
+ return channel;
+ }
+
+ if (*skip_radar) {
+ *skip_radar = 0;
+ } else {
+ int oper_chwidth;
+
+ oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+ if (oper_chwidth == CHANWIDTH_USE_HT)
+ break;
+ *skip_radar = 1;
+ hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1);
+ }
+ }
+
+ wpa_printf(MSG_INFO,
+ "%s: no DFS channels left, waiting for NOP to finish",
+ __func__);
+ return NULL;
+}
+
+
static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
{
struct hostapd_channel_data *channel;
@@ -854,8 +989,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
skip_radar);
if (!channel) {
- wpa_printf(MSG_ERROR, "No valid channel available");
- return err;
+ channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+ &oper_centr_freq_seg0_idx,
+ &oper_centr_freq_seg1_idx,
+ &skip_radar);
+ if (!channel) {
+ wpa_printf(MSG_ERROR, "No valid channel available");
+ return err;
+ }
}
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
@@ -884,11 +1025,13 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
int secondary_channel;
u8 oper_centr_freq_seg0_idx;
u8 oper_centr_freq_seg1_idx;
+ u8 new_vht_oper_chwidth;
int skip_radar = 1;
struct csa_settings csa_settings;
unsigned int i;
int err = 1;
struct hostapd_hw_modes *cmode = iface->current_mode;
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
__func__, iface->cac_started ? "yes" : "no",
@@ -922,28 +1065,25 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
* requires to perform a CAC first.
*/
skip_radar = 0;
- channel = dfs_get_valid_channel(iface, &secondary_channel,
- &oper_centr_freq_seg0_idx,
- &oper_centr_freq_seg1_idx,
- skip_radar);
- if (!channel) {
- wpa_printf(MSG_INFO,
- "%s: no DFS channels left, waiting for NOP to finish",
- __func__);
+ channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+ &oper_centr_freq_seg0_idx,
+ &oper_centr_freq_seg1_idx,
+ &skip_radar);
+ if (!channel)
return err;
+ if (!skip_radar) {
+ iface->freq = channel->freq;
+ iface->conf->channel = channel->chan;
+ iface->conf->secondary_channel = secondary_channel;
+ hostapd_set_oper_centr_freq_seg0_idx(
+ iface->conf, oper_centr_freq_seg0_idx);
+ hostapd_set_oper_centr_freq_seg1_idx(
+ iface->conf, oper_centr_freq_seg1_idx);
+
+ hostapd_disable_iface(iface);
+ hostapd_enable_iface(iface);
+ return 0;
}
-
- iface->freq = channel->freq;
- iface->conf->channel = channel->chan;
- iface->conf->secondary_channel = secondary_channel;
- hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
- oper_centr_freq_seg0_idx);
- hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
- oper_centr_freq_seg1_idx);
-
- hostapd_disable_iface(iface);
- hostapd_enable_iface(iface);
- return 0;
}
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
@@ -952,6 +1092,9 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
"freq=%d chan=%d sec_chan=%d", channel->freq,
channel->chan, secondary_channel);
+ new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+ hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
+
/* Setup CSA request */
os_memset(&csa_settings, 0, sizeof(csa_settings));
csa_settings.cs_count = 5;
@@ -966,7 +1109,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
iface->conf->ieee80211ac,
iface->conf->ieee80211ax,
secondary_channel,
- hostapd_get_oper_chwidth(iface->conf),
+ new_vht_oper_chwidth,
oper_centr_freq_seg0_idx,
oper_centr_freq_seg1_idx,
cmode->vht_capab,
@@ -990,6 +1133,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
iface->freq = channel->freq;
iface->conf->channel = channel->chan;
iface->conf->secondary_channel = secondary_channel;
+ hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
oper_centr_freq_seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
@@ -1026,8 +1170,10 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
return 0;
/* mark radar frequency as invalid */
- set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
- cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
+ res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+ cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
+ if (!res)
+ return 0;
/* Skip if reported radar event not overlapped our channels */
res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
@@ -1147,3 +1293,56 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
__func__, iface->freq);
return 2;
}
+
+
+int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+ int center_freq)
+{
+ struct hostapd_channel_data *chan;
+ struct hostapd_hw_modes *mode = iface->current_mode;
+ int half_width;
+ int res = 0;
+ int i;
+
+ if (!iface->conf->ieee80211h || !mode ||
+ mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ switch (width) {
+ case CHAN_WIDTH_20_NOHT:
+ case CHAN_WIDTH_20:
+ half_width = 10;
+ break;
+ case CHAN_WIDTH_40:
+ half_width = 20;
+ break;
+ case CHAN_WIDTH_80:
+ case CHAN_WIDTH_80P80:
+ half_width = 40;
+ break;
+ case CHAN_WIDTH_160:
+ half_width = 80;
+ break;
+ default:
+ wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported",
+ width);
+ return 0;
+ }
+
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
+
+ if (!(chan->flag & HOSTAPD_CHAN_RADAR))
+ continue;
+
+ if (center_freq - chan->freq < half_width &&
+ chan->freq - center_freq < half_width)
+ res++;
+ }
+
+ wpa_printf(MSG_DEBUG, "DFS: (%d, %d): in range: %s",
+ center_freq - half_width, center_freq + half_width,
+ res ? "yes" : "no");
+
+ return res;
+}
diff --git a/src/ap/dfs.h b/src/ap/dfs.h
index f0fa6f6..606c1b3 100644
--- a/src/ap/dfs.h
+++ b/src/ap/dfs.h
@@ -25,9 +25,12 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
int ht_enabled,
int chan_offset, int chan_width, int cf1, int cf2);
int hostapd_is_dfs_required(struct hostapd_iface *iface);
+int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2);
int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
+int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+ int center_freq);
#endif /* DFS_H */
diff --git a/src/ap/dhcp_snoop.c b/src/ap/dhcp_snoop.c
index ed37fc8..edc77da 100644
--- a/src/ap/dhcp_snoop.c
+++ b/src/ap/dhcp_snoop.c
@@ -39,22 +39,22 @@ static void handle_dhcp(void *ctx, const u8 *src_addr, const u8 *buf,
const u8 *end, *pos;
int res, msgtype = 0, prefixlen = 32;
u32 subnet_mask = 0;
- u16 tot_len;
+ u16 ip_len;
exten_len = len - ETH_HLEN - (sizeof(*b) - sizeof(b->exten));
if (exten_len < 4)
return;
b = (const struct bootp_pkt *) &buf[ETH_HLEN];
- tot_len = ntohs(b->iph.tot_len);
- if (tot_len > (unsigned int) (len - ETH_HLEN))
+ ip_len = ntohs(b->iph.ip_len);
+ if (ip_len > (unsigned int) (len - ETH_HLEN))
return;
if (WPA_GET_BE32(b->exten) != DHCP_MAGIC)
return;
/* Parse DHCP options */
- end = (const u8 *) b + tot_len;
+ end = (const u8 *) b + ip_len;
pos = &b->exten[4];
while (pos < end && *pos != DHCP_OPT_END) {
const u8 *opt = pos++;
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 085d423..6772a87 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -1,6 +1,7 @@
/*
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -25,6 +26,13 @@ static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
+#ifdef CONFIG_DPP2
+static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
+ void *timeout_ctx);
+static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
+ struct dpp_authentication *auth,
+ struct dpp_config_obj *conf);
+#endif /* CONFIG_DPP2 */
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -58,10 +66,97 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
wpabuf_len(hapd->dpp_auth->resp_msg));
}
+#ifdef CONFIG_DPP2
+ dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi);
+#endif /* CONFIG_DPP2 */
+
+ return bi->id;
+}
+
+
+/**
+ * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
+ * @hapd: Pointer to hostapd_data
+ * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
+ * Returns: Identifier of the stored info or -1 on failure
+ */
+int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
+{
+ struct dpp_bootstrap_info *bi;
+
+ bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
+ if (!bi)
+ return -1;
+
return bi->id;
}
+int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
+{
+ const char *pos;
+ struct dpp_bootstrap_info *peer_bi, *own_bi;
+
+ pos = os_strstr(cmd, " own=");
+ if (!pos)
+ return -1;
+ pos += 5;
+ own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
+ if (!own_bi)
+ return -1;
+
+ pos = os_strstr(cmd, " uri=");
+ if (!pos)
+ return -1;
+ pos += 5;
+ peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
+ if (!peer_bi) {
+ wpa_printf(MSG_INFO,
+ "DPP: Failed to parse URI from NFC Handover Request");
+ return -1;
+ }
+
+ if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
+ return -1;
+
+ return peer_bi->id;
+}
+
+
+int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
+{
+ const char *pos;
+ struct dpp_bootstrap_info *peer_bi, *own_bi;
+
+ pos = os_strstr(cmd, " own=");
+ if (!pos)
+ return -1;
+ pos += 5;
+ own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
+ if (!own_bi)
+ return -1;
+
+ pos = os_strstr(cmd, " uri=");
+ if (!pos)
+ return -1;
+ pos += 5;
+ peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
+ if (!peer_bi) {
+ wpa_printf(MSG_INFO,
+ "DPP: Failed to parse URI from NFC Handover Select");
+ return -1;
+ }
+
+ if (peer_bi->curve != own_bi->curve) {
+ wpa_printf(MSG_INFO,
+ "DPP: Peer (NFC Handover Selector) used different curve");
+ return -1;
+ }
+
+ return peer_bi->id;
+}
+
+
static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
void *timeout_ctx)
{
@@ -153,6 +248,10 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
NULL);
+#ifdef CONFIG_DPP2
+ eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
+ hapd, NULL);
+#endif /* CONFIG_DPP2 */
hostapd_drv_send_action_cancel_wait(hapd);
dpp_auth_deinit(hapd->dpp_auth);
hapd->dpp_auth = NULL;
@@ -394,12 +493,35 @@ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
}
+#ifdef CONFIG_DPP2
+static int hostapd_dpp_process_conf_obj(void *ctx,
+ struct dpp_authentication *auth)
+{
+ struct hostapd_data *hapd = ctx;
+ unsigned int i;
+
+ for (i = 0; i < auth->num_conf_obj; i++)
+ hostapd_dpp_handle_config_obj(hapd, auth,
+ &auth->conf_obj[i]);
+
+ return 0;
+}
+#endif /* CONFIG_DPP2 */
+
+
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
{
const char *pos;
struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
+ struct dpp_authentication *auth;
u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
unsigned int neg_freq = 0;
+ int tcp = 0;
+#ifdef CONFIG_DPP2
+ int tcp_port = DPP_TCP_PORT;
+ struct hostapd_ip_addr ipaddr;
+ char *addr;
+#endif /* CONFIG_DPP2 */
pos = os_strstr(cmd, " peer=");
if (!pos)
@@ -412,6 +534,25 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
return -1;
}
+#ifdef CONFIG_DPP2
+ pos = os_strstr(cmd, " tcp_port=");
+ if (pos) {
+ pos += 10;
+ tcp_port = atoi(pos);
+ }
+
+ addr = get_param(cmd, " tcp_addr=");
+ if (addr) {
+ int res;
+
+ res = hostapd_parse_ip_addr(addr, &ipaddr);
+ os_free(addr);
+ if (res)
+ return -1;
+ tcp = 1;
+ }
+#endif /* CONFIG_DPP2 */
+
pos = os_strstr(cmd, " own=");
if (pos) {
pos += 5;
@@ -449,36 +590,46 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
if (pos)
neg_freq = atoi(pos + 10);
- if (hapd->dpp_auth) {
+ if (!tcp && hapd->dpp_auth) {
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
NULL);
+#ifdef CONFIG_DPP2
+ eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
+ hapd, NULL);
+#endif /* CONFIG_DPP2 */
hostapd_drv_send_action_cancel_wait(hapd);
dpp_auth_deinit(hapd->dpp_auth);
}
- hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
- allowed_roles, neg_freq,
- hapd->iface->hw_features,
- hapd->iface->num_hw_features);
- if (!hapd->dpp_auth)
+ auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
+ peer_bi, own_bi, allowed_roles, neg_freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
+ if (!auth)
goto fail;
- hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
- if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
- hapd->dpp_auth, cmd) < 0) {
- dpp_auth_deinit(hapd->dpp_auth);
- hapd->dpp_auth = NULL;
+ hostapd_dpp_set_testing_options(hapd, auth);
+ if (dpp_set_configurator(auth, cmd) < 0) {
+ dpp_auth_deinit(auth);
goto fail;
}
- hapd->dpp_auth->neg_freq = neg_freq;
+ auth->neg_freq = neg_freq;
if (!is_zero_ether_addr(peer_bi->mac_addr))
- os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
- ETH_ALEN);
+ os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
+
+#ifdef CONFIG_DPP2
+ if (tcp)
+ return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
+ &ipaddr, tcp_port, hapd->conf->dpp_name,
+ DPP_NETROLE_AP, hapd->msg_ctx, hapd,
+ hostapd_dpp_process_conf_obj);
+#endif /* CONFIG_DPP2 */
+ hapd->dpp_auth = auth;
return hostapd_dpp_auth_init_next(hapd);
fail:
return -1;
@@ -534,6 +685,10 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
MAC2STR(src));
+#ifdef CONFIG_DPP2
+ hostapd_dpp_chirp_stop(hapd);
+#endif /* CONFIG_DPP2 */
+
r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
&r_bootstrap_len);
if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
@@ -579,7 +734,8 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
}
hapd->dpp_auth_ok_on_ack = 0;
- hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
+ hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
+ hapd->msg_ctx, hapd->dpp_allowed_roles,
hapd->dpp_qr_mutual,
peer_bi, own_bi, freq, hdr, buf, len);
if (!hapd->dpp_auth) {
@@ -587,8 +743,7 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
return;
}
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
- if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
- hapd->dpp_auth,
+ if (dpp_set_configurator(hapd->dpp_auth,
hapd->dpp_configurator_params) < 0) {
dpp_auth_deinit(hapd->dpp_auth);
hapd->dpp_auth = NULL;
@@ -624,7 +779,8 @@ static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
* message. */
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
conf->connector);
- } else if (conf->passphrase[0]) {
+ }
+ if (conf->passphrase[0]) {
char hex[64 * 2 + 1];
wpa_snprintf_hex(hex, sizeof(hex),
@@ -678,6 +834,33 @@ static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
}
+static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
+ struct dpp_asymmetric_key *key)
+{
+#ifdef CONFIG_DPP2
+ int res;
+
+ if (!key)
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
+
+ while (key) {
+ res = dpp_configurator_from_backup(
+ hapd->iface->interfaces->dpp, key);
+ if (res < 0)
+ return -1;
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
+ res);
+ key = key->next;
+ }
+#endif /* CONFIG_DPP2 */
+
+ return 0;
+}
+
+
static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
enum gas_query_ap_result result,
const struct wpabuf *adv_proto,
@@ -722,6 +905,9 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
}
hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
+ if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
+ goto fail;
+
status = DPP_STATUS_OK;
#ifdef CONFIG_TESTING_OPTIONS
if (dpp_test == DPP_TEST_REJECT_CONFIG) {
@@ -768,7 +954,8 @@ static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
struct wpabuf *buf;
int res;
- buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name, 1,
+ buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
+ DPP_NETROLE_AP,
hapd->conf->dpp_mud_url, NULL);
if (!buf) {
wpa_printf(MSG_DEBUG,
@@ -1017,6 +1204,227 @@ static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
}
+static void
+hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ const u8 *r_bootstrap;
+ u16 r_bootstrap_len;
+ struct dpp_bootstrap_info *peer_bi;
+ struct dpp_authentication *auth;
+
+ wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
+ MAC2STR(src));
+
+ r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
+ &r_bootstrap_len);
+ if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
+ "Missing or invalid required Responder Bootstrapping Key Hash attribute");
+ return;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
+ r_bootstrap, r_bootstrap_len);
+ peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
+ r_bootstrap);
+ dpp_notify_chirp_received(hapd->msg_ctx,
+ peer_bi ? (int) peer_bi->id : -1,
+ src, freq, r_bootstrap);
+ if (!peer_bi) {
+ if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
+ src, hdr, buf, len, freq, NULL,
+ r_bootstrap) == 0)
+ return;
+ wpa_printf(MSG_DEBUG,
+ "DPP: No matching bootstrapping information found");
+ return;
+ }
+
+ if (hapd->dpp_auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore Presence Announcement during ongoing Authentication");
+ return;
+ }
+
+ auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
+ peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
+ 0);
+ if (!auth)
+ return;
+ hostapd_dpp_set_testing_options(hapd, auth);
+ if (dpp_set_configurator(auth,
+ hapd->dpp_configurator_params) < 0) {
+ dpp_auth_deinit(auth);
+ return;
+ }
+
+ auth->neg_freq = freq;
+
+ if (!is_zero_ether_addr(peer_bi->mac_addr))
+ os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
+
+ hapd->dpp_auth = auth;
+ if (hostapd_dpp_auth_init_next(hapd) < 0) {
+ dpp_auth_deinit(hapd->dpp_auth);
+ hapd->dpp_auth = NULL;
+ }
+}
+
+
+static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
+ void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ struct dpp_authentication *auth = hapd->dpp_auth;
+
+ if (!auth)
+ return;
+
+ wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
+ hostapd_dpp_listen_stop(hapd);
+ dpp_auth_deinit(auth);
+ hapd->dpp_auth = NULL;
+}
+
+
+static void
+hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
+ u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
+ struct dpp_configurator *conf;
+ struct dpp_authentication *auth;
+ unsigned int wait_time, max_wait_time;
+ u16 group;
+
+ if (hapd->dpp_auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore Reconfig Announcement during ongoing Authentication");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
+ MAC2STR(src));
+
+ csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
+ &csign_hash_len);
+ if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
+ "Missing or invalid required Configurator C-sign key Hash attribute");
+ return;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
+ csign_hash, csign_hash_len);
+ conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
+ csign_hash);
+ if (!conf) {
+ if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
+ src, hdr, buf, len, freq, NULL,
+ NULL) == 0)
+ return;
+ wpa_printf(MSG_DEBUG,
+ "DPP: No matching Configurator information found");
+ return;
+ }
+
+ fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
+ &fcgroup_len);
+ if (!fcgroup || fcgroup_len != 2) {
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
+ "Missing or invalid required Finite Cyclic Group attribute");
+ return;
+ }
+ group = WPA_GET_LE16(fcgroup);
+ wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
+
+ a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
+ e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
+
+ auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
+ conf, freq, group, a_nonce, a_nonce_len,
+ e_id, e_id_len);
+ if (!auth)
+ return;
+ hostapd_dpp_set_testing_options(hapd, auth);
+ if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
+ dpp_auth_deinit(auth);
+ return;
+ }
+
+ os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
+ hapd->dpp_auth = auth;
+
+ hapd->dpp_in_response_listen = 0;
+ hapd->dpp_auth_ok_on_ack = 0;
+ wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
+ max_wait_time = hapd->dpp_resp_wait_time ?
+ hapd->dpp_resp_wait_time : 2000;
+ if (wait_time > max_wait_time)
+ wait_time = max_wait_time;
+ wait_time += 10; /* give the driver some extra time to complete */
+ eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
+ hostapd_dpp_reconfig_reply_wait_timeout,
+ hapd, NULL);
+ wait_time -= 10;
+
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+ " freq=%u type=%d",
+ MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
+ if (hostapd_drv_send_action(hapd, freq, wait_time, src,
+ wpabuf_head(auth->reconfig_req_msg),
+ wpabuf_len(auth->reconfig_req_msg)) < 0) {
+ dpp_auth_deinit(hapd->dpp_auth);
+ hapd->dpp_auth = NULL;
+ }
+}
+
+
+static void
+hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ struct dpp_authentication *auth = hapd->dpp_auth;
+ struct wpabuf *conf;
+
+ wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
+ MACSTR, MAC2STR(src));
+
+ if (!auth || !auth->reconfig || !auth->configurator) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No DPP Reconfig Authentication in progress - drop");
+ return;
+ }
+
+ if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
+ MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
+ return;
+ }
+
+ conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
+ if (!conf)
+ return;
+
+ eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
+ hapd, NULL);
+
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+ " freq=%u type=%d",
+ MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
+ if (hostapd_drv_send_action(hapd, freq, 500, src,
+ wpabuf_head(conf), wpabuf_len(conf)) < 0) {
+ wpabuf_free(conf);
+ dpp_auth_deinit(hapd->dpp_auth);
+ hapd->dpp_auth = NULL;
+ return;
+ }
+ wpabuf_free(conf);
+}
+
#endif /* CONFIG_DPP2 */
@@ -1026,9 +1434,13 @@ static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
enum dpp_status_error status)
{
struct wpabuf *msg;
+ size_t len;
- msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
- 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
+ len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
+#ifdef CONFIG_DPP2
+ len += 5;
+#endif /* CONFIG_DPP2 */
+ msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
if (!msg)
return;
@@ -1101,6 +1513,15 @@ skip_status:
skip_connector:
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_DPP2
+ if (DPP_VERSION > 1) {
+ /* Protocol Version */
+ wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
+ wpabuf_put_le16(msg, 1);
+ wpabuf_put_u8(msg, DPP_VERSION);
+ }
+#endif /* CONFIG_DPP2 */
+
wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
" status=%d", MAC2STR(src), status);
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
@@ -1466,6 +1887,18 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
case DPP_PA_CONNECTION_STATUS_RESULT:
hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
break;
+ case DPP_PA_PRESENCE_ANNOUNCEMENT:
+ hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
+ freq);
+ break;
+ case DPP_PA_RECONFIG_ANNOUNCEMENT:
+ hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
+ freq);
+ break;
+ case DPP_PA_RECONFIG_AUTH_RESP:
+ hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
+ freq);
+ break;
#endif /* CONFIG_DPP2 */
default:
wpa_printf(MSG_DEBUG,
@@ -1495,7 +1928,7 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
struct wpabuf *resp;
wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
- if (!auth || !auth->auth_success ||
+ if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
#ifdef CONFIG_DPP2
if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
@@ -1531,6 +1964,8 @@ void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
#ifdef CONFIG_DPP2
+ eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
+ hapd, NULL);
if (ok && auth->peer_version >= 2 &&
auth->conf_resp_status == DPP_STATUS_OK) {
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
@@ -1560,14 +1995,13 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
int ret = -1;
char *curve = NULL;
- auth = os_zalloc(sizeof(*auth));
+ auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
if (!auth)
return -1;
curve = get_param(cmd, " curve=");
hostapd_dpp_set_testing_options(hapd, auth);
- if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
- auth, cmd) == 0 &&
+ if (dpp_set_configurator(auth, cmd) == 0 &&
dpp_configurator_own_config(auth, curve, 1) == 0) {
hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
ret = 0;
@@ -1776,10 +2210,13 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
#ifdef CONFIG_DPP2
+ eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
+ hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
NULL);
eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
NULL);
+ hostapd_dpp_chirp_stop(hapd);
#endif /* CONFIG_DPP2 */
dpp_auth_deinit(hapd->dpp_auth);
hapd->dpp_auth = NULL;
@@ -1788,3 +2225,359 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
os_free(hapd->dpp_configurator_params);
hapd->dpp_configurator_params = NULL;
}
+
+
+#ifdef CONFIG_DPP2
+
+int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
+{
+ struct dpp_controller_config config;
+ const char *pos;
+
+ os_memset(&config, 0, sizeof(config));
+ config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
+ config.netrole = DPP_NETROLE_AP;
+ config.msg_ctx = hapd->msg_ctx;
+ config.cb_ctx = hapd;
+ config.process_conf_obj = hostapd_dpp_process_conf_obj;
+ if (cmd) {
+ pos = os_strstr(cmd, " tcp_port=");
+ if (pos) {
+ pos += 10;
+ config.tcp_port = atoi(pos);
+ }
+
+ pos = os_strstr(cmd, " role=");
+ if (pos) {
+ pos += 6;
+ if (os_strncmp(pos, "configurator", 12) == 0)
+ config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
+ else if (os_strncmp(pos, "enrollee", 8) == 0)
+ config.allowed_roles = DPP_CAPAB_ENROLLEE;
+ else if (os_strncmp(pos, "either", 6) == 0)
+ config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
+ DPP_CAPAB_ENROLLEE;
+ else
+ return -1;
+ }
+
+ config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
+ }
+ config.configurator_params = hapd->dpp_configurator_params;
+ return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
+}
+
+
+static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
+
+static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
+ hostapd_drv_send_action_cancel_wait(hapd);
+ hostapd_dpp_chirp_next(hapd, NULL);
+}
+
+
+static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
+{
+ struct wpabuf *msg;
+ int type;
+
+ msg = hapd->dpp_presence_announcement;
+ type = DPP_PA_PRESENCE_ANNOUNCEMENT;
+ wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+ " freq=%u type=%d",
+ MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
+ if (hostapd_drv_send_action(
+ hapd, hapd->dpp_chirp_freq, 2000, broadcast,
+ wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
+ eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
+ hapd, NULL) < 0)
+ hostapd_dpp_chirp_stop(hapd);
+}
+
+
+static struct hostapd_hw_modes *
+dpp_get_mode(struct hostapd_data *hapd,
+ enum hostapd_hw_mode mode)
+{
+ struct hostapd_hw_modes *modes = hapd->iface->hw_features;
+ u16 num_modes = hapd->iface->num_hw_features;
+ u16 i;
+
+ for (i = 0; i < num_modes; i++) {
+ if (modes[i].mode != mode ||
+ !modes[i].num_channels || !modes[i].channels)
+ continue;
+ return &modes[i];
+ }
+
+ return NULL;
+}
+
+
+static void
+hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
+{
+ struct hostapd_data *hapd = iface->bss[0];
+ struct wpa_scan_results *scan_res;
+ struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
+ unsigned int i;
+ struct hostapd_hw_modes *mode;
+ int c;
+
+ if (!bi)
+ return;
+
+ hapd->dpp_chirp_scan_done = 1;
+
+ scan_res = hostapd_driver_get_scan_results(hapd);
+
+ os_free(hapd->dpp_chirp_freqs);
+ hapd->dpp_chirp_freqs = NULL;
+
+ /* Channels from own bootstrapping info */
+ if (bi) {
+ for (i = 0; i < bi->num_freq; i++)
+ int_array_add_unique(&hapd->dpp_chirp_freqs,
+ bi->freq[i]);
+ }
+
+ /* Preferred chirping channels */
+ int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
+
+ mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
+ if (mode) {
+ int chan44 = 0, chan149 = 0;
+
+ for (c = 0; c < mode->num_channels; c++) {
+ struct hostapd_channel_data *chan = &mode->channels[c];
+
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+ if (chan->freq == 5220)
+ chan44 = 1;
+ if (chan->freq == 5745)
+ chan149 = 1;
+ }
+ if (chan149)
+ int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
+ else if (chan44)
+ int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
+ }
+
+ mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
+ if (mode) {
+ for (c = 0; c < mode->num_channels; c++) {
+ struct hostapd_channel_data *chan = &mode->channels[c];
+
+ if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_RADAR)) ||
+ chan->freq != 60480)
+ continue;
+ int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
+ break;
+ }
+ }
+
+ /* Add channels from scan results for APs that advertise Configurator
+ * Connectivity element */
+ for (i = 0; scan_res && i < scan_res->num; i++) {
+ struct wpa_scan_res *bss = scan_res->res[i];
+ size_t ie_len = bss->ie_len;
+
+ if (!ie_len)
+ ie_len = bss->beacon_ie_len;
+ if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
+ DPP_CC_IE_VENDOR_TYPE))
+ int_array_add_unique(&hapd->dpp_chirp_freqs,
+ bss->freq);
+ }
+
+ if (!hapd->dpp_chirp_freqs ||
+ eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
+ hapd, NULL) < 0)
+ hostapd_dpp_chirp_stop(hapd);
+
+ wpa_scan_results_free(scan_res);
+}
+
+
+static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ int i;
+
+ if (hapd->dpp_chirp_listen)
+ hostapd_dpp_listen_stop(hapd);
+
+ if (hapd->dpp_chirp_freq == 0) {
+ if (hapd->dpp_chirp_round % 4 == 0 &&
+ !hapd->dpp_chirp_scan_done) {
+ struct wpa_driver_scan_params params;
+ int ret;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Update channel list for chirping");
+ os_memset(&params, 0, sizeof(params));
+ ret = hostapd_driver_scan(hapd, &params);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Failed to request a scan ret=%d (%s)",
+ ret, strerror(-ret));
+ hostapd_dpp_chirp_scan_res_handler(hapd->iface);
+ } else {
+ hapd->iface->scan_cb =
+ hostapd_dpp_chirp_scan_res_handler;
+ }
+ return;
+ }
+ hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
+ hapd->dpp_chirp_round++;
+ wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
+ hapd->dpp_chirp_round);
+ } else {
+ for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
+ if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
+ break;
+ if (!hapd->dpp_chirp_freqs[i]) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Previous chirp freq %d not found",
+ hapd->dpp_chirp_freq);
+ return;
+ }
+ i++;
+ if (hapd->dpp_chirp_freqs[i]) {
+ hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
+ } else {
+ hapd->dpp_chirp_iter--;
+ if (hapd->dpp_chirp_iter <= 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Chirping iterations completed");
+ hostapd_dpp_chirp_stop(hapd);
+ return;
+ }
+ hapd->dpp_chirp_freq = 0;
+ hapd->dpp_chirp_scan_done = 0;
+ if (eloop_register_timeout(30, 0,
+ hostapd_dpp_chirp_next,
+ hapd, NULL) < 0) {
+ hostapd_dpp_chirp_stop(hapd);
+ return;
+ }
+ if (hapd->dpp_chirp_listen) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Listen on %d MHz during chirp 30 second wait",
+ hapd->dpp_chirp_listen);
+ /* TODO: start listen on the channel */
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Wait 30 seconds before starting the next chirping round");
+ }
+ return;
+ }
+ }
+
+ hostapd_dpp_chirp_start(hapd);
+}
+
+
+int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
+{
+ const char *pos;
+ int iter = 1, listen_freq = 0;
+ struct dpp_bootstrap_info *bi;
+
+ pos = os_strstr(cmd, " own=");
+ if (!pos)
+ return -1;
+ pos += 5;
+ bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
+ if (!bi) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Identified bootstrap info not found");
+ return -1;
+ }
+
+ pos = os_strstr(cmd, " iter=");
+ if (pos) {
+ iter = atoi(pos + 6);
+ if (iter <= 0)
+ return -1;
+ }
+
+ pos = os_strstr(cmd, " listen=");
+ if (pos) {
+ listen_freq = atoi(pos + 8);
+ if (listen_freq <= 0)
+ return -1;
+ }
+
+ hostapd_dpp_chirp_stop(hapd);
+ hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
+ hapd->dpp_qr_mutual = 0;
+ hapd->dpp_chirp_bi = bi;
+ hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
+ if (!hapd->dpp_presence_announcement)
+ return -1;
+ hapd->dpp_chirp_iter = iter;
+ hapd->dpp_chirp_round = 0;
+ hapd->dpp_chirp_scan_done = 0;
+ hapd->dpp_chirp_listen = listen_freq;
+
+ return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
+}
+
+
+void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
+{
+ if (hapd->dpp_presence_announcement) {
+ hostapd_drv_send_action_cancel_wait(hapd);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
+ }
+ hapd->dpp_chirp_bi = NULL;
+ wpabuf_free(hapd->dpp_presence_announcement);
+ hapd->dpp_presence_announcement = NULL;
+ if (hapd->dpp_chirp_listen)
+ hostapd_dpp_listen_stop(hapd);
+ hapd->dpp_chirp_listen = 0;
+ hapd->dpp_chirp_freq = 0;
+ os_free(hapd->dpp_chirp_freqs);
+ hapd->dpp_chirp_freqs = NULL;
+ eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
+ eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
+ if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
+ /* TODO: abort ongoing scan */
+ hapd->iface->scan_cb = NULL;
+ }
+}
+
+
+static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
+{
+ struct dpp_bootstrap_info *bi = ctx;
+ size_t i;
+
+ for (i = 0; i < iface->num_bss; i++) {
+ struct hostapd_data *hapd = iface->bss[i];
+
+ if (bi == hapd->dpp_chirp_bi)
+ hostapd_dpp_chirp_stop(hapd);
+ }
+
+ return 0;
+}
+
+
+void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
+{
+ struct hapd_interfaces *interfaces = ctx;
+
+ hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
+}
+
+#endif /* CONFIG_DPP2 */
diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h
index c1ec5d7..264d3e4 100644
--- a/src/ap/dpp_hostapd.h
+++ b/src/ap/dpp_hostapd.h
@@ -1,6 +1,7 @@
/*
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,7 +10,12 @@
#ifndef DPP_HOSTAPD_H
#define DPP_HOSTAPD_H
+struct dpp_bootstrap_info;
+
int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_listen_stop(struct hostapd_data *hapd);
@@ -35,4 +41,9 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd);
void hostapd_dpp_init_global(struct hapd_interfaces *ifaces);
void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces);
+int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd);
+void hostapd_dpp_chirp_stop(struct hostapd_data *hapd);
+void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi);
+
#endif /* DPP_HOSTAPD_H */
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 3198bd5..9af5445 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -17,6 +17,7 @@
#include "common/wpa_ctrl.h"
#include "common/dpp.h"
#include "common/sae.h"
+#include "common/hw_features_common.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
@@ -104,18 +105,45 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
#endif /* CONFIG_FILS */
+static bool check_sa_query_need(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ if ((sta->flags &
+ (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) !=
+ (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED))
+ return false;
+
+ if (!sta->sa_query_timed_out && sta->sa_query_count > 0)
+ ap_check_sa_query_timeout(hapd, sta);
+
+ if (!sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) {
+ /*
+ * STA has already been associated with MFP and SA Query timeout
+ * has not been reached. Reject the association attempt
+ * temporarily and start SA Query, if one is not pending.
+ */
+ if (sta->sa_query_count == 0)
+ ap_sta_start_sa_query(hapd, sta);
+
+ return true;
+ }
+
+ return false;
+}
+
+
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *req_ies, size_t req_ies_len, int reassoc)
{
struct sta_info *sta;
- int new_assoc, res;
+ int new_assoc;
+ enum wpa_validate_result res;
struct ieee802_11_elems elems;
const u8 *ie;
size_t ielen;
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
u8 *p = buf;
u16 reason = WLAN_REASON_UNSPECIFIED;
- u16 status = WLAN_STATUS_SUCCESS;
+ int status = WLAN_STATUS_SUCCESS;
const u8 *p2p_dev_addr = NULL;
if (addr == NULL) {
@@ -219,7 +247,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
#endif /* CONFIG_P2P */
-#ifdef CONFIG_IEEE80211N
#ifdef NEED_AP_MLME
if (elems.ht_capabilities &&
(hapd->iface->conf->ht_capab &
@@ -233,7 +260,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
ht40_intolerant_add(hapd->iface, sta);
}
#endif /* NEED_AP_MLME */
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_INTERWORKING
if (elems.ext_capab && elems.ext_capab_len > 4) {
@@ -293,6 +319,17 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
struct wpabuf *wps;
+ if (check_sa_query_need(hapd, sta)) {
+ status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
+
+ p = hostapd_eid_assoc_comeback_time(hapd, sta,
+ p);
+
+ hostapd_sta_assoc(hapd, addr, reassoc, status,
+ buf, p - buf);
+ return 0;
+ }
+
sta->flags |= WLAN_STA_WPS;
wps = ieee802_11_vendor_ie_concat(ie, ielen,
WPS_IE_VENDOR_TYPE);
@@ -324,52 +361,71 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
elems.rsnxe ? elems.rsnxe_len + 2 : 0,
elems.mdie, elems.mdie_len,
elems.owe_dh, elems.owe_dh_len);
- if (res != WPA_IE_OK) {
+ reason = WLAN_REASON_INVALID_IE;
+ status = WLAN_STATUS_INVALID_IE;
+ switch (res) {
+ case WPA_IE_OK:
+ reason = WLAN_REASON_UNSPECIFIED;
+ status = WLAN_STATUS_SUCCESS;
+ break;
+ case WPA_INVALID_IE:
+ reason = WLAN_REASON_INVALID_IE;
+ status = WLAN_STATUS_INVALID_IE;
+ break;
+ case WPA_INVALID_GROUP:
+ reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+ status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+ break;
+ case WPA_INVALID_PAIRWISE:
+ reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
+ status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+ break;
+ case WPA_INVALID_AKMP:
+ reason = WLAN_REASON_AKMP_NOT_VALID;
+ status = WLAN_STATUS_AKMP_NOT_VALID;
+ break;
+ case WPA_NOT_ENABLED:
+ reason = WLAN_REASON_INVALID_IE;
+ status = WLAN_STATUS_INVALID_IE;
+ break;
+ case WPA_ALLOC_FAIL:
+ reason = WLAN_REASON_UNSPECIFIED;
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ break;
+ case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
+ reason = WLAN_REASON_INVALID_IE;
+ status = WLAN_STATUS_INVALID_IE;
+ break;
+ case WPA_INVALID_MGMT_GROUP_CIPHER:
+ reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
+ status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+ break;
+ case WPA_INVALID_MDIE:
+ reason = WLAN_REASON_INVALID_MDE;
+ status = WLAN_STATUS_INVALID_MDIE;
+ break;
+ case WPA_INVALID_PROTO:
+ reason = WLAN_REASON_INVALID_IE;
+ status = WLAN_STATUS_INVALID_IE;
+ break;
+ case WPA_INVALID_PMKID:
+ reason = WLAN_REASON_INVALID_PMKID;
+ status = WLAN_STATUS_INVALID_PMKID;
+ break;
+ case WPA_DENIED_OTHER_REASON:
+ reason = WLAN_REASON_UNSPECIFIED;
+ status = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+ break;
+ }
+ if (status != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_DEBUG,
"WPA/RSN information element rejected? (res %u)",
res);
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
- if (res == WPA_INVALID_GROUP) {
- reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
- status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
- } else if (res == WPA_INVALID_PAIRWISE) {
- reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
- status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
- } else if (res == WPA_INVALID_AKMP) {
- reason = WLAN_REASON_AKMP_NOT_VALID;
- status = WLAN_STATUS_AKMP_NOT_VALID;
- } else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
- reason = WLAN_REASON_INVALID_IE;
- status = WLAN_STATUS_INVALID_IE;
- } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
- reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
- status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
- } else {
- reason = WLAN_REASON_INVALID_IE;
- status = WLAN_STATUS_INVALID_IE;
- }
goto fail;
}
- if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
- (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
- !sta->sa_query_timed_out &&
- sta->sa_query_count > 0)
- ap_check_sa_query_timeout(hapd, sta);
- if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
- (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
- !sta->sa_query_timed_out &&
- (sta->auth_alg != WLAN_AUTH_FT)) {
- /*
- * STA has already been associated with MFP and SA
- * Query timeout has not been reached. Reject the
- * association attempt temporarily and start SA Query,
- * if one is not pending.
- */
-
- if (sta->sa_query_count == 0)
- ap_sta_start_sa_query(hapd, sta);
-
+ if (check_sa_query_need(hapd, sta)) {
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
@@ -402,7 +458,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
#ifdef CONFIG_SAE
if (hapd->conf->sae_pwe == 2 &&
sta->auth_alg == WLAN_AUTH_SAE &&
- sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
+ sta->sae && !sta->sae->h2e &&
elems.rsnxe && elems.rsnxe_len >= 1 &&
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
@@ -465,6 +521,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
return WLAN_STATUS_INVALID_IE;
#endif /* CONFIG_HS20 */
}
+#ifdef CONFIG_WPS
+skip_wpa_check:
+#endif /* CONFIG_WPS */
#ifdef CONFIG_MBO
if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
@@ -476,13 +535,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
#endif /* CONFIG_MBO */
-#ifdef CONFIG_WPS
-skip_wpa_check:
-#endif /* CONFIG_WPS */
-
#ifdef CONFIG_IEEE80211R_AP
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
- sta->auth_alg, req_ies, req_ies_len);
+ sta->auth_alg, req_ies, req_ies_len,
+ !elems.rsnxe);
if (!p) {
wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -569,22 +625,24 @@ skip_wpa_check:
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
elems.owe_dh) {
u8 *npos;
+ u16 ret_status;
npos = owe_assoc_req_process(hapd, sta,
elems.owe_dh, elems.owe_dh_len,
p, sizeof(buf) - (p - buf),
- &reason);
+ &ret_status);
+ status = ret_status;
if (npos)
p = npos;
+
if (!npos &&
- reason == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
- status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
- hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
+ status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
+ hostapd_sta_assoc(hapd, addr, reassoc, ret_status, buf,
p - buf);
return 0;
}
- if (!npos || reason != WLAN_STATUS_SUCCESS)
+ if (!npos || status != WLAN_STATUS_SUCCESS)
goto fail;
}
#endif /* CONFIG_OWE */
@@ -621,6 +679,11 @@ skip_wpa_check:
pfs_fail:
#endif /* CONFIG_DPP2 */
+ if (elems.rrm_enabled &&
+ elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
+ os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
+ sizeof(sta->rrm_enabled_capa));
+
#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
@@ -667,7 +730,8 @@ skip_wpa_check:
fail:
#ifdef CONFIG_IEEE80211R_AP
- hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
+ if (status >= 0)
+ hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
#endif /* CONFIG_IEEE80211R_AP */
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
ap_free_sta(hapd, sta);
@@ -705,6 +769,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
@@ -798,8 +863,6 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset, int width, int cf1, int cf2,
int finished)
{
- /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
-
#ifdef NEED_AP_MLME
int channel, chwidth, is_dfs;
u8 seg0_idx = 0, seg1_idx = 0;
@@ -849,9 +912,18 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
switch (hapd->iface->current_mode->mode) {
case HOSTAPD_MODE_IEEE80211A:
- if (cf1 > 5000)
+ if (cf1 == 5935)
+ seg0_idx = (cf1 - 5925) / 5;
+ else if (cf1 > 5950)
+ seg0_idx = (cf1 - 5950) / 5;
+ else if (cf1 > 5000)
seg0_idx = (cf1 - 5000) / 5;
- if (cf2 > 5000)
+
+ if (cf2 == 5935)
+ seg1_idx = (cf2 - 5925) / 5;
+ else if (cf2 > 5950)
+ seg1_idx = (cf2 - 5950) / 5;
+ else if (cf2 > 5000)
seg1_idx = (cf2 - 5000) / 5;
break;
default:
@@ -902,10 +974,39 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
"freq=%d dfs=%d", freq, is_dfs);
+ } else if (is_dfs &&
+ hostapd_is_dfs_required(hapd->iface) &&
+ !hostapd_is_dfs_chan_available(hapd->iface) &&
+ !hapd->iface->cac_started) {
+ hostapd_disable_iface(hapd->iface);
+ hostapd_enable_iface(hapd->iface);
}
for (i = 0; i < hapd->iface->num_bss; i++)
hostapd_neighbor_set_own_report(hapd->iface->bss[i]);
+
+#ifdef CONFIG_OCV
+ if (hapd->conf->ocv) {
+ struct sta_info *sta;
+ bool check_sa_query = false;
+
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (wpa_auth_uses_ocv(sta->wpa_sm) &&
+ !(sta->flags & WLAN_STA_WNM_SLEEP_MODE)) {
+ sta->post_csa_sa_query = 1;
+ check_sa_query = true;
+ }
+ }
+
+ if (check_sa_query) {
+ wpa_printf(MSG_DEBUG,
+ "OCV: Check post-CSA SA Query initiation in 15 seconds");
+ eloop_register_timeout(15, 0,
+ hostapd_ocv_check_csa_sa_query,
+ hapd, NULL);
+ }
+ }
+#endif /* CONFIG_OCV */
#endif /* NEED_AP_MLME */
}
@@ -932,6 +1033,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
{
int ret, i;
int err = 0;
+ struct hostapd_channel_data *pri_chan;
if (hapd->iconf->channel) {
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
@@ -939,12 +1041,20 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
return;
}
+ hapd->iface->freq = acs_res->pri_freq;
+
if (!hapd->iface->current_mode) {
for (i = 0; i < hapd->iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode =
&hapd->iface->hw_features[i];
if (mode->mode == acs_res->hw_mode) {
+ if (hapd->iface->freq > 0 &&
+ !hw_get_chan(mode->mode,
+ hapd->iface->freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features))
+ continue;
hapd->iface->current_mode = mode;
break;
}
@@ -958,24 +1068,33 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
}
}
- hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
-
- if (!acs_res->pri_channel) {
+ if (!acs_res->pri_freq) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel");
err = 1;
goto out;
}
+ pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
+ acs_res->pri_freq, NULL,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
+ if (!pri_chan) {
+ wpa_printf(MSG_ERROR,
+ "ACS: Could not determine primary channel number from pri_freq %u",
+ acs_res->pri_freq);
+ err = 1;
+ goto out;
+ }
- hapd->iconf->channel = acs_res->pri_channel;
+ hapd->iconf->channel = pri_chan->chan;
hapd->iconf->acs = 1;
- if (acs_res->sec_channel == 0)
+ if (acs_res->sec_freq == 0)
hapd->iconf->secondary_channel = 0;
- else if (acs_res->sec_channel < acs_res->pri_channel)
+ else if (acs_res->sec_freq < acs_res->pri_freq)
hapd->iconf->secondary_channel = -1;
- else if (acs_res->sec_channel > acs_res->pri_channel)
+ else if (acs_res->sec_freq > acs_res->pri_freq)
hapd->iconf->secondary_channel = 1;
else {
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
@@ -983,32 +1102,35 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
goto out;
}
+ hapd->iconf->edmg_channel = acs_res->edmg_channel;
+
if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
/* set defaults for backwards compatibility */
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_USE_HT);
- if (acs_res->ch_width == 80) {
- hostapd_set_oper_centr_freq_seg0_idx(
- hapd->iconf, acs_res->vht_seg0_center_ch);
- hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_80MHZ);
- } else if (acs_res->ch_width == 160) {
- if (acs_res->vht_seg1_center_ch == 0) {
+ if (acs_res->ch_width == 40) {
+ if (is_6ghz_freq(acs_res->pri_freq))
hostapd_set_oper_centr_freq_seg0_idx(
hapd->iconf,
acs_res->vht_seg0_center_ch);
+ } else if (acs_res->ch_width == 80) {
+ hostapd_set_oper_centr_freq_seg0_idx(
+ hapd->iconf, acs_res->vht_seg0_center_ch);
+ if (acs_res->vht_seg1_center_ch == 0) {
hostapd_set_oper_chwidth(hapd->iconf,
- CHANWIDTH_160MHZ);
+ CHANWIDTH_80MHZ);
} else {
- hostapd_set_oper_centr_freq_seg0_idx(
- hapd->iconf,
- acs_res->vht_seg0_center_ch);
+ hostapd_set_oper_chwidth(hapd->iconf,
+ CHANWIDTH_80P80MHZ);
hostapd_set_oper_centr_freq_seg1_idx(
hapd->iconf,
acs_res->vht_seg1_center_ch);
- hostapd_set_oper_chwidth(hapd->iconf,
- CHANWIDTH_80P80MHZ);
}
+ } else if (acs_res->ch_width == 160) {
+ hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_160MHZ);
+ hostapd_set_oper_centr_freq_seg0_idx(
+ hapd->iconf, acs_res->vht_seg1_center_ch);
}
}
@@ -1404,15 +1526,33 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
#endif /* HOSTAPD */
+static struct hostapd_channel_data *
+hostapd_get_mode_chan(struct hostapd_hw_modes *mode, unsigned int freq)
+{
+ int i;
+ struct hostapd_channel_data *chan;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
+ if ((unsigned int) chan->freq == freq)
+ return chan;
+ }
+
+ return NULL;
+}
+
+
static struct hostapd_channel_data * hostapd_get_mode_channel(
struct hostapd_iface *iface, unsigned int freq)
{
int i;
struct hostapd_channel_data *chan;
- for (i = 0; i < iface->current_mode->num_channels; i++) {
- chan = &iface->current_mode->channels[i];
- if ((unsigned int) chan->freq == freq)
+ for (i = 0; i < iface->num_hw_features; i++) {
+ if (hostapd_hw_skip_mode(iface, &iface->hw_features[i]))
+ continue;
+ chan = hostapd_get_mode_chan(&iface->hw_features[i], freq);
+ if (chan)
return chan;
}
diff --git a/src/ap/fils_hlp.c b/src/ap/fils_hlp.c
index 6da514a..0310aab 100644
--- a/src/ap/fils_hlp.c
+++ b/src/ap/fils_hlp.c
@@ -158,7 +158,7 @@ static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx)
ssize_t res;
u8 msgtype = 0;
int rapid_commit = 0;
- struct iphdr *iph;
+ struct ip *iph;
struct udphdr *udph;
struct wpabuf *resp;
const u8 *rpos;
@@ -259,14 +259,14 @@ static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx)
wpabuf_put_data(resp, "\xaa\xaa\x03\x00\x00\x00", 6);
wpabuf_put_be16(resp, ETH_P_IP);
iph = wpabuf_put(resp, sizeof(*iph));
- iph->version = 4;
- iph->ihl = sizeof(*iph) / 4;
- iph->tot_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos));
- iph->ttl = 1;
- iph->protocol = 17; /* UDP */
- iph->saddr = hapd->conf->dhcp_server.u.v4.s_addr;
- iph->daddr = dhcp->client_ip;
- iph->check = ip_checksum(iph, sizeof(*iph));
+ iph->ip_v = 4;
+ iph->ip_hl = sizeof(*iph) / 4;
+ iph->ip_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos));
+ iph->ip_ttl = 1;
+ iph->ip_p = 17; /* UDP */
+ iph->ip_src.s_addr = hapd->conf->dhcp_server.u.v4.s_addr;
+ iph->ip_dst.s_addr = dhcp->client_ip;
+ iph->ip_sum = ip_checksum(iph, sizeof(*iph));
udph = wpabuf_put(resp, sizeof(*udph));
udph->uh_sport = htons(DHCP_SERVER_PORT);
udph->uh_dport = htons(DHCP_CLIENT_PORT);
@@ -479,13 +479,13 @@ static int fils_process_hlp_udp(struct hostapd_data *hapd,
struct sta_info *sta, const u8 *dst,
const u8 *pos, size_t len)
{
- const struct iphdr *iph;
+ const struct ip *iph;
const struct udphdr *udph;
u16 sport, dport, ulen;
if (len < sizeof(*iph) + sizeof(*udph))
return 0;
- iph = (const struct iphdr *) pos;
+ iph = (const struct ip *) pos;
udph = (const struct udphdr *) (iph + 1);
sport = ntohs(udph->uh_sport);
dport = ntohs(udph->uh_dport);
@@ -510,24 +510,24 @@ static int fils_process_hlp_ip(struct hostapd_data *hapd,
struct sta_info *sta, const u8 *dst,
const u8 *pos, size_t len)
{
- const struct iphdr *iph;
- u16 tot_len;
+ const struct ip *iph;
+ uint16_t ip_len;
if (len < sizeof(*iph))
return 0;
- iph = (const struct iphdr *) pos;
+ iph = (const struct ip *) pos;
if (ip_checksum(iph, sizeof(*iph)) != 0) {
wpa_printf(MSG_DEBUG,
"FILS: HLP request IPv4 packet had invalid header checksum - dropped");
return 0;
}
- tot_len = ntohs(iph->tot_len);
- if (tot_len > len)
+ ip_len = ntohs(iph->ip_len);
+ if (ip_len > len)
return 0;
wpa_printf(MSG_DEBUG,
"FILS: HLP request IPv4: saddr=%08x daddr=%08x protocol=%u",
- iph->saddr, iph->daddr, iph->protocol);
- switch (iph->protocol) {
+ iph->ip_src.s_addr, iph->ip_dst.s_addr, iph->ip_p);
+ switch (iph->ip_p) {
case 17:
return fils_process_hlp_udp(hapd, sta, dst, pos, len);
}
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index 9567e20..90f1577 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -1555,11 +1555,14 @@ void gas_serv_req_dpp_processing(struct hostapd_data *hapd,
di->prot = prot;
di->sd_resp = buf;
di->sd_resp_pos = 0;
+ di->dpp = 1;
tx_buf = gas_build_initial_resp(
dialog_token, WLAN_STATUS_SUCCESS,
- comeback_delay, 10);
- if (tx_buf)
+ comeback_delay, 10 + 2);
+ if (tx_buf) {
gas_serv_write_dpp_adv_proto(tx_buf);
+ wpabuf_put_le16(tx_buf, 0);
+ }
}
} else {
wpa_printf(MSG_DEBUG,
@@ -1782,9 +1785,10 @@ static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
tx_buf = gas_build_comeback_resp(dialog_token,
WLAN_STATUS_SUCCESS,
dialog->sd_frag_id, more, 0,
- 10 + frag_len);
+ 10 + 2 + frag_len);
if (tx_buf) {
gas_serv_write_dpp_adv_proto(tx_buf);
+ wpabuf_put_le16(tx_buf, frag_len);
wpabuf_put_buf(tx_buf, buf);
}
} else
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 3686438..b37f49f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -13,6 +13,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
+#include "utils/crc32.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
#include "common/hw_features_common.h"
@@ -57,8 +58,10 @@
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
+#ifdef CONFIG_WEP
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
+#endif /* CONFIG_WEP */
static int setup_interface2(struct hostapd_iface *iface);
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
@@ -73,6 +76,8 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int ret;
for (i = 0; i < interfaces->count; i++) {
+ if (!interfaces->iface[i])
+ continue;
ret = cb(interfaces->iface[i], ctx);
if (ret)
return ret;
@@ -88,7 +93,9 @@ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
return;
hostapd_set_privacy(hapd, 0);
+#ifdef CONFIG_WEP
hostapd_setup_encryption(hapd->conf->iface, hapd);
+#endif /* CONFIG_WEP */
}
@@ -141,7 +148,9 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
wpa_deinit(hapd->wpa_auth);
hapd->wpa_auth = NULL;
hostapd_set_privacy(hapd, 0);
+#ifdef CONFIG_WEP
hostapd_setup_encryption(hapd->conf->iface, hapd);
+#endif /* CONFIG_WEP */
hostapd_set_generic_elem(hapd, (u8 *) "", 0);
}
@@ -169,7 +178,9 @@ static void hostapd_clear_old(struct hostapd_iface *iface)
for (j = 0; j < iface->num_bss; j++) {
hostapd_flush_old_stations(iface->bss[j],
WLAN_REASON_PREV_AUTH_NOT_VALID);
+#ifdef CONFIG_WEP
hostapd_broadcast_wep_clear(iface->bss[j]);
+#endif /* CONFIG_WEP */
#ifndef CONFIG_NO_RADIUS
/* TODO: update dynamic data based on changed configuration
@@ -283,6 +294,8 @@ int hostapd_reload_config(struct hostapd_iface *iface)
}
+#ifdef CONFIG_WEP
+
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
const char *ifname)
{
@@ -291,8 +304,8 @@ static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
if (!ifname || !hapd->drv_priv)
return;
for (i = 0; i < NUM_WEP_KEYS; i++) {
- if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
- 0, NULL, 0, NULL, 0)) {
+ if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, 0,
+ 0, NULL, 0, NULL, 0, KEY_FLAG_GROUP)) {
wpa_printf(MSG_DEBUG, "Failed to clear default "
"encryption keys (ifname=%s keyidx=%d)",
ifname, i);
@@ -301,8 +314,8 @@ static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
if (hapd->conf->ieee80211w) {
for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
- NULL, i, 0, NULL,
- 0, NULL, 0)) {
+ NULL, i, 0, 0, NULL,
+ 0, NULL, 0, KEY_FLAG_GROUP)) {
wpa_printf(MSG_DEBUG, "Failed to clear "
"default mgmt encryption keys "
"(ifname=%s keyidx=%d)", ifname, i);
@@ -325,11 +338,12 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
struct hostapd_ssid *ssid = &hapd->conf->ssid;
idx = ssid->wep.idx;
- if (ssid->wep.default_len &&
+ if (ssid->wep.default_len && ssid->wep.key[idx] &&
hostapd_drv_set_key(hapd->conf->iface,
- hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
+ hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0,
1, NULL, 0, ssid->wep.key[idx],
- ssid->wep.len[idx])) {
+ ssid->wep.len[idx],
+ KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
errors++;
}
@@ -337,6 +351,8 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
return errors;
}
+#endif /* CONFIG_WEP */
+
static void hostapd_free_hapd_data(struct hostapd_data *hapd)
{
@@ -423,6 +439,10 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
hostapd_clean_rrm(hapd);
fils_hlp_deinit(hapd);
+#ifdef CONFIG_OCV
+ eloop_cancel_timeout(hostapd_ocv_check_csa_sa_query, hapd, NULL);
+#endif /* CONFIG_OCV */
+
#ifdef CONFIG_SAE
{
struct hostapd_sae_commit_queue *q;
@@ -479,11 +499,9 @@ static void sta_track_deinit(struct hostapd_iface *iface)
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
{
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
-#ifdef CONFIG_IEEE80211N
#ifdef NEED_AP_MLME
hostapd_stop_setup_timers(iface);
#endif /* NEED_AP_MLME */
-#endif /* CONFIG_IEEE80211N */
if (iface->current_mode)
acs_cleanup(iface);
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
@@ -524,6 +542,8 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
}
+#ifdef CONFIG_WEP
+
static void hostapd_clear_wep(struct hostapd_data *hapd)
{
if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) {
@@ -552,10 +572,13 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
for (i = 0; i < 4; i++) {
if (hapd->conf->ssid.wep.key[i] &&
- hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
+ hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, 0,
i == hapd->conf->ssid.wep.idx, NULL, 0,
hapd->conf->ssid.wep.key[i],
- hapd->conf->ssid.wep.len[i])) {
+ hapd->conf->ssid.wep.len[i],
+ i == hapd->conf->ssid.wep.idx ?
+ KEY_FLAG_GROUP_RX_TX_DEFAULT :
+ KEY_FLAG_GROUP_RX_TX)) {
wpa_printf(MSG_WARNING, "Could not set WEP "
"encryption.");
return -1;
@@ -568,6 +591,8 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
return 0;
}
+#endif /* CONFIG_WEP */
+
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
{
@@ -603,7 +628,9 @@ static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
{
hostapd_free_stas(hapd);
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
+#ifdef CONFIG_WEP
hostapd_clear_wep(hapd);
+#endif /* CONFIG_WEP */
}
@@ -1154,13 +1181,15 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
#endif /* CONFIG_MESH */
if (flush_old_stations)
- hostapd_flush_old_stations(hapd,
- WLAN_REASON_PREV_AUTH_NOT_VALID);
+ hostapd_flush(hapd);
hostapd_set_privacy(hapd, 0);
- hostapd_broadcast_wep_clear(hapd);
+#ifdef CONFIG_WEP
+ if (!hostapd_drv_nl80211(hapd))
+ hostapd_broadcast_wep_clear(hapd);
if (hostapd_setup_encryption(conf->iface, hapd))
return -1;
+#endif /* CONFIG_WEP */
/*
* Fetch the SSID from the system and use it or,
@@ -1190,8 +1219,14 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
}
+ /*
+ * Short SSID calculation is identical to FCS and it is defined in
+ * IEEE P802.11-REVmd/D3.0, 9.4.2.170.3 (Calculating the Short-SSID).
+ */
+ conf->ssid.short_ssid = crc32(conf->ssid.ssid, conf->ssid.ssid_len);
+
if (!hostapd_drv_none(hapd)) {
- wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
+ wpa_printf(MSG_DEBUG, "Using interface %s with hwaddr " MACSTR
" and ssid \"%s\"",
conf->iface, MAC2STR(hapd->own_addr),
wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
@@ -1340,6 +1375,21 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
return -1;
+ if (flush_old_stations && !conf->start_disabled &&
+ conf->broadcast_deauth) {
+ u8 addr[ETH_ALEN];
+
+ /* Should any previously associated STA not have noticed that
+ * the AP had stopped and restarted, send one more
+ * deauthentication notification now that the AP is ready to
+ * operate. */
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+ "Deauthenticate all stations at BSS start");
+ os_memset(addr, 0xff, ETH_ALEN);
+ hostapd_drv_sta_deauth(hapd, addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ }
+
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
return -1;
@@ -1572,6 +1622,51 @@ static int setup_interface(struct hostapd_iface *iface)
}
+static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
+{
+ int freq, i, j;
+
+ if (!iface->conf->channel)
+ return 0;
+ if (iface->conf->op_class) {
+ freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
+ iface->conf->channel);
+ if (freq < 0) {
+ wpa_printf(MSG_INFO,
+ "Could not convert op_class %u channel %u to operating frequency",
+ iface->conf->op_class, iface->conf->channel);
+ return -1;
+ }
+ iface->freq = freq;
+ return 0;
+ }
+
+ /* Old configurations using only 2.4/5/60 GHz bands may not specify the
+ * op_class parameter. Select a matching channel from the configured
+ * mode using the channel parameter for these cases.
+ */
+ for (j = 0; j < iface->num_hw_features; j++) {
+ struct hostapd_hw_modes *mode = &iface->hw_features[j];
+
+ if (iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY &&
+ iface->conf->hw_mode != mode->mode)
+ continue;
+ for (i = 0; i < mode->num_channels; i++) {
+ struct hostapd_channel_data *chan = &mode->channels[i];
+
+ if (chan->chan == iface->conf->channel &&
+ !is_6ghz_freq(chan->freq)) {
+ iface->freq = chan->freq;
+ return 0;
+ }
+ }
+ }
+
+ wpa_printf(MSG_INFO, "Could not determine operating frequency");
+ return -1;
+}
+
+
static int setup_interface2(struct hostapd_iface *iface)
{
iface->wait_channel_update = 0;
@@ -1580,7 +1675,20 @@ static int setup_interface2(struct hostapd_iface *iface)
/* Not all drivers support this yet, so continue without hw
* feature data. */
} else {
- int ret = hostapd_select_hw_mode(iface);
+ int ret;
+
+ ret = configured_fixed_chan_to_freq(iface);
+ if (ret < 0)
+ goto fail;
+
+ if (iface->conf->op_class) {
+ int ch_width;
+
+ ch_width = op_class_to_ch_width(iface->conf->op_class);
+ hostapd_set_oper_chwidth(iface->conf, ch_width);
+ }
+
+ ret = hostapd_select_hw_mode(iface);
if (ret < 0) {
wpa_printf(MSG_ERROR, "Could not select hw_mode and "
"channel. (%d)", ret);
@@ -1685,7 +1793,7 @@ static void fst_hostapd_update_mb_ie_cb(void *ctx, const u8 *addr,
static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+ bool mb_only)
{
struct sta_info *s = (struct sta_info *) *get_ctx;
@@ -1707,7 +1815,7 @@ static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx,
static const u8 * fst_hostapd_get_peer_first(void *ctx,
struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+ bool mb_only)
{
struct hostapd_data *hapd = ctx;
@@ -1719,7 +1827,7 @@ static const u8 * fst_hostapd_get_peer_first(void *ctx,
static const u8 * fst_hostapd_get_peer_next(void *ctx,
struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+ bool mb_only)
{
return fst_hostapd_get_sta(get_ctx, mb_only);
}
@@ -1807,6 +1915,13 @@ static int hostapd_owe_iface_iter2(struct hostapd_iface *iface, void *ctx)
if (!bss->conf->owe_transition_ifname[0])
continue;
+ if (bss->iface->state != HAPD_IFACE_ENABLED) {
+ wpa_printf(MSG_DEBUG,
+ "OWE: Interface %s state %s - defer beacon update",
+ bss->conf->iface,
+ hostapd_state_text(bss->iface->state));
+ continue;
+ }
res = hostapd_owe_trans_get_info(bss);
if (res == 0)
continue;
@@ -1864,12 +1979,11 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
goto fail;
wpa_printf(MSG_DEBUG, "Completing interface initialization");
- if (iface->conf->channel) {
+ if (iface->freq) {
#ifdef NEED_AP_MLME
int res;
#endif /* NEED_AP_MLME */
- iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
"Frequency: %d MHz",
hostapd_hw_mode_txt(iface->conf->hw_mode),
@@ -2281,12 +2395,10 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
hostapd_bss_deinit(iface->bss[j]);
}
-#ifdef CONFIG_IEEE80211N
#ifdef NEED_AP_MLME
hostapd_stop_setup_timers(iface);
eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
#endif /* NEED_AP_MLME */
-#endif /* CONFIG_IEEE80211N */
}
@@ -3050,6 +3162,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
hostapd_prune_associations(hapd, sta->addr);
ap_sta_clear_disconnect_timeouts(hapd, sta);
+ sta->post_csa_sa_query = 0;
#ifdef CONFIG_P2P
if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
@@ -3561,3 +3674,25 @@ void hostapd_periodic_iface(struct hostapd_iface *iface)
#endif /* CONFIG_NO_RADIUS */
}
}
+
+
+#ifdef CONFIG_OCV
+void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ struct sta_info *sta;
+
+ wpa_printf(MSG_DEBUG, "OCV: Post-CSA SA Query initiation check");
+
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (!sta->post_csa_sa_query)
+ continue;
+
+ wpa_printf(MSG_DEBUG, "OCV: OCVC STA " MACSTR
+ " did not start SA Query after CSA - disconnect",
+ MAC2STR(sta->addr));
+ ap_sta_disconnect(hapd, sta, sta->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ }
+}
+#endif /* CONFIG_OCV */
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 2358d16..b70d13f 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -38,6 +38,10 @@ union wps_event_data;
struct mesh_conf;
#endif /* CONFIG_MESH */
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define CTRL_IFACE_COOKIE_LEN 8
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
struct hostapd_iface;
struct hapd_interfaces {
@@ -72,6 +76,11 @@ struct hapd_interfaces {
#ifdef CONFIG_DPP
struct dpp_global *dpp;
#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+ unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
};
enum hostapd_chan_status {
@@ -340,6 +349,11 @@ struct hostapd_data {
int last_igtk_key_idx;
u8 last_igtk[WPA_IGTK_MAX_LEN];
size_t last_igtk_len;
+
+ enum wpa_alg last_bigtk_alg;
+ int last_bigtk_key_idx;
+ u8 last_bigtk[WPA_BIGTK_MAX_LEN];
+ size_t last_bigtk_len;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO
@@ -377,6 +391,16 @@ struct hostapd_data {
unsigned int dpp_resp_wait_time;
unsigned int dpp_resp_max_tries;
unsigned int dpp_resp_retry_time;
+#ifdef CONFIG_DPP2
+ struct wpabuf *dpp_presence_announcement;
+ struct dpp_bootstrap_info *dpp_chirp_bi;
+ int dpp_chirp_freq;
+ int *dpp_chirp_freqs;
+ int dpp_chirp_iter;
+ int dpp_chirp_round;
+ int dpp_chirp_scan_done;
+ int dpp_chirp_listen;
+#endif /* CONFIG_DPP2 */
#ifdef CONFIG_TESTING_OPTIONS
char *dpp_config_obj_override;
char *dpp_discovery_override;
@@ -395,6 +419,10 @@ struct hostapd_data {
#ifdef CONFIG_SQLITE
sqlite3 *rad_attr_db;
#endif /* CONFIG_SQLITE */
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+ unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
};
@@ -462,9 +490,7 @@ struct hostapd_iface {
struct ap_info *ap_hash[STA_HASH_SIZE];
u64 drv_flags;
-
- /* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */
- unsigned int smps_modes;
+ u64 drv_flags2;
/*
* A bitmap of supported protocols for probe response offload. See
@@ -606,6 +632,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
void hostapd_periodic_iface(struct hostapd_iface *iface);
int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
+void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 2fefaf8..f6e6903 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -224,16 +224,27 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
}
-#ifdef CONFIG_IEEE80211N
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
{
- int pri_chan, sec_chan;
+ int pri_freq, sec_freq;
+ struct hostapd_channel_data *p_chan, *s_chan;
- pri_chan = iface->conf->channel;
- sec_chan = pri_chan + iface->conf->secondary_channel * 4;
+ pri_freq = iface->freq;
+ sec_freq = pri_freq + iface->conf->secondary_channel * 20;
+
+ if (!iface->current_mode)
+ return 0;
+
+ p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
- return allowed_ht40_channel_pair(iface->current_mode, pri_chan,
- sec_chan);
+ s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
+
+ return allowed_ht40_channel_pair(iface->current_mode->mode,
+ p_chan, s_chan);
}
@@ -241,9 +252,11 @@ static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
{
if (iface->conf->secondary_channel > 0) {
iface->conf->channel += 4;
+ iface->freq += 20;
iface->conf->secondary_channel = -1;
} else {
iface->conf->channel -= 4;
+ iface->freq -= 20;
iface->conf->secondary_channel = 1;
}
}
@@ -252,13 +265,23 @@ static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
struct wpa_scan_results *scan_res)
{
- int pri_chan, sec_chan;
+ unsigned int pri_freq, sec_freq;
int res;
+ struct hostapd_channel_data *pri_chan, *sec_chan;
- pri_chan = iface->conf->channel;
- sec_chan = pri_chan + iface->conf->secondary_channel * 4;
+ pri_freq = iface->freq;
+ sec_freq = pri_freq + iface->conf->secondary_channel * 20;
+
+ if (!iface->current_mode)
+ return 0;
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
+ NULL, iface->hw_features,
+ iface->num_hw_features);
+ sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
+ NULL, iface->hw_features,
+ iface->num_hw_features);
- res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan);
+ res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
if (res == 2) {
if (iface->conf->no_pri_sec_switch) {
@@ -352,7 +375,7 @@ static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
if (iface->current_mode == NULL)
return;
- pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
+ pri_freq = iface->freq;
if (iface->conf->secondary_channel > 0)
sec_freq = pri_freq + 20;
else
@@ -397,7 +420,7 @@ static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface,
if (iface->current_mode == NULL)
return;
- pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
+ pri_freq = iface->freq;
if (iface->conf->secondary_channel > 0) {
affected_start = pri_freq - 10;
affected_end = pri_freq + 30;
@@ -537,26 +560,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
return 0;
}
- switch (conf & HT_CAP_INFO_SMPS_MASK) {
- case HT_CAP_INFO_SMPS_STATIC:
- if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) {
- wpa_printf(MSG_ERROR,
- "Driver does not support configured HT capability [SMPS-STATIC]");
- return 0;
- }
- break;
- case HT_CAP_INFO_SMPS_DYNAMIC:
- if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) {
- wpa_printf(MSG_ERROR,
- "Driver does not support configured HT capability [SMPS-DYNAMIC]");
- return 0;
- }
- break;
- case HT_CAP_INFO_SMPS_DISABLED:
- default:
- break;
- }
-
if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
!(hw & HT_CAP_INFO_GREEN_FIELD)) {
wpa_printf(MSG_ERROR, "Driver does not support configured "
@@ -663,13 +666,13 @@ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
}
#endif /* CONFIG_IEEE80211AX */
-#endif /* CONFIG_IEEE80211N */
-
int hostapd_check_ht_capab(struct hostapd_iface *iface)
{
-#ifdef CONFIG_IEEE80211N
int ret;
+
+ if (is_6ghz_freq(iface->freq))
+ return 0;
if (!iface->conf->ieee80211n)
return 0;
@@ -698,7 +701,6 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
return ret;
if (!ieee80211n_allowed_ht40_channel_pair(iface))
return -1;
-#endif /* CONFIG_IEEE80211N */
return 0;
}
@@ -731,14 +733,15 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface)
static int hostapd_is_usable_chan(struct hostapd_iface *iface,
- int channel, int primary)
+ int frequency, int primary)
{
struct hostapd_channel_data *chan;
if (!iface->current_mode)
return 0;
- chan = hw_get_channel_chan(iface->current_mode, channel, NULL);
+ chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
+ iface->hw_features, iface->num_hw_features);
if (!chan)
return 0;
@@ -747,8 +750,8 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface,
return 1;
wpa_printf(MSG_INFO,
- "Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
- channel, primary ? "primary" : "secondary",
+ "Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
+ frequency, primary ? "primary" : "secondary",
chan->flag,
chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
@@ -762,19 +765,28 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
int num_of_enabled = 0;
int max_contiguous = 0;
struct ieee80211_edmg_config edmg;
+ struct hostapd_channel_data *pri_chan;
if (!iface->conf->enable_edmg)
return 1;
+ if (!iface->current_mode)
+ return 0;
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode,
+ iface->freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
hostapd_encode_edmg_chan(iface->conf->enable_edmg,
iface->conf->edmg_channel,
- iface->conf->channel,
+ pri_chan->chan,
&edmg);
- if (!(edmg.channels & BIT(iface->conf->channel - 1)))
+ if (!(edmg.channels & BIT(pri_chan->chan - 1)))
return 0;
/* 60 GHz channels 1..6 */
for (i = 0; i < 6; i++) {
+ int freq = 56160 + 2160 * (i + 1);
+
if (edmg.channels & BIT(i)) {
contiguous++;
num_of_enabled++;
@@ -789,7 +801,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
if (num_of_enabled > 4)
return 0;
- if (!hostapd_is_usable_chan(iface, i + 1, 1))
+ if (!hostapd_is_usable_chan(iface, freq, 1))
return 0;
if (contiguous > max_contiguous)
@@ -819,38 +831,45 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
{
- int secondary_chan;
+ int secondary_freq;
struct hostapd_channel_data *pri_chan;
- pri_chan = hw_get_channel_chan(iface->current_mode,
- iface->conf->channel, NULL);
- if (!pri_chan)
+ if (!iface->current_mode)
return 0;
-
- if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1))
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode,
+ iface->freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
+ if (!pri_chan) {
+ wpa_printf(MSG_ERROR, "Primary frequency not present");
return 0;
-
+ }
+ if (!hostapd_is_usable_chan(iface, pri_chan->freq, 1)) {
+ wpa_printf(MSG_ERROR, "Primary frequency not allowed");
+ return 0;
+ }
if (!hostapd_is_usable_edmg(iface))
return 0;
if (!iface->conf->secondary_channel)
return 1;
+ if (hostapd_is_usable_chan(iface, iface->freq +
+ iface->conf->secondary_channel * 20, 0))
+ return 1;
if (!iface->conf->ht40_plus_minus_allowed)
- return hostapd_is_usable_chan(
- iface, iface->conf->channel +
- iface->conf->secondary_channel * 4, 0);
+ return 0;
/* Both HT40+ and HT40- are set, pick a valid secondary channel */
- secondary_chan = iface->conf->channel + 4;
- if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
+ secondary_freq = iface->freq + 20;
+ if (hostapd_is_usable_chan(iface, secondary_freq, 0) &&
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
iface->conf->secondary_channel = 1;
return 1;
}
- secondary_chan = iface->conf->channel - 4;
- if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
+ secondary_freq = iface->freq - 20;
+ if (hostapd_is_usable_chan(iface, secondary_freq, 0) &&
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
iface->conf->secondary_channel = -1;
return 1;
@@ -860,10 +879,43 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
}
+static void hostapd_determine_mode(struct hostapd_iface *iface)
+{
+ int i;
+ enum hostapd_hw_mode target_mode;
+
+ if (iface->current_mode ||
+ iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
+ return;
+
+ if (iface->freq < 4000)
+ target_mode = HOSTAPD_MODE_IEEE80211G;
+ else if (iface->freq > 50000)
+ target_mode = HOSTAPD_MODE_IEEE80211AD;
+ else
+ target_mode = HOSTAPD_MODE_IEEE80211A;
+
+ for (i = 0; i < iface->num_hw_features; i++) {
+ struct hostapd_hw_modes *mode;
+
+ mode = &iface->hw_features[i];
+ if (mode->mode == target_mode) {
+ iface->current_mode = mode;
+ iface->conf->hw_mode = mode->mode;
+ break;
+ }
+ }
+
+ if (!iface->current_mode)
+ wpa_printf(MSG_ERROR, "ACS: Cannot decide mode");
+}
+
+
static enum hostapd_chan_status
hostapd_check_chans(struct hostapd_iface *iface)
{
- if (iface->conf->channel) {
+ if (iface->freq) {
+ hostapd_determine_mode(iface);
if (hostapd_is_usable_chans(iface))
return HOSTAPD_CHAN_VALID;
else
@@ -897,9 +949,9 @@ static void hostapd_notify_bad_chans(struct hostapd_iface *iface)
hostapd_logger(iface->bss[0], NULL,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
- "Configured channel (%d) not found from the "
- "channel list of current mode (%d) %s",
+ "Configured channel (%d) or frequency (%d) not found from the channel list of the current mode (%d) %s",
iface->conf->channel,
+ iface->freq,
iface->current_mode->mode,
hostapd_hw_mode_txt(iface->current_mode->mode));
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
@@ -919,9 +971,7 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err)
case HOSTAPD_CHAN_VALID:
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
ACS_EVENT_COMPLETED "freq=%d channel=%d",
- hostapd_hw_get_freq(iface->bss[0],
- iface->conf->channel),
- iface->conf->channel);
+ iface->freq, iface->conf->channel);
break;
case HOSTAPD_CHAN_ACS:
wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available");
@@ -961,7 +1011,6 @@ out:
int hostapd_select_hw_mode(struct hostapd_iface *iface)
{
int i;
- int freq = -1;
if (iface->num_hw_features < 1)
return -1;
@@ -978,13 +1027,13 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
}
iface->current_mode = NULL;
- if (iface->conf->channel && iface->conf->op_class)
- freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
- iface->conf->channel);
for (i = 0; i < iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode = &iface->hw_features[i];
if (mode->mode == iface->conf->hw_mode) {
- if (freq > 0 && !hw_get_chan(mode, freq))
+ if (iface->freq > 0 &&
+ !hw_get_chan(mode->mode, iface->freq,
+ iface->hw_features,
+ iface->num_hw_features))
continue;
iface->current_mode = mode;
break;
@@ -992,9 +1041,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
}
if (iface->current_mode == NULL) {
- if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) ||
- !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY))
- {
+ if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
+ (iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) {
+ wpa_printf(MSG_DEBUG,
+ "Using offloaded hw_mode=any ACS");
+ } else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
+ iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) {
+ wpa_printf(MSG_DEBUG,
+ "Using internal ACS for hw_mode=any");
+ } else {
wpa_printf(MSG_ERROR,
"Hardware does not support configured mode");
hostapd_logger(iface->bss[0], NULL,
@@ -1048,7 +1103,9 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
struct hostapd_hw_modes *mode;
if (hapd->iface->current_mode) {
- channel = hw_get_chan(hapd->iface->current_mode, freq);
+ channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
if (channel)
return channel;
}
@@ -1059,9 +1116,28 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
return 0;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
- channel = hw_get_chan(mode, freq);
+ channel = hw_get_chan(mode->mode, freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
if (channel)
return channel;
}
return 0;
}
+
+
+int hostapd_hw_skip_mode(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode)
+{
+ int i;
+
+ if (iface->current_mode)
+ return mode != iface->current_mode;
+ if (mode->mode != HOSTAPD_MODE_IEEE80211B)
+ return 0;
+ for (i = 0; i < iface->num_hw_features; i++) {
+ if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G)
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 902a19f..dd24f95 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -25,6 +25,8 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface);
int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
void hostapd_stop_setup_timers(struct hostapd_iface *iface);
+int hostapd_hw_skip_mode(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode);
#else /* NEED_AP_MLME */
static inline void
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -49,7 +51,7 @@ static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
static inline const char * hostapd_hw_mode_txt(int mode)
{
- return NULL;
+ return "UNKNOWN";
}
static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
@@ -77,6 +79,12 @@ static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface)
{
}
+static inline int hostapd_hw_skip_mode(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode)
+{
+ return 0;
+}
+
#endif /* NEED_AP_MLME */
#endif /* HW_FEATURES_H */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 306e989..de715a0 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -24,6 +24,7 @@
#include "common/dpp.h"
#include "common/ocv.h"
#include "common/wpa_common.h"
+#include "common/wpa_ctrl.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "p2p/p2p.h"
@@ -88,6 +89,7 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
int i, num, count;
+ int h2e_required;
if (hapd->iface->current_rates == NULL)
return eid;
@@ -98,7 +100,11 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
- if (hapd->conf->sae_pwe == 1)
+ h2e_required = (hapd->conf->sae_pwe == 1 ||
+ hostapd_sae_pw_id_in_use(hapd->conf) == 2) &&
+ hapd->conf->sae_pwe != 3 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt);
+ if (h2e_required)
num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
@@ -126,7 +132,7 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
- if (hapd->conf->sae_pwe == 1 && count < 8) {
+ if (h2e_required && count < 8) {
count++;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
}
@@ -139,6 +145,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
int i, num, count;
+ int h2e_required;
if (hapd->iface->current_rates == NULL)
return eid;
@@ -148,7 +155,11 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
- if (hapd->conf->sae_pwe == 1)
+ h2e_required = (hapd->conf->sae_pwe == 1 ||
+ hostapd_sae_pw_id_in_use(hapd->conf) == 2) &&
+ hapd->conf->sae_pwe != 3 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt);
+ if (h2e_required)
num++;
if (num <= 8)
return eid;
@@ -179,7 +190,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
- if (hapd->conf->sae_pwe == 1) {
+ if (h2e_required) {
count++;
if (count > 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
@@ -189,10 +200,31 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
}
+u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
+ size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
+ if (hapd->conf->radio_measurements[i])
+ break;
+ }
+
+ if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
+ return eid;
+
+ *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
+ *eid++ = RRM_CAPABILITIES_IE_LEN;
+ os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
+
+ return eid + RRM_CAPABILITIES_IE_LEN;
+}
+
+
u16 hostapd_own_capab_info(struct hostapd_data *hapd)
{
int capab = WLAN_CAPABILITY_ESS;
- int privacy;
+ int privacy = 0;
int dfs;
int i;
@@ -208,12 +240,14 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd)
hapd->iconf->preamble == SHORT_PREAMBLE)
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+#ifdef CONFIG_WEP
privacy = hapd->conf->ssid.wep.keys_set;
if (hapd->conf->ieee802_1x &&
(hapd->conf->default_wep_key_len ||
hapd->conf->individual_wep_key_len))
privacy = 1;
+#endif /* CONFIG_WEP */
if (hapd->conf->wpa)
privacy = 1;
@@ -253,6 +287,7 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd)
}
+#ifdef CONFIG_WEP
#ifndef CONFIG_NO_RC4
static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
u16 auth_transaction, const u8 *challenge,
@@ -309,9 +344,10 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
return 0;
}
#endif /* CONFIG_NO_RC4 */
+#endif /* CONFIG_WEP */
-static int send_auth_reply(struct hostapd_data *hapd,
+static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *dst, const u8 *bssid,
u16 auth_alg, u16 auth_transaction, u16 resp,
const u8 *ies, size_t ies_len, const char *dbg)
@@ -344,7 +380,38 @@ static int send_auth_reply(struct hostapd_data *hapd,
" auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
MAC2STR(dst), auth_alg, auth_transaction,
resp, (unsigned long) ies_len, dbg);
- if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
+#ifdef CONFIG_TESTING_OPTIONS
+#ifdef CONFIG_SAE
+ if (hapd->conf->sae_confirm_immediate == 2 &&
+ auth_alg == WLAN_AUTH_SAE) {
+ if (auth_transaction == 1 && sta &&
+ (resp == WLAN_STATUS_SUCCESS ||
+ resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ resp == WLAN_STATUS_SAE_PK)) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Postpone SAE Commit transmission until Confirm is ready");
+ os_free(sta->sae_postponed_commit);
+ sta->sae_postponed_commit = buf;
+ sta->sae_postponed_commit_len = rlen;
+ return WLAN_STATUS_SUCCESS;
+ }
+
+ if (auth_transaction == 2 && sta && sta->sae_postponed_commit) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Send postponed SAE Commit first, immediately followed by SAE Confirm");
+ if (hostapd_drv_send_mlme(hapd,
+ sta->sae_postponed_commit,
+ sta->sae_postponed_commit_len,
+ 0, NULL, 0, 0) < 0)
+ wpa_printf(MSG_INFO, "send_auth_reply: send failed");
+ os_free(sta->sae_postponed_commit);
+ sta->sae_postponed_commit = NULL;
+ sta->sae_postponed_commit_len = 0;
+ }
+ }
+#endif /* CONFIG_SAE */
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (hostapd_drv_send_mlme(hapd, reply, rlen, 0, NULL, 0, 0) < 0)
wpa_printf(MSG_INFO, "send_auth_reply: send failed");
else
reply_res = WLAN_STATUS_SUCCESS;
@@ -364,7 +431,7 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
struct sta_info *sta;
int reply_res;
- reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
+ reply_res = send_auth_reply(hapd, NULL, dst, bssid, WLAN_AUTH_FT,
auth_transaction, status, ies, ies_len,
"auth-ft-finish");
@@ -403,7 +470,8 @@ static void sae_set_state(struct sta_info *sta, enum sae_state state,
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
- struct sta_info *sta, int update)
+ struct sta_info *sta, int update,
+ int status_code)
{
struct wpabuf *buf;
const char *password = NULL;
@@ -411,12 +479,25 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
const char *rx_id = NULL;
int use_pt = 0;
struct sae_pt *pt = NULL;
+ const struct sae_pk *pk = NULL;
if (sta->sae->tmp) {
rx_id = sta->sae->tmp->pw_id;
- use_pt = sta->sae->tmp->h2e;
+ use_pt = sta->sae->h2e;
+#ifdef CONFIG_SAE_PK
+ os_memcpy(sta->sae->tmp->own_addr, hapd->own_addr, ETH_ALEN);
+ os_memcpy(sta->sae->tmp->peer_addr, sta->addr, ETH_ALEN);
+#endif /* CONFIG_SAE_PK */
}
+ if (rx_id && hapd->conf->sae_pwe != 3)
+ use_pt = 1;
+ else if (status_code == WLAN_STATUS_SUCCESS)
+ use_pt = 0;
+ else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK)
+ use_pt = 1;
+
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
if (!is_broadcast_ether_addr(pw->peer_addr) &&
os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
@@ -428,6 +509,8 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
continue;
password = pw->password;
pt = pw->pt;
+ if (!(hapd->conf->mesh & MESH_ENABLED))
+ pk = pw->pk;
break;
}
if (!password) {
@@ -441,7 +524,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
if (update && use_pt &&
sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
- NULL) < 0)
+ NULL, pk) < 0)
return NULL;
if (update && !use_pt &&
@@ -463,10 +546,13 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
(rx_id ? 3 + os_strlen(rx_id) : 0));
- if (buf == NULL)
- return NULL;
- sae_write_commit(sta->sae, buf, sta->sae->tmp ?
- sta->sae->tmp->anti_clogging_token : NULL, rx_id);
+ if (buf &&
+ sae_write_commit(sta->sae, buf, sta->sae->tmp ?
+ sta->sae->tmp->anti_clogging_token : NULL,
+ rx_id) < 0) {
+ wpabuf_free(buf);
+ buf = NULL;
+ }
return buf;
}
@@ -481,7 +567,17 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
if (buf == NULL)
return NULL;
- sae_write_confirm(sta->sae, buf);
+#ifdef CONFIG_SAE_PK
+#ifdef CONFIG_TESTING_OPTIONS
+ if (sta->sae->tmp)
+ sta->sae->tmp->omit_pk_elem = hapd->conf->sae_pk_omit;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_SAE_PK */
+
+ if (sae_write_confirm(sta->sae, buf) < 0) {
+ wpabuf_free(buf);
+ return NULL;
+ }
return buf;
}
@@ -489,21 +585,35 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
static int auth_sae_send_commit(struct hostapd_data *hapd,
struct sta_info *sta,
- const u8 *bssid, int update)
+ const u8 *bssid, int update, int status_code)
{
struct wpabuf *data;
int reply_res;
u16 status;
- data = auth_build_sae_commit(hapd, sta, update);
+ data = auth_build_sae_commit(hapd, sta, update, status_code);
if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
if (data == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
- WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
- reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
+ if (sta->sae->tmp && sta->sae->pk)
+ status = WLAN_STATUS_SAE_PK;
+ else if (sta->sae->tmp && sta->sae->h2e)
+ status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
+ else
+ status = WLAN_STATUS_SUCCESS;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->sae_commit_status >= 0 &&
+ hapd->conf->sae_commit_status != status) {
+ wpa_printf(MSG_INFO,
+ "TESTING: Override SAE commit status code %u --> %d",
+ status, hapd->conf->sae_commit_status);
+ status = hapd->conf->sae_commit_status;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
+ WLAN_AUTH_SAE, 1,
status, wpabuf_head(data),
wpabuf_len(data), "sae-send-commit");
@@ -524,7 +634,8 @@ static int auth_sae_send_confirm(struct hostapd_data *hapd,
if (data == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
+ reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
+ WLAN_AUTH_SAE, 2,
WLAN_STATUS_SUCCESS, wpabuf_head(data),
wpabuf_len(data), "sae-send-confirm");
@@ -564,13 +675,15 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
}
-static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr)
+static int sae_token_hash(struct hostapd_data *hapd, const u8 *addr, u8 *idx)
{
u8 hash[SHA256_MAC_LEN];
- hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
- addr, ETH_ALEN, hash);
- return hash[0];
+ if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+ addr, ETH_ALEN, hash) < 0)
+ return -1;
+ *idx = hash[0];
+ return 0;
}
@@ -583,9 +696,8 @@ static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
u16 token_idx;
u8 idx;
- if (token_len != SHA256_MAC_LEN)
+ if (token_len != SHA256_MAC_LEN || sae_token_hash(hapd, addr, &idx) < 0)
return -1;
- idx = sae_token_hash(hapd, addr);
token_idx = hapd->sae_pending_token_idx[idx];
if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
@@ -610,7 +722,7 @@ static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
- int group, const u8 *addr)
+ int group, const u8 *addr, int h2e)
{
struct wpabuf *buf;
u8 *token;
@@ -636,13 +748,23 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
sizeof(hapd->sae_pending_token_idx));
}
- buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
+ buf = wpabuf_alloc(sizeof(le16) + 3 + SHA256_MAC_LEN);
if (buf == NULL)
return NULL;
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
- p_idx = sae_token_hash(hapd, addr);
+ if (h2e) {
+ /* Encapsulate Anti-clogging Token field in a container IE */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(buf, 1 + SHA256_MAC_LEN);
+ wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
+ }
+
+ if (sae_token_hash(hapd, addr, &p_idx) < 0) {
+ wpabuf_free(buf);
+ return NULL;
+ }
token_idx = hapd->sae_pending_token_idx[p_idx];
if (!token_idx) {
hapd->sae_token_idx++;
@@ -693,7 +815,7 @@ static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
switch (sta->sae->state) {
case SAE_COMMITTED:
- ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+ ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
eloop_register_timeout(0,
hapd->dot11RSNASAERetransPeriod * 1000,
auth_sae_retransmit_timer, hapd, sta);
@@ -784,6 +906,9 @@ void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
mlme_authenticate_indication(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
+ crypto_bignum_deinit(sta->sae->peer_commit_scalar_accepted, 0);
+ sta->sae->peer_commit_scalar_accepted = sta->sae->peer_commit_scalar;
+ sta->sae->peer_commit_scalar = NULL;
wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
sta->sae->pmk, sta->sae->pmkid);
sae_sme_send_external_auth_status(hapd, sta, WLAN_STATUS_SUCCESS);
@@ -807,11 +932,16 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
switch (sta->sae->state) {
case SAE_NOTHING:
if (auth_transaction == 1) {
- if (sta->sae->tmp)
- sta->sae->tmp->h2e = status_code ==
- WLAN_STATUS_SAE_HASH_TO_ELEMENT;
+ if (sta->sae->tmp) {
+ sta->sae->h2e =
+ (status_code ==
+ WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK);
+ sta->sae->pk =
+ status_code == WLAN_STATUS_SAE_PK;
+ }
ret = auth_sae_send_commit(hapd, sta, bssid,
- !allow_reuse);
+ !allow_reuse, status_code);
if (ret)
return ret;
sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -881,7 +1011,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS;
sta->sae->sync++;
- ret = auth_sae_send_commit(hapd, sta, bssid, 0);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 0,
+ status_code);
if (ret)
return ret;
@@ -914,7 +1045,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS;
sta->sae->sync++;
- ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+ status_code);
if (ret)
return ret;
@@ -942,7 +1074,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
*sta_removed = 1;
} else if (auth_transaction == 1) {
wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
- ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+ status_code);
if (ret)
return ret;
sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -1014,13 +1147,30 @@ static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
{
- return (hapd->conf->sae_pwe == 0 &&
+ int sae_pwe = hapd->conf->sae_pwe;
+ int id_in_use;
+ bool sae_pk = false;
+
+ id_in_use = hostapd_sae_pw_id_in_use(hapd->conf);
+ if (id_in_use == 2 && sae_pwe != 3)
+ sae_pwe = 1;
+ else if (id_in_use == 1 && sae_pwe == 0)
+ sae_pwe = 2;
+#ifdef CONFIG_SAE_PK
+ sae_pk = hostapd_sae_pk_in_use(hapd->conf);
+ if (sae_pwe == 0 && sae_pk)
+ sae_pwe = 2;
+#endif /* CONFIG_SAE_PK */
+
+ return ((sae_pwe == 0 || sae_pwe == 3) &&
status_code == WLAN_STATUS_SUCCESS) ||
- (hapd->conf->sae_pwe == 1 &&
- status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
- (hapd->conf->sae_pwe == 2 &&
+ (sae_pwe == 1 &&
+ (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ (sae_pk && status_code == WLAN_STATUS_SAE_PK))) ||
+ (sae_pwe == 2 &&
(status_code == WLAN_STATUS_SUCCESS ||
- status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT));
+ status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ (sae_pk && status_code == WLAN_STATUS_SAE_PK)));
}
@@ -1043,11 +1193,15 @@ static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
static int check_sae_rejected_groups(struct hostapd_data *hapd,
- const struct wpabuf *groups)
+ struct sae_data *sae)
{
+ const struct wpabuf *groups;
size_t i, count;
const u8 *pos;
+ if (!sae->tmp)
+ return 0;
+ groups = sae->tmp->peer_rejected_groups;
if (!groups)
return 0;
@@ -1089,7 +1243,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
pos = mgmt->u.auth.variable;
end = ((const u8 *) mgmt) + len;
- send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+ resp = status_code;
+ send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
auth_transaction, resp, pos, end - pos,
"auth-sae-reflection-attack");
goto remove_sta;
@@ -1097,7 +1252,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->conf->sae_commit_override && auth_transaction == 1) {
wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
- send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+ send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
auth_transaction, resp,
wpabuf_head(hapd->conf->sae_commit_override),
wpabuf_len(hapd->conf->sae_commit_override),
@@ -1108,8 +1263,10 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
if (!sta->sae) {
if (auth_transaction != 1 ||
!sae_status_success(hapd, status_code)) {
- resp = -1;
- goto remove_sta;
+ wpa_printf(MSG_DEBUG, "SAE: Unexpected Status Code %u",
+ status_code);
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto reply;
}
sta->sae = os_zalloc(sizeof(*sta->sae));
if (!sta->sae) {
@@ -1174,7 +1331,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
* Authentication frame, and the commit-scalar and
* COMMIT-ELEMENT previously sent.
*/
- resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
+ resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0,
+ status_code);
if (resp != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_ERROR,
"SAE: Failed to send commit message");
@@ -1231,7 +1389,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
((const u8 *) mgmt) + len -
mgmt->u.auth.variable, &token,
&token_len, groups, status_code ==
- WLAN_STATUS_SAE_HASH_TO_ELEMENT);
+ WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK);
if (resp == SAE_SILENTLY_DISCARD) {
wpa_printf(MSG_DEBUG,
"SAE: Drop commit message from " MACSTR " due to reflection attack",
@@ -1261,19 +1420,24 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
if (resp != WLAN_STATUS_SUCCESS)
goto reply;
- if (sta->sae->tmp &&
- check_sae_rejected_groups(
- hapd, sta->sae->tmp->peer_rejected_groups) < 0) {
+ if (check_sae_rejected_groups(hapd, sta->sae)) {
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto remove_sta;
+ goto reply;
}
if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
+ int h2e = 0;
+
wpa_printf(MSG_DEBUG,
"SAE: Request anti-clogging token from "
MACSTR, MAC2STR(sta->addr));
+ if (sta->sae->tmp)
+ h2e = sta->sae->h2e;
+ if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK)
+ h2e = 1;
data = auth_build_token_req(hapd, sta->sae->group,
- sta->addr);
+ sta->addr, h2e);
resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
if (hapd->conf->mesh & MESH_ENABLED)
sae_set_state(sta, SAE_NOTHING,
@@ -1348,7 +1512,7 @@ reply:
data = wpabuf_alloc_copy(pos, 2);
sae_sme_send_external_auth_status(hapd, sta, resp);
- send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+ send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
auth_transaction, resp,
data ? wpabuf_head(data) : (u8 *) "",
data ? wpabuf_len(data) : 0, "auth-sae");
@@ -1385,7 +1549,7 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->sae->state != SAE_NOTHING)
return -1;
- ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+ ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
if (ret)
return -1;
@@ -1498,27 +1662,37 @@ static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr)
#endif /* CONFIG_SAE */
-static u16 wpa_res_to_status_code(int res)
+static u16 wpa_res_to_status_code(enum wpa_validate_result res)
{
- if (res == WPA_INVALID_GROUP)
+ switch (res) {
+ case WPA_IE_OK:
+ return WLAN_STATUS_SUCCESS;
+ case WPA_INVALID_IE:
+ return WLAN_STATUS_INVALID_IE;
+ case WPA_INVALID_GROUP:
return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
- if (res == WPA_INVALID_PAIRWISE)
+ case WPA_INVALID_PAIRWISE:
return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
- if (res == WPA_INVALID_AKMP)
+ case WPA_INVALID_AKMP:
return WLAN_STATUS_AKMP_NOT_VALID;
- if (res == WPA_ALLOC_FAIL)
+ case WPA_NOT_ENABLED:
+ return WLAN_STATUS_INVALID_IE;
+ case WPA_ALLOC_FAIL:
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
+ case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
- if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
+ case WPA_INVALID_MGMT_GROUP_CIPHER:
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
- if (res == WPA_INVALID_MDIE)
+ case WPA_INVALID_MDIE:
return WLAN_STATUS_INVALID_MDIE;
- if (res == WPA_INVALID_PMKID)
- return WLAN_STATUS_INVALID_PMKID;
- if (res != WPA_IE_OK)
+ case WPA_INVALID_PROTO:
return WLAN_STATUS_INVALID_IE;
- return WLAN_STATUS_SUCCESS;
+ case WPA_INVALID_PMKID:
+ return WLAN_STATUS_INVALID_PMKID;
+ case WPA_DENIED_OTHER_REASON:
+ return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+ }
+ return WLAN_STATUS_INVALID_IE;
}
@@ -1538,7 +1712,7 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
u16 resp = WLAN_STATUS_SUCCESS;
const u8 *end;
struct ieee802_11_elems elems;
- int res;
+ enum wpa_validate_result res;
struct wpa_ie_data rsn;
struct rsn_pmksa_cache_entry *pmksa = NULL;
@@ -1714,11 +1888,11 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
FILS_SESSION_LEN);
os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
- /* FILS Wrapped Data */
- if (elems.fils_wrapped_data) {
+ /* Wrapped Data */
+ if (elems.wrapped_data) {
wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
- elems.fils_wrapped_data,
- elems.fils_wrapped_data_len);
+ elems.wrapped_data,
+ elems.wrapped_data_len);
if (!pmksa) {
#ifndef CONFIG_NO_RADIUS
if (!sta->eapol_sm) {
@@ -1728,8 +1902,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG,
"FILS: Forward EAP-Initiate/Re-auth to authentication server");
ieee802_1x_encapsulate_radius(
- hapd, sta, elems.fils_wrapped_data,
- elems.fils_wrapped_data_len);
+ hapd, sta, elems.wrapped_data,
+ elems.wrapped_data_len);
sta->fils_pending_cb = cb;
wpa_printf(MSG_DEBUG,
"FILS: Will send Authentication frame once the response from authentication server is available");
@@ -1738,8 +1912,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
* to maintain a copy of the EAP-Initiate/Reauth
* message. */
if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
- elems.fils_wrapped_data,
- elems.fils_wrapped_data_len,
+ elems.wrapped_data,
+ elems.wrapped_data_len,
sta->fils_erp_pmkid) == 0)
sta->fils_erp_pmkid_set = 1;
return;
@@ -1882,12 +2056,12 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
- /* FILS Wrapped Data */
+ /* Wrapped Data */
if (!pmksa && erp_resp) {
wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
/* Element ID Extension */
- wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
+ wpabuf_put_u8(data, WLAN_EID_EXT_WRAPPED_DATA);
wpabuf_put_buf(data, erp_resp);
if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
@@ -1989,7 +2163,7 @@ static void handle_auth_fils_finish(struct hostapd_data *hapd,
auth_alg = (pub ||
resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
- send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
+ send_auth_reply(hapd, sta, sta->addr, hapd->own_addr, auth_alg, 2, resp,
data ? wpabuf_head(data) : (u8 *) "",
data ? wpabuf_len(data) : 0, "auth-fils-finish");
wpabuf_free(data);
@@ -2033,28 +2207,18 @@ void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
#endif /* CONFIG_FILS */
-int
-ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
- const u8 *msg, size_t len, u32 *session_timeout,
- u32 *acct_interim_interval,
- struct vlan_description *vlan_id,
- struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui, int is_probe_req)
+static int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
+ const u8 *msg, size_t len,
+ struct radius_sta *info)
{
int res;
- os_memset(vlan_id, 0, sizeof(*vlan_id));
- res = hostapd_allowed_address(hapd, addr, msg, len,
- session_timeout, acct_interim_interval,
- vlan_id, psk, identity, radius_cui,
- is_probe_req);
+ res = hostapd_allowed_address(hapd, addr, msg, len, info, 0);
if (res == HOSTAPD_ACL_REJECT) {
- if (!is_probe_req)
- wpa_printf(MSG_DEBUG,
- "Station " MACSTR
- " not allowed to authenticate",
- MAC2STR(addr));
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not allowed to authenticate",
+ MAC2STR(addr));
return HOSTAPD_ACL_REJECT;
}
@@ -2074,12 +2238,15 @@ ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
static int
ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
- int res, u32 session_timeout,
- u32 acct_interim_interval,
- struct vlan_description *vlan_id,
- struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui)
+ int res, struct radius_sta *info)
{
+ u32 session_timeout = info->session_timeout;
+ u32 acct_interim_interval = info->acct_interim_interval;
+ struct vlan_description *vlan_id = &info->vlan_id;
+ struct hostapd_sta_wpa_psk_short *psk = info->psk;
+ char *identity = info->identity;
+ char *radius_cui = info->radius_cui;
+
if (vlan_id->notempty &&
!hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
@@ -2096,20 +2263,22 @@ ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
hostapd_free_psk_list(sta->psk);
- if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
- sta->psk = *psk;
- *psk = NULL;
- } else {
+ if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED)
+ hostapd_copy_psk_list(&sta->psk, psk);
+ else
sta->psk = NULL;
- }
os_free(sta->identity);
- sta->identity = *identity;
- *identity = NULL;
+ if (identity)
+ sta->identity = os_strdup(identity);
+ else
+ sta->identity = NULL;
os_free(sta->radius_cui);
- sta->radius_cui = *radius_cui;
- *radius_cui = NULL;
+ if (radius_cui)
+ sta->radius_cui = os_strdup(radius_cui);
+ else
+ sta->radius_cui = NULL;
if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
sta->acct_interim_interval = acct_interim_interval;
@@ -2137,14 +2306,10 @@ static void handle_auth(struct hostapd_data *hapd,
int res, reply_res;
u16 fc;
const u8 *challenge = NULL;
- u32 session_timeout, acct_interim_interval;
- struct vlan_description vlan_id;
- struct hostapd_sta_wpa_psk_short *psk = NULL;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
- char *identity = NULL;
- char *radius_cui = NULL;
u16 seq_ctrl;
+ struct radius_sta rad_info;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
@@ -2295,10 +2460,8 @@ static void handle_auth(struct hostapd_data *hapd,
}
}
- res = ieee802_11_allowed_address(
- hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
- &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
- 0);
+ res = ieee802_11_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
+ &rad_info);
if (res == HOSTAPD_ACL_REJECT) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Ignore Authentication frame from " MACSTR
@@ -2381,9 +2544,7 @@ static void handle_auth(struct hostapd_data *hapd,
sta->auth_rssi = rssi;
#endif /* CONFIG_MBO */
- res = ieee802_11_set_radius_info(
- hapd, sta, res, session_timeout, acct_interim_interval,
- &vlan_id, &psk, &identity, &radius_cui);
+ res = ieee802_11_set_radius_info(hapd, sta, res, &rad_info);
if (res) {
wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -2416,32 +2577,10 @@ static void handle_auth(struct hostapd_data *hapd,
(!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
!(hapd->conf->mesh & MESH_ENABLED) &&
!(sta->added_unassoc)) {
- /*
- * If a station that is already associated to the AP, is trying
- * to authenticate again, remove the STA entry, in order to make
- * sure the STA PS state gets cleared and configuration gets
- * updated. To handle this, station's added_unassoc flag is
- * cleared once the station has completed association.
- */
- ap_sta_set_authorized(hapd, sta, 0);
- hostapd_drv_sta_remove(hapd, sta->addr);
- sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
- WLAN_STA_AUTHORIZED);
-
- if (hostapd_sta_add(hapd, sta->addr, 0, 0,
- sta->supported_rates,
- sta->supported_rates_len,
- 0, NULL, NULL, NULL, 0,
- sta->flags, 0, 0, 0, 0)) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_NOTICE,
- "Could not add STA to kernel driver");
+ if (ap_sta_re_add(hapd, sta) < 0) {
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
}
-
- sta->added_unassoc = 1;
}
switch (auth_alg) {
@@ -2454,6 +2593,7 @@ static void handle_auth(struct hostapd_data *hapd,
sta->auth_alg = WLAN_AUTH_OPEN;
mlme_authenticate_indication(hapd, sta);
break;
+#ifdef CONFIG_WEP
#ifndef CONFIG_NO_RC4
case WLAN_AUTH_SHARED_KEY:
resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
@@ -2472,6 +2612,7 @@ static void handle_auth(struct hostapd_data *hapd,
}
break;
#endif /* CONFIG_NO_RC4 */
+#endif /* CONFIG_WEP */
#ifdef CONFIG_IEEE80211R_AP
case WLAN_AUTH_FT:
sta->auth_alg = WLAN_AUTH_FT;
@@ -2525,11 +2666,7 @@ static void handle_auth(struct hostapd_data *hapd,
}
fail:
- os_free(identity);
- os_free(radius_cui);
- hostapd_free_psk_list(psk);
-
- reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
+ reply_res = send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, auth_alg,
auth_transaction + 1, resp, resp_ies,
resp_ies_len, "handle-auth");
@@ -2946,7 +3083,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd,
u16 status;
u8 *owe_buf, ie[256 * 2];
size_t ie_len = 0;
- int res;
+ enum wpa_validate_result res;
if (!rsn_ie || rsn_ie_len < 2) {
wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq");
@@ -3018,11 +3155,39 @@ end:
#endif /* CONFIG_OWE */
-static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
+static bool check_sa_query(struct hostapd_data *hapd, struct sta_info *sta,
+ int reassoc)
+{
+ if ((sta->flags &
+ (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) !=
+ (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED))
+ return false;
+
+ if (!sta->sa_query_timed_out && sta->sa_query_count > 0)
+ ap_check_sa_query_timeout(hapd, sta);
+
+ if (!sta->sa_query_timed_out &&
+ (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
+ /*
+ * STA has already been associated with MFP and SA Query timeout
+ * has not been reached. Reject the association attempt
+ * temporarily and start SA Query, if one is not pending.
+ */
+ if (sta->sa_query_count == 0)
+ ap_sta_start_sa_query(hapd, sta);
+
+ return true;
+ }
+
+ return false;
+}
+
+
+static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ies, size_t ies_len, int reassoc)
{
struct ieee802_11_elems elems;
- u16 resp;
+ int resp;
const u8 *wpa_ie;
size_t wpa_ie_len;
const u8 *p2p_dev_addr = NULL;
@@ -3051,7 +3216,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (resp != WLAN_STATUS_SUCCESS)
return resp;
-#ifdef CONFIG_IEEE80211N
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
@@ -3062,7 +3226,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
"mandatory HT PHY - reject association");
return WLAN_STATUS_ASSOC_DENIED_NO_HT;
}
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac) {
@@ -3097,6 +3260,19 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
elems.he_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
+ if (is_6ghz_op_class(hapd->iconf->op_class)) {
+ if (!(sta->flags & WLAN_STA_HE)) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_INFO,
+ "Station does not support mandatory HE PHY - reject association");
+ return WLAN_STATUS_DENIED_HE_NOT_SUPPORTED;
+ }
+ resp = copy_sta_he_6ghz_capab(hapd, sta,
+ elems.he_6ghz_band_cap);
+ if (resp != WLAN_STATUS_SUCCESS)
+ return resp;
+ }
}
#endif /* CONFIG_IEEE80211AX */
@@ -3130,6 +3306,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->conf->wps_state && elems.wps_ie) {
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
"Request - assume WPS is used");
+ if (check_sa_query(hapd, sta, reassoc))
+ return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
sta->flags |= WLAN_STA_WPS;
wpabuf_free(sta->wps_ie);
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
@@ -3159,7 +3337,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
if (hapd->conf->wpa && wpa_ie) {
- int res;
+ enum wpa_validate_result res;
+
wpa_ie -= 2;
wpa_ie_len += 2;
if (sta->wpa_sm == NULL)
@@ -3182,27 +3361,9 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
resp = wpa_res_to_status_code(res);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
- (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
- !sta->sa_query_timed_out &&
- sta->sa_query_count > 0)
- ap_check_sa_query_timeout(hapd, sta);
- if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
- (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
- !sta->sa_query_timed_out &&
- (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
- /*
- * STA has already been associated with MFP and SA
- * Query timeout has not been reached. Reject the
- * association attempt temporarily and start SA Query,
- * if one is not pending.
- */
-
- if (sta->sa_query_count == 0)
- ap_sta_start_sa_query(hapd, sta);
+ if (check_sa_query(hapd, sta, reassoc))
return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
- }
if (wpa_auth_uses_mfp(sta->wpa_sm))
sta->flags |= WLAN_STA_MFP;
@@ -3255,7 +3416,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->conf->sae_pwe == 2 &&
sta->auth_alg == WLAN_AUTH_SAE &&
- sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
+ sta->sae && !sta->sae->h2e &&
elems.rsnxe && elems.rsnxe_len >= 1 &&
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
@@ -3280,7 +3441,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
dpp_pfs_free(sta->dpp_pfs);
sta->dpp_pfs = NULL;
- if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
+ if (DPP_VERSION > 1 &&
+ (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
elems.owe_dh) {
@@ -3307,7 +3469,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
pfs_fail:
#endif /* CONFIG_DPP2 */
-#ifdef CONFIG_IEEE80211N
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
hostapd_logger(hapd, sta->addr,
@@ -3317,7 +3478,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
"association");
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
}
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_HS20
} else if (hapd->conf->osen) {
if (elems.osen == NULL) {
@@ -3404,6 +3564,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
struct wpa_channel_info ci;
int tx_chanwidth;
int tx_seg1_idx;
+ enum oci_verify_result res;
if (hostapd_drv_channel_info(hapd, &ci) != 0) {
wpa_printf(MSG_WARNING,
@@ -3417,9 +3578,20 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
&tx_seg1_idx) < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
- tx_chanwidth, tx_seg1_idx) != 0) {
- wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
+ res = ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx);
+ if (wpa_auth_uses_ocv(sta->wpa_sm) == 2 &&
+ res == OCI_NOT_FOUND) {
+ /* Work around misbehaving STAs */
+ wpa_printf(MSG_INFO,
+ "FILS: Disable OCV with a STA that does not send OCI");
+ wpa_auth_set_ocv(sta->wpa_sm, 0);
+ } else if (res != OCI_SUCCESS) {
+ wpa_printf(MSG_WARNING, "FILS: OCV failed: %s",
+ ocv_errorstr);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr="
+ MACSTR " frame=fils-reassoc-req error=%s",
+ MAC2STR(sta->addr), ocv_errorstr);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
}
@@ -3462,7 +3634,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
reply.u.deauth.reason_code = host_to_le16(reason_code);
- if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
+ if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0, NULL, 0, 0) < 0)
wpa_printf(MSG_INFO, "Failed to send deauth: %s",
strerror(errno));
}
@@ -3518,10 +3690,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
sta->ft_over_ds = 0;
}
-#ifdef CONFIG_IEEE80211N
if (sta->flags & WLAN_STA_HT)
hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
if (sta->flags & WLAN_STA_VHT)
hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
@@ -3545,6 +3715,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
sta->flags & WLAN_STA_HE ? &he_cap : NULL,
sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0,
+ sta->he_6ghz_capab,
sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
set)) {
@@ -3569,7 +3740,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 status_code, int reassoc,
- const u8 *ies, size_t ies_len, int rssi)
+ const u8 *ies, size_t ies_len, int rssi,
+ int omit_rsnxe)
{
int send_len;
u8 *buf;
@@ -3620,6 +3792,9 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
/* Extended supported rates */
p = hostapd_eid_ext_supp_rates(hapd, p);
+ /* Radio measurement capabilities */
+ p = hostapd_eid_rm_enabled_capab(hapd, p, buf + buflen - p);
+
#ifdef CONFIG_MBO
if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
rssi != 0) {
@@ -3636,7 +3811,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
* Transition Information, RSN, [RIC Response] */
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
buf + buflen - p,
- sta->auth_alg, ies, ies_len);
+ sta->auth_alg, ies, ies_len,
+ omit_rsnxe);
if (!p) {
wpa_printf(MSG_DEBUG,
"FT: Failed to write AssocResp IEs");
@@ -3666,10 +3842,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
-#ifdef CONFIG_IEEE80211N
p = hostapd_eid_ht_capabilities(hapd, p);
p = hostapd_eid_ht_operation(hapd, p);
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
@@ -3701,6 +3875,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_he_operation(hapd, p);
p = hostapd_eid_spatial_reuse(hapd, p);
p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
+ p = hostapd_eid_he_6ghz_band_cap(hapd, p);
}
#endif /* CONFIG_IEEE80211AX */
@@ -3717,12 +3892,29 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
}
#endif /* CONFIG_FST */
- p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->rsnxe_override_ft &&
+ buf + buflen - p >=
+ (long int) wpabuf_len(hapd->conf->rsnxe_override_ft) &&
+ sta && sta->auth_alg == WLAN_AUTH_FT) {
+ wpa_printf(MSG_DEBUG, "TESTING: RSNXE FT override");
+ os_memcpy(p, wpabuf_head(hapd->conf->rsnxe_override_ft),
+ wpabuf_len(hapd->conf->rsnxe_override_ft));
+ p += wpabuf_len(hapd->conf->rsnxe_override_ft);
+ goto rsnxe_done;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (!omit_rsnxe)
+ p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
+#ifdef CONFIG_TESTING_OPTIONS
+rsnxe_done:
+#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_OWE
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
- wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
+ wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
+ !wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
struct wpabuf *pub;
pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
@@ -3743,7 +3935,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
#endif /* CONFIG_OWE */
#ifdef CONFIG_DPP2
- if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
+ if (DPP_VERSION > 1 && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS &&
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) {
os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie),
@@ -3848,7 +4040,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
}
#endif /* CONFIG_FILS */
- if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, reply, send_len, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
strerror(errno));
res = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3863,12 +4055,12 @@ done:
#ifdef CONFIG_OWE
u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *owe_dh, u8 owe_dh_len,
- u8 *owe_buf, size_t owe_buf_len, u16 *reason)
+ u8 *owe_buf, size_t owe_buf_len, u16 *status)
{
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->conf->own_ie_override) {
wpa_printf(MSG_DEBUG, "OWE: Using IE override");
- *reason = WLAN_STATUS_SUCCESS;
+ *status = WLAN_STATUS_SUCCESS;
return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
owe_buf_len, NULL, 0);
}
@@ -3878,18 +4070,18 @@ u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
owe_buf_len, NULL, 0);
- *reason = WLAN_STATUS_SUCCESS;
+ *status = WLAN_STATUS_SUCCESS;
return owe_buf;
}
if (sta->owe_pmk && sta->external_dh_updated) {
wpa_printf(MSG_DEBUG, "OWE: Using previously derived PMK");
- *reason = WLAN_STATUS_SUCCESS;
+ *status = WLAN_STATUS_SUCCESS;
return owe_buf;
}
- *reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
- if (*reason != WLAN_STATUS_SUCCESS)
+ *status = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
+ if (*status != WLAN_STATUS_SUCCESS)
return NULL;
owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
@@ -3900,7 +4092,7 @@ u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
if (!pub) {
- *reason = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ *status = WLAN_STATUS_UNSPECIFIED_FAILURE;
return owe_buf;
}
@@ -3935,7 +4127,7 @@ void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
sta->fils_pending_assoc_is_reassoc,
sta->fils_pending_assoc_req,
- sta->fils_pending_assoc_req_len, 0);
+ sta->fils_pending_assoc_req_len, 0, 0);
os_free(sta->fils_pending_assoc_req);
sta->fils_pending_assoc_req = NULL;
sta->fils_pending_assoc_req_len = 0;
@@ -3975,17 +4167,16 @@ static void handle_assoc(struct hostapd_data *hapd,
int reassoc, int rssi)
{
u16 capab_info, listen_interval, seq_ctrl, fc;
- u16 resp = WLAN_STATUS_SUCCESS, reply_res;
+ int resp = WLAN_STATUS_SUCCESS;
+ u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
const u8 *pos;
int left, i;
struct sta_info *sta;
u8 *tmp = NULL;
- struct hostapd_sta_wpa_psk_short *psk = NULL;
- char *identity = NULL;
- char *radius_cui = NULL;
#ifdef CONFIG_FILS
int delay_assoc = 0;
#endif /* CONFIG_FILS */
+ int omit_rsnxe = 0;
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
sizeof(mgmt->u.assoc_req))) {
@@ -4062,13 +4253,11 @@ static void handle_assoc(struct hostapd_data *hapd,
hapd->iface->current_mode->mode ==
HOSTAPD_MODE_IEEE80211AD) {
int acl_res;
- u32 session_timeout, acct_interim_interval;
- struct vlan_description vlan_id;
+ struct radius_sta info;
- acl_res = ieee802_11_allowed_address(
- hapd, mgmt->sa, (const u8 *) mgmt, len,
- &session_timeout, &acct_interim_interval,
- &vlan_id, &psk, &identity, &radius_cui, 0);
+ acl_res = ieee802_11_allowed_address(hapd, mgmt->sa,
+ (const u8 *) mgmt,
+ len, &info);
if (acl_res == HOSTAPD_ACL_REJECT) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Ignore Association Request frame from "
@@ -4093,9 +4282,7 @@ static void handle_assoc(struct hostapd_data *hapd,
}
acl_res = ieee802_11_set_radius_info(
- hapd, sta, acl_res, session_timeout,
- acct_interim_interval, &vlan_id, &psk,
- &identity, &radius_cui);
+ hapd, sta, acl_res, &info);
if (acl_res) {
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
@@ -4202,6 +4389,7 @@ static void handle_assoc(struct hostapd_data *hapd,
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
if (resp != WLAN_STATUS_SUCCESS)
goto fail;
+ omit_rsnxe = !get_ie(pos, left, WLAN_EID_RSNX);
if (hostapd_get_aid(hapd, sta) < 0) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@@ -4254,9 +4442,7 @@ static void handle_assoc(struct hostapd_data *hapd,
ieee802_11_set_beacons(hapd->iface);
}
-#ifdef CONFIG_IEEE80211N
update_ht_state(hapd, sta);
-#endif /* CONFIG_IEEE80211N */
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
@@ -4296,9 +4482,6 @@ static void handle_assoc(struct hostapd_data *hapd,
#endif /* CONFIG_FILS */
fail:
- os_free(identity);
- os_free(radius_cui);
- hostapd_free_psk_list(psk);
/*
* In case of a successful response, add the station to the driver.
@@ -4359,12 +4542,13 @@ static void handle_assoc(struct hostapd_data *hapd,
}
#endif /* CONFIG_FILS */
- reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
- left, rssi);
+ if (resp >= 0)
+ reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc,
+ pos, left, rssi, omit_rsnxe);
os_free(tmp);
/*
- * Remove the station in case tranmission of a success response fails
+ * Remove the station in case transmission of a success response fails
* (the STA was added associated to the driver) or if the station was
* previously added unassociated.
*/
@@ -4401,6 +4585,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
ap_sta_set_authorized(hapd, sta, 0);
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
+ hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated");
@@ -4467,6 +4652,7 @@ static void handle_deauth(struct hostapd_data *hapd,
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
WLAN_STA_ASSOC_REQ_OK);
+ hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "deauthenticated");
@@ -4598,14 +4784,12 @@ static int handle_action(struct hostapd_data *hapd,
#endif /* CONFIG_FST */
case WLAN_ACTION_PUBLIC:
case WLAN_ACTION_PROTECTED_DUAL:
-#ifdef CONFIG_IEEE80211N
if (len >= IEEE80211_HDRLEN + 2 &&
mgmt->u.action.u.public_action.action ==
WLAN_PA_20_40_BSS_COEX) {
hostapd_2040_coex_action(hapd, mgmt, len);
return 1;
}
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_DPP
if (len >= IEEE80211_HDRLEN + 6 &&
mgmt->u.action.u.vs_public_action.action ==
@@ -4688,7 +4872,7 @@ static int handle_action(struct hostapd_data *hapd,
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
resp->u.action.category |= 0x80;
- if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, resp, len, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
"Action frame");
}
@@ -4765,6 +4949,11 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
return 0;
}
+ if (hapd->iface->state != HAPD_IFACE_ENABLED) {
+ wpa_printf(MSG_DEBUG, "MGMT: Ignore management frame while interface is not enabled (SA=" MACSTR " DA=" MACSTR " subtype=%u)",
+ MAC2STR(mgmt->sa), MAC2STR(mgmt->da), stype);
+ return 1;
+ }
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
handle_probe_req(hapd, mgmt, len, ssi_signal);
@@ -4880,6 +5069,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
struct sta_info *sta,
char *ifname_wds)
{
+#ifdef CONFIG_WEP
int i;
struct hostapd_ssid *ssid = &hapd->conf->ssid;
@@ -4889,14 +5079,18 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
for (i = 0; i < 4; i++) {
if (ssid->wep.key[i] &&
hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
- i == ssid->wep.idx, NULL, 0,
- ssid->wep.key[i], ssid->wep.len[i])) {
+ 0, i == ssid->wep.idx, NULL, 0,
+ ssid->wep.key[i], ssid->wep.len[i],
+ i == ssid->wep.idx ?
+ KEY_FLAG_GROUP_RX_TX_DEFAULT :
+ KEY_FLAG_GROUP_RX_TX)) {
wpa_printf(MSG_WARNING,
"Could not set WEP keys for WDS interface; %s",
ifname_wds);
break;
}
}
+#endif /* CONFIG_WEP */
}
@@ -5394,4 +5588,57 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
}
+u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 bw, chan1, chan2 = 0;
+ int freq1;
+
+ if (!hapd->cs_freq_params.channel ||
+ (!hapd->cs_freq_params.vht_enabled &&
+ !hapd->cs_freq_params.he_enabled))
+ return eid;
+
+ /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */
+ switch (hapd->cs_freq_params.bandwidth) {
+ case 40:
+ bw = 0;
+ break;
+ case 80:
+ /* check if it's 80+80 */
+ if (!hapd->cs_freq_params.center_freq2)
+ bw = 1;
+ else
+ bw = 3;
+ break;
+ case 160:
+ bw = 2;
+ break;
+ default:
+ /* not valid VHT bandwidth or not in CSA */
+ return eid;
+ }
+
+ freq1 = hapd->cs_freq_params.center_freq1 ?
+ hapd->cs_freq_params.center_freq1 :
+ hapd->cs_freq_params.freq;
+ if (ieee80211_freq_to_chan(freq1, &chan1) !=
+ HOSTAPD_MODE_IEEE80211A)
+ return eid;
+
+ if (hapd->cs_freq_params.center_freq2 &&
+ ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2,
+ &chan2) != HOSTAPD_MODE_IEEE80211A)
+ return eid;
+
+ *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER;
+ *eid++ = 5; /* Length of Channel Switch Wrapper */
+ *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH;
+ *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
+ *eid++ = bw; /* New Channel Width */
+ *eid++ = chan1; /* New Channel Center Frequency Segment 0 */
+ *eid++ = chan2; /* New Channel Center Frequency Segment 1 */
+
+ return eid;
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index f592da5..ea8c608 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -16,8 +16,7 @@ struct hostapd_frame_info;
struct ieee80211_ht_capabilities;
struct ieee80211_vht_capabilities;
struct ieee80211_mgmt;
-struct vlan_description;
-struct hostapd_sta_wpa_psk_short;
+struct radius_sta;
enum ieee80211_op_mode;
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
@@ -50,9 +49,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
+ size_t len);
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
-u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
@@ -63,6 +63,7 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid);
int hostapd_ht_operation_update(struct hostapd_iface *iface);
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
@@ -95,6 +96,10 @@ u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
enum ieee80211_op_mode opmode, const u8 *he_capab,
size_t he_capab_len);
+u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *he_6ghz_capab);
+int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
+ enum ieee80211_op_mode mode);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
@@ -162,7 +167,7 @@ void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
const u8 *msk, size_t msk_len);
u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *owe_dh, u8 owe_dh_len,
- u8 *owe_buf, size_t owe_buf_len, u16 *reason);
+ u8 *owe_buf, size_t owe_buf_len, u16 *status);
u16 owe_process_rsn_ie(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *rsn_ie, size_t rsn_ie_len,
const u8 *owe_dh, size_t owe_dh_len);
@@ -180,13 +185,9 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd);
u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len);
-int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
- const u8 *msg, size_t len, u32 *session_timeout,
- u32 *acct_interim_interval,
- struct vlan_description *vlan_id,
- struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui,
- int is_probe_req);
+
+size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd);
+u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len);
int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
int ap_seg1_idx, int *bandwidth, int *seg1_idx);
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 931d4d0..783ee6d 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -32,12 +32,7 @@ struct hostapd_cached_radius_acl {
macaddr addr;
int accepted; /* HOSTAPD_ACL_* */
struct hostapd_cached_radius_acl *next;
- u32 session_timeout;
- u32 acct_interim_interval;
- struct vlan_description vlan_id;
- struct hostapd_sta_wpa_psk_short *psk;
- char *identity;
- char *radius_cui;
+ struct radius_sta info;
};
@@ -54,9 +49,9 @@ struct hostapd_acl_query_data {
#ifndef CONFIG_NO_RADIUS
static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
{
- os_free(e->identity);
- os_free(e->radius_cui);
- hostapd_free_psk_list(e->psk);
+ os_free(e->info.identity);
+ os_free(e->info.radius_cui);
+ hostapd_free_psk_list(e->info.psk);
os_free(e);
}
@@ -73,25 +68,8 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
}
-static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
- struct hostapd_sta_wpa_psk_short *src)
-{
- if (!psk)
- return;
-
- if (src)
- src->ref++;
-
- *psk = src;
-}
-
-
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
- u32 *session_timeout,
- u32 *acct_interim_interval,
- struct vlan_description *vlan_id,
- struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui)
+ struct radius_sta *out)
{
struct hostapd_cached_radius_acl *entry;
struct os_reltime now;
@@ -105,27 +83,8 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
if (os_reltime_expired(&now, &entry->timestamp,
RADIUS_ACL_TIMEOUT))
return -1; /* entry has expired */
- if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
- if (session_timeout)
- *session_timeout = entry->session_timeout;
- if (acct_interim_interval)
- *acct_interim_interval =
- entry->acct_interim_interval;
- if (vlan_id)
- *vlan_id = entry->vlan_id;
- copy_psk_list(psk, entry->psk);
- if (identity) {
- if (entry->identity)
- *identity = os_strdup(entry->identity);
- else
- *identity = NULL;
- }
- if (radius_cui) {
- if (entry->radius_cui)
- *radius_cui = os_strdup(entry->radius_cui);
- else
- *radius_cui = NULL;
- }
+ *out = entry->info;
+
return entry->accepted;
}
@@ -238,42 +197,28 @@ int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
* @addr: MAC address of the STA
* @msg: Authentication message
* @len: Length of msg in octets
- * @session_timeout: Buffer for returning session timeout (from RADIUS)
- * @acct_interim_interval: Buffer for returning account interval (from RADIUS)
- * @vlan_id: Buffer for returning VLAN ID
- * @psk: Linked list buffer for returning WPA PSK
- * @identity: Buffer for returning identity (from RADIUS)
- * @radius_cui: Buffer for returning CUI (from RADIUS)
+ * @out.session_timeout: Buffer for returning session timeout (from RADIUS)
+ * @out.acct_interim_interval: Buffer for returning account interval (from
+ * RADIUS)
+ * @out.vlan_id: Buffer for returning VLAN ID
+ * @out.psk: Linked list buffer for returning WPA PSK
+ * @out.identity: Buffer for returning identity (from RADIUS)
+ * @out.radius_cui: Buffer for returning CUI (from RADIUS)
* @is_probe_req: Whether this query for a Probe Request frame
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
*
- * The caller is responsible for freeing the returned *identity and *radius_cui
- * values with os_free().
+ * The caller is responsible for properly cloning the returned out->identity and
+ * out->radius_cui and out->psk values.
*/
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
- const u8 *msg, size_t len, u32 *session_timeout,
- u32 *acct_interim_interval,
- struct vlan_description *vlan_id,
- struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui,
+ const u8 *msg, size_t len, struct radius_sta *out,
int is_probe_req)
{
int res;
- if (session_timeout)
- *session_timeout = 0;
- if (acct_interim_interval)
- *acct_interim_interval = 0;
- if (vlan_id)
- os_memset(vlan_id, 0, sizeof(*vlan_id));
- if (psk)
- *psk = NULL;
- if (identity)
- *identity = NULL;
- if (radius_cui)
- *radius_cui = NULL;
-
- res = hostapd_check_acl(hapd, addr, vlan_id);
+ os_memset(out, 0, sizeof(*out));
+
+ res = hostapd_check_acl(hapd, addr, &out->vlan_id);
if (res != HOSTAPD_ACL_PENDING)
return res;
@@ -290,12 +235,10 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
};
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
- vlan_id = NULL;
+ os_memset(&out->vlan_id, 0, sizeof(out->vlan_id));
/* Check whether ACL cache has an entry for this station */
- res = hostapd_acl_cache_get(hapd, addr, session_timeout,
- acct_interim_interval, vlan_id, psk,
- identity, radius_cui);
+ res = hostapd_acl_cache_get(hapd, addr, out);
if (res == HOSTAPD_ACL_ACCEPT ||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
return res;
@@ -307,14 +250,6 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
/* pending query in RADIUS retransmit queue;
* do not generate a new one */
- if (identity) {
- os_free(*identity);
- *identity = NULL;
- }
- if (radius_cui) {
- os_free(*radius_cui);
- *radius_cui = NULL;
- }
return HOSTAPD_ACL_PENDING;
}
query = query->next;
@@ -488,8 +423,8 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
passphraselen);
psk->is_passphrase = 1;
}
- psk->next = cache->psk;
- cache->psk = psk;
+ psk->next = cache->info.psk;
+ cache->info.psk = psk;
psk = NULL;
}
skip:
@@ -518,6 +453,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
struct hostapd_data *hapd = data;
struct hostapd_acl_query_data *query, *prev;
struct hostapd_cached_radius_acl *cache;
+ struct radius_sta *info;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
query = hapd->acl_queries;
@@ -555,65 +491,66 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
}
os_get_reltime(&cache->timestamp);
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
+ info = &cache->info;
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
u8 *buf;
size_t len;
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
- &cache->session_timeout) == 0)
+ &info->session_timeout) == 0)
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
else
cache->accepted = HOSTAPD_ACL_ACCEPT;
if (radius_msg_get_attr_int32(
msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
- &cache->acct_interim_interval) == 0 &&
- cache->acct_interim_interval < 60) {
+ &info->acct_interim_interval) == 0 &&
+ info->acct_interim_interval < 60) {
wpa_printf(MSG_DEBUG, "Ignored too small "
"Acct-Interim-Interval %d for STA " MACSTR,
- cache->acct_interim_interval,
+ info->acct_interim_interval,
MAC2STR(query->addr));
- cache->acct_interim_interval = 0;
+ info->acct_interim_interval = 0;
}
if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED)
- cache->vlan_id.notempty = !!radius_msg_get_vlanid(
- msg, &cache->vlan_id.untagged,
- MAX_NUM_TAGGED_VLAN, cache->vlan_id.tagged);
+ info->vlan_id.notempty = !!radius_msg_get_vlanid(
+ msg, &info->vlan_id.untagged,
+ MAX_NUM_TAGGED_VLAN, info->vlan_id.tagged);
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
msg, req, cache);
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
&buf, &len, NULL) == 0) {
- cache->identity = os_zalloc(len + 1);
- if (cache->identity)
- os_memcpy(cache->identity, buf, len);
+ info->identity = os_zalloc(len + 1);
+ if (info->identity)
+ os_memcpy(info->identity, buf, len);
}
if (radius_msg_get_attr_ptr(
msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
&buf, &len, NULL) == 0) {
- cache->radius_cui = os_zalloc(len + 1);
- if (cache->radius_cui)
- os_memcpy(cache->radius_cui, buf, len);
+ info->radius_cui = os_zalloc(len + 1);
+ if (info->radius_cui)
+ os_memcpy(info->radius_cui, buf, len);
}
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
- !cache->psk)
+ !info->psk)
cache->accepted = HOSTAPD_ACL_REJECT;
- if (cache->vlan_id.notempty &&
- !hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) {
+ if (info->vlan_id.notempty &&
+ !hostapd_vlan_valid(hapd->conf->vlan, &info->vlan_id)) {
hostapd_logger(hapd, query->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Invalid VLAN %d%s received from RADIUS server",
- cache->vlan_id.untagged,
- cache->vlan_id.tagged[0] ? "+" : "");
- os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id));
+ info->vlan_id.untagged,
+ info->vlan_id.tagged[0] ? "+" : "");
+ os_memset(&info->vlan_id, 0, sizeof(info->vlan_id));
}
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
- !cache->vlan_id.notempty)
+ !info->vlan_id.notempty)
cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
@@ -622,7 +559,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
#ifdef CONFIG_DRIVER_RADIUS_ACL
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
- cache->session_timeout);
+ info->session_timeout);
#else /* CONFIG_DRIVER_RADIUS_ACL */
#ifdef NEED_AP_MLME
/* Re-send original authentication frame for 802.11 processing */
@@ -685,6 +622,19 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
}
+void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
+ struct hostapd_sta_wpa_psk_short *src)
+{
+ if (!psk)
+ return;
+
+ if (src)
+ src->ref++;
+
+ *psk = src;
+}
+
+
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
{
if (psk && psk->ref) {
diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h
index 5aece51..9410f55 100644
--- a/src/ap/ieee802_11_auth.h
+++ b/src/ap/ieee802_11_auth.h
@@ -16,18 +16,25 @@ enum {
HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
};
+struct radius_sta {
+ u32 session_timeout;
+ u32 acct_interim_interval;
+ struct vlan_description vlan_id;
+ struct hostapd_sta_wpa_psk_short *psk;
+ char *identity;
+ char *radius_cui;
+};
+
int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
struct vlan_description *vlan_id);
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
- const u8 *msg, size_t len, u32 *session_timeout,
- u32 *acct_interim_interval,
- struct vlan_description *vlan_id,
- struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui,
+ const u8 *msg, size_t len, struct radius_sta *out,
int is_probe_req);
int hostapd_acl_init(struct hostapd_data *hapd);
void hostapd_acl_deinit(struct hostapd_data *hapd);
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
void hostapd_acl_expire(struct hostapd_data *hapd);
+void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
+ struct hostapd_sta_wpa_psk_short *src);
#endif /* IEEE802_11_AUTH_H */
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index abd3940..85b7140 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -192,9 +192,12 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
params |= (hapd->iface->conf->he_op.he_rts_threshold <<
HE_OPERATION_RTS_THRESHOLD_OFFSET);
- if (hapd->iface->conf->he_op.he_bss_color)
- params |= (hapd->iface->conf->he_op.he_bss_color <<
- HE_OPERATION_BSS_COLOR_OFFSET);
+ if (hapd->iface->conf->he_op.he_bss_color_disabled)
+ params |= HE_OPERATION_BSS_COLOR_DISABLED;
+ if (hapd->iface->conf->he_op.he_bss_color_partial)
+ params |= HE_OPERATION_BSS_COLOR_PARTIAL;
+ params |= hapd->iface->conf->he_op.he_bss_color <<
+ HE_OPERATION_BSS_COLOR_OFFSET;
/* HE minimum required basic MCS and NSS for STAs */
oper->he_mcs_nss_set =
@@ -206,17 +209,25 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
if (is_6ghz_op_class(hapd->iconf->op_class)) {
u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
+ u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
if (!seg0)
seg0 = hapd->iconf->channel;
params |= HE_OPERATION_6GHZ_OPER_INFO;
+
+ /* 6 GHz Operation Information field */
*pos++ = hapd->iconf->channel; /* Primary Channel */
- *pos++ = center_idx_to_bw_6ghz(seg0); /* Control: Channel Width
- */
- /* Channel Center Freq Seg0/Seg0 */
+
+ /* Control: Channel Width */
+ if (seg1)
+ *pos++ = 3;
+ else
+ *pos++ = center_idx_to_bw_6ghz(seg0);
+
+ /* Channel Center Freq Seg0/Seg1 */
*pos++ = seg0;
- *pos++ = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
+ *pos++ = seg1;
/* Minimum Rate */
*pos++ = 6; /* TODO: what should be set here? */
}
@@ -300,6 +311,35 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid)
}
+u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid)
+{
+ struct hostapd_hw_modes *mode = hapd->iface->current_mode;
+ struct he_capabilities *he_cap;
+ struct ieee80211_he_6ghz_band_cap *cap;
+ u16 capab;
+ u8 *pos;
+
+ if (!mode || !is_6ghz_op_class(hapd->iconf->op_class) ||
+ !is_6ghz_freq(hapd->iface->freq))
+ return eid;
+
+ he_cap = &mode->he_capab[IEEE80211_MODE_AP];
+ capab = he_cap->he_6ghz_capa;
+ capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED;
+
+ pos = eid;
+ *pos++ = WLAN_EID_EXTENSION;
+ *pos++ = 1 + sizeof(*cap);
+ *pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP;
+
+ cap = (struct ieee80211_he_6ghz_band_cap *) pos;
+ cap->capab = host_to_le16(capab);
+ pos += sizeof(*cap);
+
+ return pos;
+}
+
+
void hostapd_get_he_capab(struct hostapd_data *hapd,
const struct ieee80211_he_capabilities *he_cap,
struct ieee80211_he_capabilities *neg_he_cap,
@@ -402,3 +442,44 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS;
}
+
+
+u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *he_6ghz_capab)
+{
+ if (!he_6ghz_capab || !hapd->iconf->ieee80211ax ||
+ !is_6ghz_op_class(hapd->iconf->op_class)) {
+ sta->flags &= ~WLAN_STA_6GHZ;
+ os_free(sta->he_6ghz_capab);
+ sta->he_6ghz_capab = NULL;
+ return WLAN_STATUS_SUCCESS;
+ }
+
+ if (!sta->he_6ghz_capab) {
+ sta->he_6ghz_capab =
+ os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap));
+ if (!sta->he_6ghz_capab)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+ sta->flags |= WLAN_STA_6GHZ;
+ os_memcpy(sta->he_6ghz_capab, he_6ghz_capab,
+ sizeof(struct ieee80211_he_6ghz_band_cap));
+
+ return WLAN_STATUS_SUCCESS;
+}
+
+
+int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
+ enum ieee80211_op_mode mode)
+{
+ u8 *mac_cap;
+
+ if (!hapd->iface->current_mode ||
+ !hapd->iface->current_mode->he_capab[mode].he_supported)
+ return 0;
+
+ mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
+
+ return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER);
+}
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 6db9365..59ecbdc 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -109,33 +109,9 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
}
-u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
-{
- u8 sec_ch;
-
- if (!hapd->cs_freq_params.channel ||
- !hapd->cs_freq_params.sec_channel_offset ||
- is_6ghz_op_class(hapd->iconf->op_class))
- return eid;
-
- if (hapd->cs_freq_params.sec_channel_offset == -1)
- sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
- else if (hapd->cs_freq_params.sec_channel_offset == 1)
- sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
- else
- return eid;
-
- *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
- *eid++ = 1;
- *eid++ = sec_ch;
-
- return eid;
-}
-
-
/*
op_mode
-Set to 0 (HT pure) under the followign conditions
+Set to 0 (HT pure) under the following conditions
- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
Set to 1 (HT non-member protection) if there may be non-HT STAs
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index f24963e..17003d5 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -11,6 +11,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/ocv.h"
+#include "common/wpa_ctrl.h"
#include "hostapd.h"
#include "sta_info.h"
#include "ap_config.h"
@@ -72,6 +73,16 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
"Failed to get channel info for OCI element in SA Query Request");
return;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->oci_freq_override_saquery_req) {
+ wpa_printf(MSG_INFO,
+ "TEST: Override OCI frequency %d -> %u MHz",
+ ci.frequency,
+ hapd->conf->oci_freq_override_saquery_req);
+ ci.frequency =
+ hapd->conf->oci_freq_override_saquery_req;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len);
@@ -112,7 +123,8 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
end += oci_ie_len;
}
#endif /* CONFIG_OCV */
- if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0) < 0)
+ if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0, NULL, 0, 0)
+ < 0)
wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed");
os_free(mgmt);
@@ -150,6 +162,16 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
"Failed to get channel info for OCI element in SA Query Response");
return;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->oci_freq_override_saquery_resp) {
+ wpa_printf(MSG_INFO,
+ "TEST: Override OCI frequency %d -> %u MHz",
+ ci.frequency,
+ hapd->conf->oci_freq_override_saquery_resp);
+ ci.frequency =
+ hapd->conf->oci_freq_override_saquery_resp;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len);
@@ -193,7 +215,8 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
end += oci_ie_len;
}
#endif /* CONFIG_OCV */
- if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0) < 0)
+ if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0, NULL, 0, 0)
+ < 0)
wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed");
os_free(resp);
@@ -252,14 +275,21 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd,
return;
if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
- tx_chanwidth, tx_seg1_idx) != 0) {
- wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
+ tx_chanwidth, tx_seg1_idx) !=
+ OCI_SUCCESS) {
+ wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr="
+ MACSTR " frame=saquery%s error=%s",
+ MAC2STR(sa),
+ action_type == WLAN_SA_QUERY_REQUEST ?
+ "req" : "resp", ocv_errorstr);
return;
}
}
#endif /* CONFIG_OCV */
if (action_type == WLAN_SA_QUERY_REQUEST) {
+ if (sta)
+ sta->post_csa_sa_query = 0;
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
return;
}
@@ -375,6 +405,11 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
*pos |= 0x01;
#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211AX
+ if (hapd->iconf->ieee80211ax &&
+ hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
+ *pos |= 0x40; /* Bit 78 - TWT responder */
+#endif /* CONFIG_IEEE80211AX */
break;
case 10: /* Bits 80-87 */
#ifdef CONFIG_SAE
@@ -390,6 +425,16 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
* Identifiers Used Exclusively */
}
#endif /* CONFIG_SAE */
+ if (hapd->conf->beacon_prot)
+ *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
+ break;
+ case 11: /* Bits 88-95 */
+#ifdef CONFIG_SAE_PK
+ if (hapd->conf->wpa &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+ hostapd_sae_pk_exclusively(hapd->conf))
+ *pos |= 0x01; /* Bit 88 - SAE PK Exclusively */
+#endif /* CONFIG_SAE_PK */
break;
}
}
@@ -400,14 +445,22 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
u8 *pos = eid;
u8 len = 0, i;
- if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
+ if (hapd->conf->qos_map_set_len ||
+ (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
len = 5;
- if (len < 4 && hapd->conf->interworking)
+ if (len < 4 &&
+ (hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
len = 4;
- if (len < 3 && hapd->conf->wnm_sleep_mode)
+ if (len < 3 &&
+ (hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
len = 3;
- if (len < 1 && hapd->iconf->obss_interval)
+ if (len < 1 &&
+ (hapd->iconf->obss_interval ||
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
len = 1;
+ if (len < 2 &&
+ (hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
+ len = 2;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
if (len < 9 &&
@@ -430,12 +483,25 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
!wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
len = 10;
#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211AX
+ if (len < 10 && hapd->iconf->ieee80211ax &&
+ hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
+ len = 10;
+#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_SAE
if (len < 11 && hapd->conf->wpa &&
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
hostapd_sae_pw_id_in_use(hapd->conf))
len = 11;
#endif /* CONFIG_SAE */
+ if (len < 11 && hapd->conf->beacon_prot)
+ len = 11;
+#ifdef CONFIG_SAE_PK
+ if (len < 12 && hapd->conf->wpa &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+ hostapd_sae_pk_exclusively(hapd->conf))
+ len = 12;
+#endif /* CONFIG_SAE_PK */
if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len;
if (len == 0)
@@ -850,6 +916,35 @@ u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid,
}
+size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd)
+{
+#ifdef CONFIG_DPP2
+ if (hapd->conf->dpp_configurator_connectivity)
+ return 6;
+#endif /* CONFIG_DPP2 */
+ return 0;
+}
+
+
+u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len)
+{
+ u8 *pos = eid;
+
+#ifdef CONFIG_DPP2
+ if (!hapd->conf->dpp_configurator_connectivity || len < 6)
+ return pos;
+
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4;
+ WPA_PUT_BE24(pos, OUI_WFA);
+ pos += 3;
+ *pos++ = DPP_CC_OUI_TYPE;
+#endif /* CONFIG_DPP2 */
+
+ return pos;
+}
+
+
void ap_copy_sta_supp_op_classes(struct sta_info *sta,
const u8 *supp_op_classes,
size_t supp_op_classes_len)
@@ -1001,9 +1096,17 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
{
u8 *pos = eid;
+ bool sae_pk = false;
+
+#ifdef CONFIG_SAE_PK
+ sae_pk = hostapd_sae_pk_in_use(hapd->conf);
+#endif /* CONFIG_SAE_PK */
if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
- (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2) ||
+ !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
+ (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 &&
+ !hostapd_sae_pw_id_in_use(hapd->conf) && !sae_pk) ||
+ hapd->conf->sae_pwe == 3 ||
len < 3)
return pos;
@@ -1011,7 +1114,12 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
*pos++ = 1;
/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
* used for now */
- *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+ *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+#ifdef CONFIG_SAE_PK
+ if (sae_pk)
+ *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
+#endif /* CONFIG_SAE_PK */
+ pos++;
return pos;
}
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index f50f142..c925bf1 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -167,59 +167,6 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
}
-u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
-{
- u8 bw, chan1, chan2 = 0;
- int freq1;
-
- if (!hapd->cs_freq_params.channel ||
- !hapd->cs_freq_params.vht_enabled)
- return eid;
-
- /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */
- switch (hapd->cs_freq_params.bandwidth) {
- case 40:
- bw = 0;
- break;
- case 80:
- /* check if it's 80+80 */
- if (!hapd->cs_freq_params.center_freq2)
- bw = 1;
- else
- bw = 3;
- break;
- case 160:
- bw = 2;
- break;
- default:
- /* not valid VHT bandwidth or not in CSA */
- return eid;
- }
-
- freq1 = hapd->cs_freq_params.center_freq1 ?
- hapd->cs_freq_params.center_freq1 :
- hapd->cs_freq_params.freq;
- if (ieee80211_freq_to_chan(freq1, &chan1) !=
- HOSTAPD_MODE_IEEE80211A)
- return eid;
-
- if (hapd->cs_freq_params.center_freq2 &&
- ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2,
- &chan2) != HOSTAPD_MODE_IEEE80211A)
- return eid;
-
- *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER;
- *eid++ = 5; /* Length of Channel Switch Wrapper */
- *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH;
- *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
- *eid++ = bw; /* New Channel Width */
- *eid++ = chan1; /* New Channel Center Frequency Segment 0 */
- *eid++ = chan2; /* New Channel Center Frequency Segment 1 */
-
- return eid;
-}
-
-
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
{
struct hostapd_iface *iface = hapd->iface;
@@ -425,7 +372,9 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
- if (!hapd->iface->current_mode)
+ /* Vendor VHT is applicable only to 2.4 GHz */
+ if (!hapd->iface->current_mode ||
+ hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
return eid;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index d081031..ee095f6 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -137,6 +137,7 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
}
+#ifdef CONFIG_WEP
#ifndef CONFIG_FIPS
#ifndef CONFIG_NO_RC4
@@ -284,8 +285,9 @@ static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
/* TODO: set encryption in TX callback, i.e., only after STA
* has ACKed EAPOL-Key frame */
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
- sta->addr, 0, 1, NULL, 0, ikey,
- hapd->conf->individual_wep_key_len)) {
+ sta->addr, 0, 0, 1, NULL, 0, ikey,
+ hapd->conf->individual_wep_key_len,
+ KEY_FLAG_PAIRWISE_RX_TX)) {
wpa_printf(MSG_ERROR,
"Could not set individual WEP encryption");
}
@@ -296,6 +298,7 @@ static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
#endif /* CONFIG_NO_RC4 */
#endif /* CONFIG_FIPS */
+#endif /* CONFIG_WEP */
const char *radius_mode_txt(struct hostapd_data *hapd)
@@ -875,7 +878,7 @@ static void handle_eap_response(struct hostapd_data *hapd,
wpabuf_free(sm->eap_if->eapRespData);
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
- sm->eapolEap = TRUE;
+ sm->eapolEap = true;
}
@@ -906,7 +909,7 @@ static void handle_eap_initiate(struct hostapd_data *hapd,
wpabuf_free(sm->eap_if->eapRespData);
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
- sm->eapolEap = TRUE;
+ sm->eapolEap = true;
#endif /* CONFIG_ERP */
}
@@ -1137,7 +1140,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
}
#endif /* CONFIG_WPS */
- sta->eapol_sm->eap_if->portEnabled = TRUE;
+ sta->eapol_sm->eap_if->portEnabled = true;
}
/* since we support version 1, we can ignore version field and proceed
@@ -1164,7 +1167,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
"cached PMKSA available - ignore it since STA sent EAPOL-Start");
wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa);
}
- sta->eapol_sm->eapolStart = TRUE;
+ sta->eapol_sm->eapolStart = true;
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
eap_server_clear_identity(sta->eapol_sm->eap);
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
@@ -1177,7 +1180,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
accounting_sta_stop(hapd, sta);
- sta->eapol_sm->eapolLogoff = TRUE;
+ sta->eapol_sm->eapolLogoff = true;
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
eap_server_clear_identity(sta->eapol_sm->eap);
break;
@@ -1294,7 +1297,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
}
#endif /* CONFIG_WPS */
- sta->eapol_sm->eap_if->portEnabled = TRUE;
+ sta->eapol_sm->eap_if->portEnabled = true;
#ifdef CONFIG_IEEE80211R_AP
if (sta->auth_alg == WLAN_AUTH_FT) {
@@ -1303,13 +1306,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
"PMK from FT - skip IEEE 802.1X/EAP");
/* Setup EAPOL state machines to already authenticated state
* because of existing FT information from R0KH. */
- sta->eapol_sm->keyRun = TRUE;
- sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
+ sta->eapol_sm->keyRun = true;
+ sta->eapol_sm->eap_if->eapKeyAvailable = true;
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
- sta->eapol_sm->authSuccess = TRUE;
- sta->eapol_sm->authFail = FALSE;
- sta->eapol_sm->portValid = TRUE;
+ sta->eapol_sm->authSuccess = true;
+ sta->eapol_sm->authFail = false;
+ sta->eapol_sm->portValid = true;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
ap_sta_bind_vlan(hapd, sta);
@@ -1326,13 +1329,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
"PMK from FILS - skip IEEE 802.1X/EAP");
/* Setup EAPOL state machines to already authenticated state
* because of existing FILS information. */
- sta->eapol_sm->keyRun = TRUE;
- sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
+ sta->eapol_sm->keyRun = true;
+ sta->eapol_sm->eap_if->eapKeyAvailable = true;
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
- sta->eapol_sm->authSuccess = TRUE;
- sta->eapol_sm->authFail = FALSE;
- sta->eapol_sm->portValid = TRUE;
+ sta->eapol_sm->authSuccess = true;
+ sta->eapol_sm->authFail = false;
+ sta->eapol_sm->portValid = true;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
wpa_auth_set_ptk_rekey_timer(sta->wpa_sm);
@@ -1347,12 +1350,12 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
"PMK from PMKSA cache - skip IEEE 802.1X/EAP");
/* Setup EAPOL state machines to already authenticated state
* because of existing PMKSA information in the cache. */
- sta->eapol_sm->keyRun = TRUE;
- sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
+ sta->eapol_sm->keyRun = true;
+ sta->eapol_sm->eap_if->eapKeyAvailable = true;
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
- sta->eapol_sm->authSuccess = TRUE;
- sta->eapol_sm->authFail = FALSE;
+ sta->eapol_sm->authSuccess = true;
+ sta->eapol_sm->authFail = false;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
pmksa_cache_to_eapol_data(hapd, pmksa, sta->eapol_sm);
@@ -1364,7 +1367,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
* re-authentication without having to wait for the
* Supplicant to send EAPOL-Start.
*/
- sta->eapol_sm->reAuthenticate = TRUE;
+ sta->eapol_sm->reAuthenticate = true;
}
eapol_auth_step(sta->eapol_sm);
}
@@ -1412,7 +1415,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
if (!sm || !sm->last_recv_radius) {
if (sm)
- sm->eap_if->aaaEapNoReq = TRUE;
+ sm->eap_if->aaaEapNoReq = true;
return;
}
@@ -1426,7 +1429,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING,
"could not extract EAP-Message from RADIUS message");
- sm->eap_if->aaaEapNoReq = TRUE;
+ sm->eap_if->aaaEapNoReq = true;
return;
}
@@ -1435,7 +1438,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
HOSTAPD_LEVEL_WARNING,
"too short EAP packet received from authentication server");
wpabuf_free(eap);
- sm->eap_if->aaaEapNoReq = TRUE;
+ sm->eap_if->aaaEapNoReq = true;
return;
}
@@ -1470,7 +1473,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
"decapsulated EAP packet (code=%d id=%d len=%d) from RADIUS server: %s",
hdr->code, hdr->identifier, be_to_host16(hdr->length),
buf);
- sm->eap_if->aaaEapReq = TRUE;
+ sm->eap_if->aaaEapReq = true;
wpabuf_free(sm->eap_if->aaaEapReqData);
sm->eap_if->aaaEapReqData = eap;
@@ -1509,7 +1512,7 @@ static void ieee802_1x_get_keys(struct hostapd_data *hapd,
os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len,
keys->send, keys->send_len);
sm->eap_if->aaaEapKeyDataLen = len;
- sm->eap_if->aaaEapKeyAvailable = TRUE;
+ sm->eap_if->aaaEapKeyAvailable = true;
}
} else {
wpa_printf(MSG_DEBUG,
@@ -1877,7 +1880,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg,
if (vlan_desc.notempty &&
!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
- sta->eapol_sm->authFail = TRUE;
+ sta->eapol_sm->authFail = true;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Invalid VLAN %d%s received from RADIUS server",
@@ -1890,7 +1893,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg,
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
!vlan_desc.notempty) {
- sta->eapol_sm->authFail = TRUE;
+ sta->eapol_sm->authFail = true;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_INFO,
"authentication server did not include required VLAN ID in Access-Accept");
@@ -2016,7 +2019,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
else
ap_sta_no_session_timeout(hapd, sta);
- sm->eap_if->aaaSuccess = TRUE;
+ sm->eap_if->aaaSuccess = true;
override_eapReq = 1;
ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
shared_secret_len);
@@ -2028,7 +2031,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
(int) session_timeout : -1);
break;
case RADIUS_CODE_ACCESS_REJECT:
- sm->eap_if->aaaFail = TRUE;
+ sm->eap_if->aaaFail = true;
override_eapReq = 1;
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE,
&reason_code) == 0) {
@@ -2039,7 +2042,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
}
break;
case RADIUS_CODE_ACCESS_CHALLENGE:
- sm->eap_if->aaaEapReq = TRUE;
+ sm->eap_if->aaaEapReq = true;
if (session_timeout_set) {
/* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */
sm->eap_if->aaaMethodTimeout = session_timeout;
@@ -2060,7 +2063,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
ieee802_1x_decapsulate_radius(hapd, sta);
if (override_eapReq)
- sm->eap_if->aaaEapReq = FALSE;
+ sm->eap_if->aaaEapReq = false;
#ifdef CONFIG_FILS
#ifdef NEED_AP_MLME
@@ -2106,13 +2109,15 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
MAC2STR(sta->addr));
- sm->eap_if->portEnabled = FALSE;
+ sm->eap_if->portEnabled = false;
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
}
}
+#ifdef CONFIG_WEP
+
static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
{
struct eapol_authenticator *eapol = hapd->eapol_auth;
@@ -2143,7 +2148,7 @@ static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
struct sta_info *sta, void *ctx)
{
if (sta->eapol_sm) {
- sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
+ sta->eapol_sm->eap_if->eapKeyAvailable = true;
eapol_auth_step(sta->eapol_sm);
}
return 0;
@@ -2177,9 +2182,10 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
* after new broadcast key has been sent to all stations. */
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
broadcast_ether_addr,
- eapol->default_wep_key_idx, 1, NULL, 0,
+ eapol->default_wep_key_idx, 0, 1, NULL, 0,
eapol->default_wep_key,
- hapd->conf->default_wep_key_len)) {
+ hapd->conf->default_wep_key_len,
+ KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING,
"failed to configure a new broadcast key");
@@ -2196,6 +2202,8 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
}
}
+#endif /* CONFIG_WEP */
+
static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
const u8 *data, size_t datalen)
@@ -2359,6 +2367,7 @@ static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx)
}
+#ifdef CONFIG_WEP
static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
{
#ifndef CONFIG_FIPS
@@ -2370,6 +2379,7 @@ static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
#endif /* CONFIG_NO_RC4 */
#endif /* CONFIG_FIPS */
}
+#endif /* CONFIG_WEP */
static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
@@ -2420,7 +2430,6 @@ static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
int ieee802_1x_init(struct hostapd_data *hapd)
{
- int i;
struct eapol_auth_config conf;
struct eapol_auth_cb cb;
@@ -2431,7 +2440,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
conf.ctx = hapd;
conf.eap_reauth_period = hapd->conf->eap_reauth_period;
conf.wpa = hapd->conf->wpa;
+#ifdef CONFIG_WEP
conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
+#endif /* CONFIG_WEP */
conf.eap_req_id_text = hapd->conf->eap_req_id_text;
conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
@@ -2446,7 +2457,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
cb.logger = ieee802_1x_logger;
cb.set_port_authorized = ieee802_1x_set_port_authorized;
cb.abort_auth = _ieee802_1x_abort_auth;
+#ifdef CONFIG_WEP
cb.tx_key = _ieee802_1x_tx_key;
+#endif /* CONFIG_WEP */
cb.eapol_event = ieee802_1x_eapol_event;
#ifdef CONFIG_ERP
cb.erp_get_key = ieee802_1x_erp_get_key;
@@ -2467,17 +2480,21 @@ int ieee802_1x_init(struct hostapd_data *hapd)
return -1;
#endif /* CONFIG_NO_RADIUS */
+#ifdef CONFIG_WEP
if (hapd->conf->default_wep_key_len) {
+ int i;
+
for (i = 0; i < 4; i++)
hostapd_drv_set_key(hapd->conf->iface, hapd,
- WPA_ALG_NONE, NULL, i, 0, NULL, 0,
- NULL, 0);
+ WPA_ALG_NONE, NULL, i, 0, 0, NULL,
+ 0, NULL, 0, KEY_FLAG_GROUP);
ieee802_1x_rekey(hapd, NULL);
if (!hapd->eapol_auth->default_wep_key)
return -1;
}
+#endif /* CONFIG_WEP */
return 0;
}
@@ -2497,7 +2514,9 @@ void ieee802_1x_erp_flush(struct hostapd_data *hapd)
void ieee802_1x_deinit(struct hostapd_data *hapd)
{
+#ifdef CONFIG_WEP
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
+#endif /* CONFIG_WEP */
if (hapd->driver && hapd->drv_priv &&
(hapd->conf->ieee802_1x || hapd->conf->wpa))
@@ -2658,26 +2677,25 @@ const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm,
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
- int enabled)
+ bool enabled)
{
if (!sm)
return;
- sm->eap_if->portEnabled = enabled ? TRUE : FALSE;
+ sm->eap_if->portEnabled = enabled;
eapol_auth_step(sm);
}
-void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
- int valid)
+void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid)
{
if (!sm)
return;
- sm->portValid = valid ? TRUE : FALSE;
+ sm->portValid = valid;
eapol_auth_step(sm);
}
-void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
+void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth)
{
if (!sm)
return;
@@ -2688,7 +2706,7 @@ void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
}
-static const char * bool_txt(Boolean val)
+static const char * bool_txt(bool val)
{
return val ? "TRUE" : "FALSE";
}
diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h
index bb85b93..70dc11a 100644
--- a/src/ap/ieee802_1x.h
+++ b/src/ap/ieee802_1x.h
@@ -42,10 +42,9 @@ const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm,
size_t *len);
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
- int enabled);
-void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
- int valid);
-void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth);
+ bool enabled);
+void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid);
+void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth);
int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
char *buf, size_t buflen);
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index 5415443..01bf886 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -34,6 +34,60 @@ hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
}
+int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen)
+{
+ struct hostapd_neighbor_entry *nr;
+ char *pos, *end;
+
+ pos = buf;
+ end = buf + buflen;
+
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
+ list) {
+ int ret;
+ char nrie[2 * 255 + 1];
+ char lci[2 * 255 + 1];
+ char civic[2 * 255 + 1];
+ char ssid[SSID_MAX_LEN * 2 + 1];
+
+ ssid[0] = '\0';
+ wpa_snprintf_hex(ssid, sizeof(ssid), nr->ssid.ssid,
+ nr->ssid.ssid_len);
+
+ nrie[0] = '\0';
+ if (nr->nr)
+ wpa_snprintf_hex(nrie, sizeof(nrie),
+ wpabuf_head(nr->nr),
+ wpabuf_len(nr->nr));
+
+ lci[0] = '\0';
+ if (nr->lci)
+ wpa_snprintf_hex(lci, sizeof(lci),
+ wpabuf_head(nr->lci),
+ wpabuf_len(nr->lci));
+
+ civic[0] = '\0';
+ if (nr->civic)
+ wpa_snprintf_hex(civic, sizeof(civic),
+ wpabuf_head(nr->civic),
+ wpabuf_len(nr->civic));
+
+ ret = os_snprintf(pos, end - pos, MACSTR
+ " ssid=%s%s%s%s%s%s%s%s\n",
+ MAC2STR(nr->bssid), ssid,
+ nr->nr ? " nr=" : "", nrie,
+ nr->lci ? " lci=" : "", lci,
+ nr->civic ? " civic=" : "", civic,
+ nr->stationary ? " stat" : "");
+ if (os_snprintf_error(end - pos, ret))
+ break;
+ pos += ret;
+ }
+
+ return pos - buf;
+}
+
+
static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
{
wpabuf_free(nr->nr);
@@ -202,6 +256,8 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
if (vht)
bssid_info |= NEI_REP_BSSID_INFO_VHT;
+ if (he)
+ bssid_info |= NEI_REP_BSSID_INFO_HE;
}
/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
index 9c8f4f2..bed0a2f 100644
--- a/src/ap/neighbor_db.h
+++ b/src/ap/neighbor_db.h
@@ -13,6 +13,7 @@
struct hostapd_neighbor_entry *
hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
const struct wpa_ssid_value *ssid);
+int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen);
int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
const struct wpa_ssid_value *ssid,
const struct wpabuf *nr, const struct wpabuf *lci,
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index 15e2c49..fe5f817 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -516,6 +516,11 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
for (entry = pmksa->pmksa; entry; entry = entry->next) {
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
continue;
+ if (wpa_key_mgmt_sae(entry->akmp)) {
+ if (os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
+ return entry;
+ continue;
+ }
rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
entry->akmp);
if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
diff --git a/src/ap/preauth_auth.c b/src/ap/preauth_auth.c
index 3e0c800..2ff1861 100644
--- a/src/ap/preauth_auth.c
+++ b/src/ap/preauth_auth.c
@@ -82,7 +82,7 @@ static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
sta = NULL;
} else {
sta->eapol_sm->radius_identifier = -1;
- sta->eapol_sm->portValid = TRUE;
+ sta->eapol_sm->portValid = true;
sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
}
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index d7734ee..67b5e98 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -164,6 +164,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
/* just in case */
ap_sta_set_authorized(hapd, sta, 0);
+ hostapd_set_sta_flags(hapd, sta);
if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
@@ -233,9 +234,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
sta->assoc_ie_taxonomy = NULL;
#endif /* CONFIG_TAXONOMY */
-#ifdef CONFIG_IEEE80211N
ht40_intolerant_remove(hapd->iface, sta);
-#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_P2P
if (sta->no_p2p_set) {
@@ -246,10 +245,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
}
#endif /* CONFIG_P2P */
-#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
+#ifdef NEED_AP_MLME
if (hostapd_ht_operation_update(hapd->iface) > 0)
set_beacon++;
-#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
+#endif /* NEED_AP_MLME */
#ifdef CONFIG_MESH
if (hapd->mesh_sta_free_cb)
@@ -327,6 +326,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
os_free(sta->vht_capabilities);
os_free(sta->vht_operation);
os_free(sta->he_capab);
+ os_free(sta->he_6ghz_capab);
hostapd_free_psk_list(sta->psk);
os_free(sta->identity);
os_free(sta->radius_cui);
@@ -373,6 +373,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
os_free(sta->ifname_wds);
+#ifdef CONFIG_TESTING_OPTIONS
+ os_free(sta->sae_postponed_commit);
+#endif /* CONFIG_TESTING_OPTIONS */
+
os_free(sta);
}
@@ -542,6 +546,7 @@ skip_poll:
case STA_DISASSOC_FROM_CLI:
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~WLAN_STA_ASSOC;
+ hostapd_set_sta_flags(hapd, sta);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
if (!sta->acct_terminate_cause)
sta->acct_terminate_cause =
@@ -586,7 +591,8 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
- if (!(sta->flags & WLAN_STA_AUTH)) {
+ if (!(sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC |
+ WLAN_STA_AUTHORIZED))) {
if (sta->flags & WLAN_STA_GAS) {
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
"entry " MACSTR, MAC2STR(sta->addr));
@@ -809,6 +815,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
sta->timeout_next = STA_DEAUTH;
}
ap_sta_set_authorized(hapd, sta, 0);
+ hostapd_set_sta_flags(hapd, sta);
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
@@ -859,6 +866,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
ap_sta_set_authorized(hapd, sta, 0);
+ hostapd_set_sta_flags(hapd, sta);
sta->timeout_next = STA_REMOVE;
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
@@ -1024,6 +1032,13 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
int ret;
int old_vlanid = sta->vlan_id_bound;
+ if ((sta->flags & WLAN_STA_WDS) && sta->vlan_id == 0) {
+ wpa_printf(MSG_DEBUG,
+ "Do not override WDS VLAN assignment for STA "
+ MACSTR, MAC2STR(sta->addr));
+ return 0;
+ }
+
iface = hapd->conf->iface;
if (hapd->conf->ssid.vlan[0])
iface = hapd->conf->ssid.vlan;
@@ -1045,7 +1060,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->vlan_id == old_vlanid)
goto skip_counting;
- if (sta->vlan_id > 0 && vlan == NULL) {
+ if (sta->vlan_id > 0 && !vlan &&
+ !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
"binding station to (vlan_id=%d)",
@@ -1129,6 +1145,8 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
if (sta->sa_query_count > 0 &&
ap_check_sa_query_timeout(hapd, sta))
return;
+ if (sta->sa_query_count >= 1000)
+ return;
nbuf = os_realloc_array(sta->sa_query_trans_id,
sta->sa_query_count + 1,
@@ -1316,9 +1334,10 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
if (sta == NULL)
return;
ap_sta_set_authorized(hapd, sta, 0);
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
- sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
@@ -1406,7 +1425,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
int res;
buf[0] = '\0';
- res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ res = os_snprintf(buf, buflen,
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
@@ -1425,6 +1445,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
(flags & WLAN_STA_GAS ? "[GAS]" : ""),
(flags & WLAN_STA_HT ? "[HT]" : ""),
(flags & WLAN_STA_VHT ? "[VHT]" : ""),
+ (flags & WLAN_STA_HE ? "[HE]" : ""),
+ (flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""),
(flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
(flags & WLAN_STA_WNM_SLEEP_MODE ?
"[WNM_SLEEP_MODE]" : ""));
@@ -1478,3 +1500,33 @@ int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb,
hapd, sta);
}
+
+
+int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ /*
+ * If a station that is already associated to the AP, is trying to
+ * authenticate again, remove the STA entry, in order to make sure the
+ * STA PS state gets cleared and configuration gets updated. To handle
+ * this, station's added_unassoc flag is cleared once the station has
+ * completed association.
+ */
+ ap_sta_set_authorized(hapd, sta, 0);
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | WLAN_STA_AUTHORIZED);
+
+ if (hostapd_sta_add(hapd, sta->addr, 0, 0,
+ sta->supported_rates,
+ sta->supported_rates_len,
+ 0, NULL, NULL, NULL, 0, NULL,
+ sta->flags, 0, 0, 0, 0)) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_NOTICE,
+ "Could not add STA to kernel driver");
+ return -1;
+ }
+
+ sta->added_unassoc = 1;
+ return 0;
+}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index de806b4..ef48561 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -38,6 +38,7 @@
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
#define WLAN_STA_MULTI_AP BIT(23)
#define WLAN_STA_HE BIT(24)
+#define WLAN_STA_6GHZ BIT(25)
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
@@ -121,6 +122,7 @@ struct sta_info {
unsigned int hs20_t_c_filtering:1;
unsigned int ft_over_ds:1;
unsigned int external_dh_updated:1;
+ unsigned int post_csa_sa_query:1;
u16 auth_alg;
@@ -170,6 +172,7 @@ struct sta_info {
u8 vht_opmode;
struct ieee80211_he_capabilities *he_capab;
size_t he_capab_len;
+ struct ieee80211_he_6ghz_band_cap *he_6ghz_capab;
int sa_query_count; /* number of pending SA Query requests;
* 0 = no SA Query in progress */
@@ -276,6 +279,8 @@ struct sta_info {
int last_tk_key_idx;
u8 last_tk[WPA_TK_MAX_LEN];
size_t last_tk_len;
+ u8 *sae_postponed_commit;
+ size_t sae_postponed_commit_len;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_AIRTIME_POLICY
unsigned int airtime_weight;
@@ -356,5 +361,6 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta);
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta);
+int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
#endif /* STA_INFO_H */
diff --git a/src/ap/utils.c b/src/ap/utils.c
index fcb371b..bedad6e 100644
--- a/src/ap/utils.c
+++ b/src/ap/utils.c
@@ -56,6 +56,10 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx)
ohapd = iface->bss[j];
if (ohapd == data->hapd)
continue;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (ohapd->conf->skip_prune_assoc)
+ continue;
+#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_FST
/* Don't prune STAs belong to same FST */
if (ohapd->iface->fst &&
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index e293a00..53eacfb 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -22,7 +22,9 @@
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
int existsok)
{
- int ret, i;
+ int ret;
+#ifdef CONFIG_WEP
+ int i;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (!hapd->conf->ssid.wep.key[i])
@@ -32,6 +34,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
vlan->ifname);
return -1;
}
+#endif /* CONFIG_WEP */
if (!iface_exists(vlan->ifname))
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index dc73493..9ebb01e 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -111,9 +111,11 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
u8 *pos = eid;
struct wmm_parameter_element *wmm =
(struct wmm_parameter_element *) (pos + 2);
- struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM] = { 0 };
+ struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM];
int e;
+ os_memset(wmmp, 0, sizeof(wmmp));
+
if (!hapd->conf->wmm_enabled)
return eid;
wmm_calc_regulatory_limit(hapd, wmmp);
@@ -209,7 +211,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
len = ((u8 *) (t + 1)) - buf;
- if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
+ if (hostapd_drv_send_mlme(hapd, m, len, 0, NULL, 0, 0) < 0)
wpa_printf(MSG_INFO, "wmm_send_action: send failed");
}
@@ -291,10 +293,11 @@ int wmm_process_tspec(struct wmm_tspec_element *tspec)
static void wmm_addts_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
- struct wmm_tspec_element *tspec, size_t len)
+ const struct wmm_tspec_element *tspec, size_t len)
{
const u8 *end = ((const u8 *) mgmt) + len;
int res;
+ struct wmm_tspec_element tspec_resp;
if ((const u8 *) (tspec + 1) > end) {
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
@@ -306,10 +309,11 @@ static void wmm_addts_req(struct hostapd_data *hapd,
mgmt->u.action.u.wmm_action.dialog_token,
MAC2STR(mgmt->sa));
- res = wmm_process_tspec(tspec);
+ os_memcpy(&tspec_resp, tspec, sizeof(struct wmm_tspec_element));
+ res = wmm_process_tspec(&tspec_resp);
wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
- wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
+ wmm_send_action(hapd, mgmt->sa, &tspec_resp, WMM_ACTION_CODE_ADDTS_RESP,
mgmt->u.action.u.wmm_action.dialog_token, res);
}
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index e4dcfe9..be81797 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -54,6 +54,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
size_t len;
size_t gtk_elem_len = 0;
size_t igtk_elem_len = 0;
+ size_t bigtk_elem_len = 0;
struct wnm_sleep_element wnmsleep_ie;
u8 *wnmtfs_ie, *oci_ie;
u8 wnmsleep_ie_len, oci_ie_len;
@@ -102,6 +103,15 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
os_free(wnmtfs_ie);
return -1;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->conf->oci_freq_override_wnm_sleep) {
+ wpa_printf(MSG_INFO,
+ "TEST: Override OCI frequency %d -> %u MHz",
+ ci.frequency,
+ hapd->conf->oci_freq_override_wnm_sleep);
+ ci.frequency = hapd->conf->oci_freq_override_wnm_sleep;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
oci_ie_len = OCV_OCI_EXTENDED_LEN;
oci_ie = os_zalloc(oci_ie_len);
@@ -122,8 +132,10 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#define MAX_GTK_SUBELEM_LEN 45
#define MAX_IGTK_SUBELEM_LEN 26
+#define MAX_BIGTK_SUBELEM_LEN 26
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
+ MAX_BIGTK_SUBELEM_LEN +
oci_ie_len);
if (mgmt == NULL) {
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
@@ -157,10 +169,19 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
pos += igtk_elem_len;
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
(int) igtk_elem_len);
+ if (hapd->conf->beacon_prot) {
+ res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos);
+ if (res < 0)
+ goto fail;
+ bigtk_elem_len = res;
+ pos += bigtk_elem_len;
+ wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d",
+ (int) bigtk_elem_len);
+ }
WPA_PUT_LE16((u8 *)
&mgmt->u.action.u.wnm_sleep_resp.keydata_len,
- gtk_elem_len + igtk_elem_len);
+ gtk_elem_len + igtk_elem_len + bigtk_elem_len);
}
os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
/* copy TFS IE here */
@@ -176,7 +197,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#endif /* CONFIG_OCV */
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
- igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
+ igtk_elem_len + bigtk_elem_len +
+ wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
/* In driver, response frame should be forced to sent when STA is in
* PS mode */
@@ -189,8 +211,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
/* when entering wnmsleep
* 1. pause the node in driver
- * 2. mark the node so that AP won't update GTK/IGTK during
- * WNM Sleep
+ * 2. mark the node so that AP won't update GTK/IGTK/BIGTK
+ * during WNM Sleep
*/
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
@@ -201,7 +223,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
}
/* when exiting wnmsleep
* 1. unmark the node
- * 2. start GTK/IGTK update if MFP is not used
+ * 2. start GTK/IGTK/BIGTK update if MFP is not used
* 3. unpause the node in driver
*/
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
@@ -221,6 +243,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#undef MAX_GTK_SUBELEM_LEN
#undef MAX_IGTK_SUBELEM_LEN
+#undef MAX_BIGTK_SUBELEM_LEN
fail:
os_free(wnmtfs_ie);
os_free(oci_ie);
@@ -303,8 +326,9 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd,
if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
channel_width_to_int(ci.chanwidth),
- ci.seg1_idx) != 0) {
- wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr);
+ ci.seg1_idx) != OCI_SUCCESS) {
+ wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s",
+ ocv_errorstr);
return;
}
}
@@ -508,6 +532,30 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
}
+static void wnm_beacon_protection_failure(struct hostapd_data *hapd,
+ const u8 *addr)
+{
+ struct sta_info *sta;
+
+ if (!hapd->conf->beacon_prot)
+ return;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for received WNM-Notification Request",
+ MAC2STR(addr));
+ return;
+ }
+
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_INFO,
+ "Beacon protection failure reported");
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter="
+ MACSTR, MAC2STR(addr));
+}
+
+
static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *buf,
size_t len)
@@ -526,8 +574,14 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
MAC2STR(addr), dialog_token, type);
wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
buf, len);
- if (type == WLAN_EID_VENDOR_SPECIFIC)
+ switch (type) {
+ case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE:
+ wnm_beacon_protection_failure(hapd, addr);
+ break;
+ case WNM_NOTIF_TYPE_VENDOR_SPECIFIC:
mbo_ap_wnm_notification_req(hapd, addr, buf, len);
+ break;
+ }
}
@@ -641,7 +695,7 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
MACSTR, disassoc_timer, MAC2STR(sta->addr));
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
@@ -714,7 +768,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
os_memcpy(pos, url, url_len);
pos += url_len;
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
@@ -790,7 +844,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
mbo_len);
}
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG,
"Failed to send BSS Transition Management Request frame");
os_free(buf);
@@ -834,7 +888,7 @@ int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to "
MACSTR " (dialog_token=%u auto_report=%u timeout=%u)",
MAC2STR(sta->addr), dialog_token, auto_report, timeout);
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
wpa_printf(MSG_DEBUG,
"WNM: Failed to send Collocated Interference Request frame");
return -1;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 7b690d7..9d74bfc 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -14,6 +14,8 @@
#include "utils/bitfield.h"
#include "common/ieee802_11_defs.h"
#include "common/ocv.h"
+#include "common/dpp.h"
+#include "common/wpa_ctrl.h"
#include "crypto/aes.h"
#include "crypto/aes_wrap.h"
#include "crypto/aes_siv.h"
@@ -56,13 +58,14 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len,
- struct wpa_ptk *ptk);
+ struct wpa_ptk *ptk, int force_sha256);
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_put(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
+static int ieee80211w_kde_len(struct wpa_state_machine *sm);
static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
static const u32 eapol_key_timeout_first = 100; /* ms */
@@ -105,7 +108,7 @@ static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
const u8 *addr, wpa_eapol_variable var)
{
- if (wpa_auth->cb->get_eapol == NULL)
+ if (!wpa_auth->cb->get_eapol)
return -1;
return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
}
@@ -117,7 +120,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
const u8 *prev_psk, size_t *psk_len,
int *vlan_id)
{
- if (wpa_auth->cb->get_psk == NULL)
+ if (!wpa_auth->cb->get_psk)
return NULL;
return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
prev_psk, psk_len, vlan_id);
@@ -127,7 +130,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
const u8 *addr, u8 *msk, size_t *len)
{
- if (wpa_auth->cb->get_msk == NULL)
+ if (!wpa_auth->cb->get_msk)
return -1;
return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
}
@@ -136,21 +139,46 @@ static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
int vlan_id,
enum wpa_alg alg, const u8 *addr, int idx,
- u8 *key, size_t key_len)
+ u8 *key, size_t key_len,
+ enum key_flag key_flag)
{
- if (wpa_auth->cb->set_key == NULL)
+ if (!wpa_auth->cb->set_key)
return -1;
return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
- key, key_len);
+ key, key_len, key_flag);
}
static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
const u8 *addr, int idx, u8 *seq)
{
- if (wpa_auth->cb->get_seqnum == NULL)
+ int res;
+
+ if (!wpa_auth->cb->get_seqnum)
return -1;
- return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
+ res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Override GTK RSC %016llx --> %016llx",
+ (long long unsigned) WPA_GET_LE64(seq),
+ (long long unsigned)
+ WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
+ os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
+ WPA_KEY_RSC_LEN);
+ }
+ if (!addr && idx >= 4 && idx <= 5 &&
+ wpa_auth->conf.igtk_rsc_override_set) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Override IGTK RSC %016llx --> %016llx",
+ (long long unsigned) WPA_GET_LE64(seq),
+ (long long unsigned)
+ WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
+ os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
+ WPA_KEY_RSC_LEN);
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ return res;
}
@@ -158,7 +186,7 @@ static inline int
wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *data, size_t data_len, int encrypt)
{
- if (wpa_auth->cb->send_eapol == NULL)
+ if (!wpa_auth->cb->send_eapol)
return -1;
return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
encrypt);
@@ -169,7 +197,7 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
const u8 *addr)
{
- if (wpa_auth->cb->start_ampe == NULL)
+ if (!wpa_auth->cb->start_ampe)
return -1;
return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
}
@@ -180,7 +208,7 @@ int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
int (*cb)(struct wpa_state_machine *sm, void *ctx),
void *cb_ctx)
{
- if (wpa_auth->cb->for_each_sta == NULL)
+ if (!wpa_auth->cb->for_each_sta)
return 0;
return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
}
@@ -190,7 +218,7 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
int (*cb)(struct wpa_authenticator *a, void *ctx),
void *cb_ctx)
{
- if (wpa_auth->cb->for_each_auth == NULL)
+ if (!wpa_auth->cb->for_each_auth)
return 0;
return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
}
@@ -199,7 +227,7 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
logger_level level, const char *txt)
{
- if (wpa_auth->cb->logger == NULL)
+ if (!wpa_auth->cb->logger)
return;
wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
}
@@ -212,7 +240,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
int maxlen;
va_list ap;
- if (wpa_auth->cb->logger == NULL)
+ if (!wpa_auth->cb->logger)
return;
maxlen = os_strlen(fmt) + 100;
@@ -233,7 +261,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
const u8 *addr, u16 reason)
{
- if (wpa_auth->cb->disconnect == NULL)
+ if (!wpa_auth->cb->disconnect)
return;
wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
MAC2STR(addr), reason);
@@ -266,8 +294,8 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
struct wpa_authenticator *wpa_auth = eloop_ctx;
if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
- wpa_printf(MSG_ERROR, "Failed to get random data for WPA "
- "initialization.");
+ wpa_printf(MSG_ERROR,
+ "Failed to get random data for WPA initialization.");
} else {
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
wpa_hexdump_key(MSG_DEBUG, "GMK",
@@ -291,9 +319,9 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
while (group) {
wpa_group_get(wpa_auth, group);
- group->GTKReKey = TRUE;
+ group->GTKReKey = true;
do {
- group->changed = FALSE;
+ group->changed = false;
wpa_group_sm_step(wpa_auth, group);
} while (group->changed);
@@ -391,17 +419,16 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
struct wpa_group *group;
group = os_zalloc(sizeof(struct wpa_group));
- if (group == NULL)
+ if (!group)
return NULL;
- group->GTKAuthenticator = TRUE;
+ group->GTKAuthenticator = true;
group->vlan_id = vlan_id;
group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
if (random_pool_ready() != 1) {
- wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool "
- "for secure operations - update keys later when "
- "the first station connects");
+ wpa_printf(MSG_INFO,
+ "WPA: Not enough entropy in random pool for secure operations - update keys later when the first station connects");
}
/*
@@ -411,20 +438,20 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
* on embedded devices.
*/
if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
- wpa_printf(MSG_ERROR, "Failed to get random data for WPA "
- "initialization.");
+ wpa_printf(MSG_ERROR,
+ "Failed to get random data for WPA initialization.");
os_free(group);
return NULL;
}
- group->GInit = TRUE;
+ group->GInit = true;
if (delay_init) {
- wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start "
- "until Beacon frames have been configured");
+ wpa_printf(MSG_DEBUG,
+ "WPA: Delay group state machine start until Beacon frames have been configured");
/* Initialization is completed in wpa_init_keys(). */
} else {
wpa_group_sm_step(wpa_auth, group);
- group->GInit = FALSE;
+ group->GInit = false;
wpa_group_sm_step(wpa_auth, group);
}
@@ -447,7 +474,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
struct wpa_authenticator *wpa_auth;
wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
- if (wpa_auth == NULL)
+ if (!wpa_auth)
return NULL;
os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
@@ -461,7 +488,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
}
wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
- if (wpa_auth->group == NULL) {
+ if (!wpa_auth->group) {
os_free(wpa_auth->wpa_ie);
os_free(wpa_auth);
return NULL;
@@ -469,7 +496,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
wpa_auth);
- if (wpa_auth->pmksa == NULL) {
+ if (!wpa_auth->pmksa) {
wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
os_free(wpa_auth->group);
os_free(wpa_auth->wpa_ie);
@@ -479,7 +506,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
#ifdef CONFIG_IEEE80211R_AP
wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
- if (wpa_auth->ft_pmk_cache == NULL) {
+ if (!wpa_auth->ft_pmk_cache) {
wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
os_free(wpa_auth->group);
os_free(wpa_auth->wpa_ie);
@@ -518,10 +545,10 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth)
{
struct wpa_group *group = wpa_auth->group;
- wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial "
- "keys");
+ wpa_printf(MSG_DEBUG,
+ "WPA: Start group state machine to set initial keys");
wpa_group_sm_step(wpa_auth, group);
- group->GInit = FALSE;
+ group->GInit = false;
wpa_group_sm_step(wpa_auth, group);
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
return -1;
@@ -575,7 +602,8 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
struct wpa_auth_config *conf)
{
struct wpa_group *group;
- if (wpa_auth == NULL)
+
+ if (!wpa_auth)
return 0;
os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
@@ -590,9 +618,9 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
*/
group = wpa_auth->group;
group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
- group->GInit = TRUE;
+ group->GInit = true;
wpa_group_sm_step(wpa_auth, group);
- group->GInit = FALSE;
+ group->GInit = false;
wpa_group_sm_step(wpa_auth, group);
return 0;
@@ -609,7 +637,7 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
return NULL;
sm = os_zalloc(sizeof(struct wpa_state_machine));
- if (sm == NULL)
+ if (!sm)
return NULL;
os_memcpy(sm->addr, addr, ETH_ALEN);
if (p2p_dev_addr)
@@ -626,17 +654,16 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm)
{
- if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
+ if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
return -1;
#ifdef CONFIG_IEEE80211R_AP
if (sm->ft_completed) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
- "FT authentication already completed - do not "
- "start 4-way handshake");
+ "FT authentication already completed - do not start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
- sm->Pair = TRUE;
+ sm->Pair = true;
return 0;
}
#endif /* CONFIG_IEEE80211R_AP */
@@ -647,14 +674,14 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
"FILS authentication already completed - do not start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
- sm->Pair = TRUE;
+ sm->Pair = true;
return 0;
}
#endif /* CONFIG_FILS */
if (sm->started) {
os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
- sm->ReAuthenticationRequest = TRUE;
+ sm->ReAuthenticationRequest = true;
return wpa_sm_step(sm);
}
@@ -662,11 +689,11 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
"start authentication");
sm->started = 1;
- sm->Init = TRUE;
+ sm->Init = true;
if (wpa_sm_step(sm) == 1)
return 1; /* should not really happen */
- sm->Init = FALSE;
- sm->AuthenticationRequest = TRUE;
+ sm->Init = false;
+ sm->AuthenticationRequest = true;
return wpa_sm_step(sm);
}
@@ -676,7 +703,7 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
/* WPA/RSN was not used - clear WPA state. This is needed if the STA
* reassociates back to the same AP while the previous entry for the
* STA has not yet been removed. */
- if (sm == NULL)
+ if (!sm)
return;
sm->wpa_key_mgmt = 0;
@@ -688,8 +715,9 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr)) {
u32 start;
- wpa_printf(MSG_DEBUG, "P2P: Free assigned IP "
- "address %u.%u.%u.%u from " MACSTR,
+ wpa_printf(MSG_DEBUG,
+ "P2P: Free assigned IP address %u.%u.%u.%u from "
+ MACSTR,
sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
MAC2STR(sm->addr));
@@ -700,7 +728,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
#endif /* CONFIG_P2P */
if (sm->GUpdateStationKeys) {
sm->group->GKeyDoneStations--;
- sm->GUpdateStationKeys = FALSE;
+ sm->GUpdateStationKeys = false;
}
#ifdef CONFIG_IEEE80211R_AP
os_free(sm->assoc_resp_ftie);
@@ -719,31 +747,34 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
{
- if (sm == NULL)
+ struct wpa_authenticator *wpa_auth;
+
+ if (!sm)
return;
- if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
- "strict rekeying - force GTK rekey since STA "
- "is leaving");
+ wpa_auth = sm->wpa_auth;
+ if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ "strict rekeying - force GTK rekey since STA is leaving");
if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
- sm->wpa_auth, NULL) == -1)
- eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,
- NULL);
+ wpa_auth, NULL) == -1)
+ eloop_register_timeout(0, 500000, wpa_rekey_gtk,
+ wpa_auth, NULL);
}
- eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
+ eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
sm->pending_1_of_4_timeout = 0;
eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
- eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
+ eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
#ifdef CONFIG_IEEE80211R_AP
wpa_ft_sta_deinit(sm);
#endif /* CONFIG_IEEE80211R_AP */
if (sm->in_step_loop) {
/* Must not free state machine while wpa_sm_step() is running.
* Freeing will be completed in the end of wpa_sm_step(). */
- wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state "
- "machine deinit for " MACSTR, MAC2STR(sm->addr));
+ wpa_printf(MSG_DEBUG,
+ "WPA: Registering pending STA state machine deinit for "
+ MACSTR, MAC2STR(sm->addr));
sm->pending_deinit = 1;
} else
wpa_free_sta_sm(sm);
@@ -752,11 +783,23 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
static void wpa_request_new_ptk(struct wpa_state_machine *sm)
{
- if (sm == NULL)
+ if (!sm)
return;
- sm->PTKRequest = TRUE;
- sm->PTK_valid = 0;
+ if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+ wpa_printf(MSG_INFO,
+ "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
+ MAC2STR(sm->addr));
+ sm->Disconnect = true;
+ /* Try to encourage the STA to reconnect */
+ sm->disconnect_reason =
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+ } else {
+ if (sm->use_ext_key_id)
+ sm->keyidx_active ^= 1; /* flip Key ID */
+ sm->PTKRequest = true;
+ sm->PTK_valid = 0;
+ }
}
@@ -781,10 +824,10 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
int i;
for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
if (ctr[i].valid &&
- (replay_counter == NULL ||
+ (!replay_counter ||
os_memcmp(replay_counter, ctr[i].counter,
WPA_REPLAY_COUNTER_LEN) == 0))
- ctr[i].valid = FALSE;
+ ctr[i].valid = false;
}
}
@@ -798,9 +841,9 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
struct rsn_mdie *mdie;
if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
- ie.num_pmkid != 1 || ie.pmkid == NULL) {
- wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
- "FT 4-way handshake message 2/4");
+ ie.num_pmkid != 1 || !ie.pmkid) {
+ wpa_printf(MSG_DEBUG,
+ "FT: No PMKR1Name in FT 4-way handshake message 2/4");
return -1;
}
@@ -809,8 +852,9 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
sm->sup_pmk_r1_name, PMKID_LEN);
if (!kde->mdie || !kde->ftie) {
- wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake "
- "message 2/4", kde->mdie ? "FTIE" : "MDIE");
+ wpa_printf(MSG_DEBUG,
+ "FT: No %s in FT 4-way handshake message 2/4",
+ kde->mdie ? "FTIE" : "MDIE");
return -1;
}
@@ -844,18 +888,15 @@ static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
{
/* Supplicant reported a Michael MIC error */
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
- "received EAPOL-Key Error Request "
- "(STA detected Michael MIC failure (group=%d))",
+ "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
group);
if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
- "ignore Michael MIC failure report since "
- "group cipher is not TKIP");
+ "ignore Michael MIC failure report since group cipher is not TKIP");
} else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
- "ignore Michael MIC failure report since "
- "pairwise cipher is not TKIP");
+ "ignore Michael MIC failure report since pairwise cipher is not TKIP");
} else {
if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
return 1; /* STA entry was removed */
@@ -888,7 +929,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
sm->p2p_dev_addr, pmk, &pmk_len,
&vlan_id);
- if (pmk == NULL)
+ if (!pmk)
break;
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
@@ -901,7 +942,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
pmk_len = sm->pmk_len;
}
- if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0)
+ if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
+ 0)
break;
if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
@@ -936,7 +978,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
forced_memzero(&PTK, sizeof(PTK));
- sm->PTK_valid = TRUE;
+ sm->PTK_valid = true;
return 0;
}
@@ -956,7 +998,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
size_t keyhdrlen, mic_len;
u8 *mic;
- if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
+ if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
return;
wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
@@ -975,20 +1017,19 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
key_data = mic + mic_len + 2;
key_data_length = WPA_GET_BE16(mic + mic_len);
wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
- " key_info=0x%x type=%u mic_len=%u key_data_length=%u",
+ " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
MAC2STR(sm->addr), key_info, key->type,
- (unsigned int) mic_len, key_data_length);
+ mic_len, key_data_length);
wpa_hexdump(MSG_MSGDUMP,
"WPA: EAPOL-Key header (ending before Key MIC)",
key, sizeof(*key));
wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
mic, mic_len);
if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
- wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "
- "key_data overflow (%d > %lu)",
+ wpa_printf(MSG_INFO,
+ "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
key_data_length,
- (unsigned long) (data_len - sizeof(*hdr) -
- keyhdrlen));
+ data_len - sizeof(*hdr) - keyhdrlen);
return;
}
@@ -998,18 +1039,18 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
* Some deployed station implementations seem to send
* msg 4/4 with incorrect type value in WPA2 mode.
*/
- wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key "
- "with unexpected WPA type in RSN mode");
+ wpa_printf(MSG_DEBUG,
+ "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
} else if (key->type != EAPOL_KEY_TYPE_RSN) {
- wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
- "unexpected type %d in RSN mode",
+ wpa_printf(MSG_DEBUG,
+ "Ignore EAPOL-Key with unexpected type %d in RSN mode",
key->type);
return;
}
} else {
if (key->type != EAPOL_KEY_TYPE_WPA) {
- wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
- "unexpected type %d in WPA mode",
+ wpa_printf(MSG_DEBUG,
+ "Ignore EAPOL-Key with unexpected type %d in WPA mode",
key->type);
return;
}
@@ -1054,9 +1095,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
wpa_auth_logger(wpa_auth, sm->addr,
LOGGER_WARNING,
- "advertised support for "
- "AES-128-CMAC, but did not "
- "use it");
+ "advertised support for AES-128-CMAC, but did not use it");
return;
}