summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-22 14:59:50 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:41 +0200
commit3489e3b6396ee9944a6a2e19e675ca54c36993b4 (patch)
treecd55cfac1c96ff4b888a9606fd6a0d8eb65bb446
parentck: Define CK_MD_PPC32_LWSYNC if available (diff)
downloadrtems-libbsd-3489e3b6396ee9944a6a2e19e675ca54c36993b4.tar.bz2
Update to FreeBSD head 2018-09-17
Git mirror commit 6c2192b1ef8c50788c751f878552526800b1e319. Update #3472.
-rw-r--r--Makefile.todo14
m---------freebsd-org0
-rw-r--r--freebsd/contrib/tcpdump/tcpdump.c3
-rw-r--r--freebsd/contrib/wpa/src/ap/ap_config.h55
-rw-r--r--freebsd/contrib/wpa/src/ap/ap_drv_ops.c228
-rw-r--r--freebsd/contrib/wpa/src/ap/ap_drv_ops.h18
-rw-r--r--freebsd/contrib/wpa/src/ap/hostapd.h56
-rw-r--r--freebsd/contrib/wpa/src/ap/ieee802_11.h33
-rw-r--r--freebsd/contrib/wpa/src/ap/ieee802_11_auth.h5
-rw-r--r--freebsd/contrib/wpa/src/ap/ieee802_11_shared.c78
-rw-r--r--freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h14
-rw-r--r--freebsd/contrib/wpa/src/ap/sta_info.h74
-rw-r--r--freebsd/contrib/wpa/src/ap/vlan.h30
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth.c226
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth.h42
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth_ft.c10
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth_i.h4
-rw-r--r--freebsd/contrib/wpa/src/common/ctrl_iface_common.c175
-rw-r--r--freebsd/contrib/wpa/src/common/ctrl_iface_common.h38
-rw-r--r--freebsd/contrib/wpa/src/common/defs.h15
-rw-r--r--freebsd/contrib/wpa/src/common/eapol_common.h2
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_11_common.c212
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_11_common.h28
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_11_defs.h245
-rw-r--r--freebsd/contrib/wpa/src/common/qca-vendor.h1235
-rw-r--r--freebsd/contrib/wpa/src/common/sae.h1
-rw-r--r--freebsd/contrib/wpa/src/common/version.h6
-rw-r--r--freebsd/contrib/wpa/src/common/wpa_common.c141
-rw-r--r--freebsd/contrib/wpa/src/common/wpa_common.h4
-rw-r--r--freebsd/contrib/wpa/src/common/wpa_ctrl.h32
-rw-r--r--freebsd/contrib/wpa/src/crypto/aes-omac1.c3
-rw-r--r--freebsd/contrib/wpa/src/crypto/crypto.h25
-rw-r--r--freebsd/contrib/wpa/src/crypto/crypto_openssl.c403
-rw-r--r--freebsd/contrib/wpa/src/crypto/ms_funcs.c2
-rw-r--r--freebsd/contrib/wpa/src/crypto/sha256-internal.c3
-rw-r--r--freebsd/contrib/wpa/src/crypto/sha256-prf.c26
-rw-r--r--freebsd/contrib/wpa/src/crypto/sha256.h12
-rw-r--r--freebsd/contrib/wpa/src/crypto/tls.h47
-rw-r--r--freebsd/contrib/wpa/src/crypto/tls_internal.c64
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver.h344
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_bsd.c355
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_common.c57
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_ndis.c16
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_nl80211.h36
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_wired.c14
-rw-r--r--freebsd/contrib/wpa/src/drivers/drivers.c36
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap.c80
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_config.h20
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_gtc.c6
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_i.h2
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_leap.c6
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_md5.c6
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_methods.c17
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_methods.h1
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c6
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_otp.c6
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_peap.c76
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_psk.c6
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_tls.c60
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c23
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_ttls.c128
-rw-r--r--freebsd/contrib/wpa/src/eap_server/eap_methods.h1
-rw-r--r--freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c10
-rw-r--r--freebsd/contrib/wpa/src/p2p/p2p.h71
-rw-r--r--freebsd/contrib/wpa/src/radius/radius.h19
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c13
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h8
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/preauth.c6
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/preauth.h6
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa.c172
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa.h14
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_i.h15
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c6
-rw-r--r--freebsd/contrib/wpa/src/tls/tlsv1_client.h10
-rw-r--r--freebsd/contrib/wpa/src/tls/tlsv1_cred.h8
-rw-r--r--freebsd/contrib/wpa/src/utils/common.c83
-rw-r--r--freebsd/contrib/wpa/src/utils/common.h16
-rw-r--r--freebsd/contrib/wpa/src/utils/eloop.c292
-rw-r--r--freebsd/contrib/wpa/src/utils/eloop.h8
-rw-r--r--freebsd/contrib/wpa/src/utils/module_tests.h20
-rw-r--r--freebsd/contrib/wpa/src/utils/os.h4
-rw-r--r--freebsd/contrib/wpa/src/utils/os_unix.c7
-rw-r--r--freebsd/contrib/wpa/src/utils/platform.h4
-rw-r--r--freebsd/contrib/wpa/src/utils/trace.h2
-rw-r--r--freebsd/contrib/wpa/src/utils/wpa_debug.c24
-rw-r--r--freebsd/contrib/wpa/src/utils/wpabuf.c30
-rw-r--r--freebsd/contrib/wpa/src/utils/wpabuf.h17
-rw-r--r--freebsd/contrib/wpa/src/wps/wps.c6
-rw-r--r--freebsd/contrib/wpa/src/wps/wps.h14
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_build.c31
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_parse.c4
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_process.c10
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_common.c47
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_defs.h4
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_enrollee.c33
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_i.h4
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_registrar.c77
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp.c11
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp.h3
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp_i.h3
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c6
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp_web.c88
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ap.h10
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/autoscan.h10
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/bgscan.h9
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/binder/binder.h46
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/bss.c97
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/bss.h20
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config.c190
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config.h88
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config_file.c45
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config_ssid.h45
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c1051
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c358
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h7
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/driver_i.h82
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/events.c529
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/gas_query.c154
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/gas_query.h2
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c313
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h15
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ibss_rsn.h3
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/interworking.c231
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/interworking.h3
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/main.c96
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/mesh.h3
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/mesh_mpm.h5
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/mesh_rsn.h11
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/notify.c25
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/notify.h3
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/offchannel.c52
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h26
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/scan.c471
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/scan.h13
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wmm_ac.h2
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h2
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c1197
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h148
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c11
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c46
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h7
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/a_bool.c24
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/a_object.c21
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/a_strex.c27
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/ameth_lib.c14
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/asn1.h8
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/asn1_err.c3
-rw-r--r--freebsd/crypto/openssl/crypto/asn1/tasn_enc.c4
-rw-r--r--freebsd/crypto/openssl/crypto/bio/bss_log.c4
-rw-r--r--freebsd/crypto/openssl/crypto/bio/bss_mem.c2
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn.h106
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_div.c1
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_exp.c69
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_gf2m.c34
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_lcl.h3
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_lib.c57
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_mod.c69
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_mont.c58
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_sqr.c10
-rw-r--r--freebsd/crypto/openssl/crypto/bn_int.h15
-rw-r--r--freebsd/crypto/openssl/crypto/conf/conf_api.c2
-rw-r--r--freebsd/crypto/openssl/crypto/dh/dh_key.c7
-rw-r--r--freebsd/crypto/openssl/crypto/dh/dh_pmeth.c4
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa.h9
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_err.c3
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_gen.c13
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c73
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c12
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec_ameth.c22
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec_lib.c10
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c23
-rw-r--r--freebsd/crypto/openssl/crypto/ecdsa/ecdsatest.c11
-rw-r--r--freebsd/crypto/openssl/crypto/ecdsa/ecs_ossl.c32
-rw-r--r--freebsd/crypto/openssl/crypto/engine/eng_lib.c8
-rw-r--r--freebsd/crypto/openssl/crypto/engine/tb_asnmth.c4
-rw-r--r--freebsd/crypto/openssl/crypto/o_time.c4
-rw-r--r--freebsd/crypto/openssl/crypto/opensslv.h6
-rw-r--r--freebsd/crypto/openssl/crypto/pem/pem.h3
-rw-r--r--freebsd/crypto/openssl/crypto/pem/pem_lib.c59
-rw-r--r--freebsd/crypto/openssl/crypto/pem/pem_pk8.c2
-rw-r--r--freebsd/crypto/openssl/crypto/pem/pem_pkey.c2
-rw-r--r--freebsd/crypto/openssl/crypto/pem/pvkfmt.c4
-rw-r--r--freebsd/crypto/openssl/crypto/pkcs12/p12_asn.c4
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_eay.c41
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_gen.c2
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c41
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c62
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_sign.c4
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c8
-rw-r--r--freebsd/crypto/openssl/crypto/ui/ui_openssl.c8
-rw-r--r--freebsd/crypto/openssl/crypto/x509/x509_cmp.c2
-rw-r--r--freebsd/crypto/openssl/crypto/x509/x509_lu.c16
-rw-r--r--freebsd/crypto/openssl/crypto/x509/x509_vfy.c147
-rw-r--r--freebsd/crypto/openssl/crypto/x509v3/v3_purp.c27
-rw-r--r--freebsd/crypto/openssl/ssl/d1_both.c5
-rw-r--r--freebsd/crypto/openssl/ssl/s3_lib.c12
-rw-r--r--freebsd/crypto/openssl/ssl/s3_srvr.c26
-rw-r--r--freebsd/crypto/openssl/ssl/ssl.h7
-rw-r--r--freebsd/crypto/openssl/ssl/ssl_lib.c31
-rw-r--r--freebsd/crypto/openssl/ssl/ssl_locl.h4
-rw-r--r--freebsd/crypto/openssl/ssl/t1_lib.c5
-rw-r--r--freebsd/crypto/openssl/ssl/t1_trce.c16
-rw-r--r--freebsd/include/nl_types.h99
-rw-r--r--freebsd/lib/libc/gen/err.c4
-rw-r--r--freebsd/lib/libc/gen/getdomainname.c4
-rw-r--r--freebsd/lib/libc/gen/gethostname.c4
-rw-r--r--freebsd/lib/libc/gen/sethostname.c4
-rw-r--r--freebsd/lib/libc/include/libc_private.h2
-rw-r--r--freebsd/lib/libc/include/namespace.h1
-rw-r--r--freebsd/lib/libc/include/un-namespace.h1
-rw-r--r--freebsd/lib/libc/inet/inet_addr.c7
-rw-r--r--freebsd/lib/libc/resolv/res_init.c2
-rw-r--r--freebsd/lib/libcapsicum/capsicum_helpers.h149
-rw-r--r--freebsd/lib/libcasper/libcasper/libcasper.h6
-rw-r--r--freebsd/lib/libkvm/kvm.h4
-rw-r--r--freebsd/lib/libutil/libutil.h1
-rw-r--r--freebsd/sbin/dhclient/bpf.c8
-rw-r--r--freebsd/sbin/dhclient/clparse.c5
-rw-r--r--freebsd/sbin/dhclient/conflex.c5
-rw-r--r--freebsd/sbin/dhclient/dhclient.c78
-rw-r--r--freebsd/sbin/dhclient/dhcpd.h4
-rw-r--r--freebsd/sbin/dhclient/dispatch.c22
-rw-r--r--freebsd/sbin/dhclient/options.c4
-rw-r--r--freebsd/sbin/dhclient/privsep.c6
-rw-r--r--freebsd/sbin/dhclient/privsep.h5
-rw-r--r--freebsd/sbin/ifconfig/ifconfig.c2
-rw-r--r--freebsd/sbin/ifconfig/ifieee80211.c20
-rw-r--r--freebsd/sbin/pfctl/parse.c4272
-rw-r--r--freebsd/sbin/pfctl/parse.h127
-rw-r--r--freebsd/sbin/pfctl/parse.y51
-rw-r--r--freebsd/sbin/pfctl/pfctl.c97
-rw-r--r--freebsd/sbin/pfctl/pfctl_altq.c69
-rw-r--r--freebsd/sbin/pfctl/pfctl_parser.c6
-rw-r--r--freebsd/sbin/pfctl/pfctl_parser.h4
-rw-r--r--freebsd/sbin/pfctl/pfctl_qstats.c10
-rw-r--r--freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h4
-rw-r--r--freebsd/sbin/pfctl/rtems-bsd-pfctl-parse-data.h1
-rw-r--r--freebsd/sbin/sysctl/sysctl.c40
-rw-r--r--freebsd/sys/arm/include/machine/cpufunc.h157
-rw-r--r--freebsd/sys/cam/cam_ccb.h42
-rw-r--r--freebsd/sys/cam/cam_xpt.h1
-rw-r--r--freebsd/sys/cam/mmc/mmc.h8
-rw-r--r--freebsd/sys/contrib/ck/include/ck_pr.h49
-rw-r--r--freebsd/sys/contrib/ck/include/ck_queue.h14
-rw-r--r--freebsd/sys/contrib/ck/include/gcc/ppc/ck_pr.h32
-rw-r--r--freebsd/sys/contrib/ck/include/gcc/x86/ck_pr.h10
-rw-r--r--freebsd/sys/contrib/ck/include/gcc/x86_64/ck_pr.h10
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c126
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h12
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h235
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c92
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h21
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c100
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h67
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_16.h23
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_32.h23
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_64.h23
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/export.h57
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/common.h246
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/implementations.h11
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/randombytes.h68
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/runtime.h52
-rw-r--r--freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/utils.h170
-rw-r--r--freebsd/sys/crypto/chacha20/chacha.c11
-rw-r--r--freebsd/sys/crypto/chacha20/chacha.h12
-rw-r--r--freebsd/sys/crypto/libsodium/utils.c16
-rw-r--r--freebsd/sys/crypto/sha2/sha224.h96
-rw-r--r--freebsd/sys/crypto/sha2/sha256c.c60
-rw-r--r--freebsd/sys/crypto/sha2/sha512c.c8
-rw-r--r--freebsd/sys/crypto/skein/skein.c3
-rw-r--r--freebsd/sys/dev/bfe/if_bfe.c2
-rw-r--r--freebsd/sys/dev/bge/if_bge.c16
-rw-r--r--freebsd/sys/dev/dc/if_dc.c2
-rw-r--r--freebsd/sys/dev/e1000/if_em.c134
-rw-r--r--freebsd/sys/dev/e1000/if_em.h7
-rw-r--r--freebsd/sys/dev/evdev/cdev.c4
-rw-r--r--freebsd/sys/dev/evdev/evdev.c14
-rw-r--r--freebsd/sys/dev/evdev/evdev.h11
-rw-r--r--freebsd/sys/dev/evdev/evdev_utils.c42
-rw-r--r--freebsd/sys/dev/evdev/input-event-codes.h36
-rw-r--r--freebsd/sys/dev/evdev/input.h6
-rw-r--r--freebsd/sys/dev/evdev/uinput.c6
-rw-r--r--freebsd/sys/dev/fxp/if_fxp.c2
-rw-r--r--freebsd/sys/dev/kbd/kbd.c39
-rw-r--r--freebsd/sys/dev/kbd/kbdreg.h4
-rwxr-xr-xfreebsd/sys/dev/mii/icsphy.c2
-rw-r--r--freebsd/sys/dev/mmc/mmc.c57
-rw-r--r--freebsd/sys/dev/mmc/mmcbrvar.h15
-rw-r--r--freebsd/sys/dev/mmc/mmcsd.c18
-rw-r--r--freebsd/sys/dev/nvme/nvme.h13
-rw-r--r--freebsd/sys/dev/ofw/ofw_bus_subr.c4
-rw-r--r--freebsd/sys/dev/ofw/ofw_fdt.c7
-rw-r--r--freebsd/sys/dev/ofw/ofw_subr.c47
-rw-r--r--freebsd/sys/dev/pci/pci.c257
-rw-r--r--freebsd/sys/dev/pci/pci_user.c113
-rw-r--r--freebsd/sys/dev/pci/pcivar.h64
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/r12a_reg.h10
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/usb/r12au.h1
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_init.c33
-rw-r--r--freebsd/sys/dev/rtwn/rtl8821a/usb/r21au.h1
-rw-r--r--freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_init.c11
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.c65
-rw-r--r--freebsd/sys/dev/usb/controller/usb_controller.c1
-rw-r--r--freebsd/sys/dev/usb/input/uep.c105
-rw-r--r--freebsd/sys/dev/usb/input/ukbd.c20
-rw-r--r--freebsd/sys/dev/usb/input/ums.c12
-rw-r--r--freebsd/sys/dev/usb/net/if_ure.c1
-rw-r--r--freebsd/sys/dev/usb/serial/u3g.c1
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c18
-rw-r--r--freebsd/sys/dev/usb/usb_request.c29
-rw-r--r--freebsd/sys/dev/usb/wlan/if_run.c2
-rw-r--r--freebsd/sys/i386/include/machine/cpufunc.h9
-rw-r--r--freebsd/sys/i386/include/machine/intr_machdep.h190
-rw-r--r--freebsd/sys/kern/init_main.c24
-rw-r--r--freebsd/sys/kern/kern_event.c116
-rw-r--r--freebsd/sys/kern/kern_intr.c193
-rw-r--r--freebsd/sys/kern/kern_sysctl.c102
-rw-r--r--freebsd/sys/kern/kern_time.c4
-rw-r--r--freebsd/sys/kern/subr_blist.c14
-rw-r--r--freebsd/sys/kern/subr_bus.c133
-rw-r--r--freebsd/sys/kern/subr_counter.c15
-rw-r--r--freebsd/sys/kern/subr_gtaskqueue.c18
-rw-r--r--freebsd/sys/kern/subr_hints.c353
-rw-r--r--freebsd/sys/kern/subr_module.c36
-rw-r--r--freebsd/sys/kern/subr_pcpu.c2
-rw-r--r--freebsd/sys/kern/subr_prf.c25
-rwxr-xr-xfreebsd/sys/kern/sys_pipe.c99
-rw-r--r--freebsd/sys/kern/uipc_sockbuf.c79
-rw-r--r--freebsd/sys/kern/uipc_socket.c28
-rw-r--r--freebsd/sys/kern/uipc_syscalls.c97
-rw-r--r--freebsd/sys/kern/uipc_usrreq.c157
-rw-r--r--freebsd/sys/mips/include/machine/cpuregs.h94
-rw-r--r--freebsd/sys/net/altq/altq.h29
-rw-r--r--freebsd/sys/net/altq/altq_cbq.c2
-rw-r--r--freebsd/sys/net/altq/altq_cbq.h6
-rw-r--r--freebsd/sys/net/altq/altq_codel.c2
-rw-r--r--freebsd/sys/net/altq/altq_codel.h6
-rw-r--r--freebsd/sys/net/altq/altq_fairq.c2
-rw-r--r--freebsd/sys/net/altq/altq_fairq.h6
-rw-r--r--freebsd/sys/net/altq/altq_hfsc.c161
-rw-r--r--freebsd/sys/net/altq/altq_hfsc.h97
-rw-r--r--freebsd/sys/net/altq/altq_priq.c2
-rw-r--r--freebsd/sys/net/altq/altq_priq.h6
-rw-r--r--freebsd/sys/net/altq/altq_subr.c58
-rw-r--r--freebsd/sys/net/altq/altq_var.h13
-rw-r--r--freebsd/sys/net/altq/if_altq.h4
-rw-r--r--freebsd/sys/net/bpf.c16
-rw-r--r--freebsd/sys/net/bpf_jitter.c6
-rw-r--r--freebsd/sys/net/bpf_jitter.h1
-rw-r--r--freebsd/sys/net/bpfdesc.h5
-rw-r--r--freebsd/sys/net/ieee8023ad_lacp.c69
-rw-r--r--freebsd/sys/net/if.c89
-rw-r--r--freebsd/sys/net/if_bridge.c24
-rw-r--r--freebsd/sys/net/if_clone.c2
-rw-r--r--freebsd/sys/net/if_disc.c2
-rw-r--r--freebsd/sys/net/if_edsc.c2
-rw-r--r--freebsd/sys/net/if_enc.c12
-rw-r--r--freebsd/sys/net/if_epair.c17
-rw-r--r--freebsd/sys/net/if_ethersubr.c7
-rw-r--r--freebsd/sys/net/if_gif.c547
-rw-r--r--freebsd/sys/net/if_gif.h58
-rw-r--r--freebsd/sys/net/if_gre.c668
-rw-r--r--freebsd/sys/net/if_gre.h46
-rw-r--r--freebsd/sys/net/if_ipsec.c8
-rw-r--r--freebsd/sys/net/if_lagg.c32
-rw-r--r--freebsd/sys/net/if_llatbl.c7
-rw-r--r--freebsd/sys/net/if_loop.c3
-rw-r--r--freebsd/sys/net/if_media.h168
-rw-r--r--freebsd/sys/net/if_stf.c42
-rw-r--r--freebsd/sys/net/if_tun.c2
-rw-r--r--freebsd/sys/net/if_var.h31
-rw-r--r--freebsd/sys/net/if_vlan.c17
-rw-r--r--freebsd/sys/net/if_vlan_var.h3
-rw-r--r--freebsd/sys/net/iflib.h10
-rw-r--r--freebsd/sys/net/netisr.c2
-rw-r--r--freebsd/sys/net/pfvar.h120
-rw-r--r--freebsd/sys/net/radix.c2
-rw-r--r--freebsd/sys/net/radix.h26
-rw-r--r--freebsd/sys/net/radix_mpath.c3
-rw-r--r--freebsd/sys/net/route.c9
-rw-r--r--freebsd/sys/net/route.h6
-rw-r--r--freebsd/sys/net/route_var.h19
-rw-r--r--freebsd/sys/net/rtsock.c14
-rw-r--r--freebsd/sys/net/vnet.h20
-rw-r--r--freebsd/sys/net80211/ieee80211.c23
-rw-r--r--freebsd/sys/net80211/ieee80211_hwmp.c2
-rw-r--r--freebsd/sys/net80211/ieee80211_node.c19
-rw-r--r--freebsd/sys/netinet/cc/cc_newreno.c8
-rw-r--r--freebsd/sys/netinet/if_ether.c12
-rw-r--r--freebsd/sys/netinet/igmp.c26
-rw-r--r--freebsd/sys/netinet/in.c9
-rw-r--r--freebsd/sys/netinet/in_fib.c4
-rw-r--r--freebsd/sys/netinet/in_gif.c311
-rw-r--r--freebsd/sys/netinet/in_gif.h45
-rw-r--r--freebsd/sys/netinet/in_kdtrace.h23
-rw-r--r--freebsd/sys/netinet/in_mcast.c39
-rw-r--r--freebsd/sys/netinet/in_pcb.c589
-rw-r--r--freebsd/sys/netinet/in_pcb.h167
-rw-r--r--freebsd/sys/netinet/ip.h5
-rw-r--r--freebsd/sys/netinet/ip6.h1
-rw-r--r--freebsd/sys/netinet/ip_carp.c46
-rw-r--r--freebsd/sys/netinet/ip_divert.c49
-rw-r--r--freebsd/sys/netinet/ip_encap.c470
-rw-r--r--freebsd/sys/netinet/ip_encap.h47
-rw-r--r--freebsd/sys/netinet/ip_fastfwd.c26
-rw-r--r--freebsd/sys/netinet/ip_fw.h2
-rw-r--r--freebsd/sys/netinet/ip_gre.c243
-rw-r--r--freebsd/sys/netinet/ip_icmp.c24
-rw-r--r--freebsd/sys/netinet/ip_id.c20
-rw-r--r--freebsd/sys/netinet/ip_input.c10
-rw-r--r--freebsd/sys/netinet/ip_mroute.c86
-rw-r--r--freebsd/sys/netinet/ip_options.c4
-rw-r--r--freebsd/sys/netinet/ip_output.c71
-rw-r--r--freebsd/sys/netinet/ip_reass.c203
-rw-r--r--freebsd/sys/netinet/libalias/alias.c12
-rw-r--r--freebsd/sys/netinet/libalias/alias_irc.c3
-rw-r--r--freebsd/sys/netinet/libalias/alias_mod.h8
-rw-r--r--freebsd/sys/netinet/pim_var.h2
-rw-r--r--freebsd/sys/netinet/raw_ip.c102
-rw-r--r--freebsd/sys/netinet/sctp.h2
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c39
-rw-r--r--freebsd/sys/netinet/sctp_asconf.h4
-rw-r--r--freebsd/sys/netinet/sctp_auth.c8
-rw-r--r--freebsd/sys/netinet/sctp_auth.h40
-rw-r--r--freebsd/sys/netinet/sctp_bsd_addr.c2
-rw-r--r--freebsd/sys/netinet/sctp_cc_functions.c10
-rw-r--r--freebsd/sys/netinet/sctp_constants.h12
-rw-r--r--freebsd/sys/netinet/sctp_dtrace_define.h2
-rw-r--r--freebsd/sys/netinet/sctp_header.h26
-rw-r--r--freebsd/sys/netinet/sctp_indata.c66
-rw-r--r--freebsd/sys/netinet/sctp_indata.h3
-rw-r--r--freebsd/sys/netinet/sctp_input.c154
-rw-r--r--freebsd/sys/netinet/sctp_input.h2
-rw-r--r--freebsd/sys/netinet/sctp_os_bsd.h2
-rw-r--r--freebsd/sys/netinet/sctp_output.c145
-rw-r--r--freebsd/sys/netinet/sctp_output.h10
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c67
-rw-r--r--freebsd/sys/netinet/sctp_pcb.h14
-rw-r--r--freebsd/sys/netinet/sctp_peeloff.c6
-rw-r--r--freebsd/sys/netinet/sctp_structs.h57
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.c2
-rw-r--r--freebsd/sys/netinet/sctp_timer.c23
-rw-r--r--freebsd/sys/netinet/sctp_uio.h71
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c71
-rw-r--r--freebsd/sys/netinet/sctp_var.h4
-rw-r--r--freebsd/sys/netinet/sctputil.c112
-rw-r--r--freebsd/sys/netinet/sctputil.h31
-rw-r--r--freebsd/sys/netinet/tcp_hostcache.c4
-rw-r--r--freebsd/sys/netinet/tcp_hpts.h4
-rw-r--r--freebsd/sys/netinet/tcp_input.c167
-rw-r--r--freebsd/sys/netinet/tcp_log_buf.h6
-rw-r--r--freebsd/sys/netinet/tcp_output.c245
-rw-r--r--freebsd/sys/netinet/tcp_reass.c975
-rw-r--r--freebsd/sys/netinet/tcp_subr.c165
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c92
-rw-r--r--freebsd/sys/netinet/tcp_syncache.h1
-rw-r--r--freebsd/sys/netinet/tcp_timer.c197
-rw-r--r--freebsd/sys/netinet/tcp_timer.h17
-rw-r--r--freebsd/sys/netinet/tcp_timewait.c116
-rw-r--r--freebsd/sys/netinet/tcp_usrreq.c238
-rw-r--r--freebsd/sys/netinet/tcp_var.h56
-rw-r--r--freebsd/sys/netinet/udp_usrreq.c105
-rw-r--r--freebsd/sys/netinet/udplite.h11
-rw-r--r--freebsd/sys/netinet6/frag6.c331
-rw-r--r--freebsd/sys/netinet6/icmp6.c11
-rw-r--r--freebsd/sys/netinet6/in6.c3
-rw-r--r--freebsd/sys/netinet6/in6_fib.c4
-rw-r--r--freebsd/sys/netinet6/in6_gif.c337
-rw-r--r--freebsd/sys/netinet6/in6_ifattach.c2
-rw-r--r--freebsd/sys/netinet6/in6_mcast.c46
-rw-r--r--freebsd/sys/netinet6/in6_pcb.c189
-rw-r--r--freebsd/sys/netinet6/in6_proto.c37
-rw-r--r--freebsd/sys/netinet6/in6_rmx.c4
-rw-r--r--freebsd/sys/netinet6/in6_src.c6
-rw-r--r--freebsd/sys/netinet6/in6_var.h2
-rw-r--r--freebsd/sys/netinet6/ip6_input.c4
-rw-r--r--freebsd/sys/netinet6/ip6_mroute.c55
-rw-r--r--freebsd/sys/netinet6/ip6_output.c57
-rw-r--r--freebsd/sys/netinet6/ip6_var.h8
-rw-r--r--freebsd/sys/netinet6/mld6.c43
-rw-r--r--freebsd/sys/netinet6/nd6.c6
-rw-r--r--freebsd/sys/netinet6/nd6_nbr.c8
-rw-r--r--freebsd/sys/netinet6/nd6_rtr.c2
-rw-r--r--freebsd/sys/netinet6/pim6_var.h4
-rw-r--r--freebsd/sys/netinet6/raw_ip6.c7
-rw-r--r--freebsd/sys/netinet6/scope6.c4
-rw-r--r--freebsd/sys/netinet6/scope6_var.h2
-rw-r--r--freebsd/sys/netinet6/sctp6_usrreq.c9
-rw-r--r--freebsd/sys/netinet6/sctp6_var.h4
-rw-r--r--freebsd/sys/netinet6/udp6_usrreq.c450
-rw-r--r--freebsd/sys/netipsec/ipsec.c17
-rw-r--r--freebsd/sys/netipsec/ipsec.h2
-rw-r--r--freebsd/sys/netipsec/key.c78
-rw-r--r--freebsd/sys/netipsec/key_debug.c87
-rw-r--r--freebsd/sys/netipsec/keydb.h3
-rw-r--r--freebsd/sys/netipsec/keysock.c2
-rw-r--r--freebsd/sys/netipsec/xform.h2
-rw-r--r--freebsd/sys/netipsec/xform_ah.c83
-rw-r--r--freebsd/sys/netipsec/xform_esp.c21
-rw-r--r--freebsd/sys/netipsec/xform_ipcomp.c87
-rw-r--r--freebsd/sys/netipsec/xform_tcp.c16
-rw-r--r--freebsd/sys/netpfil/pf/if_pflog.c2
-rw-r--r--freebsd/sys/netpfil/pf/if_pfsync.c10
-rw-r--r--freebsd/sys/netpfil/pf/pf.c206
-rw-r--r--freebsd/sys/netpfil/pf/pf_altq.h145
-rw-r--r--freebsd/sys/netpfil/pf/pf_if.c41
-rw-r--r--freebsd/sys/netpfil/pf/pf_ioctl.c310
-rw-r--r--freebsd/sys/netpfil/pf/pf_norm.c16
-rw-r--r--freebsd/sys/netpfil/pf/pf_osfp.c2
-rw-r--r--freebsd/sys/netpfil/pf/pf_table.c10
-rw-r--r--freebsd/sys/opencrypto/_cryptodev.h8
-rw-r--r--freebsd/sys/opencrypto/crypto.c174
-rw-r--r--freebsd/sys/opencrypto/cryptodev.c55
-rw-r--r--freebsd/sys/opencrypto/cryptodev.h64
-rw-r--r--freebsd/sys/opencrypto/cryptosoft.c335
-rw-r--r--freebsd/sys/opencrypto/cryptosoft.h5
-rw-r--r--freebsd/sys/opencrypto/xform_auth.h7
-rw-r--r--freebsd/sys/opencrypto/xform_md5.c4
-rw-r--r--freebsd/sys/opencrypto/xform_poly1305.c93
-rw-r--r--freebsd/sys/opencrypto/xform_poly1305.h16
-rw-r--r--freebsd/sys/opencrypto/xform_rmd160.c4
-rw-r--r--freebsd/sys/opencrypto/xform_sha1.c16
-rw-r--r--freebsd/sys/opencrypto/xform_sha2.c81
-rw-r--r--freebsd/sys/powerpc/include/machine/spr.h4
-rw-r--r--freebsd/sys/sys/bus.h9
-rw-r--r--freebsd/sys/sys/cpu.h2
-rw-r--r--freebsd/sys/sys/file.h13
-rw-r--r--freebsd/sys/sys/interrupt.h13
-rw-r--r--freebsd/sys/sys/jail.h5
-rw-r--r--freebsd/sys/sys/libkern.h23
-rw-r--r--freebsd/sys/sys/linker.h3
-rw-r--r--freebsd/sys/sys/malloc.h76
-rw-r--r--freebsd/sys/sys/mbuf.h7
-rw-r--r--freebsd/sys/sys/module.h5
-rw-r--r--freebsd/sys/sys/mouse.h15
-rw-r--r--freebsd/sys/sys/mutex.h2
-rw-r--r--freebsd/sys/sys/nv.h8
-rw-r--r--freebsd/sys/sys/pciio.h19
-rw-r--r--freebsd/sys/sys/pcpu.h59
-rw-r--r--freebsd/sys/sys/proc.h21
-rw-r--r--freebsd/sys/sys/random.h42
-rw-r--r--freebsd/sys/sys/reboot.h9
-rw-r--r--freebsd/sys/sys/sglist.h113
-rw-r--r--freebsd/sys/sys/sockbuf.h8
-rw-r--r--freebsd/sys/sys/socketvar.h17
-rw-r--r--freebsd/sys/sys/sockopt.h1
-rw-r--r--freebsd/sys/sys/sx.h4
-rw-r--r--freebsd/sys/sys/sysproto.h4
-rw-r--r--freebsd/sys/sys/systm.h121
-rw-r--r--freebsd/sys/sys/unpcb.h23
-rw-r--r--freebsd/sys/sys/vmmeter.h7
-rw-r--r--freebsd/sys/vm/uma.h23
-rw-r--r--freebsd/sys/vm/uma_core.c326
-rw-r--r--freebsd/sys/vm/uma_int.h53
-rw-r--r--freebsd/sys/vm/vm_extern.h9
-rw-r--r--freebsd/usr.bin/netstat/inet.c4
-rw-r--r--freebsd/usr.bin/netstat/unix.c2
-rw-r--r--freebsd/usr.bin/vmstat/vmstat.c92
-rw-r--r--libbsd.py554
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h102
-rw-r--r--rtemsbsd/include/rtems/bsd/local/cryptodev_if.h36
-rw-r--r--rtemsbsd/include/rtems/bsd/local/sdhci_if.h24
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usbdevs.h109
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usbdevs_data.h546
-rw-r--r--rtemsbsd/include/sys/boot.h0
-rw-r--r--rtemsbsd/include/sys/epoch.h4
-rw-r--r--rtemsbsd/include/sys/kpilite.h0
-rw-r--r--rtemsbsd/include/vm/vm_pager.h0
-rw-r--r--rtemsbsd/local/cryptodev_if.c29
-rw-r--r--rtemsbsd/local/ifdi_if.c106
-rw-r--r--rtemsbsd/local/sdhci_if.c4
-rw-r--r--rtemsbsd/rtems/rtems-kernel-epoch.c25
-rw-r--r--rtemsbsd/sys/arm/at91/at91_mci.c (renamed from freebsd/sys/arm/at91/at91_mci.c)0
-rw-r--r--rtemsbsd/sys/arm/at91/at91_mcireg.h (renamed from freebsd/sys/arm/at91/at91_mcireg.h)0
-rw-r--r--rtemsbsd/sys/arm/at91/at91_pdcreg.h (renamed from freebsd/sys/arm/at91/at91_pdcreg.h)0
-rw-r--r--rtemsbsd/sys/arm/at91/at91reg.h (renamed from freebsd/sys/arm/at91/at91reg.h)0
-rw-r--r--rtemsbsd/sys/arm/at91/at91var.h (renamed from freebsd/sys/arm/at91/at91var.h)0
-rw-r--r--testsuite/epoch01/test_main.c17
579 files changed, 26579 insertions, 11218 deletions
diff --git a/Makefile.todo b/Makefile.todo
index 35fdacd4..1c1c395c 100644
--- a/Makefile.todo
+++ b/Makefile.todo
@@ -11,6 +11,8 @@ FREEBSD_SRC = freebsd-org
TOOLS = freebsd-org/sys/tools
GENERATED =
+GENERATED += $(LOCAL_INC)/cryptodev_if.h
+GENERATED += $(LOCAL_SRC)/cryptodev_if.c
GENERATED += $(LOCAL_INC)/usb_if.h
GENERATED += $(LOCAL_SRC)/usb_if.c
GENERATED += $(LOCAL_INC)/bus_if.h
@@ -62,12 +64,12 @@ YACC_GENERATED += freebsd/contrib/libpcap/grammar.c
LEX_GENERATED += freebsd/contrib/libpcap/scanner.h
LEX_GENERATED += freebsd/contrib/libpcap/scanner.c
+all: yacc lex $(GENERATED)
+
yacc: $(YACC_GENERATED)
lex: $(LEX_GENERATED)
-all: yacc lex $(GENERATED)
-
program-header:
cd freebsd/bin/stty && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/bin/stty/*.o -p stty
cd freebsd/contrib/tcpdump && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/contrib/tcpdump/*.o -p tcpdump
@@ -89,6 +91,14 @@ $(LOCAL_INC)/usbdevs_data.h: $(FREEBSD_SRC)/sys/dev/usb/usbdevs
awk -f $(TOOLS)/usbdevs2h.awk $< -d
mv usbdevs_data.h $@
+$(LOCAL_INC)/cryptodev_if.h: $(FREEBSD_SRC)/sys/opencrypto/cryptodev_if.m
+ awk -f $(TOOLS)/makeobjops.awk $< -h
+ mv cryptodev_if.h $@
+
+$(LOCAL_SRC)/cryptodev_if.c: $(FREEBSD_SRC)/sys/opencrypto/cryptodev_if.m
+ awk -f $(TOOLS)/makeobjops.awk $< -c
+ mv cryptodev_if.c $@
+
$(LOCAL_INC)/usb_if.h: $(FREEBSD_SRC)/sys/dev/usb/usb_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv usb_if.h $@
diff --git a/freebsd-org b/freebsd-org
-Subproject fb63610a69b0eb7f69a201ba05c4c1a7a2739cf
+Subproject 6c2192b1ef8c50788c751f878552526800b1e31
diff --git a/freebsd/contrib/tcpdump/tcpdump.c b/freebsd/contrib/tcpdump/tcpdump.c
index 75896da3..fbee78ce 100644
--- a/freebsd/contrib/tcpdump/tcpdump.c
+++ b/freebsd/contrib/tcpdump/tcpdump.c
@@ -2210,6 +2210,9 @@ main(int argc, char **argv)
#else
cansandbox = (cansandbox && ndo->ndo_nflag);
#endif /* HAVE_CASPER */
+ cansandbox = (cansandbox && (pcap_fileno(pd) != -1 ||
+ RFileName != NULL));
+
if (cansandbox && cap_enter() < 0 && errno != ENOSYS)
error("unable to enter the capability mode");
#endif /* HAVE_CAPSICUM */
diff --git a/freebsd/contrib/wpa/src/ap/ap_config.h b/freebsd/contrib/wpa/src/ap/ap_config.h
index de470a96..8c8f7e28 100644
--- a/freebsd/contrib/wpa/src/ap/ap_config.h
+++ b/freebsd/contrib/wpa/src/ap/ap_config.h
@@ -10,12 +10,14 @@
#define HOSTAPD_CONFIG_H
#include "common/defs.h"
+#include "utils/list.h"
#include "ip_addr.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wps/wps.h"
#include "fst/fst.h"
+#include "vlan.h"
/**
* mesh_conf - local MBSS state and settings
@@ -39,6 +41,10 @@ struct mesh_conf {
#define MESH_CONF_SEC_AUTH BIT(1)
#define MESH_CONF_SEC_AMPE BIT(2)
unsigned int security;
+ enum mfp_options ieee80211w;
+ unsigned int pairwise_cipher;
+ unsigned int group_cipher;
+ unsigned int mgmt_group_cipher;
int dot11MeshMaxRetries;
int dot11MeshRetryTimeout; /* msec */
int dot11MeshConfirmTimeout; /* msec */
@@ -52,7 +58,7 @@ typedef u8 macaddr[ETH_ALEN];
struct mac_acl_entry {
macaddr addr;
- int vlan_id;
+ struct vlan_description vlan_id;
};
struct hostapd_radius_servers;
@@ -102,6 +108,7 @@ struct hostapd_ssid {
#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
#define DYNAMIC_VLAN_NAMING_END 2
int vlan_naming;
+ int per_sta_vif;
#ifdef CONFIG_FULL_DYNAMIC_VLAN
char *vlan_tagged_interface;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
@@ -113,6 +120,7 @@ struct hostapd_ssid {
struct hostapd_vlan {
struct hostapd_vlan *next;
int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
+ struct vlan_description vlan_desc;
char ifname[IFNAMSIZ + 1];
int configured;
int dynamic_vlan;
@@ -124,9 +132,14 @@ struct hostapd_vlan {
};
#define PMK_LEN 32
+#define MIN_PASSPHRASE_LEN 8
+#define MAX_PASSPHRASE_LEN 63
struct hostapd_sta_wpa_psk_short {
struct hostapd_sta_wpa_psk_short *next;
+ unsigned int is_passphrase:1;
u8 psk[PMK_LEN];
+ char passphrase[MAX_PASSPHRASE_LEN + 1];
+ int ref; /* (number of references held) - 1 */
};
struct hostapd_wpa_psk {
@@ -205,6 +218,13 @@ struct hostapd_nai_realm_data {
} eap_method[MAX_NAI_EAP_METHODS];
};
+struct anqp_element {
+ struct dl_list list;
+ u16 infoid;
+ struct wpabuf *payload;
+};
+
+
/**
* struct hostapd_bss_config - Per-BSS configuration
*/
@@ -231,6 +251,7 @@ struct hostapd_bss_config {
struct hostapd_eap_user *eap_user;
char *eap_user_sqlite;
char *eap_sim_db;
+ unsigned int eap_sim_db_timeout;
int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
struct hostapd_ip_addr own_ip_addr;
char *nas_identifier;
@@ -242,6 +263,7 @@ struct hostapd_bss_config {
int radius_das_port;
unsigned int radius_das_time_window;
int radius_das_require_event_timestamp;
+ int radius_das_require_message_authenticator;
struct hostapd_ip_addr radius_das_client_addr;
u8 *radius_das_shared_secret;
size_t radius_das_shared_secret_len;
@@ -332,6 +354,7 @@ struct hostapd_bss_config {
int check_crl;
unsigned int tls_session_lifetime;
char *ocsp_stapling_response;
+ char *ocsp_stapling_response_multi;
char *dh_file;
char *openssl_ciphers;
u8 *pac_opaque_encr_key;
@@ -358,6 +381,7 @@ struct hostapd_bss_config {
int ap_max_inactivity;
int ignore_broadcast_ssid;
+ int no_probe_resp_if_max_sta;
int wmm_enabled;
int wmm_uapsd;
@@ -481,8 +505,11 @@ struct hostapd_bss_config {
unsigned int nai_realm_count;
struct hostapd_nai_realm_data *nai_realm_data;
+ struct dl_list anqp_elem; /* list of struct anqp_element */
+
u16 gas_comeback_delay;
int gas_frag_limit;
+ int gas_address3;
u8 qos_map_set[16 + 2 * 21];
unsigned int qos_map_set_len;
@@ -536,6 +563,7 @@ struct hostapd_bss_config {
#endif /* CONFIG_RADIUS_TEST */
struct wpabuf *vendor_elements;
+ struct wpabuf *assocresp_elements;
unsigned int sae_anti_clogging_threshold;
int *sae_groups;
@@ -551,12 +579,22 @@ struct hostapd_bss_config {
#define MESH_ENABLED BIT(0)
int mesh;
- int radio_measurements;
+ u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
int vendor_vht;
+ int use_sta_nsts;
char *no_probe_resp_if_seen_on;
char *no_auth_if_seen_on;
+
+ int pbss;
+
+#ifdef CONFIG_MBO
+ int mbo_enabled;
+#endif /* CONFIG_MBO */
+
+ int ftm_responder;
+ int ftm_initiator;
};
@@ -638,6 +676,9 @@ struct hostapd_config {
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+ /* Use driver-generated interface addresses when adding multiple BSSs */
+ u8 use_driver_iface_addr;
+
#ifdef CONFIG_FST
struct fst_iface_cfg fst_cfg;
#endif /* CONFIG_FST */
@@ -652,6 +693,7 @@ struct hostapd_config {
double ignore_assoc_probability;
double ignore_reassoc_probability;
double corrupt_gtk_rekey_mic_probability;
+ int ecsa_ie_only;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_ACS
@@ -662,11 +704,13 @@ struct hostapd_config {
} *acs_chan_bias;
unsigned int num_acs_chan_bias;
#endif /* CONFIG_ACS */
+
+ struct wpabuf *lci;
+ struct wpabuf *civic;
};
int hostapd_mac_comp(const void *a, const void *b);
-int hostapd_mac_comp_empty(const void *a);
struct hostapd_config * hostapd_config_defaults(void);
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
@@ -674,13 +718,14 @@ void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
void hostapd_config_free_bss(struct hostapd_bss_config *conf);
void hostapd_config_free(struct hostapd_config *conf);
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
- const u8 *addr, int *vlan_id);
+ const u8 *addr, struct vlan_description *vlan_id);
int hostapd_rate_found(int *list, int rate);
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
-int hostapd_vlan_id_valid(struct hostapd_vlan *vlan, int vlan_id);
+int hostapd_vlan_valid(struct hostapd_vlan *vlan,
+ struct vlan_description *vlan_desc);
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
int vlan_id);
struct hostapd_radius_attr *
diff --git a/freebsd/contrib/wpa/src/ap/ap_drv_ops.c b/freebsd/contrib/wpa/src/ap/ap_drv_ops.c
index d20ee93f..c0111c37 100644
--- a/freebsd/contrib/wpa/src/ap/ap_drv_ops.c
+++ b/freebsd/contrib/wpa/src/ap/ap_drv_ops.c
@@ -35,10 +35,36 @@ u32 hostapd_sta_flags_to_drv(u32 flags)
res |= WPA_STA_SHORT_PREAMBLE;
if (flags & WLAN_STA_MFP)
res |= WPA_STA_MFP;
+ if (flags & WLAN_STA_AUTH)
+ res |= WPA_STA_AUTHENTICATED;
+ if (flags & WLAN_STA_ASSOC)
+ res |= WPA_STA_ASSOCIATED;
return res;
}
+static int add_buf(struct wpabuf **dst, const struct wpabuf *src)
+{
+ if (!src)
+ return 0;
+ if (wpabuf_resize(dst, wpabuf_len(src)) != 0)
+ return -1;
+ wpabuf_put_buf(*dst, src);
+ return 0;
+}
+
+
+static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len)
+{
+ if (!data || !len)
+ return 0;
+ if (wpabuf_resize(dst, len) != 0)
+ return -1;
+ wpabuf_put_data(*dst, data, len);
+ return 0;
+}
+
+
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
struct wpabuf **beacon_ret,
struct wpabuf **proberesp_ret,
@@ -51,82 +77,38 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
pos = buf;
pos = hostapd_eid_time_adv(hapd, pos);
- if (pos != buf) {
- if (wpabuf_resize(&beacon, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(beacon, buf, pos - buf);
- }
+ if (add_buf_data(&beacon, buf, pos - buf) < 0)
+ goto fail;
pos = hostapd_eid_time_zone(hapd, pos);
- if (pos != buf) {
- if (wpabuf_resize(&proberesp, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(proberesp, buf, pos - buf);
- }
+ if (add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
pos = buf;
pos = hostapd_eid_ext_capab(hapd, pos);
- if (pos != buf) {
- if (wpabuf_resize(&assocresp, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(assocresp, buf, pos - buf);
- }
+ if (add_buf_data(&assocresp, buf, pos - buf) < 0)
+ goto fail;
pos = hostapd_eid_interworking(hapd, pos);
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
- if (pos != buf) {
- if (wpabuf_resize(&beacon, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(beacon, buf, pos - buf);
-
- if (wpabuf_resize(&proberesp, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(proberesp, buf, pos - buf);
- }
+ if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
#ifdef CONFIG_FST
- if (hapd->iface->fst_ies) {
- size_t add = wpabuf_len(hapd->iface->fst_ies);
-
- if (wpabuf_resize(&beacon, add) < 0)
- goto fail;
- wpabuf_put_buf(beacon, hapd->iface->fst_ies);
- if (wpabuf_resize(&proberesp, add) < 0)
- goto fail;
- wpabuf_put_buf(proberesp, hapd->iface->fst_ies);
- if (wpabuf_resize(&assocresp, add) < 0)
- goto fail;
- wpabuf_put_buf(assocresp, hapd->iface->fst_ies);
- }
+ if (add_buf(&beacon, hapd->iface->fst_ies) < 0 ||
+ add_buf(&proberesp, hapd->iface->fst_ies) < 0 ||
+ add_buf(&assocresp, hapd->iface->fst_ies) < 0)
+ goto fail;
#endif /* CONFIG_FST */
- if (hapd->wps_beacon_ie) {
- if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
- 0)
- goto fail;
- wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
- }
-
- if (hapd->wps_probe_resp_ie) {
- if (wpabuf_resize(&proberesp,
- wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
- goto fail;
- wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
- }
+ if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
+ add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
+ goto fail;
#ifdef CONFIG_P2P
- if (hapd->p2p_beacon_ie) {
- if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
- 0)
- goto fail;
- wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
- }
-
- if (hapd->p2p_probe_resp_ie) {
- if (wpabuf_resize(&proberesp,
- wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
- goto fail;
- wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
- }
+ if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 ||
+ add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0)
+ goto fail;
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
@@ -150,8 +132,7 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
#ifdef CONFIG_WPS
if (hapd->conf->wps_state) {
struct wpabuf *a = wps_build_assoc_resp_ie();
- if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
- wpabuf_put_buf(assocresp, a);
+ add_buf(&assocresp, a);
wpabuf_free(a);
}
#endif /* CONFIG_WPS */
@@ -171,44 +152,36 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
if (hapd->p2p_group) {
struct wpabuf *a;
a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
- if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
- wpabuf_put_buf(assocresp, a);
+ add_buf(&assocresp, a);
wpabuf_free(a);
}
#endif /* CONFIG_WIFI_DISPLAY */
#ifdef CONFIG_HS20
- pos = buf;
- pos = hostapd_eid_hs20_indication(hapd, pos);
- if (pos != buf) {
- if (wpabuf_resize(&beacon, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(beacon, buf, pos - buf);
-
- if (wpabuf_resize(&proberesp, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(proberesp, buf, pos - buf);
- }
+ pos = hostapd_eid_hs20_indication(hapd, buf);
+ if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
pos = hostapd_eid_osen(hapd, buf);
- if (pos != buf) {
- if (wpabuf_resize(&beacon, pos - buf) != 0)
- goto fail;
- wpabuf_put_data(beacon, buf, pos - buf);
+ if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
+#endif /* CONFIG_HS20 */
- if (wpabuf_resize(&proberesp, pos - buf) != 0)
+#ifdef CONFIG_MBO
+ if (hapd->conf->mbo_enabled) {
+ pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
+ if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0 ||
+ add_buf_data(&assocresp, buf, pos - buf) < 0)
goto fail;
- wpabuf_put_data(proberesp, buf, pos - buf);
}
-#endif /* CONFIG_HS20 */
+#endif /* CONFIG_MBO */
- if (hapd->conf->vendor_elements) {
- size_t add = wpabuf_len(hapd->conf->vendor_elements);
- if (wpabuf_resize(&beacon, add) == 0)
- wpabuf_put_buf(beacon, hapd->conf->vendor_elements);
- if (wpabuf_resize(&proberesp, add) == 0)
- wpabuf_put_buf(proberesp, hapd->conf->vendor_elements);
- }
+ add_buf(&beacon, hapd->conf->vendor_elements);
+ add_buf(&proberesp, hapd->conf->vendor_elements);
+ add_buf(&assocresp, hapd->conf->assocresp_elements);
*beacon_ret = beacon;
*proberesp_ret = proberesp;
@@ -392,7 +365,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
- u32 flags, u8 qosinfo, u8 vht_opmode)
+ u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
+ int set)
{
struct hostapd_sta_add_params params;
@@ -414,6 +388,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.vht_opmode = vht_opmode;
params.flags = hostapd_sta_flags_to_drv(flags);
params.qosinfo = qosinfo;
+ params.support_p2p_ps = supp_p2p_ps;
+ params.set = set;
return hapd->driver->sta_add(hapd->drv_priv, &params);
}
@@ -470,7 +446,7 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
return -1;
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
bss_ctx, drv_priv, force_ifname, if_addr,
- bridge, use_existing);
+ bridge, use_existing, 1);
}
@@ -649,16 +625,28 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
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);
+}
+
+
+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)
+{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
- return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0);
+ return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+ csa_offs, csa_offs_len);
}
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason)
{
- if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
+ if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv)
return 0;
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
reason);
@@ -668,7 +656,7 @@ int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason)
{
- if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
+ if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv)
return 0;
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
reason);
@@ -689,6 +677,36 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
size_t len)
{
+ const u8 *bssid;
+ const u8 wildcard_bssid[ETH_ALEN] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+ if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv)
+ return 0;
+ bssid = hapd->own_addr;
+ if (!is_multicast_ether_addr(dst) &&
+ len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
+ struct sta_info *sta;
+
+ /*
+ * Public Action frames to a STA that is not a member of the BSS
+ * shall use wildcard BSSID value.
+ */
+ sta = ap_get_sta(hapd, dst);
+ if (!sta || !(sta->flags & WLAN_STA_ASSOC))
+ bssid = wildcard_bssid;
+ }
+ return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
+ hapd->own_addr, bssid, data, len, 0);
+}
+
+
+int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
+ unsigned int freq,
+ unsigned int wait, const u8 *dst,
+ const u8 *data, size_t len)
+{
if (hapd->driver == NULL || hapd->driver->send_action == NULL)
return 0;
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
@@ -738,7 +756,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
const u8 *qos_map_set, u8 qos_map_set_len)
{
- if (hapd->driver == NULL || hapd->driver->set_qos_map == NULL)
+ if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
return 0;
return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
qos_map_set_len);
@@ -764,6 +782,20 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
}
+void hostapd_get_ext_capa(struct hostapd_iface *iface)
+{
+ struct hostapd_data *hapd = iface->bss[0];
+
+ if (!hapd->driver || !hapd->driver->get_ext_capab)
+ return;
+
+ hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS,
+ &iface->extended_capa,
+ &iface->extended_capa_mask,
+ &iface->extended_capa_len);
+}
+
+
int hostapd_drv_do_acs(struct hostapd_data *hapd)
{
struct drv_acs_params params;
diff --git a/freebsd/contrib/wpa/src/ap/ap_drv_ops.h b/freebsd/contrib/wpa/src/ap/ap_drv_ops.h
index 82eaf3f0..0bb7954e 100644
--- a/freebsd/contrib/wpa/src/ap/ap_drv_ops.h
+++ b/freebsd/contrib/wpa/src/ap/ap_drv_ops.h
@@ -41,7 +41,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
- u32 flags, u8 qosinfo, u8 vht_opmode);
+ u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
+ int set);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
size_t elem_len);
@@ -88,6 +89,9 @@ int hostapd_drv_set_key(const char *ifname,
const u8 *key, size_t key_len);
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);
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
@@ -95,6 +99,10 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
size_t len);
+int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
+ unsigned int freq,
+ unsigned int wait, const u8 *dst,
+ const u8 *data, size_t len);
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg);
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
@@ -120,6 +128,8 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
int hostapd_drv_set_qos_map(struct hostapd_data *hapd, const u8 *qos_map_set,
u8 qos_map_set_len);
+void hostapd_get_ext_capa(struct hostapd_iface *iface);
+
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
int enabled)
{
@@ -150,7 +160,7 @@ static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
const u8 *addr)
{
- if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
+ if (!hapd->driver || !hapd->driver->sta_remove || !hapd->drv_priv)
return 0;
return hapd->driver->sta_remove(hapd->drv_priv, addr);
}
@@ -273,7 +283,7 @@ static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd,
static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
size_t buflen)
{
- if (hapd->driver == NULL || hapd->driver->status == NULL)
+ if (!hapd->driver || !hapd->driver->status || !hapd->drv_priv)
return -1;
return hapd->driver->status(hapd->drv_priv, buf, buflen);
}
@@ -332,7 +342,7 @@ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
{
- if (hapd->driver == NULL || hapd->driver->stop_ap == NULL)
+ if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
return 0;
return hapd->driver->stop_ap(hapd->drv_priv);
}
diff --git a/freebsd/contrib/wpa/src/ap/hostapd.h b/freebsd/contrib/wpa/src/ap/hostapd.h
index dcf51f00..dec46f69 100644
--- a/freebsd/contrib/wpa/src/ap/hostapd.h
+++ b/freebsd/contrib/wpa/src/ap/hostapd.h
@@ -41,7 +41,7 @@ struct hapd_interfaces {
size_t count;
int global_ctrl_sock;
- struct wpa_ctrl_dst *global_ctrl_dst;
+ struct dl_list global_ctrl_dst;
char *global_iface_path;
char *global_iface_name;
#ifndef CONFIG_NATIVE_WINDOWS
@@ -53,6 +53,7 @@ struct hapd_interfaces {
#ifndef CONFIG_NO_VLAN
struct dynamic_iface *vlan_priv;
#endif /* CONFIG_NO_VLAN */
+ int eloop_initialized;
};
enum hostapd_chan_status {
@@ -99,6 +100,16 @@ struct wps_stat {
u8 peer_addr[ETH_ALEN];
};
+struct hostapd_neighbor_entry {
+ struct dl_list list;
+ u8 bssid[ETH_ALEN];
+ struct wpa_ssid_value ssid;
+ struct wpabuf *nr;
+ struct wpabuf *lci;
+ struct wpabuf *civic;
+ /* LCI update time */
+ struct os_time lci_date;
+};
/**
* struct hostapd_data - hostapd per-BSS data structure
@@ -138,7 +149,7 @@ struct hostapd_data {
void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
struct radius_client_data *radius;
- u32 acct_session_id_hi, acct_session_id_lo;
+ u64 acct_session_id;
struct radius_das_data *radius_das;
struct iapp_data *iapp;
@@ -155,7 +166,7 @@ struct hostapd_data {
int tkip_countermeasures;
int ctrl_sock;
- struct wpa_ctrl_dst *ctrl_dst;
+ struct dl_list ctrl_dst;
void *ssl_ctx;
void *eap_sim_db_priv;
@@ -228,6 +239,8 @@ struct hostapd_data {
unsigned int cs_c_off_beacon;
unsigned int cs_c_off_proberesp;
int csa_in_progress;
+ unsigned int cs_c_off_ecsa_beacon;
+ unsigned int cs_c_off_ecsa_proberesp;
/* BSS Load */
unsigned int bss_load_update_timeout;
@@ -256,9 +269,11 @@ struct hostapd_data {
#ifdef CONFIG_MESH
int num_plinks;
int max_plinks;
- void (*mesh_sta_free_cb)(struct sta_info *sta);
+ void (*mesh_sta_free_cb)(struct hostapd_data *hapd,
+ struct sta_info *sta);
struct wpabuf *mesh_pending_auth;
struct os_reltime mesh_pending_auth_time;
+ u8 mesh_required_peer[ETH_ALEN];
#endif /* CONFIG_MESH */
#ifdef CONFIG_SQLITE
@@ -278,6 +293,17 @@ struct hostapd_data {
struct l2_packet_data *l2_test;
#endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_MBO
+ unsigned int mbo_assoc_disallow;
+#endif /* CONFIG_MBO */
+
+ struct dl_list nr_db;
+
+ u8 lci_req_token;
+ u8 range_req_token;
+ unsigned int lci_req_active:1;
+ unsigned int range_req_active:1;
};
@@ -285,6 +311,9 @@ struct hostapd_sta_info {
struct dl_list list;
u8 addr[ETH_ALEN];
struct os_reltime last_seen;
+#ifdef CONFIG_TAXONOMY
+ struct wpabuf *probe_ie_taxonomy;
+#endif /* CONFIG_TAXONOMY */
};
/**
@@ -327,6 +356,15 @@ struct hostapd_iface {
*/
unsigned int driver_ap_teardown:1;
+ /*
+ * When set, indicates that this interface is part of list of
+ * interfaces that need to be started together (synchronously).
+ */
+ unsigned int need_to_start_in_sync:1;
+
+ /* Ready to start but waiting for other interfaces to become ready. */
+ unsigned int ready_to_start_in_sync:1;
+
int num_ap; /* number of entries in ap_list */
struct ap_info *ap_list; /* AP info list head */
struct ap_info *ap_hash[STA_HASH_SIZE];
@@ -402,6 +440,9 @@ struct hostapd_iface {
u64 last_channel_time_busy;
u8 channel_utilization;
+ /* eCSA IE will be added only if operating class is specified */
+ u8 cs_oper_class;
+
unsigned int dfs_cac_ms;
struct os_reltime dfs_cac_start;
@@ -433,6 +474,7 @@ int hostapd_setup_interface(struct hostapd_iface *iface);
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
void hostapd_interface_deinit(struct hostapd_iface *iface);
void hostapd_interface_free(struct hostapd_iface *iface);
+struct hostapd_iface * hostapd_alloc_iface(void);
struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
const char *config_file);
struct hostapd_iface *
@@ -449,6 +491,7 @@ int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s);
const char * hostapd_state_text(enum hostapd_iface_state s);
+int hostapd_csa_in_progress(struct hostapd_iface *iface);
int hostapd_switch_channel(struct hostapd_data *hapd,
struct csa_settings *settings);
void
@@ -478,6 +521,11 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
int ssi_signal);
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset, int width, int cf1, int cf2);
+struct survey_results;
+void hostapd_event_get_survey(struct hostapd_iface *iface,
+ struct survey_results *survey_results);
+void hostapd_acs_channel_selected(struct hostapd_data *hapd,
+ struct acs_selected_channels *acs_res);
const struct hostapd_eap_user *
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11.h b/freebsd/contrib/wpa/src/ap/ieee802_11.h
index 44c1bff3..0327dec2 100644
--- a/freebsd/contrib/wpa/src/ap/ieee802_11.h
+++ b/freebsd/contrib/wpa/src/ap/ieee802_11.h
@@ -49,9 +49,13 @@ 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_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
-u8 * hostapd_eid_vht_capabilities(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);
+u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_txpower_envelope(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,
const u8 *addr, const u8 *trans_id);
@@ -61,6 +65,7 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
void hostapd_get_vht_capab(struct hostapd_data *hapd,
struct ieee80211_vht_capabilities *vht_cap,
struct ieee80211_vht_capabilities *neg_vht_cap);
+int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab);
u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta,
@@ -97,6 +102,7 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta);
#ifdef CONFIG_SAE
void sae_clear_retransmit_timer(struct hostapd_data *hapd,
struct sta_info *sta);
+void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta);
#else /* CONFIG_SAE */
static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
struct sta_info *sta)
@@ -104,4 +110,29 @@ static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
}
#endif /* CONFIG_SAE */
+#ifdef CONFIG_MBO
+
+u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len);
+
+u8 hostapd_mbo_ie_len(struct hostapd_data *hapd);
+
+#else /* CONFIG_MBO */
+
+static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid,
+ size_t len)
+{
+ return eid;
+}
+
+static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
+{
+ return 0;
+}
+
+#endif /* CONFIG_MBO */
+
+void ap_copy_sta_supp_op_classes(struct sta_info *sta,
+ const u8 *supp_op_classes,
+ size_t supp_op_classes_len);
+
#endif /* IEEE802_11_H */
diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h b/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h
index b66f244b..71f53b96 100644
--- a/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h
+++ b/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h
@@ -16,9 +16,12 @@ enum {
HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
};
+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, int *vlan_id,
+ u32 *acct_interim_interval,
+ struct vlan_description *vlan_id,
struct hostapd_sta_wpa_psk_short **psk,
char **identity, char **radius_cui);
int hostapd_acl_init(struct hostapd_data *hapd);
diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c b/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c
index ec6deaf5..8a08e93d 100644
--- a/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c
+++ b/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c
@@ -174,6 +174,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
case 0: /* Bits 0-7 */
if (hapd->iconf->obss_interval)
*pos |= 0x01; /* Bit 0 - Coexistence management */
+ if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)
+ *pos |= 0x04; /* Bit 2 - Extended Channel Switching */
break;
case 1: /* Bits 8-15 */
if (hapd->conf->proxy_arp)
@@ -209,11 +211,21 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
if (hapd->conf->hs20)
*pos |= 0x40; /* Bit 46 - WNM-Notification */
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ if (hapd->conf->mbo_enabled)
+ *pos |= 0x40; /* Bit 46 - WNM-Notification */
+#endif /* CONFIG_MBO */
break;
case 6: /* Bits 48-55 */
if (hapd->conf->ssid.utf8_ssid)
*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
break;
+ case 8: /* Bits 64-71 */
+ if (hapd->conf->ftm_responder)
+ *pos |= 0x40; /* Bit 70 - FTM responder */
+ if (hapd->conf->ftm_initiator)
+ *pos |= 0x80; /* Bit 71 - FTM initiator */
+ break;
}
}
@@ -233,6 +245,9 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
len = 1;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
+ if (len < 9 &&
+ (hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
+ len = 9;
#ifdef CONFIG_WNM
if (len < 4)
len = 4;
@@ -241,6 +256,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
if (hapd->conf->hs20 && len < 6)
len = 6;
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ if (hapd->conf->mbo_enabled && len < 6)
+ len = 6;
+#endif /* CONFIG_MBO */
if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len;
if (len == 0)
@@ -508,3 +527,62 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
return pos;
}
+
+
+#ifdef CONFIG_MBO
+
+u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
+{
+ u8 mbo[6], *mbo_pos = mbo;
+ u8 *pos = eid;
+
+ if (!hapd->conf->mbo_enabled)
+ return eid;
+
+ *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
+ *mbo_pos++ = 1;
+ /* Not Cellular aware */
+ *mbo_pos++ = 0;
+
+ if (hapd->mbo_assoc_disallow) {
+ *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = hapd->mbo_assoc_disallow;
+ }
+
+ pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo);
+
+ return pos;
+}
+
+
+u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
+{
+ if (!hapd->conf->mbo_enabled)
+ return 0;
+
+ /*
+ * MBO IE header (6) + Capability Indication attribute (3) +
+ * Association Disallowed attribute (3) = 12
+ */
+ return 6 + 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
+}
+
+#endif /* CONFIG_MBO */
+
+
+void ap_copy_sta_supp_op_classes(struct sta_info *sta,
+ const u8 *supp_op_classes,
+ size_t supp_op_classes_len)
+{
+ if (!supp_op_classes)
+ return;
+ os_free(sta->supp_op_classes);
+ sta->supp_op_classes = os_malloc(1 + supp_op_classes_len);
+ if (!sta->supp_op_classes)
+ return;
+
+ sta->supp_op_classes[0] = supp_op_classes_len;
+ os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
+ supp_op_classes_len);
+}
diff --git a/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h b/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h
index 8b7be129..d8d9c5a2 100644
--- a/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h
+++ b/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h
@@ -17,7 +17,7 @@
struct rsn_pmksa_cache_entry {
struct rsn_pmksa_cache_entry *next, *hnext;
u8 pmkid[PMKID_LEN];
- u8 pmk[PMK_LEN];
+ u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
os_time_t expiration;
int akmp; /* WPA_KEY_MGMT_* */
@@ -28,11 +28,10 @@ struct rsn_pmksa_cache_entry {
struct wpabuf *cui;
struct radius_class_data radius_class;
u8 eap_type_authsrv;
- int vlan_id;
+ struct vlan_description *vlan_desc;
int opportunistic;
- u32 acct_multi_session_id_hi;
- u32 acct_multi_session_id_lo;
+ u64 acct_multi_session_id;
};
struct rsn_pmksa_cache;
@@ -49,7 +48,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
const u8 *pmkid);
struct rsn_pmksa_cache_entry *
pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
- const u8 *pmk, size_t pmk_len,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, int session_timeout,
struct eapol_state_machine *eapol, int akmp);
@@ -57,11 +56,14 @@ struct rsn_pmksa_cache_entry *
pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
const struct rsn_pmksa_cache_entry *old_entry,
const u8 *aa, const u8 *pmkid);
-void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
+void pmksa_cache_to_eapol_data(struct hostapd_data *hapd,
+ struct rsn_pmksa_cache_entry *entry,
struct eapol_state_machine *eapol);
void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *entry);
int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
struct radius_das_attrs *attr);
+int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
+void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa);
#endif /* PMKSA_CACHE_H */
diff --git a/freebsd/contrib/wpa/src/ap/sta_info.h b/freebsd/contrib/wpa/src/ap/sta_info.h
index 420d64e5..099de62d 100644
--- a/freebsd/contrib/wpa/src/ap/sta_info.h
+++ b/freebsd/contrib/wpa/src/ap/sta_info.h
@@ -12,9 +12,11 @@
#ifdef CONFIG_MESH
/* needed for mesh_plink_state enum */
#include "common/defs.h"
+#include "common/wpa_common.h"
#endif /* CONFIG_MESH */
#include "list.h"
+#include "vlan.h"
/* STA flags */
#define WLAN_STA_AUTH BIT(0)
@@ -45,6 +47,20 @@
#define WLAN_SUPP_RATES_MAX 32
+struct mbo_non_pref_chan_info {
+ struct mbo_non_pref_chan_info *next;
+ u8 op_class;
+ u8 pref;
+ u8 reason_code;
+ u8 num_channels;
+ u8 channels[];
+};
+
+struct pending_eapol_rx {
+ struct wpabuf *buf;
+ struct os_reltime rx_time;
+};
+
struct sta_info {
struct sta_info *next; /* next entry in sta list */
struct sta_info *hnext; /* next entry in hash table list */
@@ -63,13 +79,22 @@ struct sta_info {
enum mesh_plink_state plink_state;
u16 peer_lid;
u16 my_lid;
+ u16 peer_aid;
u16 mpm_close_reason;
int mpm_retries;
- u8 my_nonce[32];
- u8 peer_nonce[32];
+ u8 my_nonce[WPA_NONCE_LEN];
+ u8 peer_nonce[WPA_NONCE_LEN];
u8 aek[32]; /* SHA256 digest length */
- u8 mtk[16];
- u8 mgtk[16];
+ u8 mtk[WPA_TK_MAX_LEN];
+ size_t mtk_len;
+ u8 mgtk_rsc[6];
+ u8 mgtk_key_id;
+ u8 mgtk[WPA_TK_MAX_LEN];
+ size_t mgtk_len;
+ u8 igtk_rsc[6];
+ u8 igtk[WPA_TK_MAX_LEN];
+ size_t igtk_len;
+ u16 igtk_key_id;
u8 sae_auth_retry;
#endif /* CONFIG_MESH */
@@ -86,6 +111,8 @@ struct sta_info {
unsigned int hs20_deauth_requested:1;
unsigned int session_timeout_set:1;
unsigned int radius_das_match:1;
+ unsigned int ecsa_supported:1;
+ unsigned int added_unassoc:1;
u16 auth_alg;
@@ -100,17 +127,20 @@ struct sta_info {
/* IEEE 802.1X related data */
struct eapol_state_machine *eapol_sm;
- u32 acct_session_id_hi;
- u32 acct_session_id_lo;
+ struct pending_eapol_rx *pending_eapol_rx;
+
+ u64 acct_session_id;
struct os_reltime acct_session_start;
int acct_session_started;
int acct_terminate_cause; /* Acct-Terminate-Cause */
int acct_interim_interval; /* Acct-Interim-Interval */
+ unsigned int acct_interim_errors;
- unsigned long last_rx_bytes;
- unsigned long last_tx_bytes;
- u32 acct_input_gigawords; /* Acct-Input-Gigawords */
- u32 acct_output_gigawords; /* Acct-Output-Gigawords */
+ /* For extending 32-bit driver counters to 64-bit counters */
+ u32 last_rx_bytes_hi;
+ u32 last_rx_bytes_lo;
+ u32 last_tx_bytes_hi;
+ u32 last_tx_bytes_lo;
u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
@@ -118,6 +148,7 @@ struct sta_info {
struct rsn_preauth_interface *preauth_iface;
int vlan_id; /* 0: none, >0: VID */
+ struct vlan_description *vlan_desc;
int vlan_id_bound; /* updated by ap_sta_bind_vlan() */
/* PSKs from RADIUS authentication server */
struct hostapd_sta_wpa_psk_short *psk;
@@ -161,6 +192,7 @@ struct sta_info {
#ifdef CONFIG_SAE
struct sae_data *sae;
+ unsigned int mesh_sae_pmksa_caching:1;
#endif /* CONFIG_SAE */
u32 session_timeout; /* valid only if session_timeout_set == 1 */
@@ -170,6 +202,22 @@ struct sta_info {
u16 last_seq_ctrl;
/* Last Authentication/(Re)Association Request/Action frame subtype */
u8 last_subtype;
+
+#ifdef CONFIG_MBO
+ u8 cell_capa; /* 0 = unknown (not an MBO STA); otherwise,
+ * enum mbo_cellular_capa values */
+ struct mbo_non_pref_chan_info *non_pref_chan;
+#endif /* CONFIG_MBO */
+
+ u8 *supp_op_classes; /* Supported Operating Classes element, if
+ * received, starting from the Length field */
+
+ u8 rrm_enabled_capa[5];
+
+#ifdef CONFIG_TAXONOMY
+ struct wpabuf *probe_ie_taxonomy;
+ struct wpabuf *assoc_ie_taxonomy;
+#endif /* CONFIG_TAXONOMY */
};
@@ -180,7 +228,7 @@ struct sta_info {
* AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
#define AP_MAX_INACTIVITY (5 * 60)
-#define AP_DISASSOC_DELAY (1)
+#define AP_DISASSOC_DELAY (3)
#define AP_DEAUTH_DELAY (1)
/* Number of seconds to keep STA entry with Authenticated flag after it has
* been disassociated. */
@@ -220,6 +268,8 @@ int ap_sta_wps_cancel(struct hostapd_data *hapd,
struct sta_info *sta, void *ctx);
#endif /* CONFIG_WPS */
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta);
+int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
+ struct vlan_description *vlan_desc);
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
@@ -235,6 +285,8 @@ static inline int ap_sta_is_authorized(struct sta_info *sta)
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
+ struct sta_info *sta);
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
diff --git a/freebsd/contrib/wpa/src/ap/vlan.h b/freebsd/contrib/wpa/src/ap/vlan.h
new file mode 100644
index 00000000..af84929d
--- /dev/null
+++ b/freebsd/contrib/wpa/src/ap/vlan.h
@@ -0,0 +1,30 @@
+/*
+ * hostapd / VLAN definition
+ * Copyright (c) 2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef VLAN_H
+#define VLAN_H
+
+#define MAX_NUM_TAGGED_VLAN 32
+
+struct vlan_description {
+ int notempty; /* 0 : no vlan information present, 1: else */
+ int untagged; /* >0 802.1q vid */
+ int tagged[MAX_NUM_TAGGED_VLAN]; /* first k items, ascending order */
+};
+
+#ifndef CONFIG_NO_VLAN
+int vlan_compare(struct vlan_description *a, struct vlan_description *b);
+#else /* CONFIG_NO_VLAN */
+static inline int
+vlan_compare(struct vlan_description *a, struct vlan_description *b)
+{
+ return 0;
+}
+#endif /* CONFIG_NO_VLAN */
+
+#endif /* VLAN_H */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth.c b/freebsd/contrib/wpa/src/ap/wpa_auth.c
index 97d44620..5e0b0bf8 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth.c
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth.c
@@ -46,7 +46,8 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
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, struct wpa_ptk *ptk);
+ const u8 *pmk, unsigned int pmk_len,
+ struct wpa_ptk *ptk);
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
@@ -829,6 +830,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
struct wpa_ptk PTK;
int ok = 0;
const u8 *pmk = NULL;
+ unsigned int pmk_len;
for (;;) {
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
@@ -836,10 +838,13 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
sm->p2p_dev_addr, pmk);
if (pmk == NULL)
break;
- } else
+ pmk_len = PMK_LEN;
+ } else {
pmk = sm->PMK;
+ pmk_len = sm->pmk_len;
+ }
- wpa_derive_ptk(sm, sm->alt_SNonce, pmk, &PTK);
+ wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK);
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len)
== 0) {
@@ -1742,6 +1747,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
#else /* CONFIG_IEEE80211R */
break;
#endif /* CONFIG_IEEE80211R */
+ case WPA_DRV_STA_REMOVED:
+ sm->tk_already_set = FALSE;
+ return 0;
}
#ifdef CONFIG_IEEE80211R
@@ -1921,11 +1929,27 @@ SM_STATE(WPA_PTK, INITPMK)
#endif /* CONFIG_IEEE80211R */
if (sm->pmksa) {
wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
- os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN);
+ os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
+ sm->pmk_len = sm->pmksa->pmk_len;
} else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
+ unsigned int pmk_len;
+
+ if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ pmk_len = PMK_LEN_SUITE_B_192;
+ else
+ pmk_len = PMK_LEN;
wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine "
- "(len=%lu)", (unsigned long) len);
- os_memcpy(sm->PMK, msk, PMK_LEN);
+ "(MSK len=%lu PMK len=%u)", (unsigned long) len,
+ pmk_len);
+ if (len < pmk_len) {
+ wpa_printf(MSG_DEBUG,
+ "WPA: MSK not long enough (%u) to create PMK (%u)",
+ (unsigned int) len, (unsigned int) pmk_len);
+ sm->Disconnect = TRUE;
+ return;
+ }
+ os_memcpy(sm->PMK, msk, pmk_len);
+ sm->pmk_len = pmk_len;
#ifdef CONFIG_IEEE80211R
if (len >= 2 * PMK_LEN) {
os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
@@ -1960,6 +1984,7 @@ SM_STATE(WPA_PTK, INITPSK)
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
if (psk) {
os_memcpy(sm->PMK, psk, PMK_LEN);
+ sm->pmk_len = PMK_LEN;
#ifdef CONFIG_IEEE80211R
os_memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN;
@@ -2011,7 +2036,7 @@ SM_STATE(WPA_PTK, PTKSTART)
* Calculate PMKID since no PMKSA cache entry was
* available with pre-calculated PMKID.
*/
- rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr,
+ rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
wpa_key_mgmt_sha256(sm->wpa_key_mgmt));
}
@@ -2023,14 +2048,15 @@ SM_STATE(WPA_PTK, PTKSTART)
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
- const u8 *pmk, struct wpa_ptk *ptk)
+ const u8 *pmk, unsigned int pmk_len,
+ struct wpa_ptk *ptk)
{
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
#endif /* CONFIG_IEEE80211R */
- return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
+ return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
ptk, sm->wpa_key_mgmt, sm->pairwise);
}
@@ -2041,6 +2067,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
struct wpa_ptk PTK;
int ok = 0, psk_found = 0;
const u8 *pmk = NULL;
+ unsigned int pmk_len;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = FALSE;
@@ -2056,10 +2083,13 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (pmk == NULL)
break;
psk_found = 1;
- } else
+ pmk_len = PMK_LEN;
+ } else {
pmk = sm->PMK;
+ pmk_len = sm->pmk_len;
+ }
- wpa_derive_ptk(sm, sm->SNonce, pmk, &PTK);
+ wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK);
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK,
sm->last_rx_eapol_key,
@@ -2109,6 +2139,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
* state machine data based on whatever PSK was selected here.
*/
os_memcpy(sm->PMK, pmk, PMK_LEN);
+ sm->pmk_len = PMK_LEN;
}
sm->MICVerified = TRUE;
@@ -2287,14 +2318,19 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos += wpa_ie_len;
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
- int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name);
+ int res;
+ size_t elen;
+
+ elen = pos - kde;
+ res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert "
"PMKR1Name into RSN IE in EAPOL-Key data");
os_free(kde);
return;
}
- pos += res;
+ pos -= wpa_ie_len;
+ pos += elen;
}
#endif /* CONFIG_IEEE80211R */
if (gtk) {
@@ -2312,10 +2348,18 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
struct wpa_auth_config *conf;
conf = &sm->wpa_auth->conf;
- res = wpa_write_ftie(conf, conf->r0_key_holder,
- conf->r0_key_holder_len,
- NULL, NULL, pos, kde + kde_len - pos,
- NULL, 0);
+ if (sm->assoc_resp_ftie &&
+ kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
+ os_memcpy(pos, sm->assoc_resp_ftie,
+ 2 + sm->assoc_resp_ftie[1]);
+ res = 2 + sm->assoc_resp_ftie[1];
+ } else {
+ res = wpa_write_ftie(conf, conf->r0_key_holder,
+ conf->r0_key_holder_len,
+ NULL, NULL, pos,
+ kde + kde_len - pos,
+ NULL, 0);
+ }
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
"into EAPOL-Key Key Data");
@@ -3271,13 +3315,21 @@ const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
+ unsigned int pmk_len,
int session_timeout, struct eapol_state_machine *eapol)
{
if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 ||
sm->wpa_auth->conf.disable_pmksa_caching)
return -1;
- if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
+ if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+ if (pmk_len > PMK_LEN_SUITE_B_192)
+ pmk_len = PMK_LEN_SUITE_B_192;
+ } else if (pmk_len > PMK_LEN) {
+ pmk_len = PMK_LEN;
+ }
+
+ if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
sm->PTK.kck, sm->PTK.kck_len,
sm->wpa_auth->addr, sm->addr, session_timeout,
eapol, sm->wpa_key_mgmt))
@@ -3295,7 +3347,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
if (wpa_auth == NULL)
return -1;
- if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len,
+ if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
NULL, 0,
wpa_auth->addr,
sta_addr, session_timeout, eapol,
@@ -3307,12 +3359,12 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
- const u8 *pmk)
+ const u8 *pmk, const u8 *pmkid)
{
if (wpa_auth->conf.disable_pmksa_caching)
return -1;
- if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN,
+ if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
NULL, 0,
wpa_auth->addr, addr, 0, NULL,
WPA_KEY_MGMT_SAE))
@@ -3338,6 +3390,46 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
}
+int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
+ size_t len)
+{
+ if (!wpa_auth || !wpa_auth->pmksa)
+ return 0;
+ return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
+}
+
+
+void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
+{
+ if (wpa_auth && wpa_auth->pmksa)
+ pmksa_cache_auth_flush(wpa_auth->pmksa);
+}
+
+
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
+{
+ if (!wpa_auth || !wpa_auth->pmksa)
+ return NULL;
+ return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
+}
+
+
+void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
+ struct wpa_state_machine *sm,
+ struct wpa_authenticator *wpa_auth,
+ u8 *pmkid, u8 *pmk)
+{
+ if (!sm)
+ return;
+
+ sm->pmksa = pmksa;
+ os_memcpy(pmk, pmksa->pmk, PMK_LEN);
+ os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
+ os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
+}
+
+
/*
* Remove and free the group from wpa_authenticator. This is triggered by a
* callback to make sure nobody is currently iterating the group list while it
@@ -3416,6 +3508,98 @@ wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
}
+/*
+ * Enforce that the group state machine for the VLAN is running, increase
+ * reference counter as interface is up. References might have been increased
+ * even if a negative value is returned.
+ * Returns: -1 on error (group missing, group already failed); otherwise, 0
+ */
+int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
+{
+ struct wpa_group *group;
+
+ if (wpa_auth == NULL)
+ return 0;
+
+ group = wpa_auth->group;
+ while (group) {
+ if (group->vlan_id == vlan_id)
+ break;
+ group = group->next;
+ }
+
+ if (group == NULL) {
+ group = wpa_auth_add_group(wpa_auth, vlan_id);
+ if (group == NULL)
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "WPA: Ensure group state machine running for VLAN ID %d",
+ vlan_id);
+
+ wpa_group_get(wpa_auth, group);
+ group->num_setup_iface++;
+
+ if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * Decrease reference counter, expected to be zero afterwards.
+ * returns: -1 on error (group not found, group in fail state)
+ * -2 if wpa_group is still referenced
+ * 0 else
+ */
+int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
+{
+ struct wpa_group *group;
+ int ret = 0;
+
+ if (wpa_auth == NULL)
+ return 0;
+
+ group = wpa_auth->group;
+ while (group) {
+ if (group->vlan_id == vlan_id)
+ break;
+ group = group->next;
+ }
+
+ if (group == NULL)
+ return -1;
+
+ wpa_printf(MSG_DEBUG,
+ "WPA: Try stopping group state machine for VLAN ID %d",
+ vlan_id);
+
+ if (group->num_setup_iface <= 0) {
+ wpa_printf(MSG_ERROR,
+ "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
+ vlan_id);
+ return -1;
+ }
+ group->num_setup_iface--;
+
+ if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
+ ret = -1;
+
+ if (group->references > 1) {
+ wpa_printf(MSG_DEBUG,
+ "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
+ vlan_id);
+ ret = -2;
+ }
+
+ wpa_group_put(wpa_auth, group);
+
+ return ret;
+}
+
+
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
{
struct wpa_group *group;
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth.h b/freebsd/contrib/wpa/src/ap/wpa_auth.h
index 1b1442f4..97461b02 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth.h
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth.h
@@ -42,10 +42,11 @@ struct ft_rrb_frame {
#define FT_PACKET_R0KH_R1KH_RESP 201
#define FT_PACKET_R0KH_R1KH_PUSH 202
-#define FT_R0KH_R1KH_PULL_DATA_LEN 44
-#define FT_R0KH_R1KH_RESP_DATA_LEN 76
-#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
#define FT_R0KH_R1KH_PULL_NONCE_LEN 16
+#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+ WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
+ ETH_ALEN)
+#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
struct ft_r0kh_r1kh_pull_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
@@ -57,14 +58,18 @@ struct ft_r0kh_r1kh_pull_frame {
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
u8 r1kh_id[FT_R1KH_ID_LEN];
u8 s1kh_id[ETH_ALEN];
- u8 pad[4]; /* 8-octet boundary for AES key wrap */
+ u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
+#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+ FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \
+ WPA_PMK_NAME_LEN + 2)
+#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8)
struct ft_r0kh_r1kh_resp_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
- le16 data_length; /* little endian length of data (76) */
+ le16 data_length; /* little endian length of data (78) */
u8 ap_address[ETH_ALEN];
u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
@@ -73,14 +78,18 @@ struct ft_r0kh_r1kh_resp_frame {
u8 pmk_r1[PMK_LEN];
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
le16 pairwise;
- u8 pad[2]; /* 8-octet boundary for AES key wrap */
+ u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
+#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \
+ WPA_PMK_NAME_LEN + PMK_LEN + \
+ WPA_PMK_NAME_LEN + 2)
+#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8)
struct ft_r0kh_r1kh_push_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
- le16 data_length; /* little endian length of data (88) */
+ le16 data_length; /* little endian length of data (82) */
u8 ap_address[ETH_ALEN];
/* Encrypted with AES key-wrap */
@@ -92,7 +101,7 @@ struct ft_r0kh_r1kh_push_frame {
u8 pmk_r1[PMK_LEN];
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
le16 pairwise;
- u8 pad[6]; /* 8-octet boundary for AES key wrap */
+ u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
@@ -258,7 +267,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
u8 *data, size_t data_len);
enum wpa_event {
WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
- WPA_REAUTH_EAPOL, WPA_ASSOC_FT
+ WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
};
void wpa_remove_ptk(struct wpa_state_machine *sm);
int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
@@ -280,15 +289,25 @@ void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm);
const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth,
size_t *len);
int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
+ unsigned int pmk_len,
int session_timeout, struct eapol_state_machine *eapol);
int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
const u8 *pmk, size_t len, const u8 *sta_addr,
int session_timeout,
struct eapol_state_machine *eapol);
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
- const u8 *pmk);
+ const u8 *pmk, const u8 *pmkid);
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr);
+int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
+ size_t len);
+void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth);
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr);
+void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
+ struct wpa_state_machine *sm,
+ struct wpa_authenticator *wpa_auth,
+ u8 *pmkid, u8 *pmk);
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int ack);
@@ -326,4 +345,7 @@ int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
struct radius_das_attrs *attr);
void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth);
+int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id);
+int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id);
+
#endif /* WPA_AUTH_H */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c b/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c
index 19530a31..fe145fad 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c
@@ -722,11 +722,6 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
ftie_len = res;
pos += res;
- os_free(sm->assoc_resp_ftie);
- sm->assoc_resp_ftie = os_malloc(ftie_len);
- if (sm->assoc_resp_ftie)
- os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
-
_ftie = (struct rsn_ftie *) (ftie + 2);
if (auth_alg == WLAN_AUTH_FT)
_ftie->mic_control[1] = 3; /* Information element count */
@@ -752,6 +747,11 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
_ftie->mic) < 0)
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
+ os_free(sm->assoc_resp_ftie);
+ sm->assoc_resp_ftie = os_malloc(ftie_len);
+ if (sm->assoc_resp_ftie)
+ os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
+
return pos;
}
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_i.h b/freebsd/contrib/wpa/src/ap/wpa_auth_i.h
index 234d84c8..7fd8f05f 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth_i.h
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth_i.h
@@ -60,7 +60,8 @@ struct wpa_state_machine {
u8 SNonce[WPA_NONCE_LEN];
u8 alt_SNonce[WPA_NONCE_LEN];
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
- u8 PMK[PMK_LEN];
+ u8 PMK[PMK_LEN_MAX];
+ unsigned int pmk_len;
struct wpa_ptk PTK;
Boolean PTK_valid;
Boolean pairwise_set;
@@ -172,6 +173,7 @@ struct wpa_group {
#endif /* CONFIG_IEEE80211W */
/* Number of references except those in struct wpa_group->next */
unsigned int references;
+ unsigned int num_setup_iface;
};
diff --git a/freebsd/contrib/wpa/src/common/ctrl_iface_common.c b/freebsd/contrib/wpa/src/common/ctrl_iface_common.c
new file mode 100644
index 00000000..72f539c4
--- /dev/null
+++ b/freebsd/contrib/wpa/src/common/ctrl_iface_common.c
@@ -0,0 +1,175 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Common hostapd/wpa_supplicant ctrl iface code.
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2015, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <netdb.h>
+#include <sys/un.h>
+
+#include "utils/common.h"
+#include "ctrl_iface_common.h"
+
+static int sockaddr_compare(struct sockaddr_storage *a, socklen_t a_len,
+ struct sockaddr_storage *b, socklen_t b_len)
+{
+ if (a->ss_family != b->ss_family)
+ return 1;
+
+ switch (a->ss_family) {
+#ifdef CONFIG_CTRL_IFACE_UDP
+ case AF_INET:
+ {
+ struct sockaddr_in *in_a, *in_b;
+
+ in_a = (struct sockaddr_in *) a;
+ in_b = (struct sockaddr_in *) b;
+
+ if (in_a->sin_port != in_b->sin_port)
+ return 1;
+ if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr)
+ return 1;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *in6_a, *in6_b;
+
+ in6_a = (struct sockaddr_in6 *) a;
+ in6_b = (struct sockaddr_in6 *) b;
+
+ if (in6_a->sin6_port != in6_b->sin6_port)
+ return 1;
+ if (os_memcmp(&in6_a->sin6_addr, &in6_b->sin6_addr,
+ sizeof(in6_a->sin6_addr)) != 0)
+ return 1;
+ break;
+ }
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#ifdef CONFIG_CTRL_IFACE_UNIX
+ case AF_UNIX:
+ {
+ struct sockaddr_un *u_a, *u_b;
+
+ u_a = (struct sockaddr_un *) a;
+ u_b = (struct sockaddr_un *) b;
+
+ if (a_len != b_len ||
+ os_memcmp(u_a->sun_path, u_b->sun_path,
+ a_len - offsetof(struct sockaddr_un, sun_path))
+ != 0)
+ return 1;
+ break;
+ }
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
+ socklen_t socklen)
+{
+ switch (sock->ss_family) {
+#ifdef CONFIG_CTRL_IFACE_UDP
+ case AF_INET:
+ case AF_INET6:
+ {
+ char host[NI_MAXHOST] = { 0 };
+ char service[NI_MAXSERV] = { 0 };
+
+ getnameinfo((struct sockaddr *) sock, socklen,
+ host, sizeof(host),
+ service, sizeof(service),
+ NI_NUMERICHOST);
+
+ wpa_printf(level, "%s %s:%s", msg, host, service);
+ break;
+ }
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#ifdef CONFIG_CTRL_IFACE_UNIX
+ case AF_UNIX:
+ {
+ char addr_txt[200];
+
+ printf_encode(addr_txt, sizeof(addr_txt),
+ (u8 *) ((struct sockaddr_un *) sock)->sun_path,
+ socklen - offsetof(struct sockaddr_un, sun_path));
+ wpa_printf(level, "%s %s", msg, addr_txt);
+ break;
+ }
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+ default:
+ wpa_printf(level, "%s", msg);
+ break;
+ }
+}
+
+
+int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
+ socklen_t fromlen)
+{
+ struct wpa_ctrl_dst *dst;
+
+ dst = os_zalloc(sizeof(*dst));
+ if (dst == NULL)
+ return -1;
+ os_memcpy(&dst->addr, from, fromlen);
+ dst->addrlen = fromlen;
+ dst->debug_level = MSG_INFO;
+ dl_list_add(ctrl_dst, &dst->list);
+
+ sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen);
+ return 0;
+}
+
+
+int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
+ socklen_t fromlen)
+{
+ struct wpa_ctrl_dst *dst;
+
+ dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
+ if (!sockaddr_compare(from, fromlen,
+ &dst->addr, dst->addrlen)) {
+ sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor detached",
+ from, fromlen);
+ dl_list_del(&dst->list);
+ os_free(dst);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
+ socklen_t fromlen, const char *level)
+{
+ struct wpa_ctrl_dst *dst;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
+
+ dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
+ if (!sockaddr_compare(from, fromlen,
+ &dst->addr, dst->addrlen)) {
+ sockaddr_print(MSG_DEBUG,
+ "CTRL_IFACE changed monitor level",
+ from, fromlen);
+ dst->debug_level = atoi(level);
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/freebsd/contrib/wpa/src/common/ctrl_iface_common.h b/freebsd/contrib/wpa/src/common/ctrl_iface_common.h
new file mode 100644
index 00000000..0b6e3e74
--- /dev/null
+++ b/freebsd/contrib/wpa/src/common/ctrl_iface_common.h
@@ -0,0 +1,38 @@
+/*
+ * Common hostapd/wpa_supplicant ctrl iface code.
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2015, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+#ifndef CONTROL_IFACE_COMMON_H
+#define CONTROL_IFACE_COMMON_H
+
+#include "utils/list.h"
+
+/**
+ * struct wpa_ctrl_dst - Data structure of control interface monitors
+ *
+ * This structure is used to store information about registered control
+ * interface monitors into struct wpa_supplicant.
+ */
+struct wpa_ctrl_dst {
+ struct dl_list list;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int debug_level;
+ int errors;
+};
+
+void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
+ socklen_t socklen);
+
+int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
+ socklen_t fromlen);
+int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
+ socklen_t fromlen);
+int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
+ socklen_t fromlen, const char *level);
+
+#endif /* CONTROL_IFACE_COMMON_H */
diff --git a/freebsd/contrib/wpa/src/common/defs.h b/freebsd/contrib/wpa/src/common/defs.h
index 6aea3751..4f567945 100644
--- a/freebsd/contrib/wpa/src/common/defs.h
+++ b/freebsd/contrib/wpa/src/common/defs.h
@@ -312,6 +312,7 @@ enum wpa_ctrl_req_type {
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
WPA_CTRL_REQ_PSK_PASSPHRASE,
+ WPA_CTRL_REQ_EXT_CERT_CHECK,
NUM_WPA_CTRL_REQS
};
@@ -319,13 +320,13 @@ enum wpa_ctrl_req_type {
#define EAP_MAX_METHODS 8
enum mesh_plink_state {
- PLINK_LISTEN = 1,
- PLINK_OPEN_SENT,
- PLINK_OPEN_RCVD,
+ PLINK_IDLE = 1,
+ PLINK_OPN_SNT,
+ PLINK_OPN_RCVD,
PLINK_CNF_RCVD,
PLINK_ESTAB,
PLINK_HOLDING,
- PLINK_BLOCKED,
+ PLINK_BLOCKED, /* not defined in the IEEE 802.11 standard */
};
enum set_band {
@@ -334,4 +335,10 @@ enum set_band {
WPA_SETBAND_2G
};
+enum wpa_radio_work_band {
+ BAND_2_4_GHZ = BIT(0),
+ BAND_5_GHZ = BIT(1),
+ BAND_60_GHZ = BIT(2),
+};
+
#endif /* DEFS_H */
diff --git a/freebsd/contrib/wpa/src/common/eapol_common.h b/freebsd/contrib/wpa/src/common/eapol_common.h
index 6958661f..d773348b 100644
--- a/freebsd/contrib/wpa/src/common/eapol_common.h
+++ b/freebsd/contrib/wpa/src/common/eapol_common.h
@@ -25,7 +25,7 @@ struct ieee802_1x_hdr {
struct ieee8023_hdr {
u8 dest[ETH_ALEN];
u8 src[ETH_ALEN];
- u16 ethertype;
+ be16 ethertype;
} STRUCT_PACKED;
#ifdef _MSC_VER
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.c b/freebsd/contrib/wpa/src/common/ieee802_11_common.c
index ba7ef0a8..286fdcf8 100644
--- a/freebsd/contrib/wpa/src/common/ieee802_11_common.c
+++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.c
@@ -117,6 +117,11 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->osen = pos;
elems->osen_len = elen;
break;
+ case MBO_OUI_TYPE:
+ /* MBO-OCE */
+ elems->mbo = pos;
+ elems->mbo_len = elen;
+ break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
"information element ignored "
@@ -368,6 +373,14 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
elems->mb_ies.nof_ies++;
break;
+ case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
+ elems->supp_op_classes = pos;
+ elems->supp_op_classes_len = elen;
+ break;
+ case WLAN_EID_RRM_ENABLED_CAPABILITIES:
+ elems->rrm_enabled = pos;
+ elems->rrm_enabled_len = elen;
+ break;
default:
unknown++;
if (!show_errors)
@@ -400,8 +413,8 @@ int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
pos = ies;
end = ies + ies_len;
- while (pos + 2 <= end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos >= 2) {
+ if (2 + pos[1] > end - pos)
break;
count++;
pos += 2 + pos[1];
@@ -421,8 +434,8 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
end = ies + ies_len;
ie = NULL;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
return NULL;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
WPA_GET_BE32(&pos[2]) == oui_type) {
@@ -443,8 +456,8 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
* There may be multiple vendor IEs in the message, so need to
* concatenate their data fields.
*/
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
WPA_GET_BE32(&pos[2]) == oui_type)
@@ -572,7 +585,8 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
{
u8 op_class;
- return ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, channel);
+ return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
+ &op_class, channel);
}
@@ -581,7 +595,7 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
* for HT40 and VHT. DFS channels are not covered.
* @freq: Frequency (MHz) to convert
* @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
- * @vht: 0 - non-VHT, 1 - 80 MHz
+ * @vht: VHT channel width (VHT_CHANWIDTH_*)
* @op_class: Buffer for returning operating class
* @channel: Buffer for returning channel number
* Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
@@ -590,6 +604,8 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
int sec_channel, int vht,
u8 *op_class, u8 *channel)
{
+ u8 vht_opclass;
+
/* TODO: more operating classes */
if (sec_channel > 1 || sec_channel < -1)
@@ -633,17 +649,32 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
return HOSTAPD_MODE_IEEE80211A;
}
+ switch (vht) {
+ case VHT_CHANWIDTH_80MHZ:
+ vht_opclass = 128;
+ break;
+ case VHT_CHANWIDTH_160MHZ:
+ vht_opclass = 129;
+ break;
+ case VHT_CHANWIDTH_80P80MHZ:
+ vht_opclass = 130;
+ break;
+ default:
+ vht_opclass = 0;
+ break;
+ }
+
/* 5 GHz, channels 36..48 */
if (freq >= 5180 && freq <= 5240) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
- if (sec_channel == 1)
+ if (vht_opclass)
+ *op_class = vht_opclass;
+ else if (sec_channel == 1)
*op_class = 116;
else if (sec_channel == -1)
*op_class = 117;
- else if (vht)
- *op_class = 128;
else
*op_class = 115;
@@ -652,31 +683,40 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
return HOSTAPD_MODE_IEEE80211A;
}
- /* 5 GHz, channels 149..161 */
- if (freq >= 5745 && freq <= 5805) {
+ /* 5 GHz, channels 149..169 */
+ if (freq >= 5745 && freq <= 5845) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
- if (sec_channel == 1)
+ if (vht_opclass)
+ *op_class = vht_opclass;
+ else if (sec_channel == 1)
*op_class = 126;
else if (sec_channel == -1)
*op_class = 127;
- else if (vht)
- *op_class = 128;
- else
+ else if (freq <= 5805)
*op_class = 124;
+ else
+ *op_class = 125;
*channel = (freq - 5000) / 5;
return HOSTAPD_MODE_IEEE80211A;
}
- /* 5 GHz, channels 149..169 */
- if (freq >= 5745 && freq <= 5845) {
+ /* 5 GHz, channels 100..140 */
+ if (freq >= 5000 && freq <= 5700) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
- *op_class = 125;
+ if (vht_opclass)
+ *op_class = vht_opclass;
+ else if (sec_channel == 1)
+ *op_class = 122;
+ else if (sec_channel == -1)
+ *op_class = 123;
+ else
+ *op_class = 121;
*channel = (freq - 5000) / 5;
@@ -1147,3 +1187,135 @@ struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
return mb_ies;
}
+
+
+const struct oper_class_map global_op_class[] = {
+ { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
+
+ /* Do not enable HT40 on 2.4 GHz for P2P use for now */
+ { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
+
+ { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP },
+
+ /*
+ * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
+ * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
+ * 80 MHz, but currently use the following definition for simplicity
+ * (these center frequencies are not actual channels, which makes
+ * wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take
+ * care of removing invalid channels.
+ */
+ { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
+ { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
+};
+
+
+static enum phy_type ieee80211_phy_type_by_freq(int freq)
+{
+ enum hostapd_hw_mode hw_mode;
+ u8 channel;
+
+ hw_mode = ieee80211_freq_to_chan(freq, &channel);
+
+ switch (hw_mode) {
+ case HOSTAPD_MODE_IEEE80211A:
+ return PHY_TYPE_OFDM;
+ case HOSTAPD_MODE_IEEE80211B:
+ return PHY_TYPE_HRDSSS;
+ case HOSTAPD_MODE_IEEE80211G:
+ return PHY_TYPE_ERP;
+ case HOSTAPD_MODE_IEEE80211AD:
+ return PHY_TYPE_DMG;
+ default:
+ return PHY_TYPE_UNSPECIFIED;
+ };
+}
+
+
+/* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
+enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
+{
+ if (vht)
+ return PHY_TYPE_VHT;
+ if (ht)
+ return PHY_TYPE_HT;
+
+ return ieee80211_phy_type_by_freq(freq);
+}
+
+
+size_t global_op_class_size = ARRAY_SIZE(global_op_class);
+
+
+/**
+ * get_ie - Fetch a specified information element from IEs buffer
+ * @ies: Information elements buffer
+ * @len: Information elements buffer length
+ * @eid: Information element identifier (WLAN_EID_*)
+ * Returns: Pointer to the information element (id field) or %NULL if not found
+ *
+ * This function returns the first matching information element in the IEs
+ * buffer or %NULL in case the element is not found.
+ */
+const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
+{
+ const u8 *end;
+
+ if (!ies)
+ return NULL;
+
+ end = ies + len;
+
+ while (end - ies > 1) {
+ if (2 + ies[1] > end - ies)
+ break;
+
+ if (ies[0] == eid)
+ return ies;
+
+ ies += 2 + ies[1];
+ }
+
+ return NULL;
+}
+
+
+size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
+{
+ /*
+ * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
+ * OUI (3), OUI type (1).
+ */
+ if (len < 6 + attr_len) {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
+ len, attr_len);
+ return 0;
+ }
+
+ *buf++ = WLAN_EID_VENDOR_SPECIFIC;
+ *buf++ = attr_len + 4;
+ WPA_PUT_BE24(buf, OUI_WFA);
+ buf += 3;
+ *buf++ = MBO_OUI_TYPE;
+ os_memcpy(buf, attr, attr_len);
+
+ return 6 + attr_len;
+}
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.h b/freebsd/contrib/wpa/src/common/ieee802_11_common.h
index 55ce0223..42f39096 100644
--- a/freebsd/contrib/wpa/src/common/ieee802_11_common.h
+++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.h
@@ -9,6 +9,8 @@
#ifndef IEEE802_11_COMMON_H
#define IEEE802_11_COMMON_H
+#include "defs.h"
+
#define MAX_NOF_MB_IES_SUPPORTED 5
struct mb_ies_info {
@@ -56,9 +58,12 @@ struct ieee802_11_elems {
const u8 *bss_max_idle_period;
const u8 *ssid_list;
const u8 *osen;
+ const u8 *mbo;
const u8 *ampe;
const u8 *mic;
const u8 *pref_freq_list;
+ const u8 *supp_op_classes;
+ const u8 *rrm_enabled;
u8 ssid_len;
u8 supp_rates_len;
@@ -85,9 +90,13 @@ struct ieee802_11_elems {
u8 ext_capab_len;
u8 ssid_list_len;
u8 osen_len;
+ u8 mbo_len;
u8 ampe_len;
u8 mic_len;
u8 pref_freq_list_len;
+ u8 supp_op_classes_len;
+ u8 rrm_enabled_len;
+
struct mb_ies_info mb_ies;
};
@@ -118,6 +127,7 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
int sec_channel, int vht,
u8 *op_class, u8 *channel);
int ieee80211_is_dfs(int freq);
+enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
@@ -125,4 +135,22 @@ int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
struct wpabuf * mb_ies_by_info(struct mb_ies_info *info);
const char * fc2str(u16 fc);
+
+struct oper_class_map {
+ enum hostapd_hw_mode mode;
+ u8 op_class;
+ u8 min_chan;
+ u8 max_chan;
+ u8 inc;
+ enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80 } bw;
+ enum { P2P_SUPP, NO_P2P_SUPP } p2p;
+};
+
+extern const struct oper_class_map global_op_class[];
+extern size_t global_op_class_size;
+
+const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
+
+size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
+
#endif /* IEEE802_11_COMMON_H */
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_defs.h b/freebsd/contrib/wpa/src/common/ieee802_11_defs.h
index 44530ce3..d453aec7 100644
--- a/freebsd/contrib/wpa/src/common/ieee802_11_defs.h
+++ b/freebsd/contrib/wpa/src/common/ieee802_11_defs.h
@@ -94,8 +94,13 @@
#define WLAN_CAPABILITY_PBCC BIT(6)
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
+#define WLAN_CAPABILITY_QOS BIT(9)
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
+#define WLAN_CAPABILITY_APSD BIT(11)
+#define WLAN_CAPABILITY_RADIO_MEASUREMENT BIT(12)
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
+#define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
+#define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
#define WLAN_STATUS_SUCCESS 0
@@ -247,6 +252,7 @@
#define WLAN_EID_TIMEOUT_INTERVAL 56
#define WLAN_EID_RIC_DATA 57
#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
+#define WLAN_EID_EXT_CHANSWITCH_ANN 60
#define WLAN_EID_HT_OPERATION 61
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
#define WLAN_EID_WAPI 68
@@ -360,6 +366,16 @@
/* byte 1 (out of 5) */
#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
+/* byte 2 (out of 5) */
+#define WLAN_RRM_CAPS_LCI_MEASUREMENT BIT(4)
+/* byte 5 (out of 5) */
+#define WLAN_RRM_CAPS_FTM_RANGE_REPORT BIT(2)
+
+/*
+ * IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 (Fine Timing Measurement Range
+ * request) - Minimum AP count
+ */
+#define WLAN_RRM_RANGE_REQ_MAX_MIN_AP 15
/* Timeout Interval Type */
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
@@ -407,7 +423,12 @@ enum anqp_info_id {
ANQP_AP_LOCATION_PUBLIC_URI = 267,
ANQP_DOMAIN_NAME = 268,
ANQP_EMERGENCY_ALERT_URI = 269,
+ ANQP_TDLS_CAPABILITY = 270,
ANQP_EMERGENCY_NAI = 271,
+ ANQP_NEIGHBOR_REPORT = 272,
+ ANQP_VENUE_URL = 277,
+ ANQP_ADVICE_OF_CHARGE = 278,
+ ANQP_LOCAL_CONTENT = 279,
ANQP_VENDOR_SPECIFIC = 56797
};
@@ -442,6 +463,48 @@ enum nai_realm_eap_cred_type {
NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
};
+/*
+ * IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
+ * measurement requests
+ */
+enum measure_type {
+ MEASURE_TYPE_BASIC = 0,
+ MEASURE_TYPE_CCA = 1,
+ MEASURE_TYPE_RPI_HIST = 2,
+ MEASURE_TYPE_CHANNEL_LOAD = 3,
+ MEASURE_TYPE_NOISE_HIST = 4,
+ MEASURE_TYPE_BEACON = 5,
+ MEASURE_TYPE_FRAME = 6,
+ MEASURE_TYPE_STA_STATISTICS = 7,
+ MEASURE_TYPE_LCI = 8,
+ MEASURE_TYPE_TRANSMIT_STREAM = 9,
+ MEASURE_TYPE_MULTICAST_DIAG = 10,
+ MEASURE_TYPE_LOCATION_CIVIC = 11,
+ MEASURE_TYPE_LOCATION_ID = 12,
+ MEASURE_TYPE_DIRECTIONAL_CHAN_QUALITY = 13,
+ MEASURE_TYPE_DIRECTIONAL_MEASURE = 14,
+ MEASURE_TYPE_DIRECTIONAL_STATS = 15,
+ MEASURE_TYPE_FTM_RANGE = 16,
+ MEASURE_TYPE_MEASURE_PAUSE = 255,
+};
+
+/* IEEE Std 802.11-2012 Table 8-71 - Location subject definition */
+enum location_subject {
+ LOCATION_SUBJECT_LOCAL = 0,
+ LOCATION_SUBJECT_REMOTE = 1,
+ LOCATION_SUBJECT_3RD_PARTY = 2,
+};
+
+/*
+ * IEEE P802.11-REVmc/D5.0 Table 9-94 - Optional subelement IDs for LCI request
+ */
+enum lci_req_subelem {
+ LCI_REQ_SUBELEM_AZIMUTH_REQ = 1,
+ LCI_REQ_SUBELEM_ORIGINATOR_MAC_ADDR = 2,
+ LCI_REQ_SUBELEM_TARGET_MAC_ADDR = 3,
+ LCI_REQ_SUBELEM_MAX_AGE = 4,
+};
+
#ifdef _MSC_VER
#pragma pack(push, 1)
#endif /* _MSC_VER */
@@ -516,10 +579,7 @@ struct ieee80211_mgmt {
* FH Params, DS Params, CF Params, IBSS Params, TIM */
u8 variable[];
} STRUCT_PACKED beacon;
- struct {
- /* only variable items: SSID, Supported rates */
- u8 variable[0];
- } STRUCT_PACKED probe_req;
+ /* probe_req: only variable items: SSID, Supported rates */
struct {
u8 timestamp[8];
le16 beacon_int;
@@ -625,12 +685,19 @@ struct ieee80211_mgmt {
u8 action;
u8 variable[];
} STRUCT_PACKED fst_action;
+ struct {
+ u8 action;
+ u8 dialog_token;
+ u8 variable[];
+ } STRUCT_PACKED rrm;
} u;
} STRUCT_PACKED action;
} u;
} STRUCT_PACKED;
+#define IEEE80211_MAX_MMPDU_SIZE 2304
+
/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */
#define IEEE80211_HT_MCS_MASK_LEN 10
@@ -690,9 +757,14 @@ struct ieee80211_ampe_ie {
u8 selected_pairwise_suite[4];
u8 local_nonce[32];
u8 peer_nonce[32];
- u8 mgtk[16];
- u8 key_rsc[8];
- u8 key_expiration[4];
+ /* Followed by
+ * Key Replay Counter[8] (optional)
+ * (only in Mesh Group Key Inform/Acknowledge frames)
+ * GTKdata[variable] (optional)
+ * (MGTK[variable] || Key RSC[8] || GTKExpirationTime[4])
+ * IGTKdata[variable] (optional)
+ * (Key ID[2], IPN[6], IGTK[variable] in IGTK KDE format)
+ */
} STRUCT_PACKED;
#ifdef _MSC_VER
@@ -879,6 +951,8 @@ struct ieee80211_ampe_ie {
#define WFD_OUI_TYPE 10
#define HS20_IE_VENDOR_TYPE 0x506f9a10
#define OSEN_IE_VENDOR_TYPE 0x506f9a12
+#define MBO_IE_VENDOR_TYPE 0x506f9a16
+#define MBO_OUI_TYPE 22
#define WMM_OUI_TYPE 2
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
@@ -1021,6 +1095,95 @@ enum wmm_ac {
#define HS20_DEAUTH_REASON_CODE_BSS 0
#define HS20_DEAUTH_REASON_CODE_ESS 1
+/* MBO v0.0_r19, 4.2: MBO Attributes */
+/* Table 4-5: MBO Attributes */
+enum mbo_attr_id {
+ MBO_ATTR_ID_AP_CAPA_IND = 1,
+ MBO_ATTR_ID_NON_PREF_CHAN_REPORT = 2,
+ MBO_ATTR_ID_CELL_DATA_CAPA = 3,
+ MBO_ATTR_ID_ASSOC_DISALLOW = 4,
+ MBO_ATTR_ID_CELL_DATA_PREF = 5,
+ MBO_ATTR_ID_TRANSITION_REASON = 6,
+ MBO_ATTR_ID_TRANSITION_REJECT_REASON = 7,
+ MBO_ATTR_ID_ASSOC_RETRY_DELAY = 8,
+};
+
+/* MBO v0.0_r19, 4.2.1: MBO AP Capability Indication Attribute */
+/* Table 4-7: MBO AP Capability Indication Field Values */
+#define MBO_AP_CAPA_CELL_AWARE BIT(6)
+
+/* MBO v0.0_r19, 4.2.2: Non-preferred Channel Report Attribute */
+/* Table 4-10: Reason Code Field Values */
+enum mbo_non_pref_chan_reason {
+ MBO_NON_PREF_CHAN_REASON_UNSPECIFIED = 0,
+ MBO_NON_PREF_CHAN_REASON_RSSI = 1,
+ MBO_NON_PREF_CHAN_REASON_EXT_INTERFERENCE = 2,
+ MBO_NON_PREF_CHAN_REASON_INT_INTERFERENCE = 3,
+};
+
+/* MBO v0.0_r19, 4.2.3: Cellular Data Capabilities Attribute */
+/* Table 4-13: Cellular Data Connectivity Field */
+enum mbo_cellular_capa {
+ MBO_CELL_CAPA_AVAILABLE = 1,
+ MBO_CELL_CAPA_NOT_AVAILABLE = 2,
+ MBO_CELL_CAPA_NOT_SUPPORTED = 3,
+};
+
+/* MBO v0.0_r19, 4.2.4: Association Disallowed Attribute */
+/* Table 4-15: Reason Code Field Values */
+enum mbo_assoc_disallow_reason {
+ MBO_ASSOC_DISALLOW_REASON_UNSPECIFIED = 1,
+ MBO_ASSOC_DISALLOW_REASON_MAX_STA = 2,
+ MBO_ASSOC_DISALLOW_REASON_AIR_INTERFERENCE = 3,
+ MBO_ASSOC_DISALLOW_REASON_AUTH_SERVER_OVERLOAD = 4,
+ MBO_ASSOC_DISALLOW_REASON_LOW_RSSI = 5,
+};
+
+/* MBO v0.0_r19, 4.2.5: Cellular Data Connection Preference Attribute */
+/* Table 4-17: Cellular Preference Field Values */
+enum mbo_cell_pref {
+ MBO_CELL_PREF_EXCLUDED = 0,
+ MBO_CELL_PREF_NO_USE = 1,
+ MBO_CELL_PREF_USE = 255
+};
+
+/* MBO v0.0_r19, 4.2.6: Transition Reason Code Attribute */
+/* Table 4-19: Transition Reason Code Field Values */
+enum mbo_transition_reason {
+ MBO_TRANSITION_REASON_UNSPECIFIED = 0,
+ MBO_TRANSITION_REASON_FRAME_LOSS = 1,
+ MBO_TRANSITION_REASON_DELAY = 2,
+ MBO_TRANSITION_REASON_BANDWIDTH = 3,
+ MBO_TRANSITION_REASON_LOAD_BALANCE = 4,
+ MBO_TRANSITION_REASON_RSSI = 5,
+ MBO_TRANSITION_REASON_RETRANSMISSIONS = 6,
+ MBO_TRANSITION_REASON_INTERFERENCE = 7,
+ MBO_TRANSITION_REASON_GRAY_ZONE = 8,
+ MBO_TRANSITION_REASON_PREMIUM_AP = 9,
+};
+
+/* MBO v0.0_r19, 4.2.7: Transition Rejection Reason Code Attribute */
+/* Table 4-21: Transition Rejection Reason Code Field Values */
+enum mbo_transition_reject_reason {
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED = 0,
+ MBO_TRANSITION_REJECT_REASON_FRAME_LOSS = 1,
+ MBO_TRANSITION_REJECT_REASON_DELAY = 2,
+ MBO_TRANSITION_REJECT_REASON_QOS_CAPACITY = 3,
+ MBO_TRANSITION_REJECT_REASON_RSSI = 4,
+ MBO_TRANSITION_REJECT_REASON_INTERFERENCE = 5,
+ MBO_TRANSITION_REJECT_REASON_SERVICES = 6,
+};
+
+/* MBO v0.0_r19, 4.4: WNM-Notification vendor subelements */
+enum wfa_wnm_notif_subelem_id {
+ WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT = 2,
+ WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3,
+};
+
+/* MBO v0.0_r25, 4.3: MBO ANQP-elements */
+#define MBO_ANQP_OUI_TYPE 0x12
+#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 1
+
/* Wi-Fi Direct (P2P) */
#define P2P_OUI_TYPE 9
@@ -1178,6 +1341,14 @@ enum wifi_display_subelem {
#define MESH_PATH_PROTOCOL_VENDOR 255
#define MESH_PATH_METRIC_AIRTIME 1
#define MESH_PATH_METRIC_VENDOR 255
+/* IEEE 802.11s - Mesh Capability */
+#define MESH_CAP_ACCEPT_ADDITIONAL_PEER BIT(0)
+#define MESH_CAP_MCCA_SUPPORTED BIT(1)
+#define MESH_CAP_MCCA_ENABLED BIT(2)
+#define MESH_CAP_FORWARDING BIT(3)
+#define MESH_CAP_MBCA_ENABLED BIT(4)
+#define MESH_CAP_TBTT_ADJUSTING BIT(5)
+#define MESH_CAP_MESH_PS_LEVEL BIT(6)
enum plink_action_field {
PLINK_OPEN = 1,
@@ -1280,14 +1451,25 @@ enum bss_trans_mgmt_status_code {
WNM_BSS_TM_REJECT_LEAVING_ESS = 8
};
+/*
+ * IEEE P802.11-REVmc/D5.0 Table 9-150 - Optional subelement IDs for
+ * neighbor report
+ */
#define WNM_NEIGHBOR_TSF 1
#define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING 2
#define WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE 3
#define WNM_NEIGHBOR_BSS_TERMINATION_DURATION 4
#define WNM_NEIGHBOR_BEARING 5
+#define WNM_NEIGHBOR_WIDE_BW_CHAN 6
+#define WNM_NEIGHBOR_MEASUREMENT_REPORT 39
+#define WNM_NEIGHBOR_HT_CAPAB 45
+#define WNM_NEIGHBOR_HT_OPER 61
+#define WNM_NEIGHBOR_SEC_CHAN_OFFSET 62
#define WNM_NEIGHBOR_MEASUREMENT_PILOT 66
#define WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES 70
#define WNM_NEIGHBOR_MULTIPLE_BSSID 71
+#define WNM_NEIGHBOR_VHT_CAPAB 191
+#define WNM_NEIGHBOR_VHT_OPER 192
/* QoS action */
enum qos_action {
@@ -1356,6 +1538,8 @@ struct tpc_report {
u8 link_margin;
} STRUCT_PACKED;
+#define RRM_CAPABILITIES_IE_LEN 5
+
/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
struct rrm_link_measurement_request {
u8 dialog_token;
@@ -1375,8 +1559,6 @@ struct rrm_link_measurement_report {
u8 variable[0];
} STRUCT_PACKED;
-#define SSID_MAX_LEN 32
-
/* IEEE Std 802.11ad-2012 - Multi-band element */
struct multi_band_ie {
u8 eid; /* WLAN_EID_MULTI_BAND */
@@ -1433,4 +1615,49 @@ enum fst_action {
FST_ACTION_ON_CHANNEL_TUNNEL = 5,
};
+/* IEEE Std 802.11ac-2013, Annex C - dot11PHYType */
+enum phy_type {
+ PHY_TYPE_UNSPECIFIED = 0,
+ PHY_TYPE_FHSS = 1,
+ PHY_TYPE_DSSS = 2,
+ PHY_TYPE_IRBASEBAND = 3,
+ PHY_TYPE_OFDM = 4,
+ PHY_TYPE_HRDSSS = 5,
+ PHY_TYPE_ERP = 6,
+ PHY_TYPE_HT = 7,
+ PHY_TYPE_DMG = 8,
+ PHY_TYPE_VHT = 9,
+};
+
+/* IEEE P802.11-REVmc/D5.0, 9.4.2.37 - Neighbor Report element */
+/* BSSID Information Field */
+#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
+#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
+#define NEI_REP_BSSID_INFO_AP_REACHABLE (BIT(0) | BIT(1))
+#define NEI_REP_BSSID_INFO_SECURITY BIT(2)
+#define NEI_REP_BSSID_INFO_KEY_SCOPE BIT(3)
+#define NEI_REP_BSSID_INFO_SPECTRUM_MGMT BIT(4)
+#define NEI_REP_BSSID_INFO_QOS BIT(5)
+#define NEI_REP_BSSID_INFO_APSD BIT(6)
+#define NEI_REP_BSSID_INFO_RM BIT(7)
+#define NEI_REP_BSSID_INFO_DELAYED_BA BIT(8)
+#define NEI_REP_BSSID_INFO_IMM_BA BIT(9)
+#define NEI_REP_BSSID_INFO_MOBILITY_DOMAIN BIT(10)
+#define NEI_REP_BSSID_INFO_HT BIT(11)
+#define NEI_REP_BSSID_INFO_VHT BIT(12)
+#define NEI_REP_BSSID_INFO_FTM BIT(13)
+
+/*
+ * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information
+ * subfields.
+ * Note: These definitions are not the same as other VHT_CHANWIDTH_*.
+ */
+enum nr_chan_width {
+ NR_CHAN_WIDTH_20 = 0,
+ NR_CHAN_WIDTH_40 = 1,
+ NR_CHAN_WIDTH_80 = 2,
+ NR_CHAN_WIDTH_160 = 3,
+ NR_CHAN_WIDTH_80P80 = 4,
+};
+
#endif /* IEEE802_11_DEFS_H */
diff --git a/freebsd/contrib/wpa/src/common/qca-vendor.h b/freebsd/contrib/wpa/src/common/qca-vendor.h
index 28985f51..adaec890 100644
--- a/freebsd/contrib/wpa/src/common/qca-vendor.h
+++ b/freebsd/contrib/wpa/src/common/qca-vendor.h
@@ -89,6 +89,102 @@ enum qca_radiotap_vendor_ids {
* @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED: Event used by driver,
* which supports DFS offloading, to indicate a radar pattern has been
* detected. The channel is now unusable.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to
+ * start the P2P Listen offload function in device and pass the listen
+ * channel, period, interval, count, device types, and vendor specific
+ * information elements to the device driver and firmware.
+ * Uses the attributes defines in
+ * enum qca_wlan_vendor_attr_p2p_listen_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP: Command/event used to
+ * indicate stop request/response of the P2P Listen offload function in
+ * device. As an event, it indicates either the feature stopped after it
+ * was already running or feature has actually failed to start. Uses the
+ * attributes defines in enum qca_wlan_vendor_attr_p2p_listen_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH: After AP starts
+ * beaconing, this sub command provides the driver, the frequencies on the
+ * 5 GHz band to check for any radar activity. Driver selects one channel
+ * from this priority list provided through
+ * @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST and starts
+ * to check for radar activity on it. If no radar activity is detected
+ * during the channel availability check period, driver internally switches
+ * to the selected frequency of operation. If the frequency is zero, driver
+ * internally selects a channel. The status of this conditional switch is
+ * indicated through an event using the same sub command through
+ * @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS. Attributes are
+ * listed in qca_wlan_vendor_attr_sap_conditional_chan_switch.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND: Set GPIO pins. This uses the
+ * attributes defined in enum qca_wlan_gpio_attr.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY: Fetch hardware capabilities.
+ * This uses @QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY to indicate which
+ * capabilities are to be fetched and other
+ * enum qca_wlan_vendor_attr_get_hw_capability attributes to return the
+ * requested capabilities.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT: Link layer statistics extension.
+ * enum qca_wlan_vendor_attr_ll_stats_ext attributes are used with this
+ * command and event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA: Get capabilities for
+ * indoor location features. Capabilities are reported in
+ * QCA_WLAN_VENDOR_ATTR_LOC_CAPA.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION: Start an FTM
+ * (fine timing measurement) session with one or more peers.
+ * Specify Session cookie in QCA_WLAN_VENDOR_ATTR_FTM_SESSION_COOKIE and
+ * peer information in QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEERS.
+ * On success, 0 or more QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT
+ * events will be reported, followed by
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE event to indicate
+ * end of session.
+ * Refer to IEEE P802.11-REVmc/D7.0, 11.24.6
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION: Abort a running session.
+ * A QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE will be reported with
+ * status code indicating session was aborted.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT: Event with measurement
+ * results for one peer. Results are reported in
+ * QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEER_RESULTS.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE: Event triggered when
+ * FTM session is finished, either successfully or aborted by
+ * request.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER: Configure FTM responder
+ * mode. QCA_WLAN_VENDOR_ATTR_FTM_RESPONDER_ENABLE specifies whether
+ * to enable or disable the responder. LCI/LCR reports can be
+ * configured with QCA_WLAN_VENDOR_ATTR_FTM_LCI and
+ * QCA_WLAN_VENDOR_ATTR_FTM_LCR. Can be called multiple
+ * times to update the LCI/LCR reports.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS: Perform a standalone AOA (angle of
+ * arrival) measurement with a single peer. Specify peer MAC address in
+ * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and measurement type in
+ * QCA_WLAN_VENDOR_ATTR_AOA_TYPE. Measurement result is reported in
+ * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS: Abort an AOA measurement. Specify
+ * peer MAC address in QCA_WLAN_VENDOR_ATTR_MAC_ADDR.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT: Event that reports
+ * the AOA measurement result.
+ * Peer MAC address reported in QCA_WLAN_VENDOR_ATTR_MAC_ADDR.
+ * success/failure status is reported in
+ * QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS.
+ * Measurement data is reported in QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT.
+ * The antenna array(s) used in the measurement are reported in
+ * QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST: Encrypt/decrypt the given
+ * data as per the given parameters.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI: Get antenna RSSI value for a
+ * specific chain.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -140,7 +236,11 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60,
- /* 61-90 - reserved for QCA */
+ /* 61-73 - reserved for QCA */
+ /* Wi-Fi configuration subcommands */
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74,
+ QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75,
+ /* 76-90 - reserved for QCA */
QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93,
@@ -156,6 +256,35 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104,
QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
+ QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN = 106,
+ QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE = 107,
+ QCA_NL80211_VENDOR_SUBCMD_OTA_TEST = 108,
+ QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE = 109,
+ /* 110..114 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_DECR_DB = 115,
+ /* 116..117 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG = 118,
+ QCA_NL80211_VENDOR_SUBCMD_TSF = 119,
+ QCA_NL80211_VENDOR_SUBCMD_WISA = 120,
+ /* 121 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START = 122,
+ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP = 123,
+ QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH = 124,
+ QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND = 125,
+ QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY = 126,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT = 127,
+ /* FTM/indoor location subcommands */
+ QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA = 128,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION = 129,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION = 130,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT = 131,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE = 132,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER = 133,
+ QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS = 134,
+ QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS = 135,
+ QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT = 136,
+ QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST = 137,
+ QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI = 138,
};
@@ -185,6 +314,84 @@ enum qca_wlan_vendor_attr {
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11,
/* Unsigned 32-bit value from enum qca_set_band. */
QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12,
+ /* Dummy (NOP) attribute for 64 bit padding */
+ QCA_WLAN_VENDOR_ATTR_PAD = 13,
+ /* Unique FTM session cookie (Unsigned 64 bit). Specified in
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION. Reported in
+ * the session in QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT and
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_SESSION_COOKIE = 14,
+ /* Indoor location capabilities, returned by
+ * QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA.
+ * see enum qca_wlan_vendor_attr_loc_capa.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA = 15,
+ /* Array of nested attributes containing information about each peer
+ * in FTM measurement session. See enum qca_wlan_vendor_attr_peer_info
+ * for supported attributes for each peer.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEERS = 16,
+ /* Array of nested attributes containing measurement results for
+ * one or more peers, reported by the
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT event.
+ * See enum qca_wlan_vendor_attr_peer_result for list of supported
+ * attributes.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEER_RESULTS = 17,
+ /* Flag attribute for enabling or disabling responder functionality. */
+ QCA_WLAN_VENDOR_ATTR_FTM_RESPONDER_ENABLE = 18,
+ /* Used in the QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER
+ * command to specify the LCI report that will be sent by
+ * the responder during a measurement exchange. The format is
+ * defined in IEEE P802.11-REVmc/D7.0, 9.4.2.22.10.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_LCI = 19,
+ /* Used in the QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER
+ * command to specify the location civic report that will
+ * be sent by the responder during a measurement exchange.
+ * The format is defined in IEEE P802.11-REVmc/D7.0, 9.4.2.22.13.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_LCR = 20,
+ /* Session/measurement completion status code,
+ * reported in QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE and
+ * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT
+ * see enum qca_vendor_attr_loc_session_status.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS = 21,
+ /* Initial dialog token used by responder (0 if not specified),
+ * unsigned 8 bit value.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_INITIAL_TOKEN = 22,
+ /* AOA measurement type. Requested in QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS
+ * and optionally in QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION if
+ * AOA measurements are needed as part of an FTM session.
+ * Reported by QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT. See
+ * enum qca_wlan_vendor_attr_aoa_type.
+ */
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE = 23,
+ /* A bit mask (unsigned 32 bit value) of antenna arrays used
+ * by indoor location measurements. Refers to the antenna
+ * arrays described by QCA_VENDOR_ATTR_LOC_CAPA_ANTENNA_ARRAYS.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK = 24,
+ /* AOA measurement data. Its contents depends on the AOA measurement
+ * type and antenna array mask:
+ * QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE: array of U16 values,
+ * phase of the strongest CIR path for each antenna in the measured
+ * array(s).
+ * QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP: array of 2 U16
+ * values, phase and amplitude of the strongest CIR path for each
+ * antenna in the measured array(s).
+ */
+ QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
+ * to specify the chain number (unsigned 32 bit value) to inquire
+ * the corresponding antenna RSSI value */
+ QCA_WLAN_VENDOR_ATTR_CHAIN_INDEX = 26,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
+ * to report the specific antenna RSSI value (unsigned 32 bit value) */
+ QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI = 27,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
@@ -205,12 +412,50 @@ enum qca_wlan_vendor_attr_roam_auth {
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1
};
+enum qca_wlan_vendor_attr_p2p_listen_offload {
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INVALID = 0,
+ /* A 32-bit unsigned value; the P2P listen frequency (MHz); must be one
+ * of the social channels.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL,
+ /* A 32-bit unsigned value; the P2P listen offload period (ms).
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD,
+ /* A 32-bit unsigned value; the P2P listen interval duration (ms).
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL,
+ /* A 32-bit unsigned value; number of interval times the firmware needs
+ * to run the offloaded P2P listen operation before it stops.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT,
+ /* An array of arbitrary binary data with one or more 8-byte values.
+ * The device types include both primary and secondary device types.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES,
+ /* An array of unsigned 8-bit characters; vendor information elements.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE,
+ /* A 32-bit unsigned value; a control flag to indicate whether listen
+ * results need to be flushed to wpa_supplicant.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG,
+ /* A 8-bit unsigned value; reason code for P2P listen offload stop
+ * event.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST - 1
+};
+
enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
@@ -247,11 +492,21 @@ enum qca_wlan_vendor_acs_hw_mode {
* after roaming, rather than having the user space wpa_supplicant do it.
* @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic
* band selection based on channel selection results.
+ * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports
+ * simultaneous off-channel operations.
+ * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P
+ * Listen offload; a mechanism where the station's firmware takes care of
+ * responding to incoming Probe Request frames received from other P2P
+ * Devices whilst in Listen state, rather than having the user space
+ * wpa_supplicant do it. Information from received P2P requests are
+ * forwarded from firmware to host whenever the host processor wakes up.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0,
QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1,
+ QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2,
+ QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@@ -324,6 +579,67 @@ enum qca_set_band {
QCA_SETBAND_2G,
};
+/**
+ * enum qca_access_policy - Access control policy
+ *
+ * Access control policy is applied on the configured IE
+ * (QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE).
+ * To be set with QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY.
+ *
+ * @QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED: Deny Wi-Fi connections which match
+ * the specific configuration (IE) set, i.e., allow all the
+ * connections which do not match the configuration.
+ * @QCA_ACCESS_POLICY_DENY_UNLESS_LISTED: Accept Wi-Fi connections which match
+ * the specific configuration (IE) set, i.e., deny all the
+ * connections which do not match the configuration.
+ */
+enum qca_access_policy {
+ QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED,
+ QCA_ACCESS_POLICY_DENY_UNLESS_LISTED,
+};
+
+/**
+ * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
+ * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
+ * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
+ * SOC timer value at TSF capture
+ */
+enum qca_vendor_attr_tsf_cmd {
+ QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TSF_CMD,
+ QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TSF_MAX =
+ QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_tsf_operation: TSF driver commands
+ * @QCA_TSF_CAPTURE: Initiate TSF Capture
+ * @QCA_TSF_GET: Get TSF capture value
+ * @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ */
+enum qca_tsf_cmd {
+ QCA_TSF_CAPTURE,
+ QCA_TSF_GET,
+ QCA_TSF_SYNC_GET,
+};
+
+/**
+ * enum qca_vendor_attr_wisa_cmd
+ * @QCA_WLAN_VENDOR_ATTR_WISA_MODE: WISA mode value (u32)
+ * WISA setup vendor commands
+ */
+enum qca_vendor_attr_wisa_cmd {
+ QCA_WLAN_VENDOR_ATTR_WISA_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_WISA_MODE,
+ QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_WISA_MAX =
+ QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST - 1
+};
+
/* IEEE 802.11 Vendor Specific elements */
/**
@@ -349,9 +665,926 @@ enum qca_set_band {
*
* This vendor element may be included in GO Negotiation Request, P2P
* Invitation Request, and Provision Discovery Request frames.
+ *
+ * @QCA_VENDOR_ELEM_HE_CAPAB: HE Capabilities element.
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID. The payload of this
+ * vendor specific element is defined by the latest P802.11ax draft.
+ * Please note that the draft is still work in progress and this element
+ * payload is subject to change.
+ *
+ * @QCA_VENDOR_ELEM_HE_OPER: HE Operation element.
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID. The payload of this
+ * vendor specific element is defined by the latest P802.11ax draft.
+ * Please note that the draft is still work in progress and this element
+ * payload is subject to change.
*/
enum qca_vendor_element_id {
QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0,
+ QCA_VENDOR_ELEM_HE_CAPAB = 1,
+ QCA_VENDOR_ELEM_HE_OPER = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES: Nested unsigned 32-bit attributes
+ * with frequencies to be scanned (in MHz)
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS: Nested attribute with SSIDs to be scanned
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported
+ * rates to be included
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests
+ * at non CCK rate in 2GHz band
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the
+ * driver for the specific scan request
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan
+ * request decoded as in enum scan_status
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation
+ * scan flag is set
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with
+ * randomisation
+ */
+enum qca_wlan_vendor_attr_scan {
+ QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
+ QCA_WLAN_VENDOR_ATTR_SCAN_IE,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES,
+ QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
+ QCA_WLAN_VENDOR_ATTR_SCAN_STATUS,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAC,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK,
+ QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
+ QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
+};
+
+/**
+ * enum scan_status - Specifies the valid values the vendor scan attribute
+ * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take
+ *
+ * @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with
+ * new scan results
+ * @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between
+ */
+enum scan_status {
+ VENDOR_SCAN_STATUS_NEW_RESULTS,
+ VENDOR_SCAN_STATUS_ABORTED,
+ VENDOR_SCAN_STATUS_MAX,
+};
+
+/**
+ * enum qca_vendor_attr_ota_test - Specifies the values for vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_OTA_TEST
+ * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE: enable ota test
+ */
+enum qca_vendor_attr_ota_test {
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_INVALID,
+ /* 8-bit unsigned value to indicate if OTA test is enabled */
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX =
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_vendor_attr_txpower_scale - vendor sub commands index
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE: scaling value
+ */
+enum qca_vendor_attr_txpower_scale {
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_INVALID,
+ /* 8-bit unsigned value to indicate the scaling of tx power */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX =
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_vendor_attr_txpower_decr_db - Attributes for TX power decrease
+ *
+ * These attributes are used with QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_DECR_DB.
+ */
+enum qca_vendor_attr_txpower_decr_db {
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_INVALID,
+ /* 8-bit unsigned value to indicate the reduction of TX power in dB for
+ * a virtual interface. */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_MAX =
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST - 1
+};
+
+/* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and
+ * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION subcommands.
+ */
+enum qca_wlan_vendor_attr_config {
+ QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID = 0,
+ /* Unsigned 32-bit value to set the DTIM period.
+ * Whether the wifi chipset wakes at every dtim beacon or a multiple of
+ * the DTIM period. If DTIM is set to 3, the STA shall wake up every 3
+ * DTIM beacons.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM = 1,
+ /* Unsigned 32-bit value to set the wifi_iface stats averaging factor
+ * used to calculate statistics like average the TSF offset or average
+ * number of frame leaked.
+ * For instance, upon Beacon frame reception:
+ * current_avg = ((beacon_TSF - TBTT) * factor + previous_avg * (0x10000 - factor) ) / 0x10000
+ * For instance, when evaluating leaky APs:
+ * current_avg = ((num frame received within guard time) * factor + previous_avg * (0x10000 - factor)) / 0x10000
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR = 2,
+ /* Unsigned 32-bit value to configure guard time, i.e., when
+ * implementing IEEE power management based on frame control PM bit, how
+ * long the driver waits before shutting down the radio and after
+ * receiving an ACK frame for a Data frame with PM bit set.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME = 3,
+ /* Unsigned 32-bit value to change the FTM capability dynamically */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT = 4,
+ /* Unsigned 16-bit value to configure maximum TX rate dynamically */
+ QCA_WLAN_VENDOR_ATTR_CONF_TX_RATE = 5,
+ /* Unsigned 32-bit value to configure the number of continuous
+ * Beacon Miss which shall be used by the firmware to penalize
+ * the RSSI.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS = 6,
+ /* Unsigned 8-bit value to configure the channel avoidance indication
+ * behavior. Firmware to send only one indication and ignore duplicate
+ * indications when set to avoid multiple Apps wakeups.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND = 7,
+ /* 8-bit unsigned value to configure the maximum TX MPDU for
+ * aggregation. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION = 8,
+ /* 8-bit unsigned value to configure the maximum RX MPDU for
+ * aggregation. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION = 9,
+ /* 8-bit unsigned value to configure the Non aggregrate/11g sw
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY = 10,
+ /* 8-bit unsigned value to configure the aggregrate sw
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY = 11,
+ /* 8-bit unsigned value to configure the MGMT frame
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY = 12,
+ /* 8-bit unsigned value to configure the CTRL frame
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY = 13,
+ /* 8-bit unsigned value to configure the propagation delay for
+ * 2G/5G band (0~63, units in us) */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY = 14,
+ /* Unsigned 32-bit value to configure the number of unicast TX fail
+ * packet count. The peer is disconnected once this threshold is
+ * reached. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT = 15,
+ /* Attribute used to set scan default IEs to the driver.
+ *
+ * These IEs can be used by scan operations that will be initiated by
+ * the driver/firmware.
+ *
+ * For further scan requests coming to the driver, these IEs should be
+ * merged with the IEs received along with scan request coming to the
+ * driver. If a particular IE is present in the scan default IEs but not
+ * present in the scan request, then that IE should be added to the IEs
+ * sent in the Probe Request frames for that scan request. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES = 16,
+ /* Unsigned 32-bit attribute for generic commands */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND = 17,
+ /* Unsigned 32-bit value attribute for generic commands */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE = 18,
+ /* Unsigned 32-bit data attribute for generic command response */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA = 19,
+ /* Unsigned 32-bit length attribute for
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH = 20,
+ /* Unsigned 32-bit flags attribute for
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS = 21,
+ /* Unsigned 32-bit, defining the access policy.
+ * See enum qca_access_policy. Used with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY = 22,
+ /* Sets the list of full set of IEs for which a specific access policy
+ * has to be applied. Used along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access.
+ * Zero length payload can be used to clear this access constraint. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST = 23,
+ /* Unsigned 32-bit, specifies the interface index (netdev) for which the
+ * corresponding configurations are applied. If the interface index is
+ * not specified, the configurations are attributed to the respective
+ * wiphy. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24,
+ /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25,
+ /* 8-bit unsigned value to configure the driver and below layers to
+ * ignore the assoc disallowed set by APs while connecting
+ * 1-Ignore, 0-Don't ignore */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED = 26,
+ /* 32-bit unsigned value to trigger antenna diversity features:
+ * 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA = 27,
+ /* 32-bit unsigned value to configure specific chain antenna */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN = 28,
+ /* 32-bit unsigned value to trigger cycle selftest
+ * 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST = 29,
+ /* 32-bit unsigned to configure the cycle time of selftest
+ * the unit is micro-second */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL = 30,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration
+ */
+enum qca_wlan_vendor_attr_sap_config {
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID = 0,
+ /* 1 - reserved for QCA */
+ /* List of frequencies on which AP is expected to operate.
+ * This is irrespective of ACS configuration. This list is a priority
+ * based one and is looked for before the AP is created to ensure the
+ * best concurrency sessions (avoid MCC and use DBS/SCC) co-exist in
+ * the system.
+ */
+ QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST = 2,
+
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sap_conditional_chan_switch - Parameters for AP
+ * conditional channel switch
+ */
+enum qca_wlan_vendor_attr_sap_conditional_chan_switch {
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0,
+ /* Priority based frequency list (an array of u32 values in host byte
+ * order) */
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1,
+ /* Status of the conditional switch (u32).
+ * 0: Success, Non-zero: Failure
+ */
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS = 2,
+
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_gpio_attr - Parameters for GPIO configuration
+ */
+enum qca_wlan_gpio_attr {
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0,
+ /* Unsigned 32-bit attribute for GPIO command */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND,
+ /* Unsigned 32-bit attribute for GPIO PIN number to configure */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM,
+ /* Unsigned 32-bit attribute for GPIO value to configure */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE,
+ /* Unsigned 32-bit attribute for GPIO pull type */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE,
+ /* Unsigned 32-bit attribute for GPIO interrupt mode */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST,
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability
+ */
+enum qca_wlan_vendor_attr_get_hw_capability {
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_INVALID,
+ /* Antenna isolation
+ * An attribute used in the response.
+ * The content of this attribute is encoded in a byte array. Each byte
+ * value is an antenna isolation value. The array length is the number
+ * of antennas.
+ */
+ QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+ /* Request HW capability
+ * An attribute used in the request.
+ * The content of this attribute is a u32 array for one or more of
+ * hardware capabilities (attribute IDs) that are being requested. Each
+ * u32 value has a value from this
+ * enum qca_wlan_vendor_attr_get_hw_capability
+ * identifying which capabilities are requested.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_MAX =
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ll_stats_ext - Attributes for MAC layer monitoring
+ * offload which is an extension for LL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD: Monitoring period. Unit in ms.
+ * If MAC counters do not exceed the threshold, FW will report monitored
+ * link layer counters periodically as this setting. The first report is
+ * always triggered by this timer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD: It is a percentage (1-99).
+ * For each MAC layer counter, FW holds two copies. One is the current value.
+ * The other is the last report. Once a current counter's increment is larger
+ * than the threshold, FW will indicate that counter to host even if the
+ * monitoring timer does not expire.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG: Peer STA power state change
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID: TID of MSDU
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU: Count of MSDU with the same
+ * failure code.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS: TX failure code
+ * 1: TX packet discarded
+ * 2: No ACK
+ * 3: Postpone
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS: peer MAC address
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE: Peer STA current state
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_GLOBAL: Global threshold.
+ * Threshold for all monitored parameters. If per counter dedicated threshold
+ * is not enabled, this threshold will take effect.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_EVENT_MODE: Indicate what triggers this
+ * event, PERORID_TIMEOUT == 1, THRESH_EXCEED == 0.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_ID: interface ID
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ID: peer ID
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BITMAP: bitmap for TX counters
+ * Bit0: TX counter unit in MSDU
+ * Bit1: TX counter unit in MPDU
+ * Bit2: TX counter unit in PPDU
+ * Bit3: TX counter unit in byte
+ * Bit4: Dropped MSDUs
+ * Bit5: Dropped Bytes
+ * Bit6: MPDU retry counter
+ * Bit7: MPDU failure counter
+ * Bit8: PPDU failure counter
+ * Bit9: MPDU aggregation counter
+ * Bit10: MCS counter for ACKed MPDUs
+ * Bit11: MCS counter for Failed MPDUs
+ * Bit12: TX Delay counter
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BITMAP: bitmap for RX counters
+ * Bit0: MAC RX counter unit in MPDU
+ * Bit1: MAC RX counter unit in byte
+ * Bit2: PHY RX counter unit in PPDU
+ * Bit3: PHY RX counter unit in byte
+ * Bit4: Disorder counter
+ * Bit5: Retry counter
+ * Bit6: Duplication counter
+ * Bit7: Discard counter
+ * Bit8: MPDU aggregation size counter
+ * Bit9: MCS counter
+ * Bit10: Peer STA power state change (wake to sleep) counter
+ * Bit11: Peer STA power save counter, total time in PS mode
+ * Bit12: Probe request counter
+ * Bit13: Other management frames counter
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS_BITMAP: bitmap for CCA
+ * Bit0: Idle time
+ * Bit1: TX time
+ * Bit2: time RX in current bss
+ * Bit3: Out of current bss time
+ * Bit4: Wireless medium busy time
+ * Bit5: RX in bad condition time
+ * Bit6: TX in bad condition time
+ * Bit7: time wlan card not available
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_SIGNAL_BITMAP: bitmap for signal
+ * Bit0: Per channel SNR counter
+ * Bit1: Per channel noise floor counter
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM: number of peers
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CHANNEL_NUM: number of channels
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_AC_RX_NUM: number of RX stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS: per channel BSS CCA stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER: container for per PEER stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MSDU: Number of total TX MSDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MPDU: Number of total TX MPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_PPDU: Number of total TX PPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BYTES: bytes of TX data
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP: Number of dropped TX packets
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP_BYTES: Bytes dropped
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_RETRY: waiting time without an ACK
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_ACK: number of MPDU not-ACKed
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_BACK: number of PPDU not-ACKed
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR_NUM:
+ * aggregation stats buffer length
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS_NUM: length of mcs stats
+ * buffer for ACKed MPDUs.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS_NUM: length of mcs stats
+ * buffer for failed MPDUs.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_DELAY_ARRAY_SIZE:
+ * length of delay stats array.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR: TX aggregation stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS: MCS stats for ACKed MPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS: MCS stats for failed MPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DELAY: tx delay stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU: MPDUs received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_BYTES: bytes received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU: PPDU received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU_BYTES: PPDU bytes received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_LOST: packets lost
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_RETRY: number of RX packets
+ * flagged as retransmissions
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DUP: number of RX packets
+ * flagged as duplicated
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DISCARD: number of RX
+ * packets discarded
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR_NUM: length of RX aggregation
+ * stats buffer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS_NUM: length of RX mcs
+ * stats buffer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS: RX mcs stats buffer
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR: aggregation stats buffer
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_TIMES: times STAs go to sleep
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_DURATION: STAs' total sleep time
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PROBE_REQ: number of probe
+ * requests received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MGMT: number of other mgmt
+ * frames received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IDLE_TIME: Percentage of idle time
+ * there is no TX, nor RX, nor interference.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_TIME: percentage of time
+ * transmitting packets.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_TIME: percentage of time
+ * for receiving.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BUSY: percentage of time
+ * interference detected.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BAD: percentage of time
+ * receiving packets with errors.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BAD: percentage of time
+ * TX no-ACK.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NO_AVAIL: percentage of time
+ * the chip is unable to work in normal conditions.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IN_BSS_TIME: percentage of time
+ * receiving packets in current BSS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_OUT_BSS_TIME: percentage of time
+ * receiving packets not in current BSS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ANT_NUM: number of antennas
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_SIGNAL:
+ * This is a container for per antenna signal stats.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_SNR: per antenna SNR value
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF: per antenna NF value
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON: RSSI of beacon
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON: SNR of beacon
+ */
+enum qca_wlan_vendor_attr_ll_stats_ext {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0,
+
+ /* Attributes for configurations */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD,
+
+ /* Peer STA power state change */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG,
+
+ /* TX failure event */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS,
+
+ /* MAC counters */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_GLOBAL,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_EVENT_MODE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_ID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_SIGNAL_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CHANNEL_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER,
+
+ /* Sub-attributes for PEER_AC_TX */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MSDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_PPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_RETRY,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_ACK,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_BACK,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_DELAY_ARRAY_SIZE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DELAY,
+
+ /* Sub-attributes for PEER_AC_RX */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_LOST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_RETRY,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DUP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DISCARD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_TIMES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_DURATION,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PROBE_REQ,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MGMT,
+
+ /* Sub-attributes for CCA_BSS */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IDLE_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BUSY,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BAD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BAD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NO_AVAIL,
+
+ /* sub-attribute for BSS_RX_TIME */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IN_BSS_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_OUT_BSS_TIME,
+
+ /* Sub-attributes for PEER_SIGNAL */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ANT_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_SIGNAL,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_SNR,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF,
+
+ /* Sub-attributes for IFACE_BSS */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1
+};
+
+/* Attributes for FTM commands and events */
+
+/**
+ * enum qca_wlan_vendor_attr_loc_capa - Indoor location capabilities
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAGS: Various flags. See
+ * enum qca_wlan_vendor_attr_loc_capa_flags.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_SESSIONS: Maximum number
+ * of measurement sessions that can run concurrently.
+ * Default is one session (no session concurrency).
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_PEERS: The total number of unique
+ * peers that are supported in running sessions. For example,
+ * if the value is 8 and maximum number of sessions is 2, you can
+ * have one session with 8 unique peers, or 2 sessions with 4 unique
+ * peers each, and so on.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_BURSTS_EXP: Maximum number
+ * of bursts per peer, as an exponent (2^value). Default is 0,
+ * meaning no multi-burst support.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_MEAS_PER_BURST: Maximum number
+ * of measurement exchanges allowed in a single burst.
+ * @QCA_WLAN_VENDOR_ATTR_AOA_CAPA_SUPPORTED_TYPES: Supported AOA measurement
+ * types. A bit mask (unsigned 32 bit value), each bit corresponds
+ * to an AOA type as defined by enum qca_vendor_attr_aoa_type.
+ */
+enum qca_wlan_vendor_attr_loc_capa {
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_INVALID,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_SESSIONS,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_PEERS,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_BURSTS_EXP,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_MEAS_PER_BURST,
+ QCA_WLAN_VENDOR_ATTR_AOA_CAPA_SUPPORTED_TYPES,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_MAX =
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_loc_capa_flags: Indoor location capability flags
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_RESPONDER: Set if driver
+ * can be configured as an FTM responder (for example, an AP that
+ * services FTM requests). QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER
+ * will be supported if set.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR: Set if driver
+ * can run FTM sessions. QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION
+ * will be supported if set.
+* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder
+ * supports immediate (ASAP) response.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA: Set if driver supports standalone
+ * AOA measurement using QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA_IN_FTM: Set if driver supports
+ * requesting AOA measurements as part of an FTM session.
+ */
+enum qca_wlan_vendor_attr_loc_capa_flags {
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_RESPONDER = 1 << 0,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR = 1 << 1,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP = 1 << 2,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA = 1 << 3,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA_IN_FTM = 1 << 4,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_info: Information about
+ * a single peer in a measurement session.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAC_ADDR: The MAC address of the peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAGS: Various flags related
+ * to measurement. See enum qca_wlan_vendor_attr_ftm_peer_meas_flags.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS: Nested attribute of
+ * FTM measurement parameters, as specified by IEEE P802.11-REVmc/D7.0
+ * 9.4.2.167. See enum qca_wlan_vendor_attr_ftm_meas_param for
+ * list of supported attributes.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID: Initial token ID for
+ * secure measurement.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD: Request AOA
+ * measurement every <value> bursts. If 0 or not specified,
+ * AOA measurements will be disabled for this peer.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_info {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAC_ADDR,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_meas_flags: Measurement request flags,
+ * per-peer
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_ASAP: If set, request
+ * immediate (ASAP) response from peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCI: If set, request
+ * LCI report from peer. The LCI report includes the absolute
+ * location of the peer in "official" coordinates (similar to GPS).
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.7 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCR: If set, request
+ * Location civic report from peer. The LCR includes the location
+ * of the peer in free-form format. See IEEE P802.11-REVmc/D7.0,
+ * 11.24.6.7 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_SECURE: If set,
+ * request a secure measurement.
+ * QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID must also be provided.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_meas_flags {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_ASAP = 1 << 0,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCI = 1 << 1,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCR = 1 << 2,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_SECURE = 1 << 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_meas_param: Measurement parameters
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MEAS_PER_BURST: Number of measurements
+ * to perform in a single burst.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_NUM_BURSTS_EXP: Number of bursts to
+ * perform, specified as an exponent (2^value).
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION: Duration of burst
+ * instance, as specified in IEEE P802.11-REVmc/D7.0, 9.4.2.167.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_PERIOD: Time between bursts,
+ * as specified in IEEE P802.11-REVmc/D7.0, 9.4.2.167. Must
+ * be larger than QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION.
+ */
+enum qca_wlan_vendor_attr_ftm_meas_param {
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MEAS_PER_BURST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_NUM_BURSTS_EXP,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_PERIOD,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_result: Per-peer results
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAC_ADDR: MAC address of the reported
+ * peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS: Status of measurement
+ * request for this peer.
+ * See enum qca_wlan_vendor_attr_ftm_peer_result_status.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAGS: Various flags related
+ * to measurement results for this peer.
+ * See enum qca_wlan_vendor_attr_ftm_peer_result_flags.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS: Specified when
+ * request failed and peer requested not to send an additional request
+ * for this number of seconds.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCI: LCI report when received
+ * from peer. In the format specified by IEEE P802.11-REVmc/D7.0,
+ * 9.4.2.22.10.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCR: Location civic report when
+ * received from peer. In the format specified by IEEE P802.11-REVmc/D7.0,
+ * 9.4.2.22.13.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAMS: Reported when peer
+ * overridden some measurement request parameters. See
+ * enum qca_wlan_vendor_attr_ftm_meas_param.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AOA_MEAS: AOA measurement
+ * for this peer. Same contents as @QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS: Array of measurement
+ * results. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_ftm_meas.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_result {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAC_ADDR,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCI,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCR,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAMS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AOA_MEAS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_result_status
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_OK: Request sent ok and results
+ * will be provided. Peer may have overridden some measurement parameters,
+ * in which case overridden parameters will be report by
+ * QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAM attribute.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INCAPABLE: Peer is incapable
+ * of performing the measurement request. No more results will be sent
+ * for this peer in this session.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_FAILED: Peer reported request
+ * failed, and requested not to send an additional request for number
+ * of seconds specified by QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS
+ * attribute.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INVALID: Request validation
+ * failed. Request was not sent over the air.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_result_status {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_OK,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INCAPABLE,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_FAILED,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INVALID,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_result_flags: Various flags
+ * for measurement result, per-peer
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAG_DONE: If set,
+ * measurement completed for this peer. No more results will be reported
+ * for this peer in this session.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_result_flags {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAG_DONE = 1 << 0,
+};
+
+/**
+ * enum qca_vendor_attr_loc_session_status: Session completion status code
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_OK: Session completed
+ * successfully.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_ABORTED: Session aborted
+ * by request.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_INVALID: Session request
+ * was invalid and was not started.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_FAILED: Session had an error
+ * and did not complete normally (for example out of resources).
+ */
+enum qca_vendor_attr_loc_session_status {
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_OK,
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_ABORTED,
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_INVALID,
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_FAILED,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_meas: Single measurement data
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T1: Time of departure (TOD) of FTM packet as
+ * recorded by responder, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T2: Time of arrival (TOA) of FTM packet at
+ * initiator, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T3: TOD of ACK packet as recorded by
+ * initiator, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T4: TOA of ACK packet at
+ * responder, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_RSSI: RSSI (signal level) as recorded
+ * during this measurement exchange. Optional and will be provided if
+ * the hardware can measure it.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOD_ERR: TOD error reported by
+ * responder. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOA_ERR: TOA error reported by
+ * responder. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOD_ERR: TOD error measured by
+ * initiator. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOA_ERR: TOA error measured by
+ * initiator. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PAD: Dummy attribute for padding.
+ */
+enum qca_wlan_vendor_attr_ftm_meas {
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T1,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T2,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T3,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T4,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_RSSI,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOD_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOA_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOD_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOA_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PAD,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_aoa_type - AOA measurement type
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE: Phase of the strongest
+ * CIR (channel impulse response) path for each antenna.
+ * @QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP: Phase and amplitude
+ * of the strongest CIR path for each antenna.
+ */
+enum qca_wlan_vendor_attr_aoa_type {
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE,
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP,
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE_MAX
+};
+
+/**
+ * enum qca_wlan_vendor_attr_encryption_test - Attributes to
+ * validate encryption engine
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION: Flag attribute.
+ * This will be included if the request is for decryption; if not included,
+ * the request is treated as a request for encryption by default.
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER: Unsigned 32-bit value
+ * indicating the key cipher suite. Takes same values as
+ * NL80211_ATTR_KEY_CIPHER.
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID: Unsigned 8-bit value
+ * Key Id to be used for encryption
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK: Array of 8-bit values.
+ * Key (TK) to be used for encryption/decryption
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN: Array of 8-bit values.
+ * Packet number to be specified for encryption/decryption
+ * 6 bytes for TKIP/CCMP/GCMP.
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA: Array of 8-bit values
+ * representing the 802.11 packet (header + payload + FCS) that
+ * needs to be encrypted/decrypted.
+ * Encrypted/decrypted response from the driver will also be sent
+ * to userspace with the same attribute.
+ */
+enum qca_wlan_vendor_attr_encryption_test {
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX =
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST - 1
};
#endif /* QCA_VENDOR_H */
diff --git a/freebsd/contrib/wpa/src/common/sae.h b/freebsd/contrib/wpa/src/common/sae.h
index c07026cd..a4270bc2 100644
--- a/freebsd/contrib/wpa/src/common/sae.h
+++ b/freebsd/contrib/wpa/src/common/sae.h
@@ -45,6 +45,7 @@ struct sae_data {
enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state;
u16 send_confirm;
u8 pmk[SAE_PMK_LEN];
+ u8 pmkid[SAE_PMKID_LEN];
struct crypto_bignum *peer_commit_scalar;
int group;
int sync;
diff --git a/freebsd/contrib/wpa/src/common/version.h b/freebsd/contrib/wpa/src/common/version.h
index a5cc5b7b..75e5c6e0 100644
--- a/freebsd/contrib/wpa/src/common/version.h
+++ b/freebsd/contrib/wpa/src/common/version.h
@@ -5,6 +5,10 @@
#define VERSION_STR_POSTFIX ""
#endif /* VERSION_STR_POSTFIX */
-#define VERSION_STR "2.5" VERSION_STR_POSTFIX
+#ifndef GIT_VERSION_STR_POSTFIX
+#define GIT_VERSION_STR_POSTFIX ""
+#endif /* GIT_VERSION_STR_POSTFIX */
+
+#define VERSION_STR "2.6" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
#endif /* VERSION_H */
diff --git a/freebsd/contrib/wpa/src/common/wpa_common.c b/freebsd/contrib/wpa/src/common/wpa_common.c
index f2c2d56d..f1802c36 100644
--- a/freebsd/contrib/wpa/src/common/wpa_common.c
+++ b/freebsd/contrib/wpa/src/common/wpa_common.c
@@ -294,38 +294,47 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
pos = ie + sizeof(struct rsn_ftie);
end = ie + ie_len;
- while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
- switch (pos[0]) {
+ while (end - pos >= 2) {
+ u8 id, len;
+
+ id = *pos++;
+ len = *pos++;
+ if (len > end - pos)
+ break;
+
+ switch (id) {
case FTIE_SUBELEM_R1KH_ID:
- if (pos[1] != FT_R1KH_ID_LEN) {
- wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
- "length in FTIE: %d", pos[1]);
+ if (len != FT_R1KH_ID_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Invalid R1KH-ID length in FTIE: %d",
+ len);
return -1;
}
- parse->r1kh_id = pos + 2;
+ parse->r1kh_id = pos;
break;
case FTIE_SUBELEM_GTK:
- parse->gtk = pos + 2;
- parse->gtk_len = pos[1];
+ parse->gtk = pos;
+ parse->gtk_len = len;
break;
case FTIE_SUBELEM_R0KH_ID:
- if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
- wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
- "length in FTIE: %d", pos[1]);
+ if (len < 1 || len > FT_R0KH_ID_MAX_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Invalid R0KH-ID length in FTIE: %d",
+ len);
return -1;
}
- parse->r0kh_id = pos + 2;
- parse->r0kh_id_len = pos[1];
+ parse->r0kh_id = pos;
+ parse->r0kh_id_len = len;
break;
#ifdef CONFIG_IEEE80211W
case FTIE_SUBELEM_IGTK:
- parse->igtk = pos + 2;
- parse->igtk_len = pos[1];
+ parse->igtk = pos;
+ parse->igtk_len = len;
break;
#endif /* CONFIG_IEEE80211W */
}
- pos += 2 + pos[1];
+ pos += len;
}
return 0;
@@ -347,11 +356,18 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
pos = ies;
end = ies + ies_len;
- while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
- switch (pos[0]) {
+ while (end - pos >= 2) {
+ u8 id, len;
+
+ id = *pos++;
+ len = *pos++;
+ if (len > end - pos)
+ break;
+
+ switch (id) {
case WLAN_EID_RSN:
- parse->rsn = pos + 2;
- parse->rsn_len = pos[1];
+ parse->rsn = pos;
+ parse->rsn_len = len;
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
parse->rsn_len + 2,
&data);
@@ -364,32 +380,32 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
parse->rsn_pmkid = data.pmkid;
break;
case WLAN_EID_MOBILITY_DOMAIN:
- if (pos[1] < sizeof(struct rsn_mdie))
+ if (len < sizeof(struct rsn_mdie))
return -1;
- parse->mdie = pos + 2;
- parse->mdie_len = pos[1];
+ parse->mdie = pos;
+ parse->mdie_len = len;
break;
case WLAN_EID_FAST_BSS_TRANSITION:
- if (pos[1] < sizeof(*ftie))
+ if (len < sizeof(*ftie))
return -1;
- ftie = (const struct rsn_ftie *) (pos + 2);
+ ftie = (const struct rsn_ftie *) pos;
prot_ie_count = ftie->mic_control[1];
- if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
+ if (wpa_ft_parse_ftie(pos, len, parse) < 0)
return -1;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
- if (pos[1] != 5)
+ if (len != 5)
break;
- parse->tie = pos + 2;
- parse->tie_len = pos[1];
+ parse->tie = pos;
+ parse->tie_len = len;
break;
case WLAN_EID_RIC_DATA:
if (parse->ric == NULL)
- parse->ric = pos;
+ parse->ric = pos - 2;
break;
}
- pos += 2 + pos[1];
+ pos += len;
}
if (prot_ie_count == 0)
@@ -418,13 +434,15 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
}
/* Determine the end of the RIC IE(s) */
- pos = parse->ric;
- while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
- prot_ie_count) {
- prot_ie_count--;
- pos += 2 + pos[1];
+ if (parse->ric) {
+ pos = parse->ric;
+ while (end - pos >= 2 && 2 + pos[1] <= end - pos &&
+ prot_ie_count) {
+ prot_ie_count--;
+ pos += 2 + pos[1];
+ }
+ parse->ric_len = pos - parse->ric;
}
- parse->ric_len = pos - parse->ric;
if (prot_ie_count) {
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
"frame", (int) prot_ie_count);
@@ -584,8 +602,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
if (!wpa_cipher_valid_group(data->group_cipher)) {
- wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x",
- __func__, data->group_cipher);
+ wpa_printf(MSG_DEBUG,
+ "%s: invalid group cipher 0x%x (%08x)",
+ __func__, data->group_cipher,
+ WPA_GET_BE32(pos));
return -1;
}
pos += RSN_SELECTOR_LEN;
@@ -673,9 +693,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
if (left >= 4) {
data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
- wpa_printf(MSG_DEBUG, "%s: Unsupported management "
- "group cipher 0x%x", __func__,
- data->mgmt_group_cipher);
+ wpa_printf(MSG_DEBUG,
+ "%s: Unsupported management group cipher 0x%x (%08x)",
+ __func__, data->mgmt_group_cipher,
+ WPA_GET_BE32(pos));
return -10;
}
pos += RSN_SELECTOR_LEN;
@@ -1165,6 +1186,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
"WPA2-PSK" : "WPA-PSK";
case WPA_KEY_MGMT_NONE:
return "NONE";
+ case WPA_KEY_MGMT_WPA_NONE:
+ return "WPA-NONE";
case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
return "IEEE 802.1X (no WPA)";
#ifdef CONFIG_IEEE80211R
@@ -1263,13 +1286,13 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
#ifdef CONFIG_IEEE80211R
-int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
+int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
{
u8 *start, *end, *rpos, *rend;
int added = 0;
start = ies;
- end = ies + ies_len;
+ end = ies + *ies_len;
while (start < end) {
if (*start == WLAN_EID_RSN)
@@ -1322,11 +1345,29 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
added += 2 + PMKID_LEN;
start[1] += 2 + PMKID_LEN;
} else {
- /* PMKID-Count was included; use it */
- if (WPA_GET_LE16(rpos) != 0) {
- wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
- "in RSN IE in EAPOL-Key data");
+ u16 num_pmkid;
+
+ if (rend - rpos < 2)
return -1;
+ num_pmkid = WPA_GET_LE16(rpos);
+ /* PMKID-Count was included; use it */
+ if (num_pmkid != 0) {
+ u8 *after;
+
+ if (num_pmkid * PMKID_LEN > rend - rpos - 2)
+ return -1;
+ /*
+ * PMKID may have been included in RSN IE in
+ * (Re)Association Request frame, so remove the old
+ * PMKID(s) first before adding the new one.
+ */
+ wpa_printf(MSG_DEBUG,
+ "FT: Remove %u old PMKID(s) from RSN IE",
+ num_pmkid);
+ after = rpos + 2 + num_pmkid * PMKID_LEN;
+ os_memmove(rpos + 2, after, rend - after);
+ start[1] -= num_pmkid * PMKID_LEN;
+ added -= num_pmkid * PMKID_LEN;
}
WPA_PUT_LE16(rpos, 1);
rpos += 2;
@@ -1339,7 +1380,9 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
"(PMKID inserted)", start, 2 + start[1]);
- return added;
+ *ies_len += added;
+
+ return 0;
}
#endif /* CONFIG_IEEE80211R */
diff --git a/freebsd/contrib/wpa/src/common/wpa_common.h b/freebsd/contrib/wpa/src/common/wpa_common.h
index a04e7593..1021ccb0 100644
--- a/freebsd/contrib/wpa/src/common/wpa_common.h
+++ b/freebsd/contrib/wpa/src/common/wpa_common.h
@@ -12,6 +12,8 @@
/* IEEE 802.11i */
#define PMKID_LEN 16
#define PMK_LEN 32
+#define PMK_LEN_SUITE_B_192 48
+#define PMK_LEN_MAX 48
#define WPA_REPLAY_COUNTER_LEN 8
#define WPA_NONCE_LEN 32
#define WPA_KEY_RSC_LEN 8
@@ -419,7 +421,7 @@ u32 wpa_akm_to_suite(int akm);
int wpa_compare_rsn_ie(int ft_initial_assoc,
const u8 *ie1, size_t ie1len,
const u8 *ie2, size_t ie2len);
-int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
+int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid);
struct wpa_ft_ies {
const u8 *mdie;
diff --git a/freebsd/contrib/wpa/src/common/wpa_ctrl.h b/freebsd/contrib/wpa/src/common/wpa_ctrl.h
index 3de46823..4dcba81d 100644
--- a/freebsd/contrib/wpa/src/common/wpa_ctrl.h
+++ b/freebsd/contrib/wpa/src/common/wpa_ctrl.h
@@ -76,6 +76,21 @@ extern "C" {
#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE "
/** Regulatory domain channel */
#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
+/** Channel switch (followed by freq=<MHz> and other channel parameters) */
+#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
+
+/** IP subnet status change notification
+ *
+ * When using an offloaded roaming mechanism where driver/firmware takes care
+ * of roaming and IP subnet validation checks post-roaming, this event can
+ * indicate whether IP subnet has changed.
+ *
+ * The event has a status=<0/1/2> parameter where
+ * 0 = unknown
+ * 1 = IP subnet unchanged (can continue to use the old IP address)
+ * 2 = IP subnet changed (need to get a new IP address)
+ */
+#define WPA_EVENT_SUBNET_STATUS_UPDATE "CTRL-EVENT-SUBNET-STATUS-UPDATE "
/** RSN IBSS 4-way handshakes completed with specified peer */
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
@@ -174,6 +189,7 @@ extern "C" {
#define P2P_EVENT_SERV_ASP_RESP "P2P-SERV-ASP-RESP "
#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED "
#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
+#define P2P_EVENT_INVITATION_ACCEPTED "P2P-INVITATION-ACCEPTED "
#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED "
#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
@@ -212,6 +228,11 @@ extern "C" {
/* parameters: <addr> <result> */
#define ANQP_QUERY_DONE "ANQP-QUERY-DONE "
+#define RX_ANQP "RX-ANQP "
+#define RX_HS20_ANQP "RX-HS20-ANQP "
+#define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON "
+#define RX_HS20_ICON "RX-HS20-ICON "
+
#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION "
#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE "
@@ -232,6 +253,7 @@ extern "C" {
#define AP_STA_CONNECTED "AP-STA-CONNECTED "
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
#define AP_STA_POSSIBLE_PSK_MISMATCH "AP-STA-POSSIBLE-PSK-MISMATCH "
+#define AP_STA_POLL_OK "AP-STA-POLL-OK "
#define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
#define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
@@ -254,9 +276,18 @@ extern "C" {
#define AP_CSA_FINISHED "AP-CSA-FINISHED "
+#define P2P_EVENT_LISTEN_OFFLOAD_STOP "P2P-LISTEN-OFFLOAD-STOPPED "
+#define P2P_LISTEN_OFFLOAD_STOP_REASON "P2P-LISTEN-OFFLOAD-STOP-REASON "
+
/* BSS Transition Management Response frame received */
#define BSS_TM_RESP "BSS-TM-RESP "
+/* MBO IE with cellular data connection preference received */
+#define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE "
+
+/* BSS Transition Management Request received with MBO transition reason */
+#define MBO_TRANSITION_REASON "MBO-TRANSITION-REASON "
+
/* BSS command information masks */
#define WPA_BSS_MASK_ALL 0xFFFDFFFF
@@ -300,6 +331,7 @@ enum wpa_vendor_elem_frame {
VENDOR_ELEM_P2P_ASSOC_REQ = 11,
VENDOR_ELEM_P2P_ASSOC_RESP = 12,
VENDOR_ELEM_ASSOC_REQ = 13,
+ VENDOR_ELEM_PROBE_REQ = 14,
NUM_VENDOR_ELEM_FRAMES
};
diff --git a/freebsd/contrib/wpa/src/crypto/aes-omac1.c b/freebsd/contrib/wpa/src/crypto/aes-omac1.c
index 7e62ef85..8ad5a356 100644
--- a/freebsd/contrib/wpa/src/crypto/aes-omac1.c
+++ b/freebsd/contrib/wpa/src/crypto/aes-omac1.c
@@ -50,6 +50,9 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *pos, *end;
size_t i, e, left, total_len;
+ if (TEST_FAIL())
+ return -1;
+
ctx = aes_encrypt_init(key, key_len);
if (ctx == NULL)
return -1;
diff --git a/freebsd/contrib/wpa/src/crypto/crypto.h b/freebsd/contrib/wpa/src/crypto/crypto.h
index 534c4bd7..bdc3ba6f 100644
--- a/freebsd/contrib/wpa/src/crypto/crypto.h
+++ b/freebsd/contrib/wpa/src/crypto/crypto.h
@@ -80,6 +80,28 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac);
/**
+ * sha384_vector - SHA384 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac);
+
+/**
+ * sha512_vector - SHA512 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac);
+
+/**
* des_encrypt - Encrypt one block with DES
* @clear: 8 octets (in)
* @key: 7 octets (in) (no parity bits included)
@@ -135,7 +157,8 @@ void aes_decrypt_deinit(void *ctx);
enum crypto_hash_alg {
CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1,
- CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256
+ CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256,
+ CRYPTO_HASH_ALG_SHA384, CRYPTO_HASH_ALG_SHA512
};
struct crypto_hash;
diff --git a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c
index 83630422..ee4d55eb 100644
--- a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c
+++ b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c
@@ -31,11 +31,61 @@
#include "sha1.h"
#include "sha256.h"
#include "sha384.h"
+#include "md5.h"
+#include "aes_wrap.h"
#include "crypto.h"
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+/* Compatibility wrappers for older versions. */
+
+static HMAC_CTX * HMAC_CTX_new(void)
+{
+ HMAC_CTX *ctx;
+
+ ctx = os_zalloc(sizeof(*ctx));
+ if (ctx)
+ HMAC_CTX_init(ctx);
+ return ctx;
+}
+
+
+static void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+ if (!ctx)
+ return;
+ HMAC_CTX_cleanup(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
+}
+
+
+static EVP_MD_CTX * EVP_MD_CTX_new(void)
+{
+ EVP_MD_CTX *ctx;
+
+ ctx = os_zalloc(sizeof(*ctx));
+ if (ctx)
+ EVP_MD_CTX_init(ctx);
+ return ctx;
+}
+
+
+static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+ if (!ctx)
+ return;
+ EVP_MD_CTX_cleanup(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
+}
+
+#endif /* OpenSSL version < 1.1.0 */
+
static BIGNUM * get_group5_prime(void)
{
-#ifdef OPENSSL_IS_BORINGSSL
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return BN_get_rfc3526_prime_1536(NULL);
+#elif !defined(OPENSSL_IS_BORINGSSL)
+ return get_rfc3526_prime_1536(NULL);
+#else
static const unsigned char RFC3526_PRIME_1536[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
@@ -55,9 +105,7 @@ static BIGNUM * get_group5_prime(void)
0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
-#else /* OPENSSL_IS_BORINGSSL */
- return get_rfc3526_prime_1536(NULL);
-#endif /* OPENSSL_IS_BORINGSSL */
+#endif
}
#ifdef OPENSSL_NO_SHA256
@@ -67,29 +115,38 @@ static BIGNUM * get_group5_prime(void)
static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
- EVP_MD_CTX ctx;
+ EVP_MD_CTX *ctx;
size_t i;
unsigned int mac_len;
- EVP_MD_CTX_init(&ctx);
- if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
+ if (TEST_FAIL())
+ return -1;
+
+ ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ return -1;
+ if (!EVP_DigestInit_ex(ctx, type, NULL)) {
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
ERR_error_string(ERR_get_error(), NULL));
+ EVP_MD_CTX_free(ctx);
return -1;
}
for (i = 0; i < num_elem; i++) {
- if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) {
+ if (!EVP_DigestUpdate(ctx, addr[i], len[i])) {
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
"failed: %s",
ERR_error_string(ERR_get_error(), NULL));
+ EVP_MD_CTX_free(ctx);
return -1;
}
}
- if (!EVP_DigestFinal(&ctx, mac, &mac_len)) {
+ if (!EVP_DigestFinal(ctx, mac, &mac_len)) {
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
ERR_error_string(ERR_get_error(), NULL));
+ EVP_MD_CTX_free(ctx);
return -1;
}
+ EVP_MD_CTX_free(ctx);
return 0;
}
@@ -131,32 +188,34 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip,
#ifdef OPENSSL_NO_RC4
return -1;
#else /* OPENSSL_NO_RC4 */
- EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX *ctx;
int outl;
int res = -1;
unsigned char skip_buf[16];
- EVP_CIPHER_CTX_init(&ctx);
- if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) ||
- !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
- !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) ||
- !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1))
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx ||
+ !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
+ !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
+ !EVP_CIPHER_CTX_set_key_length(ctx, keylen) ||
+ !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1))
goto out;
while (skip >= sizeof(skip_buf)) {
size_t len = skip;
if (len > sizeof(skip_buf))
len = sizeof(skip_buf);
- if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len))
+ if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len))
goto out;
skip -= len;
}
- if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len))
+ if (EVP_CipherUpdate(ctx, data, &outl, data, data_len))
res = 0;
out:
- EVP_CIPHER_CTX_cleanup(&ctx);
+ if (ctx)
+ EVP_CIPHER_CTX_free(ctx);
return res;
#endif /* OPENSSL_NO_RC4 */
}
@@ -208,14 +267,16 @@ void * aes_encrypt_init(const u8 *key, size_t len)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *type;
+ if (TEST_FAIL())
+ return NULL;
+
type = aes_get_evp_cipher(len);
if (type == NULL)
return NULL;
- ctx = os_malloc(sizeof(*ctx));
+ ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return NULL;
- EVP_CIPHER_CTX_init(ctx);
if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
os_free(ctx);
return NULL;
@@ -249,8 +310,7 @@ void aes_encrypt_deinit(void *ctx)
wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
"in AES encrypt", len);
}
- EVP_CIPHER_CTX_cleanup(c);
- bin_clear_free(c, sizeof(*c));
+ EVP_CIPHER_CTX_free(c);
}
@@ -259,16 +319,18 @@ void * aes_decrypt_init(const u8 *key, size_t len)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *type;
+ if (TEST_FAIL())
+ return NULL;
+
type = aes_get_evp_cipher(len);
if (type == NULL)
return NULL;
- ctx = os_malloc(sizeof(*ctx));
+ ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return NULL;
- EVP_CIPHER_CTX_init(ctx);
if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
- os_free(ctx);
+ EVP_CIPHER_CTX_free(ctx);
return NULL;
}
EVP_CIPHER_CTX_set_padding(ctx, 0);
@@ -300,8 +362,7 @@ void aes_decrypt_deinit(void *ctx)
wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
"in AES decrypt", len);
}
- EVP_CIPHER_CTX_cleanup(c);
- bin_clear_free(c, sizeof(*c));
+ EVP_CIPHER_CTX_free(c);
}
@@ -340,51 +401,56 @@ int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
{
- EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX *ctx;
int clen, len;
u8 buf[16];
+ int res = -1;
- EVP_CIPHER_CTX_init(&ctx);
- if (EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
+ if (TEST_FAIL())
return -1;
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
- clen = data_len;
- if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 ||
- clen != (int) data_len)
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
return -1;
-
+ clen = data_len;
len = sizeof(buf);
- if (EVP_EncryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
- return -1;
- EVP_CIPHER_CTX_cleanup(&ctx);
+ if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
+ EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
+ EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 &&
+ clen == (int) data_len &&
+ EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
+ res = 0;
+ EVP_CIPHER_CTX_free(ctx);
- return 0;
+ return res;
}
int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
{
- EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX *ctx;
int plen, len;
u8 buf[16];
+ int res = -1;
- EVP_CIPHER_CTX_init(&ctx);
- if (EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
+ if (TEST_FAIL())
return -1;
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
- plen = data_len;
- if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 ||
- plen != (int) data_len)
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
return -1;
-
+ plen = data_len;
len = sizeof(buf);
- if (EVP_DecryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
- return -1;
- EVP_CIPHER_CTX_cleanup(&ctx);
+ if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
+ EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
+ EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 &&
+ plen == (int) data_len &&
+ EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
+ res = 0;
+ EVP_CIPHER_CTX_free(ctx);
+
+ return res;
- return 0;
}
@@ -427,8 +493,8 @@ error:
struct crypto_cipher {
- EVP_CIPHER_CTX enc;
- EVP_CIPHER_CTX dec;
+ EVP_CIPHER_CTX *enc;
+ EVP_CIPHER_CTX *dec;
};
@@ -489,23 +555,25 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
return NULL;
}
- EVP_CIPHER_CTX_init(&ctx->enc);
- EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
- if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
- !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
- !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) {
- EVP_CIPHER_CTX_cleanup(&ctx->enc);
+ if (!(ctx->enc = EVP_CIPHER_CTX_new()) ||
+ !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) ||
+ !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) ||
+ !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) ||
+ !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) {
+ if (ctx->enc)
+ EVP_CIPHER_CTX_free(ctx->enc);
os_free(ctx);
return NULL;
}
- EVP_CIPHER_CTX_init(&ctx->dec);
- EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
- if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
- !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
- !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) {
- EVP_CIPHER_CTX_cleanup(&ctx->enc);
- EVP_CIPHER_CTX_cleanup(&ctx->dec);
+ if (!(ctx->dec = EVP_CIPHER_CTX_new()) ||
+ !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) ||
+ !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) ||
+ !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) ||
+ !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) {
+ EVP_CIPHER_CTX_free(ctx->enc);
+ if (ctx->dec)
+ EVP_CIPHER_CTX_free(ctx->dec);
os_free(ctx);
return NULL;
}
@@ -518,7 +586,7 @@ int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
u8 *crypt, size_t len)
{
int outl;
- if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len))
+ if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len))
return -1;
return 0;
}
@@ -529,7 +597,7 @@ int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
{
int outl;
outl = len;
- if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len))
+ if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len))
return -1;
return 0;
}
@@ -537,19 +605,21 @@ int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
void crypto_cipher_deinit(struct crypto_cipher *ctx)
{
- EVP_CIPHER_CTX_cleanup(&ctx->enc);
- EVP_CIPHER_CTX_cleanup(&ctx->dec);
+ EVP_CIPHER_CTX_free(ctx->enc);
+ EVP_CIPHER_CTX_free(ctx->dec);
os_free(ctx);
}
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
{
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
DH *dh;
struct wpabuf *pubkey = NULL, *privkey = NULL;
size_t publen, privlen;
*priv = NULL;
+ wpabuf_free(*publ);
*publ = NULL;
dh = DH_new();
@@ -588,11 +658,63 @@ err:
wpabuf_clear_free(privkey);
DH_free(dh);
return NULL;
+#else
+ DH *dh;
+ struct wpabuf *pubkey = NULL, *privkey = NULL;
+ size_t publen, privlen;
+ BIGNUM *p = NULL, *g;
+ const BIGNUM *priv_key = NULL, *pub_key = NULL;
+
+ *priv = NULL;
+ wpabuf_free(*publ);
+ *publ = NULL;
+
+ dh = DH_new();
+ if (dh == NULL)
+ return NULL;
+
+ g = BN_new();
+ p = get_group5_prime();
+ if (!g || BN_set_word(g, 2) != 1 || !p ||
+ DH_set0_pqg(dh, p, NULL, g) != 1)
+ goto err;
+ p = NULL;
+ g = NULL;
+
+ if (DH_generate_key(dh) != 1)
+ goto err;
+
+ DH_get0_key(dh, &pub_key, &priv_key);
+ publen = BN_num_bytes(pub_key);
+ pubkey = wpabuf_alloc(publen);
+ if (!pubkey)
+ goto err;
+ privlen = BN_num_bytes(priv_key);
+ privkey = wpabuf_alloc(privlen);
+ if (!privkey)
+ goto err;
+
+ BN_bn2bin(pub_key, wpabuf_put(pubkey, publen));
+ BN_bn2bin(priv_key, wpabuf_put(privkey, privlen));
+
+ *priv = privkey;
+ *publ = pubkey;
+ return dh;
+
+err:
+ BN_free(p);
+ BN_free(g);
+ wpabuf_clear_free(pubkey);
+ wpabuf_clear_free(privkey);
+ DH_free(dh);
+ return NULL;
+#endif
}
void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
{
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
DH *dh;
dh = DH_new();
@@ -623,6 +745,42 @@ void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
err:
DH_free(dh);
return NULL;
+#else
+ DH *dh;
+ BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL;
+
+ dh = DH_new();
+ if (dh == NULL)
+ return NULL;
+
+ g = BN_new();
+ p = get_group5_prime();
+ if (!g || BN_set_word(g, 2) != 1 || !p ||
+ DH_set0_pqg(dh, p, NULL, g) != 1)
+ goto err;
+ p = NULL;
+ g = NULL;
+
+ priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
+ pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
+ if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1)
+ goto err;
+ pub_key = NULL;
+ priv_key = NULL;
+
+ if (DH_generate_key(dh) != 1)
+ goto err;
+
+ return dh;
+
+err:
+ BN_free(p);
+ BN_free(g);
+ BN_free(pub_key);
+ BN_clear_free(priv_key);
+ DH_free(dh);
+ return NULL;
+#endif
}
@@ -674,7 +832,7 @@ void dh5_free(void *ctx)
struct crypto_hash {
- HMAC_CTX ctx;
+ HMAC_CTX *ctx;
};
@@ -709,16 +867,17 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
ctx = os_zalloc(sizeof(*ctx));
if (ctx == NULL)
return NULL;
- HMAC_CTX_init(&ctx->ctx);
+ ctx->ctx = HMAC_CTX_new();
+ if (!ctx->ctx) {
+ os_free(ctx);
+ return NULL;
+ }
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL);
-#else /* openssl < 0.9.9 */
- if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) {
+ if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) {
+ HMAC_CTX_free(ctx->ctx);
bin_clear_free(ctx, sizeof(*ctx));
return NULL;
}
-#endif /* openssl < 0.9.9 */
return ctx;
}
@@ -728,7 +887,7 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
{
if (ctx == NULL)
return;
- HMAC_Update(&ctx->ctx, data, len);
+ HMAC_Update(ctx->ctx, data, len);
}
@@ -741,18 +900,14 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
return -2;
if (mac == NULL || len == NULL) {
+ HMAC_CTX_free(ctx->ctx);
bin_clear_free(ctx, sizeof(*ctx));
return 0;
}
mdlen = *len;
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Final(&ctx->ctx, mac, &mdlen);
- res = 1;
-#else /* openssl < 0.9.9 */
- res = HMAC_Final(&ctx->ctx, mac, &mdlen);
-#endif /* openssl < 0.9.9 */
- HMAC_CTX_cleanup(&ctx->ctx);
+ res = HMAC_Final(ctx->ctx, mac, &mdlen);
+ HMAC_CTX_free(ctx->ctx);
bin_clear_free(ctx, sizeof(*ctx));
if (res == 1) {
@@ -769,28 +924,26 @@ static int openssl_hmac_vector(const EVP_MD *type, const u8 *key,
const u8 *addr[], const size_t *len, u8 *mac,
unsigned int mdlen)
{
- HMAC_CTX ctx;
+ HMAC_CTX *ctx;
size_t i;
int res;
- HMAC_CTX_init(&ctx);
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Init_ex(&ctx, key, key_len, type, NULL);
-#else /* openssl < 0.9.9 */
- if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1)
+ if (TEST_FAIL())
return -1;
-#endif /* openssl < 0.9.9 */
+
+ ctx = HMAC_CTX_new();
+ if (!ctx)
+ return -1;
+ res = HMAC_Init_ex(ctx, key, key_len, type, NULL);
+ if (res != 1)
+ goto done;
for (i = 0; i < num_elem; i++)
- HMAC_Update(&ctx, addr[i], len[i]);
+ HMAC_Update(ctx, addr[i], len[i]);
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Final(&ctx, mac, &mdlen);
- res = 1;
-#else /* openssl < 0.9.9 */
- res = HMAC_Final(&ctx, mac, &mdlen);
-#endif /* openssl < 0.9.9 */
- HMAC_CTX_cleanup(&ctx);
+ res = HMAC_Final(ctx, mac, &mdlen);
+done:
+ HMAC_CTX_free(ctx);
return res == 1 ? 0 : -1;
}
@@ -894,6 +1047,9 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
int ret = -1;
size_t outlen, i;
+ if (TEST_FAIL())
+ return -1;
+
ctx = CMAC_CTX_new();
if (ctx == NULL)
return -1;
@@ -943,13 +1099,20 @@ int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
struct crypto_bignum * crypto_bignum_init(void)
{
+ if (TEST_FAIL())
+ return NULL;
return (struct crypto_bignum *) BN_new();
}
struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
{
- BIGNUM *bn = BN_bin2bn(buf, len, NULL);
+ BIGNUM *bn;
+
+ if (TEST_FAIL())
+ return NULL;
+
+ bn = BN_bin2bn(buf, len, NULL);
return (struct crypto_bignum *) bn;
}
@@ -968,6 +1131,9 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
{
int num_bytes, offset;
+ if (TEST_FAIL())
+ return -1;
+
if (padlen > buflen)
return -1;
@@ -1021,6 +1187,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
int res;
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
@@ -1039,6 +1208,8 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
BIGNUM *res;
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
@@ -1054,6 +1225,8 @@ int crypto_bignum_sub(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
{
+ if (TEST_FAIL())
+ return -1;
return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
0 : -1;
}
@@ -1067,6 +1240,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
@@ -1087,6 +1263,9 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
@@ -1130,6 +1309,9 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
BIGNUM *exp = NULL, *tmp = NULL;
int res = -2;
+ if (TEST_FAIL())
+ return -2;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -2;
@@ -1254,6 +1436,8 @@ void crypto_ec_deinit(struct crypto_ec *e)
struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
{
+ if (TEST_FAIL())
+ return NULL;
if (e == NULL)
return NULL;
return (struct crypto_ec_point *) EC_POINT_new(e->group);
@@ -1300,6 +1484,9 @@ int crypto_ec_point_to_bin(struct crypto_ec *e,
int ret = -1;
int len = BN_num_bytes(e->prime);
+ if (TEST_FAIL())
+ return -1;
+
x_bn = BN_new();
y_bn = BN_new();
@@ -1330,6 +1517,9 @@ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
EC_POINT *elem;
int len = BN_num_bytes(e->prime);
+ if (TEST_FAIL())
+ return NULL;
+
x = BN_bin2bn(val, len, NULL);
y = BN_bin2bn(val + len, len, NULL);
elem = EC_POINT_new(e->group);
@@ -1357,6 +1547,8 @@ int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
const struct crypto_ec_point *b,
struct crypto_ec_point *c)
{
+ if (TEST_FAIL())
+ return -1;
return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a,
(const EC_POINT *) b, e->bnctx) ? 0 : -1;
}
@@ -1366,6 +1558,8 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
const struct crypto_bignum *b,
struct crypto_ec_point *res)
{
+ if (TEST_FAIL())
+ return -1;
return EC_POINT_mul(e->group, (EC_POINT *) res, NULL,
(const EC_POINT *) p, (const BIGNUM *) b, e->bnctx)
? 0 : -1;
@@ -1374,6 +1568,8 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
{
+ if (TEST_FAIL())
+ return -1;
return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1;
}
@@ -1382,6 +1578,8 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
struct crypto_ec_point *p,
const struct crypto_bignum *x, int y_bit)
{
+ if (TEST_FAIL())
+ return -1;
if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p,
(const BIGNUM *) x, y_bit,
e->bnctx) ||
@@ -1397,6 +1595,9 @@ crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
{
BIGNUM *tmp, *tmp2, *y_sqr = NULL;
+ if (TEST_FAIL())
+ return NULL;
+
tmp = BN_new();
tmp2 = BN_new();
diff --git a/freebsd/contrib/wpa/src/crypto/ms_funcs.c b/freebsd/contrib/wpa/src/crypto/ms_funcs.c
index dda2ba7c..67e98dbf 100644
--- a/freebsd/contrib/wpa/src/crypto/ms_funcs.c
+++ b/freebsd/contrib/wpa/src/crypto/ms_funcs.c
@@ -50,7 +50,7 @@ static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
WPA_PUT_LE16(ucs2_buffer + j,
((c & 0x1F) << 6) | (c2 & 0x3F));
j += 2;
- } else if (i == utf8_string_len ||
+ } else if (i == utf8_string_len - 1 ||
j >= ucs2_buffer_size - 1) {
/* incomplete surrogate */
return -1;
diff --git a/freebsd/contrib/wpa/src/crypto/sha256-internal.c b/freebsd/contrib/wpa/src/crypto/sha256-internal.c
index c2ef3154..174bf3c4 100644
--- a/freebsd/contrib/wpa/src/crypto/sha256-internal.c
+++ b/freebsd/contrib/wpa/src/crypto/sha256-internal.c
@@ -30,6 +30,9 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
struct sha256_state ctx;
size_t i;
+ if (TEST_FAIL())
+ return -1;
+
sha256_init(&ctx);
for (i = 0; i < num_elem; i++)
if (sha256_process(&ctx, addr[i], len[i]))
diff --git a/freebsd/contrib/wpa/src/crypto/sha256-prf.c b/freebsd/contrib/wpa/src/crypto/sha256-prf.c
index 76496214..e2150e21 100644
--- a/freebsd/contrib/wpa/src/crypto/sha256-prf.c
+++ b/freebsd/contrib/wpa/src/crypto/sha256-prf.c
@@ -2,7 +2,7 @@
/*
* SHA256-based PRF (IEEE 802.11r)
- * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -24,14 +24,16 @@
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bytes of key to generate
+ * Returns: 0 on success, -1 on failure
*
* This function is used to derive new, cryptographically separate keys from a
* given key.
*/
-void sha256_prf(const u8 *key, size_t key_len, const char *label,
+int sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{
- sha256_prf_bits(key, key_len, label, data, data_len, buf, buf_len * 8);
+ return sha256_prf_bits(key, key_len, label, data, data_len, buf,
+ buf_len * 8);
}
@@ -44,15 +46,16 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bits of key to generate
+ * Returns: 0 on success, -1 on failure
*
* This function is used to derive new, cryptographically separate keys from a
* given key. If the requested buf_len is not divisible by eight, the least
* significant 1-7 bits of the last octet in the output are not part of the
* requested output.
*/
-void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
- const u8 *data, size_t data_len, u8 *buf,
- size_t buf_len_bits)
+int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits)
{
u16 counter = 1;
size_t pos, plen;
@@ -77,11 +80,14 @@ void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
plen = buf_len - pos;
WPA_PUT_LE16(counter_le, counter);
if (plen >= SHA256_MAC_LEN) {
- hmac_sha256_vector(key, key_len, 4, addr, len,
- &buf[pos]);
+ if (hmac_sha256_vector(key, key_len, 4, addr, len,
+ &buf[pos]) < 0)
+ return -1;
pos += SHA256_MAC_LEN;
} else {
- hmac_sha256_vector(key, key_len, 4, addr, len, hash);
+ if (hmac_sha256_vector(key, key_len, 4, addr, len,
+ hash) < 0)
+ return -1;
os_memcpy(&buf[pos], hash, plen);
pos += plen;
break;
@@ -99,4 +105,6 @@ void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
}
os_memset(hash, 0, sizeof(hash));
+
+ return 0;
}
diff --git a/freebsd/contrib/wpa/src/crypto/sha256.h b/freebsd/contrib/wpa/src/crypto/sha256.h
index b15f5115..5219022e 100644
--- a/freebsd/contrib/wpa/src/crypto/sha256.h
+++ b/freebsd/contrib/wpa/src/crypto/sha256.h
@@ -1,6 +1,6 @@
/*
* SHA256 hash implementation and interface functions
- * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -15,11 +15,11 @@ int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac);
int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
-void sha256_prf(const u8 *key, size_t key_len, const char *label,
- const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
-void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
- const u8 *data, size_t data_len, u8 *buf,
- size_t buf_len_bits);
+int sha256_prf(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits);
void tls_prf_sha256(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);
diff --git a/freebsd/contrib/wpa/src/crypto/tls.h b/freebsd/contrib/wpa/src/crypto/tls.h
index 2e562339..11d504a9 100644
--- a/freebsd/contrib/wpa/src/crypto/tls.h
+++ b/freebsd/contrib/wpa/src/crypto/tls.h
@@ -95,6 +95,8 @@ struct tls_config {
#define TLS_CONN_DISABLE_TLSv1_2 BIT(6)
#define TLS_CONN_EAP_FAST BIT(7)
#define TLS_CONN_DISABLE_TLSv1_0 BIT(8)
+#define TLS_CONN_EXT_CERT_CHECK BIT(9)
+#define TLS_CONN_REQUIRE_OCSP_ALL BIT(10)
/**
* struct tls_connection_params - Parameters for TLS connection
@@ -139,6 +141,9 @@ struct tls_config {
* @flags: Parameter options (TLS_CONN_*)
* @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
* or %NULL if OCSP is not enabled
+ * @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling
+ * response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if
+ * ocsp_multi is not enabled
*
* TLS connection parameters to be configured with tls_connection_set_params()
* and tls_global_set_params().
@@ -179,6 +184,7 @@ struct tls_connection_params {
unsigned int flags;
const char *ocsp_stapling_response;
+ const char *ocsp_stapling_response_multi;
};
@@ -330,29 +336,36 @@ int __must_check tls_connection_get_random(void *tls_ctx,
struct tls_random *data);
/**
- * tls_connection_prf - Use TLS-PRF to derive keying material
+ * tls_connection_export_key - Derive keying material from a TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @label: Label (e.g., description of the key) for PRF
- * @server_random_first: seed is 0 = client_random|server_random,
- * 1 = server_random|client_random
- * @skip_keyblock: Skip TLS key block from the beginning of PRF output
* @out: Buffer for output data from TLS-PRF
* @out_len: Length of the output buffer
* Returns: 0 on success, -1 on failure
*
- * tls_connection_prf() is required so that further keying material can be
- * derived from the master secret. Example implementation of this function is in
- * tls_prf_sha1_md5() when it is called with seed set to
- * client_random|server_random (or server_random|client_random). For TLSv1.2 and
- * newer, a different PRF is needed, though.
+ * Exports keying material using the mechanism described in RFC 5705.
*/
-int __must_check tls_connection_prf(void *tls_ctx,
- struct tls_connection *conn,
- const char *label,
- int server_random_first,
- int skip_keyblock,
- u8 *out, size_t out_len);
+int __must_check tls_connection_export_key(void *tls_ctx,
+ struct tls_connection *conn,
+ const char *label,
+ u8 *out, size_t out_len);
+
+/**
+ * tls_connection_get_eap_fast_key - Derive key material for EAP-FAST
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @out: Buffer for output data from TLS-PRF
+ * @out_len: Length of the output buffer
+ * Returns: 0 on success, -1 on failure
+ *
+ * Exports key material after the normal TLS key block for use with
+ * EAP-FAST. Most callers will want tls_connection_export_key(), but EAP-FAST
+ * uses a different legacy mechanism.
+ */
+int __must_check tls_connection_get_eap_fast_key(void *tls_ctx,
+ struct tls_connection *conn,
+ u8 *out, size_t out_len);
/**
* tls_connection_handshake - Process TLS handshake (client side)
@@ -455,7 +468,9 @@ enum {
TLS_CIPHER_RC4_SHA /* 0x0005 */,
TLS_CIPHER_AES128_SHA /* 0x002f */,
TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */,
- TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */
+ TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */,
+ TLS_CIPHER_RSA_DHE_AES256_SHA /* 0x0039 */,
+ TLS_CIPHER_AES256_SHA /* 0x0035 */,
};
/**
diff --git a/freebsd/contrib/wpa/src/crypto/tls_internal.c b/freebsd/contrib/wpa/src/crypto/tls_internal.c
index 6a91f497..c6f65dc0 100644
--- a/freebsd/contrib/wpa/src/crypto/tls_internal.c
+++ b/freebsd/contrib/wpa/src/crypto/tls_internal.c
@@ -25,6 +25,11 @@ struct tls_global {
int server;
struct tlsv1_credentials *server_cred;
int check_crl;
+
+ void (*event_cb)(void *ctx, enum tls_event ev,
+ union tls_event_data *data);
+ void *cb_ctx;
+ int cert_in_cb;
};
struct tls_connection {
@@ -53,6 +58,11 @@ void * tls_init(const struct tls_config *conf)
global = os_zalloc(sizeof(*global));
if (global == NULL)
return NULL;
+ if (conf) {
+ global->event_cb = conf->event_cb;
+ global->cb_ctx = conf->cb_ctx;
+ global->cert_in_cb = conf->cert_in_cb;
+ }
return global;
}
@@ -66,10 +76,12 @@ void tls_deinit(void *ssl_ctx)
tlsv1_client_global_deinit();
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
- tlsv1_cred_free(global->server_cred);
tlsv1_server_global_deinit();
#endif /* CONFIG_TLS_INTERNAL_SERVER */
}
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ tlsv1_cred_free(global->server_cred);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
os_free(global);
}
@@ -97,6 +109,8 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
os_free(conn);
return NULL;
}
+ tlsv1_client_set_cb(conn->client, global->event_cb,
+ global->cb_ctx, global->cert_in_cb);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
@@ -188,6 +202,12 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
if (conn->client == NULL)
return -1;
+ if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
+ wpa_printf(MSG_INFO,
+ "TLS: tls_ext_cert_check=1 not supported");
+ return -1;
+ }
+
cred = tlsv1_cred_alloc();
if (cred == NULL)
return -1;
@@ -261,8 +281,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
- tlsv1_client_set_time_checks(
- conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
+ tlsv1_client_set_flags(conn->client, params->flags);
return 0;
#else /* CONFIG_TLS_INTERNAL_CLIENT */
@@ -314,6 +333,13 @@ int tls_global_set_params(void *tls_ctx,
return -1;
}
+ if (params->ocsp_stapling_response)
+ cred->ocsp_stapling_response =
+ os_strdup(params->ocsp_stapling_response);
+ if (params->ocsp_stapling_response_multi)
+ cred->ocsp_stapling_response_multi =
+ os_strdup(params->ocsp_stapling_response_multi);
+
return 0;
#else /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
@@ -370,9 +396,9 @@ static int tls_get_keyblock_size(struct tls_connection *conn)
}
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
- int skip_keyblock, u8 *out, size_t out_len)
+static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+ const char *label, int server_random_first,
+ int skip_keyblock, u8 *out, size_t out_len)
{
int ret = -1, skip = 0;
u8 *tmp_out = NULL;
@@ -392,14 +418,14 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
if (conn->client) {
ret = tlsv1_client_prf(conn->client, label,
server_random_first,
- _out, out_len);
+ _out, skip + out_len);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
ret = tlsv1_server_prf(conn->server, label,
server_random_first,
- _out, out_len);
+ _out, skip + out_len);
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
if (ret == 0 && skip_keyblock)
@@ -410,6 +436,21 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
+int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
+ const char *label, u8 *out, size_t out_len)
+{
+ return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
+}
+
+
+int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
+ u8 *out, size_t out_len)
+{
+ return tls_connection_prf(tls_ctx, conn, "key expansion", 1, 1, out,
+ out_len);
+}
+
+
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
@@ -623,7 +664,12 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
char *buf, size_t buflen)
{
- /* TODO */
+ if (conn == NULL)
+ return -1;
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+ if (conn->client)
+ return tlsv1_client_get_version(conn->client, buf, buflen);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
return -1;
}
diff --git a/freebsd/contrib/wpa/src/drivers/driver.h b/freebsd/contrib/wpa/src/drivers/driver.h
index 3cdab5a7..a449cc93 100644
--- a/freebsd/contrib/wpa/src/drivers/driver.h
+++ b/freebsd/contrib/wpa/src/drivers/driver.h
@@ -45,6 +45,22 @@
#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
+#define HOSTAPD_CHAN_VHT_10_150 0x00100000
+#define HOSTAPD_CHAN_VHT_30_130 0x00200000
+#define HOSTAPD_CHAN_VHT_50_110 0x00400000
+#define HOSTAPD_CHAN_VHT_70_90 0x00800000
+#define HOSTAPD_CHAN_VHT_90_70 0x01000000
+#define HOSTAPD_CHAN_VHT_110_50 0x02000000
+#define HOSTAPD_CHAN_VHT_130_30 0x04000000
+#define HOSTAPD_CHAN_VHT_150_10 0x08000000
+
+/* Filter gratuitous ARP */
+#define WPA_DATA_FRAME_FILTER_FLAG_ARP BIT(0)
+/* Filter unsolicited Neighbor Advertisement */
+#define WPA_DATA_FRAME_FILTER_FLAG_NA BIT(1)
+/* Filter unicast IP packets encrypted using the GTK */
+#define WPA_DATA_FRAME_FILTER_FLAG_GTK BIT(2)
+
/**
* enum reg_change_initiator - Regulatory change initiator
*/
@@ -284,6 +300,18 @@ struct wpa_interface_info {
#define WPAS_MAX_SCAN_SSIDS 16
/**
+ * struct wpa_driver_scan_ssid - SSIDs to scan for
+ * @ssid - specific SSID to scan for (ProbeReq)
+ * %NULL or zero-length SSID is used to indicate active scan
+ * with wildcard SSID.
+ * @ssid_len - Length of the SSID in octets
+ */
+struct wpa_driver_scan_ssid {
+ const u8 *ssid;
+ size_t ssid_len;
+};
+
+/**
* struct wpa_driver_scan_params - Scan parameters
* Data for struct wpa_driver_ops::scan2().
*/
@@ -291,18 +319,7 @@ struct wpa_driver_scan_params {
/**
* ssids - SSIDs to scan for
*/
- struct wpa_driver_scan_ssid {
- /**
- * ssid - specific SSID to scan for (ProbeReq)
- * %NULL or zero-length SSID is used to indicate active scan
- * with wildcard SSID.
- */
- const u8 *ssid;
- /**
- * ssid_len: Length of the SSID in octets
- */
- size_t ssid_len;
- } ssids[WPAS_MAX_SCAN_SSIDS];
+ struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
/**
* num_ssids - Number of entries in ssids array
@@ -407,6 +424,37 @@ struct wpa_driver_scan_params {
*/
const u8 *mac_addr_mask;
+ /**
+ * sched_scan_plans - Scan plans for scheduled scan
+ *
+ * Each scan plan consists of the number of iterations to scan and the
+ * interval between scans. When a scan plan finishes (i.e., it was run
+ * for the specified number of iterations), the next scan plan is
+ * executed. The scan plans are executed in the order they appear in
+ * the array (lower index first). The last scan plan will run infinitely
+ * (until requested to stop), thus must not specify the number of
+ * iterations. All other scan plans must specify the number of
+ * iterations.
+ */
+ struct sched_scan_plan {
+ u32 interval; /* In seconds */
+ u32 iterations; /* Zero to run infinitely */
+ } *sched_scan_plans;
+
+ /**
+ * sched_scan_plans_num - Number of scan plans in sched_scan_plans array
+ */
+ unsigned int sched_scan_plans_num;
+
+ /**
+ * bssid - Specific BSSID to scan for
+ *
+ * This optional parameter can be used to replace the default wildcard
+ * BSSID with a specific BSSID to scan for if results are needed from
+ * only a single BSS.
+ */
+ const u8 *bssid;
+
/*
* NOTE: Whenever adding new parameters here, please make sure
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
@@ -828,6 +876,12 @@ struct wpa_driver_associate_params {
* RRM (Radio Resource Measurements)
*/
int rrm_used;
+
+ /**
+ * pbss - If set, connect to a PCP in a PBSS. Otherwise, connect to an
+ * AP as usual. Valid for DMG network only.
+ */
+ int pbss;
};
enum hide_ssid {
@@ -1055,16 +1109,28 @@ struct wpa_driver_ap_params {
* reenable - Whether this is to re-enable beaconing
*/
int reenable;
+
+ /**
+ * pbss - Whether to start a PCP (in PBSS) instead of an AP in
+ * infrastructure BSS. Valid only for DMG network.
+ */
+ int pbss;
};
struct wpa_driver_mesh_bss_params {
-#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
+#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
+#define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT 0x00000002
+#define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
+#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
/*
* TODO: Other mesh configuration parameters would go here.
* See NL80211_MESHCONF_* for all the mesh config parameters.
*/
unsigned int flags;
+ int auto_plinks;
int peer_link_timeout;
+ int max_peer_links;
+ u16 ht_opmode;
};
struct wpa_driver_mesh_join_params {
@@ -1075,7 +1141,7 @@ struct wpa_driver_mesh_join_params {
int ie_len;
struct hostapd_freq_params freq;
int beacon_int;
- int max_peer_links;
+ int dtim_period;
struct wpa_driver_mesh_bss_params conf;
#define WPA_DRIVER_MESH_FLAG_USER_MPM 0x00000001
#define WPA_DRIVER_MESH_FLAG_DRIVER_MPM 0x00000002
@@ -1214,8 +1280,17 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS_VHT_IBSS 0x0000002000000000ULL
/** Driver supports automatic band selection */
#define WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY 0x0000004000000000ULL
+/** Driver supports simultaneous off-channel operations */
+#define WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS 0x0000008000000000ULL
+/** Driver supports full AP client state */
+#define WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE 0x0000010000000000ULL
+/** Driver supports P2P Listen offload */
+#define WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD 0x0000020000000000ULL
u64 flags;
+#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
+ (drv_flags & WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE)
+
#define WPA_DRIVER_SMPS_MODE_STATIC 0x00000001
#define WPA_DRIVER_SMPS_MODE_DYNAMIC 0x00000002
unsigned int smps_modes;
@@ -1231,6 +1306,15 @@ struct wpa_driver_capa {
/** Maximum number of supported active probe SSIDs for sched_scan */
int max_sched_scan_ssids;
+ /** Maximum number of supported scan plans for scheduled scan */
+ unsigned int max_sched_scan_plans;
+
+ /** Maximum interval in a scan plan. In seconds */
+ u32 max_sched_scan_plan_interval;
+
+ /** Maximum number of iterations in a single scan plan */
+ u32 max_sched_scan_plan_iterations;
+
/** Whether sched_scan (offloaded scanning) is supported */
int sched_scan_supported;
@@ -1296,6 +1380,12 @@ struct wpa_driver_capa {
* offset, namely the 6th byte in the Action frame body.
*/
#define WPA_DRIVER_FLAGS_TX_POWER_INSERTION 0x00000008
+/**
+ * Driver supports RRM. With this support, the driver will accept to use RRM in
+ * (Re)Association Request frames, without supporting quiet period.
+ */
+#define WPA_DRIVER_FLAGS_SUPPORT_RRM 0x00000010
+
u32 rrm_flags;
/* Driver concurrency capabilities */
@@ -1304,13 +1394,18 @@ struct wpa_driver_capa {
unsigned int max_conc_chan_2_4;
/* Maximum number of concurrent channels on 5 GHz */
unsigned int max_conc_chan_5_0;
+
+ /* Maximum number of supported CSA counters */
+ u16 max_csa_counters;
};
struct hostapd_data;
struct hostap_sta_driver_data {
- unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes;
+ unsigned long rx_packets, tx_packets;
+ unsigned long long rx_bytes, tx_bytes;
+ int bytes_64bit; /* whether 64-bit byte counters are supported */
unsigned long current_tx_rate;
unsigned long inactive_msec;
unsigned long flags;
@@ -1336,6 +1431,7 @@ struct hostapd_sta_add_params {
u32 flags_mask; /* unset bits in flags */
#ifdef CONFIG_MESH
enum mesh_plink_state plink_state;
+ u16 peer_aid;
#endif /* CONFIG_MESH */
int set; /* Set STA parameters instead of add */
u8 qosinfo;
@@ -1345,6 +1441,7 @@ struct hostapd_sta_add_params {
size_t supp_channels_len;
const u8 *supp_oper_classes;
size_t supp_oper_classes_len;
+ int support_p2p_ps;
};
struct mac_address {
@@ -1450,6 +1547,7 @@ struct wpa_bss_params {
#define WPA_STA_MFP BIT(3)
#define WPA_STA_TDLS_PEER BIT(4)
#define WPA_STA_AUTHENTICATED BIT(5)
+#define WPA_STA_ASSOCIATED BIT(6)
enum tdls_oper {
TDLS_DISCOVERY_REQ,
@@ -1554,8 +1652,8 @@ struct csa_settings {
struct beacon_data beacon_csa;
struct beacon_data beacon_after;
- u16 counter_offset_beacon;
- u16 counter_offset_presp;
+ u16 counter_offset_beacon[2];
+ u16 counter_offset_presp[2];
};
/* TDLS peer capabilities for send_tdls_mgmt() */
@@ -1883,6 +1981,14 @@ struct wpa_driver_ops {
void (*poll)(void *priv);
/**
+ * get_ifindex - Get interface index
+ * @priv: private driver interface data
+ *
+ * Returns: Interface index
+ */
+ unsigned int (*get_ifindex)(void *priv);
+
+ /**
* get_ifname - Get interface name
* @priv: private driver interface data
*
@@ -1960,10 +2066,13 @@ struct wpa_driver_ops {
* @noack: Do not wait for this frame to be acked (disable retries)
* @freq: Frequency (in MHz) to send the frame on, or 0 to let the
* driver decide
+ * @csa_offs: Array of CSA offsets or %NULL
+ * @csa_offs_len: Number of elements in csa_offs
* Returns: 0 on success, -1 on failure
*/
int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
- int noack, unsigned int freq);
+ int noack, unsigned int freq, const u16 *csa_offs,
+ size_t csa_offs_len);
/**
* update_ft_ies - Update FT (IEEE 802.11r) IEs
@@ -2013,6 +2122,7 @@ struct wpa_driver_ops {
/**
* global_init - Global driver initialization
+ * @ctx: wpa_global pointer
* Returns: Pointer to private data (global), %NULL on failure
*
* This optional function is called to initialize the driver wrapper
@@ -2022,7 +2132,7 @@ struct wpa_driver_ops {
* use init2() function instead of init() to get the pointer to global
* data available to per-interface initializer.
*/
- void * (*global_init)(void);
+ void * (*global_init)(void *ctx);
/**
* global_deinit - Global driver deinitialization
@@ -2308,12 +2418,17 @@ struct wpa_driver_ops {
* @params: Station parameters
* Returns: 0 on success, -1 on failure
*
- * This function is used to add a station entry to the driver once the
- * station has completed association. This is only used if the driver
+ * This function is used to add or set (params->set 1) a station
+ * entry in the driver. Adding STA entries is used only if the driver
* does not take care of association processing.
*
- * With TDLS, this function is also used to add or set (params->set 1)
- * TDLS peer entries.
+ * With drivers that don't support full AP client state, this function
+ * is used to add a station entry to the driver once the station has
+ * completed association.
+ *
+ * With TDLS, this function is used to add or set (params->set 1)
+ * TDLS peer entries (even with drivers that do not support full AP
+ * client state).
*/
int (*sta_add)(void *priv, struct hostapd_sta_add_params *params);
@@ -2399,12 +2514,13 @@ struct wpa_driver_ops {
* change interface address)
* @bridge: Bridge interface to use or %NULL if no bridge configured
* @use_existing: Whether to allow existing interface to be used
+ * @setup_ap: Whether to setup AP for %WPA_IF_AP_BSS interfaces
* Returns: 0 on success, -1 on failure
*/
int (*if_add)(void *priv, enum wpa_driver_if_type type,
const char *ifname, const u8 *addr, void *bss_ctx,
void **drv_priv, char *force_ifname, u8 *if_addr,
- const char *bridge, int use_existing);
+ const char *bridge, int use_existing, int setup_ap);
/**
* if_remove - Remove a virtual interface
@@ -2986,7 +3102,6 @@ struct wpa_driver_ops {
* sched_scan - Request the driver to initiate scheduled scan
* @priv: Private driver interface data
* @params: Scan parameters
- * @interval: Interval between scan cycles in milliseconds
* Returns: 0 on success, -1 on failure
*
* This operation should be used for scheduled scan offload to
@@ -2997,8 +3112,7 @@ struct wpa_driver_ops {
* and if not provided or if it returns -1, we fall back to
* normal host-scheduled scans.
*/
- int (*sched_scan)(void *priv, struct wpa_driver_scan_params *params,
- u32 interval);
+ int (*sched_scan)(void *priv, struct wpa_driver_scan_params *params);
/**
* stop_sched_scan - Request the driver to stop a scheduled scan
@@ -3203,11 +3317,9 @@ struct wpa_driver_ops {
* set_current_cipher_suite - Set current cipher suite
* @priv: Private driver interface data
* @cs: EUI64 identifier
- * @cs_len: Length of the cs buffer in octets
* Returns: 0 on success, -1 on failure (or if not supported)
*/
- int (*set_current_cipher_suite)(void *priv, const u8 *cs,
- size_t cs_len);
+ int (*set_current_cipher_suite)(void *priv, u64 cs);
/**
* enable_controlled_port - Set controlled port status
@@ -3439,6 +3551,78 @@ struct wpa_driver_ops {
* on. Local device is assuming P2P Client role.
*/
int (*set_prob_oper_freq)(void *priv, unsigned int freq);
+
+ /**
+ * abort_scan - Request the driver to abort an ongoing scan
+ * @priv: Private driver interface data
+ * Returns 0 on success, -1 on failure
+ */
+ int (*abort_scan)(void *priv);
+
+ /**
+ * configure_data_frame_filters - Request to configure frame filters
+ * @priv: Private driver interface data
+ * @filter_flags: The type of frames to filter (bitfield of
+ * WPA_DATA_FRAME_FILTER_FLAG_*)
+ * Returns: 0 on success or -1 on failure
+ */
+ int (*configure_data_frame_filters)(void *priv, u32 filter_flags);
+
+ /**
+ * get_ext_capab - Get extended capabilities for the specified interface
+ * @priv: Private driver interface data
+ * @type: Interface type for which to get extended capabilities
+ * @ext_capab: Extended capabilities fetched
+ * @ext_capab_mask: Extended capabilities mask
+ * @ext_capab_len: Length of the extended capabilities
+ * Returns: 0 on success or -1 on failure
+ */
+ int (*get_ext_capab)(void *priv, enum wpa_driver_if_type type,
+ const u8 **ext_capab, const u8 **ext_capab_mask,
+ unsigned int *ext_capab_len);
+
+ /**
+ * p2p_lo_start - Start offloading P2P listen to device
+ * @priv: Private driver interface data
+ * @freq: Listening frequency (MHz) for P2P listen
+ * @period: Length of the listen operation in milliseconds
+ * @interval: Interval for running the listen operation in milliseconds
+ * @count: Number of times to run the listen operation
+ * @device_types: Device primary and secondary types
+ * @dev_types_len: Number of bytes for device_types
+ * @ies: P2P IE and WSC IE for Probe Response frames
+ * @ies_len: Length of ies in bytes
+ * Returns: 0 on success or -1 on failure
+ */
+ int (*p2p_lo_start)(void *priv, unsigned int freq,
+ unsigned int period, unsigned int interval,
+ unsigned int count,
+ const u8 *device_types, size_t dev_types_len,
+ const u8 *ies, size_t ies_len);
+
+ /**
+ * p2p_lo_stop - Stop P2P listen offload
+ * @priv: Private driver interface data
+ * Returns: 0 on success or -1 on failure
+ */
+ int (*p2p_lo_stop)(void *priv);
+
+ /**
+ * set_default_scan_ies - Set default scan IEs
+ * @priv: Private driver interface data
+ * @ies: Scan default IEs buffer
+ * @ies_len: Length of IEs in bytes
+ * Returns: 0 on success or -1 on failure
+ *
+ * The driver can use these by default when there are no scan IEs coming
+ * in the subsequent scan requests. Also in case of one or more of IEs
+ * given in set_default_scan_ies() are missing in the subsequent scan
+ * request, the driver should merge the missing scan IEs in the scan
+ * request from the IEs set by set_default_scan_ies() in the Probe
+ * Request frames sent.
+ */
+ int (*set_default_scan_ies)(void *priv, const u8 *ies, size_t ies_len);
+
};
@@ -3923,6 +4107,11 @@ enum wpa_event_type {
* on a DFS frequency by a driver that supports DFS Offload.
*/
EVENT_DFS_CAC_STARTED,
+
+ /**
+ * EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped
+ */
+ EVENT_P2P_LO_STOP,
};
@@ -4098,6 +4287,12 @@ union wpa_event_data {
* ptk_kek_len - The length of ptk_kek
*/
size_t ptk_kek_len;
+
+ /**
+ * subnet_status - The subnet status:
+ * 0 = unknown, 1 = unchanged, 2 = changed
+ */
+ u8 subnet_status;
} assoc_info;
/**
@@ -4174,6 +4369,7 @@ union wpa_event_data {
* struct interface_status - Data for EVENT_INTERFACE_STATUS
*/
struct interface_status {
+ unsigned int ifindex;
char ifname[100];
enum {
EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED
@@ -4301,6 +4497,12 @@ union wpa_event_data {
* status_code - Status Code from (Re)association Response
*/
u16 status_code;
+
+ /**
+ * timed_out - Whether failure is due to timeout (etc.) rather
+ * than explicit rejection response from the AP.
+ */
+ int timed_out;
} assoc_reject;
struct timeout_event {
@@ -4381,6 +4583,9 @@ union wpa_event_data {
* @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard
* SSID)
* @num_ssids: Number of entries in ssids array
+ * @external_scan: Whether the scan info is for an external scan
+ * @nl_scan_event: 1 if the source of this scan event is a normal scan,
+ * 0 if the source of the scan event is a vendor scan
*/
struct scan_info {
int aborted;
@@ -4388,6 +4593,8 @@ union wpa_event_data {
size_t num_freqs;
struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
size_t num_ssids;
+ int external_scan;
+ int nl_scan_event;
} scan_info;
/**
@@ -4630,6 +4837,27 @@ union wpa_event_data {
u16 ch_width;
enum hostapd_hw_mode hw_mode;
} acs_selected_channels;
+
+ /**
+ * struct p2p_lo_stop - Reason code for P2P Listen offload stop event
+ * @reason_code: Reason for stopping offload
+ * P2P_LO_STOPPED_REASON_COMPLETE: Listen offload finished as
+ * scheduled.
+ * P2P_LO_STOPPED_REASON_RECV_STOP_CMD: Host requested offload to
+ * be stopped.
+ * P2P_LO_STOPPED_REASON_INVALID_PARAM: Invalid listen offload
+ * parameters.
+ * P2P_LO_STOPPED_REASON_NOT_SUPPORTED: Listen offload not
+ * supported by device.
+ */
+ struct p2p_lo_stop {
+ enum {
+ P2P_LO_STOPPED_REASON_COMPLETE = 0,
+ P2P_LO_STOPPED_REASON_RECV_STOP_CMD,
+ P2P_LO_STOPPED_REASON_INVALID_PARAM,
+ P2P_LO_STOPPED_REASON_NOT_SUPPORTED,
+ } reason_code;
+ } p2p_lo_stop;
};
/**
@@ -4645,6 +4873,18 @@ union wpa_event_data {
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data);
+/**
+ * wpa_supplicant_event_global - Report a driver event for wpa_supplicant
+ * @ctx: Context pointer (wpa_s); this is the ctx variable registered
+ * with struct wpa_driver_ops::init()
+ * @event: event type (defined above)
+ * @data: possible extra data for the event
+ *
+ * Same as wpa_supplicant_event(), but we search for the interface in
+ * wpa_global.
+ */
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data);
/*
* The following inline functions are provided for convenience to simplify
@@ -4697,8 +4937,52 @@ int vht_supported(const struct hostapd_hw_modes *mode);
struct wowlan_triggers *
wpa_get_wowlan_triggers(const char *wowlan_triggers,
const struct wpa_driver_capa *capa);
+/* Convert driver flag to string */
+const char * driver_flag_to_string(u64 flag);
/* NULL terminated array of linked in driver wrappers */
extern const struct wpa_driver_ops *const wpa_drivers[];
+
+/* Available drivers */
+
+#ifdef CONFIG_DRIVER_WEXT
+extern const struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
+#endif /* CONFIG_DRIVER_WEXT */
+#ifdef CONFIG_DRIVER_NL80211
+/* driver_nl80211.c */
+extern const struct wpa_driver_ops wpa_driver_nl80211_ops;
+#endif /* CONFIG_DRIVER_NL80211 */
+#ifdef CONFIG_DRIVER_HOSTAP
+extern const struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
+#endif /* CONFIG_DRIVER_HOSTAP */
+#ifdef CONFIG_DRIVER_BSD
+extern const struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
+#endif /* CONFIG_DRIVER_BSD */
+#ifdef CONFIG_DRIVER_OPENBSD
+/* driver_openbsd.c */
+extern const struct wpa_driver_ops wpa_driver_openbsd_ops;
+#endif /* CONFIG_DRIVER_OPENBSD */
+#ifdef CONFIG_DRIVER_NDIS
+extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */
+#endif /* CONFIG_DRIVER_NDIS */
+#ifdef CONFIG_DRIVER_WIRED
+extern const struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
+#endif /* CONFIG_DRIVER_WIRED */
+#ifdef CONFIG_DRIVER_MACSEC_QCA
+/* driver_macsec_qca.c */
+extern const struct wpa_driver_ops wpa_driver_macsec_qca_ops;
+#endif /* CONFIG_DRIVER_MACSEC_QCA */
+#ifdef CONFIG_DRIVER_ROBOSWITCH
+/* driver_roboswitch.c */
+extern const struct wpa_driver_ops wpa_driver_roboswitch_ops;
+#endif /* CONFIG_DRIVER_ROBOSWITCH */
+#ifdef CONFIG_DRIVER_ATHEROS
+/* driver_atheros.c */
+extern const struct wpa_driver_ops wpa_driver_atheros_ops;
+#endif /* CONFIG_DRIVER_ATHEROS */
+#ifdef CONFIG_DRIVER_NONE
+extern const struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
+#endif /* CONFIG_DRIVER_NONE */
+
#endif /* DRIVER_H */
diff --git a/freebsd/contrib/wpa/src/drivers/driver_bsd.c b/freebsd/contrib/wpa/src/drivers/driver_bsd.c
index 5f6e129d..c1679806 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_bsd.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_bsd.c
@@ -49,14 +49,25 @@
#include "l2_packet/l2_packet.h"
+struct bsd_driver_global {
+ void *ctx;
+ int sock; /* socket for 802.11 ioctls */
+ int route; /* routing socket for events */
+ char *event_buf;
+ size_t event_buf_len;
+ struct dl_list ifaces; /* list of interfaces */
+};
+
struct bsd_driver_data {
+ struct dl_list list;
+ struct bsd_driver_global *global;
struct hostapd_data *hapd; /* back pointer */
- int sock; /* open socket for 802.11 ioctls */
struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
- int route; /* routing socket for events */
char ifname[IFNAMSIZ+1]; /* interface name */
+ int flags;
unsigned int ifindex; /* interface index */
+ int if_removed; /* has the interface been removed? */
void *ctx;
struct wpa_driver_capa capa; /* driver capability */
int is_ap; /* Access point mode */
@@ -64,17 +75,46 @@ struct bsd_driver_data {
int prev_privacy; /* privacy state to restore on deinit */
int prev_wpa; /* wpa state to restore on deinit */
enum ieee80211_opmode opmode; /* operation mode */
- char *event_buf;
- size_t event_buf_len;
};
/* Generic functions for hostapd and wpa_supplicant */
+static struct bsd_driver_data *
+bsd_get_drvindex(void *priv, unsigned int ifindex)
+{
+ struct bsd_driver_global *global = priv;
+ struct bsd_driver_data *drv;
+
+ dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
+ if (drv->ifindex == ifindex)
+ return drv;
+ }
+ return NULL;
+}
+
+#ifndef HOSTAPD
+static struct bsd_driver_data *
+bsd_get_drvname(void *priv, const char *ifname)
+{
+ struct bsd_driver_global *global = priv;
+ struct bsd_driver_data *drv;
+
+ dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
+ if (os_strcmp(drv->ifname, ifname) == 0)
+ return drv;
+ }
+ return NULL;
+}
+#endif /* HOSTAPD */
+
static int
bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req ireq;
+ if (drv->ifindex == 0 || drv->if_removed)
+ return -1;
+
os_memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
ireq.i_type = op;
@@ -82,7 +122,7 @@ bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
ireq.i_data = (void *) arg;
ireq.i_len = arg_len;
- if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
+ if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) {
wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
"arg_len=%u]: %s", op, val, arg_len,
strerror(errno));
@@ -103,7 +143,7 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
ireq->i_len = arg_len;
ireq->i_data = arg;
- if (ioctl(drv->sock, SIOCG80211, ireq) < 0) {
+ if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) {
wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, "
"arg_len=%u]: %s", op, arg_len, strerror(errno));
return -1;
@@ -144,7 +184,7 @@ bsd_get_ssid(void *priv, u8 *ssid, int len)
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&nwid;
- if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
+ if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 ||
nwid.i_len > IEEE80211_NWID_LEN)
return -1;
os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
@@ -167,7 +207,7 @@ bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len)
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&nwid;
- return ioctl(drv->sock, SIOCS80211NWID, &ifr);
+ return ioctl(drv->global->sock, SIOCS80211NWID, &ifr);
#else
return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
#endif
@@ -182,7 +222,7 @@ bsd_get_if_media(void *priv)
os_memset(&ifmr, 0, sizeof(ifmr));
os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
- if (ioctl(drv->sock, SIOCGIFMEDIA, &ifmr) < 0) {
+ if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) {
wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__,
strerror(errno));
return -1;
@@ -201,7 +241,7 @@ bsd_set_if_media(void *priv, int media)
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_media = media;
- if (ioctl(drv->sock, SIOCSIFMEDIA, &ifr) < 0) {
+ if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) {
wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__,
strerror(errno));
return -1;
@@ -264,11 +304,12 @@ bsd_ctrl_iface(void *priv, int enable)
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
- if (ioctl(drv->sock, SIOCGIFFLAGS, &ifr) < 0) {
+ if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) {
wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
strerror(errno));
return -1;
}
+ drv->flags = ifr.ifr_flags;
if (enable) {
if (ifr.ifr_flags & IFF_UP)
@@ -280,12 +321,13 @@ bsd_ctrl_iface(void *priv, int enable)
ifr.ifr_flags &= ~IFF_UP;
}
- if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) {
+ if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) {
wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
strerror(errno));
return -1;
}
+ drv->flags = ifr.ifr_flags;
return 0;
}
@@ -577,7 +619,7 @@ bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
os_memset(&creq, 0, sizeof(creq));
os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
creq.i_channel = (u_int16_t)channel;
- return ioctl(drv->sock, SIOCS80211CHANNEL, &creq);
+ return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq);
#else /* SIOCS80211CHANNEL */
return set80211param(priv, IEEE80211_IOC_CHANNEL, channel);
#endif /* SIOCS80211CHANNEL */
@@ -731,7 +773,8 @@ bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
static void
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
{
- struct bsd_driver_data *drv = ctx;
+ struct bsd_driver_global *global = sock_ctx;
+ struct bsd_driver_data *drv;
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
@@ -740,7 +783,7 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
int n;
union wpa_event_data data;
- n = read(sock, drv->event_buf, drv->event_buf_len);
+ n = read(sock, global->event_buf, global->event_buf_len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s",
@@ -748,15 +791,18 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
return;
}
- rtm = (struct rt_msghdr *) drv->event_buf;
+ rtm = (struct rt_msghdr *) global->event_buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version);
return;
}
- ifan = (struct if_announcemsghdr *) rtm;
switch (rtm->rtm_type) {
case RTM_IEEE80211:
+ ifan = (struct if_announcemsghdr *) rtm;
+ drv = bsd_get_drvindex(global, ifan->ifan_index);
+ if (drv == NULL)
+ return;
switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC:
@@ -812,21 +858,15 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
return NULL;
}
- drv->event_buf_len = rtbuf_len();
-
- drv->event_buf = os_malloc(drv->event_buf_len);
- if (drv->event_buf == NULL) {
- wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
+ drv->ifindex = if_nametoindex(params->ifname);
+ if (drv->ifindex == 0) {
+ wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
+ __func__, params->ifname);
goto bad;
}
drv->hapd = hapd;
- drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
- if (drv->sock < 0) {
- wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
- strerror(errno));
- goto bad;
- }
+ drv->global = params->global_priv;
os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL,
@@ -840,28 +880,18 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
if (bsd_ctrl_iface(drv, 0) < 0)
goto bad;
- drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
- if (drv->route < 0) {
- wpa_printf(MSG_ERROR, "socket(PF_ROUTE,SOCK_RAW): %s",
- strerror(errno));
- goto bad;
- }
- eloop_register_read_sock(drv->route, bsd_wireless_event_receive, drv,
- NULL);
-
if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
__func__);
goto bad;
}
+ dl_list_add(&drv->global->ifaces, &drv->list);
+
return drv;
bad:
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
- if (drv->sock >= 0)
- close(drv->sock);
- os_free(drv->event_buf);
os_free(drv);
return NULL;
}
@@ -872,16 +902,10 @@ bsd_deinit(void *priv)
{
struct bsd_driver_data *drv = priv;
- if (drv->route >= 0) {
- eloop_unregister_read_sock(drv->route);
- close(drv->route);
- }
- bsd_ctrl_iface(drv, 0);
- if (drv->sock >= 0)
- close(drv->sock);
+ if (drv->ifindex != 0)
+ bsd_ctrl_iface(drv, 0);
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
- os_free(drv->event_buf);
os_free(drv);
}
@@ -933,7 +957,7 @@ wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
struct ieee80211_bssid bs;
os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
- if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
+ if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0)
return -1;
os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
return 0;
@@ -967,7 +991,7 @@ wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
int ret = 0;
wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
- __FUNCTION__, wpa, privacy);
+ __func__, wpa, privacy);
if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0)
ret = -1;
@@ -982,7 +1006,7 @@ wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
static int
wpa_driver_bsd_set_wpa(void *priv, int enabled)
{
- wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
+ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
}
@@ -1201,7 +1225,8 @@ wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
- struct bsd_driver_data *drv = sock_ctx;
+ struct bsd_driver_global *global = sock_ctx;
+ struct bsd_driver_data *drv;
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm;
@@ -1211,7 +1236,12 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
struct ieee80211_join_event *join;
int n;
- n = read(sock, drv->event_buf, drv->event_buf_len);
+ /*
+ * CID 1394785: Memory - illegal access (STRING_NULL):
+ * Though global->event_buf is a char *, it actually contains
+ * a struct rt_msghdr *. See below.
+ */
+ n = read(sock, global->event_buf, global->event_buf_len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s",
@@ -1219,7 +1249,11 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
return;
}
- rtm = (struct rt_msghdr *) drv->event_buf;
+ /*
+ * CID 1394785: global->event_buf is assigned here to a
+ * struct rt_msghdr *.
+ */
+ rtm = (struct rt_msghdr *) global->event_buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version);
@@ -1229,53 +1263,79 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
switch (rtm->rtm_type) {
case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *) rtm;
- if (ifan->ifan_index != drv->ifindex)
- break;
- os_strlcpy(event.interface_status.ifname, drv->ifname,
- sizeof(event.interface_status.ifname));
switch (ifan->ifan_what) {
case IFAN_DEPARTURE:
+ drv = bsd_get_drvindex(global, ifan->ifan_index);
+ if (drv)
+ drv->if_removed = 1;
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+ break;
+ case IFAN_ARRIVAL:
+ drv = bsd_get_drvname(global, ifan->ifan_name);
+ if (drv) {
+ drv->ifindex = ifan->ifan_index;
+ drv->if_removed = 0;
+ }
+ event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+ break;
default:
+ wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
return;
}
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
- event.interface_status.ifname,
+ ifan->ifan_name,
ifan->ifan_what == IFAN_DEPARTURE ?
"removed" : "added");
- wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+ os_strlcpy(event.interface_status.ifname, ifan->ifan_name,
+ sizeof(event.interface_status.ifname));
+ if (drv) {
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
+ &event);
+ /*
+ * Set ifindex to zero after sending the event as the
+ * event might query the driver to ensure a match.
+ */
+ if (ifan->ifan_what == IFAN_DEPARTURE)
+ drv->ifindex = 0;
+ } else {
+ wpa_supplicant_event_global(global->ctx,
+ EVENT_INTERFACE_STATUS,
+ &event);
+ }
break;
case RTM_IEEE80211:
ifan = (struct if_announcemsghdr *) rtm;
- if (ifan->ifan_index != drv->ifindex)
- break;
+ drv = bsd_get_drvindex(global, ifan->ifan_index);
+ if (drv == NULL)
+ return;
switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC:
if (drv->is_ap)
break;
- wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
break;
case RTM_IEEE80211_DISASSOC:
if (drv->is_ap)
break;
- wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
+ wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
break;
case RTM_IEEE80211_SCAN:
if (drv->is_ap)
break;
- wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
+ wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
+ NULL);
break;
case RTM_IEEE80211_LEAVE:
leave = (struct ieee80211_leave_event *) &ifan[1];
- drv_event_disassoc(ctx, leave->iev_addr);
+ drv_event_disassoc(drv->ctx, leave->iev_addr);
break;
case RTM_IEEE80211_JOIN:
#ifdef RTM_IEEE80211_REJOIN
case RTM_IEEE80211_REJOIN:
#endif
join = (struct ieee80211_join_event *) &ifan[1];
- bsd_new_sta(drv, ctx, join->iev_addr);
+ bsd_new_sta(drv, drv->ctx, join->iev_addr);
break;
case RTM_IEEE80211_REPLAY:
/* ignore */
@@ -1290,23 +1350,30 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
os_memset(&event, 0, sizeof(event));
event.michael_mic_failure.unicast =
!IEEE80211_IS_MULTICAST(mic->iev_dst);
- wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
- &event);
+ wpa_supplicant_event(drv->ctx,
+ EVENT_MICHAEL_MIC_FAILURE, &event);
break;
}
break;
case RTM_IFINFO:
ifm = (struct if_msghdr *) rtm;
- if (ifm->ifm_index != drv->ifindex)
- break;
- if ((rtm->rtm_flags & RTF_UP) == 0) {
- os_strlcpy(event.interface_status.ifname, drv->ifname,
- sizeof(event.interface_status.ifname));
- event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+ drv = bsd_get_drvindex(global, ifm->ifm_index);
+ if (drv == NULL)
+ return;
+ if ((ifm->ifm_flags & IFF_UP) == 0 &&
+ (drv->flags & IFF_UP) != 0) {
wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
- event.interface_status.ifname);
- wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+ drv->ifname);
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
+ NULL);
+ } else if ((ifm->ifm_flags & IFF_UP) != 0 &&
+ (drv->flags & IFF_UP) == 0) {
+ wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
+ drv->ifname);
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
+ NULL);
}
+ drv->flags = ifm->ifm_flags;
break;
}
}
@@ -1333,11 +1400,16 @@ wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
result->caps = sr->isr_capinfo;
result->qual = sr->isr_rssi;
result->noise = sr->isr_noise;
+
+#ifdef __FreeBSD__
/*
* the rssi value reported by the kernel is in 0.5dB steps relative to
* the reported noise floor. see ieee80211_node.h for details.
*/
result->level = sr->isr_rssi / 2 + sr->isr_noise;
+#else
+ result->level = sr->isr_rssi;
+#endif
pos = (u8 *)(result + 1);
@@ -1504,7 +1576,7 @@ get80211opmode(struct bsd_driver_data *drv)
(void) memset(&ifmr, 0, sizeof(ifmr));
(void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
- if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
+ if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
if (ifmr.ifm_current & IFM_FLAG0)
return IEEE80211_M_AHDEMO;
@@ -1526,7 +1598,7 @@ get80211opmode(struct bsd_driver_data *drv)
}
static void *
-wpa_driver_bsd_init(void *ctx, const char *ifname)
+wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
{
#define GETPARAM(drv, param, v) \
(((v) = get80211param(drv, param)) != -1)
@@ -1536,14 +1608,6 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (drv == NULL)
return NULL;
- drv->event_buf_len = rtbuf_len();
-
- drv->event_buf = os_malloc(drv->event_buf_len);
- if (drv->event_buf == NULL) {
- wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
- goto fail1;
- }
-
/*
* NB: We require the interface name be mappable to an index.
* This implies we do not support having wpa_supplicant
@@ -1554,24 +1618,12 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (drv->ifindex == 0) {
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
__func__, ifname);
- goto fail1;
- }
- drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
- if (drv->sock < 0)
- goto fail1;
-
- os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
- /* Down interface during setup. */
- if (bsd_ctrl_iface(drv, 0) < 0)
goto fail;
-
- drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
- if (drv->route < 0)
- goto fail;
- eloop_register_read_sock(drv->route,
- wpa_driver_bsd_event_receive, ctx, drv);
+ }
drv->ctx = ctx;
+ drv->global = priv;
+ os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
@@ -1592,13 +1644,15 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (wpa_driver_bsd_capa(drv))
goto fail;
+ /* Down interface during setup. */
+ if (bsd_ctrl_iface(drv, 0) < 0)
+ goto fail;
+
drv->opmode = get80211opmode(drv);
+ dl_list_add(&drv->global->ifaces, &drv->list);
return drv;
fail:
- close(drv->sock);
-fail1:
- os_free(drv->event_buf);
os_free(drv);
return NULL;
#undef GETPARAM
@@ -1609,22 +1663,25 @@ wpa_driver_bsd_deinit(void *priv)
{
struct bsd_driver_data *drv = priv;
- wpa_driver_bsd_set_wpa(drv, 0);
- eloop_unregister_read_sock(drv->route);
+ if (drv->ifindex != 0 && !drv->if_removed) {
+ wpa_driver_bsd_set_wpa(drv, 0);
- /* NB: mark interface down */
- bsd_ctrl_iface(drv, 0);
+ /* NB: mark interface down */
+ bsd_ctrl_iface(drv, 0);
- wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
- if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
- wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
- __func__);
+ wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa,
+ drv->prev_privacy);
+
+ if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)
+ < 0)
+ wpa_printf(MSG_DEBUG,
+ "%s: failed to restore roaming state",
+ __func__);
+ }
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
- (void) close(drv->route); /* ioctl socket */
- (void) close(drv->sock); /* event socket */
- os_free(drv->event_buf);
+ dl_list_del(&drv->list);
os_free(drv);
}
@@ -1638,10 +1695,74 @@ wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
}
#endif /* HOSTAPD */
+static void *
+bsd_global_init(void *ctx)
+{
+ struct bsd_driver_global *global;
+
+ global = os_zalloc(sizeof(*global));
+ if (global == NULL)
+ return NULL;
+
+ global->ctx = ctx;
+ dl_list_init(&global->ifaces);
+
+ global->sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (global->sock < 0) {
+ wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
+ strerror(errno));
+ goto fail1;
+ }
+
+ global->route = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (global->route < 0) {
+ wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ global->event_buf_len = rtbuf_len();
+ global->event_buf = os_malloc(global->event_buf_len);
+ if (global->event_buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
+ goto fail;
+ }
+
+#ifdef HOSTAPD
+ eloop_register_read_sock(global->route, bsd_wireless_event_receive,
+ NULL, global);
+
+#else /* HOSTAPD */
+ eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive,
+ NULL, global);
+#endif /* HOSTAPD */
+
+ return global;
+
+fail:
+ close(global->sock);
+fail1:
+ os_free(global);
+ return NULL;
+}
+
+static void
+bsd_global_deinit(void *priv)
+{
+ struct bsd_driver_global *global = priv;
+
+ eloop_unregister_read_sock(global->route);
+ (void) close(global->route);
+ (void) close(global->sock);
+ os_free(global);
+}
+
const struct wpa_driver_ops wpa_driver_bsd_ops = {
.name = "bsd",
.desc = "BSD 802.11 support",
+ .global_init = bsd_global_init,
+ .global_deinit = bsd_global_deinit,
#ifdef HOSTAPD
.hapd_init = bsd_init,
.hapd_deinit = bsd_deinit,
@@ -1654,7 +1775,7 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.sta_set_flags = bsd_set_sta_authorized,
.commit = bsd_commit,
#else /* HOSTAPD */
- .init = wpa_driver_bsd_init,
+ .init2 = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,
.get_bssid = wpa_driver_bsd_get_bssid,
.get_ssid = wpa_driver_bsd_get_ssid,
diff --git a/freebsd/contrib/wpa/src/drivers/driver_common.c b/freebsd/contrib/wpa/src/drivers/driver_common.c
index 28f483e9..139829e4 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_common.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_common.c
@@ -82,6 +82,7 @@ const char * event_to_string(enum wpa_event_type event)
E2S(NEW_PEER_CANDIDATE);
E2S(ACS_CHANNEL_SELECTED);
E2S(DFS_CAC_STARTED);
+ E2S(P2P_LO_STOP);
}
return "UNKNOWN";
@@ -185,12 +186,12 @@ wpa_get_wowlan_triggers(const char *wowlan_triggers,
start = buf;
while (*start != '\0') {
- while (isblank(*start))
+ while (isblank((unsigned char) *start))
start++;
if (*start == '\0')
break;
end = start;
- while (!isblank(*end) && *end != '\0')
+ while (!isblank((unsigned char) *end) && *end != '\0')
end++;
last = *end == '\0';
*end = '\0';
@@ -220,3 +221,55 @@ out:
os_free(buf);
return triggers;
}
+
+
+const char * driver_flag_to_string(u64 flag)
+{
+#define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
+ switch (flag) {
+ DF2S(DRIVER_IE);
+ DF2S(SET_KEYS_AFTER_ASSOC);
+ DF2S(DFS_OFFLOAD);
+ DF2S(4WAY_HANDSHAKE);
+ DF2S(WIRED);
+ DF2S(SME);
+ DF2S(AP);
+ DF2S(SET_KEYS_AFTER_ASSOC_DONE);
+ DF2S(HT_2040_COEX);
+ DF2S(P2P_CONCURRENT);
+ DF2S(P2P_DEDICATED_INTERFACE);
+ DF2S(P2P_CAPABLE);
+ DF2S(AP_TEARDOWN_SUPPORT);
+ DF2S(P2P_MGMT_AND_NON_P2P);
+ DF2S(SANE_ERROR_CODES);
+ DF2S(OFFCHANNEL_TX);
+ DF2S(EAPOL_TX_STATUS);
+ DF2S(DEAUTH_TX_STATUS);
+ DF2S(BSS_SELECTION);
+ DF2S(TDLS_SUPPORT);
+ DF2S(TDLS_EXTERNAL_SETUP);
+ DF2S(PROBE_RESP_OFFLOAD);
+ DF2S(AP_UAPSD);
+ DF2S(INACTIVITY_TIMER);
+ DF2S(AP_MLME);
+ DF2S(SAE);
+ DF2S(OBSS_SCAN);
+ DF2S(IBSS);
+ DF2S(RADAR);
+ DF2S(DEDICATED_P2P_DEVICE);
+ DF2S(QOS_MAPPING);
+ DF2S(AP_CSA);
+ DF2S(MESH);
+ DF2S(ACS_OFFLOAD);
+ DF2S(KEY_MGMT_OFFLOAD);
+ DF2S(TDLS_CHANNEL_SWITCH);
+ DF2S(HT_IBSS);
+ DF2S(VHT_IBSS);
+ DF2S(SUPPORT_HW_MODE_ANY);
+ DF2S(OFFCHANNEL_SIMULTANEOUS);
+ DF2S(FULL_AP_CLIENT_STATE);
+ DF2S(P2P_LISTEN_OFFLOAD);
+ }
+ return "UNKNOWN";
+#undef DF2S
+}
diff --git a/freebsd/contrib/wpa/src/drivers/driver_ndis.c b/freebsd/contrib/wpa/src/drivers/driver_ndis.c
index 6b3b26bc..98aa48ba 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_ndis.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_ndis.c
@@ -37,6 +37,7 @@ int close(int fd);
#include "driver.h"
#include "eloop.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "driver_ndis.h"
int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
@@ -783,20 +784,7 @@ static int wpa_driver_ndis_scan(void *priv,
static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
{
- const u8 *end, *pos;
-
- pos = (const u8 *) (res + 1);
- end = pos + res->ie_len;
-
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
- break;
- if (pos[0] == ie)
- return pos;
- pos += 2 + pos[1];
- }
-
- return NULL;
+ return get_ie((const u8 *) (res + 1), res->ie_len, ie);
}
diff --git a/freebsd/contrib/wpa/src/drivers/driver_nl80211.h b/freebsd/contrib/wpa/src/drivers/driver_nl80211.h
index 5c21e0fa..d0ec48c9 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_nl80211.h
+++ b/freebsd/contrib/wpa/src/drivers/driver_nl80211.h
@@ -25,6 +25,7 @@
#endif /* CONFIG_LIBNL20 */
struct nl80211_global {
+ void *ctx;
struct dl_list interfaces;
int if_add_ifindex;
u64 if_add_wdevid;
@@ -84,6 +85,7 @@ struct wpa_driver_nl80211_data {
struct dl_list list;
struct dl_list wiphy_list;
char phyname[32];
+ unsigned int wiphy_idx;
u8 perm_addr[ETH_ALEN];
void *ctx;
int ifindex;
@@ -94,6 +96,13 @@ struct wpa_driver_nl80211_data {
struct wpa_driver_capa capa;
u8 *extended_capa, *extended_capa_mask;
unsigned int extended_capa_len;
+ struct drv_nl80211_ext_capa {
+ enum nl80211_iftype iftype;
+ u8 *ext_capa, *ext_capa_mask;
+ unsigned int ext_capa_len;
+ } iface_ext_capa[NL80211_IFTYPE_MAX];
+ unsigned int num_iface_ext_capa;
+
int has_capability;
int operstate;
@@ -148,9 +157,16 @@ struct wpa_driver_nl80211_data {
unsigned int setband_vendor_cmd_avail:1;
unsigned int get_pref_freq_list:1;
unsigned int set_prob_oper_freq:1;
+ unsigned int scan_vendor_cmd_avail:1;
+ unsigned int connect_reassoc:1;
+ unsigned int set_wifi_conf_vendor_cmd_avail:1;
+ u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
+#define MAX_SEND_ACTION_COOKIES 20
+ u64 send_action_cookies[MAX_SEND_ACTION_COOKIES];
+ unsigned int num_send_action_cookies;
unsigned int last_mgmt_freq;
@@ -166,7 +182,10 @@ struct wpa_driver_nl80211_data {
struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
int default_if_indices[16];
+ /* the AP/AP_VLAN iface that is in this bridge */
+ int default_if_indices_reason[16];
int *if_indices;
+ int *if_indices_reason;
int num_if_indices;
/* From failed authentication command */
@@ -182,6 +201,13 @@ struct wpa_driver_nl80211_data {
int auth_wep_tx_keyidx;
int auth_local_state_change;
int auth_p2p;
+
+ /*
+ * Tells whether the last scan issued from wpa_supplicant was a normal
+ * scan (NL80211_CMD_TRIGGER_SCAN) or a vendor scan
+ * (NL80211_CMD_VENDOR). 0 if no pending scan request.
+ */
+ int last_scan_cmd;
};
struct nl_msg;
@@ -233,6 +259,8 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags);
int process_global_event(struct nl_msg *msg, void *arg);
int process_bss_event(struct nl_msg *msg, void *arg);
+const char * nl80211_iftype_str(enum nl80211_iftype mode);
+
#ifdef ANDROID
int android_nl_socket_set_nonblocking(struct nl_handle *handle);
int android_pno_start(struct i802_bss *bss,
@@ -267,11 +295,13 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx);
int wpa_driver_nl80211_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params);
int wpa_driver_nl80211_sched_scan(void *priv,
- struct wpa_driver_scan_params *params,
- u32 interval);
+ struct wpa_driver_scan_params *params);
int wpa_driver_nl80211_stop_sched_scan(void *priv);
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
-const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie);
+int wpa_driver_nl80211_abort_scan(void *priv);
+int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
+ struct wpa_driver_scan_params *params);
+int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
#endif /* DRIVER_NL80211_H */
diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired.c b/freebsd/contrib/wpa/src/drivers/driver_wired.c
index b30d47cf..372bf791 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_wired.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_wired.c
@@ -10,12 +10,17 @@
*/
#include "includes.h"
+
+#include "common.h"
+#include "eloop.h"
+#include "driver.h"
+
#include <sys/ioctl.h>
+#undef IFNAMSIZ
#include <net/if.h>
#ifdef __linux__
#include <netpacket/packet.h>
#include <net/if_arp.h>
-#include <net/if.h>
#endif /* __linux__ */
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
#include <net/if_dl.h>
@@ -25,10 +30,6 @@
#include <sys/sockio.h>
#endif /* __sun__ */
-#include "common.h"
-#include "eloop.h"
-#include "driver.h"
-
#ifdef _MSC_VER
#pragma pack(push, 1)
#endif /* _MSC_VER */
@@ -472,6 +473,7 @@ static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
return 0;
}
+
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
static int wpa_driver_wired_get_ifstatus(const char *ifname, int *status)
{
@@ -559,7 +561,7 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
static void * wpa_driver_wired_init(void *ctx, const char *ifname)
{
struct wpa_driver_wired_data *drv;
- int flags, status;
+ int flags;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
diff --git a/freebsd/contrib/wpa/src/drivers/drivers.c b/freebsd/contrib/wpa/src/drivers/drivers.c
index 5a0b58c2..ac83600e 100644
--- a/freebsd/contrib/wpa/src/drivers/drivers.c
+++ b/freebsd/contrib/wpa/src/drivers/drivers.c
@@ -12,42 +12,6 @@
#include "utils/common.h"
#include "driver.h"
-#ifdef CONFIG_DRIVER_WEXT
-extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
-#endif /* CONFIG_DRIVER_WEXT */
-#ifdef CONFIG_DRIVER_NL80211
-extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
-#endif /* CONFIG_DRIVER_NL80211 */
-#ifdef CONFIG_DRIVER_HOSTAP
-extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
-#endif /* CONFIG_DRIVER_HOSTAP */
-#ifdef CONFIG_DRIVER_BSD
-extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
-#endif /* CONFIG_DRIVER_BSD */
-#ifdef CONFIG_DRIVER_OPENBSD
-extern struct wpa_driver_ops wpa_driver_openbsd_ops; /* driver_openbsd.c */
-#endif /* CONFIG_DRIVER_OPENBSD */
-#ifdef CONFIG_DRIVER_NDIS
-extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */
-#endif /* CONFIG_DRIVER_NDIS */
-#ifdef CONFIG_DRIVER_WIRED
-extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
-#endif /* CONFIG_DRIVER_WIRED */
-#ifdef CONFIG_DRIVER_MACSEC_QCA
- /* driver_macsec_qca.c */
-extern struct wpa_driver_ops wpa_driver_macsec_qca_ops;
-#endif /* CONFIG_DRIVER_MACSEC_QCA */
-#ifdef CONFIG_DRIVER_ROBOSWITCH
-/* driver_roboswitch.c */
-extern struct wpa_driver_ops wpa_driver_roboswitch_ops;
-#endif /* CONFIG_DRIVER_ROBOSWITCH */
-#ifdef CONFIG_DRIVER_ATHEROS
-extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
-#endif /* CONFIG_DRIVER_ATHEROS */
-#ifdef CONFIG_DRIVER_NONE
-extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
-#endif /* CONFIG_DRIVER_NONE */
-
const struct wpa_driver_ops *const wpa_drivers[] =
{
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap.c b/freebsd/contrib/wpa/src/eap_peer/eap.c
index cfaf201a..6a183071 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap.c
@@ -50,6 +50,8 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
static const char * eap_sm_method_state_txt(EapMethodState state);
static const char * eap_sm_decision_txt(EapDecision decision);
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
+ const char *msg, size_t msglen);
@@ -190,6 +192,14 @@ SM_STATE(EAP, INITIALIZE)
*/
eapol_set_bool(sm, EAPOL_eapResp, FALSE);
eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
+ /*
+ * RFC 4137 does not reset ignore here, but since it is possible for
+ * some method code paths to end up not setting ignore=FALSE, clear the
+ * value here to avoid issues if a previous authentication attempt
+ * failed with ignore=TRUE being left behind in the last
+ * m.check(eapReqData) operation.
+ */
+ sm->ignore = 0;
sm->num_rounds = 0;
sm->prev_failure = 0;
sm->expected_failure = 0;
@@ -314,11 +324,14 @@ SM_STATE(EAP, GET_METHOD)
wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
"vendor %u method %u (%s)",
sm->reqVendor, method, sm->m->name);
- if (reinit)
+ if (reinit) {
sm->eap_method_priv = sm->m->init_for_reauth(
sm, sm->eap_method_priv);
- else
+ } else {
+ sm->waiting_ext_cert_check = 0;
+ sm->ext_cert_check = 0;
sm->eap_method_priv = sm->m->init(sm);
+ }
if (sm->eap_method_priv == NULL) {
struct eap_peer_config *config = eap_get_config(sm);
@@ -1375,13 +1388,10 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
return 0;
}
-#endif /* PCSC_FUNCS */
-
static int eap_sm_set_scard_pin(struct eap_sm *sm,
struct eap_peer_config *conf)
{
-#ifdef PCSC_FUNCS
if (scard_set_pin(sm->scard_ctx, conf->pin)) {
/*
* Make sure the same PIN is not tried again in order to avoid
@@ -1395,24 +1405,20 @@ static int eap_sm_set_scard_pin(struct eap_sm *sm,
return -1;
}
return 0;
-#else /* PCSC_FUNCS */
- return -1;
-#endif /* PCSC_FUNCS */
}
+
static int eap_sm_get_scard_identity(struct eap_sm *sm,
struct eap_peer_config *conf)
{
-#ifdef PCSC_FUNCS
if (eap_sm_set_scard_pin(sm, conf))
return -1;
return eap_sm_imsi_identity(sm, conf);
-#else /* PCSC_FUNCS */
- return -1;
-#endif /* PCSC_FUNCS */
}
+#endif /* PCSC_FUNCS */
+
/**
* eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
@@ -1455,23 +1461,27 @@ struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
identity, identity_len);
}
- if (identity == NULL) {
- wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
- "configuration was not available");
- if (config->pcsc) {
+ if (config->pcsc) {
+#ifdef PCSC_FUNCS
+ if (!identity) {
if (eap_sm_get_scard_identity(sm, config) < 0)
return NULL;
identity = config->identity;
identity_len = config->identity_len;
- wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
- "IMSI", identity, identity_len);
- } else {
- eap_sm_request_identity(sm);
+ wpa_hexdump_ascii(MSG_DEBUG,
+ "permanent identity from IMSI",
+ identity, identity_len);
+ } else if (eap_sm_set_scard_pin(sm, config) < 0) {
return NULL;
}
- } else if (config->pcsc) {
- if (eap_sm_set_scard_pin(sm, config) < 0)
- return NULL;
+#else /* PCSC_FUNCS */
+ return NULL;
+#endif /* PCSC_FUNCS */
+ } else if (!identity) {
+ wpa_printf(MSG_WARNING,
+ "EAP: buildIdentity: identity configuration was not available");
+ eap_sm_request_identity(sm);
+ return NULL;
}
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
@@ -1512,15 +1522,9 @@ static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
static struct wpabuf * eap_sm_buildNotify(int id)
{
- struct wpabuf *resp;
-
wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
- resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
- EAP_CODE_RESPONSE, id);
- if (resp == NULL)
- return NULL;
-
- return resp;
+ return eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
+ EAP_CODE_RESPONSE, id);
}
@@ -1852,6 +1856,11 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
case TLS_CERT_CHAIN_SUCCESS:
eap_notify_status(sm, "remote certificate verification",
"success");
+ if (sm->ext_cert_check) {
+ sm->waiting_ext_cert_check = 1;
+ eap_sm_request(sm, WPA_CTRL_REQ_EXT_CERT_CHECK,
+ NULL, 0);
+ }
break;
case TLS_CERT_CHAIN_FAILURE:
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
@@ -2174,10 +2183,10 @@ int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
#endif /* CONFIG_CTRL_IFACE */
-#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
const char *msg, size_t msglen)
{
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
struct eap_peer_config *config;
const char *txt = NULL;
char *tmp;
@@ -2226,16 +2235,17 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
case WPA_CTRL_REQ_SIM:
txt = msg;
break;
+ case WPA_CTRL_REQ_EXT_CERT_CHECK:
+ break;
default:
return;
}
if (sm->eapol_cb->eap_param_needed)
sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
-}
-#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
-#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+}
+
const char * eap_sm_get_method_name(struct eap_sm *sm)
{
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_config.h b/freebsd/contrib/wpa/src/eap_peer/eap_config.h
index 2b1a1d5e..f9800726 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_config.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_config.h
@@ -181,13 +181,13 @@ struct eap_peer_config {
* subject_match - Constraint for server certificate subject
*
* This substring is matched against the subject of the authentication
- * server certificate. If this string is set, the server sertificate is
+ * server certificate. If this string is set, the server certificate is
* only accepted if it contains this string in the subject. The subject
* string is in following format:
*
* /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@n.example.com
*
- * Note: Since this is a substring match, this cannot be used securily
+ * Note: Since this is a substring match, this cannot be used securely
* to do a suffix match against a possible domain name in the CN entry.
* For such a use case, domain_suffix_match should be used instead.
*/
@@ -198,7 +198,7 @@ struct eap_peer_config {
*
* Semicolon separated string of entries to be matched against the
* alternative subject name of the authentication server certificate.
- * If this string is set, the server sertificate is only accepted if it
+ * If this string is set, the server certificate is only accepted if it
* contains one of the entries in an alternative subject name
* extension.
*
@@ -739,6 +739,20 @@ struct eap_peer_config {
* erp - Whether EAP Re-authentication Protocol (ERP) is enabled
*/
int erp;
+
+ /**
+ * pending_ext_cert_check - External server certificate check status
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request external
+ * validation of server certificate chain.
+ */
+ enum {
+ NO_CHECK = 0,
+ PENDING_CHECK,
+ EXT_CERT_CHECK_GOOD,
+ EXT_CERT_CHECK_BAD,
+ } pending_ext_cert_check;
};
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c b/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c
index 2ffc142c..cacf3d41 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c
@@ -129,7 +129,6 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv,
int eap_peer_gtc_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
@@ -140,8 +139,5 @@ int eap_peer_gtc_register(void)
eap->deinit = eap_gtc_deinit;
eap->process = eap_gtc_process;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_i.h b/freebsd/contrib/wpa/src/eap_peer/eap_i.h
index 99b44dae..6ab24834 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_i.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_i.h
@@ -366,6 +366,8 @@ struct eap_sm {
int external_sim;
unsigned int expected_failure:1;
+ unsigned int ext_cert_check:1;
+ unsigned int waiting_ext_cert_check:1;
struct dl_list erp_keys; /* struct eap_erp_key */
};
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c
index e765af14..af63bf88 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c
@@ -395,7 +395,6 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_leap_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP");
@@ -408,8 +407,5 @@ int eap_peer_leap_register(void)
eap->isKeyAvailable = eap_leap_isKeyAvailable;
eap->getKey = eap_leap_getKey;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_md5.c b/freebsd/contrib/wpa/src/eap_peer/eap_md5.c
index 145bfa8f..2cc66e6d 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_md5.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_md5.c
@@ -104,7 +104,6 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
int eap_peer_md5_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
@@ -115,8 +114,5 @@ int eap_peer_md5_register(void)
eap->deinit = eap_md5_deinit;
eap->process = eap_md5_process;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_methods.c b/freebsd/contrib/wpa/src/eap_peer/eap_methods.c
index 44b4af92..23004eac 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_methods.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_methods.c
@@ -23,6 +23,8 @@
static struct eap_method *eap_methods = NULL;
+static void eap_peer_method_free(struct eap_method *method);
+
/**
* eap_peer_get_eap_method - Get EAP method based on type number
@@ -300,7 +302,7 @@ struct eap_method * eap_peer_method_alloc(int version, int vendor,
* eap_peer_method_free - Free EAP peer method structure
* @method: Method structure allocated with eap_peer_method_alloc()
*/
-void eap_peer_method_free(struct eap_method *method)
+static void eap_peer_method_free(struct eap_method *method)
{
os_free(method);
}
@@ -308,26 +310,31 @@ void eap_peer_method_free(struct eap_method *method)
/**
* eap_peer_method_register - Register an EAP peer method
- * @method: EAP method to register
+ * @method: EAP method to register from eap_peer_method_alloc()
* Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
* has already been registered
*
* Each EAP peer method needs to call this function to register itself as a
- * supported EAP method.
+ * supported EAP method. The caller must not free the allocated method data
+ * regardless of the return value.
*/
int eap_peer_method_register(struct eap_method *method)
{
struct eap_method *m, *last = NULL;
if (method == NULL || method->name == NULL ||
- method->version != EAP_PEER_METHOD_INTERFACE_VERSION)
+ method->version != EAP_PEER_METHOD_INTERFACE_VERSION) {
+ eap_peer_method_free(method);
return -1;
+ }
for (m = eap_methods; m; m = m->next) {
if ((m->vendor == method->vendor &&
m->method == method->method) ||
- os_strcmp(m->name, method->name) == 0)
+ os_strcmp(m->name, method->name) == 0) {
+ eap_peer_method_free(method);
return -2;
+ }
last = m;
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_methods.h b/freebsd/contrib/wpa/src/eap_peer/eap_methods.h
index e35c919a..b96b211d 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_methods.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_methods.h
@@ -16,7 +16,6 @@ const struct eap_method * eap_peer_get_methods(size_t *count);
struct eap_method * eap_peer_method_alloc(int version, int vendor,
EapType method, const char *name);
-void eap_peer_method_free(struct eap_method *method);
int eap_peer_method_register(struct eap_method *method);
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c
index 18bb04c2..9193a772 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c
@@ -882,7 +882,6 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_mschapv2_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
@@ -896,8 +895,5 @@ int eap_peer_mschapv2_register(void)
eap->isKeyAvailable = eap_mschapv2_isKeyAvailable;
eap->getKey = eap_mschapv2_getKey;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_otp.c b/freebsd/contrib/wpa/src/eap_peer/eap_otp.c
index d4d8bc1c..f375d438 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_otp.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_otp.c
@@ -85,7 +85,6 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv,
int eap_peer_otp_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP");
@@ -96,8 +95,5 @@ int eap_peer_otp_register(void)
eap->deinit = eap_otp_deinit;
eap->process = eap_otp_process;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c
index 19afa1cf..ab270bbc 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c
@@ -2,7 +2,7 @@
/*
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -61,6 +61,7 @@ struct eap_peap_data {
size_t id_len;
struct wpabuf *pending_phase2_req;
+ struct wpabuf *pending_resp;
enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
int crypto_binding_used;
u8 binding_nonce[32];
@@ -71,8 +72,8 @@ struct eap_peap_data {
};
-static int eap_peap_parse_phase1(struct eap_peap_data *data,
- const char *phase1)
+static void eap_peap_parse_phase1(struct eap_peap_data *data,
+ const char *phase1)
{
const char *pos;
@@ -127,8 +128,6 @@ static int eap_peap_parse_phase1(struct eap_peap_data *data,
wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
}
#endif /* EAP_TNC */
-
- return 0;
}
@@ -146,11 +145,8 @@ static void * eap_peap_init(struct eap_sm *sm)
data->peap_outer_success = 2;
data->crypto_binding = OPTIONAL_BINDING;
- if (config && config->phase1 &&
- eap_peap_parse_phase1(data, config->phase1) < 0) {
- eap_peap_deinit(sm, data);
- return NULL;
- }
+ if (config && config->phase1)
+ eap_peap_parse_phase1(data, config->phase1);
if (eap_peer_select_phase2_methods(config, "auth=",
&data->phase2_types,
@@ -193,6 +189,7 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv)
eap_peap_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
@@ -258,6 +255,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
{
u8 *tk;
u8 isk[32], imck[60];
+ int resumed;
/*
* Tunnel key (TK) is the first 60 octets of the key generated by
@@ -268,8 +266,12 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
- if (data->reauth &&
- tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
+ resumed = tls_connection_resumed(sm->ssl_ctx, data->ssl.conn);
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: CMK derivation - reauth=%d resumed=%d phase2_eap_started=%d phase2_success=%d",
+ data->reauth, resumed, data->phase2_eap_started,
+ data->phase2_success);
+ if (data->reauth && !data->phase2_eap_started && resumed) {
/* Fast-connect: IPMK|CMK = TK */
os_memcpy(data->ipmk, tk, 40);
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
@@ -339,7 +341,8 @@ static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
addr[0], len[0]);
wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
addr[1], len[1]);
- hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
+ if (hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac) < 0)
+ return -1;
wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
data->crypto_binding_used = 1;
@@ -650,6 +653,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
if (*resp == NULL) {
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
+ wpabuf_free(buf);
return -1;
}
wpabuf_put_buf(*resp, buf);
@@ -1008,6 +1012,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
!data->resuming) {
res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
} else {
+ if (sm->waiting_ext_cert_check && data->pending_resp) {
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ if (config->pending_ext_cert_check ==
+ EXT_CERT_CHECK_GOOD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: External certificate check succeeded - continue handshake");
+ resp = data->pending_resp;
+ data->pending_resp = NULL;
+ sm->waiting_ext_cert_check = 0;
+ return resp;
+ }
+
+ if (config->pending_ext_cert_check ==
+ EXT_CERT_CHECK_BAD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: External certificate check failed - force authentication failure");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ sm->waiting_ext_cert_check = 0;
+ return NULL;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: Continuing to wait external server certificate validation");
+ return NULL;
+ }
+
res = eap_peer_tls_process_helper(sm, &data->ssl,
EAP_TYPE_PEAP,
data->peap_version, id, &msg,
@@ -1020,6 +1052,16 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
ret->decision = DECISION_FAIL;
return resp;
}
+
+
+ if (sm->waiting_ext_cert_check) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: Waiting external server certificate validation");
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = resp;
+ return NULL;
+ }
+
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
char *label;
wpa_printf(MSG_DEBUG,
@@ -1125,6 +1167,8 @@ static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
struct eap_peap_data *data = priv;
wpabuf_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = NULL;
data->crypto_binding_used = 0;
}
@@ -1239,7 +1283,6 @@ static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_peap_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
@@ -1257,8 +1300,5 @@ int eap_peer_peap_register(void)
eap->init_for_reauth = eap_peap_init_for_reauth;
eap->getSessionId = eap_peap_get_session_id;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c
index f91c9b39..49ed1736 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c
@@ -482,7 +482,6 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_psk_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
@@ -497,8 +496,5 @@ int eap_peer_psk_register(void)
eap->getSessionId = eap_psk_get_session_id;
eap->get_emsk = eap_psk_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c
index 8ca6db9c..35afcf77 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c
@@ -2,7 +2,7 @@
/*
* EAP peer method: EAP-TLS (RFC 2716)
- * Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -27,6 +27,7 @@ struct eap_tls_data {
size_t id_len;
void *ssl_ctx;
u8 eap_type;
+ struct wpabuf *pending_resp;
};
@@ -144,6 +145,7 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv)
eap_peer_tls_ssl_deinit(sm, &data->ssl);
eap_tls_free_key(data);
os_free(data->session_id);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
@@ -218,6 +220,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
struct eap_tls_data *data = priv;
struct wpabuf msg;
+ if (sm->waiting_ext_cert_check && data->pending_resp) {
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TLS: External certificate check succeeded - continue handshake");
+ resp = data->pending_resp;
+ data->pending_resp = NULL;
+ sm->waiting_ext_cert_check = 0;
+ return resp;
+ }
+
+ if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TLS: External certificate check failed - force authentication failure");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ sm->waiting_ext_cert_check = 0;
+ return NULL;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "EAP-TLS: Continuing to wait external server certificate validation");
+ return NULL;
+ }
+
pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
reqData, &left, &flags);
if (pos == NULL)
@@ -239,6 +267,14 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
return eap_tls_failure(sm, data, ret, res, resp, id);
}
+ if (sm->waiting_ext_cert_check) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TLS: Waiting external server certificate validation");
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = resp;
+ return NULL;
+ }
+
if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
eap_tls_success(sm, data, ret);
@@ -260,6 +296,10 @@ static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
+ struct eap_tls_data *data = priv;
+
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = NULL;
}
@@ -352,7 +392,6 @@ static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_tls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
@@ -371,10 +410,7 @@ int eap_peer_tls_register(void)
eap->init_for_reauth = eap_tls_init_for_reauth;
eap->get_emsk = eap_tls_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
@@ -382,7 +418,6 @@ int eap_peer_tls_register(void)
int eap_peer_unauth_tls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_UNAUTH_TLS,
@@ -401,10 +436,7 @@ int eap_peer_unauth_tls_register(void)
eap->init_for_reauth = eap_tls_init_for_reauth;
eap->get_emsk = eap_tls_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
#endif /* EAP_UNAUTH_TLS */
@@ -413,7 +445,6 @@ int eap_peer_unauth_tls_register(void)
int eap_peer_wfa_unauth_tls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_WFA_NEW,
@@ -433,9 +464,6 @@ int eap_peer_wfa_unauth_tls_register(void)
eap->init_for_reauth = eap_tls_init_for_reauth;
eap->get_emsk = eap_tls_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
#endif /* CONFIG_HS20 */
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c
index ff6c937c..8908dc2f 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c
@@ -82,6 +82,10 @@ static void eap_tls_params_flags(struct tls_connection_params *params,
params->flags |= TLS_CONN_DISABLE_TLSv1_2;
if (os_strstr(txt, "tls_disable_tlsv1_2=0"))
params->flags &= ~TLS_CONN_DISABLE_TLSv1_2;
+ if (os_strstr(txt, "tls_ext_cert_check=1"))
+ params->flags |= TLS_CONN_EXT_CERT_CHECK;
+ if (os_strstr(txt, "tls_ext_cert_check=0"))
+ params->flags &= ~TLS_CONN_EXT_CERT_CHECK;
}
@@ -179,6 +183,8 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
params->openssl_ciphers = config->openssl_ciphers;
+ sm->ext_cert_check = !!(params->flags & TLS_CONN_EXT_CERT_CHECK);
+
return 0;
}
@@ -192,8 +198,10 @@ static int eap_tls_init_connection(struct eap_sm *sm,
if (config->ocsp)
params->flags |= TLS_CONN_REQUEST_OCSP;
- if (config->ocsp == 2)
+ if (config->ocsp >= 2)
params->flags |= TLS_CONN_REQUIRE_OCSP;
+ if (config->ocsp == 3)
+ params->flags |= TLS_CONN_REQUIRE_OCSP_ALL;
data->conn = tls_connection_init(data->ssl_ctx);
if (data->conn == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
@@ -322,8 +330,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
if (out == NULL)
return NULL;
- if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0,
- out, len)) {
+ if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out,
+ len)) {
os_free(out);
return NULL;
}
@@ -352,10 +360,8 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct tls_random keys;
u8 *out;
- if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
- return NULL;
-
- if (keys.client_random == NULL || keys.server_random == NULL)
+ if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys) ||
+ keys.client_random == NULL || keys.server_random == NULL)
return NULL;
*len = 1 + keys.client_random_len + keys.server_random_len;
@@ -1037,6 +1043,9 @@ int eap_peer_select_phase2_methods(struct eap_peer_config *config,
if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
"method '%s'", start);
+ os_free(methods);
+ os_free(buf);
+ return -1;
} else {
num_methods++;
_methods = os_realloc_array(methods, num_methods,
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c
index 55788774..f9601e45 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c
@@ -2,7 +2,7 @@
/*
* EAP peer method: EAP-TTLS (RFC 5281)
- * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -37,6 +37,7 @@ struct eap_ttls_data {
void *phase2_priv;
int phase2_success;
int phase2_start;
+ EapDecision decision_succ;
enum phase2_types {
EAP_TTLS_PHASE2_EAP,
@@ -60,6 +61,7 @@ struct eap_ttls_data {
size_t id_len;
struct wpabuf *pending_phase2_req;
+ struct wpabuf *pending_resp;
#ifdef EAP_TNC
int ready_for_tnc;
@@ -72,6 +74,7 @@ static void * eap_ttls_init(struct eap_sm *sm)
{
struct eap_ttls_data *data;
struct eap_peer_config *config = eap_get_config(sm);
+ int selected_non_eap;
char *selected;
data = os_zalloc(sizeof(*data));
@@ -79,26 +82,67 @@ static void * eap_ttls_init(struct eap_sm *sm)
return NULL;
data->ttls_version = EAP_TTLS_VERSION;
selected = "EAP";
+ selected_non_eap = 0;
data->phase2_type = EAP_TTLS_PHASE2_EAP;
+ /*
+ * Either one auth= type or one or more autheap= methods can be
+ * specified.
+ */
if (config && config->phase2) {
+ const char *token, *last = NULL;
+
+ while ((token = cstr_token(config->phase2, " \t", &last))) {
+ if (os_strncmp(token, "auth=", 5) != 0)
+ continue;
+ token += 5;
+
+ if (last - token == 8 &&
+ os_strncmp(token, "MSCHAPV2", 8) == 0) {
+ selected = "MSCHAPV2";
+ data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
+ } else if (last - token == 6 &&
+ os_strncmp(token, "MSCHAP", 6) == 0) {
+ selected = "MSCHAP";
+ data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
+ } else if (last - token == 3 &&
+ os_strncmp(token, "PAP", 3) == 0) {
+ selected = "PAP";
+ data->phase2_type = EAP_TTLS_PHASE2_PAP;
+ } else if (last - token == 4 &&
+ os_strncmp(token, "CHAP", 4) == 0) {
+ selected = "CHAP";
+ data->phase2_type = EAP_TTLS_PHASE2_CHAP;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "EAP-TTLS: Unsupported Phase2 type '%s'",
+ token);
+ eap_ttls_deinit(sm, data);
+ return NULL;
+ }
+
+ if (selected_non_eap) {
+ wpa_printf(MSG_ERROR,
+ "EAP-TTLS: Only one Phase2 type can be specified");
+ eap_ttls_deinit(sm, data);
+ return NULL;
+ }
+
+ selected_non_eap = 1;
+ }
+
if (os_strstr(config->phase2, "autheap=")) {
+ if (selected_non_eap) {
+ wpa_printf(MSG_ERROR,
+ "EAP-TTLS: Both auth= and autheap= params cannot be specified");
+ eap_ttls_deinit(sm, data);
+ return NULL;
+ }
selected = "EAP";
data->phase2_type = EAP_TTLS_PHASE2_EAP;
- } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
- selected = "MSCHAPV2";
- data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
- } else if (os_strstr(config->phase2, "auth=MSCHAP")) {
- selected = "MSCHAP";
- data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
- } else if (os_strstr(config->phase2, "auth=PAP")) {
- selected = "PAP";
- data->phase2_type = EAP_TTLS_PHASE2_PAP;
- } else if (os_strstr(config->phase2, "auth=CHAP")) {
- selected = "CHAP";
- data->phase2_type = EAP_TTLS_PHASE2_CHAP;
}
}
+
wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
@@ -155,6 +199,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
eap_ttls_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
@@ -1410,6 +1455,32 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
{
int res;
+ if (sm->waiting_ext_cert_check && data->pending_resp) {
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TTLS: External certificate check succeeded - continue handshake");
+ *out_data = data->pending_resp;
+ data->pending_resp = NULL;
+ sm->waiting_ext_cert_check = 0;
+ return 0;
+ }
+
+ if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TTLS: External certificate check failed - force authentication failure");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ sm->waiting_ext_cert_check = 0;
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "EAP-TTLS: Continuing to wait external server certificate validation");
+ return 0;
+ }
+
res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
data->ttls_version, identifier,
in_data, out_data);
@@ -1420,6 +1491,15 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
return -1;
}
+ if (sm->waiting_ext_cert_check) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TTLS: Waiting external server certificate validation");
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = *out_data;
+ *out_data = NULL;
+ return 0;
+ }
+
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
"Phase 2");
@@ -1470,6 +1550,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
"completed successfully");
data->phase2_success = 1;
+ data->decision_succ = ret->decision;
#ifdef EAP_TNC
if (!data->ready_for_tnc && !data->tnc_started) {
/*
@@ -1487,6 +1568,18 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
"completed successfully (MAY_CONT)");
data->phase2_success = 1;
+ data->decision_succ = ret->decision;
+ } else if (data->decision_succ != DECISION_FAIL &&
+ data->phase2_success &&
+ !data->ssl.tls_out) {
+ /*
+ * This is needed to cover the case where the final Phase 2
+ * message gets fragmented since fragmentation clears
+ * decision back to FAIL.
+ */
+ wpa_printf(MSG_DEBUG,
+ "EAP-TTLS: Restore success decision after fragmented frame sent completely");
+ ret->decision = data->decision_succ;
}
}
@@ -1559,6 +1652,9 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
struct eap_ttls_data *data = priv;
wpabuf_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = NULL;
+ data->decision_succ = DECISION_FAIL;
#ifdef EAP_TNC
data->ready_for_tnc = 0;
data->tnc_started = 0;
@@ -1697,7 +1793,6 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_ttls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
@@ -1716,8 +1811,5 @@ int eap_peer_ttls_register(void)
eap->init_for_reauth = eap_ttls_init_for_reauth;
eap->get_emsk = eap_ttls_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
diff --git a/freebsd/contrib/wpa/src/eap_server/eap_methods.h b/freebsd/contrib/wpa/src/eap_server/eap_methods.h
index 0baa3279..3bf1495f 100644
--- a/freebsd/contrib/wpa/src/eap_server/eap_methods.h
+++ b/freebsd/contrib/wpa/src/eap_server/eap_methods.h
@@ -15,7 +15,6 @@ const struct eap_method * eap_server_get_eap_method(int vendor,
EapType method);
struct eap_method * eap_server_method_alloc(int version, int vendor,
EapType method, const char *name);
-void eap_server_method_free(struct eap_method *method);
int eap_server_method_register(struct eap_method *method);
EapType eap_server_get_type(const char *name, int *vendor);
diff --git a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
index e633d7c1..938e0d05 100644
--- a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
+++ b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
@@ -316,6 +316,16 @@ SM_STATE(SUPP_PAE, RESTART)
{
SM_ENTRY(SUPP_PAE, RESTART);
sm->eapRestart = TRUE;
+ if (sm->altAccept) {
+ /*
+ * Prevent EAP peer state machine from failing due to prior
+ * external EAP success notification (altSuccess=TRUE in the
+ * IDLE state could result in a transition to the FAILURE state.
+ */
+ wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
+ sm->eapSuccess = FALSE;
+ sm->altAccept = FALSE;
+ }
}
diff --git a/freebsd/contrib/wpa/src/p2p/p2p.h b/freebsd/contrib/wpa/src/p2p/p2p.h
index b4060be4..7b18dcfc 100644
--- a/freebsd/contrib/wpa/src/p2p/p2p.h
+++ b/freebsd/contrib/wpa/src/p2p/p2p.h
@@ -31,7 +31,7 @@
/**
* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
*/
-#define P2P_MAX_REG_CLASSES 10
+#define P2P_MAX_REG_CLASSES 15
/**
* P2P_MAX_REG_CLASS_CHANNELS - Maximum number of channels per regulatory class
@@ -99,6 +99,10 @@ struct p2p_go_neg_results {
int vht;
+ u8 max_oper_chwidth;
+
+ unsigned int vht_center_freq2;
+
/**
* ssid - SSID of the group
*/
@@ -224,6 +228,16 @@ struct p2ps_provision {
u8 cpt_priority[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
/**
+ * force_freq - The only allowed channel frequency in MHz or 0.
+ */
+ unsigned int force_freq;
+
+ /**
+ * pref_freq - Preferred operating frequency in MHz or 0.
+ */
+ unsigned int pref_freq;
+
+ /**
* info - Vendor defined extra Provisioning information
*/
char info[0];
@@ -1024,6 +1038,8 @@ struct p2p_config {
* @ssid_len: Buffer for returning length of @ssid
* @group_iface: Buffer for returning whether a separate group interface
* would be used
+ * @freq: Variable for returning the current operating frequency of a
+ * currently running P2P GO.
* Returns: 1 if GO info found, 0 otherwise
*
* This is used to compose New Group settings (SSID, and intended
@@ -1031,7 +1047,8 @@ struct p2p_config {
* result in our being an autonomous GO.
*/
int (*get_go_info)(void *ctx, u8 *intended_addr,
- u8 *ssid, size_t *ssid_len, int *group_iface);
+ u8 *ssid, size_t *ssid_len, int *group_iface,
+ unsigned int *freq);
/**
* remove_stale_groups - Remove stale P2PS groups
@@ -1056,7 +1073,9 @@ struct p2p_config {
const u8 *persist_ssid,
size_t persist_ssid_size, int response_done,
int prov_start, const char *session_info,
- const u8 *feat_cap, size_t feat_cap_len);
+ const u8 *feat_cap, size_t feat_cap_len,
+ unsigned int freq, const u8 *group_ssid,
+ size_t group_ssid_len);
/**
* prov_disc_resp_cb - Callback for indicating completion of PD Response
@@ -1070,14 +1089,20 @@ struct p2p_config {
/**
* p2ps_group_capability - Determine group capability
+ * @ctx: Callback context from cb_ctx
+ * @incoming: Peer requested roles, expressed with P2PS_SETUP_* bitmap.
+ * @role: Local roles, expressed with P2PS_SETUP_* bitmap.
+ * @force_freq: Variable for returning forced frequency for the group.
+ * @pref_freq: Variable for returning preferred frequency for the group.
+ * Returns: P2PS_SETUP_* bitmap of group capability result.
*
- * This function can be used to determine group capability based on
- * information from P2PS PD exchange and the current state of ongoing
- * groups and driver capabilities.
- *
- * P2PS_SETUP_* bitmap is used as the parameters and return value.
+ * This function can be used to determine group capability and
+ * frequencies based on information from P2PS PD exchange and the
+ * current state of ongoing groups and driver capabilities.
*/
- u8 (*p2ps_group_capability)(void *ctx, u8 incoming, u8 role);
+ u8 (*p2ps_group_capability)(void *ctx, u8 incoming, u8 role,
+ unsigned int *force_freq,
+ unsigned int *pref_freq);
/**
* get_pref_freq_list - Get preferred frequency list for an interface
@@ -1530,12 +1555,13 @@ enum p2p_probe_req_status {
* @ie: Information elements from the Probe Request frame body
* @ie_len: Length of ie buffer in octets
* @rx_freq: Probe Request frame RX frequency
+ * @p2p_lo_started: Whether P2P Listen Offload is started
* Returns: value indicating the type and status of the probe request
*/
enum p2p_probe_req_status
p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
const u8 *bssid, const u8 *ie, size_t ie_len,
- unsigned int rx_freq);
+ unsigned int rx_freq, int p2p_lo_started);
/**
* p2p_rx_action - Report received Action frame
@@ -1691,6 +1717,12 @@ struct p2p_group_config {
int freq;
/**
+ * ip_addr_alloc - Whether IP address allocation within 4-way handshake
+ * is supported
+ */
+ int ip_addr_alloc;
+
+ /**
* cb_ctx - Context to use with callback functions
*/
void *cb_ctx;
@@ -1877,8 +1909,10 @@ int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
* @p2p: P2P module context from p2p_init()
* @ies: Buffer for writing P2P IE
* @dev_id: Device ID to search for or %NULL for any
+ * @bands: Frequency bands used in the scan (enum wpa_radio_work_band bitmap)
*/
-void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id);
+void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
+ unsigned int bands);
/**
* p2p_scan_ie_buf_len - Get maximum buffer length needed for p2p_scan_ie
@@ -2100,6 +2134,16 @@ int p2p_client_limit_reached(struct p2p_group *group);
const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next);
/**
+ * p2p_group_get_client_interface_addr - Get P2P Interface Address of a client in a group
+ * @group: P2P group context from p2p_group_init()
+ * @dev_addr: P2P Device Address of the client
+ * Returns: P2P Interface Address of the client if found or %NULL if no match
+ * found
+ */
+const u8 * p2p_group_get_client_interface_addr(struct p2p_group *group,
+ const u8 *dev_addr);
+
+/**
* p2p_group_get_dev_addr - Get a P2P Device Address of a client in a group
* @group: P2P group context from p2p_group_init()
* @addr: P2P Interface Address of the client
@@ -2241,7 +2285,7 @@ struct wpabuf * wifi_display_encaps(struct wpabuf *subelems);
* discovery (p2p_find). A random number of 100 TU units is picked for each
* Listen state iteration from [min_disc_int,max_disc_int] range.
*
- * max_disc_tu can be used to futher limit the discoverable duration. However,
+ * max_disc_tu can be used to further limit the discoverable duration. However,
* it should be noted that use of this parameter is not recommended since it
* would not be compliant with the P2P specification.
*/
@@ -2340,4 +2384,7 @@ void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
int p2p_group_get_common_freqs(struct p2p_group *group, int *common_freqs,
unsigned int *num);
+struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
+ unsigned int freq);
+
#endif /* P2P_H */
diff --git a/freebsd/contrib/wpa/src/radius/radius.h b/freebsd/contrib/wpa/src/radius/radius.h
index 5977339e..cd510d2c 100644
--- a/freebsd/contrib/wpa/src/radius/radius.h
+++ b/freebsd/contrib/wpa/src/radius/radius.h
@@ -1,6 +1,6 @@
/*
* RADIUS message processing
- * Copyright (c) 2002-2009, 2012, 2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -52,6 +52,8 @@ enum { RADIUS_ATTR_USER_NAME = 1,
RADIUS_ATTR_USER_PASSWORD = 2,
RADIUS_ATTR_NAS_IP_ADDRESS = 4,
RADIUS_ATTR_NAS_PORT = 5,
+ RADIUS_ATTR_SERVICE_TYPE = 6,
+ RADIUS_ATTR_FRAMED_IP_ADDRESS = 8,
RADIUS_ATTR_FRAMED_MTU = 12,
RADIUS_ATTR_REPLY_MESSAGE = 18,
RADIUS_ATTR_STATE = 24,
@@ -79,6 +81,7 @@ enum { RADIUS_ATTR_USER_NAME = 1,
RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52,
RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53,
RADIUS_ATTR_EVENT_TIMESTAMP = 55,
+ RADIUS_ATTR_EGRESS_VLANID = 56,
RADIUS_ATTR_NAS_PORT_TYPE = 61,
RADIUS_ATTR_TUNNEL_TYPE = 64,
RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65,
@@ -108,6 +111,9 @@ enum { RADIUS_ATTR_USER_NAME = 1,
};
+/* Service-Type values (RFC 2865, 5.6) */
+#define RADIUS_SERVICE_TYPE_FRAMED 2
+
/* Termination-Action */
#define RADIUS_TERMINATION_ACTION_DEFAULT 0
#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1
@@ -236,7 +242,8 @@ void radius_msg_finish_acct_resp(struct radius_msg *msg, const u8 *secret,
int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret,
size_t secret_len);
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
- size_t secret_len);
+ size_t secret_len,
+ int require_message_authenticator);
struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type,
const u8 *data, size_t data_len);
struct radius_msg * radius_msg_parse(const u8 *data, size_t len);
@@ -250,8 +257,7 @@ int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
size_t secret_len, const u8 *req_auth);
int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
u8 type);
-void radius_msg_make_authenticator(struct radius_msg *msg,
- const u8 *data, size_t len);
+int radius_msg_make_authenticator(struct radius_msg *msg);
struct radius_ms_mppe_keys *
radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
const u8 *secret, size_t secret_len);
@@ -274,7 +280,8 @@ radius_msg_add_attr_user_password(struct radius_msg *msg,
const u8 *data, size_t data_len,
const u8 *secret, size_t secret_len);
int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len);
-int radius_msg_get_vlanid(struct radius_msg *msg);
+int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
+ int *tagged);
char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
const u8 *secret, size_t secret_len,
struct radius_msg *sent_msg, size_t n);
@@ -319,4 +326,6 @@ int radius_copy_class(struct radius_class_data *dst,
u8 radius_msg_find_unlisted_attr(struct radius_msg *msg, u8 *attrs);
+int radius_gen_session_id(u8 *id, size_t len);
+
#endif /* RADIUS_H */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c
index e9bf319a..7f7cbbec 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c
@@ -17,7 +17,7 @@
#include "wpa_i.h"
#include "pmksa_cache.h"
-#ifdef IEEE8021X_EAPOL
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
static const int pmksa_cache_max_entries = 32;
@@ -111,6 +111,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @pmk: The new pairwise master key
* @pmk_len: PMK length in bytes, usually PMK_LEN (32)
+ * @pmkid: Calculated PMKID
* @kck: Key confirmation key or %NULL if not yet derived
* @kck_len: KCK length in bytes
* @aa: Authenticator address
@@ -126,13 +127,13 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
*/
struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
- const u8 *kck, size_t kck_len,
+ const u8 *pmkid, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
{
struct rsn_pmksa_cache_entry *entry, *pos, *prev;
struct os_reltime now;
- if (pmk_len > PMK_LEN)
+ if (pmk_len > PMK_LEN_MAX)
return NULL;
if (wpa_key_mgmt_suite_b(akmp) && !kck)
@@ -143,7 +144,9 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
return NULL;
os_memcpy(entry->pmk, pmk, pmk_len);
entry->pmk_len = pmk_len;
- if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ if (pmkid)
+ os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
+ else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
else if (wpa_key_mgmt_suite_b(akmp))
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
@@ -346,7 +349,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *new_entry;
new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
- NULL, 0,
+ NULL, NULL, 0,
aa, pmksa->sm->own_addr,
old_entry->network_ctx, old_entry->akmp);
if (new_entry == NULL)
diff --git a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h
index f8e040e0..daede6da 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h
@@ -15,7 +15,7 @@
struct rsn_pmksa_cache_entry {
struct rsn_pmksa_cache_entry *next;
u8 pmkid[PMKID_LEN];
- u8 pmk[PMK_LEN];
+ u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
os_time_t expiration;
int akmp; /* WPA_KEY_MGMT_* */
@@ -44,7 +44,7 @@ enum pmksa_free_reason {
PMKSA_EXPIRE,
};
-#ifdef IEEE8021X_EAPOL
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
struct rsn_pmksa_cache *
pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
@@ -57,7 +57,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
- const u8 *kck, size_t kck_len,
+ const u8 *pmkid, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
void pmksa_cache_clear_current(struct wpa_sm *sm);
@@ -105,7 +105,7 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
static inline struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
- const u8 *kck, size_t kck_len,
+ const u8 *pmkid, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
{
return NULL;
diff --git a/freebsd/contrib/wpa/src/rsn_supp/preauth.c b/freebsd/contrib/wpa/src/rsn_supp/preauth.c
index f6b3cf5c..470f5971 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/preauth.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/preauth.c
@@ -20,7 +20,7 @@
#include "wpa_i.h"
-#ifdef IEEE8021X_EAPOL
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
#define PMKID_CANDIDATE_PRIO_SCAN 1000
@@ -95,7 +95,7 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
pmk, pmk_len);
sm->pmk_len = pmk_len;
- pmksa_cache_add(sm->pmksa, pmk, pmk_len,
+ pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL,
NULL, 0,
sm->preauth_bssid, sm->own_addr,
sm->network_ctx,
@@ -540,4 +540,4 @@ int rsn_preauth_in_progress(struct wpa_sm *sm)
return sm->preauth_eapol != NULL;
}
-#endif /* IEEE8021X_EAPOL */
+#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/preauth.h b/freebsd/contrib/wpa/src/rsn_supp/preauth.h
index 277f0663..8caf3ee5 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/preauth.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/preauth.h
@@ -11,7 +11,7 @@
struct wpa_scan_results;
-#ifdef IEEE8021X_EAPOL
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
void pmksa_candidate_free(struct wpa_sm *sm);
int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
@@ -27,7 +27,7 @@ int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
int verbose);
int rsn_preauth_in_progress(struct wpa_sm *sm);
-#else /* IEEE8021X_EAPOL */
+#else /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
static inline void pmksa_candidate_free(struct wpa_sm *sm)
{
@@ -74,6 +74,6 @@ static inline int rsn_preauth_in_progress(struct wpa_sm *sm)
return 0;
}
-#endif /* IEEE8021X_EAPOL */
+#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
#endif /* PREAUTH_H */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa.c b/freebsd/contrib/wpa/src/rsn_supp/wpa.c
index c4181bdf..4ad6bb6a 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa.c
@@ -3,6 +3,7 @@
/*
* WPA Supplicant - WPA state machine and EAPOL-Key processing
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright(c) 2015 Intel Deutschland GmbH
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -25,6 +26,9 @@
#include "peerkey.h"
+static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+
/**
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -36,11 +40,13 @@
* @msg: EAPOL-Key message
* @msg_len: Length of message
* @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
+ * Returns: >= 0 on success, < 0 on failure
*/
-void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
- int ver, const u8 *dest, u16 proto,
- u8 *msg, size_t msg_len, u8 *key_mic)
+int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
+ int ver, const u8 *dest, u16 proto,
+ u8 *msg, size_t msg_len, u8 *key_mic)
{
+ int ret = -1;
size_t mic_len = wpa_mic_len(sm->key_mgmt);
if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
@@ -71,10 +77,11 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len);
wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len);
wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
- wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
+ ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
eapol_sm_notify_tx_eapol_key(sm->eapol);
out:
os_free(msg);
+ return ret;
}
@@ -126,7 +133,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
key_info = WPA_KEY_INFO_REQUEST | ver;
if (sm->ptk_set)
- key_info |= WPA_KEY_INFO_MIC;
+ key_info |= WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
if (error)
key_info |= WPA_KEY_INFO_ERROR;
if (pairwise)
@@ -208,15 +215,21 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
#endif /* CONFIG_IEEE80211R */
} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
int res, pmk_len;
- pmk_len = PMK_LEN;
- res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
+
+ if (sm->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ pmk_len = PMK_LEN_SUITE_B_192;
+ else
+ pmk_len = PMK_LEN;
+ res = eapol_sm_get_key(sm->eapol, sm->pmk, pmk_len);
if (res) {
- /*
- * EAP-LEAP is an exception from other EAP methods: it
- * uses only 16-byte PMK.
- */
- res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
- pmk_len = 16;
+ if (pmk_len == PMK_LEN) {
+ /*
+ * EAP-LEAP is an exception from other EAP
+ * methods: it uses only 16-byte PMK.
+ */
+ res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
+ pmk_len = 16;
+ }
} else {
#ifdef CONFIG_IEEE80211R
u8 buf[2 * PMK_LEN];
@@ -238,7 +251,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
!wpa_key_mgmt_ft(sm->key_mgmt)) {
sa = pmksa_cache_add(sm->pmksa,
- sm->pmk, pmk_len,
+ sm->pmk, pmk_len, NULL,
NULL, 0,
src_addr, sm->own_addr,
sm->network_ctx,
@@ -259,7 +272,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
* much we can do here without knowing what
* exactly caused the server to misbehave.
*/
- wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: PMKID mismatch - authentication server may have derived different MSK?!");
return -1;
}
@@ -320,7 +333,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
* @wpa_ie: WPA/RSN IE
* @wpa_ie_len: Length of the WPA/RSN IE
* @ptk: PTK to use for keyed hash and encryption
- * Returns: 0 on success, -1 on failure
+ * Returns: >= 0 on success, < 0 on failure
*/
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
const struct wpa_eapol_key *key,
@@ -353,13 +366,12 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
if (rsn_ie_buf == NULL)
return -1;
os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
- res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
+ res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
sm->pmk_r1_name);
if (res < 0) {
os_free(rsn_ie_buf);
return -1;
}
- wpa_ie_len += res;
if (sm->assoc_resp_ies) {
os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
@@ -411,10 +423,8 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
- wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL,
- rbuf, rlen, key_mic);
-
- return 0;
+ return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst,
+ ETH_P_EAPOL, rbuf, rlen, key_mic);
}
@@ -527,7 +537,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
#endif /* CONFIG_P2P */
if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
- kde, kde_len, ptk))
+ kde, kde_len, ptk) < 0)
goto failed;
os_free(kde_buf);
@@ -605,7 +615,6 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
int keylen, rsclen;
enum wpa_alg alg;
const u8 *key_rsc;
- u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (sm->ptk.installed) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -783,12 +792,43 @@ static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
}
+static int wpa_supplicant_rsc_relaxation(const struct wpa_sm *sm,
+ const u8 *rsc)
+{
+ int rsclen;
+
+ if (!sm->wpa_rsc_relaxation)
+ return 0;
+
+ rsclen = wpa_cipher_rsc_len(sm->group_cipher);
+
+ /*
+ * Try to detect RSC (endian) corruption issue where the AP sends
+ * the RSC bytes in EAPOL-Key message in the wrong order, both if
+ * it's actually a 6-byte field (as it should be) and if it treats
+ * it as an 8-byte field.
+ * An AP model known to have this bug is the Sapido RB-1632.
+ */
+ if (rsclen == 6 && ((rsc[5] && !rsc[0]) || rsc[6] || rsc[7])) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSC %02x%02x%02x%02x%02x%02x%02x%02x is likely bogus, using 0",
+ rsc[0], rsc[1], rsc[2], rsc[3],
+ rsc[4], rsc[5], rsc[6], rsc[7]);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
const u8 *gtk, size_t gtk_len,
int key_info)
{
struct wpa_gtk_data gd;
+ const u8 *key_rsc;
/*
* IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
@@ -814,11 +854,15 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
os_memcpy(gd.gtk, gtk, gtk_len);
gd.gtk_len = gtk_len;
+ key_rsc = key->key_rsc;
+ if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
+ key_rsc = null_rsc;
+
if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
(wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
gtk_len, gtk_len,
&gd.key_rsc_len, &gd.alg) ||
- wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0))) {
+ wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Failed to install GTK");
os_memset(&gd, 0, sizeof(gd));
@@ -1055,8 +1099,8 @@ static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
if (sm->assoc_resp_ies) {
pos = sm->assoc_resp_ies;
end = pos + sm->assoc_resp_ies_len;
- while (pos + 2 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 2) {
+ if (2 + pos[1] > end - pos)
break;
switch (*pos) {
case WLAN_EID_MOBILITY_DOMAIN:
@@ -1152,7 +1196,7 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
* @ver: Version bits from EAPOL-Key Key Info
* @key_info: Key Info
* @ptk: PTK to use for keyed hash and encryption
- * Returns: 0 on success, -1 on failure
+ * Returns: >= 0 on success, < 0 on failure
*/
int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
const struct wpa_eapol_key *key,
@@ -1192,10 +1236,8 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
WPA_PUT_BE16(reply->key_data_length, 0);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
- wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL,
- rbuf, rlen, key_mic);
-
- return 0;
+ return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst,
+ ETH_P_EAPOL, rbuf, rlen, key_mic);
}
@@ -1268,7 +1310,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
#endif /* CONFIG_P2P */
if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
- &sm->ptk)) {
+ &sm->ptk) < 0) {
goto failed;
}
@@ -1313,7 +1355,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) {
struct rsn_pmksa_cache_entry *sa;
- sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
+ sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
sm->ptk.kck, sm->ptk.kck_len,
sm->bssid, sm->own_addr,
sm->network_ctx, sm->key_mgmt);
@@ -1503,10 +1545,8 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
WPA_PUT_BE16(reply->key_data_length, 0);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
- wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid,
- ETH_P_EAPOL, rbuf, rlen, key_mic);
-
- return 0;
+ return wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver,
+ sm->bssid, ETH_P_EAPOL, rbuf, rlen, key_mic);
}
@@ -1519,6 +1559,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
u16 key_info;
int rekey, ret;
struct wpa_gtk_data gd;
+ const u8 *key_rsc;
if (!sm->msg_3_of_4_ok) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -1549,13 +1590,17 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
if (ret)
goto failed;
- if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0) ||
- wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
+ key_rsc = key->key_rsc;
+ if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
+ key_rsc = null_rsc;
+
+ if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
+ wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
goto failed;
os_memset(&gd, 0, sizeof(gd));
if (rekey) {
- wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Group rekeying "
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
"completed with " MACSTR " [GTK=%s]",
MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
wpa_sm_cancel_auth_timeout(sm);
@@ -1683,14 +1728,14 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
}
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
key_data, buf)) {
- os_free(buf);
+ bin_clear_free(buf, *key_data_len);
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: AES unwrap failed - "
"could not decrypt EAPOL-Key key data");
return -1;
}
os_memcpy(key_data, buf, *key_data_len);
- os_free(buf);
+ bin_clear_free(buf, *key_data_len);
WPA_PUT_BE16(key->key_data_length, *key_data_len);
} else {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@@ -2029,6 +2074,17 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ /*
+ * Only decrypt the Key Data field if the frame's authenticity
+ * was verified. When using AES-SIV (FILS), the MIC flag is not
+ * set, so this check should only be performed if mic_len != 0
+ * which is the case in this code branch.
+ */
+ if (!(key_info & WPA_KEY_INFO_MIC)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
+ goto out;
+ }
if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
&key_data_len))
goto out;
@@ -2303,6 +2359,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
#ifdef CONFIG_IEEE80211R
os_free(sm->assoc_resp_ies);
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_TESTING_OPTIONS
+ wpabuf_free(sm->test_assoc_ie);
+#endif /* CONFIG_TESTING_OPTIONS */
os_free(sm);
}
@@ -2410,12 +2469,13 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @pmk: The new PMK
* @pmk_len: The length of the new PMK in bytes
+ * @pmkid: Calculated PMKID
* @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
*
* Configure the PMK for WPA state machine.
*/
void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
- const u8 *bssid)
+ const u8 *pmkid, const u8 *bssid)
{
if (sm == NULL)
return;
@@ -2430,7 +2490,7 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
#endif /* CONFIG_IEEE80211R */
if (bssid) {
- pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0,
+ pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
bssid, sm->own_addr,
sm->network_ctx, sm->key_mgmt);
}
@@ -2514,6 +2574,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
sm->ssid_len = 0;
sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
sm->p2p = config->p2p;
+ sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation;
} else {
sm->network_ctx = NULL;
sm->peerkey_enabled = 0;
@@ -2524,6 +2585,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
sm->ssid_len = 0;
sm->wpa_ptk_rekey = 0;
sm->p2p = 0;
+ sm->wpa_rsc_relaxation = 0;
}
}
@@ -2711,6 +2773,17 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
if (sm == NULL)
return -1;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (sm->test_assoc_ie) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Replace association WPA/RSN IE");
+ if (*wpa_ie_len < wpabuf_len(sm->test_assoc_ie))
+ return -1;
+ os_memcpy(wpa_ie, wpabuf_head(sm->test_assoc_ie),
+ wpabuf_len(sm->test_assoc_ie));
+ res = wpabuf_len(sm->test_assoc_ie);
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
if (res < 0)
return -1;
@@ -3038,3 +3111,12 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
}
sm->ptk_set = 1;
}
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
+{
+ wpabuf_free(sm->test_assoc_ie);
+ sm->test_assoc_ie = buf;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa.h b/freebsd/contrib/wpa/src/rsn_supp/wpa.h
index e163b701..0b7477f3 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa.h
@@ -104,6 +104,7 @@ struct rsn_supp_config {
size_t ssid_len;
int wpa_ptk_rekey;
int p2p;
+ int wpa_rsc_relaxation;
};
#ifndef CONFIG_NO_WPA
@@ -113,7 +114,7 @@ void wpa_sm_deinit(struct wpa_sm *sm);
void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid);
void wpa_sm_notify_disassoc(struct wpa_sm *sm);
void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
- const u8 *bssid);
+ const u8 *pmkid, const u8 *bssid);
void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth);
void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx);
@@ -180,7 +181,8 @@ static inline void wpa_sm_notify_disassoc(struct wpa_sm *sm)
}
static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk,
- size_t pmk_len)
+ size_t pmk_len, const u8 *pmkid,
+ const u8 *bssid)
{
}
@@ -320,7 +322,8 @@ static inline void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm,
}
static inline void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck,
- const u8 *ptk_kek)
+ size_t ptk_kck_len,
+ const u8 *ptk_kek, size_t ptk_kek_len)
{
}
@@ -415,7 +418,12 @@ int wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr,
u8 oper_class,
struct hostapd_freq_params *freq_params);
int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr);
+#ifdef CONFIG_TDLS_TESTING
+extern unsigned int tdls_testing;
+#endif /* CONFIG_TDLS_TESTING */
+
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
+void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
#endif /* WPA_H */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h b/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h
index 85cc8628..56f88dcd 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h
@@ -19,7 +19,7 @@ struct wpa_eapol_key;
* struct wpa_sm - Internal WPA state machine data
*/
struct wpa_sm {
- u8 pmk[PMK_LEN];
+ u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
struct wpa_ptk ptk, tptk;
int ptk_set, tptk_set;
@@ -66,6 +66,7 @@ struct wpa_sm {
size_t ssid_len;
int wpa_ptk_rekey;
int p2p;
+ int wpa_rsc_relaxation;
u8 own_addr[ETH_ALEN];
const char *ifname;
@@ -139,6 +140,10 @@ struct wpa_sm {
#ifdef CONFIG_P2P
u8 p2p_ip_addr[3 * 4];
#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_TESTING_OPTIONS
+ struct wpabuf *test_assoc_ie;
+#endif /* CONFIG_TESTING_OPTIONS */
};
@@ -349,16 +354,14 @@ wpa_sm_tdls_disable_channel_switch(struct wpa_sm *sm, const u8 *addr)
static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm,
const u8 *pmk, size_t pmk_len)
{
- if (!sm->proactive_key_caching)
- return 0;
if (!sm->ctx->key_mgmt_set_pmk)
return -1;
return sm->ctx->key_mgmt_set_pmk(sm->ctx->ctx, pmk, pmk_len);
}
-void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
- int ver, const u8 *dest, u16 proto,
- u8 *msg, size_t msg_len, u8 *key_mic);
+int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
+ int ver, const u8 *dest, u16 proto,
+ u8 *msg, size_t msg_len, u8 *key_mic);
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
const struct wpa_eapol_key *key,
int ver, const u8 *nonce,
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c
index 2a22d7de..4caf9c6b 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c
@@ -380,7 +380,7 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
return 0;
}
- if (pos + 1 + RSN_SELECTOR_LEN < end &&
+ if (1 + RSN_SELECTOR_LEN < end - pos &&
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
@@ -493,13 +493,13 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
int ret = 0;
os_memset(ie, 0, sizeof(*ie));
- for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
+ for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) {
if (pos[0] == 0xdd &&
((pos == buf + len - 1) || pos[1] == 0)) {
/* Ignore padding */
break;
}
- if (pos + 2 + pos[1] > end) {
+ if (2 + pos[1] > end - pos) {
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
"underflow (ie=%d len=%d pos=%d)",
pos[0], pos[1], (int) (pos - buf));
diff --git a/freebsd/contrib/wpa/src/tls/tlsv1_client.h b/freebsd/contrib/wpa/src/tls/tlsv1_client.h
index a4e25e96..40fa6c7f 100644
--- a/freebsd/contrib/wpa/src/tls/tlsv1_client.h
+++ b/freebsd/contrib/wpa/src/tls/tlsv1_client.h
@@ -41,7 +41,7 @@ int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn);
int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers);
int tlsv1_client_set_cred(struct tlsv1_client *conn,
struct tlsv1_credentials *cred);
-void tlsv1_client_set_time_checks(struct tlsv1_client *conn, int enabled);
+void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags);
typedef int (*tlsv1_client_session_ticket_cb)
(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
@@ -51,4 +51,12 @@ void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
tlsv1_client_session_ticket_cb cb,
void *ctx);
+void tlsv1_client_set_cb(struct tlsv1_client *conn,
+ void (*event_cb)(void *ctx, enum tls_event ev,
+ union tls_event_data *data),
+ void *cb_ctx,
+ int cert_in_cb);
+int tlsv1_client_get_version(struct tlsv1_client *conn, char *buf,
+ size_t buflen);
+
#endif /* TLSV1_CLIENT_H */
diff --git a/freebsd/contrib/wpa/src/tls/tlsv1_cred.h b/freebsd/contrib/wpa/src/tls/tlsv1_cred.h
index 68fbdc92..716e93c3 100644
--- a/freebsd/contrib/wpa/src/tls/tlsv1_cred.h
+++ b/freebsd/contrib/wpa/src/tls/tlsv1_cred.h
@@ -14,11 +14,19 @@ struct tlsv1_credentials {
struct x509_certificate *cert;
struct crypto_private_key *key;
+ unsigned int cert_probe:1;
+ unsigned int ca_cert_verify:1;
+ unsigned int server_cert_only:1;
+ u8 srv_cert_hash[32];
+
/* Diffie-Hellman parameters */
u8 *dh_p; /* prime */
size_t dh_p_len;
u8 *dh_g; /* generator */
size_t dh_g_len;
+
+ char *ocsp_stapling_response;
+ char *ocsp_stapling_response_multi;
};
diff --git a/freebsd/contrib/wpa/src/utils/common.c b/freebsd/contrib/wpa/src/utils/common.c
index 9665bd3c..4d414bfa 100644
--- a/freebsd/contrib/wpa/src/utils/common.c
+++ b/freebsd/contrib/wpa/src/utils/common.c
@@ -88,7 +88,7 @@ int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable)
return -1;
/* check for optional mask */
- if (*r == '\0' || isspace(*r)) {
+ if (*r == '\0' || isspace((unsigned char) *r)) {
/* no mask specified, assume default */
os_memset(mask, 0xff, ETH_ALEN);
} else if (maskable && *r == '/') {
@@ -500,7 +500,7 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
*txt++ = 't';
break;
default:
- if (data[i] >= 32 && data[i] <= 127) {
+ if (data[i] >= 32 && data[i] <= 126) {
*txt++ = data[i];
} else {
txt += os_snprintf(txt, end - txt, "\\x%02x",
@@ -699,6 +699,29 @@ int is_hex(const u8 *data, size_t len)
}
+int has_ctrl_char(const u8 *data, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (data[i] < 32 || data[i] == 127)
+ return 1;
+ }
+ return 0;
+}
+
+
+int has_newline(const char *str)
+{
+ while (*str) {
+ if (*str == '\n' || *str == '\r')
+ return 1;
+ str++;
+ }
+ return 0;
+}
+
+
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len)
@@ -980,7 +1003,7 @@ int random_mac_addr_keep_oui(u8 *addr)
* @delim: a string of delimiters
* @last: a pointer to a character following the returned token
* It has to be set to NULL for the first call and passed for any
- * futher call.
+ * further call.
* Returns: a pointer to token position in str or NULL
*
* This function is similar to str_token, but it can be used with both
@@ -1125,3 +1148,57 @@ int is_ctrl_char(char c)
{
return c > 0 && c < 32;
}
+
+
+/**
+ * ssid_parse - Parse a string that contains SSID in hex or text format
+ * @buf: Input NULL terminated string that contains the SSID
+ * @ssid: Output SSID
+ * Returns: 0 on success, -1 otherwise
+ *
+ * The SSID has to be enclosed in double quotes for the text format or space
+ * or NULL terminated string of hex digits for the hex format. buf can include
+ * additional arguments after the SSID.
+ */
+int ssid_parse(const char *buf, struct wpa_ssid_value *ssid)
+{
+ char *tmp, *res, *end;
+ size_t len;
+
+ ssid->ssid_len = 0;
+
+ tmp = os_strdup(buf);
+ if (!tmp)
+ return -1;
+
+ if (*tmp != '"') {
+ end = os_strchr(tmp, ' ');
+ if (end)
+ *end = '\0';
+ } else {
+ end = os_strchr(tmp + 1, '"');
+ if (!end) {
+ os_free(tmp);
+ return -1;
+ }
+
+ end[1] = '\0';
+ }
+
+ res = wpa_config_parse_string(tmp, &len);
+ if (res && len <= SSID_MAX_LEN) {
+ ssid->ssid_len = len;
+ os_memcpy(ssid->ssid, res, len);
+ }
+
+ os_free(tmp);
+ os_free(res);
+
+ return ssid->ssid_len ? 0 : -1;
+}
+
+
+int str_starts(const char *str, const char *start)
+{
+ return os_strncmp(str, start, os_strlen(start)) == 0;
+}
diff --git a/freebsd/contrib/wpa/src/utils/common.h b/freebsd/contrib/wpa/src/utils/common.h
index 0b9cc3d8..77856774 100644
--- a/freebsd/contrib/wpa/src/utils/common.h
+++ b/freebsd/contrib/wpa/src/utils/common.h
@@ -313,6 +313,9 @@ static inline void WPA_PUT_LE64(u8 *a, u64 val)
#ifndef ETH_P_ALL
#define ETH_P_ALL 0x0003
#endif
+#ifndef ETH_P_IP
+#define ETH_P_IP 0x0800
+#endif
#ifndef ETH_P_80211_ENCAP
#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */
#endif
@@ -416,6 +419,7 @@ void perror(const char *s);
*/
#ifdef __CHECKER__
#define __force __attribute__((force))
+#undef __bitwise
#define __bitwise __attribute__((bitwise))
#else
#define __force
@@ -445,6 +449,13 @@ typedef u64 __bitwise le64;
#endif /* __GNUC__ */
#endif /* __must_check */
+#define SSID_MAX_LEN 32
+
+struct wpa_ssid_value {
+ u8 ssid[SSID_MAX_LEN];
+ size_t ssid_len;
+};
+
int hwaddr_aton(const char *txt, u8 *addr);
int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable);
int hwaddr_compact_aton(const char *txt, u8 *addr);
@@ -461,6 +472,7 @@ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
size_t len);
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
+int ssid_parse(const char *buf, struct wpa_ssid_value *ssid);
#ifdef CONFIG_NATIVE_WINDOWS
void wpa_unicode2ascii_inplace(TCHAR *str);
@@ -477,6 +489,8 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
char * wpa_config_parse_string(const char *value, size_t *len);
int is_hex(const u8 *data, size_t len);
+int has_ctrl_char(const u8 *data, size_t len);
+int has_newline(const char *str);
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len);
@@ -536,6 +550,8 @@ size_t utf8_unescape(const char *inp, size_t in_size,
char *outp, size_t out_size);
int is_ctrl_char(char c);
+int str_starts(const char *str, const char *start);
+
/*
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
diff --git a/freebsd/contrib/wpa/src/utils/eloop.c b/freebsd/contrib/wpa/src/utils/eloop.c
index 5b1cc862..2ec86ff6 100644
--- a/freebsd/contrib/wpa/src/utils/eloop.c
+++ b/freebsd/contrib/wpa/src/utils/eloop.c
@@ -20,7 +20,12 @@
#error Do not define both of poll and epoll
#endif
-#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
+#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_KQUEUE)
+#error Do not define both of poll and kqueue
+#endif
+
+#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) && \
+ !defined(CONFIG_ELOOP_KQUEUE)
#define CONFIG_ELOOP_SELECT
#endif
@@ -32,6 +37,10 @@
#include <sys/epoll.h>
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+#include <sys/event.h>
+#endif /* CONFIG_ELOOP_KQUEUE */
+
struct eloop_sock {
int sock;
void *eloop_data;
@@ -77,13 +86,20 @@ struct eloop_data {
struct pollfd *pollfds;
struct pollfd **pollfds_map;
#endif /* CONFIG_ELOOP_POLL */
+#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
+ int max_fd;
+ struct eloop_sock *fd_table;
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
#ifdef CONFIG_ELOOP_EPOLL
int epollfd;
int epoll_max_event_num;
- int epoll_max_fd;
- struct eloop_sock *epoll_table;
struct epoll_event *epoll_events;
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ int kqueuefd;
+ int kqueue_nevents;
+ struct kevent *kqueue_events;
+#endif /* CONFIG_ELOOP_KQUEUE */
struct eloop_sock_table readers;
struct eloop_sock_table writers;
struct eloop_sock_table exceptions;
@@ -151,14 +167,24 @@ int eloop_init(void)
#ifdef CONFIG_ELOOP_EPOLL
eloop.epollfd = epoll_create1(0);
if (eloop.epollfd < 0) {
- wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
+ wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s",
+ __func__, strerror(errno));
+ return -1;
+ }
+#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ eloop.kqueuefd = kqueue();
+ if (eloop.kqueuefd < 0) {
+ wpa_printf(MSG_ERROR, "%s: kqueue failed: %s",
__func__, strerror(errno));
return -1;
}
+#endif /* CONFIG_ELOOP_KQUEUE */
+#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
eloop.readers.type = EVENT_TYPE_READ;
eloop.writers.type = EVENT_TYPE_WRITE;
eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
-#endif /* CONFIG_ELOOP_EPOLL */
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
#ifdef WPA_TRACE
signal(SIGSEGV, eloop_sigsegv_handler);
#endif /* WPA_TRACE */
@@ -166,15 +192,80 @@ int eloop_init(void)
}
+#ifdef CONFIG_ELOOP_EPOLL
+static int eloop_sock_queue(int sock, eloop_event_type type)
+{
+ struct epoll_event ev;
+
+ os_memset(&ev, 0, sizeof(ev));
+ switch (type) {
+ case EVENT_TYPE_READ:
+ ev.events = EPOLLIN;
+ break;
+ case EVENT_TYPE_WRITE:
+ ev.events = EPOLLOUT;
+ break;
+ /*
+ * Exceptions are always checked when using epoll, but I suppose it's
+ * possible that someone registered a socket *only* for exception
+ * handling.
+ */
+ case EVENT_TYPE_EXCEPTION:
+ ev.events = EPOLLERR | EPOLLHUP;
+ break;
+ }
+ ev.data.fd = sock;
+ if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
+ wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d failed: %s",
+ __func__, sock, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+#endif /* CONFIG_ELOOP_EPOLL */
+
+
+#ifdef CONFIG_ELOOP_KQUEUE
+static int eloop_sock_queue(int sock, eloop_event_type type)
+{
+ int filter;
+ struct kevent ke;
+
+ switch (type) {
+ case EVENT_TYPE_READ:
+ filter = EVFILT_READ;
+ break;
+ case EVENT_TYPE_WRITE:
+ filter = EVFILT_WRITE;
+ break;
+ default:
+ filter = 0;
+ }
+ EV_SET(&ke, sock, filter, EV_ADD, 0, 0, 0);
+ if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) {
+ wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s",
+ __func__, sock, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+#endif /* CONFIG_ELOOP_KQUEUE */
+
+
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
int sock, eloop_sock_handler handler,
void *eloop_data, void *user_data)
{
#ifdef CONFIG_ELOOP_EPOLL
+ struct epoll_event *temp_events;
+#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ struct kevent *temp_events;
+#endif /* CONFIG_ELOOP_EPOLL */
+#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
struct eloop_sock *temp_table;
- struct epoll_event ev, *temp_events;
int next;
-#endif /* CONFIG_ELOOP_EPOLL */
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
struct eloop_sock *tmp;
int new_max_sock;
@@ -210,26 +301,28 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
eloop.pollfds = n;
}
#endif /* CONFIG_ELOOP_POLL */
-#ifdef CONFIG_ELOOP_EPOLL
- if (new_max_sock >= eloop.epoll_max_fd) {
- next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
- temp_table = os_realloc_array(eloop.epoll_table, next,
+#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
+ if (new_max_sock >= eloop.max_fd) {
+ next = eloop.max_fd == 0 ? 16 : eloop.max_fd * 2;
+ temp_table = os_realloc_array(eloop.fd_table, next,
sizeof(struct eloop_sock));
if (temp_table == NULL)
return -1;
- eloop.epoll_max_fd = next;
- eloop.epoll_table = temp_table;
+ eloop.max_fd = next;
+ eloop.fd_table = temp_table;
}
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
+#ifdef CONFIG_ELOOP_EPOLL
if (eloop.count + 1 > eloop.epoll_max_event_num) {
next = eloop.epoll_max_event_num == 0 ? 8 :
eloop.epoll_max_event_num * 2;
temp_events = os_realloc_array(eloop.epoll_events, next,
sizeof(struct epoll_event));
if (temp_events == NULL) {
- wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
- "%s\n", __func__, strerror(errno));
+ wpa_printf(MSG_ERROR, "%s: malloc for epoll failed: %s",
+ __func__, strerror(errno));
return -1;
}
@@ -237,6 +330,22 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
eloop.epoll_events = temp_events;
}
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ if (eloop.count + 1 > eloop.kqueue_nevents) {
+ next = eloop.kqueue_nevents == 0 ? 8 : eloop.kqueue_nevents * 2;
+ temp_events = os_malloc(next * sizeof(*temp_events));
+ if (!temp_events) {
+ wpa_printf(MSG_ERROR,
+ "%s: malloc for kqueue failed: %s",
+ __func__, strerror(errno));
+ return -1;
+ }
+
+ os_free(eloop.kqueue_events);
+ eloop.kqueue_events = temp_events;
+ eloop.kqueue_nevents = next;
+ }
+#endif /* CONFIG_ELOOP_KQUEUE */
eloop_trace_sock_remove_ref(table);
tmp = os_realloc_array(table->table, table->count + 1,
@@ -258,33 +367,12 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
table->changed = 1;
eloop_trace_sock_add_ref(table);
-#ifdef CONFIG_ELOOP_EPOLL
- os_memset(&ev, 0, sizeof(ev));
- switch (table->type) {
- case EVENT_TYPE_READ:
- ev.events = EPOLLIN;
- break;
- case EVENT_TYPE_WRITE:
- ev.events = EPOLLOUT;
- break;
- /*
- * Exceptions are always checked when using epoll, but I suppose it's
- * possible that someone registered a socket *only* for exception
- * handling.
- */
- case EVENT_TYPE_EXCEPTION:
- ev.events = EPOLLERR | EPOLLHUP;
- break;
- }
- ev.data.fd = sock;
- if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
- wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
- "failed. %s\n", __func__, sock, strerror(errno));
+#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
+ if (eloop_sock_queue(sock, table->type) < 0)
return -1;
- }
- os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
+ os_memcpy(&eloop.fd_table[sock], &table->table[table->count - 1],
sizeof(struct eloop_sock));
-#endif /* CONFIG_ELOOP_EPOLL */
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
return 0;
}
@@ -292,6 +380,9 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
int sock)
{
+#ifdef CONFIG_ELOOP_KQUEUE
+ struct kevent ke;
+#endif /* CONFIG_ELOOP_KQUEUE */
int i;
if (table == NULL || table->table == NULL || table->count == 0)
@@ -315,12 +406,21 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
eloop_trace_sock_add_ref(table);
#ifdef CONFIG_ELOOP_EPOLL
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
- wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
- "failed. %s\n", __func__, sock, strerror(errno));
+ wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d failed: %s",
+ __func__, sock, strerror(errno));
return;
}
- os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
+ os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ EV_SET(&ke, sock, 0, EV_DELETE, 0, 0, 0);
+ if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) {
+ wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s",
+ __func__, sock, strerror(errno));
+ return;
+ }
+ os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
+#endif /* CONFIG_ELOOP_KQUEUE */
}
@@ -513,7 +613,7 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
int i;
for (i = 0; i < nfds; i++) {
- table = &eloop.epoll_table[events[i].data.fd];
+ table = &eloop.fd_table[events[i].data.fd];
if (table->handler == NULL)
continue;
table->handler(table->sock, table->eloop_data,
@@ -527,6 +627,67 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+
+static void eloop_sock_table_dispatch(struct kevent *events, int nfds)
+{
+ struct eloop_sock *table;
+ int i;
+
+ for (i = 0; i < nfds; i++) {
+ table = &eloop.fd_table[events[i].ident];
+ if (table->handler == NULL)
+ continue;
+ table->handler(table->sock, table->eloop_data,
+ table->user_data);
+ if (eloop.readers.changed ||
+ eloop.writers.changed ||
+ eloop.exceptions.changed)
+ break;
+ }
+}
+
+
+static int eloop_sock_table_requeue(struct eloop_sock_table *table)
+{
+ int i, r;
+
+ r = 0;
+ for (i = 0; i < table->count && table->table; i++) {
+ if (eloop_sock_queue(table->table[i].sock, table->type) == -1)
+ r = -1;
+ }
+ return r;
+}
+
+#endif /* CONFIG_ELOOP_KQUEUE */
+
+
+int eloop_sock_requeue(void)
+{
+ int r = 0;
+
+#ifdef CONFIG_ELOOP_KQUEUE
+ close(eloop.kqueuefd);
+ eloop.kqueuefd = kqueue();
+ if (eloop.kqueuefd < 0) {
+ wpa_printf(MSG_ERROR, "%s: kqueue failed: %s",
+ __func__, strerror(errno));
+ return -1;
+ }
+
+ if (eloop_sock_table_requeue(&eloop.readers) < 0)
+ r = -1;
+ if (eloop_sock_table_requeue(&eloop.writers) < 0)
+ r = -1;
+ if (eloop_sock_table_requeue(&eloop.exceptions) < 0)
+ r = -1;
+#endif /* CONFIG_ELOOP_KQUEUE */
+
+ return r;
+}
+
+
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
{
if (table) {
@@ -907,6 +1068,9 @@ void eloop_run(void)
#ifdef CONFIG_ELOOP_EPOLL
int timeout_ms = -1;
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ struct timespec ts;
+#endif /* CONFIG_ELOOP_KQUEUE */
int res;
struct os_reltime tv, now;
@@ -951,6 +1115,10 @@ void eloop_run(void)
_tv.tv_sec = tv.sec;
_tv.tv_usec = tv.usec;
#endif /* CONFIG_ELOOP_SELECT */
+#ifdef CONFIG_ELOOP_KQUEUE
+ ts.tv_sec = tv.sec;
+ ts.tv_nsec = tv.usec * 1000L;
+#endif /* CONFIG_ELOOP_KQUEUE */
}
#ifdef CONFIG_ELOOP_POLL
@@ -976,6 +1144,15 @@ void eloop_run(void)
eloop.count, timeout_ms);
}
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ if (eloop.count == 0) {
+ res = 0;
+ } else {
+ res = kevent(eloop.kqueuefd, NULL, 0,
+ eloop.kqueue_events, eloop.kqueue_nevents,
+ timeout ? &ts : NULL);
+ }
+#endif /* CONFIG_ELOOP_KQUEUE */
if (res < 0 && errno != EINTR && errno != 0) {
wpa_printf(MSG_ERROR, "eloop: %s: %s",
#ifdef CONFIG_ELOOP_POLL
@@ -987,6 +1164,10 @@ void eloop_run(void)
#ifdef CONFIG_ELOOP_EPOLL
"epoll"
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ "kqueue"
+#endif /* CONFIG_ELOOP_EKQUEUE */
+
, strerror(errno));
goto out;
}
@@ -997,6 +1178,7 @@ void eloop_run(void)
eloop_process_pending_signals();
+
/* check if some registered timeouts have occurred */
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
list);
@@ -1042,6 +1224,9 @@ void eloop_run(void)
#ifdef CONFIG_ELOOP_EPOLL
eloop_sock_table_dispatch(eloop.epoll_events, res);
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ eloop_sock_table_dispatch(eloop.kqueue_events, res);
+#endif /* CONFIG_ELOOP_KQUEUE */
}
eloop.terminate = 0;
@@ -1094,11 +1279,17 @@ void eloop_destroy(void)
os_free(eloop.pollfds);
os_free(eloop.pollfds_map);
#endif /* CONFIG_ELOOP_POLL */
+#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
+ os_free(eloop.fd_table);
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
#ifdef CONFIG_ELOOP_EPOLL
- os_free(eloop.epoll_table);
os_free(eloop.epoll_events);
close(eloop.epollfd);
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ os_free(eloop.kqueue_events);
+ close(eloop.kqueuefd);
+#endif /* CONFIG_ELOOP_KQUEUE */
}
@@ -1137,6 +1328,17 @@ void eloop_wait_for_read_sock(int sock)
FD_SET(sock, &rfds);
select(sock + 1, &rfds, NULL, NULL, NULL);
#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
+#ifdef CONFIG_ELOOP_KQUEUE
+ int kfd;
+ struct kevent ke1, ke2;
+
+ kfd = kqueue();
+ if (kfd == -1)
+ return;
+ EV_SET(&ke1, sock, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
+ kevent(kfd, &ke1, 1, &ke2, 1, NULL);
+ close(kfd);
+#endif /* CONFIG_ELOOP_KQUEUE */
}
#ifdef CONFIG_ELOOP_SELECT
diff --git a/freebsd/contrib/wpa/src/utils/eloop.h b/freebsd/contrib/wpa/src/utils/eloop.h
index 07b8c0dc..97af16f0 100644
--- a/freebsd/contrib/wpa/src/utils/eloop.h
+++ b/freebsd/contrib/wpa/src/utils/eloop.h
@@ -313,6 +313,14 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
void *user_data);
/**
+ * eloop_sock_requeue - Requeue sockets
+ *
+ * Requeue sockets after forking because some implementations require this,
+ * such as epoll and kqueue.
+ */
+int eloop_sock_requeue(void);
+
+/**
* eloop_run - Start the event loop
*
* Start the event loop and continue running as long as there are any
diff --git a/freebsd/contrib/wpa/src/utils/module_tests.h b/freebsd/contrib/wpa/src/utils/module_tests.h
new file mode 100644
index 00000000..3bfe4ad0
--- /dev/null
+++ b/freebsd/contrib/wpa/src/utils/module_tests.h
@@ -0,0 +1,20 @@
+/*
+ * Module tests
+ * Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MODULE_TESTS_H
+#define MODULE_TESTS_H
+
+int wpas_module_tests(void);
+int hapd_module_tests(void);
+
+int utils_module_tests(void);
+int wps_module_tests(void);
+int common_module_tests(void);
+int crypto_module_tests(void);
+
+#endif /* MODULE_TESTS_H */
diff --git a/freebsd/contrib/wpa/src/utils/os.h b/freebsd/contrib/wpa/src/utils/os.h
index 9e496fb6..e8f0b792 100644
--- a/freebsd/contrib/wpa/src/utils/os.h
+++ b/freebsd/contrib/wpa/src/utils/os.h
@@ -657,6 +657,10 @@ int os_exec(const char *program, const char *arg, int wait_completion);
#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
#define TEST_FAIL() testing_test_fail()
int testing_test_fail(void);
+extern char wpa_trace_fail_func[256];
+extern unsigned int wpa_trace_fail_after;
+extern char wpa_trace_test_fail_func[256];
+extern unsigned int wpa_trace_test_fail_after;
#else
#define TEST_FAIL() 0
#endif
diff --git a/freebsd/contrib/wpa/src/utils/os_unix.c b/freebsd/contrib/wpa/src/utils/os_unix.c
index 1c960e51..b5879dc8 100644
--- a/freebsd/contrib/wpa/src/utils/os_unix.c
+++ b/freebsd/contrib/wpa/src/utils/os_unix.c
@@ -411,6 +411,7 @@ void os_program_deinit(void)
if (total)
wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
(unsigned long) total);
+ wpa_trace_deinit();
#endif /* WPA_TRACE */
}
@@ -473,11 +474,7 @@ char * os_readfile(const char *name, size_t *len)
int os_file_exists(const char *fname)
{
- FILE *f = fopen(fname, "rb");
- if (f == NULL)
- return 0;
- fclose(f);
- return 1;
+ return access(fname, F_OK) == 0;
}
diff --git a/freebsd/contrib/wpa/src/utils/platform.h b/freebsd/contrib/wpa/src/utils/platform.h
index 46cfe785..813987eb 100644
--- a/freebsd/contrib/wpa/src/utils/platform.h
+++ b/freebsd/contrib/wpa/src/utils/platform.h
@@ -15,7 +15,7 @@
\
__ptr->__val; \
})
-#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((uint16_t *)(p)))
-#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((uint32_t *)(p)))
+#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((le16 *)(p)))
+#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((le32 *)(p)))
#endif /* PLATFORM_H */
diff --git a/freebsd/contrib/wpa/src/utils/trace.h b/freebsd/contrib/wpa/src/utils/trace.h
index 43ed86c1..d1636de0 100644
--- a/freebsd/contrib/wpa/src/utils/trace.h
+++ b/freebsd/contrib/wpa/src/utils/trace.h
@@ -66,4 +66,6 @@ void wpa_trace_dump_funcname(const char *title, void *pc);
#endif /* WPA_TRACE_BFD */
+void wpa_trace_deinit(void);
+
#endif /* TRACE_H */
diff --git a/freebsd/contrib/wpa/src/utils/wpa_debug.c b/freebsd/contrib/wpa/src/utils/wpa_debug.c
index 1b725ad5..68100490 100644
--- a/freebsd/contrib/wpa/src/utils/wpa_debug.c
+++ b/freebsd/contrib/wpa/src/utils/wpa_debug.c
@@ -150,7 +150,7 @@ int wpa_debug_open_linux_tracing(void)
strtok_r(line, " ", &tmp2);
tmp_path = strtok_r(NULL, " ", &tmp2);
fstype = strtok_r(NULL, " ", &tmp2);
- if (strcmp(fstype, "debugfs") == 0) {
+ if (fstype && strcmp(fstype, "debugfs") == 0) {
path = tmp_path;
break;
}
@@ -519,16 +519,18 @@ int wpa_debug_reopen_file(void)
{
#ifdef CONFIG_DEBUG_FILE
int rv;
- if (last_path) {
- char *tmp = os_strdup(last_path);
- wpa_debug_close_file();
- rv = wpa_debug_open_file(tmp);
- os_free(tmp);
- } else {
- wpa_printf(MSG_ERROR, "Last-path was not set, cannot "
- "re-open log file.");
- rv = -1;
- }
+ char *tmp;
+
+ if (!last_path)
+ return 0; /* logfile not used */
+
+ tmp = os_strdup(last_path);
+ if (!tmp)
+ return -1;
+
+ wpa_debug_close_file();
+ rv = wpa_debug_open_file(tmp);
+ os_free(tmp);
return rv;
#else /* CONFIG_DEBUG_FILE */
return 0;
diff --git a/freebsd/contrib/wpa/src/utils/wpabuf.c b/freebsd/contrib/wpa/src/utils/wpabuf.c
index c6e22aeb..26e2e8bb 100644
--- a/freebsd/contrib/wpa/src/utils/wpabuf.c
+++ b/freebsd/contrib/wpa/src/utils/wpabuf.c
@@ -312,3 +312,33 @@ void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
wpabuf_overflow(buf, res);
buf->used += res;
}
+
+
+/**
+ * wpabuf_parse_bin - Parse a null terminated string of binary data to a wpabuf
+ * @buf: Buffer with null terminated string (hexdump) of binary data
+ * Returns: wpabuf or %NULL on failure
+ *
+ * The string len must be a multiple of two and contain only hexadecimal digits.
+ */
+struct wpabuf * wpabuf_parse_bin(const char *buf)
+{
+ size_t len;
+ struct wpabuf *ret;
+
+ len = os_strlen(buf);
+ if (len & 0x01)
+ return NULL;
+ len /= 2;
+
+ ret = wpabuf_alloc(len);
+ if (ret == NULL)
+ return NULL;
+
+ if (hexstr2bin(buf, wpabuf_put(ret, len), len)) {
+ wpabuf_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
diff --git a/freebsd/contrib/wpa/src/utils/wpabuf.h b/freebsd/contrib/wpa/src/utils/wpabuf.h
index c3ef1bae..01da41b3 100644
--- a/freebsd/contrib/wpa/src/utils/wpabuf.h
+++ b/freebsd/contrib/wpa/src/utils/wpabuf.h
@@ -37,6 +37,7 @@ void * wpabuf_put(struct wpabuf *buf, size_t len);
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3);
+struct wpabuf * wpabuf_parse_bin(const char *buf);
/**
@@ -81,7 +82,7 @@ static inline const void * wpabuf_head(const struct wpabuf *buf)
static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf)
{
- return wpabuf_head(buf);
+ return (const u8 *) wpabuf_head(buf);
}
/**
@@ -96,42 +97,42 @@ static inline void * wpabuf_mhead(struct wpabuf *buf)
static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf)
{
- return wpabuf_mhead(buf);
+ return (u8 *) wpabuf_mhead(buf);
}
static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
{
- u8 *pos = wpabuf_put(buf, 1);
+ u8 *pos = (u8 *) wpabuf_put(buf, 1);
*pos = data;
}
static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data)
{
- u8 *pos = wpabuf_put(buf, 2);
+ u8 *pos = (u8 *) wpabuf_put(buf, 2);
WPA_PUT_LE16(pos, data);
}
static inline void wpabuf_put_le32(struct wpabuf *buf, u32 data)
{
- u8 *pos = wpabuf_put(buf, 4);
+ u8 *pos = (u8 *) wpabuf_put(buf, 4);
WPA_PUT_LE32(pos, data);
}
static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data)
{
- u8 *pos = wpabuf_put(buf, 2);
+ u8 *pos = (u8 *) wpabuf_put(buf, 2);
WPA_PUT_BE16(pos, data);
}
static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data)
{
- u8 *pos = wpabuf_put(buf, 3);
+ u8 *pos = (u8 *) wpabuf_put(buf, 3);
WPA_PUT_BE24(pos, data);
}
static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data)
{
- u8 *pos = wpabuf_put(buf, 4);
+ u8 *pos = (u8 *) wpabuf_put(buf, 4);
WPA_PUT_BE32(pos, data);
}
diff --git a/freebsd/contrib/wpa/src/wps/wps.c b/freebsd/contrib/wpa/src/wps/wps.c
index fb6d8f65..c0caca91 100644
--- a/freebsd/contrib/wpa/src/wps/wps.c
+++ b/freebsd/contrib/wpa/src/wps/wps.c
@@ -21,6 +21,10 @@
int wps_version_number = 0x20;
int wps_testing_dummy_cred = 0;
int wps_corrupt_pkhash = 0;
+int wps_force_auth_types_in_use = 0;
+u16 wps_force_auth_types = 0;
+int wps_force_encr_types_in_use = 0;
+u16 wps_force_encr_types = 0;
#endif /* CONFIG_WPS_TESTING */
@@ -172,7 +176,7 @@ void wps_deinit(struct wps_data *data)
} else if (data->registrar)
wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
- wpabuf_free(data->dh_privkey);
+ wpabuf_clear_free(data->dh_privkey);
wpabuf_free(data->dh_pubkey_e);
wpabuf_free(data->dh_pubkey_r);
wpabuf_free(data->last_msg);
diff --git a/freebsd/contrib/wpa/src/wps/wps.h b/freebsd/contrib/wpa/src/wps/wps.h
index 2c91d167..2505d2d9 100644
--- a/freebsd/contrib/wpa/src/wps/wps.h
+++ b/freebsd/contrib/wpa/src/wps/wps.h
@@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup
- * Copyright (c) 2007-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -664,6 +664,16 @@ struct wps_context {
u16 encr_types;
/**
+ * encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*)
+ */
+ u16 encr_types_rsn;
+
+ /**
+ * encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*)
+ */
+ u16 encr_types_wpa;
+
+ /**
* auth_types - Authentication types (bit field of WPS_AUTH_*)
*/
u16 auth_types;
@@ -827,7 +837,7 @@ int wps_build_credential_wrap(struct wpabuf *msg,
unsigned int wps_pin_checksum(unsigned int pin);
unsigned int wps_pin_valid(unsigned int pin);
-unsigned int wps_generate_pin(void);
+int wps_generate_pin(unsigned int *pin);
int wps_pin_str_valid(const char *pin);
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_build.c b/freebsd/contrib/wpa/src/wps/wps_attr_build.c
index 742e082c..e7083388 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_build.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_build.c
@@ -2,7 +2,7 @@
/*
* Wi-Fi Protected Setup - attribute building
- * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,10 +22,10 @@
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
{
- struct wpabuf *pubkey;
+ struct wpabuf *pubkey = NULL;
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
- wpabuf_free(wps->dh_privkey);
+ wpabuf_clear_free(wps->dh_privkey);
wps->dh_privkey = NULL;
if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
wps->wps->dh_ctx) {
@@ -300,7 +300,16 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
auth_types &= ~WPS_AUTH_WPA;
auth_types &= ~WPS_AUTH_WPA2;
auth_types &= ~WPS_AUTH_SHARED;
- wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags");
+#ifdef CONFIG_WPS_TESTING
+ if (wps_force_auth_types_in_use) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Testing - replace auth type 0x%x with 0x%x",
+ auth_types, wps_force_auth_types);
+ auth_types = wps_force_auth_types;
+ }
+#endif /* CONFIG_WPS_TESTING */
+ wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags (0x%x)",
+ auth_types);
wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
wpabuf_put_be16(msg, 2);
wpabuf_put_be16(msg, auth_types);
@@ -312,7 +321,16 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
{
u16 encr_types = WPS_ENCR_TYPES;
encr_types &= ~WPS_ENCR_WEP;
- wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags");
+#ifdef CONFIG_WPS_TESTING
+ if (wps_force_encr_types_in_use) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Testing - replace encr type 0x%x with 0x%x",
+ encr_types, wps_force_encr_types);
+ encr_types = wps_force_encr_types;
+ }
+#endif /* CONFIG_WPS_TESTING */
+ wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags (0x%x)",
+ encr_types);
wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
wpabuf_put_be16(msg, 2);
wpabuf_put_be16(msg, encr_types);
@@ -397,7 +415,8 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
dev_pw_id);
addr[0] = wpabuf_head(pubkey);
hash_len = wpabuf_len(pubkey);
- sha256_vector(1, addr, &hash_len, pubkey_hash);
+ if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0)
+ return -1;
#ifdef CONFIG_WPS_TESTING
if (wps_corrupt_pkhash) {
wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash",
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
index 748fe0ac..edcfb58b 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
@@ -85,10 +85,10 @@ static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
const u8 *end = pos + len;
u8 id, elen;
- while (pos + 2 <= end) {
+ while (end - pos >= 2) {
id = *pos++;
elen = *pos++;
- if (pos + elen > end)
+ if (elen > end - pos)
break;
if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
return -1;
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_process.c b/freebsd/contrib/wpa/src/wps/wps_attr_process.c
index 329649df..bf04d784 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_process.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_process.c
@@ -231,6 +231,16 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
cred->key_len--;
#endif /* CONFIG_WPS_STRICT */
}
+
+
+ if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
+ (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) {
+ wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase");
+ wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
+ cred->key, cred->key_len);
+ return -1;
+ }
+
return 0;
}
diff --git a/freebsd/contrib/wpa/src/wps/wps_common.c b/freebsd/contrib/wpa/src/wps/wps_common.c
index b6c83892..d7ac00b7 100644
--- a/freebsd/contrib/wpa/src/wps/wps_common.c
+++ b/freebsd/contrib/wpa/src/wps/wps_common.c
@@ -92,7 +92,7 @@ int wps_derive_keys(struct wps_data *wps)
}
/* Own DH private key is not needed anymore */
- wpabuf_free(wps->dh_privkey);
+ wpabuf_clear_free(wps->dh_privkey);
wps->dh_privkey = NULL;
wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
@@ -102,7 +102,7 @@ int wps_derive_keys(struct wps_data *wps)
len[0] = wpabuf_len(dh_shared);
sha256_vector(1, addr, len, dhkey);
wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
- wpabuf_free(dh_shared);
+ wpabuf_clear_free(dh_shared);
/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
addr[0] = wps->nonce_e;
@@ -131,23 +131,26 @@ int wps_derive_keys(struct wps_data *wps)
}
-void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
- size_t dev_passwd_len)
+int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
+ size_t dev_passwd_len)
{
u8 hash[SHA256_MAC_LEN];
- hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
- (dev_passwd_len + 1) / 2, hash);
+ if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
+ (dev_passwd_len + 1) / 2, hash) < 0)
+ return -1;
os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
- hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
- dev_passwd + (dev_passwd_len + 1) / 2,
- dev_passwd_len / 2, hash);
+ if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
+ dev_passwd + (dev_passwd_len + 1) / 2,
+ dev_passwd_len / 2, hash) < 0)
+ return -1;
os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
dev_passwd, dev_passwd_len);
wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
+ return 0;
}
@@ -175,7 +178,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
wpabuf_len(decrypted))) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
return NULL;
}
@@ -186,14 +189,14 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
pad = *pos;
if (pad > wpabuf_len(decrypted)) {
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
return NULL;
}
for (i = 0; i < pad; i++) {
if (*pos-- != pad) {
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
"string");
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
return NULL;
}
}
@@ -237,20 +240,18 @@ unsigned int wps_pin_valid(unsigned int pin)
* wps_generate_pin - Generate a random PIN
* Returns: Eight digit PIN (i.e., including the checksum digit)
*/
-unsigned int wps_generate_pin(void)
+int wps_generate_pin(unsigned int *pin)
{
unsigned int val;
/* Generate seven random digits for the PIN */
- if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
- struct os_time now;
- os_get_time(&now);
- val = os_random() ^ now.sec ^ now.usec;
- }
+ if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
+ return -1;
val %= 10000000;
/* Append checksum digit */
- return val * 10 + wps_pin_checksum(val);
+ *pin = val * 10 + wps_pin_checksum(val);
+ return 0;
}
@@ -377,7 +378,7 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
wps_build_mac_addr(plain, wps->dev.mac_addr) ||
wps_build_wfa_ext(plain, 0, NULL, 0)) {
os_free(data.new_psk);
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
return NULL;
}
@@ -425,7 +426,7 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
wps_build_wfa_ext(data, 0, NULL, 0)) {
wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
"token");
- wpabuf_free(data);
+ wpabuf_clear_free(data);
return NULL;
}
@@ -662,7 +663,7 @@ int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
wpabuf_free(*pubkey);
*pubkey = pub;
- wpabuf_free(*privkey);
+ wpabuf_clear_free(*privkey);
*privkey = priv;
return 0;
@@ -693,7 +694,7 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
}
*id = 0x10 + val % 0xfff0;
- wpabuf_free(*dev_pw);
+ wpabuf_clear_free(*dev_pw);
*dev_pw = pw;
return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
diff --git a/freebsd/contrib/wpa/src/wps/wps_defs.h b/freebsd/contrib/wpa/src/wps/wps_defs.h
index a23b979d..301864da 100644
--- a/freebsd/contrib/wpa/src/wps/wps_defs.h
+++ b/freebsd/contrib/wpa/src/wps/wps_defs.h
@@ -14,6 +14,10 @@
extern int wps_version_number;
extern int wps_testing_dummy_cred;
extern int wps_corrupt_pkhash;
+extern int wps_force_auth_types_in_use;
+extern u16 wps_force_auth_types;
+extern int wps_force_encr_types_in_use;
+extern u16 wps_force_encr_types;
#define WPS_VERSION wps_version_number
#else /* CONFIG_WPS_TESTING */
diff --git a/freebsd/contrib/wpa/src/wps/wps_enrollee.c b/freebsd/contrib/wpa/src/wps/wps_enrollee.c
index e2cfa571..2260b506 100644
--- a/freebsd/contrib/wpa/src/wps/wps_enrollee.c
+++ b/freebsd/contrib/wpa/src/wps/wps_enrollee.c
@@ -175,7 +175,8 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
return NULL;
}
- wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
+ if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0)
+ return NULL;
if (wps->wps->ap && random_pool_ready() != 1) {
wpa_printf(MSG_INFO,
@@ -226,11 +227,11 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->state = RECV_M6;
return msg;
@@ -396,11 +397,11 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
if (wps->wps->ap && wps->wps->registrar) {
/*
@@ -1009,11 +1010,11 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
eattr.key_wrap_auth) ||
wps_process_creds(wps, eattr.cred, eattr.cred_len,
eattr.num_cred, attr->version2 != NULL)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = WPS_MSG_DONE;
return WPS_CONTINUE;
@@ -1114,7 +1115,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps,
}
if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -1124,11 +1125,11 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps,
if (wps_parse_msg(decrypted, &eattr) < 0 ||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_r_snonce1(wps, eattr.r_snonce1)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_M5;
return WPS_CONTINUE;
@@ -1167,7 +1168,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
}
if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -1177,11 +1178,11 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
if (wps_parse_msg(decrypted, &eattr) < 0 ||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_r_snonce2(wps, eattr.r_snonce2)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
if (wps->wps->ap)
wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS,
@@ -1238,7 +1239,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps,
if (wps_validate_m8_encr(decrypted, wps->wps->ap,
attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -1251,11 +1252,11 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps,
eattr.num_cred, attr->version2 != NULL) ||
wps_process_ap_settings_e(wps, &eattr, decrypted,
attr->version2 != NULL)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = WPS_MSG_DONE;
return WPS_CONTINUE;
diff --git a/freebsd/contrib/wpa/src/wps/wps_i.h b/freebsd/contrib/wpa/src/wps/wps_i.h
index f7154f87..fe0c60bd 100644
--- a/freebsd/contrib/wpa/src/wps/wps_i.h
+++ b/freebsd/contrib/wpa/src/wps/wps_i.h
@@ -132,8 +132,8 @@ struct wps_data {
void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
const char *label, u8 *res, size_t res_len);
int wps_derive_keys(struct wps_data *wps);
-void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
- size_t dev_passwd_len);
+int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
+ size_t dev_passwd_len);
struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
size_t encr_len);
void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
diff --git a/freebsd/contrib/wpa/src/wps/wps_registrar.c b/freebsd/contrib/wpa/src/wps/wps_registrar.c
index 261b4557..803569ea 100644
--- a/freebsd/contrib/wpa/src/wps/wps_registrar.c
+++ b/freebsd/contrib/wpa/src/wps/wps_registrar.c
@@ -2,7 +2,7 @@
/*
* Wi-Fi Protected Setup - Registrar
- * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -705,7 +705,7 @@ void wps_registrar_deinit(struct wps_registrar *reg)
eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
wps_registrar_flush(reg);
- wpabuf_free(reg->extra_cred);
+ wpabuf_clear_free(reg->extra_cred);
os_free(reg);
}
@@ -1579,13 +1579,13 @@ int wps_build_credential_wrap(struct wpabuf *msg,
if (wbuf == NULL)
return -1;
if (wps_build_credential(wbuf, cred)) {
- wpabuf_free(wbuf);
+ wpabuf_clear_free(wbuf);
return -1;
}
wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(wbuf));
wpabuf_put_buf(msg, wbuf);
- wpabuf_free(wbuf);
+ wpabuf_clear_free(wbuf);
return 0;
}
@@ -1608,6 +1608,9 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
wps->cred.ssid_len = wps->wps->ssid_len;
/* Select the best authentication and encryption type */
+ wpa_printf(MSG_DEBUG,
+ "WPS: Own auth types 0x%x - masked Enrollee auth types 0x%x",
+ wps->wps->auth_types, wps->auth_type);
if (wps->auth_type & WPS_AUTH_WPA2PSK)
wps->auth_type = WPS_AUTH_WPA2PSK;
else if (wps->auth_type & WPS_AUTH_WPAPSK)
@@ -1621,6 +1624,14 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
}
wps->cred.auth_type = wps->auth_type;
+ wpa_printf(MSG_DEBUG,
+ "WPS: Own encr types 0x%x (rsn: 0x%x, wpa: 0x%x) - masked Enrollee encr types 0x%x",
+ wps->wps->encr_types, wps->wps->encr_types_rsn,
+ wps->wps->encr_types_wpa, wps->encr_type);
+ if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPA2PSK)
+ wps->encr_type &= wps->wps->encr_types_rsn;
+ else if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPAPSK)
+ wps->encr_type &= wps->wps->encr_types_wpa;
if (wps->auth_type == WPS_AUTH_WPA2PSK ||
wps->auth_type == WPS_AUTH_WPAPSK) {
if (wps->encr_type & WPS_ENCR_AES)
@@ -1742,14 +1753,14 @@ use_provided:
return -1;
if (wps_build_credential(cred, &wps->cred)) {
- wpabuf_free(cred);
+ wpabuf_clear_free(cred);
return -1;
}
wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(cred));
wpabuf_put_buf(msg, cred);
- wpabuf_free(cred);
+ wpabuf_clear_free(cred);
skip_cred_build:
if (wps->wps->registrar->extra_cred) {
@@ -1787,7 +1798,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
}
if (wps_build_ap_settings(wps, plain)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
@@ -1795,7 +1806,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(plain));
wpabuf_put_buf(msg, plain);
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
return msg;
}
@@ -1855,10 +1866,10 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain)) {
wpabuf_free(msg);
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
config_in_m2 = 1;
}
#endif /* CONFIG_WPS_NFC */
@@ -1919,7 +1930,8 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
wpa_printf(MSG_DEBUG, "WPS: Building Message M4");
- wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
+ if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0)
+ return NULL;
plain = wpabuf_alloc(200);
if (plain == NULL)
@@ -1940,11 +1952,11 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->state = RECV_M5;
return msg;
@@ -1975,11 +1987,11 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->wps_pin_revealed = 1;
wps->state = RECV_M7;
@@ -2012,11 +2024,11 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
- wpabuf_free(msg);
+ wpabuf_clear_free(plain);
+ wpabuf_clear_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->state = RECV_DONE;
return msg;
@@ -2345,6 +2357,23 @@ static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth)
wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
auth_types);
+#ifdef WPS_WORKAROUNDS
+ /*
+ * Some deployed implementations seem to advertise incorrect information
+ * in this attribute. A value of 0x1b (WPA2 + WPA + WPAPSK + OPEN, but
+ * no WPA2PSK) has been reported to be used. Add WPA2PSK to the list to
+ * avoid issues with building Credentials that do not use the strongest
+ * actually supported authentication option (that device does support
+ * WPA2PSK even when it does not claim it here).
+ */
+ if ((auth_types &
+ (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) ==
+ (WPS_AUTH_WPA2 | WPS_AUTH_WPAPSK)) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Workaround - assume Enrollee supports WPA2PSK based on claimed WPA2 support");
+ auth_types |= WPS_AUTH_WPA2PSK;
+ }
+#endif /* WPS_WORKAROUNDS */
wps->auth_type = wps->wps->auth_types & auth_types;
if (wps->auth_type == 0) {
wpa_printf(MSG_DEBUG, "WPS: No match in supported "
@@ -2759,7 +2788,7 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
}
if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -2769,11 +2798,11 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
if (wps_parse_msg(decrypted, &eattr) < 0 ||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_e_snonce1(wps, eattr.e_snonce1)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_M6;
return WPS_CONTINUE;
@@ -2911,7 +2940,7 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps,
if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er,
attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -2922,12 +2951,12 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps,
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_e_snonce2(wps, eattr.e_snonce2) ||
wps_process_ap_settings_r(wps, &eattr)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_M8;
return WPS_CONTINUE;
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp.c b/freebsd/contrib/wpa/src/wps/wps_upnp.c
index d66ca357..b69d2026 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp.c
@@ -1084,6 +1084,7 @@ upnp_wps_get_iface(struct upnp_wps_device_sm *sm, void *priv)
void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv)
{
struct upnp_wps_device_interface *iface;
+ struct upnp_wps_peer *peer;
if (!sm)
return;
@@ -1104,8 +1105,13 @@ void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv)
iface->wps->registrar);
dl_list_del(&iface->list);
- if (iface->peer.wps)
- wps_deinit(iface->peer.wps);
+ while ((peer = dl_list_first(&iface->peers, struct upnp_wps_peer,
+ list))) {
+ if (peer->wps)
+ wps_deinit(peer->wps);
+ dl_list_del(&peer->list);
+ os_free(peer);
+ }
os_free(iface->ctx->ap_pin);
os_free(iface->ctx);
os_free(iface);
@@ -1143,6 +1149,7 @@ upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
}
wpa_printf(MSG_DEBUG, "WPS UPnP: Init interface instance %p", iface);
+ dl_list_init(&iface->peers);
iface->ctx = ctx;
iface->wps = wps;
iface->priv = priv;
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp.h b/freebsd/contrib/wpa/src/wps/wps_upnp.h
index 87b7ab14..b6f6df5e 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp.h
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp.h
@@ -11,11 +11,14 @@
#ifndef WPS_UPNP_H
#define WPS_UPNP_H
+#include "utils/list.h"
+
struct upnp_wps_device_sm;
struct wps_context;
struct wps_data;
struct upnp_wps_peer {
+ struct dl_list list;
struct wps_data *wps;
};
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp_i.h b/freebsd/contrib/wpa/src/wps/wps_upnp_i.h
index f289fe68..6a7c6272 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp_i.h
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp_i.h
@@ -109,8 +109,7 @@ struct upnp_wps_device_interface {
struct wps_context *wps;
void *priv;
- /* FIX: maintain separate structures for each UPnP peer */
- struct upnp_wps_peer peer;
+ struct dl_list peers; /* active UPnP peer sessions */
};
/*
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c b/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c
index ed972494..4d1c8ed4 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c
@@ -102,12 +102,6 @@ static int line_length(const char *l)
}
-static int str_starts(const char *str, const char *start)
-{
- return os_strncmp(str, start, os_strlen(start)) == 0;
-}
-
-
/***************************************************************************
* Advertisements.
* These are multicast to the world to tell them we are here.
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp_web.c b/freebsd/contrib/wpa/src/wps/wps_upnp_web.c
index 8c3bbd1b..09f36d37 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp_web.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp_web.c
@@ -302,7 +302,8 @@ static void http_put_empty(struct wpabuf *buf, enum http_reply_code code)
* would appear to be required (given that we will be closing it!).
*/
static void web_connection_parse_get(struct upnp_wps_device_sm *sm,
- struct http_request *hreq, char *filename)
+ struct http_request *hreq,
+ const char *filename)
{
struct wpabuf *buf; /* output buffer, allocated */
char *put_length_here;
@@ -411,6 +412,15 @@ send_buf:
}
+static void wps_upnp_peer_del(struct upnp_wps_peer *peer)
+{
+ dl_list_del(&peer->list);
+ if (peer->wps)
+ wps_deinit(peer->wps);
+ os_free(peer);
+}
+
+
static enum http_reply_code
web_process_get_device_info(struct upnp_wps_device_sm *sm,
struct wpabuf **reply, const char **replyname)
@@ -428,7 +438,9 @@ web_process_get_device_info(struct upnp_wps_device_sm *sm,
if (!iface || iface->ctx->ap_pin == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
- peer = &iface->peer;
+ peer = os_zalloc(sizeof(*peer));
+ if (!peer)
+ return HTTP_INTERNAL_SERVER_ERROR;
/*
* Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS
@@ -438,9 +450,6 @@ web_process_get_device_info(struct upnp_wps_device_sm *sm,
* registration.
*/
- if (peer->wps)
- wps_deinit(peer->wps);
-
os_memset(&cfg, 0, sizeof(cfg));
cfg.wps = iface->wps;
cfg.pin = (u8 *) iface->ctx->ap_pin;
@@ -457,8 +466,22 @@ web_process_get_device_info(struct upnp_wps_device_sm *sm,
*reply = NULL;
if (*reply == NULL) {
wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo");
+ os_free(peer);
return HTTP_INTERNAL_SERVER_ERROR;
}
+
+ if (dl_list_len(&iface->peers) > 3) {
+ struct upnp_wps_peer *old;
+
+ old = dl_list_first(&iface->peers, struct upnp_wps_peer, list);
+ if (old) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop oldest active session");
+ wps_upnp_peer_del(old);
+ }
+ }
+ dl_list_add_tail(&iface->peers, &peer->list);
+ /* TODO: Could schedule a timeout to free the entry */
+
*replyname = name;
return HTTP_OK;
}
@@ -474,6 +497,8 @@ web_process_put_message(struct upnp_wps_device_sm *sm, char *data,
enum wps_process_res res;
enum wsc_op_code op_code;
struct upnp_wps_device_interface *iface;
+ struct wps_parse_attr attr;
+ struct upnp_wps_peer *tmp, *peer;
iface = dl_list_first(&sm->interfaces,
struct upnp_wps_device_interface, list);
@@ -489,11 +514,56 @@ web_process_put_message(struct upnp_wps_device_sm *sm, char *data,
msg = xml_get_base64_item(data, "NewInMessage", &ret);
if (msg == NULL)
return ret;
- res = wps_process_msg(iface->peer.wps, WSC_UPnP, msg);
- if (res == WPS_FAILURE)
+
+ if (wps_parse_msg(msg, &attr)) {
+ wpa_printf(MSG_DEBUG,
+ "WPS UPnP: Could not parse PutMessage - NewInMessage");
+ wpabuf_free(msg);
+ return HTTP_BAD_REQUEST;
+ }
+
+ /* Find a matching active peer session */
+ peer = NULL;
+ dl_list_for_each(tmp, &iface->peers, struct upnp_wps_peer, list) {
+ if (!tmp->wps)
+ continue;
+ if (attr.enrollee_nonce &&
+ os_memcmp(tmp->wps->nonce_e, attr.enrollee_nonce,
+ WPS_NONCE_LEN) != 0)
+ continue; /* Enrollee nonce mismatch */
+ if (attr.msg_type &&
+ *attr.msg_type != WPS_M2 &&
+ *attr.msg_type != WPS_M2D &&
+ attr.registrar_nonce &&
+ os_memcmp(tmp->wps->nonce_r, attr.registrar_nonce,
+ WPS_NONCE_LEN) != 0)
+ continue; /* Registrar nonce mismatch */
+ peer = tmp;
+ break;
+ }
+ if (!peer) {
+ /*
+ Try to use the first entry in case message could work with
+ * it. The actual handler function will reject this, if needed.
+ * This maintains older behavior where only a single peer entry
+ * was supported.
+ */
+ peer = dl_list_first(&iface->peers, struct upnp_wps_peer, list);
+ }
+ if (!peer || !peer->wps) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: No active peer entry found");
+ wpabuf_free(msg);
+ return HTTP_BAD_REQUEST;
+ }
+
+ res = wps_process_msg(peer->wps, WSC_UPnP, msg);
+ if (res == WPS_FAILURE) {
*reply = NULL;
- else
- *reply = wps_get_msg(iface->peer.wps, &op_code);
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop active peer session");
+ wps_upnp_peer_del(peer);
+ } else {
+ *reply = wps_get_msg(peer->wps, &op_code);
+ }
wpabuf_free(msg);
if (*reply == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ap.h b/freebsd/contrib/wpa/wpa_supplicant/ap.h
index 594168cf..5a59ddcc 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ap.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/ap.h
@@ -76,12 +76,16 @@ int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
const struct wpabuf *pw, const u8 *pubkey_hash);
struct hostapd_config;
-void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid,
- struct hostapd_config *conf);
+int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ struct hostapd_config *conf);
int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
+int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
+ size_t len);
+void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
+
void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
diff --git a/freebsd/contrib/wpa/wpa_supplicant/autoscan.h b/freebsd/contrib/wpa/wpa_supplicant/autoscan.h
index e2a76522..560684fc 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/autoscan.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/autoscan.h
@@ -27,6 +27,16 @@ void autoscan_deinit(struct wpa_supplicant *wpa_s);
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
+/* Available autoscan modules */
+
+#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
+extern const struct autoscan_ops autoscan_exponential_ops;
+#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
+
+#ifdef CONFIG_AUTOSCAN_PERIODIC
+extern const struct autoscan_ops autoscan_periodic_ops;
+#endif /* CONFIG_AUTOSCAN_PERIODIC */
+
#else /* CONFIG_AUTOSCAN */
static inline int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
diff --git a/freebsd/contrib/wpa/wpa_supplicant/bgscan.h b/freebsd/contrib/wpa/wpa_supplicant/bgscan.h
index 9131e4ec..3df1550a 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/bgscan.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/bgscan.h
@@ -39,6 +39,15 @@ void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
int current_signal, int current_noise,
int current_txrate);
+/* Available bgscan modules */
+
+#ifdef CONFIG_BGSCAN_SIMPLE
+extern const struct bgscan_ops bgscan_simple_ops;
+#endif /* CONFIG_BGSCAN_SIMPLE */
+#ifdef CONFIG_BGSCAN_LEARN
+extern const struct bgscan_ops bgscan_learn_ops;
+#endif /* CONFIG_BGSCAN_LEARN */
+
#else /* CONFIG_BGSCAN */
static inline int bgscan_init(struct wpa_supplicant *wpa_s,
diff --git a/freebsd/contrib/wpa/wpa_supplicant/binder/binder.h b/freebsd/contrib/wpa/wpa_supplicant/binder/binder.h
new file mode 100644
index 00000000..019e3275
--- /dev/null
+++ b/freebsd/contrib/wpa/wpa_supplicant/binder/binder.h
@@ -0,0 +1,46 @@
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_H
+#define WPA_SUPPLICANT_BINDER_BINDER_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif /* _cplusplus */
+
+/**
+ * This is the binder RPC interface entry point to the wpa_supplicant core.
+ * This initializes the binder driver & BinderManager instance and then forwards
+ * all the notifcations from the supplicant core to the BinderManager.
+ */
+struct wpas_binder_priv;
+struct wpa_global;
+
+struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global);
+void wpas_binder_deinit(struct wpas_binder_priv *priv);
+
+#ifdef CONFIG_CTRL_IFACE_BINDER
+int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
+#else /* CONFIG_CTRL_IFACE_BINDER */
+static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+#endif /* CONFIG_CTRL_IFACE_BINDER */
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/bss.c b/freebsd/contrib/wpa/wpa_supplicant/bss.c
index ff40bef0..4f805b1b 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/bss.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/bss.c
@@ -14,6 +14,7 @@
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
+#include "eap_peer/eap.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "notify.h"
@@ -62,6 +63,9 @@ struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
anqp = os_zalloc(sizeof(*anqp));
if (anqp == NULL)
return NULL;
+#ifdef CONFIG_INTERWORKING
+ dl_list_init(&anqp->anqp_elems);
+#endif /* CONFIG_INTERWORKING */
anqp->users = 1;
return anqp;
}
@@ -82,6 +86,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
#ifdef CONFIG_INTERWORKING
+ dl_list_init(&n->anqp_elems);
ANQP_DUP(capability_list);
ANQP_DUP(venue_name);
ANQP_DUP(network_auth_type);
@@ -143,6 +148,10 @@ int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss)
*/
static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
{
+#ifdef CONFIG_INTERWORKING
+ struct wpa_bss_anqp_elem *elem;
+#endif /* CONFIG_INTERWORKING */
+
if (anqp == NULL)
return;
@@ -161,6 +170,13 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->nai_realm);
wpabuf_free(anqp->anqp_3gpp);
wpabuf_free(anqp->domain_name);
+
+ while ((elem = dl_list_first(&anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list))) {
+ dl_list_del(&elem->list);
+ wpabuf_free(elem->payload);
+ os_free(elem);
+ }
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
wpabuf_free(anqp->hs20_capability_list);
@@ -200,8 +216,8 @@ static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s,
}
-static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- const char *reason)
+void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const char *reason)
{
if (wpa_s->last_scan_res) {
unsigned int i;
@@ -290,6 +306,47 @@ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
}
+static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+#ifdef CONFIG_WPS
+ struct wpa_ssid *ssid;
+ struct wpabuf *wps_ie;
+ int pbc = 0, ret;
+
+ wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
+ if (!wps_ie)
+ return 0;
+
+ if (wps_is_selected_pbc_registrar(wps_ie)) {
+ pbc = 1;
+ } else if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
+ wpabuf_free(wps_ie);
+ return 0;
+ }
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
+ continue;
+ if (ssid->ssid_len &&
+ (ssid->ssid_len != bss->ssid_len ||
+ os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 0))
+ continue;
+
+ if (pbc)
+ ret = eap_is_wps_pbc_enrollee(&ssid->eap);
+ else
+ ret = eap_is_wps_pin_enrollee(&ssid->eap);
+ wpabuf_free(wps_ie);
+ return ret;
+ }
+ wpabuf_free(wps_ie);
+#endif /* CONFIG_WPS */
+
+ return 0;
+}
+
+
static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
struct wpa_ssid *ssid;
@@ -328,7 +385,8 @@ static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
struct wpa_bss *bss;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (!wpa_bss_known(wpa_s, bss)) {
+ if (!wpa_bss_known(wpa_s, bss) &&
+ !wpa_bss_is_wps_candidate(wpa_s, bss)) {
wpa_bss_remove(wpa_s, bss, __func__);
return 0;
}
@@ -786,7 +844,7 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
struct wpa_bss *bss, *n;
os_get_reltime(&wpa_s->last_scan);
- if (!new_scan)
+ if ((info && info->aborted) || !new_scan)
return; /* do not expire entries without new scan */
dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
@@ -1006,20 +1064,7 @@ struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
*/
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
{
- const u8 *end, *pos;
-
- pos = (const u8 *) (bss + 1);
- end = pos + bss->ie_len;
-
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
- break;
- if (pos[0] == ie)
- return pos;
- pos += 2 + pos[1];
- }
-
- return NULL;
+ return get_ie((const u8 *) (bss + 1), bss->ie_len, ie);
}
@@ -1039,8 +1084,8 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
pos = (const u8 *) (bss + 1);
end = pos + bss->ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
@@ -1076,8 +1121,8 @@ const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
pos += bss->ie_len;
end = pos + bss->beacon_ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
@@ -1112,8 +1157,8 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
pos = (const u8 *) (bss + 1);
end = pos + bss->ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
@@ -1157,8 +1202,8 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
pos += bss->ie_len;
end = pos + bss->beacon_ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
diff --git a/freebsd/contrib/wpa/wpa_supplicant/bss.h b/freebsd/contrib/wpa/wpa_supplicant/bss.h
index b215380e..84e8fb07 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/bss.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/bss.h
@@ -19,6 +19,12 @@ struct wpa_scan_res;
#define WPA_BSS_ASSOCIATED BIT(5)
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
+struct wpa_bss_anqp_elem {
+ struct dl_list list;
+ u16 infoid;
+ struct wpabuf *payload;
+};
+
/**
* struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss)
*/
@@ -34,6 +40,7 @@ struct wpa_bss_anqp {
struct wpabuf *nai_realm;
struct wpabuf *anqp_3gpp;
struct wpabuf *domain_name;
+ struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
struct wpabuf *hs20_capability_list;
@@ -106,6 +113,8 @@ void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res,
struct os_reltime *fetch_time);
+void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const char *reason);
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
int new_scan);
int wpa_bss_init(struct wpa_supplicant *wpa_s);
@@ -141,6 +150,17 @@ static inline int bss_is_dmg(const struct wpa_bss *bss)
return bss->freq > 45000;
}
+/**
+ * Test whether a BSS is a PBSS.
+ * This checks whether a BSS is a DMG-band PBSS. PBSS is used for P2P DMG
+ * network.
+ */
+static inline int bss_is_pbss(struct wpa_bss *bss)
+{
+ return bss_is_dmg(bss) &&
+ (bss->caps & IEEE80211_CAP_DMG_MASK) == IEEE80211_CAP_DMG_PBSS;
+}
+
static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
{
if (bss != NULL && new_level < 0)
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config.c b/freebsd/contrib/wpa/wpa_supplicant/config.c
index 992ba83d..cf9da641 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/config.c
@@ -34,7 +34,11 @@ struct parse_data {
/* Configuration variable name */
char *name;
- /* Parser function for this variable */
+ /* Parser function for this variable. The parser functions return 0 or 1
+ * to indicate success. Value 0 indicates that the parameter value may
+ * have changed while value 1 means that the value did not change.
+ * Error cases (failure to parse the string) are indicated by returning
+ * -1. */
int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
int line, const char *value);
@@ -61,7 +65,7 @@ static int wpa_config_parse_str(const struct parse_data *data,
struct wpa_ssid *ssid,
int line, const char *value)
{
- size_t res_len, *dst_len;
+ size_t res_len, *dst_len, prev_len;
char **dst, *tmp;
if (os_strcmp(value, "NULL") == 0) {
@@ -107,6 +111,21 @@ static int wpa_config_parse_str(const struct parse_data *data,
set:
dst = (char **) (((u8 *) ssid) + (long) data->param1);
dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
+
+ if (data->param2)
+ prev_len = *dst_len;
+ else if (*dst)
+ prev_len = os_strlen(*dst);
+ else
+ prev_len = 0;
+ if ((*dst == NULL && tmp == NULL) ||
+ (*dst && tmp && prev_len == res_len &&
+ os_memcmp(*dst, tmp, res_len) == 0)) {
+ /* No change to the previously configured value */
+ os_free(tmp);
+ return 1;
+ }
+
os_free(*dst);
*dst = tmp;
if (data->param2)
@@ -192,6 +211,9 @@ static int wpa_config_parse_int(const struct parse_data *data,
line, value);
return -1;
}
+
+ if (*dst == val)
+ return 1;
*dst = val;
wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
@@ -458,9 +480,17 @@ static int wpa_config_parse_psk(const struct parse_data *data,
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
(u8 *) value, len);
+ if (has_ctrl_char((u8 *) value, len)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid passphrase character",
+ line);
+ return -1;
+ }
if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
- os_memcmp(ssid->passphrase, value, len) == 0)
- return 0;
+ os_memcmp(ssid->passphrase, value, len) == 0) {
+ /* No change to the previously configured value */
+ return 1;
+ }
ssid->psk_set = 0;
str_clear_free(ssid->passphrase);
ssid->passphrase = dup_binstr(value, len);
@@ -571,6 +601,8 @@ static int wpa_config_parse_proto(const struct parse_data *data,
errors++;
}
+ if (!errors && ssid->proto == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
ssid->proto = val;
return errors ? -1 : 0;
@@ -707,6 +739,8 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
errors++;
}
+ if (!errors && ssid->key_mgmt == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
ssid->key_mgmt = val;
return errors ? -1 : 0;
@@ -901,6 +935,9 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
static int wpa_config_parse_cipher(int line, const char *value)
{
+#ifdef CONFIG_NO_WPA
+ return -1;
+#else /* CONFIG_NO_WPA */
int val = wpa_parse_cipher(value);
if (val < 0) {
wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
@@ -913,12 +950,16 @@ static int wpa_config_parse_cipher(int line, const char *value)
return -1;
}
return val;
+#endif /* CONFIG_NO_WPA */
}
#ifndef NO_CONFIG_WRITE
static char * wpa_config_write_cipher(int cipher)
{
+#ifdef CONFIG_NO_WPA
+ return NULL;
+#else /* CONFIG_NO_WPA */
char *buf = os_zalloc(50);
if (buf == NULL)
return NULL;
@@ -929,6 +970,7 @@ static char * wpa_config_write_cipher(int cipher)
}
return buf;
+#endif /* CONFIG_NO_WPA */
}
#endif /* NO_CONFIG_WRITE */
@@ -947,6 +989,8 @@ static int wpa_config_parse_pairwise(const struct parse_data *data,
return -1;
}
+ if (ssid->pairwise_cipher == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
ssid->pairwise_cipher = val;
return 0;
@@ -983,6 +1027,8 @@ static int wpa_config_parse_group(const struct parse_data *data,
return -1;
}
+ if (ssid->group_cipher == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
ssid->group_cipher = val;
return 0;
@@ -1044,6 +1090,8 @@ static int wpa_config_parse_auth_alg(const struct parse_data *data,
errors++;
}
+ if (!errors && ssid->auth_alg == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
ssid->auth_alg = val;
return errors ? -1 : 0;
@@ -1298,6 +1346,32 @@ static int wpa_config_parse_eap(const struct parse_data *data,
methods[num_methods].method = EAP_TYPE_NONE;
num_methods++;
+ if (!errors && ssid->eap.eap_methods) {
+ struct eap_method_type *prev_m;
+ size_t i, j, prev_methods, match = 0;
+
+ prev_m = ssid->eap.eap_methods;
+ for (i = 0; prev_m[i].vendor != EAP_VENDOR_IETF ||
+ prev_m[i].method != EAP_TYPE_NONE; i++) {
+ /* Count the methods */
+ }
+ prev_methods = i + 1;
+
+ for (i = 0; prev_methods == num_methods && i < prev_methods;
+ i++) {
+ for (j = 0; j < num_methods; j++) {
+ if (prev_m[i].vendor == methods[j].vendor &&
+ prev_m[i].method == methods[j].method) {
+ match++;
+ break;
+ }
+ }
+ }
+ if (match == num_methods) {
+ os_free(methods);
+ return 1;
+ }
+ }
wpa_hexdump(MSG_MSGDUMP, "eap methods",
(u8 *) methods, num_methods * sizeof(*methods));
os_free(ssid->eap.eap_methods);
@@ -1350,6 +1424,8 @@ static int wpa_config_parse_password(const struct parse_data *data,
u8 *hash;
if (os_strcmp(value, "NULL") == 0) {
+ if (!ssid->eap.password)
+ return 1; /* Already unset */
wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = NULL;
@@ -1413,6 +1489,12 @@ static int wpa_config_parse_password(const struct parse_data *data,
wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
+ if (ssid->eap.password && ssid->eap.password_len == 16 &&
+ os_memcmp(ssid->eap.password, hash, 16) == 0 &&
+ (ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
+ bin_clear_free(hash, 16);
+ return 1;
+ }
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = hash;
ssid->eap.password_len = 16;
@@ -1839,6 +1921,8 @@ static const struct parse_data ssid_fields[] = {
{ FUNC(auth_alg) },
{ FUNC(scan_freq) },
{ FUNC(freq_list) },
+ { INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT,
+ VHT_CHANWIDTH_80P80MHZ) },
#ifdef IEEE8021X_EAPOL
{ FUNC(eap) },
{ STR_LENe(identity) },
@@ -1912,6 +1996,9 @@ static const struct parse_data ssid_fields[] = {
{ INT_RANGE(mixed_cell, 0, 1) },
{ INT_RANGE(frequency, 0, 65000) },
{ INT_RANGE(fixed_freq, 0, 1) },
+#ifdef CONFIG_ACS
+ { INT_RANGE(acs, 0, 1) },
+#endif /* CONFIG_ACS */
#ifdef CONFIG_MESH
{ FUNC(mesh_basic_rates) },
{ INT(dot11MeshMaxRetries) },
@@ -1920,6 +2007,7 @@ static const struct parse_data ssid_fields[] = {
{ INT(dot11MeshHoldingTimeout) },
#endif /* CONFIG_MESH */
{ INT(wpa_ptk_rekey) },
+ { INT(group_rekey) },
{ STR(bgscan) },
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
#ifdef CONFIG_P2P
@@ -1969,6 +2057,8 @@ static const struct parse_data ssid_fields[] = {
{ INT(update_identifier) },
#endif /* CONFIG_HS20 */
{ INT_RANGE(mac_addr, 0, 2) },
+ { INT_RANGE(pbss, 0, 2) },
+ { INT_RANGE(wps_disabled, 0, 1) },
};
#undef OFFSET
@@ -2273,6 +2363,11 @@ void wpa_config_free(struct wpa_config *config)
os_free(config->bgscan);
os_free(config->wowlan_triggers);
os_free(config->fst_group_id);
+ os_free(config->sched_scan_plans);
+#ifdef CONFIG_MBO
+ os_free(config->non_pref_chan);
+#endif /* CONFIG_MBO */
+
os_free(config);
}
@@ -2455,7 +2550,8 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
* @var: Variable name, e.g., "ssid"
* @value: Variable value
* @line: Line number in configuration file or 0 if not used
- * Returns: 0 on success, -1 on failure
+ * Returns: 0 on success with possible change in the value, 1 on success with
+ * no change to previously configured value, or -1 on failure
*
* This function can be used to set network configuration variables based on
* both the configuration file and management interface input. The value
@@ -2476,7 +2572,8 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
if (os_strcmp(var, field->name) != 0)
continue;
- if (field->parser(field, ssid, line, value)) {
+ ret = field->parser(field, ssid, line, value);
+ if (ret < 0) {
if (line) {
wpa_printf(MSG_ERROR, "Line %d: failed to "
"parse %s '%s'.", line, var, value);
@@ -2575,9 +2672,8 @@ char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
return props;
err:
- value = *props;
- while (value)
- os_free(value++);
+ for (i = 0; props[i]; i++)
+ os_free(props[i]);
os_free(props);
return NULL;
#endif /* NO_CONFIG_WRITE */
@@ -2606,8 +2702,19 @@ char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
for (i = 0; i < NUM_SSID_FIELDS; i++) {
const struct parse_data *field = &ssid_fields[i];
- if (os_strcmp(var, field->name) == 0)
- return field->writer(field, ssid);
+ if (os_strcmp(var, field->name) == 0) {
+ char *ret = field->writer(field, ssid);
+
+ if (ret && has_newline(ret)) {
+ wpa_printf(MSG_ERROR,
+ "Found newline in value for %s; not returning it",
+ var);
+ os_free(ret);
+ ret = NULL;
+ }
+
+ return ret;
+ }
}
return NULL;
@@ -2792,6 +2899,8 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
if (os_strcmp(var, "password") == 0 &&
os_strncmp(value, "ext:", 4) == 0) {
+ if (has_newline(value))
+ return -1;
str_clear_free(cred->password);
cred->password = os_strdup(value);
cred->ext_password = 1;
@@ -2842,9 +2951,14 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
}
val = wpa_config_parse_string(value, &len);
- if (val == NULL) {
+ if (val == NULL ||
+ (os_strcmp(var, "excluded_ssid") != 0 &&
+ os_strcmp(var, "roaming_consortium") != 0 &&
+ os_strcmp(var, "required_roaming_consortium") != 0 &&
+ has_newline(val))) {
wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
"value '%s'.", line, var, value);
+ os_free(val);
return -1;
}
@@ -3542,6 +3656,11 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
config->cert_in_cb = DEFAULT_CERT_IN_CB;
+ config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION;
+
+#ifdef CONFIG_MBO
+ config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
+#endif /* CONFIG_MBO */
if (ctrl_interface)
config->ctrl_interface = os_strdup(ctrl_interface);
@@ -3648,6 +3767,12 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data,
return -1;
}
+ if (has_newline(pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
+ line, data->name);
+ return -1;
+ }
+
tmp = os_strdup(pos);
if (tmp == NULL)
return -1;
@@ -3686,22 +3811,12 @@ static int wpa_global_config_parse_bin(const struct global_parse_data *data,
struct wpa_config *config, int line,
const char *pos)
{
- size_t len;
struct wpabuf **dst, *tmp;
- len = os_strlen(pos);
- if (len & 0x01)
- return -1;
-
- tmp = wpabuf_alloc(len / 2);
- if (tmp == NULL)
+ tmp = wpabuf_parse_bin(pos);
+ if (!tmp)
return -1;
- if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) {
- wpabuf_free(tmp);
- return -1;
- }
-
dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
wpabuf_free(*dst);
*dst = tmp;
@@ -4248,6 +4363,16 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
#endif /* CONFIG_FST */
+ { INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
+ { STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS },
+#ifdef CONFIG_MBO
+ { STR(non_pref_chan), 0 },
+ { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE,
+ MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
+#endif /*CONFIG_MBO */
+ { INT(gas_address3), 0 },
+ { INT_RANGE(ftm_responder, 0, 1), 0 },
+ { INT_RANGE(ftm_initiator, 0, 1), 0 },
};
#undef FUNC
@@ -4306,6 +4431,23 @@ int wpa_config_get_value(const char *name, struct wpa_config *config,
}
+int wpa_config_get_num_global_field_names(void)
+{
+ return NUM_GLOBAL_FIELDS;
+}
+
+
+const char * wpa_config_get_global_field_name(unsigned int i, int *no_var)
+{
+ if (i >= NUM_GLOBAL_FIELDS)
+ return NULL;
+
+ if (no_var)
+ *no_var = !global_fields[i].param1;
+ return global_fields[i].name;
+}
+
+
int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
{
size_t i;
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config.h b/freebsd/contrib/wpa/wpa_supplicant/config.h
index 9de7e704..9d41fd17 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/config.h
@@ -39,6 +39,8 @@
#define DEFAULT_KEY_MGMT_OFFLOAD 1
#define DEFAULT_CERT_IN_CB 1
#define DEFAULT_P2P_GO_CTWINDOW 0
+#define DEFAULT_WPA_RSC_RELAXATION 1
+#define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED
#include "config_ssid.h"
#include "wps/wps.h"
@@ -334,6 +336,7 @@ struct wpa_cred {
#define CFG_CHANGED_EXT_PW_BACKEND BIT(14)
#define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15)
#define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16)
+#define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17)
/**
* struct wpa_config - wpa_supplicant configuration data
@@ -764,12 +767,17 @@ struct wpa_config {
* frequency list of the local device and the peer device.
*
* @P2P_GO_FREQ_MOVE_STAY: Prefer to stay on the current frequency.
+ *
+ * @P2P_GO_FREQ_MOVE_SCM_ECSA: Same as
+ * P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS but a transition is possible only
+ * if all the group members advertise eCSA support.
*/
enum {
P2P_GO_FREQ_MOVE_SCM = 0,
P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS = 1,
P2P_GO_FREQ_MOVE_STAY = 2,
- P2P_GO_FREQ_MOVE_MAX = P2P_GO_FREQ_MOVE_STAY,
+ P2P_GO_FREQ_MOVE_SCM_ECSA = 3,
+ P2P_GO_FREQ_MOVE_MAX = P2P_GO_FREQ_MOVE_SCM_ECSA,
} p2p_go_freq_change_policy;
#define DEFAULT_P2P_GO_FREQ_MOVE P2P_GO_FREQ_MOVE_STAY
@@ -1034,7 +1042,8 @@ struct wpa_config {
*
* By default, PMF is disabled unless enabled by the per-network
* ieee80211w=1 or ieee80211w=2 parameter. pmf=1/2 can be used to change
- * this default behavior.
+ * this default behavior for RSN network (this is not applicable for
+ * non-RSN cases).
*/
enum mfp_options pmf;
@@ -1250,6 +1259,78 @@ struct wpa_config {
* interface.
*/
int fst_llt;
+
+ /**
+ * wpa_rsc_relaxation - RSC relaxation on GTK installation
+ *
+ * Values:
+ * 0 - use the EAPOL-Key RSC value on GTK installation
+ * 1 - use the null RSC if a bogus RSC value is detected in message 3
+ * of 4-Way Handshake or message 1 of Group Key Handshake.
+ */
+ int wpa_rsc_relaxation;
+
+ /**
+ * sched_scan_plans - Scan plans for scheduled scan
+ *
+ * Each scan plan specifies the interval between scans and the number of
+ * iterations. The last scan plan only specifies the scan interval and
+ * will be run infinitely.
+ *
+ * format: <interval:iterations> <interval2:iterations2> ... <interval>
+ */
+ char *sched_scan_plans;
+
+#ifdef CONFIG_MBO
+ /**
+ * non_pref_chan - Non-preferred channels list, separated by spaces.
+ *
+ * format: op_class:chan:preference:reason<:detail>
+ * Detail is optional.
+ */
+ char *non_pref_chan;
+
+ /**
+ * mbo_cell_capa - Cellular capabilities for MBO
+ */
+ enum mbo_cellular_capa mbo_cell_capa;
+#endif /* CONFIG_MBO */
+
+ /**
+ * gas_address3 - GAS Address3 field behavior
+ *
+ * Values:
+ * 0 - P2P specification (Address3 = AP BSSID)
+ * 1 = IEEE 802.11 standard compliant (Address3 = Wildcard BSSID when
+ * sent to not-associated AP; if associated, AP BSSID)
+ */
+ int gas_address3;
+
+ /**
+ * ftm_responder - Publish FTM (fine timing measurement)
+ * responder functionality
+ *
+ * Values:
+ * 0 - do not publish FTM responder functionality (Default)
+ * 1 - publish FTM responder functionality in
+ * bit 70 of Extended Capabilities element
+ * Note, actual FTM responder operation is managed outside
+ * wpa_supplicant.
+ */
+ int ftm_responder;
+
+ /**
+ * ftm_initiator - Publish FTM (fine timing measurement)
+ * initiator functionality
+ *
+ * Values:
+ * 0 - do not publish FTM initiator functionality (Default)
+ * 1 - publish FTM initiator functionality in
+ * bit 71 of Extended Capabilities element
+ * Note, actual FTM initiator operation is managed outside
+ * wpa_supplicant.
+ */
+ int ftm_initiator;
};
@@ -1308,6 +1389,9 @@ void wpa_config_debug_dump_networks(struct wpa_config *config);
/* Prototypes for common functions from config.c */
int wpa_config_process_global(struct wpa_config *config, char *pos, int line);
+int wpa_config_get_num_global_field_names(void);
+
+const char * wpa_config_get_global_field_name(unsigned int i, int *no_var);
/* Prototypes for backend specific functions from the selected config_*.c */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config_file.c b/freebsd/contrib/wpa/wpa_supplicant/config_file.c
index 8466fc39..09df6c14 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config_file.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/config_file.c
@@ -749,10 +749,16 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(no_auto_peer);
INT(frequency);
INT(fixed_freq);
+#ifdef CONFIG_ACS
+ INT(acs);
+#endif /* CONFIG_ACS */
write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
INT(disabled);
INT(peerkey);
INT(mixed_cell);
+ INT(max_oper_chwidth);
+ INT(pbss);
+ INT(wps_disabled);
#ifdef CONFIG_IEEE80211W
write_int(f, "ieee80211w", ssid->ieee80211w,
MGMT_FRAME_PROTECTION_DEFAULT);
@@ -781,6 +787,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
#endif /* CONFIG_MESH */
INT(wpa_ptk_rekey);
+ INT(group_rekey);
INT(ignore_broadcast_ssid);
#ifdef CONFIG_HT_OVERRIDES
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
@@ -1138,6 +1145,22 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE)
fprintf(f, "p2p_go_freq_change_policy=%u\n",
config->p2p_go_freq_change_policy);
+ if (WPA_GET_BE32(config->ip_addr_go))
+ fprintf(f, "ip_addr_go=%u.%u.%u.%u\n",
+ config->ip_addr_go[0], config->ip_addr_go[1],
+ config->ip_addr_go[2], config->ip_addr_go[3]);
+ if (WPA_GET_BE32(config->ip_addr_mask))
+ fprintf(f, "ip_addr_mask=%u.%u.%u.%u\n",
+ config->ip_addr_mask[0], config->ip_addr_mask[1],
+ config->ip_addr_mask[2], config->ip_addr_mask[3]);
+ if (WPA_GET_BE32(config->ip_addr_start))
+ fprintf(f, "ip_addr_start=%u.%u.%u.%u\n",
+ config->ip_addr_start[0], config->ip_addr_start[1],
+ config->ip_addr_start[2], config->ip_addr_start[3]);
+ if (WPA_GET_BE32(config->ip_addr_end))
+ fprintf(f, "ip_addr_end=%u.%u.%u.%u\n",
+ config->ip_addr_end[0], config->ip_addr_end[1],
+ config->ip_addr_end[2], config->ip_addr_end[3]);
#endif /* CONFIG_P2P */
if (config->country[0] && config->country[1]) {
fprintf(f, "country=%c%c\n",
@@ -1301,6 +1324,28 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->wps_priority)
fprintf(f, "wps_priority=%d\n", config->wps_priority);
+
+ if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION)
+ fprintf(f, "wpa_rsc_relaxation=%d\n",
+ config->wpa_rsc_relaxation);
+
+ if (config->sched_scan_plans)
+ fprintf(f, "sched_scan_plans=%s\n", config->sched_scan_plans);
+
+#ifdef CONFIG_MBO
+ if (config->non_pref_chan)
+ fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan);
+ if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA)
+ fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa);
+#endif /* CONFIG_MBO */
+
+ if (config->gas_address3)
+ fprintf(f, "gas_address3=%d\n", config->gas_address3);
+
+ if (config->ftm_responder)
+ fprintf(f, "ftm_responder=%d\n", config->ftm_responder);
+ if (config->ftm_initiator)
+ fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h b/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h
index 7ef326cf..010b594a 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h
@@ -360,6 +360,19 @@ struct wpa_ssid {
} mode;
/**
+ * pbss - Whether to use PBSS. Relevant to DMG networks only.
+ * 0 = do not use PBSS
+ * 1 = use PBSS
+ * 2 = don't care (not allowed in AP mode)
+ * Used together with mode configuration. When mode is AP, it
+ * means to start a PCP instead of a regular AP. When mode is INFRA it
+ * means connect to a PCP instead of AP. In this mode you can also
+ * specify 2 (don't care) meaning connect to either AP or PCP.
+ * P2P_GO and P2P_GROUP_FORMATION modes must use PBSS in DMG network.
+ */
+ int pbss;
+
+ /**
* disabled - Whether this network is currently disabled
*
* 0 = this network can be used (default).
@@ -431,6 +444,18 @@ struct wpa_ssid {
*/
int fixed_freq;
+#ifdef CONFIG_ACS
+ /**
+ * ACS - Automatic Channel Selection for AP mode
+ *
+ * If present, it will be handled together with frequency.
+ * frequency will be used to determine hardware mode only, when it is
+ * used for both hardware mode and channel when used alone. This will
+ * force the channel to be set to 0, thus enabling ACS.
+ */
+ int acs;
+#endif /* CONFIG_ACS */
+
/**
* mesh_basic_rates - BSS Basic rate set for mesh network
*
@@ -449,6 +474,10 @@ struct wpa_ssid {
int vht;
+ u8 max_oper_chwidth;
+
+ unsigned int vht_center_freq2;
+
/**
* wpa_ptk_rekey - Maximum lifetime for PTK in seconds
*
@@ -458,6 +487,14 @@ struct wpa_ssid {
int wpa_ptk_rekey;
/**
+ * group_rekey - Group rekeying time in seconds
+ *
+ * This value, if non-zero, is used as the dot11RSNAConfigGroupRekeyTime
+ * parameter when operating in Authenticator role in IBSS.
+ */
+ int group_rekey;
+
+ /**
* scan_freq - Array of frequencies to scan or %NULL for all
*
* This is an optional zero-terminated array of frequencies in
@@ -719,6 +756,14 @@ struct wpa_ssid {
* this MBSS will trigger a peering attempt.
*/
int no_auto_peer;
+
+ /**
+ * wps_disabled - WPS disabled in AP mode
+ *
+ * 0 = WPS enabled and configured (default)
+ * 1 = WPS disabled
+ */
+ int wps_disabled;
};
#endif /* CONFIG_SSID_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c
index d540fc8c..9699c784 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c
@@ -17,6 +17,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/uuid.h"
+#include "utils/module_tests.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
@@ -57,6 +58,7 @@
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
+ const char *input,
char *buf, int len);
static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
char *val);
@@ -312,6 +314,33 @@ static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
}
+static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *lci;
+
+ if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
+ wpabuf_free(wpa_s->lci);
+ wpa_s->lci = NULL;
+ return 0;
+ }
+
+ lci = wpabuf_parse_bin(cmd);
+ if (!lci)
+ return -1;
+
+ if (os_get_reltime(&wpa_s->lci_time)) {
+ wpabuf_free(lci);
+ return -1;
+ }
+
+ wpabuf_free(wpa_s->lci);
+ wpa_s->lci = lci;
+
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
@@ -373,6 +402,20 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
wps_corrupt_pkhash = atoi(value);
wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
wps_corrupt_pkhash);
+ } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
+ if (value[0] == '\0') {
+ wps_force_auth_types_in_use = 0;
+ } else {
+ wps_force_auth_types = strtol(value, NULL, 0);
+ wps_force_auth_types_in_use = 1;
+ }
+ } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
+ if (value[0] == '\0') {
+ wps_force_encr_types_in_use = 0;
+ } else {
+ wps_force_encr_types = strtol(value, NULL, 0);
+ wps_force_encr_types_in_use = 1;
+ }
#endif /* CONFIG_WPS_TESTING */
} else if (os_strcasecmp(cmd, "ampdu") == 0) {
if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
@@ -380,7 +423,6 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
- extern unsigned int tdls_testing;
tdls_testing = strtol(value, NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
#endif /* CONFIG_TDLS_TESTING */
@@ -469,6 +511,14 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
wpa_s->extra_roc_dur = atoi(value);
} else if (os_strcasecmp(cmd, "test_failure") == 0) {
wpa_s->test_failure = atoi(value);
+ } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
+ wpa_s->p2p_go_csa_on_inv = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
+ wpa_s->ignore_auth_resp = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
+ wpa_s->ignore_assoc_disallow = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
+ wpa_s->reject_btm_req_reason = atoi(value);
#endif /* CONFIG_TESTING_OPTIONS */
#ifndef CONFIG_NO_CONFIG_BLOBS
} else if (os_strcmp(cmd, "blob") == 0) {
@@ -476,6 +526,14 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_CONFIG_BLOBS */
} else if (os_strcasecmp(cmd, "setband") == 0) {
ret = wpas_ctrl_set_band(wpa_s, value);
+#ifdef CONFIG_MBO
+ } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
+ ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
+ wpas_mbo_update_cell_capa(wpa_s, atoi(value));
+#endif /* CONFIG_MBO */
+ } else if (os_strcasecmp(cmd, "lci") == 0) {
+ ret = wpas_ctrl_iface_set_lci(wpa_s, value);
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -942,7 +1000,8 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
if (os_strcmp(cmd, "any") == 0)
_bssid = NULL;
else if (os_strcmp(cmd, "get") == 0) {
- ret = wps_generate_pin();
+ if (wps_generate_pin((unsigned int *) &ret) < 0)
+ return -1;
goto done;
} else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
@@ -1835,6 +1894,10 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
"mode=P2P GO - group "
"formation\n");
break;
+ case WPAS_MODE_MESH:
+ ret = os_snprintf(pos, end - pos,
+ "mode=mesh\n");
+ break;
default:
ret = 0;
break;
@@ -2705,6 +2768,40 @@ static int wpa_supplicant_ctrl_iface_mesh_group_remove(
return 0;
}
+
+static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 addr[ETH_ALEN];
+
+ if (hwaddr_aton(cmd, addr) < 0)
+ return -1;
+
+ return wpas_mesh_peer_remove(wpa_s, addr);
+}
+
+
+static int wpa_supplicant_ctrl_iface_mesh_peer_add(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ int duration;
+ char *pos;
+
+ pos = os_strstr(cmd, " duration=");
+ if (pos) {
+ *pos = '\0';
+ duration = atoi(pos + 10);
+ } else {
+ duration = -1;
+ }
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ return wpas_mesh_peer_add(wpa_s, addr, duration);
+}
+
#endif /* CONFIG_MESH */
@@ -2834,15 +2931,10 @@ static int wpa_supplicant_ctrl_iface_add_network(
wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL)
return -1;
- wpas_notify_network_added(wpa_s, ssid);
-
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
-
ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
if (os_snprintf_error(buflen, ret))
return -1;
@@ -2855,7 +2947,7 @@ static int wpa_supplicant_ctrl_iface_remove_network(
{
int id;
struct wpa_ssid *ssid;
- int was_disabled;
+ int result;
/* cmd: "<network id>" or "all" */
if (os_strcmp(cmd, "all") == 0) {
@@ -2891,54 +2983,17 @@ static int wpa_supplicant_ctrl_iface_remove_network(
id = atoi(cmd);
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid)
- wpas_notify_network_removed(wpa_s, ssid);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
"id=%d", id);
return -1;
}
-
- if (wpa_s->last_ssid == ssid)
- wpa_s->last_ssid = NULL;
-
- if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
- /*
- * Invalidate the EAP session cache if the current or
- * previously used network is removed.
- */
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
- }
-
- if (ssid == wpa_s->current_ssid) {
- wpa_sm_set_config(wpa_s->wpa, NULL);
- eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-
- if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
- wpa_s->own_disconnect_req = 1;
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- }
-
- was_disabled = ssid->disabled;
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
"network id=%d", id);
return -1;
}
-
- if (!was_disabled && wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
- "network from filters");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
-
return 0;
}
@@ -2947,22 +3002,29 @@ static int wpa_supplicant_ctrl_iface_update_network(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
char *name, char *value)
{
- if (wpa_config_set(ssid, name, value, 0) < 0) {
+ int ret;
+
+ ret = wpa_config_set(ssid, name, value, 0);
+ if (ret < 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
"variable '%s'", name);
return -1;
}
+ if (ret == 1)
+ return 0; /* No change to the previously configured value */
if (os_strcmp(name, "bssid") != 0 &&
- os_strcmp(name, "priority") != 0)
+ os_strcmp(name, "priority") != 0) {
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
- if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
- /*
- * Invalidate the EAP session cache if anything in the current
- * or previously used configuration changes.
- */
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ if (wpa_s->current_ssid == ssid ||
+ wpa_s->current_ssid == NULL) {
+ /*
+ * Invalidate the EAP session cache if anything in the
+ * current or previously used configuration changes.
+ */
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
}
if ((os_strcmp(name, "psk") == 0 &&
@@ -3937,6 +3999,15 @@ static int wpa_supplicant_ctrl_iface_get_capability(
}
#endif /* CONFIG_FIPS */
+#ifdef CONFIG_ACS
+ if (os_strcmp(field, "acs") == 0) {
+ res = os_snprintf(buf, buflen, "ACS");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_ACS */
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
field);
@@ -4197,9 +4268,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
if (mask & WPA_BSS_MASK_P2P_SCAN) {
ie = (const u8 *) (bss + 1);
ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
- if (ret < 0 || ret >= end - pos)
+ if (ret >= end - pos)
return 0;
- pos += ret;
+ if (ret > 0)
+ pos += ret;
}
#endif /* CONFIG_P2P */
@@ -4233,6 +4305,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
#ifdef CONFIG_INTERWORKING
if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
struct wpa_bss_anqp *anqp = bss->anqp;
+ struct wpa_bss_anqp_elem *elem;
+
pos = anqp_add_hex(pos, end, "anqp_capability_list",
anqp->capability_list);
pos = anqp_add_hex(pos, end, "anqp_venue_name",
@@ -4262,6 +4336,15 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
anqp->hs20_osu_providers_list);
#endif /* CONFIG_HS20 */
+
+ dl_list_for_each(elem, &anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list) {
+ char title[20];
+
+ os_snprintf(title, sizeof(title), "anqp[%u]",
+ elem->infoid);
+ pos = anqp_add_hex(pos, end, title, elem->payload);
+ }
}
#endif /* CONFIG_INTERWORKING */
@@ -4269,9 +4352,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
if (mask & WPA_BSS_MASK_MESH_SCAN) {
ie = (const u8 *) (bss + 1);
ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
- if (ret < 0 || ret >= end - pos)
+ if (ret >= end - pos)
return 0;
- pos += ret;
+ if (ret > 0)
+ pos += ret;
}
#endif /* CONFIG_MESH */
@@ -4678,7 +4762,7 @@ static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
return -1;
}
- if (isblank(*last)) {
+ if (isblank((unsigned char) *last)) {
i++;
break;
}
@@ -4850,6 +4934,30 @@ static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
}
+static int parse_freq(int chwidth, int freq2)
+{
+ if (freq2 < 0)
+ return -1;
+ if (freq2)
+ return VHT_CHANWIDTH_80P80MHZ;
+
+ switch (chwidth) {
+ case 0:
+ case 20:
+ case 40:
+ return VHT_CHANWIDTH_USE_HT;
+ case 80:
+ return VHT_CHANWIDTH_80MHZ;
+ case 160:
+ return VHT_CHANWIDTH_160MHZ;
+ default:
+ wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
+ chwidth);
+ return -1;
+ }
+}
+
+
static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen)
{
@@ -4866,7 +4974,9 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
int go_intent = -1;
int freq = 0;
int pd;
- int ht40, vht;
+ int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
+ u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
+ size_t group_ssid_len = 0;
if (!wpa_s->global->p2p_init_wpa_s)
return -1;
@@ -4879,7 +4989,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
- * [ht40] [vht] [auto] */
+ * [ht40] [vht] [auto] [ssid=<hexdump>] */
if (hwaddr_aton(cmd, addr))
return -1;
@@ -4927,11 +5037,41 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
return -1;
}
+ pos2 = os_strstr(pos, " freq2=");
+ if (pos2)
+ freq2 = atoi(pos2 + 7);
+
+ pos2 = os_strstr(pos, " max_oper_chwidth=");
+ if (pos2)
+ chwidth = atoi(pos2 + 18);
+
+ max_oper_chwidth = parse_freq(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ return -1;
+
+ pos2 = os_strstr(pos, " ssid=");
+ if (pos2) {
+ char *end;
+
+ pos2 += 6;
+ end = os_strchr(pos2, ' ');
+ if (!end)
+ group_ssid_len = os_strlen(pos2) / 2;
+ else
+ group_ssid_len = (end - pos2) / 2;
+ if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
+ hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
+ return -1;
+ group_ssid = _group_ssid;
+ }
+
if (os_strncmp(pos, "pin", 3) == 0) {
/* Request random PIN (to be displayed) and enable the PIN */
wps_method = WPS_PIN_DISPLAY;
} else if (os_strncmp(pos, "pbc", 3) == 0) {
wps_method = WPS_PBC;
+ } else if (os_strstr(pos, "p2ps") != NULL) {
+ wps_method = WPS_P2PS;
} else {
pin = pos;
pos = os_strchr(pin, ' ');
@@ -4940,8 +5080,6 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
*pos++ = '\0';
if (os_strncmp(pos, "display", 7) == 0)
wps_method = WPS_PIN_DISPLAY;
- else if (os_strncmp(pos, "p2ps", 4) == 0)
- wps_method = WPS_P2PS;
}
if (!wps_pin_str_valid(pin)) {
os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
@@ -4951,8 +5089,9 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join,
- auth, go_intent, freq, persistent_id, pd,
- ht40, vht);
+ auth, go_intent, freq, freq2, persistent_id,
+ pd, ht40, vht, max_oper_chwidth,
+ group_ssid, group_ssid_len);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25;
@@ -5507,7 +5646,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
struct wpa_ssid *ssid;
u8 *_peer = NULL, peer[ETH_ALEN];
int freq = 0, pref_freq = 0;
- int ht40, vht;
+ int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -5545,8 +5684,20 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
- return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
- pref_freq);
+ pos = os_strstr(cmd, "freq2=");
+ if (pos)
+ freq2 = atoi(pos + 6);
+
+ pos = os_strstr(cmd, " max_oper_chwidth=");
+ if (pos)
+ chwidth = atoi(pos + 18);
+
+ max_oper_chwidth = parse_freq(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ return -1;
+
+ return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
+ max_oper_chwidth, pref_freq);
}
@@ -5593,7 +5744,8 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
- int id, int freq, int ht40, int vht)
+ int id, int freq, int vht_center_freq2,
+ int ht40, int vht, int vht_chwidth)
{
struct wpa_ssid *ssid;
@@ -5605,8 +5757,9 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
return -1;
}
- return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
- NULL, 0, 0);
+ return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
+ vht_center_freq2, 0, ht40, vht,
+ vht_chwidth, NULL, 0, 0);
}
@@ -5615,11 +5768,14 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
int freq = 0, persistent = 0, group_id = -1;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ int max_oper_chwidth, chwidth = 0, freq2 = 0;
char *token, *context = NULL;
while ((token = str_token(cmd, " ", &context))) {
if (sscanf(token, "freq=%d", &freq) == 1 ||
- sscanf(token, "persistent=%d", &group_id) == 1) {
+ sscanf(token, "freq2=%d", &freq2) == 1 ||
+ sscanf(token, "persistent=%d", &group_id) == 1 ||
+ sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
continue;
} else if (os_strcmp(token, "ht40") == 0) {
ht40 = 1;
@@ -5636,11 +5792,40 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
}
}
+ max_oper_chwidth = parse_freq(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ return -1;
+
if (group_id >= 0)
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
- freq, ht40, vht);
+ freq, freq2, ht40, vht,
+ max_oper_chwidth);
+
+ return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
+ max_oper_chwidth);
+}
+
+
+static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
+ char *buf, size_t buflen)
+{
+ u8 dev_addr[ETH_ALEN];
+ struct wpa_ssid *ssid;
+ int res;
+ const u8 *iaddr;
+
+ ssid = wpa_s->current_ssid;
+ if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
+ hwaddr_aton(cmd, dev_addr))
+ return -1;
- return wpas_p2p_group_add(wpa_s, persistent, freq, ht40, vht);
+ iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
+ if (!iaddr)
+ return -1;
+ res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
}
@@ -5799,8 +5984,15 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
}
if (os_strcmp(cmd, "listen_channel") == 0) {
- return p2p_set_listen_channel(wpa_s->global->p2p, 81,
- atoi(param), 1);
+ char *pos;
+ u8 channel, op_class;
+
+ channel = atoi(param);
+ pos = os_strchr(param, ' ');
+ op_class = pos ? atoi(pos) : 81;
+
+ return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
+ channel, 1);
}
if (os_strcmp(cmd, "ssid_postfix") == 0) {
@@ -6061,6 +6253,21 @@ static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
return 0;
}
+
+static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int freq = 0, period = 0, interval = 0, count = 0;
+
+ if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
+ {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
+ return -1;
+ }
+
+ return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
+}
+
#endif /* CONFIG_P2P */
@@ -6178,6 +6385,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
u16 id[MAX_ANQP_INFO_ID];
size_t num_id = 0;
u32 subtypes = 0;
+ int get_cell_pref = 0;
used = hwaddr_aton2(dst, dst_addr);
if (used < 0)
@@ -6195,6 +6403,15 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
#else /* CONFIG_HS20 */
return -1;
#endif /* CONFIG_HS20 */
+ } else if (os_strncmp(pos, "mbo:", 4) == 0) {
+#ifdef CONFIG_MBO
+ int num = atoi(pos + 4);
+ if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
+ return -1;
+ get_cell_pref = 1;
+#else /* CONFIG_MBO */
+ return -1;
+#endif /* CONFIG_MBO */
} else {
id[num_id] = atoi(pos);
if (id[num_id])
@@ -6209,7 +6426,8 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
if (num_id == 0)
return -1;
- return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
+ return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
+ get_cell_pref);
}
@@ -6380,7 +6598,7 @@ static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
if (subtypes == 0)
return -1;
- return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
+ return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
}
@@ -6403,7 +6621,7 @@ static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
ret = hs20_anqp_send_req(wpa_s, addr,
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
- buf, len);
+ buf, len, 0);
os_free(buf);
@@ -6449,14 +6667,59 @@ static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
ret = hs20_anqp_send_req(wpa_s, dst_addr,
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
- buf, len);
+ buf, len, 0);
os_free(buf);
return ret;
}
-static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
+static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
+ int buflen)
+{
+ u8 dst_addr[ETH_ALEN];
+ int used;
+ char *ctx = NULL, *icon, *poffset, *psize;
+
+ used = hwaddr_aton2(cmd, dst_addr);
+ if (used < 0)
+ return -1;
+ cmd += used;
+
+ icon = str_token(cmd, " ", &ctx);
+ poffset = str_token(cmd, " ", &ctx);
+ psize = str_token(cmd, " ", &ctx);
+ if (!icon || !poffset || !psize)
+ return -1;
+
+ wpa_s->fetch_osu_icon_in_progress = 0;
+ return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
+ reply, buflen);
+}
+
+
+static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 dst_addr[ETH_ALEN];
+ int used;
+ char *icon;
+
+ if (!cmd[0])
+ return hs20_del_icon(wpa_s, NULL, NULL);
+
+ used = hwaddr_aton2(cmd, dst_addr);
+ if (used < 0)
+ return -1;
+
+ while (cmd[used] == ' ')
+ used++;
+ icon = cmd[used] ? &cmd[used] : NULL;
+
+ return hs20_del_icon(wpa_s, dst_addr, icon);
+}
+
+
+static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
{
u8 dst_addr[ETH_ALEN];
int used;
@@ -6472,7 +6735,7 @@ static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
wpa_s->fetch_osu_icon_in_progress = 0;
return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
- (u8 *) icon, os_strlen(icon));
+ (u8 *) icon, os_strlen(icon), inmem);
}
#endif /* CONFIG_HS20 */
@@ -6562,14 +6825,27 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
{
- int query_reason;
+ int query_reason, list = 0;
query_reason = atoi(cmd);
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
- query_reason);
+ cmd = os_strchr(cmd, ' ');
+ if (cmd) {
+ cmd++;
+ if (os_strncmp(cmd, "list", 4) == 0) {
+ list = 1;
+ } else {
+ wpa_printf(MSG_DEBUG, "WNM Query: Invalid option %s",
+ cmd);
+ return -1;
+ }
+ }
- return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
+ wpa_printf(MSG_DEBUG,
+ "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
+ query_reason, list ? " candidate list" : "");
+
+ return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, list);
}
#endif /* CONFIG_WNM */
@@ -6634,6 +6910,28 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
}
+static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ const char *pos;
+ int threshold = 0;
+ int hysteresis = 0;
+
+ if (wpa_s->bgscan && wpa_s->bgscan_priv) {
+ wpa_printf(MSG_DEBUG,
+ "Reject SIGNAL_MONITOR command - bgscan is active");
+ return -1;
+ }
+ pos = os_strstr(cmd, "THRESHOLD=");
+ if (pos)
+ threshold = atoi(pos + 10);
+ pos = os_strstr(cmd, "HYSTERESIS=");
+ if (pos)
+ hysteresis = atoi(pos + 11);
+ return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
+}
+
+
static int wpas_ctrl_iface_get_pref_freq_list(
struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
{
@@ -6681,6 +6979,34 @@ static int wpas_ctrl_iface_get_pref_freq_list(
}
+static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
+ char *buf, size_t buflen)
+{
+ int ret, i;
+ char *pos, *end;
+
+ ret = os_snprintf(buf, buflen, "%016llX:\n",
+ (long long unsigned) wpa_s->drv_flags);
+ if (os_snprintf_error(buflen, ret))
+ return -1;
+
+ pos = buf + ret;
+ end = buf + buflen;
+
+ for (i = 0; i < 64; i++) {
+ if (wpa_s->drv_flags & (1LLU << i)) {
+ ret = os_snprintf(pos, end - pos, "%s\n",
+ driver_flag_to_string(1LLU << i));
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ }
+
+ return pos - buf;
+}
+
+
static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
size_t buflen)
{
@@ -6738,13 +7064,13 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
vendor_id = strtoul(cmd, &pos, 16);
- if (!isblank(*pos))
+ if (!isblank((unsigned char) *pos))
return -EINVAL;
subcmd = strtoul(pos, &pos, 10);
if (*pos != '\0') {
- if (!isblank(*pos++))
+ if (!isblank((unsigned char) *pos++))
return -EINVAL;
data_len = os_strlen(pos);
}
@@ -6792,10 +7118,20 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
+ wpas_abort_ongoing_scan(wpa_s);
+
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
+ /*
+ * Avoid possible auto connect re-connection on getting
+ * disconnected due to state flush.
+ */
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+ }
+
#ifdef CONFIG_P2P
+ wpas_p2p_group_remove(p2p_wpa_s, "*");
wpas_p2p_cancel(p2p_wpa_s);
p2p_ctrl_flush(p2p_wpa_s);
- wpas_p2p_group_remove(p2p_wpa_s, "*");
wpas_p2p_service_flush(p2p_wpa_s);
p2p_wpa_s->global->p2p_disabled = 0;
p2p_wpa_s->global->p2p_per_sta_psk = 0;
@@ -6805,12 +7141,15 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
p2p_wpa_s->global->pending_p2ps_group = 0;
+ p2p_wpa_s->global->pending_p2ps_group_freq = 0;
#endif /* CONFIG_P2P */
#ifdef CONFIG_WPS_TESTING
wps_version_number = 0x20;
wps_testing_dummy_cred = 0;
wps_corrupt_pkhash = 0;
+ wps_force_auth_types_in_use = 0;
+ wps_force_encr_types_in_use = 0;
#endif /* CONFIG_WPS_TESTING */
#ifdef CONFIG_WPS
wpa_s->wps_fragment_size = 0;
@@ -6822,7 +7161,6 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
- extern unsigned int tdls_testing;
tdls_testing = 0;
#endif /* CONFIG_TDLS_TESTING */
wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
@@ -6868,7 +7206,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->next_ssid = NULL;
#ifdef CONFIG_INTERWORKING
+#ifdef CONFIG_HS20
hs20_cancel_fetch_osu(wpa_s);
+ hs20_del_icon(wpa_s, NULL, NULL);
+#endif /* CONFIG_HS20 */
#endif /* CONFIG_INTERWORKING */
wpa_s->ext_mgmt_frame_handling = 0;
@@ -6876,6 +7217,11 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
#ifdef CONFIG_TESTING_OPTIONS
wpa_s->extra_roc_dur = 0;
wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
+ wpa_s->p2p_go_csa_on_inv = 0;
+ wpa_s->ignore_auth_resp = 0;
+ wpa_s->ignore_assoc_disallow = 0;
+ wpa_s->reject_btm_req_reason = 0;
+ wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
#endif /* CONFIG_TESTING_OPTIONS */
wpa_s->disconnected = 0;
@@ -6894,6 +7240,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
wpa_s->wnmsleep_used = 0;
+
+#ifdef CONFIG_SME
+ wpa_s->sme.last_unprot_disconnect.sec = 0;
+#endif /* CONFIG_SME */
}
@@ -6950,6 +7300,13 @@ static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
work, NULL);
+ /*
+ * work->type points to a buffer in ework, so need to replace
+ * that here with a fixed string to avoid use of freed memory
+ * in debug prints.
+ */
+ work->type = "freed-ext-work";
+ work->ctx = NULL;
os_free(ework);
return;
}
@@ -7399,6 +7756,76 @@ static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
}
+static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *pos, *param;
+ size_t len;
+ u8 *buf;
+ int freq = 0, datarate = 0, ssi_signal = 0;
+ union wpa_event_data event;
+
+ if (!wpa_s->ext_mgmt_frame_handling)
+ return -1;
+
+ /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
+
+ wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
+
+ pos = cmd;
+ param = os_strstr(pos, "freq=");
+ if (param) {
+ param += 5;
+ freq = atoi(param);
+ }
+
+ param = os_strstr(pos, " datarate=");
+ if (param) {
+ param += 10;
+ datarate = atoi(param);
+ }
+
+ param = os_strstr(pos, " ssi_signal=");
+ if (param) {
+ param += 12;
+ ssi_signal = atoi(param);
+ }
+
+ param = os_strstr(pos, " frame=");
+ if (param == NULL)
+ return -1;
+ param += 7;
+
+ len = os_strlen(param);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(param, buf, len) < 0) {
+ os_free(buf);
+ return -1;
+ }
+
+ os_memset(&event, 0, sizeof(event));
+ event.rx_mgmt.freq = freq;
+ event.rx_mgmt.frame = buf;
+ event.rx_mgmt.frame_len = len;
+ event.rx_mgmt.ssi_signal = ssi_signal;
+ event.rx_mgmt.datarate = datarate;
+ wpa_s->ext_mgmt_frame_handling = 0;
+ wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
+ wpa_s->ext_mgmt_frame_handling = 1;
+
+ os_free(buf);
+
+ return 0;
+}
+
+
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos, *param;
@@ -7498,7 +7925,8 @@ static u16 ipv4_hdr_checksum(const void *buf, size_t len)
#define HWSIM_PACKETLEN 1500
#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
-void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
+ size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
const struct ether_header *eth;
@@ -7532,6 +7960,8 @@ static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
char *cmd)
{
int enabled = atoi(cmd);
+ char *pos;
+ const char *ifname;
if (!enabled) {
if (wpa_s->l2_test) {
@@ -7545,7 +7975,13 @@ static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
if (wpa_s->l2_test)
return 0;
- wpa_s->l2_test = l2_packet_init(wpa_s->ifname, wpa_s->own_addr,
+ pos = os_strstr(cmd, " ifname=");
+ if (pos)
+ ifname = pos + 8;
+ else
+ ifname = wpa_s->ifname;
+
+ wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
ETHERTYPE_IP, wpas_data_test_rx,
wpa_s, 1);
if (wpa_s->l2_test == NULL)
@@ -7666,8 +8102,6 @@ done:
static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_fail_func[256];
- extern unsigned int wpa_trace_fail_after;
char *pos;
wpa_trace_fail_after = atoi(cmd);
@@ -7690,9 +8124,6 @@ static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
char *buf, size_t buflen)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_fail_func[256];
- extern unsigned int wpa_trace_fail_after;
-
return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
wpa_trace_fail_func);
#else /* WPA_TRACE_BFD */
@@ -7704,8 +8135,6 @@ static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_test_fail_func[256];
- extern unsigned int wpa_trace_test_fail_after;
char *pos;
wpa_trace_test_fail_after = atoi(cmd);
@@ -7728,9 +8157,6 @@ static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
char *buf, size_t buflen)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_test_fail_func[256];
- extern unsigned int wpa_trace_test_fail_after;
-
return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
wpa_trace_test_fail_func);
#else /* WPA_TRACE_BFD */
@@ -7738,62 +8164,64 @@ static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
#endif /* WPA_TRACE_BFD */
}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
+static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
{
- unsigned int i;
- char buf[30];
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ int i, count = (intptr_t) timeout_ctx;
- wpa_printf(MSG_DEBUG, "Update vendor elements");
+ wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
+ count);
+ for (i = 0; i < count; i++) {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
+ i + 1, count);
+ }
+}
- for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
- if (wpa_s->vendor_elem[i]) {
- int res;
- res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
- if (!os_snprintf_error(sizeof(buf), res)) {
- wpa_hexdump_buf(MSG_DEBUG, buf,
- wpa_s->vendor_elem[i]);
- }
- }
- }
+static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ int count;
-#ifdef CONFIG_P2P
- if (wpa_s->parent == wpa_s &&
- wpa_s->global->p2p &&
- !wpa_s->global->p2p_disabled)
- p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
-#endif /* CONFIG_P2P */
+ count = atoi(cmd);
+ if (count <= 0)
+ return -1;
+
+ return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
+ (void *) (intptr_t) count);
}
-static struct wpa_supplicant *
-wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
- enum wpa_vendor_elem_frame frame)
+static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
+ const char *cmd)
{
- switch (frame) {
-#ifdef CONFIG_P2P
- case VENDOR_ELEM_PROBE_REQ_P2P:
- case VENDOR_ELEM_PROBE_RESP_P2P:
- case VENDOR_ELEM_PROBE_RESP_P2P_GO:
- case VENDOR_ELEM_BEACON_P2P_GO:
- case VENDOR_ELEM_P2P_PD_REQ:
- case VENDOR_ELEM_P2P_PD_RESP:
- case VENDOR_ELEM_P2P_GO_NEG_REQ:
- case VENDOR_ELEM_P2P_GO_NEG_RESP:
- case VENDOR_ELEM_P2P_GO_NEG_CONF:
- case VENDOR_ELEM_P2P_INV_REQ:
- case VENDOR_ELEM_P2P_INV_RESP:
- case VENDOR_ELEM_P2P_ASSOC_REQ:
- return wpa_s->parent;
-#endif /* CONFIG_P2P */
- default:
- return wpa_s;
+ struct wpabuf *buf;
+ size_t len;
+
+ len = os_strlen(cmd);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ if (len == 0) {
+ buf = NULL;
+ } else {
+ buf = wpabuf_alloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
+ wpabuf_free(buf);
+ return -1;
+ }
}
+
+ wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
+ return 0;
}
+#endif /* CONFIG_TESTING_OPTIONS */
+
static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
{
@@ -7806,7 +8234,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
frame = atoi(pos);
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
return -1;
- wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+ wpa_s = wpas_vendor_elem(wpa_s, frame);
pos = os_strchr(pos, ' ');
if (pos == NULL)
@@ -7837,7 +8265,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
if (wpa_s->vendor_elem[frame] == NULL) {
wpa_s->vendor_elem[frame] = buf;
- wpas_ctrl_vendor_elem_update(wpa_s);
+ wpas_vendor_elem_update(wpa_s);
return 0;
}
@@ -7848,7 +8276,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
wpabuf_free(buf);
- wpas_ctrl_vendor_elem_update(wpa_s);
+ wpas_vendor_elem_update(wpa_s);
return 0;
}
@@ -7861,7 +8289,7 @@ static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
return -1;
- wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+ wpa_s = wpas_vendor_elem(wpa_s, frame);
if (wpa_s->vendor_elem[frame] == NULL)
return 0;
@@ -7879,12 +8307,12 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
size_t len;
u8 *buf;
struct ieee802_11_elems elems;
- u8 *ie, *end;
+ int res;
frame = atoi(pos);
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
return -1;
- wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+ wpa_s = wpas_vendor_elem(wpa_s, frame);
pos = os_strchr(pos, ' ');
if (pos == NULL)
@@ -7894,7 +8322,7 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
if (*pos == '*') {
wpabuf_free(wpa_s->vendor_elem[frame]);
wpa_s->vendor_elem[frame] = NULL;
- wpas_ctrl_vendor_elem_update(wpa_s);
+ wpas_vendor_elem_update(wpa_s);
return 0;
}
@@ -7922,65 +8350,149 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
return -1;
}
- ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
- end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
-
- for (; ie + 1 < end; ie += 2 + ie[1]) {
- if (ie + len > end)
- break;
- if (os_memcmp(ie, buf, len) != 0)
- continue;
-
- if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
- wpabuf_free(wpa_s->vendor_elem[frame]);
- wpa_s->vendor_elem[frame] = NULL;
- } else {
- os_memmove(ie, ie + len,
- end - (ie + len));
- wpa_s->vendor_elem[frame]->used -= len;
- }
- os_free(buf);
- wpas_ctrl_vendor_elem_update(wpa_s);
- return 0;
- }
-
+ res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
os_free(buf);
-
- return -1;
+ return res;
}
static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
{
struct wpa_supplicant *wpa_s = ctx;
+ size_t len;
+ const u8 *data;
- if (neighbor_rep) {
- wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
- "length=%u",
- (unsigned int) wpabuf_len(neighbor_rep));
- wpabuf_free(neighbor_rep);
- } else {
+ /*
+ * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
+ * BSSID[6]
+ * BSSID Information[4]
+ * Operating Class[1]
+ * Channel Number[1]
+ * PHY Type[1]
+ * Optional Subelements[variable]
+ */
+#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
+
+ if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
+ goto out;
+ }
+
+ data = wpabuf_head_u8(neighbor_rep);
+ len = wpabuf_len(neighbor_rep);
+
+ while (len >= 2 + NR_IE_MIN_LEN) {
+ const u8 *nr;
+ char lci[256 * 2 + 1];
+ char civic[256 * 2 + 1];
+ u8 nr_len = data[1];
+ const u8 *pos = data, *end;
+
+ if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
+ nr_len < NR_IE_MIN_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid Neighbor Report element: id=%u len=%u",
+ data[0], nr_len);
+ goto out;
+ }
+
+ if (2U + nr_len > len) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
+ data[0], len, nr_len);
+ goto out;
+ }
+ pos += 2;
+ end = pos + nr_len;
+
+ nr = pos;
+ pos += NR_IE_MIN_LEN;
+
+ lci[0] = '\0';
+ civic[0] = '\0';
+ while (end - pos > 2) {
+ u8 s_id, s_len;
+
+ s_id = *pos++;
+ s_len = *pos++;
+ if (s_len > end - pos)
+ goto out;
+ if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
+ /* Measurement Token[1] */
+ /* Measurement Report Mode[1] */
+ /* Measurement Type[1] */
+ /* Measurement Report[variable] */
+ switch (pos[2]) {
+ case MEASURE_TYPE_LCI:
+ if (lci[0])
+ break;
+ wpa_snprintf_hex(lci, sizeof(lci),
+ pos, s_len);
+ break;
+ case MEASURE_TYPE_LOCATION_CIVIC:
+ if (civic[0])
+ break;
+ wpa_snprintf_hex(civic, sizeof(civic),
+ pos, s_len);
+ break;
+ }
+ }
+
+ pos += s_len;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
+ "bssid=" MACSTR
+ " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
+ MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
+ nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
+ nr[ETH_ALEN + 6],
+ lci[0] ? " lci=" : "", lci,
+ civic[0] ? " civic=" : "", civic);
+
+ data = end;
+ len -= 2 + nr_len;
}
+
+out:
+ wpabuf_free(neighbor_rep);
}
-static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
- char *cmd)
+static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
+ char *cmd)
{
- struct wpa_ssid ssid;
- struct wpa_ssid *ssid_p = NULL;
- int ret = 0;
+ struct wpa_ssid_value ssid, *ssid_p = NULL;
+ int ret, lci = 0, civic = 0;
+ char *ssid_s;
- if (os_strncmp(cmd, " ssid=", 6) == 0) {
- ssid.ssid_len = os_strlen(cmd + 6);
- if (ssid.ssid_len > SSID_MAX_LEN)
+ ssid_s = os_strstr(cmd, "ssid=");
+ if (ssid_s) {
+ if (ssid_parse(ssid_s + 5, &ssid)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: Send Neighbor Report: bad SSID");
return -1;
- ssid.ssid = (u8 *) (cmd + 6);
+ }
+
ssid_p = &ssid;
+
+ /*
+ * Move cmd after the SSID text that may include "lci" or
+ * "civic".
+ */
+ cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
+ if (cmd)
+ cmd++;
+
}
- ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p,
+ if (cmd && os_strstr(cmd, "lci"))
+ lci = 1;
+
+ if (cmd && os_strstr(cmd, "civic"))
+ civic = 1;
+
+ ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
wpas_ctrl_neighbor_rep_cb,
wpa_s);
@@ -8065,10 +8577,7 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
}
} else if (wpa_s->sched_scanning &&
(type & MAC_ADDR_RAND_SCHED_SCAN)) {
- /* simulate timeout to restart the sched scan */
- wpa_s->sched_scan_timed_out = 1;
- wpa_s->prev_sched_ssid = NULL;
- wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpas_scan_restart_sched_scan(wpa_s);
}
return 0;
}
@@ -8094,12 +8603,8 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
addr, mask);
- if (wpa_s->sched_scanning && !wpa_s->pno) {
- /* simulate timeout to restart the sched scan */
- wpa_s->sched_scan_timed_out = 1;
- wpa_s->prev_sched_ssid = NULL;
- wpa_supplicant_cancel_sched_scan(wpa_s);
- }
+ if (wpa_s->sched_scanning && !wpa_s->pno)
+ wpas_scan_restart_sched_scan(wpa_s);
}
if (type & MAC_ADDR_RAND_PNO) {
@@ -8115,6 +8620,29 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
}
+static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
+ char *buf, size_t buflen)
+{
+ size_t reply_len;
+
+ reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
+#ifdef CONFIG_AP
+ reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
+ buflen - reply_len);
+#endif /* CONFIG_AP */
+ return reply_len;
+}
+
+
+static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
+{
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
+#ifdef CONFIG_AP
+ wpas_ap_pmksa_cache_flush(wpa_s);
+#endif /* CONFIG_AP */
+}
+
+
static int wpas_ctrl_cmd_debug_level(const char *cmd)
{
if (os_strcmp(cmd, "PING") == 0 ||
@@ -8186,10 +8714,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = wpa_supplicant_ctrl_iface_status(
wpa_s, buf + 6, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA") == 0) {
- reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
- reply_size);
+ reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
- wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
+ wpas_ctrl_iface_pmksa_flush(wpa_s);
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
reply_len = -1;
@@ -8357,6 +8884,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
buf + 18))
reply_len = -1;
+ } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
+ if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
+ if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
+ reply_len = -1;
#endif /* CONFIG_MESH */
#ifdef CONFIG_P2P
} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
@@ -8391,6 +8924,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
if (p2p_ctrl_group_add(wpa_s, buf + 14))
reply_len = -1;
+ } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
+ reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
+ reply_size);
} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
reply_len = -1;
@@ -8456,6 +8992,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
+ if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
+ if (wpas_p2p_lo_stop(wpa_s))
+ reply_len = -1;
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
@@ -8509,10 +9051,21 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
- if (hs20_icon_request(wpa_s, buf + 18) < 0)
+ if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
+ if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
+ reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
+ } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
+ if (del_hs20_icon(wpa_s, buf + 14) < 0)
reply_len = -1;
} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
- if (hs20_fetch_osu(wpa_s) < 0)
+ if (hs20_fetch_osu(wpa_s, 0) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
+ if (hs20_fetch_osu(wpa_s, 1) < 0)
reply_len = -1;
} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
hs20_cancel_fetch_osu(wpa_s);
@@ -8551,16 +9104,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = wpa_supplicant_ctrl_iface_list_networks(
wpa_s, NULL, reply, reply_size);
} else if (os_strcmp(buf, "DISCONNECT") == 0) {
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
- wpa_s->reassociate = 0;
- wpa_s->disconnected = 1;
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_cancel_scan(wpa_s);
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ wpas_request_disconnection(wpa_s);
} else if (os_strcmp(buf, "SCAN") == 0) {
wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
@@ -8568,6 +9112,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
reply_len = wpa_supplicant_ctrl_iface_scan_results(
wpa_s, reply, reply_size);
+ } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
+ if (wpas_abort_ongoing_scan(wpa_s) < 0)
+ reply_len = -1;
} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
reply_len = -1;
@@ -8626,9 +9173,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
reply_len = wpa_supplicant_global_iface_list(
wpa_s->global, reply, reply_size);
- } else if (os_strcmp(buf, "INTERFACES") == 0) {
+ } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
reply_len = wpa_supplicant_global_iface_interfaces(
- wpa_s->global, reply, reply_size);
+ wpa_s->global, buf + 10, reply, reply_size);
} else if (os_strncmp(buf, "BSS ", 4) == 0) {
reply_len = wpa_supplicant_ctrl_iface_bss(
wpa_s, buf + 4, reply, reply_size);
@@ -8709,6 +9256,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
reply_size);
+ } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
+ if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
+ reply_len = -1;
} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
reply_size);
@@ -8717,6 +9267,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
reply_len = -1;
#endif /* CONFIG_AUTOSCAN */
+ } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+ reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
+ reply_size);
#ifdef ANDROID
} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
@@ -8747,6 +9300,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = -1;
} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
wpas_ctrl_iface_mgmt_tx_done(wpa_s);
+ } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
+ if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
+ reply_len = -1;
} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
reply_len = -1;
@@ -8772,6 +9328,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = -1;
} else if (os_strcmp(buf, "GET_FAIL") == 0) {
reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
+ } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
+ if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
+ if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
+ reply_len = -1;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
@@ -8783,7 +9345,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
- if (wpas_ctrl_iface_send_neigbor_rep(wpa_s, buf + 20))
+ if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
reply_len = -1;
} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
wpas_ctrl_iface_erp_flush(wpa_s);
@@ -8816,10 +9378,11 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
struct wpa_supplicant *wpa_s;
unsigned int create_iface = 0;
u8 mac_addr[ETH_ALEN];
+ enum wpa_driver_if_type type = WPA_IF_STATION;
/*
* <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
- * TAB<bridge_ifname>[TAB<create>]
+ * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
*/
wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
@@ -8887,9 +9450,22 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
if (!extra[0])
break;
- if (os_strcmp(extra, "create") == 0)
+ if (os_strcmp(extra, "create") == 0) {
create_iface = 1;
- else {
+ if (!pos)
+ break;
+
+ if (os_strcmp(pos, "sta") == 0) {
+ type = WPA_IF_STATION;
+ } else if (os_strcmp(pos, "ap") == 0) {
+ type = WPA_IF_AP_BSS;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "INTERFACE_ADD unsupported interface type: '%s'",
+ pos);
+ return -1;
+ }
+ } else {
wpa_printf(MSG_DEBUG,
"INTERFACE_ADD unsupported extra parameter: '%s'",
extra);
@@ -8902,7 +9478,7 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
iface.ifname);
if (!global->ifaces)
return -1;
- if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+ if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
NULL, NULL, NULL, mac_addr, NULL) < 0) {
wpa_printf(MSG_ERROR,
"CTRL_IFACE interface creation failed");
@@ -9011,18 +9587,31 @@ static int wpa_supplicant_global_iface_list(struct wpa_global *global,
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
+ const char *input,
char *buf, int len)
{
int res;
char *pos, *end;
struct wpa_supplicant *wpa_s;
+ int show_ctrl = 0;
+
+ if (input)
+ show_ctrl = !!os_strstr(input, "ctrl");
wpa_s = global->ifaces;
pos = buf;
end = buf + len;
while (wpa_s) {
- res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
+ if (show_ctrl)
+ res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
+ wpa_s->ifname,
+ wpa_s->conf->ctrl_interface ?
+ wpa_s->conf->ctrl_interface : "N/A");
+ else
+ res = os_snprintf(pos, end - pos, "%s\n",
+ wpa_s->ifname);
+
if (os_snprintf_error(end - pos, res)) {
*pos = '\0';
break;
@@ -9088,6 +9677,7 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
"P2P_LISTEN ",
"P2P_GROUP_REMOVE ",
"P2P_GROUP_ADD ",
+ "P2P_GROUP_MEMBER ",
"P2P_PROV_DISC ",
"P2P_SERV_DISC_REQ ",
"P2P_SERV_DISC_CANCEL_REQ ",
@@ -9411,9 +10001,9 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
reply_len = wpa_supplicant_global_iface_list(
global, reply, reply_size);
- } else if (os_strcmp(buf, "INTERFACES") == 0) {
+ } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
reply_len = wpa_supplicant_global_iface_interfaces(
- global, reply, reply_size);
+ global, buf + 10, reply, reply_size);
#ifdef CONFIG_FST
} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
@@ -9459,7 +10049,6 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
reply_size);
#ifdef CONFIG_MODULE_TESTS
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
- int wpas_module_tests(void);
if (wpas_module_tests() < 0)
reply_len = -1;
#endif /* CONFIG_MODULE_TESTS */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
index 259d2937..ff1814c9 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
@@ -17,7 +17,6 @@
#include <fcntl.h>
#ifdef __linux__
#include <sys/ioctl.h>
-#include <linux/sockios.h>
#endif /* __linux__ */
#ifdef ANDROID
#include <cutils/sockets.h>
@@ -26,6 +25,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/list.h"
+#include "common/ctrl_iface_common.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "config.h"
#include "wpa_supplicant_i.h"
@@ -33,27 +33,13 @@
/* Per-interface ctrl_iface */
-/**
- * struct wpa_ctrl_dst - Internal data structure of control interface monitors
- *
- * This structure is used to store information about registered control
- * interface monitors into struct wpa_supplicant. This data is private to
- * ctrl_iface_unix.c and should not be touched directly from other files.
- */
-struct wpa_ctrl_dst {
- struct dl_list list;
- struct sockaddr_un addr;
- socklen_t addrlen;
- int debug_level;
- int errors;
-};
-
-
struct ctrl_iface_priv {
struct wpa_supplicant *wpa_s;
int sock;
struct dl_list ctrl_dst;
int android_control_socket;
+ struct dl_list msg_queue;
+ unsigned int throttle_count;
};
@@ -62,6 +48,17 @@ struct ctrl_iface_global_priv {
int sock;
struct dl_list ctrl_dst;
int android_control_socket;
+ struct dl_list msg_queue;
+ unsigned int throttle_count;
+};
+
+struct ctrl_iface_msg {
+ struct dl_list list;
+ struct wpa_supplicant *wpa_s;
+ int level;
+ enum wpa_msg_type type;
+ const char *txt;
+ size_t len;
};
@@ -94,7 +91,7 @@ static void wpas_ctrl_sock_debug(const char *title, int sock, const char *buf,
if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen) < 0)
sndbuf = -1;
- if (ioctl(sock, SIOCOUTQ, &outq) < 0)
+ if (ioctl(sock, TIOCOUTQ, &outq) < 0)
outq = -1;
wpa_printf(level,
@@ -105,81 +102,29 @@ static void wpas_ctrl_sock_debug(const char *title, int sock, const char *buf,
static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen, int global)
{
- struct wpa_ctrl_dst *dst;
- char addr_txt[200];
-
- dst = os_zalloc(sizeof(*dst));
- if (dst == NULL)
- return -1;
- os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
- dst->addrlen = fromlen;
- dst->debug_level = MSG_INFO;
- dl_list_add(ctrl_dst, &dst->list);
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) from->sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path));
- wpa_printf(MSG_DEBUG, "CTRL_IFACE %smonitor attached %s",
- global ? "global " : "", addr_txt);
- return 0;
+ return ctrl_iface_attach(ctrl_dst, from, fromlen);
}
static int wpa_supplicant_ctrl_iface_detach(struct dl_list *ctrl_dst,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen)
{
- struct wpa_ctrl_dst *dst;
-
- dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
- if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- char addr_txt[200];
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
- wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s",
- addr_txt);
- dl_list_del(&dst->list);
- os_free(dst);
- return 0;
- }
- }
- return -1;
+ return ctrl_iface_detach(ctrl_dst, from, fromlen);
}
static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen,
char *level)
{
- struct wpa_ctrl_dst *dst;
-
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
- dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
- if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- char addr_txt[200];
- dst->debug_level = atoi(level);
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) from->sun_path, fromlen -
- offsetof(struct sockaddr_un, sun_path));
- wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level to %d for %s",
- dst->debug_level, addr_txt);
- return 0;
- }
- }
-
- return -1;
+ return ctrl_iface_level(&priv->ctrl_dst, from, fromlen, level);
}
@@ -190,7 +135,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
struct ctrl_iface_priv *priv = sock_ctx;
char buf[4096];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply = NULL, *reply_buf = NULL;
size_t reply_len = 0;
@@ -336,33 +281,209 @@ static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
}
+static int wpas_ctrl_iface_throttle(int sock)
+{
+#ifdef __linux__
+ socklen_t optlen;
+ int sndbuf, outq;
+
+ optlen = sizeof(sndbuf);
+ sndbuf = 0;
+ if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen) < 0 ||
+ ioctl(sock, TIOCOUTQ, &outq) < 0 ||
+ sndbuf <= 0 || outq < 0)
+ return 0;
+ return outq > sndbuf / 2;
+#else /* __linux__ */
+ return 0;
+#endif /* __linux__ */
+}
+
+
+static void wpas_ctrl_msg_send_pending_global(struct wpa_global *global)
+{
+ struct ctrl_iface_global_priv *gpriv;
+ struct ctrl_iface_msg *msg;
+
+ gpriv = global->ctrl_iface;
+ while (gpriv && !dl_list_empty(&gpriv->msg_queue) &&
+ !wpas_ctrl_iface_throttle(gpriv->sock)) {
+ msg = dl_list_first(&gpriv->msg_queue, struct ctrl_iface_msg,
+ list);
+ if (!msg)
+ break;
+ dl_list_del(&msg->list);
+ wpa_supplicant_ctrl_iface_send(
+ msg->wpa_s,
+ msg->type != WPA_MSG_PER_INTERFACE ?
+ NULL : msg->wpa_s->ifname,
+ gpriv->sock, &gpriv->ctrl_dst, msg->level,
+ msg->txt, msg->len, NULL, gpriv);
+ os_free(msg);
+ }
+}
+
+
+static void wpas_ctrl_msg_send_pending_iface(struct wpa_supplicant *wpa_s)
+{
+ struct ctrl_iface_priv *priv;
+ struct ctrl_iface_msg *msg;
+
+ priv = wpa_s->ctrl_iface;
+ while (priv && !dl_list_empty(&priv->msg_queue) &&
+ !wpas_ctrl_iface_throttle(priv->sock)) {
+ msg = dl_list_first(&priv->msg_queue, struct ctrl_iface_msg,
+ list);
+ if (!msg)
+ break;
+ dl_list_del(&msg->list);
+ wpa_supplicant_ctrl_iface_send(wpa_s, NULL, priv->sock,
+ &priv->ctrl_dst, msg->level,
+ msg->txt, msg->len, priv, NULL);
+ os_free(msg);
+ }
+}
+
+
+static void wpas_ctrl_msg_queue_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct ctrl_iface_priv *priv;
+ struct ctrl_iface_global_priv *gpriv;
+ int sock = -1, gsock = -1;
+
+ wpas_ctrl_msg_send_pending_global(wpa_s->global);
+ wpas_ctrl_msg_send_pending_iface(wpa_s);
+
+ priv = wpa_s->ctrl_iface;
+ if (priv && !dl_list_empty(&priv->msg_queue))
+ sock = priv->sock;
+
+ gpriv = wpa_s->global->ctrl_iface;
+ if (gpriv && !dl_list_empty(&gpriv->msg_queue))
+ gsock = gpriv->sock;
+
+ if (sock > -1 || gsock > -1) {
+ /* Continue pending message transmission from a timeout */
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle pending event message transmission for (sock %d gsock %d)",
+ sock, gsock);
+ eloop_register_timeout(0, 20000, wpas_ctrl_msg_queue_timeout,
+ wpa_s, NULL);
+ }
+}
+
+
+static void wpas_ctrl_msg_queue(struct dl_list *queue,
+ struct wpa_supplicant *wpa_s, int level,
+ enum wpa_msg_type type,
+ const char *txt, size_t len)
+{
+ struct ctrl_iface_msg *msg;
+
+ msg = os_zalloc(sizeof(*msg) + len);
+ if (!msg)
+ return;
+
+ msg->wpa_s = wpa_s;
+ msg->level = level;
+ msg->type = type;
+ os_memcpy(msg + 1, txt, len);
+ msg->txt = (const char *) (msg + 1);
+ msg->len = len;
+ dl_list_add_tail(queue, &msg->list);
+ eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
+ eloop_register_timeout(0, 0, wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
+}
+
+
+static void wpas_ctrl_msg_queue_limit(unsigned int throttle_count,
+ struct dl_list *queue)
+{
+ struct ctrl_iface_msg *msg;
+
+ if (throttle_count < 2000)
+ return;
+
+ msg = dl_list_first(queue, struct ctrl_iface_msg, list);
+ if (msg) {
+ wpa_printf(MSG_DEBUG, "CTRL: Dropped oldest pending message");
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+}
+
+
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
enum wpa_msg_type type,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
+ struct ctrl_iface_priv *priv;
+ struct ctrl_iface_global_priv *gpriv;
if (wpa_s == NULL)
return;
- if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
- struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
- if (!dl_list_empty(&priv->ctrl_dst)) {
+ gpriv = wpa_s->global->ctrl_iface;
+
+ if (type != WPA_MSG_NO_GLOBAL && gpriv &&
+ !dl_list_empty(&gpriv->ctrl_dst)) {
+ if (!dl_list_empty(&gpriv->msg_queue) ||
+ wpas_ctrl_iface_throttle(gpriv->sock)) {
+ if (gpriv->throttle_count == 0) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle global event message for sock %d",
+ gpriv->sock);
+ }
+ gpriv->throttle_count++;
+ wpas_ctrl_msg_queue_limit(gpriv->throttle_count,
+ &gpriv->msg_queue);
+ wpas_ctrl_msg_queue(&gpriv->msg_queue, wpa_s, level,
+ type, txt, len);
+ } else {
+ if (gpriv->throttle_count) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle %u global event message(s) for sock %d",
+ gpriv->throttle_count, gpriv->sock);
+ }
+ gpriv->throttle_count = 0;
wpa_supplicant_ctrl_iface_send(
wpa_s,
type != WPA_MSG_PER_INTERFACE ?
NULL : wpa_s->ifname,
- priv->sock, &priv->ctrl_dst, level, txt, len,
- NULL, priv);
+ gpriv->sock, &gpriv->ctrl_dst, level,
+ txt, len, NULL, gpriv);
}
}
- if (type == WPA_MSG_ONLY_GLOBAL || wpa_s->ctrl_iface == NULL)
- return;
- wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
- &wpa_s->ctrl_iface->ctrl_dst,
- level, txt, len, wpa_s->ctrl_iface,
- NULL);
+ priv = wpa_s->ctrl_iface;
+
+ if (type != WPA_MSG_ONLY_GLOBAL && priv) {
+ if (!dl_list_empty(&priv->msg_queue) ||
+ wpas_ctrl_iface_throttle(priv->sock)) {
+ if (priv->throttle_count == 0) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle event message for sock %d",
+ priv->sock);
+ }
+ priv->throttle_count++;
+ wpas_ctrl_msg_queue_limit(priv->throttle_count,
+ &priv->msg_queue);
+ wpas_ctrl_msg_queue(&priv->msg_queue, wpa_s, level,
+ type, txt, len);
+ } else {
+ if (priv->throttle_count) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle %u event message(s) for sock %d",
+ priv->throttle_count, priv->sock);
+ }
+ priv->throttle_count = 0;
+ wpa_supplicant_ctrl_iface_send(wpa_s, NULL, priv->sock,
+ &priv->ctrl_dst, level,
+ txt, len, priv, NULL);
+ }
+ }
}
@@ -580,6 +701,7 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
if (priv == NULL)
return NULL;
dl_list_init(&priv->ctrl_dst);
+ dl_list_init(&priv->msg_queue);
priv->wpa_s = wpa_s;
priv->sock = -1;
@@ -673,6 +795,8 @@ static int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s,
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
{
struct wpa_ctrl_dst *dst, *prev;
+ struct ctrl_iface_msg *msg, *prev_msg;
+ struct ctrl_iface_global_priv *gpriv;
if (priv->sock > -1) {
char *fname;
@@ -726,8 +850,26 @@ void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
free_dst:
dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
- list)
+ list) {
+ dl_list_del(&dst->list);
os_free(dst);
+ }
+ dl_list_for_each_safe(msg, prev_msg, &priv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+ gpriv = priv->wpa_s->global->ctrl_iface;
+ if (gpriv) {
+ dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ if (msg->wpa_s == priv->wpa_s) {
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+ }
+ }
+ eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
os_free(priv);
}
@@ -787,33 +929,31 @@ static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
int _errno;
- char addr_txt[200];
+ char txt[200];
if (level < dst->debug_level)
continue;
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) dst->addr.sun_path, dst->addrlen -
- offsetof(struct sockaddr_un, sun_path));
msg.msg_name = (void *) &dst->addr;
msg.msg_namelen = dst->addrlen;
wpas_ctrl_sock_debug("ctrl_sock-sendmsg", sock, buf, len);
if (sendmsg(sock, &msg, MSG_DONTWAIT) >= 0) {
- wpa_printf(MSG_MSGDUMP,
- "CTRL_IFACE monitor sent successfully to %s",
- addr_txt);
+ sockaddr_print(MSG_MSGDUMP,
+ "CTRL_IFACE monitor sent successfully to",
+ &dst->addr, dst->addrlen);
dst->errors = 0;
continue;
}
_errno = errno;
- wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor[%s]: %d - %s",
- addr_txt, errno, strerror(errno));
+ os_snprintf(txt, sizeof(txt), "CTRL_IFACE monitor: %d (%s) for",
+ _errno, strerror(_errno));
+ sockaddr_print(MSG_DEBUG, txt, &dst->addr, dst->addrlen);
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT || _errno == EPERM) {
- wpa_printf(MSG_INFO, "CTRL_IFACE: Detach monitor %s that cannot receive messages",
- addr_txt);
+ sockaddr_print(MSG_INFO, "CTRL_IFACE: Detach monitor that cannot receive messages:",
+ &dst->addr, dst->addrlen);
wpa_supplicant_ctrl_iface_detach(ctrl_dst, &dst->addr,
dst->addrlen);
}
@@ -847,9 +987,12 @@ void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
{
char buf[256];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
+ if (priv->sock == -1)
+ return;
+
for (;;) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
"attach", priv->wpa_s->ifname);
@@ -907,7 +1050,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
struct ctrl_iface_global_priv *priv = sock_ctx;
char buf[4096];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply = NULL, *reply_buf = NULL;
size_t reply_len;
@@ -1157,6 +1300,7 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
if (priv == NULL)
return NULL;
dl_list_init(&priv->ctrl_dst);
+ dl_list_init(&priv->msg_queue);
priv->global = global;
priv->sock = -1;
@@ -1206,6 +1350,7 @@ void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
struct wpa_ctrl_dst *dst, *prev;
+ struct ctrl_iface_msg *msg, *prev_msg;
if (priv->sock >= 0) {
eloop_unregister_read_sock(priv->sock);
@@ -1214,7 +1359,14 @@ wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
if (priv->global->params.ctrl_interface)
unlink(priv->global->params.ctrl_interface);
dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
- list)
+ list) {
+ dl_list_del(&dst->list);
os_free(dst);
+ }
+ dl_list_for_each_safe(msg, prev_msg, &priv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
os_free(priv);
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
index 6d240fff..d64fceef 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
@@ -29,6 +29,7 @@ enum wpas_dbus_prop {
WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
WPAS_DBUS_PROP_BSSS,
WPAS_DBUS_PROP_DISCONNECT_REASON,
+ WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
};
enum wpas_dbus_bss_prop {
@@ -189,8 +190,7 @@ void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
const u8 *src, u16 dev_passwd_id,
u8 go_intent);
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
- int client, int network_id);
+ int client, int persistent);
void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
@@ -400,8 +400,7 @@ static inline void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
static inline void
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
- int client, int network_id)
+ int client, int persistent)
{
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/driver_i.h b/freebsd/contrib/wpa/wpa_supplicant/driver_i.h
index 73768c75..220b7ba3 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/driver_i.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/driver_i.h
@@ -100,12 +100,10 @@ static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s,
}
static inline int wpa_drv_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- u32 interval)
+ struct wpa_driver_scan_params *params)
{
if (wpa_s->driver->sched_scan)
- return wpa_s->driver->sched_scan(wpa_s->drv_priv,
- params, interval);
+ return wpa_s->driver->sched_scan(wpa_s->drv_priv, params);
return -1;
}
@@ -160,6 +158,15 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s,
return -1;
}
+static inline int wpa_drv_get_seqnum(struct wpa_supplicant *wpa_s,
+ const u8 *addr, int idx, u8 *seq)
+{
+ if (wpa_s->driver->get_seqnum)
+ return wpa_s->driver->get_seqnum(wpa_s->ifname, wpa_s->drv_priv,
+ addr, idx, seq);
+ return -1;
+}
+
static inline int wpa_drv_sta_deauth(struct wpa_supplicant *wpa_s,
const u8 *addr, int reason_code)
{
@@ -292,7 +299,7 @@ static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
if (wpa_s->driver->send_mlme)
return wpa_s->driver->send_mlme(wpa_s->drv_priv,
data, data_len, noack,
- freq);
+ freq, NULL, 0);
return -1;
}
@@ -401,7 +408,7 @@ static inline int wpa_drv_if_add(struct wpa_supplicant *wpa_s,
if (wpa_s->driver->if_add)
return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname,
addr, bss_ctx, NULL, force_ifname,
- if_addr, bridge, 0);
+ if_addr, bridge, 0, 0);
return -1;
}
@@ -726,12 +733,11 @@ static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s,
}
static inline int wpa_drv_set_current_cipher_suite(struct wpa_supplicant *wpa_s,
- const u8 *cs, size_t cs_len)
+ u64 cs)
{
if (!wpa_s->driver->set_current_cipher_suite)
return -1;
- return wpa_s->driver->set_current_cipher_suite(wpa_s->drv_priv, cs,
- cs_len);
+ return wpa_s->driver->set_current_cipher_suite(wpa_s->drv_priv, cs);
}
static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s,
@@ -912,4 +918,62 @@ static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq);
}
+static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->driver->abort_scan)
+ return -1;
+ return wpa_s->driver->abort_scan(wpa_s->drv_priv);
+}
+
+static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s,
+ u32 filters)
+{
+ if (!wpa_s->driver->configure_data_frame_filters)
+ return -1;
+ return wpa_s->driver->configure_data_frame_filters(wpa_s->drv_priv,
+ filters);
+}
+
+static inline int wpa_drv_get_ext_capa(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type type)
+{
+ if (!wpa_s->driver->get_ext_capab)
+ return -1;
+ return wpa_s->driver->get_ext_capab(wpa_s->drv_priv, type,
+ &wpa_s->extended_capa,
+ &wpa_s->extended_capa_mask,
+ &wpa_s->extended_capa_len);
+}
+
+static inline int wpa_drv_p2p_lo_start(struct wpa_supplicant *wpa_s,
+ unsigned int channel,
+ unsigned int period,
+ unsigned int interval,
+ unsigned int count,
+ const u8 *device_types,
+ size_t dev_types_len,
+ const u8 *ies, size_t ies_len)
+{
+ if (!wpa_s->driver->p2p_lo_start)
+ return -1;
+ return wpa_s->driver->p2p_lo_start(wpa_s->drv_priv, channel, period,
+ interval, count, device_types,
+ dev_types_len, ies, ies_len);
+}
+
+static inline int wpa_drv_p2p_lo_stop(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->driver->p2p_lo_stop)
+ return -1;
+ return wpa_s->driver->p2p_lo_stop(wpa_s->drv_priv);
+}
+
+static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s,
+ const u8 *ies, size_t len)
+{
+ if (!wpa_s->driver->set_default_scan_ies)
+ return -1;
+ return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len);
+}
+
#endif /* DRIVER_I_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/events.c b/freebsd/contrib/wpa/wpa_supplicant/events.c
index 3cf22d4c..1ed27b58 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/events.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/events.c
@@ -74,6 +74,7 @@ static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
}
+#ifndef CONFIG_NO_SCAN_PROCESSING
/**
* wpas_reenabled_network_time - Time until first network is re-enabled
* @wpa_s: Pointer to wpa_supplicant data
@@ -109,6 +110,7 @@ static int wpas_reenabled_network_time(struct wpa_supplicant *wpa_s)
return res;
}
+#endif /* CONFIG_NO_SCAN_PROCESSING */
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx)
@@ -281,6 +283,11 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
wpa_supplicant_ap_deinit(wpa_s);
#endif /* CONFIG_AP */
+#ifdef CONFIG_HS20
+ /* Clear possibly configured frame filters */
+ wpa_drv_configure_frame_filters(wpa_s, 0);
+#endif /* CONFIG_HS20 */
+
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
return;
@@ -567,11 +574,36 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
break;
}
#endif /* CONFIG_IEEE80211W */
+ if ((ie.capabilities & WPA_CAPABILITY_MFPR) &&
+ wpas_get_ssid_pmf(wpa_s, ssid) ==
+ NO_MGMT_FRAME_PROTECTION) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled but AP requires it");
+ break;
+ }
+#ifdef CONFIG_MBO
+ if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
+ wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_AP_CAPA_IND) &&
+ wpas_get_ssid_pmf(wpa_s, ssid) !=
+ NO_MGMT_FRAME_PROTECTION) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled on MBO AP");
+ break;
+ }
+#endif /* CONFIG_MBO */
wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE");
return 1;
}
+#ifdef CONFIG_IEEE80211W
+ if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MFP Required but network not MFP Capable");
+ return 0;
+ }
+#endif /* CONFIG_IEEE80211W */
+
wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
proto_match++;
@@ -809,10 +841,10 @@ static int addr_in_list(const u8 *addr, const u8 *list, size_t num)
}
-static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
- int i, struct wpa_bss *bss,
- struct wpa_ssid *group,
- int only_first_ssid)
+struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
+ int i, struct wpa_bss *bss,
+ struct wpa_ssid *group,
+ int only_first_ssid)
{
u8 wpa_ie_len, rsn_ie_len;
int wpa;
@@ -820,6 +852,9 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
const u8 *ie;
struct wpa_ssid *ssid;
int osen;
+#ifdef CONFIG_MBO
+ const u8 *assoc_disallow;
+#endif /* CONFIG_MBO */
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0;
@@ -981,8 +1016,16 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
continue;
}
- if (!bss_is_ess(bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - not ESS network");
+ if (ssid->mode != IEEE80211_MODE_MESH && !bss_is_ess(bss) &&
+ !bss_is_pbss(bss)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - not ESS, PBSS, or MBSS");
+ continue;
+ }
+
+ if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)",
+ ssid->pbss, bss_is_pbss(bss));
continue;
}
@@ -992,6 +1035,14 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
continue;
}
+#ifdef CONFIG_MESH
+ if (ssid->mode == IEEE80211_MODE_MESH && ssid->frequency > 0 &&
+ ssid->frequency != bss->freq) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not allowed (mesh)");
+ continue;
+ }
+#endif /* CONFIG_MESH */
+
if (!rate_match(wpa_s, bss)) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do "
"not match");
@@ -1051,6 +1102,29 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
(unsigned int) diff.usec);
continue;
}
+#ifdef CONFIG_MBO
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_assoc_disallow)
+ goto skip_assoc_disallow;
+#endif /* CONFIG_TESTING_OPTIONS */
+ assoc_disallow = wpas_mbo_get_bss_attr(
+ bss, MBO_ATTR_ID_ASSOC_DISALLOW);
+ if (assoc_disallow && assoc_disallow[1] >= 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MBO association disallowed (reason %u)",
+ assoc_disallow[2]);
+ continue;
+ }
+
+ if (wpa_is_bss_tmp_disallowed(wpa_s, bss->bssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MBO retry delay has not passed yet");
+ continue;
+ }
+#ifdef CONFIG_TESTING_OPTIONS
+ skip_assoc_disallow:
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_MBO */
/* Matching configuration found */
return ssid;
@@ -1304,6 +1378,7 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
struct wpa_bss *current_bss = NULL;
#ifndef CONFIG_NO_ROAMING
int min_diff;
+ int to_5ghz;
#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
@@ -1359,7 +1434,10 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
return 1;
}
- if (current_bss->level < 0 && current_bss->level > selected->level) {
+ to_5ghz = selected->freq > 4000 && current_bss->freq < 4000;
+
+ if (current_bss->level < 0 &&
+ current_bss->level > selected->level + to_5ghz * 2) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
"signal level");
return 0;
@@ -1378,6 +1456,13 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
else
min_diff = 5;
}
+ if (to_5ghz) {
+ /* Make it easier to move to 5 GHz band */
+ if (min_diff > 2)
+ min_diff -= 2;
+ else
+ min_diff = 0;
+ }
if (abs(current_bss->level - selected->level) < min_diff) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
"in signal level");
@@ -1420,6 +1505,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
return -1;
if (!own_request)
return -1;
+ if (data && data->scan_info.external_scan)
+ return -1;
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
"scanning again");
wpa_supplicant_req_new_scan(wpa_s, 1, 0);
@@ -1444,7 +1531,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_RANDOM_POOL */
if (own_request && wpa_s->scan_res_handler &&
- (wpa_s->own_scan_running || !wpa_s->radio->external_scan_running)) {
+ !(data && data->scan_info.external_scan)) {
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
@@ -1465,9 +1552,11 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
}
wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)",
- wpa_s->own_scan_running, wpa_s->radio->external_scan_running);
+ wpa_s->own_scan_running,
+ data ? data->scan_info.external_scan : 0);
if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
- wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
+ wpa_s->manual_scan_use_id && wpa_s->own_scan_running &&
+ own_request && !(data && data->scan_info.external_scan)) {
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
wpa_s->manual_scan_id);
wpa_s->manual_scan_use_id = 0;
@@ -1478,7 +1567,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
wpas_notify_scan_done(wpa_s, 1);
- if (!wpa_s->own_scan_running && wpa_s->radio->external_scan_running) {
+ if (data && data->scan_info.external_scan) {
wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection");
wpa_scan_results_free(scan_res);
return 0;
@@ -1507,9 +1596,13 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
wpas_wps_update_ap_info(wpa_s, scan_res);
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
+ wpa_s->wpa_state < WPA_COMPLETED)
+ goto scan_work_done;
+
wpa_scan_results_free(scan_res);
- if (wpa_s->scan_work) {
+ if (own_request && wpa_s->scan_work) {
struct wpa_radio_work *work = wpa_s->scan_work;
wpa_s->scan_work = NULL;
radio_work_done(work);
@@ -1519,7 +1612,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
scan_work_done:
wpa_scan_results_free(scan_res);
- if (wpa_s->scan_work) {
+ if (own_request && wpa_s->scan_work) {
struct wpa_radio_work *work = wpa_s->scan_work;
wpa_s->scan_work = NULL;
radio_work_done(work);
@@ -1550,6 +1643,14 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
+#ifdef CONFIG_MESH
+ if (wpa_s->ifmsh) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Avoiding join because we already joined a mesh group");
+ return 0;
+ }
+#endif /* CONFIG_MESH */
+
if (selected) {
int skip;
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);
@@ -1559,6 +1660,13 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
return 0;
}
+ if (ssid != wpa_s->current_ssid &&
+ wpa_s->wpa_state >= WPA_AUTHENTICATING) {
+ wpa_s->own_disconnect_req = 1;
+ wpa_supplicant_deauthenticate(
+ wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
+
if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Connect failed");
return -1;
@@ -1571,13 +1679,6 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
*/
return 1;
} else {
-#ifdef CONFIG_MESH
- if (wpa_s->ifmsh) {
- wpa_msg(wpa_s, MSG_INFO,
- "Avoiding join because we already joined a mesh group");
- return 0;
- }
-#endif /* CONFIG_MESH */
wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
ssid = wpa_supplicant_pick_new_network(wpa_s);
if (ssid) {
@@ -1833,6 +1934,50 @@ static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_FST
+static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
+ const u8 *ie, size_t ie_len)
+{
+ struct mb_ies_info mb_ies;
+
+ if (!ie || !ie_len || !wpa_s->fst)
+ return -ENOENT;
+
+ os_memset(&mb_ies, 0, sizeof(mb_ies));
+
+ while (ie_len >= 2 && mb_ies.nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
+ size_t len;
+
+ len = 2 + ie[1];
+ if (len > ie_len) {
+ wpa_hexdump(MSG_DEBUG, "FST: Truncated IE found",
+ ie, ie_len);
+ break;
+ }
+
+ if (ie[0] == WLAN_EID_MULTI_BAND) {
+ wpa_printf(MSG_DEBUG, "MB IE of %u bytes found",
+ (unsigned int) len);
+ mb_ies.ies[mb_ies.nof_ies].ie = ie + 2;
+ mb_ies.ies[mb_ies.nof_ies].ie_len = len - 2;
+ mb_ies.nof_ies++;
+ }
+
+ ie_len -= len;
+ ie += len;
+ }
+
+ if (mb_ies.nof_ies > 0) {
+ wpabuf_free(wpa_s->received_mb_ies);
+ wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+#endif /* CONFIG_FST */
+
+
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
@@ -1883,6 +2028,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
}
if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
(os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
+ (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
+ (os_memcmp(&p[2], "\x50\x6F\x9A\x12", 4) == 0)) ||
(p[0] == WLAN_EID_RSN && p[1] >= 2)) {
if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
break;
@@ -2015,19 +2162,6 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1;
-#ifdef CONFIG_FST
- wpabuf_free(wpa_s->received_mb_ies);
- wpa_s->received_mb_ies = NULL;
- if (wpa_s->fst) {
- struct mb_ies_info mb_ies;
-
- wpa_printf(MSG_DEBUG, "Looking for MB IE");
- if (!mb_ies_info_by_ies(&mb_ies, data->assoc_info.resp_ies,
- data->assoc_info.resp_ies_len))
- wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
- }
-#endif /* CONFIG_FST */
-
if (wpa_s->assoc_freq && data->assoc_info.freq &&
wpa_s->assoc_freq != data->assoc_info.freq) {
wpa_printf(MSG_DEBUG, "Operating frequency changed from "
@@ -2066,11 +2200,50 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
}
+static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+#ifdef CONFIG_FST
+ struct assoc_info *ai = data ? &data->assoc_info : NULL;
+ struct wpa_bss *bss = wpa_s->current_bss;
+ const u8 *ieprb, *iebcn;
+
+ wpabuf_free(wpa_s->received_mb_ies);
+ wpa_s->received_mb_ies = NULL;
+
+ if (ai &&
+ !wpas_fst_update_mbie(wpa_s, ai->resp_ies, ai->resp_ies_len)) {
+ wpa_printf(MSG_DEBUG,
+ "FST: MB IEs updated from Association Response frame");
+ return;
+ }
+
+ if (ai &&
+ !wpas_fst_update_mbie(wpa_s, ai->beacon_ies, ai->beacon_ies_len)) {
+ wpa_printf(MSG_DEBUG,
+ "FST: MB IEs updated from association event Beacon IEs");
+ return;
+ }
+
+ if (!bss)
+ return;
+
+ ieprb = (const u8 *) (bss + 1);
+ iebcn = ieprb + bss->ie_len;
+
+ if (!wpas_fst_update_mbie(wpa_s, ieprb, bss->ie_len))
+ wpa_printf(MSG_DEBUG, "FST: MB IEs updated from bss IE");
+ else if (!wpas_fst_update_mbie(wpa_s, iebcn, bss->beacon_ie_len))
+ wpa_printf(MSG_DEBUG, "FST: MB IEs updated from bss beacon IE");
+#endif /* CONFIG_FST */
+}
+
+
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
u8 bssid[ETH_ALEN];
- int ft_completed;
+ int ft_completed, already_authorized;
int new_bss = 0;
#ifdef CONFIG_AP
@@ -2126,6 +2299,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
"WPA/RSN IEs not updated");
}
+ wpas_fst_update_mb_assoc(wpa_s, data);
+
#ifdef CONFIG_SME
os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
wpa_s->sme.prev_bssid_set = 1;
@@ -2144,6 +2319,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
if (wpa_s->l2)
l2_packet_notify_auth_start(wpa_s->l2);
+ already_authorized = data && data->assoc_info.authorized;
+
/*
* Set portEnabled first to FALSE in order to get EAP state machine out
* of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE
@@ -2152,11 +2329,12 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
* AUTHENTICATED without ever giving chance to EAP state machine to
* reset the state.
*/
- if (!ft_completed) {
+ if (!ft_completed && !already_authorized) {
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed)
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed ||
+ already_authorized)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
/* 802.1X::portControl = Auto */
eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
@@ -2248,7 +2426,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE &&
wpa_s->ibss_rsn == NULL) {
- wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
+ wpa_s->ibss_rsn = ibss_rsn_init(wpa_s, wpa_s->current_ssid);
if (!wpa_s->ibss_rsn) {
wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN");
wpa_supplicant_deauthenticate(
@@ -2342,6 +2520,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
struct wpa_bss *fast_reconnect = NULL;
struct wpa_ssid *fast_reconnect_ssid = NULL;
struct wpa_ssid *last_ssid;
+ struct wpa_bss *curr = NULL;
authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
@@ -2357,6 +2536,19 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
return;
}
+ if (!wpa_s->disconnected && wpa_s->wpa_state >= WPA_AUTHENTICATING &&
+ reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY &&
+ locally_generated)
+ /*
+ * Remove the inactive AP (which is probably out of range) from
+ * the BSS list after marking disassociation. In particular
+ * mac80211-based drivers use the
+ * WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY reason code in
+ * locally generated disconnection events for cases where the
+ * AP does not reply anymore.
+ */
+ curr = wpa_s->current_bss;
+
if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
"pre-shared key may be incorrect");
@@ -2367,7 +2559,8 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
if (!wpa_s->disconnected &&
(!wpa_s->auto_reconnect_disabled ||
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS ||
- wpas_wps_searching(wpa_s))) {
+ wpas_wps_searching(wpa_s) ||
+ wpas_wps_reenable_networks_pending(wpa_s))) {
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
"reconnect (wps=%d/%d wpa_state=%d)",
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
@@ -2417,6 +2610,9 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
last_ssid = wpa_s->current_ssid;
wpa_supplicant_mark_disassoc(wpa_s);
+ if (curr)
+ wpa_bss_remove(wpa_s, curr, "Connection to AP lost");
+
if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
wpa_s->current_ssid = last_ssid;
@@ -2427,7 +2623,8 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
!disallowed_bssid(wpa_s, fast_reconnect->bssid) &&
!disallowed_ssid(wpa_s, fast_reconnect->ssid,
fast_reconnect->ssid_len) &&
- !wpas_temp_disabled(wpa_s, fast_reconnect_ssid)) {
+ !wpas_temp_disabled(wpa_s, fast_reconnect_ssid) &&
+ !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect->bssid)) {
#ifndef CONFIG_NO_SCAN_PROCESSING
wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
if (wpa_supplicant_connect(wpa_s, fast_reconnect,
@@ -2625,6 +2822,13 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ if (wpa_s->matched) {
+ wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
+ break;
+ }
+#endif /* CONFIG_MATCH_IFACE */
+
#ifdef CONFIG_TERMINATE_ONLASTIF
/* check if last interface */
if (!any_interfaces(wpa_s->global->ifaces))
@@ -3010,7 +3214,16 @@ static void wpa_supplicant_update_channel_list(
{
struct wpa_supplicant *ifs;
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+ /*
+ * To allow backwards compatibility with higher level layers that
+ * assumed the REGDOM_CHANGE event is sent over the initially added
+ * interface. Find the highest parent of this interface and use it to
+ * send the event.
+ */
+ for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent)
+ ;
+
+ wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
reg_init_str(info->initiator), reg_type_str(info->type),
info->alpha2[0] ? " alpha2=" : "",
info->alpha2[0] ? info->alpha2 : "");
@@ -3025,14 +3238,16 @@ static void wpa_supplicant_update_channel_list(
free_hw_features(ifs);
ifs->hw.modes = wpa_drv_get_hw_feature_data(
ifs, &ifs->hw.num_modes, &ifs->hw.flags);
- }
- /* Restart sched_scan with updated channel list */
- if (wpa_s->sched_scanning) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- "Channel list changed restart sched scan.");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ /* Restart PNO/sched_scan with updated channel list */
+ if (ifs->pno) {
+ wpas_stop_pno(ifs);
+ wpas_start_pno(ifs);
+ } else if (ifs->sched_scanning && !ifs->pno_sched_pending) {
+ wpa_dbg(ifs, MSG_DEBUG,
+ "Channel list changed - restart sched_scan");
+ wpas_scan_restart_sched_scan(ifs);
+ }
}
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DRIVER);
@@ -3123,6 +3338,14 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
+ payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
+ wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
+ payload + 1,
+ plen - 1);
+ return;
+ }
+
+ if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
payload[0] == WLAN_RRM_NEIGHBOR_REPORT_RESPONSE) {
wpas_rrm_process_neighbor_rep(wpa_s, payload + 1, plen - 1);
return;
@@ -3212,6 +3435,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
event != EVENT_INTERFACE_STATUS &&
+ event != EVENT_SCAN_RESULTS &&
event != EVENT_SCHED_SCAN_STOPPED) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Ignore event %s (%d) while interface is disabled",
@@ -3240,18 +3464,43 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
switch (event) {
case EVENT_AUTH:
+#ifdef CONFIG_FST
+ if (!wpas_fst_update_mbie(wpa_s, data->auth.ies,
+ data->auth.ies_len))
+ wpa_printf(MSG_DEBUG,
+ "FST: MB IEs updated from auth IE");
+#endif /* CONFIG_FST */
sme_event_auth(wpa_s, data);
break;
case EVENT_ASSOC:
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_auth_resp) {
+ wpa_printf(MSG_INFO,
+ "EVENT_ASSOC - ignore_auth_resp active!");
+ break;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
wpa_supplicant_event_assoc(wpa_s, data);
if (data && data->assoc_info.authorized)
wpa_supplicant_event_assoc_auth(wpa_s, data);
+ if (data) {
+ wpa_msg(wpa_s, MSG_INFO,
+ WPA_EVENT_SUBNET_STATUS_UPDATE "status=%u",
+ data->assoc_info.subnet_status);
+ }
break;
case EVENT_DISASSOC:
wpas_event_disassoc(wpa_s,
data ? &data->disassoc_info : NULL);
break;
case EVENT_DEAUTH:
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_auth_resp) {
+ wpa_printf(MSG_INFO,
+ "EVENT_DEAUTH - ignore_auth_resp active!");
+ break;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
wpas_event_deauth(wpa_s,
data ? &data->deauth_info : NULL);
break;
@@ -3260,10 +3509,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#ifndef CONFIG_NO_SCAN_PROCESSING
case EVENT_SCAN_STARTED:
- os_get_reltime(&wpa_s->scan_start_time);
- if (wpa_s->own_scan_requested) {
+ if (wpa_s->own_scan_requested ||
+ (data && !data->scan_info.external_scan)) {
struct os_reltime diff;
+ os_get_reltime(&wpa_s->scan_start_time);
os_reltime_sub(&wpa_s->scan_start_time,
&wpa_s->scan_trigger_time, &diff);
wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds",
@@ -3286,7 +3536,16 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
break;
case EVENT_SCAN_RESULTS:
- if (os_reltime_initialized(&wpa_s->scan_start_time)) {
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ wpa_s->scan_res_handler = NULL;
+ wpa_s->own_scan_running = 0;
+ wpa_s->radio->external_scan_running = 0;
+ wpa_s->last_scan_req = NORMAL_SCAN_REQ;
+ break;
+ }
+
+ if (!(data && data->scan_info.external_scan) &&
+ os_reltime_initialized(&wpa_s->scan_start_time)) {
struct os_reltime now, diff;
os_get_reltime(&now);
os_reltime_sub(&now, &wpa_s->scan_start_time, &diff);
@@ -3297,8 +3556,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
if (wpa_supplicant_event_scan_results(wpa_s, data))
break; /* interface may have been removed */
- wpa_s->own_scan_running = 0;
- wpa_s->radio->external_scan_running = 0;
+ if (!(data && data->scan_info.external_scan))
+ wpa_s->own_scan_running = 0;
+ if (data && data->scan_info.nl_scan_event)
+ wpa_s->radio->external_scan_running = 0;
radio_work_check_next(wpa_s);
break;
#endif /* CONFIG_NO_SCAN_PROCESSING */
@@ -3339,13 +3600,17 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_ASSOC_REJECT:
if (data->assoc_reject.bssid)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "bssid=" MACSTR " status_code=%u",
+ "bssid=" MACSTR " status_code=%u%s",
MAC2STR(data->assoc_reject.bssid),
- data->assoc_reject.status_code);
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "");
else
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "status_code=%u",
- data->assoc_reject.status_code);
+ "status_code=%u%s",
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "");
+ wpa_s->assoc_status_code = data->assoc_reject.status_code;
+ wpas_notify_assoc_status_code(wpa_s);
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
sme_event_assoc_reject(wpa_s, data);
else {
@@ -3401,17 +3666,20 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_AP */
#ifdef CONFIG_OFFCHANNEL
wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst="
- MACSTR, MAC2STR(wpa_s->parent->pending_action_dst));
+ MACSTR, MAC2STR(wpa_s->p2pdev->pending_action_dst));
/*
* Catch TX status events for Action frames we sent via group
- * interface in GO mode.
+ * interface in GO mode, or via standalone AP interface.
+ * Note, wpa_s->p2pdev will be the same as wpa_s->parent,
+ * except when the primary interface is used as a GO interface
+ * (for drivers which do not have group interface concurrency)
*/
if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
- os_memcmp(wpa_s->parent->pending_action_dst,
+ os_memcmp(wpa_s->p2pdev->pending_action_dst,
data->tx_status.dst, ETH_ALEN) == 0) {
offchannel_send_action_tx_status(
- wpa_s->parent, data->tx_status.dst,
+ wpa_s->p2pdev, data->tx_status.dst,
data->tx_status.data,
data->tx_status.data_len,
data->tx_status.ack ?
@@ -3454,20 +3722,34 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->rx_from_unknown.wds);
break;
case EVENT_CH_SWITCH:
- if (!data)
- break;
- if (!wpa_s->ap_iface) {
- wpa_dbg(wpa_s, MSG_DEBUG, "AP: Ignore channel switch "
- "event in non-AP mode");
+ if (!data || !wpa_s->current_ssid)
break;
+
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
+ "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+ data->ch_switch.freq,
+ data->ch_switch.ht_enabled,
+ data->ch_switch.ch_offset,
+ channel_width_to_string(data->ch_switch.ch_width),
+ data->ch_switch.cf1,
+ data->ch_switch.cf2);
+
+ wpa_s->assoc_freq = data->ch_switch.freq;
+ wpa_s->current_ssid->frequency = data->ch_switch.freq;
+
+ if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
+ wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
+ wpa_s->current_ssid->mode ==
+ WPAS_MODE_P2P_GROUP_FORMATION) {
+ wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
+ data->ch_switch.ht_enabled,
+ data->ch_switch.ch_offset,
+ data->ch_switch.ch_width,
+ data->ch_switch.cf1,
+ data->ch_switch.cf2);
}
- wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
- data->ch_switch.ht_enabled,
- data->ch_switch.ch_offset,
- data->ch_switch.ch_width,
- data->ch_switch.cf1,
- data->ch_switch.cf2);
+ wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
break;
#ifdef NEED_AP_MLME
case EVENT_DFS_RADAR_DETECTED:
@@ -3524,12 +3806,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_AP */
#ifdef CONFIG_P2P
if (stype == WLAN_FC_STYPE_PROBE_REQ &&
- data->rx_mgmt.frame_len > 24) {
+ data->rx_mgmt.frame_len > IEEE80211_HDRLEN) {
const u8 *src = mgmt->sa;
- const u8 *ie = mgmt->u.probe_req.variable;
- size_t ie_len = data->rx_mgmt.frame_len -
- (mgmt->u.probe_req.variable -
- data->rx_mgmt.frame);
+ const u8 *ie;
+ size_t ie_len;
+
+ ie = data->rx_mgmt.frame + IEEE80211_HDRLEN;
+ ie_len = data->rx_mgmt.frame_len -
+ IEEE80211_HDRLEN;
wpas_p2p_probe_req_rx(
wpa_s, src, mgmt->da,
mgmt->bssid, ie, ie_len,
@@ -3569,11 +3853,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
if (stype == WLAN_FC_STYPE_PROBE_REQ &&
- data->rx_mgmt.frame_len > 24) {
- const u8 *ie = mgmt->u.probe_req.variable;
- size_t ie_len = data->rx_mgmt.frame_len -
- (mgmt->u.probe_req.variable -
- data->rx_mgmt.frame);
+ data->rx_mgmt.frame_len > IEEE80211_HDRLEN) {
+ const u8 *ie;
+ size_t ie_len;
+
+ ie = data->rx_mgmt.frame + IEEE80211_HDRLEN;
+ ie_len = data->rx_mgmt.frame_len - IEEE80211_HDRLEN;
wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da,
mgmt->bssid, ie, ie_len,
@@ -3716,6 +4001,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1);
}
wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_bss_flush(wpa_s);
radio_remove_works(wpa_s, NULL, 0);
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
@@ -3774,15 +4060,28 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->driver_gtk_rekey.replay_ctr);
break;
case EVENT_SCHED_SCAN_STOPPED:
- wpa_s->pno = 0;
wpa_s->sched_scanning = 0;
- resched = wpa_s->scanning;
+ resched = wpa_s->scanning && wpas_scan_scheduled(wpa_s);
wpa_supplicant_notify_scanning(wpa_s, 0);
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
break;
/*
+ * If the driver stopped scanning without being requested to,
+ * request a new scan to continue scanning for networks.
+ */
+ if (!wpa_s->sched_scan_stop_req &&
+ wpa_s->wpa_state == WPA_SCANNING) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Restart scanning after unexpected sched_scan stop event");
+ wpa_supplicant_req_scan(wpa_s, 1, 0);
+ break;
+ }
+
+ wpa_s->sched_scan_stop_req = 0;
+
+ /*
* Start a new sched scan to continue searching for more SSIDs
* either if timed out or PNO schedule scan is pending.
*/
@@ -3823,8 +4122,72 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->mesh_peer.ie_len);
#endif /* CONFIG_MESH */
break;
+ case EVENT_SURVEY:
+#ifdef CONFIG_AP
+ if (!wpa_s->ap_iface)
+ break;
+ hostapd_event_get_survey(wpa_s->ap_iface,
+ &data->survey_results);
+#endif /* CONFIG_AP */
+ break;
+ case EVENT_ACS_CHANNEL_SELECTED:
+#ifdef CONFIG_ACS
+ if (!wpa_s->ap_iface)
+ break;
+ hostapd_acs_channel_selected(wpa_s->ap_iface->bss[0],
+ &data->acs_selected_channels);
+#endif /* CONFIG_ACS */
+ break;
+ case EVENT_P2P_LO_STOP:
+#ifdef CONFIG_P2P
+ wpa_s->p2p_lo_started = 0;
+ wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_LISTEN_OFFLOAD_STOP
+ P2P_LISTEN_OFFLOAD_STOP_REASON "reason=%d",
+ data->p2p_lo_stop.reason_code);
+#endif /* CONFIG_P2P */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;
}
}
+
+
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+{
+ struct wpa_supplicant *wpa_s;
+
+ if (event != EVENT_INTERFACE_STATUS)
+ return;
+
+ wpa_s = wpa_supplicant_get_iface(ctx, data->interface_status.ifname);
+ if (wpa_s && wpa_s->driver->get_ifindex) {
+ unsigned int ifindex;
+
+ ifindex = wpa_s->driver->get_ifindex(wpa_s->drv_priv);
+ if (ifindex != data->interface_status.ifindex) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "interface status ifindex %d mismatch (%d)",
+ ifindex, data->interface_status.ifindex);
+ return;
+ }
+ }
+#ifdef CONFIG_MATCH_IFACE
+ else if (data->interface_status.ievent == EVENT_INTERFACE_ADDED) {
+ struct wpa_interface *wpa_i;
+
+ wpa_i = wpa_supplicant_match_iface(
+ ctx, data->interface_status.ifname);
+ if (!wpa_i)
+ return;
+ wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, NULL);
+ os_free(wpa_i);
+ if (wpa_s)
+ wpa_s->matched = 1;
+ }
+#endif /* CONFIG_MATCH_IFACE */
+
+ if (wpa_s)
+ wpa_supplicant_event(wpa_s, event, data);
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/gas_query.c b/freebsd/contrib/wpa/wpa_supplicant/gas_query.c
index a93f8064..c099bc9a 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/gas_query.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/gas_query.c
@@ -19,6 +19,7 @@
#include "common/wpa_ctrl.h"
#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
+#include "config.h"
#include "driver_i.h"
#include "offchannel.h"
#include "gas_query.h"
@@ -27,6 +28,9 @@
/** GAS query timeout in seconds */
#define GAS_QUERY_TIMEOUT_PERIOD 2
+/* GAS query wait-time / duration in ms */
+#define GAS_QUERY_WAIT_TIME_INITIAL 1000
+#define GAS_QUERY_WAIT_TIME_COMEBACK 150
/**
* struct gas_query_pending - Pending GAS query
@@ -39,6 +43,7 @@ struct gas_query_pending {
u8 next_frag_id;
unsigned int wait_comeback:1;
unsigned int offchannel_tx_started:1;
+ unsigned int retry:1;
int freq;
u16 status_code;
struct wpabuf *req;
@@ -65,6 +70,10 @@ struct gas_query {
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx);
static void gas_query_timeout(void *eloop_data, void *user_ctx);
+static void gas_query_rx_comeback_timeout(void *eloop_data, void *user_ctx);
+static void gas_query_tx_initial_req(struct gas_query *gas,
+ struct gas_query_pending *query);
+static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst);
static int ms_from_time(struct os_reltime *last)
@@ -110,8 +119,6 @@ static const char * gas_result_txt(enum gas_query_result result)
return "PEER_ERROR";
case GAS_QUERY_INTERNAL_ERROR:
return "INTERNAL_ERROR";
- case GAS_QUERY_CANCELLED:
- return "CANCELLED";
case GAS_QUERY_DELETED_AT_DEINIT:
return "DELETED_AT_DEINIT";
}
@@ -153,6 +160,7 @@ static void gas_query_done(struct gas_query *gas,
offchannel_send_action_done(gas->wpa_s);
eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
eloop_cancel_timeout(gas_query_timeout, gas, query);
+ eloop_cancel_timeout(gas_query_rx_comeback_timeout, gas, query);
dl_list_del(&query->list);
query->cb(query->ctx, query->addr, query->dialog_token, result,
query->adv_proto, query->resp, query->status_code);
@@ -237,6 +245,13 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
eloop_cancel_timeout(gas_query_timeout, gas, query);
eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
gas_query_timeout, gas, query);
+ if (query->wait_comeback && !query->retry) {
+ eloop_cancel_timeout(gas_query_rx_comeback_timeout,
+ gas, query);
+ eloop_register_timeout(
+ 0, (GAS_QUERY_WAIT_TIME_COMEBACK + 10) * 1000,
+ gas_query_rx_comeback_timeout, gas, query);
+ }
}
if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
eloop_cancel_timeout(gas_query_timeout, gas, query);
@@ -256,10 +271,13 @@ static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
- struct wpabuf *req)
+ struct wpabuf *req, unsigned int wait_time)
{
- unsigned int wait_time;
int res, prot = pmf_in_use(gas->wpa_s, query->addr);
+ const u8 *bssid;
+ const u8 wildcard_bssid[ETH_ALEN] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
"freq=%d prot=%d", MAC2STR(query->addr),
@@ -269,12 +287,18 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
*categ = WLAN_ACTION_PROTECTED_DUAL;
}
os_get_reltime(&query->last_oper);
- wait_time = 1000;
if (gas->wpa_s->max_remain_on_chan &&
wait_time > gas->wpa_s->max_remain_on_chan)
wait_time = gas->wpa_s->max_remain_on_chan;
+ if (!gas->wpa_s->conf->gas_address3 ||
+ (gas->wpa_s->current_ssid &&
+ gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
+ os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0))
+ bssid = query->addr;
+ else
+ bssid = wildcard_bssid;
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
- gas->wpa_s->own_addr, query->addr,
+ gas->wpa_s->own_addr, bssid,
wpabuf_head(req), wpabuf_len(req),
wait_time, gas_query_tx_status, 0);
if (res == 0)
@@ -287,6 +311,7 @@ static void gas_query_tx_comeback_req(struct gas_query *gas,
struct gas_query_pending *query)
{
struct wpabuf *req;
+ unsigned int wait_time;
req = gas_build_comeback_req(query->dialog_token);
if (req == NULL) {
@@ -294,7 +319,10 @@ static void gas_query_tx_comeback_req(struct gas_query *gas,
return;
}
- if (gas_query_tx(gas, query, req) < 0) {
+ wait_time = (query->retry || !query->offchannel_tx_started) ?
+ GAS_QUERY_WAIT_TIME_INITIAL : GAS_QUERY_WAIT_TIME_COMEBACK;
+
+ if (gas_query_tx(gas, query, req, wait_time) < 0) {
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
MACSTR, MAC2STR(query->addr));
gas_query_done(gas, query, GAS_QUERY_INTERNAL_ERROR);
@@ -304,6 +332,35 @@ static void gas_query_tx_comeback_req(struct gas_query *gas,
}
+static void gas_query_rx_comeback_timeout(void *eloop_data, void *user_ctx)
+{
+ struct gas_query *gas = eloop_data;
+ struct gas_query_pending *query = user_ctx;
+ int dialog_token;
+
+ wpa_printf(MSG_DEBUG,
+ "GAS: No response to comeback request received (retry=%u)",
+ query->retry);
+ if (gas->current != query || query->retry)
+ return;
+ dialog_token = gas_query_new_dialog_token(gas, query->addr);
+ if (dialog_token < 0)
+ return;
+ wpa_printf(MSG_DEBUG,
+ "GAS: Retry GAS query due to comeback response timeout");
+ query->retry = 1;
+ query->dialog_token = dialog_token;
+ *(wpabuf_mhead_u8(query->req) + 2) = dialog_token;
+ query->wait_comeback = 0;
+ query->next_frag_id = 0;
+ wpabuf_free(query->adv_proto);
+ query->adv_proto = NULL;
+ eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
+ eloop_cancel_timeout(gas_query_timeout, gas, query);
+ gas_query_tx_initial_req(gas, query);
+}
+
+
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx)
{
struct gas_query *gas = eloop_data;
@@ -321,6 +378,11 @@ static void gas_query_tx_comeback_req_delay(struct gas_query *gas,
{
unsigned int secs, usecs;
+ if (comeback_delay > 1 && query->offchannel_tx_started) {
+ offchannel_send_action_done(gas->wpa_s);
+ query->offchannel_tx_started = 0;
+ }
+
secs = (comeback_delay * 1024) / 1000000;
usecs = comeback_delay * 1024 - secs * 1000000;
wpa_printf(MSG_DEBUG, "GAS: Send comeback request to " MACSTR
@@ -373,6 +435,7 @@ static void gas_query_rx_comeback(struct gas_query *gas,
"comeback_delay=%u)",
MAC2STR(query->addr), query->dialog_token, frag_id,
more_frags, comeback_delay);
+ eloop_cancel_timeout(gas_query_rx_comeback_timeout, gas, query);
if ((size_t) 2 + adv_proto[1] != wpabuf_len(query->adv_proto) ||
os_memcmp(adv_proto, wpabuf_head(query->adv_proto),
@@ -449,8 +512,16 @@ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
if (gas == NULL || len < 4)
return -1;
+ pos = data;
+ action = *pos++;
+ dialog_token = *pos++;
+
+ if (action != WLAN_PA_GAS_INITIAL_RESP &&
+ action != WLAN_PA_GAS_COMEBACK_RESP)
+ return -1; /* Not a GAS response */
+
prot = categ == WLAN_ACTION_PROTECTED_DUAL;
- pmf = pmf_in_use(gas->wpa_s, bssid);
+ pmf = pmf_in_use(gas->wpa_s, sa);
if (prot && !pmf) {
wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled");
return 0;
@@ -460,14 +531,6 @@ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
return 0;
}
- pos = data;
- action = *pos++;
- dialog_token = *pos++;
-
- if (action != WLAN_PA_GAS_INITIAL_RESP &&
- action != WLAN_PA_GAS_COMEBACK_RESP)
- return -1; /* Not a GAS response */
-
query = gas_query_get_pending(gas, sa, dialog_token);
if (query == NULL) {
wpa_printf(MSG_DEBUG, "GAS: No pending query found for " MACSTR
@@ -622,11 +685,18 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit)
}
gas->work = work;
+ gas_query_tx_initial_req(gas, query);
+}
- if (gas_query_tx(gas, query, query->req) < 0) {
+
+static void gas_query_tx_initial_req(struct gas_query *gas,
+ struct gas_query_pending *query)
+{
+ if (gas_query_tx(gas, query, query->req,
+ GAS_QUERY_WAIT_TIME_INITIAL) < 0) {
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
MACSTR, MAC2STR(query->addr));
- gas_query_free(query, 1);
+ gas_query_done(gas, query, GAS_QUERY_INTERNAL_ERROR);
return;
}
gas->current = query;
@@ -635,7 +705,24 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit)
query->dialog_token);
eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
gas_query_timeout, gas, query);
+}
+
+
+static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
+{
+ static int next_start = 0;
+ int dialog_token;
+ for (dialog_token = 0; dialog_token < 256; dialog_token++) {
+ if (gas_query_dialog_token_available(
+ gas, dst, (next_start + dialog_token) % 256))
+ break;
+ }
+ if (dialog_token == 256)
+ return -1; /* Too many pending queries */
+ dialog_token = (next_start + dialog_token) % 256;
+ next_start = (dialog_token + 1) % 256;
+ return dialog_token;
}
@@ -660,20 +747,13 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
{
struct gas_query_pending *query;
int dialog_token;
- static int next_start = 0;
if (wpabuf_len(req) < 3)
return -1;
- for (dialog_token = 0; dialog_token < 256; dialog_token++) {
- if (gas_query_dialog_token_available(
- gas, dst, (next_start + dialog_token) % 256))
- break;
- }
- if (dialog_token == 256)
- return -1; /* Too many pending queries */
- dialog_token = (next_start + dialog_token) % 256;
- next_start = (dialog_token + 1) % 256;
+ dialog_token = gas_query_new_dialog_token(gas, dst);
+ if (dialog_token < 0)
+ return -1;
query = os_zalloc(sizeof(*query));
if (query == NULL)
@@ -696,26 +776,10 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb,
query) < 0) {
+ query->req = NULL; /* caller will free this in error case */
gas_query_free(query, 1);
return -1;
}
return dialog_token;
}
-
-
-/**
- * gas_query_cancel - Cancel a pending GAS query
- * @gas: GAS query data from gas_query_init()
- * @dst: Destination MAC address for the query
- * @dialog_token: Dialog token from gas_query_req()
- */
-void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token)
-{
- struct gas_query_pending *query;
-
- query = gas_query_get_pending(gas, dst, dialog_token);
- if (query)
- gas_query_done(gas, query, GAS_QUERY_CANCELLED);
-
-}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/gas_query.h b/freebsd/contrib/wpa/wpa_supplicant/gas_query.h
index ad134908..ef82097e 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/gas_query.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/gas_query.h
@@ -29,7 +29,6 @@ enum gas_query_result {
GAS_QUERY_TIMEOUT,
GAS_QUERY_PEER_ERROR,
GAS_QUERY_INTERNAL_ERROR,
- GAS_QUERY_CANCELLED,
GAS_QUERY_DELETED_AT_DEINIT
};
@@ -40,7 +39,6 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
const struct wpabuf *adv_proto,
const struct wpabuf *resp, u16 status_code),
void *ctx);
-void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token);
#else /* CONFIG_GAS */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c
index ab52320d..44be415a 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c
@@ -27,6 +27,7 @@
#include "gas_query.h"
#include "interworking.h"
#include "hs20_supplicant.h"
+#include "base64.h"
#define OSU_MAX_ITEMS 10
@@ -62,6 +63,46 @@ struct osu_provider {
};
+void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss *bss = wpa_s->current_bss;
+ u8 *bssid = wpa_s->bssid;
+ const u8 *ie;
+ const u8 *ext_capa;
+ u32 filter = 0;
+
+ if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)) {
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - BSS " MACSTR
+ " is not a Hotspot 2.0 network", MAC2STR(bssid));
+ return;
+ }
+
+ ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
+
+ /* Check if DGAF disabled bit is zero (5th byte in the IE) */
+ if (!ie || ie[1] < 5)
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - Can't extract DGAF bit");
+ else if (!(ie[6] & HS20_DGAF_DISABLED))
+ filter |= WPA_DATA_FRAME_FILTER_FLAG_GTK;
+
+ ext_capa = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
+ if (!ext_capa || ext_capa[1] < 2) {
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - Can't extract Proxy ARP bit");
+ return;
+ }
+
+ /* Check if Proxy ARP is enabled (2nd byte in the IE) */
+ if (ext_capa[3] & BIT(4))
+ filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
+ WPA_DATA_FRAME_FILTER_FLAG_NA;
+
+ wpa_drv_configure_frame_filters(wpa_s, filter);
+}
+
+
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
{
u8 conf;
@@ -166,8 +207,8 @@ void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
}
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
- size_t payload_len)
+static struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
+ size_t payload_len)
{
struct wpabuf *buf;
@@ -182,13 +223,14 @@ struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
- const u8 *payload, size_t payload_len)
+ const u8 *payload, size_t payload_len, int inmem)
{
struct wpabuf *buf;
int ret = 0;
int freq;
struct wpa_bss *bss;
int res;
+ struct icon_entry *icon_entry;
bss = wpa_bss_get_bssid(wpa_s, dst);
if (!bss) {
@@ -212,15 +254,127 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
if (res < 0) {
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
wpabuf_free(buf);
- ret = -1;
+ return -1;
} else
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
"%u", res);
+ if (inmem) {
+ icon_entry = os_zalloc(sizeof(struct icon_entry));
+ if (!icon_entry)
+ return -1;
+ os_memcpy(icon_entry->bssid, dst, ETH_ALEN);
+ icon_entry->file_name = os_malloc(payload_len + 1);
+ if (!icon_entry->file_name) {
+ os_free(icon_entry);
+ return -1;
+ }
+ os_memcpy(icon_entry->file_name, payload, payload_len);
+ icon_entry->file_name[payload_len] = '\0';
+ icon_entry->dialog_token = res;
+
+ dl_list_add(&wpa_s->icon_head, &icon_entry->list);
+ }
+
return ret;
}
+static struct icon_entry * hs20_find_icon(struct wpa_supplicant *wpa_s,
+ const u8 *bssid,
+ const char *file_name)
+{
+ struct icon_entry *icon;
+
+ dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
+ if (os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0 &&
+ os_strcmp(icon->file_name, file_name) == 0 && icon->image)
+ return icon;
+ }
+
+ return NULL;
+}
+
+
+int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, size_t offset, size_t size,
+ char *reply, size_t buf_len)
+{
+ struct icon_entry *icon;
+ size_t out_size;
+ unsigned char *b64;
+ size_t b64_size;
+ int reply_size;
+
+ wpa_printf(MSG_DEBUG, "HS20: Get icon " MACSTR " %s @ %u +%u (%u)",
+ MAC2STR(bssid), file_name, (unsigned int) offset,
+ (unsigned int) size, (unsigned int) buf_len);
+
+ icon = hs20_find_icon(wpa_s, bssid, file_name);
+ if (!icon || !icon->image || offset >= icon->image_len)
+ return -1;
+ if (size > icon->image_len - offset)
+ size = icon->image_len - offset;
+ out_size = buf_len - 3 /* max base64 padding */;
+ if (size * 4 > out_size * 3)
+ size = out_size * 3 / 4;
+ if (size == 0)
+ return -1;
+
+ b64 = base64_encode(&icon->image[offset], size, &b64_size);
+ if (b64 && buf_len >= b64_size) {
+ os_memcpy(reply, b64, b64_size);
+ reply_size = b64_size;
+ } else {
+ reply_size = -1;
+ }
+ os_free(b64);
+ return reply_size;
+}
+
+
+static void hs20_free_icon_entry(struct icon_entry *icon)
+{
+ wpa_printf(MSG_DEBUG, "HS20: Free stored icon from " MACSTR
+ " dialog_token=%u file_name=%s image_len=%u",
+ MAC2STR(icon->bssid), icon->dialog_token,
+ icon->file_name ? icon->file_name : "N/A",
+ (unsigned int) icon->image_len);
+ os_free(icon->file_name);
+ os_free(icon->image);
+ os_free(icon);
+}
+
+
+int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name)
+{
+ struct icon_entry *icon, *tmp;
+ int count = 0;
+
+ if (!bssid)
+ wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons");
+ else if (!file_name)
+ wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons for "
+ MACSTR, MAC2STR(bssid));
+ else
+ wpa_printf(MSG_DEBUG, "HS20: Delete stored icons for "
+ MACSTR " file name %s", MAC2STR(bssid), file_name);
+
+ dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
+ list) {
+ if ((!bssid || os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0) &&
+ (!file_name ||
+ os_strcmp(icon->file_name, file_name) == 0)) {
+ dl_list_del(&icon->list);
+ hs20_free_icon_entry(icon);
+ count++;
+ }
+ }
+ return count == 0 ? -1 : 0;
+}
+
+
static void hs20_set_osu_access_permission(const char *osu_dir,
const char *fname)
{
@@ -245,16 +399,53 @@ static void hs20_set_osu_access_permission(const char *osu_dir,
}
}
+
+static void hs20_remove_duplicate_icons(struct wpa_supplicant *wpa_s,
+ struct icon_entry *new_icon)
+{
+ struct icon_entry *icon, *tmp;
+
+ dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
+ list) {
+ if (icon == new_icon)
+ continue;
+ if (os_memcmp(icon->bssid, new_icon->bssid, ETH_ALEN) == 0 &&
+ os_strcmp(icon->file_name, new_icon->file_name) == 0) {
+ dl_list_del(&icon->list);
+ hs20_free_icon_entry(icon);
+ }
+ }
+}
+
+
static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *pos,
- size_t slen)
+ size_t slen, u8 dialog_token)
{
char fname[256];
int png;
FILE *f;
u16 data_len;
+ struct icon_entry *icon;
+
+ dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
+ if (icon->dialog_token == dialog_token && !icon->image &&
+ os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) {
+ icon->image = os_malloc(slen);
+ if (!icon->image)
+ return -1;
+ os_memcpy(icon->image, pos, slen);
+ icon->image_len = slen;
+ hs20_remove_duplicate_icons(wpa_s, icon);
+ wpa_msg(wpa_s, MSG_INFO,
+ RX_HS20_ICON MACSTR " %s %u",
+ MAC2STR(sa), icon->file_name,
+ (unsigned int) icon->image_len);
+ return 0;
+ }
+ }
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Icon Binary File",
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Icon Binary File",
MAC2STR(sa));
if (slen < 4) {
@@ -317,7 +508,7 @@ static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
}
fclose(f);
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP-ICON %s", fname);
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP_ICON "%s", fname);
return 0;
}
@@ -360,7 +551,7 @@ static void hs20_osu_icon_fetch_result(struct wpa_supplicant *wpa_s, int res)
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
- const u8 *data, size_t slen)
+ const u8 *data, size_t slen, u8 dialog_token)
{
const u8 *pos = data;
u8 subtype;
@@ -381,7 +572,7 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
switch (subtype) {
case HS20_STYPE_CAPABILITY_LIST:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" HS Capability List", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen);
if (anqp) {
@@ -391,7 +582,7 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" Operator Friendly Name", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
if (anqp) {
@@ -407,7 +598,7 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
"Metrics value from " MACSTR, MAC2STR(sa));
break;
}
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa),
pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5),
pos[9], pos[10], WPA_GET_LE16(pos + 11));
@@ -417,7 +608,7 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case HS20_STYPE_CONNECTION_CAPABILITY:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" Connection Capability", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
if (anqp) {
@@ -427,7 +618,7 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case HS20_STYPE_OPERATING_CLASS:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" Operating Class", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
if (anqp) {
@@ -437,7 +628,7 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case HS20_STYPE_OSU_PROVIDERS_LIST:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" OSU Providers list", MAC2STR(sa));
wpa_s->num_prov_found++;
if (anqp) {
@@ -447,7 +638,8 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case HS20_STYPE_ICON_BINARY_FILE:
- ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen);
+ ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen,
+ dialog_token);
if (wpa_s->fetch_osu_icon_in_progress) {
hs20_osu_icon_fetch_result(wpa_s, ret);
eloop_cancel_timeout(hs20_continue_icon_fetch,
@@ -513,7 +705,10 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
wpa_s->conf->osu_dir);
f = fopen(fname, "w");
if (f == NULL) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not write OSU provider information");
hs20_free_osu_prov(wpa_s);
+ wpa_s->fetch_anqp_in_progress = 0;
return;
}
@@ -581,7 +776,8 @@ void hs20_next_osu_icon(struct wpa_supplicant *wpa_s)
if (hs20_anqp_send_req(wpa_s, osu->bssid,
BIT(HS20_STYPE_ICON_REQUEST),
(u8 *) icon->filename,
- os_strlen(icon->filename)) < 0) {
+ os_strlen(icon->filename),
+ 0) < 0) {
icon->failed = 1;
continue;
}
@@ -619,7 +815,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
prov->osu_ssid_len = osu_ssid_len;
/* OSU Friendly Name Length */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
"Friendly Name Length");
return;
@@ -635,9 +831,9 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos += len2;
/* OSU Friendly Name Duples */
- while (pos2 + 4 <= pos && prov->friendly_name_count < OSU_MAX_ITEMS) {
+ while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) {
struct osu_lang_string *f;
- if (pos2 + 1 + pos2[0] > pos || pos2[0] < 3) {
+ if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) {
wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
break;
}
@@ -648,7 +844,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
}
/* OSU Server URI */
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG,
"HS 2.0: Not enough room for OSU Server URI length");
return;
@@ -663,7 +859,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos += uri_len;
/* OSU Method list */
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
"list length");
return;
@@ -683,7 +879,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
}
/* Icons Available Length */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
"Available Length");
return;
@@ -703,7 +899,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
struct osu_icon *icon = &prov->icon[prov->icon_count];
u8 flen;
- if (pos2 + 2 + 2 + 3 + 1 + 1 > pos) {
+ if (2 + 2 + 3 + 1 + 1 > pos - pos2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata");
break;
}
@@ -715,46 +911,46 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
os_memcpy(icon->lang, pos2, 3);
pos2 += 3;
- flen = pos2[0];
- if (flen > pos - pos2 - 1) {
+ flen = *pos2++;
+ if (flen > pos - pos2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type");
break;
}
- os_memcpy(icon->icon_type, pos2 + 1, flen);
- pos2 += 1 + flen;
+ os_memcpy(icon->icon_type, pos2, flen);
+ pos2 += flen;
- if (pos2 + 1 > pos) {
+ if (pos - pos2 < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
"Filename length");
break;
}
- flen = pos2[0];
- if (flen > pos - pos2 - 1) {
+ flen = *pos2++;
+ if (flen > pos - pos2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
"Filename");
break;
}
- os_memcpy(icon->filename, pos2 + 1, flen);
- pos2 += 1 + flen;
+ os_memcpy(icon->filename, pos2, flen);
+ pos2 += flen;
prov->icon_count++;
}
/* OSU_NAI */
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
return;
}
- osu_nai_len = pos[0];
- if (osu_nai_len > end - pos - 1) {
+ osu_nai_len = *pos++;
+ if (osu_nai_len > end - pos) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
return;
}
- os_memcpy(prov->osu_nai, pos + 1, osu_nai_len);
- pos += 1 + osu_nai_len;
+ os_memcpy(prov->osu_nai, pos, osu_nai_len);
+ pos += osu_nai_len;
/* OSU Service Description Length */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
"Service Description Length");
return;
@@ -770,20 +966,20 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos += len2;
/* OSU Service Description Duples */
- while (pos2 + 4 <= pos && prov->serv_desc_count < OSU_MAX_ITEMS) {
+ while (pos - pos2 >= 4 && prov->serv_desc_count < OSU_MAX_ITEMS) {
struct osu_lang_string *f;
u8 descr_len;
- descr_len = pos2[0];
- if (descr_len > pos - pos2 - 1 || descr_len < 3) {
+ descr_len = *pos2++;
+ if (descr_len > pos - pos2 || descr_len < 3) {
wpa_printf(MSG_DEBUG, "Invalid OSU Service "
"Description");
break;
}
f = &prov->serv_desc[prov->serv_desc_count++];
- os_memcpy(f->lang, pos2 + 1, 3);
- os_memcpy(f->text, pos2 + 1 + 3, descr_len - 3);
- pos2 += 1 + descr_len;
+ os_memcpy(f->lang, pos2, 3);
+ os_memcpy(f->text, pos2 + 3, descr_len - 3);
+ pos2 += descr_len;
}
wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,
@@ -818,9 +1014,9 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
end = pos + wpabuf_len(prov_anqp);
/* OSU SSID */
- if (pos + 1 > end)
+ if (end - pos < 1)
continue;
- if (pos + 1 + pos[0] > end) {
+ if (1 + pos[0] > end - pos) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
"OSU SSID");
continue;
@@ -834,7 +1030,7 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
osu_ssid = pos;
pos += osu_ssid_len;
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
"Number of OSU Providers");
continue;
@@ -844,7 +1040,7 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
num_providers);
/* OSU Providers */
- while (pos + 2 < end && num_providers > 0) {
+ while (end - pos > 2 && num_providers > 0) {
num_providers--;
len = WPA_GET_LE16(pos);
pos += 2;
@@ -884,7 +1080,7 @@ static void hs20_osu_scan_res_handler(struct wpa_supplicant *wpa_s,
}
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s)
+int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan)
{
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
@@ -915,7 +1111,16 @@ int hs20_fetch_osu(struct wpa_supplicant *wpa_s)
wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch");
wpa_s->num_osu_scans = 0;
wpa_s->num_prov_found = 0;
- hs20_start_osu_scan(wpa_s);
+ if (skip_scan) {
+ wpa_s->network_select = 0;
+ wpa_s->fetch_all_anqp = 1;
+ wpa_s->fetch_osu_info = 1;
+ wpa_s->fetch_osu_icon_in_progress = 0;
+
+ interworking_start_fetch_anqp(wpa_s);
+ } else {
+ hs20_start_osu_scan(wpa_s);
+ }
return 0;
}
@@ -1004,8 +1209,16 @@ void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
}
+void hs20_init(struct wpa_supplicant *wpa_s)
+{
+ dl_list_init(&wpa_s->icon_head);
+}
+
+
void hs20_deinit(struct wpa_supplicant *wpa_s)
{
eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
hs20_free_osu_prov(wpa_s);
+ if (wpa_s->icon_head.next)
+ hs20_del_icon(wpa_s, NULL, NULL);
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h
index 85b51201..0dd559fd 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h
@@ -8,17 +8,16 @@
#ifndef HS20_SUPPLICANT_H
#define HS20_SUPPLICANT_H
+void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s);
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
- const u8 *payload, size_t payload_len);
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
- size_t payload_len);
+ const u8 *payload, size_t payload_len, int inmem);
void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
struct wpabuf *buf);
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
- const u8 *data, size_t slen);
+ const u8 *data, size_t slen, u8 dialog_token);
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
@@ -32,10 +31,16 @@ void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
void hs20_free_osu_prov(struct wpa_supplicant *wpa_s);
void hs20_next_osu_icon(struct wpa_supplicant *wpa_s);
void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s);
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s);
+int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan);
void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s);
void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s);
void hs20_start_osu_scan(struct wpa_supplicant *wpa_s);
+void hs20_init(struct wpa_supplicant *wpa_s);
void hs20_deinit(struct wpa_supplicant *wpa_s);
+int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, size_t offset, size_t size,
+ char *reply, size_t buf_len);
+int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name);
#endif /* HS20_SUPPLICANT_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ibss_rsn.h b/freebsd/contrib/wpa/wpa_supplicant/ibss_rsn.h
index 67fae2d1..626c5435 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ibss_rsn.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/ibss_rsn.h
@@ -51,7 +51,8 @@ struct ibss_rsn {
};
-struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s);
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn);
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr);
void ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/interworking.c b/freebsd/contrib/wpa/wpa_supplicant/interworking.c
index 21875e15..89f9a9be 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/interworking.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/interworking.c
@@ -364,13 +364,13 @@ static const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos,
u8 elen, auth_count, a;
const u8 *e_end;
- if (pos + 3 > end) {
+ if (end - pos < 3) {
wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields");
return NULL;
}
elen = *pos++;
- if (pos + elen > end || elen < 2) {
+ if (elen > end - pos || elen < 2) {
wpa_printf(MSG_DEBUG, "No room for EAP Method subfield");
return NULL;
}
@@ -383,14 +383,19 @@ static const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos,
for (a = 0; a < auth_count; a++) {
u8 id, len;
- if (pos + 2 > end || pos + 2 + pos[1] > end) {
- wpa_printf(MSG_DEBUG, "No room for Authentication "
- "Parameter subfield");
+ if (end - pos < 2) {
+ wpa_printf(MSG_DEBUG,
+ "No room for Authentication Parameter subfield header");
return NULL;
}
id = *pos++;
len = *pos++;
+ if (len > end - pos) {
+ wpa_printf(MSG_DEBUG,
+ "No room for Authentication Parameter subfield");
+ return NULL;
+ }
switch (id) {
case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH:
@@ -465,7 +470,7 @@ static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos,
len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */
pos += 2;
- if (pos + len > end || len < 3) {
+ if (len > end - pos || len < 3) {
wpa_printf(MSG_DEBUG, "No room for NAI Realm Data "
"(len=%u; left=%u)",
len, (unsigned int) (end - pos));
@@ -475,7 +480,7 @@ static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos,
r->encoding = *pos++;
realm_len = *pos++;
- if (pos + realm_len > f_end) {
+ if (realm_len > f_end - pos) {
wpa_printf(MSG_DEBUG, "No room for NAI Realm "
"(len=%u; left=%u)",
realm_len, (unsigned int) (f_end - pos));
@@ -487,13 +492,13 @@ static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos,
return NULL;
pos += realm_len;
- if (pos + 1 > f_end) {
+ if (f_end - pos < 1) {
wpa_printf(MSG_DEBUG, "No room for EAP Method Count");
return NULL;
}
r->eap_count = *pos++;
wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count);
- if (pos + r->eap_count * 3 > f_end) {
+ if (r->eap_count * 3 > f_end - pos) {
wpa_printf(MSG_DEBUG, "No room for EAP Methods");
return NULL;
}
@@ -748,7 +753,7 @@ static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
return 0;
pos = wpabuf_head_u8(anqp);
end = pos + wpabuf_len(anqp);
- if (pos + 2 > end)
+ if (end - pos < 2)
return 0;
if (*pos != 0) {
wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos);
@@ -756,7 +761,7 @@ static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
}
pos++;
udhl = *pos++;
- if (pos + udhl > end) {
+ if (udhl > end - pos) {
wpa_printf(MSG_DEBUG, "Invalid UDHL");
return 0;
}
@@ -766,12 +771,12 @@ static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2],
imsi, mnc_len);
- while (pos + 2 <= end) {
+ while (end - pos >= 2) {
u8 iei, len;
const u8 *l_end;
iei = *pos++;
len = *pos++ & 0x7f;
- if (pos + len > end)
+ if (len > end - pos)
break;
l_end = pos + len;
@@ -782,7 +787,7 @@ static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
pos, len);
num = *pos++;
for (i = 0; i < num; i++) {
- if (pos + 3 > l_end)
+ if (l_end - pos < 3)
break;
if (os_memcmp(pos, plmn, 3) == 0 ||
os_memcmp(pos, plmn2, 3) == 0)
@@ -947,11 +952,9 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
if (!key_mgmt)
key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
- if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0)
- return -1;
- if (wpa_config_set(ssid, "proto", "RSN", 0) < 0)
- return -1;
- if (wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
+ if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
+ wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+ wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
return -1;
return 0;
}
@@ -1084,12 +1087,12 @@ static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
* OI #1, [OI #2], [OI #3]
*/
- if (pos + 2 > end)
+ if (end - pos < 2)
return 0;
pos++; /* skip Number of ANQP OIs */
lens = *pos++;
- if (pos + (lens & 0x0f) + (lens >> 4) > end)
+ if ((lens & 0x0f) + (lens >> 4) > end - pos)
return 0;
if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
@@ -1123,7 +1126,7 @@ static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
/* Set of <OI Length, OI> duples */
while (pos < end) {
len = *pos++;
- if (pos + len > end)
+ if (len > end - pos)
break;
if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
return 1;
@@ -1184,6 +1187,7 @@ static int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss)
static int cred_below_min_backhaul(struct wpa_supplicant *wpa_s,
struct wpa_cred *cred, struct wpa_bss *bss)
{
+#ifdef CONFIG_HS20
int res;
unsigned int dl_bandwidth, ul_bandwidth;
const u8 *wan;
@@ -1235,6 +1239,7 @@ static int cred_below_min_backhaul(struct wpa_supplicant *wpa_s,
if (cred->min_ul_bandwidth_roaming > ul_bandwidth)
return 1;
}
+#endif /* CONFIG_HS20 */
return 0;
}
@@ -1262,9 +1267,11 @@ static int cred_over_max_bss_load(struct wpa_supplicant *wpa_s,
}
+#ifdef CONFIG_HS20
+
static int has_proto_match(const u8 *pos, const u8 *end, u8 proto)
{
- while (pos + 4 <= end) {
+ while (end - pos >= 4) {
if (pos[0] == proto && pos[3] == 1 /* Open */)
return 1;
pos += 4;
@@ -1277,7 +1284,7 @@ static int has_proto_match(const u8 *pos, const u8 *end, u8 proto)
static int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto,
u16 port)
{
- while (pos + 4 <= end) {
+ while (end - pos >= 4) {
if (pos[0] == proto && WPA_GET_LE16(&pos[1]) == port &&
pos[3] == 1 /* Open */)
return 1;
@@ -1287,10 +1294,13 @@ static int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto,
return 0;
}
+#endif /* CONFIG_HS20 */
+
static int cred_conn_capab_missing(struct wpa_supplicant *wpa_s,
struct wpa_cred *cred, struct wpa_bss *bss)
{
+#ifdef CONFIG_HS20
int res;
const u8 *capab, *end;
unsigned int i, j;
@@ -1327,6 +1337,7 @@ static int cred_conn_capab_missing(struct wpa_supplicant *wpa_s,
}
}
}
+#endif /* CONFIG_HS20 */
return 0;
}
@@ -1440,7 +1451,24 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
os_free(anon);
}
- if (cred->username && cred->username[0] &&
+ if (!ttls && cred->username && cred->username[0] && cred->realm &&
+ !os_strchr(cred->username, '@')) {
+ char *id;
+ size_t buflen;
+ int res;
+
+ buflen = os_strlen(cred->username) + 1 +
+ os_strlen(cred->realm) + 1;
+
+ id = os_malloc(buflen);
+ if (!id)
+ return -1;
+ os_snprintf(id, buflen, "%s@%s", cred->username, cred->realm);
+ res = wpa_config_set_quoted(ssid, "identity", id);
+ os_free(id);
+ if (res < 0)
+ return -1;
+ } else if (cred->username && cred->username[0] &&
wpa_config_set_quoted(ssid, "identity", cred->username) < 0)
return -1;
@@ -1562,9 +1590,8 @@ fail:
}
-static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss, int allow_excluded,
- int only_add)
+int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ int only_add)
{
struct wpa_cred *cred, *cred_rc, *cred_3gpp;
struct wpa_ssid *ssid;
@@ -1572,7 +1599,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
struct nai_realm_eap *eap = NULL;
u16 count, i;
char buf[100];
- int excluded = 0, *excl = allow_excluded ? &excluded : NULL;
+ int excluded = 0, *excl = &excluded;
const char *name;
if (wpa_s->conf->cred == NULL || bss == NULL)
@@ -1586,8 +1613,8 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
}
wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR
- " for connection (allow_excluded=%d)",
- MAC2STR(bss->bssid), allow_excluded);
+ " for connection",
+ MAC2STR(bss->bssid));
if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
/*
@@ -1605,7 +1632,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d",
cred_rc->priority, cred_rc->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
@@ -1614,7 +1641,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d",
cred->priority, cred->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
@@ -1624,7 +1651,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest 3GPP matching credential priority %d sp_priority %d",
cred_3gpp->priority, cred_3gpp->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
@@ -1637,7 +1664,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)",
cred_rc->priority, cred_rc->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
@@ -1647,7 +1674,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)",
cred->priority, cred->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
@@ -1657,7 +1684,7 @@ static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)",
cred_3gpp->priority, cred_3gpp->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
}
@@ -1822,13 +1849,6 @@ fail:
}
-int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- int only_add)
-{
- return interworking_connect_helper(wpa_s, bss, 1, only_add);
-}
-
-
#ifdef PCSC_FUNCS
static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s)
{
@@ -2127,23 +2147,27 @@ int domain_name_list_contains(struct wpabuf *domain_names,
pos = wpabuf_head(domain_names);
end = pos + wpabuf_len(domain_names);
- while (pos + 1 < end) {
- if (pos + 1 + pos[0] > end)
+ while (end - pos > 1) {
+ u8 elen;
+
+ elen = *pos++;
+ if (elen > end - pos)
break;
wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name",
- pos + 1, pos[0]);
- if (pos[0] == len &&
- os_strncasecmp(domain, (const char *) (pos + 1), len) == 0)
+ pos, elen);
+ if (elen == len &&
+ os_strncasecmp(domain, (const char *) pos, len) == 0)
return 1;
- if (!exact_match && pos[0] > len && pos[pos[0] - len] == '.') {
- const char *ap = (const char *) (pos + 1);
- int offset = pos[0] - len;
+ if (!exact_match && elen > len && pos[elen - len - 1] == '.') {
+ const char *ap = (const char *) pos;
+ int offset = elen - len;
+
if (os_strncasecmp(domain, ap + offset, len) == 0)
return 1;
}
- pos += 1 + pos[0];
+ pos += elen;
}
return 0;
@@ -2566,11 +2590,13 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
return;
}
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_icon_in_progress) {
wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)");
hs20_next_osu_icon(wpa_s);
return;
}
+#endif /* CONFIG_HS20 */
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
if (!(bss->caps & IEEE80211_CAP_ESS))
@@ -2604,6 +2630,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
}
if (found == 0) {
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_info) {
if (wpa_s->num_prov_found == 0 &&
wpa_s->fetch_osu_waiting_scan &&
@@ -2616,6 +2643,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
hs20_osu_icon_fetch(wpa_s);
return;
}
+#endif /* CONFIG_HS20 */
wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed");
wpa_s->fetch_anqp_in_progress = 0;
if (wpa_s->network_select)
@@ -2666,10 +2694,11 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s)
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
- u16 info_ids[], size_t num_ids, u32 subtypes)
+ u16 info_ids[], size_t num_ids, u32 subtypes,
+ int get_cell_pref)
{
struct wpabuf *buf;
- struct wpabuf *hs20_buf = NULL;
+ struct wpabuf *extra_buf = NULL;
int ret = 0;
int freq;
struct wpa_bss *bss;
@@ -2692,15 +2721,31 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
#ifdef CONFIG_HS20
if (subtypes != 0) {
- hs20_buf = wpabuf_alloc(100);
- if (hs20_buf == NULL)
+ extra_buf = wpabuf_alloc(100);
+ if (extra_buf == NULL)
return -1;
- hs20_put_anqp_req(subtypes, NULL, 0, hs20_buf);
+ hs20_put_anqp_req(subtypes, NULL, 0, extra_buf);
}
#endif /* CONFIG_HS20 */
- buf = anqp_build_req(info_ids, num_ids, hs20_buf);
- wpabuf_free(hs20_buf);
+#ifdef CONFIG_MBO
+ if (get_cell_pref) {
+ struct wpabuf *mbo;
+
+ mbo = mbo_build_anqp_buf(wpa_s, bss);
+ if (mbo) {
+ if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
+ wpabuf_free(extra_buf);
+ return -1;
+ }
+ wpabuf_put_buf(extra_buf, mbo);
+ wpabuf_free(mbo);
+ }
+ }
+#endif /* CONFIG_MBO */
+
+ buf = anqp_build_req(info_ids, num_ids, extra_buf);
+ wpabuf_free(extra_buf);
if (buf == NULL)
return -1;
@@ -2718,10 +2763,46 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
}
+static void anqp_add_extra(struct wpa_supplicant *wpa_s,
+ struct wpa_bss_anqp *anqp, u16 info_id,
+ const u8 *data, size_t slen)
+{
+ struct wpa_bss_anqp_elem *tmp, *elem = NULL;
+
+ if (!anqp)
+ return;
+
+ dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+ list) {
+ if (tmp->infoid == info_id) {
+ elem = tmp;
+ break;
+ }
+ }
+
+ if (!elem) {
+ elem = os_zalloc(sizeof(*elem));
+ if (!elem)
+ return;
+ elem->infoid = info_id;
+ dl_list_add(&anqp->anqp_elems, &elem->list);
+ } else {
+ wpabuf_free(elem->payload);
+ }
+
+ elem->payload = wpabuf_alloc_copy(data, slen);
+ if (!elem->payload) {
+ dl_list_del(&elem->list);
+ os_free(elem);
+ }
+}
+
+
static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
u16 info_id,
- const u8 *data, size_t slen)
+ const u8 *data, size_t slen,
+ u8 dialog_token)
{
const u8 *pos = data;
struct wpa_bss_anqp *anqp = NULL;
@@ -2734,7 +2815,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
switch (info_id) {
case ANQP_CAPABILITY_LIST:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" ANQP Capability list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list",
pos, slen);
@@ -2744,7 +2825,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_VENUE_NAME:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Venue Name", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen);
if (anqp) {
@@ -2753,7 +2834,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_NETWORK_AUTH_TYPE:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Network Authentication Type information",
MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication "
@@ -2764,7 +2845,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_ROAMING_CONSORTIUM:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Roaming Consortium list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium",
pos, slen);
@@ -2774,7 +2855,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_IP_ADDR_TYPE_AVAILABILITY:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" IP Address Type Availability information",
MAC2STR(sa));
wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability",
@@ -2786,7 +2867,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_NAI_REALM:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" NAI Realm list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen);
if (anqp) {
@@ -2795,7 +2876,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_3GPP_CELLULAR_NETWORK:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" 3GPP Cellular Network information", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network",
pos, slen);
@@ -2805,7 +2886,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
}
break;
case ANQP_DOMAIN_NAME:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Domain Name list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen);
if (anqp) {
@@ -2831,7 +2912,8 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
switch (type) {
case HS20_ANQP_OUI_TYPE:
hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa,
- pos, slen);
+ pos, slen,
+ dialog_token);
break;
default:
wpa_msg(wpa_s, MSG_DEBUG,
@@ -2851,6 +2933,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
default:
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Unsupported ANQP Info ID %u", info_id);
+ anqp_add_extra(wpa_s, anqp, info_id, data, slen);
break;
}
}
@@ -2873,8 +2956,10 @@ void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
" dialog_token=%u result=%d status_code=%u",
MAC2STR(dst), dialog_token, result, status_code);
if (result != GAS_QUERY_SUCCESS) {
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_icon_in_progress)
hs20_icon_fetch_failed(wpa_s);
+#endif /* CONFIG_HS20 */
anqp_result = "FAILURE";
goto out;
}
@@ -2884,8 +2969,10 @@ void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) {
wpa_msg(wpa_s, MSG_DEBUG,
"ANQP: Unexpected Advertisement Protocol in response");
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_icon_in_progress)
hs20_icon_fetch_failed(wpa_s);
+#endif /* CONFIG_HS20 */
anqp_result = "INVALID_FRAME";
goto out;
}
@@ -2929,12 +3016,14 @@ void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
goto out_parse_done;
}
interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos,
- slen);
+ slen, dialog_token);
pos += slen;
}
out_parse_done:
+#ifdef CONFIG_HS20
hs20_notify_parse_done(wpa_s);
+#endif /* CONFIG_HS20 */
out:
wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
MAC2STR(dst), anqp_result);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/interworking.h b/freebsd/contrib/wpa/wpa_supplicant/interworking.h
index 3743dc00..3d222926 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/interworking.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/interworking.h
@@ -12,7 +12,8 @@
enum gas_query_result;
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
- u16 info_ids[], size_t num_ids, u32 subtypes);
+ u16 info_ids[], size_t num_ids, u32 subtypes,
+ int get_cell_pref);
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
diff --git a/freebsd/contrib/wpa/wpa_supplicant/main.c b/freebsd/contrib/wpa/wpa_supplicant/main.c
index e1c13df3..75f07e36 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/main.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/main.c
@@ -75,41 +75,44 @@ static void usage(void)
" -B = run daemon in the background\n"
" -c = Configuration file\n"
" -C = ctrl_interface parameter (only used if -c is not)\n"
- " -i = interface name\n"
- " -I = additional configuration file\n"
" -d = increase debugging verbosity (-dd even more)\n"
" -D = driver name (can be multiple drivers: nl80211,wext)\n"
- " -e = entropy file\n");
+ " -e = entropy file\n"
#ifdef CONFIG_DEBUG_FILE
- printf(" -f = log output to debug file instead of stdout\n");
+ " -f = log output to debug file instead of stdout\n"
#endif /* CONFIG_DEBUG_FILE */
- printf(" -g = global ctrl_interface\n"
+ " -g = global ctrl_interface\n"
" -G = global ctrl_interface group\n"
- " -K = include keys (passwords, etc.) in debug output\n");
-#ifdef CONFIG_DEBUG_SYSLOG
- printf(" -s = log output to syslog instead of stdout\n");
-#endif /* CONFIG_DEBUG_SYSLOG */
-#ifdef CONFIG_DEBUG_LINUX_TRACING
- printf(" -T = record to Linux tracing in addition to logging\n");
- printf(" (records all messages regardless of debug verbosity)\n");
-#endif /* CONFIG_DEBUG_LINUX_TRACING */
- printf(" -t = include timestamp in debug messages\n"
" -h = show this help text\n"
+ " -i = interface name\n"
+ " -I = additional configuration file\n"
+ " -K = include keys (passwords, etc.) in debug output\n"
" -L = show license (BSD)\n"
+#ifdef CONFIG_P2P
+ " -m = Configuration file for the P2P Device interface\n"
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ " -M = start describing new matching interface\n"
+#endif /* CONFIG_MATCH_IFACE */
+ " -N = start describing new interface\n"
" -o = override driver parameter for new interfaces\n"
" -O = override ctrl_interface parameter for new interfaces\n"
" -p = driver parameters\n"
" -P = PID file\n"
- " -q = decrease debugging verbosity (-qq even less)\n");
+ " -q = decrease debugging verbosity (-qq even less)\n"
+#ifdef CONFIG_DEBUG_SYSLOG
+ " -s = log output to syslog instead of stdout\n"
+#endif /* CONFIG_DEBUG_SYSLOG */
+ " -t = include timestamp in debug messages\n"
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+ " -T = record to Linux tracing in addition to logging\n"
+ " (records all messages regardless of debug verbosity)\n"
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
#ifdef CONFIG_DBUS
- printf(" -u = enable DBus control interface\n");
+ " -u = enable DBus control interface\n"
#endif /* CONFIG_DBUS */
- printf(" -v = show version\n"
- " -W = wait for a control interface monitor before starting\n"
-#ifdef CONFIG_P2P
- " -m = Configuration file for the P2P Device interface\n"
-#endif /* CONFIG_P2P */
- " -N = start describing new interface\n");
+ " -v = show version\n"
+ " -W = wait for a control interface monitor before starting\n");
printf("example:\n"
" wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
@@ -182,6 +185,28 @@ int rtems_bsd_command_wpa_supplicant(int argc, char **argv)
}
#endif /* __rtems__ */
+#ifdef CONFIG_MATCH_IFACE
+static int wpa_supplicant_init_match(struct wpa_global *global)
+{
+ /*
+ * The assumption is that the first driver is the primary driver and
+ * will handle the arrival / departure of interfaces.
+ */
+ if (wpa_drivers[0]->global_init && !global->drv_priv[0]) {
+ global->drv_priv[0] = wpa_drivers[0]->global_init(global);
+ if (!global->drv_priv[0]) {
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize driver '%s'",
+ wpa_drivers[0]->name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_MATCH_IFACE */
+
+
int main(int argc, char *argv[])
{
int c, i;
@@ -214,7 +239,7 @@ int main(int argc, char *argv[])
for (;;) {
c = getopt(argc, argv,
- "b:Bc:C:D:de:f:g:G:hi:I:KLm:No:O:p:P:qsTtuvW");
+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
if (c < 0)
break;
switch (c) {
@@ -320,6 +345,20 @@ int main(int argc, char *argv[])
case 'W':
params.wait_for_monitor++;
break;
+#ifdef CONFIG_MATCH_IFACE
+ case 'M':
+ params.match_iface_count++;
+ iface = os_realloc_array(params.match_ifaces,
+ params.match_iface_count,
+ sizeof(struct wpa_interface));
+ if (!iface)
+ goto out;
+ params.match_ifaces = iface;
+ iface = &params.match_ifaces[params.match_iface_count -
+ 1];
+ os_memset(iface, 0, sizeof(*iface));
+ break;
+#endif /* CONFIG_MATCH_IFACE */
case 'N':
iface_count++;
iface = os_realloc_array(ifaces, iface_count,
@@ -366,6 +405,9 @@ int main(int argc, char *argv[])
ifaces[i].ctrl_interface == NULL) ||
ifaces[i].ifname == NULL) {
if (iface_count == 1 && (params.ctrl_interface ||
+#ifdef CONFIG_MATCH_IFACE
+ params.match_iface_count ||
+#endif /* CONFIG_MATCH_IFACE */
params.dbus_ctrl_interface))
break;
usage();
@@ -379,6 +421,11 @@ int main(int argc, char *argv[])
}
}
+#ifdef CONFIG_MATCH_IFACE
+ if (exitcode == 0)
+ exitcode = wpa_supplicant_init_match(global);
+#endif /* CONFIG_MATCH_IFACE */
+
if (exitcode == 0)
exitcode = wpa_supplicant_run(global);
@@ -389,6 +436,9 @@ int main(int argc, char *argv[])
out:
wpa_supplicant_fd_workaround(0);
os_free(ifaces);
+#ifdef CONFIG_MATCH_IFACE
+ os_free(params.match_ifaces);
+#endif /* CONFIG_MATCH_IFACE */
os_free(params.pid_file);
os_program_deinit();
diff --git a/freebsd/contrib/wpa/wpa_supplicant/mesh.h b/freebsd/contrib/wpa/wpa_supplicant/mesh.h
index 3cb7f1b1..7317083c 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/mesh.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/mesh.h
@@ -18,6 +18,9 @@ int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
char *end);
int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
size_t len);
+int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr);
+int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration);
#ifdef CONFIG_MESH
diff --git a/freebsd/contrib/wpa/wpa_supplicant/mesh_mpm.h b/freebsd/contrib/wpa/wpa_supplicant/mesh_mpm.h
index 7ebaef0c..5fc1e618 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/mesh_mpm.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/mesh_mpm.h
@@ -14,10 +14,13 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
struct ieee802_11_elems *elems);
void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh);
void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
-void mesh_mpm_free_sta(struct sta_info *sta);
+void mesh_mpm_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s,
struct sta_info *sta,
enum mesh_plink_state state);
+int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
+int mesh_mpm_connect_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration);
#ifdef CONFIG_MESH
diff --git a/freebsd/contrib/wpa/wpa_supplicant/mesh_rsn.h b/freebsd/contrib/wpa/wpa_supplicant/mesh_rsn.h
index b1471b2d..8775cedc 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/mesh_rsn.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/mesh_rsn.h
@@ -12,7 +12,15 @@
struct mesh_rsn {
struct wpa_supplicant *wpa_s;
struct wpa_authenticator *auth;
- u8 mgtk[16];
+ unsigned int pairwise_cipher;
+ unsigned int group_cipher;
+ u8 mgtk[WPA_TK_MAX_LEN];
+ size_t mgtk_len;
+ u8 mgtk_key_id;
+ unsigned int mgmt_group_cipher;
+ u8 igtk_key_id;
+ u8 igtk[WPA_TK_MAX_LEN];
+ size_t igtk_len;
#ifdef CONFIG_SAE
struct wpabuf *sae_token;
int sae_group_index;
@@ -30,6 +38,7 @@ int mesh_rsn_protect_frame(struct mesh_rsn *rsn, struct sta_info *sta,
const u8 *cat, struct wpabuf *buf);
int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
struct ieee802_11_elems *elems, const u8 *cat,
+ const u8 *chosen_pmk,
const u8 *start, size_t elems_len);
void mesh_auth_timer(void *eloop_ctx, void *user_data);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/notify.c b/freebsd/contrib/wpa/wpa_supplicant/notify.c
index 1b41f147..020a9a7b 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/notify.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/notify.c
@@ -15,6 +15,7 @@
#include "config.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
+#include "binder/binder.h"
#include "dbus/dbus_common.h"
#include "dbus/dbus_old.h"
#include "dbus/dbus_new.h"
@@ -36,6 +37,12 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global)
}
#endif /* CONFIG_DBUS */
+#ifdef CONFIG_BINDER
+ global->binder = wpas_binder_init(global);
+ if (!global->binder)
+ return -1;
+#endif /* CONFIG_BINDER */
+
return 0;
}
@@ -46,6 +53,11 @@ void wpas_notify_supplicant_deinitialized(struct wpa_global *global)
if (global->dbus)
wpas_dbus_deinit(global->dbus);
#endif /* CONFIG_DBUS */
+
+#ifdef CONFIG_BINDER
+ if (global->binder)
+ wpas_binder_deinit(global->binder);
+#endif /* CONFIG_BINDER */
}
@@ -130,6 +142,15 @@ void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
}
+void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ASSOC_STATUS_CODE);
+}
+
+
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
@@ -649,13 +670,13 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid, int network_id,
+ struct wpa_ssid *ssid, int persistent,
int client)
{
/* Notify a group has been started */
wpas_dbus_register_p2p_group(wpa_s, ssid);
- wpas_dbus_signal_p2p_group_started(wpa_s, ssid, client, network_id);
+ wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent);
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/notify.h b/freebsd/contrib/wpa/wpa_supplicant/notify.h
index d9f0f5a9..8cce0f30 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/notify.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/notify.h
@@ -23,6 +23,7 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
enum wpa_states new_state,
enum wpa_states old_state);
void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s);
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s);
@@ -112,7 +113,7 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
u16 config_methods,
unsigned int generated_pin);
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid, int network_id,
+ struct wpa_ssid *ssid, int persistent,
int client);
void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/offchannel.c b/freebsd/contrib/wpa/wpa_supplicant/offchannel.c
index 54b8772b..a269fdaf 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/offchannel.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/offchannel.c
@@ -25,8 +25,29 @@ wpas_get_tx_interface(struct wpa_supplicant *wpa_s, const u8 *src)
{
struct wpa_supplicant *iface;
- if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0)
+ if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0) {
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_mgmt && wpa_s != wpa_s->parent &&
+ wpa_s->parent->ap_iface &&
+ os_memcmp(wpa_s->parent->own_addr,
+ wpa_s->own_addr, ETH_ALEN) == 0 &&
+ wpabuf_len(wpa_s->pending_action_tx) >= 2 &&
+ *wpabuf_head_u8(wpa_s->pending_action_tx) !=
+ WLAN_ACTION_PUBLIC) {
+ /*
+ * When P2P Device interface has same MAC address as
+ * the GO interface, make sure non-Public Action frames
+ * are sent through the GO interface. The P2P Device
+ * interface can only send Public Action frames.
+ */
+ wpa_printf(MSG_DEBUG,
+ "P2P: Use GO interface %s instead of interface %s for Action TX",
+ wpa_s->parent->ifname, wpa_s->ifname);
+ return wpa_s->parent;
+ }
+#endif /* CONFIG_P2P */
return wpa_s;
+ }
/*
* Try to find a group interface that matches with the source address.
@@ -120,8 +141,9 @@ static void wpas_send_action_cb(void *eloop_ctx, void *timeout_ctx)
}
wpa_printf(MSG_DEBUG, "Off-channel: Sending pending Action frame to "
- MACSTR " using interface %s",
- MAC2STR(wpa_s->pending_action_dst), iface->ifname);
+ MACSTR " using interface %s (pending_action_tx=%p)",
+ MAC2STR(wpa_s->pending_action_dst), iface->ifname,
+ wpa_s->pending_action_tx);
res = wpa_drv_send_action(iface, wpa_s->pending_action_freq, 0,
wpa_s->pending_action_dst,
wpa_s->pending_action_src,
@@ -185,8 +207,12 @@ void offchannel_send_action_tx_status(
return;
}
- wpa_printf(MSG_DEBUG, "Off-channel: Delete matching pending action frame");
-
+ wpa_printf(MSG_DEBUG,
+ "Off-channel: Delete matching pending action frame (dst="
+ MACSTR " pending_action_tx=%p)", MAC2STR(dst),
+ wpa_s->pending_action_tx);
+ wpa_hexdump_buf(MSG_MSGDUMP, "Pending TX frame",
+ wpa_s->pending_action_tx);
wpabuf_free(wpa_s->pending_action_tx);
wpa_s->pending_action_tx = NULL;
@@ -252,8 +278,11 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
if (wpa_s->pending_action_tx) {
wpa_printf(MSG_DEBUG, "Off-channel: Dropped pending Action "
- "frame TX to " MACSTR,
- MAC2STR(wpa_s->pending_action_dst));
+ "frame TX to " MACSTR " (pending_action_tx=%p)",
+ MAC2STR(wpa_s->pending_action_dst),
+ wpa_s->pending_action_tx);
+ wpa_hexdump_buf(MSG_MSGDUMP, "Pending TX frame",
+ wpa_s->pending_action_tx);
wpabuf_free(wpa_s->pending_action_tx);
}
wpa_s->pending_action_tx_done = 0;
@@ -270,6 +299,12 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
os_memcpy(wpa_s->pending_action_bssid, bssid, ETH_ALEN);
wpa_s->pending_action_freq = freq;
wpa_s->pending_action_no_cck = no_cck;
+ wpa_printf(MSG_DEBUG,
+ "Off-channel: Stored pending action frame (dst=" MACSTR
+ " pending_action_tx=%p)",
+ MAC2STR(dst), wpa_s->pending_action_tx);
+ wpa_hexdump_buf(MSG_MSGDUMP, "Pending TX frame",
+ wpa_s->pending_action_tx);
if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) {
struct wpa_supplicant *iface;
@@ -430,6 +465,9 @@ const void * offchannel_pending_action_tx(struct wpa_supplicant *wpa_s)
*/
void offchannel_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
{
+ wpa_printf(MSG_DEBUG,
+ "Off-channel: Clear pending Action frame TX (pending_action_tx=%p",
+ wpa_s->pending_action_tx);
wpabuf_free(wpa_s->pending_action_tx);
wpa_s->pending_action_tx = NULL;
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h
index 56e68349..63910d1c 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h
@@ -34,17 +34,22 @@ struct wpa_supplicant * wpas_get_p2p_client_iface(struct wpa_supplicant *wpa_s,
const u8 *peer_dev_addr);
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method,
- int persistent_group, int auto_join, int join,
- int auth, int go_intent, int freq, int persistent_id,
- int pd, int ht40, int vht);
+ int persistent_group, int auto_join, int join, int auth,
+ int go_intent, int freq, unsigned int vht_center_freq2,
+ int persistent_id, int pd, int ht40, int vht,
+ unsigned int vht_chwidth, const u8 *group_ssid,
+ size_t group_ssid_len);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
- int freq, int ht40, int vht);
+ int freq, int vht_center_freq2, int ht40, int vht,
+ int max_oper_chwidth);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
- int force_freq, int neg_freq, int ht40,
- int vht, const struct p2p_channels *channels,
+ int force_freq, int neg_freq,
+ int vht_center_freq2, int ht40,
+ int vht, int max_oper_chwidth,
+ const struct p2p_channels *channels,
int connection_timeout, int force_scan);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
@@ -111,7 +116,8 @@ void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
- int ht40, int vht, int pref_freq);
+ int vht_center_freq2, int ht40, int vht,
+ int max_oper_chwidth, int pref_freq);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
@@ -140,6 +146,8 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel);
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel);
+int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
+ struct hostapd_hw_modes *mode, u8 channel);
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
const u8 *p2p_dev_addr,
@@ -199,6 +207,10 @@ int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s);
void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail);
int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
+int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
+ unsigned int period, unsigned int interval,
+ unsigned int count);
+int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
#else /* CONFIG_P2P */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/scan.c b/freebsd/contrib/wpa/wpa_supplicant/scan.c
index 9f9f4148..4fd269a8 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/scan.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/scan.c
@@ -38,8 +38,7 @@ static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
if (wpa_s->current_ssid == NULL) {
wpa_s->current_ssid = ssid;
- if (wpa_s->current_ssid != NULL)
- wpas_notify_network_changed(wpa_s);
+ wpas_notify_network_changed(wpa_s);
}
wpa_supplicant_initiate_eapol(wpa_s);
wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
@@ -62,10 +61,7 @@ static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
wps = 1;
*req_type = wpas_wps_get_req_type(ssid);
- if (!ssid->eap.phase1)
- continue;
-
- if (os_strstr(ssid->eap.phase1, "pbc=1"))
+ if (ssid->eap.phase1 && os_strstr(ssid->eap.phase1, "pbc=1"))
return 2;
}
@@ -168,6 +164,8 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
wpa_msg(wpa_s, MSG_INFO,
"Failed to assign random MAC address for a scan");
+ wpa_scan_free_params(params);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
radio_work_done(work);
return;
}
@@ -231,12 +229,11 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
}
ctx = wpa_scan_clone_params(params);
- if (ctx == NULL)
- return -1;
-
- if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
+ if (!ctx ||
+ radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
{
wpa_scan_free_params(ctx);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
return -1;
}
@@ -268,14 +265,14 @@ wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
}
-int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- int interval)
+static int
+wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params)
{
int ret;
wpa_supplicant_notify_scanning(wpa_s, 1);
- ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
+ ret = wpa_drv_sched_scan(wpa_s, params);
if (ret)
wpa_supplicant_notify_scanning(wpa_s, 0);
else
@@ -285,7 +282,7 @@ int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
}
-int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
+static int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
{
int ret;
@@ -431,6 +428,39 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
+{
+ struct wpabuf *default_ies = NULL;
+ u8 ext_capab[18];
+ int ext_capab_len;
+ enum wpa_driver_if_type type = WPA_IF_STATION;
+
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+ type = WPA_IF_P2P_CLIENT;
+#endif /* CONFIG_P2P */
+
+ wpa_drv_get_ext_capa(wpa_s, type);
+
+ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+ sizeof(ext_capab));
+ if (ext_capab_len > 0 &&
+ wpabuf_resize(&default_ies, ext_capab_len) == 0)
+ wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
+
+#ifdef CONFIG_MBO
+ /* Send cellular capabilities for potential MBO STAs */
+ if (wpabuf_resize(&default_ies, 9) == 0)
+ wpas_mbo_scan_ie(wpa_s, default_ies);
+#endif /* CONFIG_MBO */
+
+ if (default_ies)
+ wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
+ wpabuf_len(default_ies));
+ wpabuf_free(default_ies);
+}
+
+
static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
{
struct wpabuf *extra_ie = NULL;
@@ -441,6 +471,13 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
+ else
+#endif /* CONFIG_P2P */
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab));
if (ext_capab_len > 0 &&
@@ -493,6 +530,19 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
wpabuf_put_buf(extra_ie, wpa_s->fst_ies);
#endif /* CONFIG_FST */
+#ifdef CONFIG_MBO
+ /* Send cellular capabilities for potential MBO STAs */
+ if (wpabuf_resize(&extra_ie, 9) == 0)
+ wpas_mbo_scan_ie(wpa_s, extra_ie);
+#endif /* CONFIG_MBO */
+
+ if (wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ]) {
+ struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ];
+
+ if (wpabuf_resize(&extra_ie, wpabuf_len(buf)) == 0)
+ wpabuf_put_buf(extra_ie, buf);
+ }
+
return extra_ie;
}
@@ -524,21 +574,6 @@ static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_P2P */
-static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
- u16 num_modes,
- enum hostapd_hw_mode mode)
-{
- u16 i;
-
- for (i = 0; i < num_modes; i++) {
- if (modes[i].mode == mode)
- return &modes[i];
- }
-
- return NULL;
-}
-
-
static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
enum hostapd_hw_mode band,
struct wpa_driver_scan_params *params)
@@ -588,6 +623,12 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
unsigned int i;
struct wpa_ssid *ssid;
+ /*
+ * For devices with max_ssids greater than 1, leave the last slot empty
+ * for adding the wildcard scan entry.
+ */
+ max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
+
for (i = 0; i < wpa_s->scan_id_count; i++) {
unsigned int j;
@@ -842,12 +883,10 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
* slot for the zero-terminator.
*/
params.freqs = os_malloc(sizeof(int) * 2);
- if (params.freqs == NULL) {
- wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
- return;
+ if (params.freqs) {
+ params.freqs[0] = wpa_s->assoc_freq;
+ params.freqs[1] = 0;
}
- params.freqs[0] = wpa_s->assoc_freq;
- params.freqs[1] = 0;
/*
* Reset the reattach flag so that we fall back to full scan if
@@ -1018,6 +1057,27 @@ ssid_list_set:
}
}
+ if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
+ struct wpa_bss *bss;
+
+ params.bssid = wpa_s->next_scan_bssid;
+ bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
+ if (bss && bss->ssid_len && params.num_ssids == 1 &&
+ params.ssids[0].ssid_len == 0) {
+ params.ssids[0].ssid = bss->ssid;
+ params.ssids[0].ssid_len = bss->ssid_len;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Scan a previously specified BSSID " MACSTR
+ " and SSID %s",
+ MAC2STR(params.bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len));
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Scan a previously specified BSSID " MACSTR,
+ MAC2STR(params.bssid));
+ }
+ }
+
scan_params = &params;
scan:
@@ -1078,6 +1138,8 @@ scan:
#ifdef CONFIG_INTERWORKING
wpa_s->interworking_fast_assoc_tried = 0;
#endif /* CONFIG_INTERWORKING */
+ if (params.bssid)
+ os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
}
}
@@ -1184,6 +1246,7 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
unsigned int max_sched_scan_ssids;
int wildcard = 0;
int need_ssids;
+ struct sched_scan_plan scan_plan;
if (!wpa_s->sched_scan_supported)
return -1;
@@ -1195,6 +1258,8 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
return -1;
+ wpa_s->sched_scan_stop_req = 0;
+
if (wpa_s->sched_scanning) {
wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
return 0;
@@ -1273,11 +1338,6 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
if (!ssid || !wpa_s->prev_sched_ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
- if (wpa_s->conf->sched_scan_interval)
- wpa_s->sched_scan_interval =
- wpa_s->conf->sched_scan_interval;
- if (wpa_s->sched_scan_interval == 0)
- wpa_s->sched_scan_interval = 10;
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
wpa_s->first_sched_scan = 1;
ssid = wpa_s->conf->ssid;
@@ -1362,14 +1422,51 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
scan_params = &params;
scan:
- if (ssid || !wpa_s->first_sched_scan) {
+ wpa_s->sched_scan_timed_out = 0;
+
+ /*
+ * We cannot support multiple scan plans if the scan request includes
+ * too many SSID's, so in this case use only the last scan plan and make
+ * it run infinitely. It will be stopped by the timeout.
+ */
+ if (wpa_s->sched_scan_plans_num == 1 ||
+ (wpa_s->sched_scan_plans_num && !ssid && wpa_s->first_sched_scan)) {
+ params.sched_scan_plans = wpa_s->sched_scan_plans;
+ params.sched_scan_plans_num = wpa_s->sched_scan_plans_num;
+ } else if (wpa_s->sched_scan_plans_num > 1) {
wpa_dbg(wpa_s, MSG_DEBUG,
- "Starting sched scan: interval %d timeout %d",
- wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
+ "Too many SSIDs. Default to using single scheduled_scan plan");
+ params.sched_scan_plans =
+ &wpa_s->sched_scan_plans[wpa_s->sched_scan_plans_num -
+ 1];
+ params.sched_scan_plans_num = 1;
} else {
+ if (wpa_s->conf->sched_scan_interval)
+ scan_plan.interval = wpa_s->conf->sched_scan_interval;
+ else
+ scan_plan.interval = 10;
+
+ if (scan_plan.interval > wpa_s->max_sched_scan_plan_interval) {
+ wpa_printf(MSG_WARNING,
+ "Scan interval too long(%u), use the maximum allowed(%u)",
+ scan_plan.interval,
+ wpa_s->max_sched_scan_plan_interval);
+ scan_plan.interval =
+ wpa_s->max_sched_scan_plan_interval;
+ }
+
+ scan_plan.iterations = 0;
+ params.sched_scan_plans = &scan_plan;
+ params.sched_scan_plans_num = 1;
+ }
+
+ if (ssid || !wpa_s->first_sched_scan) {
wpa_dbg(wpa_s, MSG_DEBUG,
- "Starting sched scan: interval %d (no timeout)",
- wpa_s->sched_scan_interval);
+ "Starting sched scan: interval %u timeout %d",
+ params.sched_scan_plans[0].interval,
+ wpa_s->sched_scan_timeout);
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan (no timeout)");
}
wpa_setband_scan_freqs(wpa_s, scan_params);
@@ -1383,8 +1480,7 @@ scan:
}
}
- ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
- wpa_s->sched_scan_interval);
+ ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params);
wpabuf_free(extra_ie);
os_free(params.filter_ssids);
if (ret) {
@@ -1402,9 +1498,12 @@ scan:
wpa_s, NULL);
wpa_s->first_sched_scan = 0;
wpa_s->sched_scan_timeout /= 2;
- wpa_s->sched_scan_interval *= 2;
- if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) {
- wpa_s->sched_scan_interval = 10;
+ params.sched_scan_plans[0].interval *= 2;
+ if ((unsigned int) wpa_s->sched_scan_timeout <
+ params.sched_scan_plans[0].interval ||
+ params.sched_scan_plans[0].interval >
+ wpa_s->max_sched_scan_plan_interval) {
+ params.sched_scan_plans[0].interval = 10;
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
}
}
@@ -1459,6 +1558,9 @@ void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
if (!wpa_s->sched_scanning)
return;
+ if (wpa_s->sched_scanning)
+ wpa_s->sched_scan_stop_req = 1;
+
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
wpa_supplicant_stop_sched_scan(wpa_s);
@@ -1518,20 +1620,7 @@ static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
*/
const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
{
- const u8 *end, *pos;
-
- pos = (const u8 *) (res + 1);
- end = pos + res->ie_len;
-
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
- break;
- if (pos[0] == ie)
- return pos;
- pos += 2 + pos[1];
- }
-
- return NULL;
+ return get_ie((const u8 *) (res + 1), res->ie_len, ie);
}
@@ -1552,8 +1641,8 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
pos = (const u8 *) (res + 1);
end = pos + res->ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
@@ -1589,8 +1678,8 @@ const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
pos += res->ie_len;
end = pos + res->beacon_ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
@@ -1625,8 +1714,8 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
pos = (const u8 *) (res + 1);
end = pos + res->ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
@@ -1834,8 +1923,8 @@ int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
}
-static void filter_scan_res(struct wpa_supplicant *wpa_s,
- struct wpa_scan_results *res)
+void filter_scan_res(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *res)
{
size_t i, j;
@@ -1862,13 +1951,13 @@ static void filter_scan_res(struct wpa_supplicant *wpa_s,
/*
* Noise floor values to use when we have signal strength
- * measurements, but no noise floor measurments. These values were
+ * measurements, but no noise floor measurements. These values were
* measured in an office environment with many APs.
*/
#define DEFAULT_NOISE_FLOOR_2GHZ (-89)
#define DEFAULT_NOISE_FLOOR_5GHZ (-92)
-static void scan_snr(struct wpa_scan_res *res)
+void scan_snr(struct wpa_scan_res *res)
{
if (res->flags & WPA_SCAN_NOISE_INVALID) {
res->noise = IS_5GHZ(res->freq) ?
@@ -1952,8 +2041,8 @@ static unsigned int max_vht80_rate(int snr)
}
-static void scan_est_throughput(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *res)
+void scan_est_throughput(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *res)
{
enum local_hw_capab capab = wpa_s->hw_capab;
int rate; /* max legacy rate in 500 kb/s units */
@@ -2150,6 +2239,9 @@ void scan_only_handler(struct wpa_supplicant *wpa_s,
wpa_s->scan_work = NULL;
radio_work_done(work);
}
+
+ if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
}
@@ -2216,6 +2308,19 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->only_new_results = src->only_new_results;
params->low_priority = src->low_priority;
+ if (src->sched_scan_plans_num > 0) {
+ params->sched_scan_plans =
+ os_malloc(sizeof(*src->sched_scan_plans) *
+ src->sched_scan_plans_num);
+ if (!params->sched_scan_plans)
+ goto failed;
+
+ os_memcpy(params->sched_scan_plans, src->sched_scan_plans,
+ sizeof(*src->sched_scan_plans) *
+ src->sched_scan_plans_num);
+ params->sched_scan_plans_num = src->sched_scan_plans_num;
+ }
+
if (src->mac_addr_rand) {
params->mac_addr_rand = src->mac_addr_rand;
@@ -2233,6 +2338,17 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->mac_addr_mask = mac_addr + ETH_ALEN;
}
}
+
+ if (src->bssid) {
+ u8 *bssid;
+
+ bssid = os_malloc(ETH_ALEN);
+ if (!bssid)
+ goto failed;
+ os_memcpy(bssid, src->bssid, ETH_ALEN);
+ params->bssid = bssid;
+ }
+
return params;
failed:
@@ -2253,6 +2369,7 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params)
os_free((u8 *) params->extra_ies);
os_free(params->freqs);
os_free(params->filter_ssids);
+ os_free(params->sched_scan_plans);
/*
* Note: params->mac_addr_mask points to same memory allocation and
@@ -2260,20 +2377,31 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params)
*/
os_free((u8 *) params->mac_addr);
+ os_free((u8 *) params->bssid);
+
os_free(params);
}
int wpas_start_pno(struct wpa_supplicant *wpa_s)
{
- int ret, interval, prio;
+ int ret, prio;
size_t i, num_ssid, num_match_ssid;
struct wpa_ssid *ssid;
struct wpa_driver_scan_params params;
+ struct sched_scan_plan scan_plan;
+ unsigned int max_sched_scan_ssids;
if (!wpa_s->sched_scan_supported)
return -1;
+ if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
+ max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
+ else
+ max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
+ if (max_sched_scan_ssids < 1)
+ return -1;
+
if (wpa_s->pno || wpa_s->pno_sched_pending)
return 0;
@@ -2294,6 +2422,13 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
}
}
+ if (wpa_s->sched_scan_stop_req) {
+ wpa_printf(MSG_DEBUG,
+ "Schedule PNO after previous sched scan has stopped");
+ wpa_s->pno_sched_pending = 1;
+ return 0;
+ }
+
os_memset(&params, 0, sizeof(params));
num_ssid = num_match_ssid = 0;
@@ -2317,10 +2452,10 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
num_ssid++;
}
- if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
+ if (num_ssid > max_sched_scan_ssids) {
wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
- "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
- num_ssid = WPAS_MAX_SCAN_SSIDS;
+ "%u", max_sched_scan_ssids, (unsigned int) num_ssid);
+ num_ssid = max_sched_scan_ssids;
}
if (num_match_ssid > wpa_s->max_match_sets) {
@@ -2363,8 +2498,20 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
if (wpa_s->conf->filter_rssi)
params.filter_rssi = wpa_s->conf->filter_rssi;
- interval = wpa_s->conf->sched_scan_interval ?
- wpa_s->conf->sched_scan_interval : 10;
+ if (wpa_s->sched_scan_plans_num) {
+ params.sched_scan_plans = wpa_s->sched_scan_plans;
+ params.sched_scan_plans_num = wpa_s->sched_scan_plans_num;
+ } else {
+ /* Set one scan plan that will run infinitely */
+ if (wpa_s->conf->sched_scan_interval)
+ scan_plan.interval = wpa_s->conf->sched_scan_interval;
+ else
+ scan_plan.interval = 10;
+
+ scan_plan.iterations = 0;
+ params.sched_scan_plans = &scan_plan;
+ params.sched_scan_plans_num = 1;
+ }
if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
@@ -2379,7 +2526,7 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
}
}
- ret = wpa_supplicant_start_sched_scan(wpa_s, &params, interval);
+ ret = wpa_supplicant_start_sched_scan(wpa_s, &params);
os_free(params.filter_ssids);
if (ret == 0)
wpa_s->pno = 1;
@@ -2397,6 +2544,7 @@ int wpas_stop_pno(struct wpa_supplicant *wpa_s)
return 0;
ret = wpa_supplicant_stop_sched_scan(wpa_s);
+ wpa_s->sched_scan_stop_req = 1;
wpa_s->pno = 0;
wpa_s->pno_sched_pending = 0;
@@ -2464,3 +2612,160 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
wpa_s->mac_addr_rand_enable |= type;
return 0;
}
+
+
+int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
+{
+ int scan_work = !!wpa_s->scan_work;
+
+#ifdef CONFIG_P2P
+ scan_work |= !!wpa_s->p2p_scan_work;
+#endif /* CONFIG_P2P */
+
+ if (scan_work && wpa_s->own_scan_running) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
+ return wpa_drv_abort_scan(wpa_s);
+ }
+
+ return 0;
+}
+
+
+int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct sched_scan_plan *scan_plans = NULL;
+ const char *token, *context = NULL;
+ unsigned int num = 0;
+
+ if (!cmd)
+ return -1;
+
+ if (!cmd[0]) {
+ wpa_printf(MSG_DEBUG, "Clear sched scan plans");
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = NULL;
+ wpa_s->sched_scan_plans_num = 0;
+ return 0;
+ }
+
+ while ((token = cstr_token(cmd, " ", &context))) {
+ int ret;
+ struct sched_scan_plan *scan_plan, *n;
+
+ n = os_realloc_array(scan_plans, num + 1, sizeof(*scan_plans));
+ if (!n)
+ goto fail;
+
+ scan_plans = n;
+ scan_plan = &scan_plans[num];
+ num++;
+
+ ret = sscanf(token, "%u:%u", &scan_plan->interval,
+ &scan_plan->iterations);
+ if (ret <= 0 || ret > 2 || !scan_plan->interval) {
+ wpa_printf(MSG_ERROR,
+ "Invalid sched scan plan input: %s", token);
+ goto fail;
+ }
+
+ if (scan_plan->interval > wpa_s->max_sched_scan_plan_interval) {
+ wpa_printf(MSG_WARNING,
+ "scan plan %u: Scan interval too long(%u), use the maximum allowed(%u)",
+ num, scan_plan->interval,
+ wpa_s->max_sched_scan_plan_interval);
+ scan_plan->interval =
+ wpa_s->max_sched_scan_plan_interval;
+ }
+
+ if (ret == 1) {
+ scan_plan->iterations = 0;
+ break;
+ }
+
+ if (!scan_plan->iterations) {
+ wpa_printf(MSG_ERROR,
+ "scan plan %u: Number of iterations cannot be zero",
+ num);
+ goto fail;
+ }
+
+ if (scan_plan->iterations >
+ wpa_s->max_sched_scan_plan_iterations) {
+ wpa_printf(MSG_WARNING,
+ "scan plan %u: Too many iterations(%u), use the maximum allowed(%u)",
+ num, scan_plan->iterations,
+ wpa_s->max_sched_scan_plan_iterations);
+ scan_plan->iterations =
+ wpa_s->max_sched_scan_plan_iterations;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "scan plan %u: interval=%u iterations=%u",
+ num, scan_plan->interval, scan_plan->iterations);
+ }
+
+ if (!scan_plans) {
+ wpa_printf(MSG_ERROR, "Invalid scan plans entry");
+ goto fail;
+ }
+
+ if (cstr_token(cmd, " ", &context) || scan_plans[num - 1].iterations) {
+ wpa_printf(MSG_ERROR,
+ "All scan plans but the last must specify a number of iterations");
+ goto fail;
+ }
+
+ wpa_printf(MSG_DEBUG, "scan plan %u (last plan): interval=%u",
+ num, scan_plans[num - 1].interval);
+
+ if (num > wpa_s->max_sched_scan_plans) {
+ wpa_printf(MSG_WARNING,
+ "Too many scheduled scan plans (only %u supported)",
+ wpa_s->max_sched_scan_plans);
+ wpa_printf(MSG_WARNING,
+ "Use only the first %u scan plans, and the last one (in infinite loop)",
+ wpa_s->max_sched_scan_plans - 1);
+ os_memcpy(&scan_plans[wpa_s->max_sched_scan_plans - 1],
+ &scan_plans[num - 1], sizeof(*scan_plans));
+ num = wpa_s->max_sched_scan_plans;
+ }
+
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = scan_plans;
+ wpa_s->sched_scan_plans_num = num;
+
+ return 0;
+
+fail:
+ os_free(scan_plans);
+ wpa_printf(MSG_ERROR, "invalid scan plans list");
+ return -1;
+}
+
+
+/**
+ * wpas_scan_reset_sched_scan - Reset sched_scan state
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to cancel a running scheduled scan and to reset an
+ * internal scan state to continue with a regular scan on the following
+ * wpa_supplicant_req_scan() calls.
+ */
+void wpas_scan_reset_sched_scan(struct wpa_supplicant *wpa_s)
+{
+ wpa_s->normal_scans = 0;
+ if (wpa_s->sched_scanning) {
+ wpa_s->sched_scan_timed_out = 0;
+ wpa_s->prev_sched_ssid = NULL;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ }
+}
+
+
+void wpas_scan_restart_sched_scan(struct wpa_supplicant *wpa_s)
+{
+ /* simulate timeout to restart the sched scan */
+ wpa_s->sched_scan_timed_out = 1;
+ wpa_s->prev_sched_ssid = NULL;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/scan.h b/freebsd/contrib/wpa/wpa_supplicant/scan.h
index 7650f5a2..2aa0a8be 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/scan.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/scan.h
@@ -39,20 +39,25 @@ void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec);
void scan_only_handler(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
int wpas_scan_scheduled(struct wpa_supplicant *wpa_s);
-int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- int interval);
-int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s);
struct wpa_driver_scan_params *
wpa_scan_clone_params(const struct wpa_driver_scan_params *src);
void wpa_scan_free_params(struct wpa_driver_scan_params *params);
int wpas_start_pno(struct wpa_supplicant *wpa_s);
int wpas_stop_pno(struct wpa_supplicant *wpa_s);
+void wpas_scan_reset_sched_scan(struct wpa_supplicant *wpa_s);
+void wpas_scan_restart_sched_scan(struct wpa_supplicant *wpa_s);
void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
unsigned int type);
int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
unsigned int type, const u8 *addr,
const u8 *mask);
+int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s);
+void filter_scan_res(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *res);
+void scan_snr(struct wpa_scan_res *res);
+void scan_est_throughput(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *res);
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
#endif /* SCAN_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.h b/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.h
index 5171b168..0d15ad01 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.h
@@ -88,7 +88,7 @@ enum ts_dir_idx {
*/
struct wmm_ac_addts_request {
/*
- * dialog token - Used to link the recived ADDTS response with this
+ * dialog token - Used to link the received ADDTS response with this
* saved ADDTS request when ADDTS response is being handled
*/
u8 dialog_token;
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h b/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h
index 8de43480..81d81535 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h
@@ -56,7 +56,7 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len);
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
- u8 query_reason);
+ u8 query_reason, int cand_list);
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c
index d65398e2..7346ae0b 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -13,6 +13,10 @@
*/
#include "includes.h"
+#ifdef CONFIG_MATCH_IFACE
+#include <net/if.h>
+#include <fnmatch.h>
+#endif /* CONFIG_MATCH_IFACE */
#include "common.h"
#include "crypto/random.h"
@@ -60,7 +64,7 @@
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
const char *const wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
@@ -190,7 +194,9 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
const u8 *bssid = wpa_s->bssid;
- if (is_zero_ether_addr(bssid))
+ if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
+ (wpa_s->wpa_state == WPA_AUTHENTICATING ||
+ wpa_s->wpa_state == WPA_ASSOCIATING))
bssid = wpa_s->pending_bssid;
wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
MAC2STR(bssid));
@@ -399,6 +405,18 @@ void free_hw_features(struct wpa_supplicant *wpa_s)
}
+static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss_tmp_disallowed *bss, *prev;
+
+ dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ dl_list_del(&bss->list);
+ os_free(bss);
+ }
+}
+
+
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
int i;
@@ -538,6 +556,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_s->last_scan_res = NULL;
#ifdef CONFIG_HS20
+ if (wpa_s->drv_priv)
+ wpa_drv_configure_frame_filters(wpa_s, 0);
hs20_deinit(wpa_s);
#endif /* CONFIG_HS20 */
@@ -547,6 +567,21 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
}
wmm_ac_notify_disassoc(wpa_s);
+
+ wpa_s->sched_scan_plans_num = 0;
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = NULL;
+
+#ifdef CONFIG_MBO
+ wpa_s->non_pref_chan_num = 0;
+ os_free(wpa_s->non_pref_chan);
+ wpa_s->non_pref_chan = NULL;
+#endif /* CONFIG_MBO */
+
+ free_bss_tmp_disallowed(wpa_s);
+
+ wpabuf_free(wpa_s->lci);
+ wpa_s->lci = NULL;
}
@@ -965,6 +1000,11 @@ static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
wpa_supplicant_terminate_proc(global);
}
}
+
+ if (wpa_debug_reopen_file() < 0) {
+ /* Ignore errors since we cannot really do much to fix this */
+ wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
+ }
}
@@ -1152,6 +1192,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
return -1;
}
+#ifdef CONFIG_NO_WPA
+ wpa_s->group_cipher = WPA_CIPHER_NONE;
+ wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
+#else /* CONFIG_NO_WPA */
sel = ie.group_cipher & ssid->group_cipher;
wpa_s->group_cipher = wpa_pick_group_cipher(sel);
if (wpa_s->group_cipher < 0) {
@@ -1171,6 +1215,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
}
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
wpa_cipher_txt(wpa_s->pairwise_cipher));
+#endif /* CONFIG_NO_WPA */
sel = ie.key_mgmt & ssid->key_mgmt;
#ifdef CONFIG_SAE
@@ -1281,7 +1326,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
int psk_set = 0;
if (ssid->psk_set) {
- wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
+ NULL);
psk_set = 1;
}
#ifndef CONFIG_NO_PBKDF2
@@ -1292,7 +1338,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
4096, psk, PMK_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
psk_set = 1;
os_memset(psk, 0, sizeof(psk));
}
@@ -1330,7 +1376,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
"external passphrase)",
psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
+ NULL);
psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else
@@ -1343,7 +1390,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
ext_password_free(pw);
return -1;
}
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
+ NULL);
psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else {
@@ -1406,9 +1454,20 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
if (wpa_s->conf->hs20)
*pos |= 0x40; /* Bit 46 - WNM-Notification */
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ *pos |= 0x40; /* Bit 46 - WNM-Notification */
+#endif /* CONFIG_MBO */
break;
case 6: /* Bits 48-55 */
break;
+ case 7: /* Bits 56-63 */
+ break;
+ case 8: /* Bits 64-71 */
+ if (wpa_s->conf->ftm_responder)
+ *pos |= 0x40; /* Bit 70 - FTM responder */
+ if (wpa_s->conf->ftm_initiator)
+ *pos |= 0x80; /* Bit 71 - FTM initiator */
+ break;
}
}
@@ -1418,6 +1477,9 @@ int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
u8 *pos = buf;
u8 len = 6, i;
+ if (len < 9 &&
+ (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder))
+ len = 9;
if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len;
if (buflen < (size_t) len + 2) {
@@ -1588,6 +1650,15 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
struct wpa_connect_work *cwork;
int rand_style;
+ wpa_s->own_disconnect_req = 0;
+
+ /*
+ * If we are starting a new connection, any previously pending EAPOL
+ * RX cannot be valid anymore.
+ */
+ wpabuf_free(wpa_s->pending_eapol_rx);
+ wpa_s->pending_eapol_rx = NULL;
+
if (ssid->mac_addr == -1)
rand_style = wpa_s->conf->mac_addr;
else
@@ -1595,9 +1666,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
wmm_ac_clear_saved_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 0;
+ wpa_s->reassoc_same_ess = 0;
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
+ wpa_s->reassoc_same_ess = 1;
if (wpa_s->current_bss && wpa_s->current_bss == bss) {
wmm_ac_save_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 1;
@@ -1663,10 +1736,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
wpa_s->current_bss = bss;
- wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
- "ssid=\"%s\" id=%d",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
- ssid->id);
+ wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->id);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
@@ -1696,6 +1768,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
+ wpas_abort_ongoing_scan(wpa_s);
+
cwork = os_zalloc(sizeof(*cwork));
if (cwork == NULL)
return;
@@ -1717,6 +1791,36 @@ static int bss_is_ibss(struct wpa_bss *bss)
}
+static int drv_supports_vht(struct wpa_supplicant *wpa_s,
+ const struct wpa_ssid *ssid)
+{
+ enum hostapd_hw_mode hw_mode;
+ struct hostapd_hw_modes *mode = NULL;
+ u8 channel;
+ int i;
+
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht)
+ return 0;
+#endif /* CONFIG_HT_OVERRIDES */
+
+ hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
+ if (hw_mode == NUM_HOSTAPD_MODES)
+ return 0;
+ for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
+ if (wpa_s->hw.modes[i].mode == hw_mode) {
+ mode = &wpa_s->hw.modes[i];
+ break;
+ }
+ }
+
+ if (!mode)
+ return 0;
+
+ return mode->vht_capab != 0;
+}
+
+
void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid,
struct hostapd_freq_params *freq)
@@ -1729,8 +1833,10 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
u8 channel;
int i, chan_idx, ht40 = -1, res, obss_scan = 1;
- unsigned int j;
+ unsigned int j, k;
struct hostapd_freq_params vht_freq;
+ int chwidth, seg0, seg1;
+ u32 vht_caps = 0;
freq->freq = ssid->frequency;
@@ -1782,6 +1888,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (!mode)
return;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht) {
+ freq->ht_enabled = 0;
+ return;
+ }
+#endif /* CONFIG_HT_OVERRIDES */
+
freq->ht_enabled = ht_supported(mode);
if (!freq->ht_enabled)
return;
@@ -1803,6 +1916,11 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht40)
+ return;
+#endif /* CONFIG_HT_OVERRIDES */
+
/* Check/setup HT40+/HT40- */
for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
if (ht40plus[j] == channel) {
@@ -1827,22 +1945,16 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
freq->channel = pri_chan->chan;
- switch (ht40) {
- case -1:
+ if (ht40 == -1) {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
return;
- freq->sec_channel_offset = -1;
- break;
- case 1:
+ } else {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
return;
- freq->sec_channel_offset = 1;
- break;
- default:
- break;
}
+ freq->sec_channel_offset = ht40;
- if (freq->sec_channel_offset && obss_scan) {
+ if (obss_scan) {
struct wpa_scan_results *scan_res;
scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
@@ -1880,12 +1992,12 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
"IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
freq->channel, freq->sec_channel_offset);
- /* Not sure if mesh is ready for VHT */
- if (ssid->mode != WPAS_MODE_IBSS)
+ if (!drv_supports_vht(wpa_s, ssid))
return;
/* For IBSS check VHT_IBSS flag */
- if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
return;
vht_freq = *freq;
@@ -1916,12 +2028,55 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
return;
}
+ chwidth = VHT_CHANWIDTH_80MHZ;
+ seg0 = vht80[j] + 6;
+ seg1 = 0;
+
+ if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
+ /* setup center_freq2, bandwidth */
+ for (k = 0; k < ARRAY_SIZE(vht80); k++) {
+ /* Only accept 80 MHz segments separated by a gap */
+ if (j == k || abs(vht80[j] - vht80[k]) == 16)
+ continue;
+ for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
+ struct hostapd_channel_data *chan;
+
+ chan = hw_get_channel_chan(mode, i, NULL);
+ if (!chan)
+ continue;
+
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_NO_IR |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+
+ /* Found a suitable second segment for 80+80 */
+ chwidth = VHT_CHANWIDTH_80P80MHZ;
+ vht_caps |=
+ VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+ seg1 = vht80[k] + 6;
+ }
+
+ if (chwidth == VHT_CHANWIDTH_80P80MHZ)
+ break;
+ }
+ } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
+ if (freq->freq == 5180) {
+ chwidth = VHT_CHANWIDTH_160MHZ;
+ vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ seg0 = 50;
+ } else if (freq->freq == 5520) {
+ chwidth = VHT_CHANWIDTH_160MHZ;
+ vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ seg0 = 114;
+ }
+ }
+
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
freq->channel, freq->ht_enabled,
vht_freq.vht_enabled,
freq->sec_channel_offset,
- VHT_CHANWIDTH_80MHZ,
- vht80[j] + 6, 0, 0) != 0)
+ chwidth, seg0, seg1, vht_caps) != 0)
return;
*freq = vht_freq;
@@ -1946,6 +2101,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
int wep_keys_set = 0;
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
+ u8 prev_bssid[ETH_ALEN];
#ifdef CONFIG_HT_OVERRIDES
struct ieee80211_ht_capabilities htcaps;
struct ieee80211_ht_capabilities htcaps_mask;
@@ -1954,6 +2110,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
struct ieee80211_vht_capabilities vhtcaps;
struct ieee80211_vht_capabilities vhtcaps_mask;
#endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_MBO
+ const u8 *mbo = NULL;
+#endif /* CONFIG_MBO */
if (deinit) {
if (work->started) {
@@ -1976,6 +2135,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
return;
}
+ os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
os_memset(&params, 0, sizeof(params));
wpa_s->reassociate = 0;
wpa_s->eap_expected_failure = 0;
@@ -2017,7 +2177,10 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
} else {
wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ if (bss)
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ else
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
}
if (!wpa_s->pno)
wpa_supplicant_cancel_sched_scan(wpa_s);
@@ -2138,25 +2301,21 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
#endif /* CONFIG_P2P */
-#ifdef CONFIG_HS20
- if (is_hs20_network(wpa_s, ssid, bss)) {
- struct wpabuf *hs20;
- hs20 = wpabuf_alloc(20);
- if (hs20) {
- int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
- size_t len;
-
- wpas_hs20_add_indication(hs20, pps_mo_id);
- len = sizeof(wpa_ie) - wpa_ie_len;
- if (wpabuf_len(hs20) <= len) {
- os_memcpy(wpa_ie + wpa_ie_len,
- wpabuf_head(hs20), wpabuf_len(hs20));
- wpa_ie_len += wpabuf_len(hs20);
- }
- wpabuf_free(hs20);
+#ifdef CONFIG_MBO
+ if (bss) {
+ mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
+ if (mbo) {
+ int len;
+
+ len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
+ wpa_ie + wpa_ie_len,
+ sizeof(wpa_ie) -
+ wpa_ie_len);
+ if (len > 0)
+ wpa_ie_len += len;
}
}
-#endif /* CONFIG_HS20 */
+#endif /* CONFIG_MBO */
/*
* Workaround: Add Extended Capabilities element only if the AP
@@ -2166,6 +2325,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
* element in all cases, it is justifiable to skip it to avoid
* interoperability issues.
*/
+ if (ssid->p2p_group)
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
+ else
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+
if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
u8 ext_capab[18];
int ext_capab_len;
@@ -2182,6 +2346,29 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
}
+#ifdef CONFIG_HS20
+ if (is_hs20_network(wpa_s, ssid, bss)) {
+ struct wpabuf *hs20;
+
+ hs20 = wpabuf_alloc(20);
+ if (hs20) {
+ int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+ size_t len;
+
+ wpas_hs20_add_indication(hs20, pps_mo_id);
+ len = sizeof(wpa_ie) - wpa_ie_len;
+ if (wpabuf_len(hs20) <= len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(hs20), wpabuf_len(hs20));
+ wpa_ie_len += wpabuf_len(hs20);
+ }
+ wpabuf_free(hs20);
+
+ hs20_configure_frame_filters(wpa_s);
+ }
+ }
+#endif /* CONFIG_HS20 */
+
if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
@@ -2206,6 +2393,17 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
#endif /* CONFIG_FST */
+#ifdef CONFIG_MBO
+ if (mbo) {
+ int len;
+
+ len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
+ sizeof(wpa_ie) - wpa_ie_len);
+ if (len >= 0)
+ wpa_ie_len += len;
+ }
+#endif /* CONFIG_MBO */
+
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
@@ -2258,9 +2456,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
params.bssid_hint = bss->bssid;
params.freq_hint = bss->freq;
+ params.pbss = bss_is_pbss(bss);
} else {
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
+ params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
}
if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
@@ -2344,8 +2544,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.p2p = ssid->p2p_group;
- if (wpa_s->parent->set_sta_uapsd)
- params.uapsd = wpa_s->parent->sta_uapsd;
+ if (wpa_s->p2pdev->set_sta_uapsd)
+ params.uapsd = wpa_s->p2pdev->sta_uapsd;
else
params.uapsd = -1;
@@ -2386,6 +2586,10 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
#endif /* CONFIG_P2P */
+ if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
+ wpa_s->current_ssid)
+ params.prev_bssid = prev_bssid;
+
ret = wpa_drv_associate(wpa_s, &params);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
@@ -2453,8 +2657,14 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid;
- if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set)
+
+ if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
wpa_s->current_bss = bss;
+#ifdef CONFIG_HS20
+ hs20_configure_frame_filters(wpa_s);
+#endif /* CONFIG_HS20 */
+ }
+
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
if (old_ssid != wpa_s->current_ssid)
@@ -2499,12 +2709,12 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
- if (!is_zero_ether_addr(wpa_s->bssid))
- addr = wpa_s->bssid;
- else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
- (wpa_s->wpa_state == WPA_AUTHENTICATING ||
- wpa_s->wpa_state == WPA_ASSOCIATING))
+ if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
+ (wpa_s->wpa_state == WPA_AUTHENTICATING ||
+ wpa_s->wpa_state == WPA_ASSOCIATING))
addr = wpa_s->pending_bssid;
+ else if (!is_zero_ether_addr(wpa_s->bssid))
+ addr = wpa_s->bssid;
else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
/*
* When using driver-based BSS selection, we may not know the
@@ -2522,8 +2732,8 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
- wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
- wpa_s->ifname);
+ wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
+ wpa_s->ifname);
wpa_supplicant_leave_mesh(wpa_s);
}
#endif /* CONFIG_MESH */
@@ -2561,6 +2771,95 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
/**
+ * wpa_supplicant_add_network - Add a new network
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: The new network configuration or %NULL if operation failed
+ *
+ * This function performs the following operations:
+ * 1. Adds a new network.
+ * 2. Send network addition notification.
+ * 3. Marks the network disabled.
+ * 4. Set network default parameters.
+ */
+struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid;
+
+ ssid = wpa_config_add_network(wpa_s->conf);
+ if (!ssid)
+ return NULL;
+ wpas_notify_network_added(wpa_s, ssid);
+ ssid->disabled = 1;
+ wpa_config_set_network_defaults(ssid);
+
+ return ssid;
+}
+
+
+/**
+ * wpa_supplicant_remove_network - Remove a configured network based on id
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @id: Unique network id to search for
+ * Returns: 0 on success, or -1 if the network was not found, -2 if the network
+ * could not be removed
+ *
+ * This function performs the following operations:
+ * 1. Removes the network.
+ * 2. Send network removal notification.
+ * 3. Update internal state machines.
+ * 4. Stop any running sched scans.
+ */
+int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
+{
+ struct wpa_ssid *ssid;
+ int was_disabled;
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (!ssid)
+ return -1;
+ wpas_notify_network_removed(wpa_s, ssid);
+
+ if (wpa_s->last_ssid == ssid)
+ wpa_s->last_ssid = NULL;
+
+ if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
+#ifdef CONFIG_SME
+ wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+ /*
+ * Invalidate the EAP session cache if the current or
+ * previously used network is removed.
+ */
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
+
+ if (ssid == wpa_s->current_ssid) {
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ }
+
+ was_disabled = ssid->disabled;
+
+ if (wpa_config_remove_network(wpa_s->conf, id) < 0)
+ return -2;
+
+ if (!was_disabled && wpa_s->sched_scanning) {
+ wpa_printf(MSG_DEBUG,
+ "Stop ongoing sched_scan to remove network from filters");
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ }
+
+ return 0;
+}
+
+
+/**
* wpa_supplicant_enable_network - Mark a configured network as enabled
* @wpa_s: wpa_supplicant structure for a network interface
* @ssid: wpa_ssid structure for a configured network or %NULL
@@ -2690,7 +2989,8 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
wpas_notify_network_enabled_changed(wpa_s, other_ssid);
}
- if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
+ if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
+ wpa_s->wpa_state >= WPA_AUTHENTICATING) {
/* We are already associated with the selected network */
wpa_printf(MSG_DEBUG, "Already associated with the "
"selected network - do nothing");
@@ -2719,6 +3019,7 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
if (wpa_s->connect_without_scan ||
wpa_supplicant_fast_associate(wpa_s) != 1) {
wpa_s->scan_req = NORMAL_SCAN_REQ;
+ wpas_scan_reset_sched_scan(wpa_s);
wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
}
@@ -2996,7 +3297,7 @@ static int select_driver(struct wpa_supplicant *wpa_s, int i)
struct wpa_global *global = wpa_s->global;
if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
- global->drv_priv[i] = wpa_drivers[i]->global_init();
+ global->drv_priv[i] = wpa_drivers[i]->global_init(global);
if (global->drv_priv[i] == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize driver "
"'%s'", wpa_drivers[i]->name);
@@ -3079,6 +3380,13 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_auth_resp) {
+ wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
+ return;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
#ifdef CONFIG_PEERKEY
if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
wpa_s->current_ssid->peerkey &&
@@ -3363,8 +3671,11 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
wpa_s->scan_interval = 5;
wpa_s->new_connection = 1;
wpa_s->parent = parent ? parent : wpa_s;
+ wpa_s->p2pdev = wpa_s->parent;
wpa_s->sched_scanning = 0;
+ dl_list_init(&wpa_s->bss_tmp_disallowed);
+
return wpa_s;
}
@@ -3616,8 +3927,8 @@ void wpa_supplicant_apply_vht_overrides(
if (!vhtcaps || !vhtcaps_mask)
return;
- vhtcaps->vht_capabilities_info = ssid->vht_capa;
- vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
+ vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
+ vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
#ifdef CONFIG_HT_OVERRIDES
/* if max ampdu is <= 3, we have to make the HT cap the same */
@@ -3639,15 +3950,17 @@ void wpa_supplicant_apply_vht_overrides(
#define OVERRIDE_MCS(i) \
if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
- 3 << 2 * (i - 1); \
+ host_to_le16(3 << 2 * (i - 1)); \
vhtcaps->vht_supported_mcs_set.tx_map |= \
- ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
+ host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
+ 2 * (i - 1)); \
} \
if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
- 3 << 2 * (i - 1); \
+ host_to_le16(3 << 2 * (i - 1)); \
vhtcaps->vht_supported_mcs_set.rx_map |= \
- ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
+ host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
+ 2 * (i - 1)); \
}
OVERRIDE_MCS(1);
@@ -3819,8 +4132,9 @@ static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
}
-const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+static const u8 * wpas_fst_get_peer_first(void *ctx,
+ struct fst_get_peer_ctx **get_ctx,
+ Boolean mb_only)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -3832,8 +4146,9 @@ const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx,
}
-const u8 * wpas_fst_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+static const u8 * wpas_fst_get_peer_next(void *ctx,
+ struct fst_get_peer_ctx **get_ctx,
+ Boolean mb_only)
{
return NULL;
}
@@ -3872,6 +4187,55 @@ static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
}
+enum wpa_radio_work_band wpas_freq_to_band(int freq)
+{
+ if (freq < 3000)
+ return BAND_2_4_GHZ;
+ if (freq > 50000)
+ return BAND_60_GHZ;
+ return BAND_5_GHZ;
+}
+
+
+unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
+{
+ int i;
+ unsigned int band = 0;
+
+ if (freqs) {
+ /* freqs are specified for the radio work */
+ for (i = 0; freqs[i]; i++)
+ band |= wpas_freq_to_band(freqs[i]);
+ } else {
+ /*
+ * freqs are not specified, implies all
+ * the supported freqs by HW
+ */
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ if (wpa_s->hw.modes[i].num_channels != 0) {
+ if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211B ||
+ wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211G)
+ band |= BAND_2_4_GHZ;
+ else if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211A)
+ band |= BAND_5_GHZ;
+ else if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211AD)
+ band |= BAND_60_GHZ;
+ else if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211ANY)
+ band = BAND_2_4_GHZ | BAND_5_GHZ |
+ BAND_60_GHZ;
+ }
+ }
+ }
+
+ return band;
+}
+
+
static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
const char *rn)
{
@@ -3924,11 +4288,103 @@ static void radio_work_free(struct wpa_radio_work *work)
}
#endif /* CONFIG_P2P */
+ if (work->started) {
+ work->wpa_s->radio->num_active_works--;
+ wpa_dbg(work->wpa_s, MSG_DEBUG,
+ "radio_work_free('%s'@%p: num_active_works --> %u",
+ work->type, work,
+ work->wpa_s->radio->num_active_works);
+ }
+
dl_list_del(&work->list);
os_free(work);
}
+static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
+{
+ struct wpa_radio_work *active_work = NULL;
+ struct wpa_radio_work *tmp;
+
+ /* Get the active work to know the type and band. */
+ dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
+ if (tmp->started) {
+ active_work = tmp;
+ break;
+ }
+ }
+
+ if (!active_work) {
+ /* No active work, start one */
+ radio->num_active_works = 0;
+ dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
+ list) {
+ if (os_strcmp(tmp->type, "scan") == 0 &&
+ radio->external_scan_running &&
+ (((struct wpa_driver_scan_params *)
+ tmp->ctx)->only_new_results ||
+ tmp->wpa_s->clear_driver_scan_cache))
+ continue;
+ return tmp;
+ }
+ return NULL;
+ }
+
+ if (os_strcmp(active_work->type, "sme-connect") == 0 ||
+ os_strcmp(active_work->type, "connect") == 0) {
+ /*
+ * If the active work is either connect or sme-connect,
+ * do not parallelize them with other radio works.
+ */
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "Do not parallelize radio work with %s",
+ active_work->type);
+ return NULL;
+ }
+
+ dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
+ if (tmp->started)
+ continue;
+
+ /*
+ * If connect or sme-connect are enqueued, parallelize only
+ * those operations ahead of them in the queue.
+ */
+ if (os_strcmp(tmp->type, "connect") == 0 ||
+ os_strcmp(tmp->type, "sme-connect") == 0)
+ break;
+
+ /*
+ * Check that the radio works are distinct and
+ * on different bands.
+ */
+ if (os_strcmp(active_work->type, tmp->type) != 0 &&
+ (active_work->bands != tmp->bands)) {
+ /*
+ * If a scan has to be scheduled through nl80211 scan
+ * interface and if an external scan is already running,
+ * do not schedule the scan since it is likely to get
+ * rejected by kernel.
+ */
+ if (os_strcmp(tmp->type, "scan") == 0 &&
+ radio->external_scan_running &&
+ (((struct wpa_driver_scan_params *)
+ tmp->ctx)->only_new_results ||
+ tmp->wpa_s->clear_driver_scan_cache))
+ continue;
+
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "active_work:%s new_work:%s",
+ active_work->type, tmp->type);
+ return tmp;
+ }
+ }
+
+ /* Did not find a radio work to schedule in parallel. */
+ return NULL;
+}
+
+
static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_radio *radio = eloop_ctx;
@@ -3937,26 +4393,48 @@ static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
struct wpa_supplicant *wpa_s;
work = dl_list_first(&radio->work, struct wpa_radio_work, list);
- if (work == NULL)
+ if (work == NULL) {
+ radio->num_active_works = 0;
return;
-
- if (work->started)
- return; /* already started and still in progress */
+ }
wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
radio_list);
- if (wpa_s && wpa_s->radio->external_scan_running) {
- wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
- return;
+
+ if (!(wpa_s &&
+ wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
+ if (work->started)
+ return; /* already started and still in progress */
+
+ if (wpa_s && wpa_s->radio->external_scan_running) {
+ wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
+ return;
+ }
+ } else {
+ work = NULL;
+ if (radio->num_active_works < MAX_ACTIVE_WORKS) {
+ /* get the work to schedule next */
+ work = radio_work_get_next_work(radio);
+ }
+ if (!work)
+ return;
}
+ wpa_s = work->wpa_s;
os_get_reltime(&now);
os_reltime_sub(&now, &work->time, &diff);
- wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Starting radio work '%s'@%p after %ld.%06ld second wait",
work->type, work, diff.sec, diff.usec);
work->started = 1;
work->time = now;
+ radio->num_active_works++;
+
work->cb(work, 0);
+
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
+ radio->num_active_works < MAX_ACTIVE_WORKS)
+ radio_work_check_next(wpa_s);
}
@@ -4064,6 +4542,7 @@ int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
void (*cb)(struct wpa_radio_work *work, int deinit),
void *ctx)
{
+ struct wpa_radio *radio = wpa_s->radio;
struct wpa_radio_work *work;
int was_empty;
@@ -4078,6 +4557,16 @@ int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
work->cb = cb;
work->ctx = ctx;
+ if (freq)
+ work->bands = wpas_freq_to_band(freq);
+ else if (os_strcmp(type, "scan") == 0 ||
+ os_strcmp(type, "p2p-scan") == 0)
+ work->bands = wpas_get_bands(wpa_s,
+ ((struct wpa_driver_scan_params *)
+ ctx)->freqs);
+ else
+ work->bands = wpas_get_bands(wpa_s, NULL);
+
was_empty = dl_list_empty(&wpa_s->radio->work);
if (next)
dl_list_add(&wpa_s->radio->work, &work->list);
@@ -4086,6 +4575,12 @@ int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
if (was_empty) {
wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
radio_work_check_next(wpa_s);
+ } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
+ && radio->num_active_works < MAX_ACTIVE_WORKS) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Try to schedule a radio work (num_active_works=%u)",
+ radio->num_active_works);
+ radio_work_check_next(wpa_s);
}
return 0;
@@ -4341,6 +4836,11 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
wpa_s->max_scan_ssids = capa.max_scan_ssids;
wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
+ wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
+ wpa_s->max_sched_scan_plan_interval =
+ capa.max_sched_scan_plan_interval;
+ wpa_s->max_sched_scan_plan_iterations =
+ capa.max_sched_scan_plan_iterations;
wpa_s->sched_scan_supported = capa.sched_scan_supported;
wpa_s->max_match_sets = capa.max_match_sets;
wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
@@ -4480,6 +4980,17 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
wpas_rrm_reset(wpa_s);
+ wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+
+#ifdef CONFIG_HS20
+ hs20_init(wpa_s);
+#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
+#endif /* CONFIG_MBO */
+
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+
return 0;
}
@@ -4495,6 +5006,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
iface = global->ifaces;
while (iface) {
+ if (iface->p2pdev == wpa_s)
+ iface->p2pdev = iface->parent;
if (iface == wpa_s || iface->parent != wpa_s) {
iface = iface->next;
continue;
@@ -4565,6 +5078,74 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
}
+#ifdef CONFIG_MATCH_IFACE
+
+/**
+ * wpa_supplicant_match_iface - Match an interface description to a name
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @ifname: Name of the interface to match
+ * Returns: Pointer to the created interface description or %NULL on failure
+ */
+struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
+ const char *ifname)
+{
+ int i;
+ struct wpa_interface *iface, *miface;
+
+ for (i = 0; i < global->params.match_iface_count; i++) {
+ miface = &global->params.match_ifaces[i];
+ if (!miface->ifname ||
+ fnmatch(miface->ifname, ifname, 0) == 0) {
+ iface = os_zalloc(sizeof(*iface));
+ if (!iface)
+ return NULL;
+ *iface = *miface;
+ iface->ifname = ifname;
+ return iface;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * wpa_supplicant_match_existing - Match existing interfaces
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 on success, -1 on failure
+ */
+static int wpa_supplicant_match_existing(struct wpa_global *global)
+{
+ struct if_nameindex *ifi, *ifp;
+ struct wpa_supplicant *wpa_s;
+ struct wpa_interface *iface;
+
+ ifp = if_nameindex();
+ if (!ifp) {
+ wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
+ return -1;
+ }
+
+ for (ifi = ifp; ifi->if_name; ifi++) {
+ wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
+ if (wpa_s)
+ continue;
+ iface = wpa_supplicant_match_iface(global, ifi->if_name);
+ if (iface) {
+ wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
+ os_free(iface);
+ if (wpa_s)
+ wpa_s->matched = 1;
+ }
+ }
+
+ if_freenameindex(ifp);
+ return 0;
+}
+
+#endif /* CONFIG_MATCH_IFACE */
+
+
/**
* wpa_supplicant_add_iface - Add a new network interface
* @global: Pointer to global data from wpa_supplicant_init()
@@ -4866,6 +5447,18 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
if (params->override_ctrl_interface)
global->params.override_ctrl_interface =
os_strdup(params->override_ctrl_interface);
+#ifdef CONFIG_MATCH_IFACE
+ global->params.match_iface_count = params->match_iface_count;
+ if (params->match_iface_count) {
+ global->params.match_ifaces =
+ os_calloc(params->match_iface_count,
+ sizeof(struct wpa_interface));
+ os_memcpy(global->params.match_ifaces,
+ params->match_ifaces,
+ params->match_iface_count *
+ sizeof(struct wpa_interface));
+ }
+#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_P2P
if (params->conf_p2p_dev)
global->params.conf_p2p_dev =
@@ -4941,12 +5534,18 @@ int wpa_supplicant_run(struct wpa_global *global)
struct wpa_supplicant *wpa_s;
if (global->params.daemonize &&
- wpa_supplicant_daemon(global->params.pid_file))
+ (wpa_supplicant_daemon(global->params.pid_file) ||
+ eloop_sock_requeue()))
+ return -1;
+
+#ifdef CONFIG_MATCH_IFACE
+ if (wpa_supplicant_match_existing(global))
return -1;
+#endif
if (global->params.wait_for_monitor) {
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
- if (wpa_s->ctrl_iface)
+ if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
wpa_supplicant_ctrl_iface_wait(
wpa_s->ctrl_iface);
}
@@ -5012,6 +5611,9 @@ void wpa_supplicant_deinit(struct wpa_global *global)
os_free(global->params.ctrl_interface_group);
os_free(global->params.override_driver);
os_free(global->params.override_ctrl_interface);
+#ifdef CONFIG_MATCH_IFACE
+ os_free(global->params.match_ifaces);
+#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_P2P
os_free(global->params.conf_p2p_dev);
#endif /* CONFIG_P2P */
@@ -5044,6 +5646,9 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
wpas_init_ext_pw(wpa_s);
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
+ wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
@@ -5283,6 +5888,16 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
wpa_supplicant_req_scan(wpa_s, 0, 0);
break;
+ case WPA_CTRL_REQ_EXT_CERT_CHECK:
+ if (eap->pending_ext_cert_check != PENDING_CHECK)
+ return -1;
+ if (os_strcmp(value, "good") == 0)
+ eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
+ else if (os_strcmp(value, "bad") == 0)
+ eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
+ else
+ return -1;
+ break;
default:
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
return -1;
@@ -5352,6 +5967,19 @@ int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
return NO_MGMT_FRAME_PROTECTION;
}
+ if (ssid &&
+ (ssid->key_mgmt &
+ ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
+ WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
+ /*
+ * Do not use the default PMF value for non-RSN networks
+ * since PMF is available only with RSN and pmf=2
+ * configuration would otherwise prevent connections to
+ * all open networks.
+ */
+ return NO_MGMT_FRAME_PROTECTION;
+ }
+
return wpa_s->conf->pmf;
}
@@ -5510,6 +6138,27 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s)
}
+/**
+ * wpas_request_disconnection - Request disconnection
+ * @wpa_s: Pointer to the network interface
+ *
+ * This function is used to request disconnection from the currently connected
+ * network. This will stop any ongoing scans and initiate deauthentication.
+ */
+void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_SME
+ wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+ wpa_s->reassociate = 0;
+ wpa_s->disconnected = 1;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_cancel_scan(wpa_s);
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+}
+
+
void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
struct wpa_used_freq_data *freqs_data,
unsigned int len)
@@ -5692,11 +6341,19 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
#define ECANCELED -1
#endif
+/* Measurement Request element + Location Subject + Maximum Age subelement */
+#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
+/* Measurement Request element + Location Civic Request */
+#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
+
+
/**
* wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
* @wpa_s: Pointer to wpa_supplicant
* @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
* is sent in the request.
+ * @lci: if set, neighbor request will include LCI request
+ * @civic: if set, neighbor request will include civic location request
* @cb: Callback function to be called once the requested report arrives, or
* timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
* In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
@@ -5710,7 +6367,8 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
* Request must contain a callback function.
*/
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
+ const struct wpa_ssid_value *ssid,
+ int lci, int civic,
void (*cb)(void *ctx,
struct wpabuf *neighbor_rep),
void *cb_ctx)
@@ -5751,7 +6409,9 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
}
/* 3 = action category + action code + dialog token */
- buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
+ buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
+ (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
+ (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
if (buf == NULL) {
wpa_printf(MSG_DEBUG,
"RRM: Failed to allocate Neighbor Report Request");
@@ -5771,6 +6431,72 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
}
+ if (lci) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 1); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+
+ /* Optional Subelements */
+ /*
+ * IEEE P802.11-REVmc/D5.0 Figure 9-170
+ * The Maximum Age subelement is required, otherwise the AP can
+ * send only data that was determined after receiving the
+ * request. Setting it here to unlimited age.
+ */
+ wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
+ wpabuf_put_u8(buf, 2);
+ wpabuf_put_le16(buf, 0xffff);
+ }
+
+ if (civic) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 2); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ /* Measurement Type */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
+ * Location Civic request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+ wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
+ /* Location Service Interval Units: Seconds */
+ wpabuf_put_u8(buf, 0);
+ /* Location Service Interval: 0 - Only one report is requested
+ */
+ wpabuf_put_le16(buf, 0);
+ /* No optional subelements */
+ }
+
wpa_s->rrm.next_neighbor_rep_token++;
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
@@ -5793,6 +6519,147 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
}
+static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
+ const u8 *request, size_t len,
+ struct wpabuf *report)
+{
+ u8 token, type, subject;
+ u16 max_age = 0;
+ struct os_reltime t, diff;
+ unsigned long diff_l;
+ u8 *ptoken;
+ const u8 *subelem;
+
+ if (!wpa_s->lci || len < 3 + 4)
+ return report;
+
+ token = *request++;
+ /* Measurement request mode isn't used */
+ request++;
+ type = *request++;
+ subject = *request++;
+
+ wpa_printf(MSG_DEBUG,
+ "Measurement request token %u type %u location subject %u",
+ token, type, subject);
+
+ if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
+ wpa_printf(MSG_INFO,
+ "Not building LCI report - bad type or location subject");
+ return report;
+ }
+
+ /* Subelements are formatted exactly like elements */
+ subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
+ if (subelem && subelem[1] == 2)
+ max_age = WPA_GET_LE16(subelem + 2);
+
+ if (os_get_reltime(&t))
+ return report;
+
+ os_reltime_sub(&t, &wpa_s->lci_time, &diff);
+ /* LCI age is calculated in 10th of a second units. */
+ diff_l = diff.sec * 10 + diff.usec / 100000;
+
+ if (max_age != 0xffff && max_age < diff_l)
+ return report;
+
+ if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
+ return report;
+
+ wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
+ wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
+ /* We'll override user's measurement token */
+ ptoken = wpabuf_put(report, 0);
+ wpabuf_put_buf(report, wpa_s->lci);
+ *ptoken = token;
+
+ return report;
+}
+
+
+void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *frame, size_t len)
+{
+ struct wpabuf *buf, *report;
+ u8 token;
+ const u8 *ie, *end;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not associated");
+ return;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not RRM network");
+ return;
+ }
+
+ if (len < 3) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring too short radio measurement request");
+ return;
+ }
+
+ end = frame + len;
+
+ token = *frame++;
+
+ /* Ignore number of repetitions because it's not used in LCI request */
+ frame += 2;
+
+ report = NULL;
+ while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
+ ie[1] >= 3) {
+ u8 msmt_type;
+
+ msmt_type = ie[4];
+ wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
+
+ switch (msmt_type) {
+ case MEASURE_TYPE_LCI:
+ report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
+ report);
+ break;
+ default:
+ wpa_printf(MSG_INFO,
+ "RRM: Unsupported radio measurement request %d",
+ msmt_type);
+ break;
+ }
+
+ frame = ie + ie[1] + 2;
+ }
+
+ if (!report)
+ return;
+
+ buf = wpabuf_alloc(3 + wpabuf_len(report));
+ if (!buf) {
+ wpabuf_free(report);
+ return;
+ }
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
+ wpabuf_put_u8(buf, token);
+
+ wpabuf_put_buf(buf, report);
+ wpabuf_free(report);
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0)) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Radio measurement report failed: Sending Action frame failed");
+ }
+ wpabuf_free(buf);
+}
+
+
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
const u8 *src,
const u8 *frame, size_t len,
@@ -5870,3 +6737,175 @@ void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
}
wpabuf_free(buf);
}
+
+
+struct wpa_supplicant *
+wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
+{
+ switch (frame) {
+#ifdef CONFIG_P2P
+ case VENDOR_ELEM_PROBE_REQ_P2P:
+ case VENDOR_ELEM_PROBE_RESP_P2P:
+ case VENDOR_ELEM_PROBE_RESP_P2P_GO:
+ case VENDOR_ELEM_BEACON_P2P_GO:
+ case VENDOR_ELEM_P2P_PD_REQ:
+ case VENDOR_ELEM_P2P_PD_RESP:
+ case VENDOR_ELEM_P2P_GO_NEG_REQ:
+ case VENDOR_ELEM_P2P_GO_NEG_RESP:
+ case VENDOR_ELEM_P2P_GO_NEG_CONF:
+ case VENDOR_ELEM_P2P_INV_REQ:
+ case VENDOR_ELEM_P2P_INV_RESP:
+ case VENDOR_ELEM_P2P_ASSOC_REQ:
+ case VENDOR_ELEM_P2P_ASSOC_RESP:
+ return wpa_s->p2pdev;
+#endif /* CONFIG_P2P */
+ default:
+ return wpa_s;
+ }
+}
+
+
+void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
+{
+ unsigned int i;
+ char buf[30];
+
+ wpa_printf(MSG_DEBUG, "Update vendor elements");
+
+ for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
+ if (wpa_s->vendor_elem[i]) {
+ int res;
+
+ res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
+ if (!os_snprintf_error(sizeof(buf), res)) {
+ wpa_hexdump_buf(MSG_DEBUG, buf,
+ wpa_s->vendor_elem[i]);
+ }
+ }
+ }
+
+#ifdef CONFIG_P2P
+ if (wpa_s->parent == wpa_s &&
+ wpa_s->global->p2p &&
+ !wpa_s->global->p2p_disabled)
+ p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
+#endif /* CONFIG_P2P */
+}
+
+
+int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
+ const u8 *elem, size_t len)
+{
+ u8 *ie, *end;
+
+ ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
+ end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
+
+ for (; ie + 1 < end; ie += 2 + ie[1]) {
+ if (ie + len > end)
+ break;
+ if (os_memcmp(ie, elem, len) != 0)
+ continue;
+
+ if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
+ wpabuf_free(wpa_s->vendor_elem[frame]);
+ wpa_s->vendor_elem[frame] = NULL;
+ } else {
+ os_memmove(ie, ie + len, end - (ie + len));
+ wpa_s->vendor_elem[frame]->used -= len;
+ }
+ wpas_vendor_elem_update(wpa_s);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
+ u16 num_modes, enum hostapd_hw_mode mode)
+{
+ u16 i;
+
+ for (i = 0; i < num_modes; i++) {
+ if (modes[i].mode == mode)
+ return &modes[i];
+ }
+
+ return NULL;
+}
+
+
+static struct
+wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
+{
+ struct wpa_bss_tmp_disallowed *bss;
+
+ dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
+ return bss;
+ }
+
+ return NULL;
+}
+
+
+void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ unsigned int sec)
+{
+ struct wpa_bss_tmp_disallowed *bss;
+ struct os_reltime until;
+
+ os_get_reltime(&until);
+ until.sec += sec;
+
+ bss = wpas_get_disallowed_bss(wpa_s, bssid);
+ if (bss) {
+ bss->disallowed_until = until;
+ return;
+ }
+
+ bss = os_malloc(sizeof(*bss));
+ if (!bss) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to allocate memory for temp disallow BSS");
+ return;
+ }
+
+ bss->disallowed_until = until;
+ os_memcpy(bss->bssid, bssid, ETH_ALEN);
+ dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
+}
+
+
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+ struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
+ struct os_reltime now, age;
+
+ os_get_reltime(&now);
+
+ dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (!os_reltime_before(&now, &tmp->disallowed_until)) {
+ /* This BSS is not disallowed anymore */
+ dl_list_del(&tmp->list);
+ os_free(tmp);
+ continue;
+ }
+ if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
+ bss = tmp;
+ break;
+ }
+ }
+ if (!bss)
+ return 0;
+
+ os_reltime_sub(&bss->disallowed_until, &now, &age);
+ wpa_printf(MSG_DEBUG,
+ "BSS " MACSTR " disabled for %ld.%0ld seconds",
+ MAC2STR(bss->bssid), age.sec, age.usec);
+ return 1;
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
index 318768bc..ef9273d0 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
@@ -44,6 +44,7 @@ struct wpa_driver_associate_params;
struct ctrl_iface_priv;
struct ctrl_iface_global_priv;
struct wpas_dbus_priv;
+struct wpas_binder_priv;
/**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface()
@@ -228,6 +229,17 @@ struct wpa_params {
char *conf_p2p_dev;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ /**
+ * match_ifaces - Interface descriptions to match
+ */
+ struct wpa_interface *match_ifaces;
+
+ /**
+ * match_iface_count - Number of defined matching interfaces
+ */
+ int match_iface_count;
+#endif /* CONFIG_MATCH_IFACE */
};
struct p2p_srv_bonjour {
@@ -253,6 +265,7 @@ struct wpa_global {
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
struct wpas_dbus_priv *dbus;
+ struct wpas_binder_priv *binder;
void **drv_priv;
size_t drv_count;
struct os_time suspend_time;
@@ -278,6 +291,7 @@ struct wpa_global {
unsigned int p2p_24ghz_social_channels:1;
unsigned int pending_p2ps_group:1;
unsigned int pending_group_iface_for_p2ps:1;
+ unsigned int pending_p2ps_group_freq;
#ifdef CONFIG_WIFI_DISPLAY
int wifi_display;
@@ -300,10 +314,14 @@ struct wpa_radio {
char name[16]; /* from driver_ops get_radio_name() or empty if not
* available */
unsigned int external_scan_running:1;
+ unsigned int num_active_works;
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
struct dl_list work; /* struct wpa_radio_work::list entries */
};
+#define MAX_ACTIVE_WORKS 2
+
+
/**
* struct wpa_radio_work - Radio work item
*/
@@ -316,6 +334,7 @@ struct wpa_radio_work {
void *ctx;
unsigned int started:1;
struct os_reltime time;
+ unsigned int bands;
};
int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
@@ -347,6 +366,9 @@ struct wpa_external_work {
unsigned int timeout;
};
+enum wpa_radio_work_band wpas_freq_to_band(int freq);
+unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs);
+
/**
* offchannel_send_action_result - Result of offchannel send Action frame
*/
@@ -371,11 +393,6 @@ struct wps_ap_info {
u8 uuid[WPS_UUID_LEN];
};
-struct wpa_ssid_value {
- u8 ssid[SSID_MAX_LEN];
- size_t ssid_len;
-};
-
#define WPA_FREQ_USED_BY_INFRA_STATION BIT(0)
#define WPA_FREQ_USED_BY_P2P_CLIENT BIT(1)
@@ -414,6 +431,21 @@ enum wpa_supplicant_test_failure {
WPAS_TEST_FAILURE_SCAN_TRIGGER,
};
+struct icon_entry {
+ struct dl_list list;
+ u8 bssid[ETH_ALEN];
+ u8 dialog_token;
+ char *file_name;
+ u8 *image;
+ size_t image_len;
+};
+
+struct wpa_bss_tmp_disallowed {
+ struct dl_list list;
+ u8 bssid[ETH_ALEN];
+ struct os_reltime disallowed_until;
+};
+
/**
* struct wpa_supplicant - Internal data for wpa_supplicant interface
*
@@ -427,12 +459,16 @@ struct wpa_supplicant {
struct wpa_radio *radio; /* shared radio context */
struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */
struct wpa_supplicant *parent;
+ struct wpa_supplicant *p2pdev;
struct wpa_supplicant *next;
struct l2_packet_data *l2;
struct l2_packet_data *l2_br;
unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
+#ifdef CONFIG_MATCH_IFACE
+ int matched;
+#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_CTRL_IFACE_DBUS
char *dbus_path;
#endif /* CONFIG_CTRL_IFACE_DBUS */
@@ -443,6 +479,9 @@ struct wpa_supplicant {
char *preq_notify_peer;
#endif /* CONFIG_AP */
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+#ifdef CONFIG_CTRL_IFACE_BINDER
+ const void *binder_object_key;
+#endif /* CONFIG_CTRL_IFACE_BINDER */
char bridge_ifname[16];
char *confname;
@@ -455,7 +494,8 @@ struct wpa_supplicant {
u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
* field contains the target BSSID. */
int reassociate; /* reassociation requested */
- int reassoc_same_bss; /* reassociating to the same bss */
+ unsigned int reassoc_same_bss:1; /* reassociating to the same BSS */
+ unsigned int reassoc_same_ess:1; /* reassociating to the same ESS */
int disconnected; /* all connections disabled; i.e., do no reassociate
* before this has been cleared */
struct wpa_ssid *current_ssid;
@@ -500,9 +540,10 @@ struct wpa_supplicant {
struct wpa_ssid *prev_sched_ssid; /* last SSID used in sched scan */
int sched_scan_timeout;
- int sched_scan_interval;
int first_sched_scan;
int sched_scan_timed_out;
+ struct sched_scan_plan *sched_scan_plans;
+ size_t sched_scan_plans_num;
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
@@ -533,6 +574,7 @@ struct wpa_supplicant {
struct wpa_radio_work *scan_work;
int scanning;
int sched_scanning;
+ unsigned int sched_scan_stop_req:1;
int new_connection;
int eapol_received; /* number of EAPOL packets received after the
@@ -613,6 +655,7 @@ struct wpa_supplicant {
#define MAX_SCAN_ID 16
int scan_id[MAX_SCAN_ID];
unsigned int scan_id_count;
+ u8 next_scan_bssid[ETH_ALEN];
struct wpa_ssid_value *ssids_from_scan_req;
unsigned int num_ssids_from_scan_req;
@@ -634,6 +677,9 @@ struct wpa_supplicant {
int max_scan_ssids;
int max_sched_scan_ssids;
+ unsigned int max_sched_scan_plans;
+ unsigned int max_sched_scan_plan_interval;
+ unsigned int max_sched_scan_plan_iterations;
int sched_scan_supported;
unsigned int max_match_sets;
unsigned int max_remain_on_chan;
@@ -723,7 +769,7 @@ struct wpa_supplicant {
int mesh_if_idx;
unsigned int mesh_if_created:1;
unsigned int mesh_ht_enabled:1;
- int mesh_auth_block_duration; /* sec */
+ unsigned int mesh_vht_enabled:1;
#endif /* CONFIG_MESH */
unsigned int off_channel_freq;
@@ -845,6 +891,10 @@ struct wpa_supplicant {
int *p2p_group_common_freqs;
unsigned int p2p_group_common_freqs_num;
u8 p2ps_join_addr[ETH_ALEN];
+
+ unsigned int p2p_go_max_oper_chwidth;
+ unsigned int p2p_go_vht_center_freq2;
+ int p2p_lo_started;
#endif /* CONFIG_P2P */
struct wpa_ssid *bgscan_ssid;
@@ -886,6 +936,7 @@ struct wpa_supplicant {
unsigned int fetch_osu_icon_in_progress:1;
struct wpa_bss *interworking_gas_bss;
unsigned int osu_icon_id;
+ struct dl_list icon_head; /* struct icon_entry */
struct osu_provider *osu_prov;
size_t osu_prov_count;
struct os_reltime osu_icon_fetch_start;
@@ -915,6 +966,9 @@ struct wpa_supplicant {
/* WLAN_REASON_* reason codes. Negative if locally generated. */
int disconnect_reason;
+ /* WLAN_STATUS_* status codes from (Re)Association Response frame. */
+ u16 assoc_status_code;
+
struct ext_password_data *ext_pw;
struct wpabuf *last_gas_resp, *prev_gas_resp;
@@ -970,6 +1024,10 @@ struct wpa_supplicant {
struct l2_packet_data *l2_test;
unsigned int extra_roc_dur;
enum wpa_supplicant_test_failure test_failure;
+ unsigned int reject_btm_req_reason;
+ unsigned int p2p_go_csa_on_inv:1;
+ unsigned int ignore_auth_resp:1;
+ unsigned int ignore_assoc_disallow:1;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -986,6 +1044,31 @@ struct wpa_supplicant {
const struct wpabuf *fst_ies;
struct wpabuf *received_mb_ies;
#endif /* CONFIG_FST */
+
+#ifdef CONFIG_MBO
+ /* Multiband operation non-preferred channel */
+ struct wpa_mbo_non_pref_channel {
+ enum mbo_non_pref_chan_reason reason;
+ u8 oper_class;
+ u8 chan;
+ u8 preference;
+ } *non_pref_chan;
+ size_t non_pref_chan_num;
+ u8 mbo_wnm_token;
+#endif /* CONFIG_MBO */
+
+ /*
+ * This should be under CONFIG_MBO, but it is left out to allow using
+ * the bss_temp_disallowed list for other purposes as well.
+ */
+ struct dl_list bss_tmp_disallowed;
+
+ /*
+ * Content of a measurement report element with type 8 (LCI),
+ * own location.
+ */
+ struct wpabuf *lci;
+ struct os_reltime lci_time;
};
@@ -1027,6 +1110,8 @@ void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s);
void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
int reason_code);
+struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
@@ -1051,6 +1136,8 @@ void free_hw_features(struct wpa_supplicant *wpa_s);
void wpa_show_license(void);
+struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
+ const char *ifname);
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
struct wpa_interface *iface,
struct wpa_supplicant *parent);
@@ -1080,6 +1167,7 @@ int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid);
int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
size_t ssid_len);
void wpas_request_connection(struct wpa_supplicant *wpa_s);
+void wpas_request_disconnection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
@@ -1089,15 +1177,37 @@ void wpas_rrm_reset(struct wpa_supplicant *wpa_s);
void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
const u8 *report, size_t report_len);
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
+ const struct wpa_ssid_value *ssid,
+ int lci, int civic,
void (*cb)(void *ctx,
struct wpabuf *neighbor_rep),
void *cb_ctx);
+void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *frame, size_t len);
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
const u8 *src,
const u8 *frame, size_t len,
int rssi);
+
+/* MBO functions */
+int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len);
+const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr);
+int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
+ const char *non_pref_chan);
+void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie);
+int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
+ size_t len);
+void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *ie,
+ size_t len);
+size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
+ size_t len,
+ enum mbo_transition_reject_reason reason);
+void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa);
+struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
+
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
* @wpa_s: Pointer to wpa_supplicant data
@@ -1159,6 +1269,12 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);
+void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s);
+struct wpa_supplicant * wpas_vendor_elem(struct wpa_supplicant *wpa_s,
+ enum wpa_vendor_elem_frame frame);
+int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
+ const u8 *elem, size_t len);
+
#ifdef CONFIG_FST
struct fst_wpa_obj;
@@ -1168,4 +1284,18 @@ void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_FST */
+int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd);
+
+struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
+ u16 num_modes, enum hostapd_hw_mode mode);
+
+void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ unsigned int sec);
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+
+struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
+ int i, struct wpa_bss *bss,
+ struct wpa_ssid *group,
+ int only_first_ssid);
+
#endif /* WPA_SUPPLICANT_I_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c b/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c
index 7ce05ddb..158cbb07 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c
@@ -741,6 +741,8 @@ enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
return WPA_CTRL_REQ_SIM;
else if (os_strcmp(field, "PSK_PASSPHRASE") == 0)
return WPA_CTRL_REQ_PSK_PASSPHRASE;
+ else if (os_strcmp(field, "EXT_CERT_CHECK") == 0)
+ return WPA_CTRL_REQ_EXT_CERT_CHECK;
return WPA_CTRL_REQ_UNKNOWN;
}
@@ -784,6 +786,10 @@ const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
*txt = "PSK or passphrase";
ret = "PSK_PASSPHRASE";
break;
+ case WPA_CTRL_REQ_EXT_CERT_CHECK:
+ *txt = "External server certificate validation";
+ ret = "EXT_CERT_CHECK";
+ break;
default:
break;
}
@@ -839,6 +845,8 @@ static void wpa_supplicant_eap_param_needed(void *ctx,
if (ssid == NULL)
return;
+ if (field == WPA_CTRL_REQ_EXT_CERT_CHECK)
+ ssid->eap.pending_ext_cert_check = PENDING_CHECK;
wpas_notify_network_request(wpa_s, ssid, field, default_txt);
field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
@@ -1015,7 +1023,6 @@ static void wpa_supplicant_set_rekey_offload(void *ctx,
wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr);
}
-#endif /* CONFIG_NO_WPA */
static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
@@ -1030,6 +1037,7 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
else
return 0;
}
+#endif /* CONFIG_NO_WPA */
int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
@@ -1126,6 +1134,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
}
}
#endif /* CONFIG_P2P */
+ conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation;
}
wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c
index b3c061b3..39440b36 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c
@@ -585,8 +585,8 @@ static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
m2d->dev_password_id, m2d->config_error);
wpas_notify_wps_event_m2d(wpa_s, m2d);
#ifdef CONFIG_P2P
- if (wpa_s->parent && wpa_s->parent != wpa_s) {
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s) {
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_M2D
"dev_password_id=%d config_error=%d",
m2d->dev_password_id, m2d->config_error);
}
@@ -619,8 +619,8 @@ static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
fail->msg, fail->config_error, fail->error_indication,
wps_ei_str(fail->error_indication));
- if (wpa_s->parent && wpa_s->parent != wpa_s)
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s)
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
"msg=%d config_error=%d reason=%d (%s)",
fail->msg, fail->config_error,
fail->error_indication,
@@ -629,8 +629,8 @@ static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO,
WPS_EVENT_FAIL "msg=%d config_error=%d",
fail->msg, fail->config_error);
- if (wpa_s->parent && wpa_s->parent != wpa_s)
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s)
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
"msg=%d config_error=%d",
fail->msg, fail->config_error);
}
@@ -685,6 +685,13 @@ static void wpas_wps_reenable_networks_cb(void *eloop_ctx, void *timeout_ctx)
}
+int wpas_wps_reenable_networks_pending(struct wpa_supplicant *wpa_s)
+{
+ return eloop_is_timeout_registered(wpas_wps_reenable_networks_cb,
+ wpa_s, NULL);
+}
+
+
static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
{
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
@@ -1137,6 +1144,13 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
return -1;
ssid->temporary = 1;
ssid->p2p_group = p2p_group;
+ /*
+ * When starting a regular WPS process (not P2P group formation)
+ * the registrar/final station can be either AP or PCP
+ * so use a "don't care" value for the pbss flag.
+ */
+ if (!p2p_group)
+ ssid->pbss = 2;
#ifdef CONFIG_P2P
if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
@@ -1144,6 +1158,10 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
ssid->ssid_len = wpa_s->go_params->ssid_len;
os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
ssid->ssid_len);
+ if (wpa_s->go_params->freq > 56160) {
+ /* P2P in 60 GHz uses PBSS */
+ ssid->pbss = 1;
+ }
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
"SSID", ssid->ssid, ssid->ssid_len);
}
@@ -1188,6 +1206,13 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
}
ssid->temporary = 1;
ssid->p2p_group = p2p_group;
+ /*
+ * When starting a regular WPS process (not P2P group formation)
+ * the registrar/final station can be either AP or PCP
+ * so use a "don't care" value for the pbss flag.
+ */
+ if (!p2p_group)
+ ssid->pbss = 2;
if (ssid_val) {
ssid->ssid = os_malloc(ssid_len);
if (ssid->ssid) {
@@ -1211,6 +1236,10 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
ssid->ssid_len = wpa_s->go_params->ssid_len;
os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
ssid->ssid_len);
+ if (wpa_s->go_params->freq > 56160) {
+ /* P2P in 60 GHz uses PBSS */
+ ssid->pbss = 1;
+ }
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
"SSID", ssid->ssid, ssid->ssid_len);
}
@@ -1223,7 +1252,10 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
dev_pw_id, hash);
} else {
- rpin = wps_generate_pin();
+ if (wps_generate_pin(&rpin) < 0) {
+ wpa_printf(MSG_DEBUG, "WPS: Could not generate PIN");
+ return -1;
+ }
os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
rpin, dev_pw_id, hash);
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h
index 3c25ca86..c8fe47e3 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h
@@ -85,6 +85,7 @@ int wpas_er_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpas_wps_reenable_networks_pending(struct wpa_supplicant *wpa_s);
#else /* CONFIG_WPS */
@@ -147,6 +148,12 @@ static inline void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s,
{
}
+static inline int
+wpas_wps_reenable_networks_pending(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+
#endif /* CONFIG_WPS */
#endif /* WPS_SUPPLICANT_H */
diff --git a/freebsd/crypto/openssl/crypto/asn1/a_bool.c b/freebsd/crypto/openssl/crypto/asn1/a_bool.c
index 39aef1c2..d0920c3e 100644
--- a/freebsd/crypto/openssl/crypto/asn1/a_bool.c
+++ b/freebsd/crypto/openssl/crypto/asn1/a_bool.c
@@ -65,17 +65,31 @@
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
{
int r;
- unsigned char *p;
+ unsigned char *p, *allocated = NULL;
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
if (pp == NULL)
return (r);
- p = *pp;
+
+ if (*pp == NULL) {
+ if ((p = allocated = OPENSSL_malloc(r)) == NULL) {
+ ASN1err(ASN1_F_I2D_ASN1_BOOLEAN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ p = *pp;
+ }
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
- *(p++) = (unsigned char)a;
- *pp = p;
- return (r);
+ *p = (unsigned char)a;
+
+
+ /*
+ * If a new buffer was allocated, just return it back.
+ * If not, return the incremented buffer pointer.
+ */
+ *pp = allocated != NULL ? allocated : p + 1;
+ return r;
}
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
diff --git a/freebsd/crypto/openssl/crypto/asn1/a_object.c b/freebsd/crypto/openssl/crypto/asn1/a_object.c
index 069b1457..0e30de2f 100644
--- a/freebsd/crypto/openssl/crypto/asn1/a_object.c
+++ b/freebsd/crypto/openssl/crypto/asn1/a_object.c
@@ -68,7 +68,7 @@
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
{
- unsigned char *p;
+ unsigned char *p, *allocated = NULL;
int objsize;
if ((a == NULL) || (a->data == NULL))
@@ -78,13 +78,24 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
if (pp == NULL || objsize == -1)
return objsize;
- p = *pp;
+ if (*pp == NULL) {
+ if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
+ ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ p = *pp;
+ }
+
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
memcpy(p, a->data, a->length);
- p += a->length;
- *pp = p;
- return (objsize);
+ /*
+ * If a new buffer was allocated, just return it back.
+ * If not, return the incremented buffer pointer.
+ */
+ *pp = allocated != NULL ? allocated : p + a->length;
+ return objsize;
}
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
diff --git a/freebsd/crypto/openssl/crypto/asn1/a_strex.c b/freebsd/crypto/openssl/crypto/asn1/a_strex.c
index 8521cb39..031303c3 100644
--- a/freebsd/crypto/openssl/crypto/asn1/a_strex.c
+++ b/freebsd/crypto/openssl/crypto/asn1/a_strex.c
@@ -6,7 +6,7 @@
* 2000.
*/
/* ====================================================================
- * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2000-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -196,18 +196,38 @@ static int do_buf(unsigned char *buf, int buflen,
int type, unsigned char flags, char *quotes, char_io *io_ch,
void *arg)
{
- int i, outlen, len;
+ int i, outlen, len, charwidth;
unsigned char orflags, *p, *q;
unsigned long c;
p = buf;
q = buf + buflen;
outlen = 0;
+ charwidth = type & BUF_TYPE_WIDTH_MASK;
+
+ switch (charwidth) {
+ case 4:
+ if (buflen & 3) {
+ ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+ return -1;
+ }
+ break;
+ case 2:
+ if (buflen & 1) {
+ ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+
while (p != q) {
if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
orflags = CHARTYPE_FIRST_ESC_2253;
else
orflags = 0;
- switch (type & BUF_TYPE_WIDTH_MASK) {
+
+ switch (charwidth) {
case 4:
c = ((unsigned long)*p++) << 24;
c |= ((unsigned long)*p++) << 16;
@@ -228,6 +248,7 @@ static int do_buf(unsigned char *buf, int buflen,
i = UTF8_getc(p, buflen, &c);
if (i < 0)
return -1; /* Invalid UTF8String */
+ buflen -= i;
p += i;
break;
default:
diff --git a/freebsd/crypto/openssl/crypto/asn1/ameth_lib.c b/freebsd/crypto/openssl/crypto/asn1/ameth_lib.c
index 878138a1..737078f3 100644
--- a/freebsd/crypto/openssl/crypto/asn1/ameth_lib.c
+++ b/freebsd/crypto/openssl/crypto/asn1/ameth_lib.c
@@ -5,7 +5,7 @@
* 2006.
*/
/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -307,6 +307,18 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
} else
ameth->info = NULL;
+ /*
+ * One of the following must be true:
+ *
+ * pem_str == NULL AND ASN1_PKEY_ALIAS is set
+ * pem_str != NULL AND ASN1_PKEY_ALIAS is clear
+ *
+ * Anything else is an error and may lead to a corrupt ASN1 method table
+ */
+ if (!((pem_str == NULL && (flags & ASN1_PKEY_ALIAS) != 0)
+ || (pem_str != NULL && (flags & ASN1_PKEY_ALIAS) == 0)))
+ goto err;
+
if (pem_str) {
ameth->pem_str = BUF_strdup(pem_str);
if (!ameth->pem_str)
diff --git a/freebsd/crypto/openssl/crypto/asn1/asn1.h b/freebsd/crypto/openssl/crypto/asn1/asn1.h
index 35a2b2aa..36e79d5e 100644
--- a/freebsd/crypto/openssl/crypto/asn1/asn1.h
+++ b/freebsd/crypto/openssl/crypto/asn1/asn1.h
@@ -1164,6 +1164,7 @@ int SMIME_text(BIO *in, BIO *out);
* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
*/
+
void ERR_load_ASN1_strings(void);
/* Error codes for the ASN1 functions. */
@@ -1264,7 +1265,10 @@ void ERR_load_ASN1_strings(void);
# define ASN1_F_D2I_X509 156
# define ASN1_F_D2I_X509_CINF 157
# define ASN1_F_D2I_X509_PKEY 159
+# define ASN1_F_DO_BUF 221
# define ASN1_F_I2D_ASN1_BIO_STREAM 211
+# define ASN1_F_I2D_ASN1_BOOLEAN 223
+# define ASN1_F_I2D_ASN1_OBJECT 222
# define ASN1_F_I2D_ASN1_SET 188
# define ASN1_F_I2D_ASN1_TIME 160
# define ASN1_F_I2D_DSA_PUBKEY 161
@@ -1414,7 +1418,7 @@ void ERR_load_ASN1_strings(void);
# define ASN1_R_WRONG_TAG 168
# define ASN1_R_WRONG_TYPE 169
-#ifdef __cplusplus
+# ifdef __cplusplus
}
-#endif
+# endif
#endif
diff --git a/freebsd/crypto/openssl/crypto/asn1/asn1_err.c b/freebsd/crypto/openssl/crypto/asn1/asn1_err.c
index 2c343382..197005ac 100644
--- a/freebsd/crypto/openssl/crypto/asn1/asn1_err.c
+++ b/freebsd/crypto/openssl/crypto/asn1/asn1_err.c
@@ -168,7 +168,10 @@ static ERR_STRING_DATA ASN1_str_functs[] = {
{ERR_FUNC(ASN1_F_D2I_X509), "D2I_X509"},
{ERR_FUNC(ASN1_F_D2I_X509_CINF), "D2I_X509_CINF"},
{ERR_FUNC(ASN1_F_D2I_X509_PKEY), "d2i_X509_PKEY"},
+ {ERR_FUNC(ASN1_F_DO_BUF), "DO_BUF"},
{ERR_FUNC(ASN1_F_I2D_ASN1_BIO_STREAM), "i2d_ASN1_bio_stream"},
+ {ERR_FUNC(ASN1_F_I2D_ASN1_BOOLEAN), "i2d_ASN1_BOOLEAN"},
+ {ERR_FUNC(ASN1_F_I2D_ASN1_OBJECT), "i2d_ASN1_OBJECT"},
{ERR_FUNC(ASN1_F_I2D_ASN1_SET), "i2d_ASN1_SET"},
{ERR_FUNC(ASN1_F_I2D_ASN1_TIME), "I2D_ASN1_TIME"},
{ERR_FUNC(ASN1_F_I2D_DSA_PUBKEY), "i2d_DSA_PUBKEY"},
diff --git a/freebsd/crypto/openssl/crypto/asn1/tasn_enc.c b/freebsd/crypto/openssl/crypto/asn1/tasn_enc.c
index fa257559..6c7980ea 100644
--- a/freebsd/crypto/openssl/crypto/asn1/tasn_enc.c
+++ b/freebsd/crypto/openssl/crypto/asn1/tasn_enc.c
@@ -6,7 +6,7 @@
* 2000.
*/
/* ====================================================================
- * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2000-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -590,6 +590,8 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
otmp = (ASN1_OBJECT *)*pval;
cont = otmp->data;
len = otmp->length;
+ if (cont == NULL || len == 0)
+ return -1;
break;
case V_ASN1_NULL:
diff --git a/freebsd/crypto/openssl/crypto/bio/bss_log.c b/freebsd/crypto/openssl/crypto/bio/bss_log.c
index a73302e1..d7cb573c 100644
--- a/freebsd/crypto/openssl/crypto/bio/bss_log.c
+++ b/freebsd/crypto/openssl/crypto/bio/bss_log.c
@@ -2,7 +2,7 @@
/* crypto/bio/bss_log.c */
/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -244,7 +244,7 @@ static int MS_CALLBACK slg_write(BIO *b, const char *in, int inl)
if ((buf = (char *)OPENSSL_malloc(inl + 1)) == NULL) {
return (0);
}
- strncpy(buf, in, inl);
+ memcpy(buf, in, inl);
buf[inl] = '\0';
i = 0;
diff --git a/freebsd/crypto/openssl/crypto/bio/bss_mem.c b/freebsd/crypto/openssl/crypto/bio/bss_mem.c
index 4326e117..03404a5b 100644
--- a/freebsd/crypto/openssl/crypto/bio/bss_mem.c
+++ b/freebsd/crypto/openssl/crypto/bio/bss_mem.c
@@ -190,6 +190,8 @@ static int mem_write(BIO *b, const char *in, int inl)
}
BIO_clear_retry_flags(b);
+ if (inl == 0)
+ return 0;
blen = bm->length;
if (BUF_MEM_grow_clean(bm, blen + inl) != (blen + inl))
goto end;
diff --git a/freebsd/crypto/openssl/crypto/bn/bn.h b/freebsd/crypto/openssl/crypto/bn/bn.h
index 633d1b1f..d4b9f27b 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn.h
+++ b/freebsd/crypto/openssl/crypto/bn/bn.h
@@ -56,7 +56,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -375,25 +375,76 @@ int BN_GENCB_call(BN_GENCB *cb, int a, int b);
* on the size of the number */
/*
- * number of Miller-Rabin iterations for an error rate of less than 2^-80 for
- * random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook of
- * Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
- * original paper: Damgaard, Landrock, Pomerance: Average case error
- * estimates for the strong probable prime test. -- Math. Comp. 61 (1993)
- * 177-194)
+ * BN_prime_checks_for_size() returns the number of Miller-Rabin iterations
+ * that will be done for checking that a random number is probably prime. The
+ * error rate for accepting a composite number as prime depends on the size of
+ * the prime |b|. The error rates used are for calculating an RSA key with 2 primes,
+ * and so the level is what you would expect for a key of double the size of the
+ * prime.
+ *
+ * This table is generated using the algorithm of FIPS PUB 186-4
+ * Digital Signature Standard (DSS), section F.1, page 117.
+ * (https://dx.doi.org/10.6028/NIST.FIPS.186-4)
+ *
+ * The following magma script was used to generate the output:
+ * securitybits:=125;
+ * k:=1024;
+ * for t:=1 to 65 do
+ * for M:=3 to Floor(2*Sqrt(k-1)-1) do
+ * S:=0;
+ * // Sum over m
+ * for m:=3 to M do
+ * s:=0;
+ * // Sum over j
+ * for j:=2 to m do
+ * s+:=(RealField(32)!2)^-(j+(k-1)/j);
+ * end for;
+ * S+:=2^(m-(m-1)*t)*s;
+ * end for;
+ * A:=2^(k-2-M*t);
+ * B:=8*(Pi(RealField(32))^2-6)/3*2^(k-2)*S;
+ * pkt:=2.00743*Log(2)*k*2^-k*(A+B);
+ * seclevel:=Floor(-Log(2,pkt));
+ * if seclevel ge securitybits then
+ * printf "k: %5o, security: %o bits (t: %o, M: %o)\n",k,seclevel,t,M;
+ * break;
+ * end if;
+ * end for;
+ * if seclevel ge securitybits then break; end if;
+ * end for;
+ *
+ * It can be run online at:
+ * http://magma.maths.usyd.edu.au/calc
+ *
+ * And will output:
+ * k: 1024, security: 129 bits (t: 6, M: 23)
+ *
+ * k is the number of bits of the prime, securitybits is the level we want to
+ * reach.
+ *
+ * prime length | RSA key size | # MR tests | security level
+ * -------------+--------------|------------+---------------
+ * (b) >= 6394 | >= 12788 | 3 | 256 bit
+ * (b) >= 3747 | >= 7494 | 3 | 192 bit
+ * (b) >= 1345 | >= 2690 | 4 | 128 bit
+ * (b) >= 1080 | >= 2160 | 5 | 128 bit
+ * (b) >= 852 | >= 1704 | 5 | 112 bit
+ * (b) >= 476 | >= 952 | 5 | 80 bit
+ * (b) >= 400 | >= 800 | 6 | 80 bit
+ * (b) >= 347 | >= 694 | 7 | 80 bit
+ * (b) >= 308 | >= 616 | 8 | 80 bit
+ * (b) >= 55 | >= 110 | 27 | 64 bit
+ * (b) >= 6 | >= 12 | 34 | 64 bit
*/
-# define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \
- (b) >= 850 ? 3 : \
- (b) >= 650 ? 4 : \
- (b) >= 550 ? 5 : \
- (b) >= 450 ? 6 : \
- (b) >= 400 ? 7 : \
- (b) >= 350 ? 8 : \
- (b) >= 300 ? 9 : \
- (b) >= 250 ? 12 : \
- (b) >= 200 ? 15 : \
- (b) >= 150 ? 18 : \
- /* b >= 100 */ 27)
+
+# define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \
+ (b) >= 1345 ? 4 : \
+ (b) >= 476 ? 5 : \
+ (b) >= 400 ? 6 : \
+ (b) >= 347 ? 7 : \
+ (b) >= 308 ? 8 : \
+ (b) >= 55 ? 27 : \
+ /* b >= 6 */ 34)
# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
@@ -773,6 +824,16 @@ BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */
/* We only need assert() when debugging */
# include <assert.h>
+/*
+ * The new BN_FLG_FIXED_TOP flag marks vectors that were not treated with
+ * bn_correct_top, in other words such vectors are permitted to have zeros
+ * in most significant limbs. Such vectors are used internally to achieve
+ * execution time invariance for critical operations with private keys.
+ * It's BN_DEBUG-only flag, because user application is not supposed to
+ * observe it anyway. Moreover, optimizing compiler would actually remove
+ * all operations manipulating the bit in question in non-BN_DEBUG build.
+ */
+# define BN_FLG_FIXED_TOP 0x10000
# ifdef BN_DEBUG_RAND
/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
# ifndef RAND_pseudo_bytes
@@ -805,8 +866,10 @@ int RAND_pseudo_bytes(unsigned char *buf, int num);
do { \
const BIGNUM *_bnum2 = (a); \
if (_bnum2 != NULL) { \
- assert((_bnum2->top == 0) || \
- (_bnum2->d[_bnum2->top - 1] != 0)); \
+ int _top = _bnum2->top; \
+ assert((_top == 0) || \
+ (_bnum2->flags & BN_FLG_FIXED_TOP) || \
+ (_bnum2->d[_top - 1] != 0)); \
bn_pollute(_bnum2); \
} \
} while(0)
@@ -824,6 +887,7 @@ int RAND_pseudo_bytes(unsigned char *buf, int num);
# else /* !BN_DEBUG */
+# define BN_FLG_FIXED_TOP 0
# define bn_pollute(a)
# define bn_check_top(a)
# define bn_fix_top(a) bn_correct_top(a)
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_div.c b/freebsd/crypto/openssl/crypto/bn/bn_div.c
index d85ac669..2888becf 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_div.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_div.c
@@ -292,6 +292,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
wnum.neg = 0;
wnum.d = &(snum->d[loop]);
wnum.top = div_n;
+ wnum.flags = BN_FLG_STATIC_DATA;
/*
* only needed when BN_ucmp messes up the values between top and max
*/
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_exp.c b/freebsd/crypto/openssl/crypto/bn/bn_exp.c
index 50374334..423285dc 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_exp.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_exp.c
@@ -292,8 +292,8 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
bits = BN_num_bits(p);
if (bits == 0) {
- /* x**0 mod 1 is still zero. */
- if (BN_is_one(m)) {
+ /* x**0 mod 1, or x**0 mod -1 is still zero. */
+ if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(r);
} else {
@@ -434,8 +434,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
bits = BN_num_bits(p);
if (bits == 0) {
- /* x**0 mod 1 is still zero. */
- if (BN_is_one(m)) {
+ /* x**0 mod 1, or x**0 mod -1 is still zero. */
+ if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(rr);
} else {
@@ -475,17 +475,17 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
ret = 1;
goto err;
}
- if (!BN_to_montgomery(val[0], aa, mont, ctx))
+ if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))
goto err; /* 1 */
window = BN_window_bits_for_exponent_size(bits);
if (window > 1) {
- if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx))
+ if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))
goto err; /* 2 */
j = 1 << (window - 1);
for (i = 1; i < j; i++) {
if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
- !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx))
+ !bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx))
goto err;
}
}
@@ -507,19 +507,15 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
for (i = 1; i < j; i++)
r->d[i] = (~m->d[i]) & BN_MASK2;
r->top = j;
- /*
- * Upper words will be zero if the corresponding words of 'm' were
- * 0xfff[...], so decrement r->top accordingly.
- */
- bn_correct_top(r);
+ r->flags |= BN_FLG_FIXED_TOP;
} else
#endif
- if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))
+ if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))
goto err;
for (;;) {
if (BN_is_bit_set(p, wstart) == 0) {
if (!start) {
- if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
+ if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
goto err;
}
if (wstart == 0)
@@ -550,12 +546,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* add the 'bytes above' */
if (!start)
for (i = 0; i < j; i++) {
- if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
+ if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
- if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx))
+ if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx))
goto err;
/* move the 'window' down further */
@@ -565,6 +561,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
if (wstart < 0)
break;
}
+ /*
+ * Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
+ * removes padding [if any] and makes return value suitable for public
+ * API consumer.
+ */
#if defined(SPARC_T4_MONT)
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
j = mont->N.top; /* borrow j */
@@ -683,7 +684,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
}
b->top = top;
- bn_correct_top(b);
+ b->flags |= BN_FLG_FIXED_TOP;
return 1;
}
@@ -735,8 +736,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
*/
bits = p->top * BN_BITS2;
if (bits == 0) {
- /* x**0 mod 1 is still zero. */
- if (BN_is_one(m)) {
+ /* x**0 mod 1, or x**0 mod -1 is still zero. */
+ if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(rr);
} else {
@@ -854,16 +855,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
tmp.top = top;
} else
#endif
- if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))
+ if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))
goto err;
/* prepare a^1 in Montgomery domain */
if (a->neg || BN_ucmp(a, m) >= 0) {
if (!BN_mod(&am, a, m, ctx))
goto err;
- if (!BN_to_montgomery(&am, &am, mont, ctx))
+ if (!bn_to_mont_fixed_top(&am, &am, mont, ctx))
goto err;
- } else if (!BN_to_montgomery(&am, a, mont, ctx))
+ } else if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
goto err;
#if defined(SPARC_T4_MONT)
@@ -1130,14 +1131,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
* performance advantage of sqr over mul).
*/
if (window > 1) {
- if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx))
+ if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx))
goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,
window))
goto err;
for (i = 3; i < numPowers; i++) {
/* Calculate a^i = a^(i-1) * a */
- if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx))
+ if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx))
goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,
window))
@@ -1161,7 +1162,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* Scan the window, squaring the result as we go */
for (i = 0; i < window; i++, bits--) {
- if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx))
+ if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx))
goto err;
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
}
@@ -1174,12 +1175,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
goto err;
/* Multiply the result into the intermediate result */
- if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx))
+ if (!bn_mul_mont_fixed_top(&tmp, &tmp, &am, mont, ctx))
goto err;
}
}
- /* Convert the final result from montgomery to standard format */
+ /*
+ * Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
+ * removes padding [if any] and makes return value suitable for public
+ * API consumer.
+ */
#if defined(SPARC_T4_MONT)
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
am.d[0] = 1; /* borrow am */
@@ -1249,8 +1254,8 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
bits = BN_num_bits(p);
if (bits == 0) {
- /* x**0 mod 1 is still zero. */
- if (BN_is_one(m)) {
+ /* x**0 mod 1, or x**0 mod -1 is still zero. */
+ if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(rr);
} else {
@@ -1371,9 +1376,9 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
}
bits = BN_num_bits(p);
- if (bits == 0) {
- /* x**0 mod 1 is still zero. */
- if (BN_is_one(m)) {
+ if (bits == 0) {
+ /* x**0 mod 1, or x**0 mod -1 is still zero. */
+ if (BN_abs_is_word(m, 1)) {
ret = 1;
BN_zero(r);
} else {
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_gf2m.c b/freebsd/crypto/openssl/crypto/bn/bn_gf2m.c
index 74726f55..a2b29e3c 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_gf2m.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_gf2m.c
@@ -38,7 +38,7 @@
*/
/* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -105,30 +105,32 @@
*/
# define MAX_ITERATIONS 50
-static const BN_ULONG SQR_tb[16] = { 0, 1, 4, 5, 16, 17, 20, 21,
- 64, 65, 68, 69, 80, 81, 84, 85
-};
+# define SQR_nibble(w) ((((w) & 8) << 3) \
+ | (((w) & 4) << 2) \
+ | (((w) & 2) << 1) \
+ | ((w) & 1))
+
/* Platform-specific macros to accelerate squaring. */
# if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
# define SQR1(w) \
- SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \
- SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \
- SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \
- SQR_tb[(w) >> 36 & 0xF] << 8 | SQR_tb[(w) >> 32 & 0xF]
+ SQR_nibble((w) >> 60) << 56 | SQR_nibble((w) >> 56) << 48 | \
+ SQR_nibble((w) >> 52) << 40 | SQR_nibble((w) >> 48) << 32 | \
+ SQR_nibble((w) >> 44) << 24 | SQR_nibble((w) >> 40) << 16 | \
+ SQR_nibble((w) >> 36) << 8 | SQR_nibble((w) >> 32)
# define SQR0(w) \
- SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \
- SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \
- SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >> 8 & 0xF] << 16 | \
- SQR_tb[(w) >> 4 & 0xF] << 8 | SQR_tb[(w) & 0xF]
+ SQR_nibble((w) >> 28) << 56 | SQR_nibble((w) >> 24) << 48 | \
+ SQR_nibble((w) >> 20) << 40 | SQR_nibble((w) >> 16) << 32 | \
+ SQR_nibble((w) >> 12) << 24 | SQR_nibble((w) >> 8) << 16 | \
+ SQR_nibble((w) >> 4) << 8 | SQR_nibble((w) )
# endif
# ifdef THIRTY_TWO_BIT
# define SQR1(w) \
- SQR_tb[(w) >> 28 & 0xF] << 24 | SQR_tb[(w) >> 24 & 0xF] << 16 | \
- SQR_tb[(w) >> 20 & 0xF] << 8 | SQR_tb[(w) >> 16 & 0xF]
+ SQR_nibble((w) >> 28) << 24 | SQR_nibble((w) >> 24) << 16 | \
+ SQR_nibble((w) >> 20) << 8 | SQR_nibble((w) >> 16)
# define SQR0(w) \
- SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >> 8 & 0xF] << 16 | \
- SQR_tb[(w) >> 4 & 0xF] << 8 | SQR_tb[(w) & 0xF]
+ SQR_nibble((w) >> 12) << 24 | SQR_nibble((w) >> 8) << 16 | \
+ SQR_nibble((w) >> 4) << 8 | SQR_nibble((w) )
# endif
# if !defined(OPENSSL_BN_ASM_GF2m)
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_lcl.h b/freebsd/crypto/openssl/crypto/bn/bn_lcl.h
index 00f4f099..6f7335b7 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_lcl.h
+++ b/freebsd/crypto/openssl/crypto/bn/bn_lcl.h
@@ -56,7 +56,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -113,6 +113,7 @@
# define HEADER_BN_LCL_H
# include <openssl/bn.h>
+# include "bn_int.h"
#ifdef __cplusplus
extern "C" {
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_lib.c b/freebsd/crypto/openssl/crypto/bn/bn_lib.c
index e63f6100..755322ce 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_lib.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_lib.c
@@ -265,8 +265,6 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
const BN_ULONG *B;
int i;
- bn_check_top(b);
-
if (words > (INT_MAX / (4 * BN_BITS2))) {
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
return NULL;
@@ -400,8 +398,6 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, int words)
BIGNUM *bn_expand2(BIGNUM *b, int words)
{
- bn_check_top(b);
-
if (words > b->dmax) {
BN_ULONG *a = bn_expand_internal(b, words);
if (!a)
@@ -435,7 +431,6 @@ BIGNUM *bn_expand2(BIGNUM *b, int words)
assert(A == &(b->d[b->dmax]));
}
#endif
- bn_check_top(b);
return b;
}
@@ -499,12 +494,18 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
memcpy(a->d, b->d, sizeof(b->d[0]) * b->top);
#endif
- a->top = b->top;
a->neg = b->neg;
+ a->top = b->top;
+ a->flags |= b->flags & BN_FLG_FIXED_TOP;
bn_check_top(a);
return (a);
}
+#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \
+ | BN_FLG_CONSTTIME \
+ | BN_FLG_FIXED_TOP))
+#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED))
+
void BN_swap(BIGNUM *a, BIGNUM *b)
{
int flags_old_a, flags_old_b;
@@ -532,10 +533,8 @@ void BN_swap(BIGNUM *a, BIGNUM *b)
b->dmax = tmp_dmax;
b->neg = tmp_neg;
- a->flags =
- (flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA);
- b->flags =
- (flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA);
+ a->flags = FLAGS_STRUCT(flags_old_a) | FLAGS_DATA(flags_old_b);
+ b->flags = FLAGS_STRUCT(flags_old_b) | FLAGS_DATA(flags_old_a);
bn_check_top(a);
bn_check_top(b);
}
@@ -547,6 +546,7 @@ void BN_clear(BIGNUM *a)
OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
a->top = 0;
a->neg = 0;
+ a->flags &= ~BN_FLG_FIXED_TOP;
}
BN_ULONG BN_get_word(const BIGNUM *a)
@@ -567,6 +567,7 @@ int BN_set_word(BIGNUM *a, BN_ULONG w)
a->neg = 0;
a->d[0] = w;
a->top = (w ? 1 : 0);
+ a->flags &= ~BN_FLG_FIXED_TOP;
bn_check_top(a);
return (1);
}
@@ -615,6 +616,41 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
}
/* ignore negative */
+static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
+{
+ int n;
+ size_t i, inc, lasti, j;
+ BN_ULONG l;
+
+ n = BN_num_bytes(a);
+ if (tolen == -1)
+ tolen = n;
+ else if (tolen < n)
+ return -1;
+
+ if (n == 0) {
+ OPENSSL_cleanse(to, tolen);
+ return tolen;
+ }
+
+ lasti = n - 1;
+ for (i = 0, inc = 1, j = tolen; j > 0;) {
+ l = a->d[i / BN_BYTES];
+ to[--j] = (unsigned char)(l >> (8 * (i % BN_BYTES)) & (0 - inc));
+ inc = (i - lasti) >> (8 * sizeof(i) - 1);
+ i += inc; /* stay on top limb */
+ }
+
+ return tolen;
+}
+
+int bn_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
+{
+ if (tolen < 0)
+ return -1;
+ return bn2binpad(a, to, tolen);
+}
+
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
int n, i;
@@ -713,6 +749,7 @@ int BN_set_bit(BIGNUM *a, int n)
for (k = a->top; k < i + 1; k++)
a->d[k] = 0;
a->top = i + 1;
+ a->flags &= ~BN_FLG_FIXED_TOP;
}
a->d[i] |= (((BN_ULONG)1) << j);
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_mod.c b/freebsd/crypto/openssl/crypto/bn/bn_mod.c
index e79d8209..94762168 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_mod.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_mod.c
@@ -6,7 +6,7 @@
* for the OpenSSL project.
*/
/* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -151,18 +151,73 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
/*
* BN_mod_add variant that may be used if both a and b are non-negative and
- * less than m
+ * less than m. The original algorithm was
+ *
+ * if (!BN_uadd(r, a, b))
+ * return 0;
+ * if (BN_ucmp(r, m) >= 0)
+ * return BN_usub(r, r, m);
+ *
+ * which is replaced with addition, subtracting modulus, and conditional
+ * move depending on whether or not subtraction borrowed.
*/
-int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
- const BIGNUM *m)
+int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m)
{
- if (!BN_uadd(r, a, b))
+ size_t i, ai, bi, mtop = m->top;
+ BN_ULONG storage[1024 / BN_BITS2];
+ BN_ULONG carry, temp, mask, *rp, *tp = storage;
+ const BN_ULONG *ap, *bp;
+
+ if (bn_wexpand(r, m->top) == NULL)
return 0;
- if (BN_ucmp(r, m) >= 0)
- return BN_usub(r, r, m);
+
+ if (mtop > sizeof(storage) / sizeof(storage[0])
+ && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL)
+ return 0;
+
+ ap = a->d != NULL ? a->d : tp;
+ bp = b->d != NULL ? b->d : tp;
+
+ for (i = 0, ai = 0, bi = 0, carry = 0; i < mtop;) {
+ mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1));
+ temp = ((ap[ai] & mask) + carry) & BN_MASK2;
+ carry = (temp < carry);
+
+ mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1));
+ tp[i] = ((bp[bi] & mask) + temp) & BN_MASK2;
+ carry += (tp[i] < temp);
+
+ i++;
+ ai += (i - a->dmax) >> (8 * sizeof(i) - 1);
+ bi += (i - b->dmax) >> (8 * sizeof(i) - 1);
+ }
+ rp = r->d;
+ carry -= bn_sub_words(rp, tp, m->d, mtop);
+ for (i = 0; i < mtop; i++) {
+ rp[i] = (carry & tp[i]) | (~carry & rp[i]);
+ ((volatile BN_ULONG *)tp)[i] = 0;
+ }
+ r->top = mtop;
+ r->neg = 0;
+
+ if (tp != storage)
+ OPENSSL_free(tp);
+
return 1;
}
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m)
+{
+ int ret = bn_mod_add_fixed_top(r, a, b, m);
+
+ if (ret)
+ bn_correct_top(r);
+
+ return ret;
+}
+
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx)
{
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_mont.c b/freebsd/crypto/openssl/crypto/bn/bn_mont.c
index d21a9501..7657798a 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_mont.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_mont.c
@@ -125,12 +125,23 @@
#define MONT_WORD /* use the faster word-based algorithm */
#ifdef MONT_WORD
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
+static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
#endif
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mont, BN_CTX *ctx)
{
+ int ret = bn_mul_mont_fixed_top(r, a, b, mont, ctx);
+
+ bn_correct_top(r);
+ bn_check_top(r);
+
+ return ret;
+}
+
+int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ BN_MONT_CTX *mont, BN_CTX *ctx)
+{
BIGNUM *tmp;
int ret = 0;
#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
@@ -142,8 +153,8 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
r->neg = a->neg ^ b->neg;
r->top = num;
- bn_correct_top(r);
- return (1);
+ r->flags |= BN_FLG_FIXED_TOP;
+ return 1;
}
}
#endif
@@ -163,13 +174,12 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
}
/* reduce from aRR to aR */
#ifdef MONT_WORD
- if (!BN_from_montgomery_word(r, tmp, mont))
+ if (!bn_from_montgomery_word(r, tmp, mont))
goto err;
#else
if (!BN_from_montgomery(r, tmp, mont, ctx))
goto err;
#endif
- bn_check_top(r);
ret = 1;
err:
BN_CTX_end(ctx);
@@ -177,7 +187,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
}
#ifdef MONT_WORD
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
+static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
{
BIGNUM *n;
BN_ULONG *ap, *np, *rp, n0, v, carry;
@@ -207,6 +217,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
# endif
r->top = max;
+ r->flags |= BN_FLG_FIXED_TOP;
n0 = mont->n0[0];
/*
@@ -225,6 +236,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
if (bn_wexpand(ret, nl) == NULL)
return (0);
ret->top = nl;
+ ret->flags |= BN_FLG_FIXED_TOP;
ret->neg = r->neg;
rp = ret->d;
@@ -235,20 +247,16 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
*/
ap = &(r->d[nl]);
+ carry -= bn_sub_words(rp, ap, np, nl);
/*
- * |v| is one if |ap| - |np| underflowed or zero if it did not. Note |v|
- * cannot be -1. That would imply the subtraction did not fit in |nl| words,
- * and we know at most one subtraction is needed.
+ * |carry| is -1 if |ap| - |np| underflowed or zero if it did not. Note
+ * |carry| cannot be 1. That would imply the subtraction did not fit in
+ * |nl| words, and we know at most one subtraction is needed.
*/
- v = bn_sub_words(rp, ap, np, nl) - carry;
- v = 0 - v;
for (i = 0; i < nl; i++) {
- rp[i] = (v & ap[i]) | (~v & rp[i]);
+ rp[i] = (carry & ap[i]) | (~carry & rp[i]);
ap[i] = 0;
}
- bn_correct_top(r);
- bn_correct_top(ret);
- bn_check_top(ret);
return (1);
}
@@ -262,8 +270,11 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
BIGNUM *t;
BN_CTX_start(ctx);
- if ((t = BN_CTX_get(ctx)) && BN_copy(t, a))
- retn = BN_from_montgomery_word(ret, t, mont);
+ if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) {
+ retn = bn_from_montgomery_word(ret, t, mont);
+ bn_correct_top(ret);
+ bn_check_top(ret);
+ }
BN_CTX_end(ctx);
#else /* !MONT_WORD */
BIGNUM *t1, *t2;
@@ -301,6 +312,12 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
return (retn);
}
+int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
+ BN_CTX *ctx)
+{
+ return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx);
+}
+
BN_MONT_CTX *BN_MONT_CTX_new(void)
{
BN_MONT_CTX *ret;
@@ -337,7 +354,7 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont)
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
{
- int ret = 0;
+ int i, ret = 0;
BIGNUM *Ri, *R;
if (BN_is_zero(mod))
@@ -468,6 +485,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx))
goto err;
+ for (i = mont->RR.top, ret = mont->N.top; i < ret; i++)
+ mont->RR.d[i] = 0;
+ mont->RR.top = ret;
+ mont->RR.flags |= BN_FLG_FIXED_TOP;
+
ret = 1;
err:
BN_CTX_end(ctx);
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_sqr.c b/freebsd/crypto/openssl/crypto/bn/bn_sqr.c
index 759d5d20..bc52dfd0 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_sqr.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_sqr.c
@@ -137,14 +137,8 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
}
rr->neg = 0;
- /*
- * If the most-significant half of the top word of 'a' is zero, then the
- * square of 'a' will max-1 words.
- */
- if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l))
- rr->top = max - 1;
- else
- rr->top = max;
+ rr->top = max;
+ bn_correct_top(rr);
if (r != rr && BN_copy(r, rr) == NULL)
goto err;
diff --git a/freebsd/crypto/openssl/crypto/bn_int.h b/freebsd/crypto/openssl/crypto/bn_int.h
new file mode 100644
index 00000000..9c42d6f3
--- /dev/null
+++ b/freebsd/crypto/openssl/crypto/bn_int.h
@@ -0,0 +1,15 @@
+/*
+ * Some BIGNUM functions assume most significant limb to be non-zero, which
+ * is customarily arranged by bn_correct_top. Output from below functions
+ * is not processed with bn_correct_top, and for this reason it may not be
+ * returned out of public API. It may only be passed internally into other
+ * functions known to support non-minimal or zero-padded BIGNUMs.
+ */
+int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ BN_MONT_CTX *mont, BN_CTX *ctx);
+int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
+ BN_CTX *ctx);
+int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m);
+
+int bn_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
diff --git a/freebsd/crypto/openssl/crypto/conf/conf_api.c b/freebsd/crypto/openssl/crypto/conf/conf_api.c
index 0ce7b21a..e55c2d54 100644
--- a/freebsd/crypto/openssl/crypto/conf/conf_api.c
+++ b/freebsd/crypto/openssl/crypto/conf/conf_api.c
@@ -292,6 +292,8 @@ CONF_VALUE *_CONF_new_section(CONF *conf, const char *section)
vv = lh_CONF_VALUE_insert(conf->data, v);
OPENSSL_assert(vv == NULL);
+ if (lh_CONF_VALUE_error(conf->data) > 0)
+ goto err;
ok = 1;
err:
if (!ok) {
diff --git a/freebsd/crypto/openssl/crypto/dh/dh_key.c b/freebsd/crypto/openssl/crypto/dh/dh_key.c
index f6e9d20e..eb40d030 100644
--- a/freebsd/crypto/openssl/crypto/dh/dh_key.c
+++ b/freebsd/crypto/openssl/crypto/dh/dh_key.c
@@ -132,10 +132,15 @@ static int generate_key(DH *dh)
int ok = 0;
int generate_new_key = 0;
unsigned l;
- BN_CTX *ctx;
+ BN_CTX *ctx = NULL;
BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
+ if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
+ DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
diff --git a/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c b/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c
index fe5684ce..6456729b 100644
--- a/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c
+++ b/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c
@@ -5,7 +5,7 @@
* 2006.
*/
/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -488,7 +488,7 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
return ret;
}
#endif
- return 1;
+ return 0;
}
const EVP_PKEY_METHOD dh_pkey_meth = {
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa.h b/freebsd/crypto/openssl/crypto/dsa/dsa.h
index 545358fd..3e6984ea 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa.h
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa.h
@@ -249,10 +249,12 @@ int DSAparams_print_fp(FILE *fp, const DSA *x);
int DSA_print_fp(FILE *bp, const DSA *x, int off);
# endif
-# define DSS_prime_checks 50
+# define DSS_prime_checks 64
/*
- * Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of
- * Rabin-Miller
+ * Primality test according to FIPS PUB 186-4, Appendix C.3. Since we only
+ * have one value here we set the number of checks to 64 which is the 128 bit
+ * security level that is the highest level and valid for creating a 3072 bit
+ * DSA key.
*/
# define DSA_is_prime(n, callback, cb_arg) \
BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
@@ -307,6 +309,7 @@ void ERR_load_DSA_strings(void);
# define DSA_F_I2D_DSA_SIG 111
# define DSA_F_OLD_DSA_PRIV_DECODE 122
# define DSA_F_PKEY_DSA_CTRL 120
+# define DSA_F_PKEY_DSA_CTRL_STR 127
# define DSA_F_PKEY_DSA_KEYGEN 121
# define DSA_F_SIG_CB 114
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_err.c b/freebsd/crypto/openssl/crypto/dsa/dsa_err.c
index 7fb155a6..7c2491f4 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_err.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_err.c
@@ -2,7 +2,7 @@
/* crypto/dsa/dsa_err.c */
/* ====================================================================
- * Copyright (c) 1999-2013 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -97,6 +97,7 @@ static ERR_STRING_DATA DSA_str_functs[] = {
{ERR_FUNC(DSA_F_I2D_DSA_SIG), "i2d_DSA_SIG"},
{ERR_FUNC(DSA_F_OLD_DSA_PRIV_DECODE), "OLD_DSA_PRIV_DECODE"},
{ERR_FUNC(DSA_F_PKEY_DSA_CTRL), "PKEY_DSA_CTRL"},
+ {ERR_FUNC(DSA_F_PKEY_DSA_CTRL_STR), "PKEY_DSA_CTRL_STR"},
{ERR_FUNC(DSA_F_PKEY_DSA_KEYGEN), "PKEY_DSA_KEYGEN"},
{ERR_FUNC(DSA_F_SIG_CB), "SIG_CB"},
{0, NULL}
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c b/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c
index cdca6fcc..ca54fb18 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c
@@ -148,9 +148,16 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
/* invalid q size */
return 0;
- if (evpmd == NULL)
- /* use SHA1 as default */
- evpmd = EVP_sha1();
+ if (evpmd == NULL) {
+ if (qsize == SHA_DIGEST_LENGTH)
+ evpmd = EVP_sha1();
+ else if (qsize == SHA224_DIGEST_LENGTH)
+ evpmd = EVP_sha224();
+ else
+ evpmd = EVP_sha256();
+ } else {
+ qsize = EVP_MD_size(evpmd);
+ }
if (bits < 512)
bits = 512;
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c b/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c
index 715511c2..dc6c2c94 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -135,17 +135,13 @@ const DSA_METHOD *DSA_OpenSSL(void)
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
- BIGNUM m;
- BIGNUM xr;
+ BIGNUM *m, *blind, *blindm, *tmp;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int noredo = 0;
- BN_init(&m);
- BN_init(&xr);
-
- if (!dsa->p || !dsa->q || !dsa->g) {
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
reason = DSA_R_MISSING_PARAMETERS;
goto err;
}
@@ -156,6 +152,13 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
+ m = BN_CTX_get(ctx);
+ blind = BN_CTX_get(ctx);
+ blindm = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == NULL)
+ goto err;
+
redo:
if ((dsa->kinv == NULL) || (dsa->r == NULL)) {
if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
@@ -175,20 +178,52 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
* 4.2
*/
dlen = BN_num_bytes(dsa->q);
- if (BN_bin2bn(dgst, dlen, &m) == NULL)
+ if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err;
- /* Compute s = inv(k) (m + xr) mod q */
- if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx))
- goto err; /* s = xr */
- if (!BN_add(s, &xr, &m))
- goto err; /* s = m + xr */
- if (BN_cmp(s, dsa->q) > 0)
- if (!BN_sub(s, s, dsa->q))
+ /*
+ * The normal signature calculation is:
+ *
+ * s := k^-1 * (m + r * priv_key) mod q
+ *
+ * We will blind this to protect against side channel attacks
+ *
+ * s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
+ */
+
+ /* Generate a blinding value */
+ do {
+ if (!BN_rand(blind, BN_num_bits(dsa->q) - 1, -1, 0))
goto err;
+ } while (BN_is_zero(blind));
+ BN_set_flags(blind, BN_FLG_CONSTTIME);
+ BN_set_flags(blindm, BN_FLG_CONSTTIME);
+ BN_set_flags(tmp, BN_FLG_CONSTTIME);
+
+ /* tmp := blind * priv_key * r mod q */
+ if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx))
+ goto err;
+ if (!BN_mod_mul(tmp, tmp, r, dsa->q, ctx))
+ goto err;
+
+ /* blindm := blind * m mod q */
+ if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx))
+ goto err;
+
+ /* s : = (blind * priv_key * r) + (blind * m) mod q */
+ if (!BN_mod_add_quick(s, tmp, blindm, dsa->q))
+ goto err;
+
+ /* s := s * k^-1 mod q */
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
goto err;
+ /* s:= s * blind^-1 mod q */
+ if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL)
+ goto err;
+ if (!BN_mod_mul(s, s, blind, dsa->q, ctx))
+ goto err;
+
/*
* Redo if r or s is zero as required by FIPS 186-3: this is very
* unlikely.
@@ -212,13 +247,9 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
BN_free(r);
BN_free(s);
}
- if (ctx != NULL)
- BN_CTX_free(ctx);
- BN_clear_free(&m);
- BN_clear_free(&xr);
- if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
- BN_clear_free(kinv);
- return (ret);
+ BN_CTX_free(ctx);
+ BN_clear_free(kinv);
+ return ret;
}
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c b/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c
index 49cf38fe..c5cf7749 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c
@@ -5,7 +5,7 @@
* 2006.
*/
/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -232,10 +232,16 @@ static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits,
NULL);
}
- if (!strcmp(type, "dsa_paramgen_md")) {
+ if (strcmp(type, "dsa_paramgen_md") == 0) {
+ const EVP_MD *md = EVP_get_digestbyname(value);
+
+ if (md == NULL) {
+ DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE);
+ return 0;
+ }
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0,
- (void *)EVP_get_digestbyname(value));
+ (void *)md);
}
return -2;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ec_ameth.c b/freebsd/crypto/openssl/crypto/ec/ec_ameth.c
index ddecdc05..d29fab1f 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec_ameth.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec_ameth.c
@@ -5,7 +5,7 @@
* 2006.
*/
/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -145,19 +145,19 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
static EC_KEY *eckey_type2param(int ptype, void *pval)
{
EC_KEY *eckey = NULL;
+ EC_GROUP *group = NULL;
+
if (ptype == V_ASN1_SEQUENCE) {
- ASN1_STRING *pstr = pval;
- const unsigned char *pm = NULL;
- int pmlen;
- pm = pstr->data;
- pmlen = pstr->length;
- if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
+ const ASN1_STRING *pstr = pval;
+ const unsigned char *pm = pstr->data;
+ int pmlen = pstr->length;
+
+ if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) {
ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
goto ecerr;
}
} else if (ptype == V_ASN1_OBJECT) {
- ASN1_OBJECT *poid = pval;
- EC_GROUP *group;
+ const ASN1_OBJECT *poid = pval;
/*
* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
@@ -181,8 +181,8 @@ static EC_KEY *eckey_type2param(int ptype, void *pval)
return eckey;
ecerr:
- if (eckey)
- EC_KEY_free(eckey);
+ EC_KEY_free(eckey);
+ EC_GROUP_free(group);
return NULL;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ec_lib.c b/freebsd/crypto/openssl/crypto/ec/ec_lib.c
index ce22b252..e7756dc1 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec_lib.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec_lib.c
@@ -5,7 +5,7 @@
* Originally written by Bodo Moeller for the OpenSSL project.
*/
/* ====================================================================
- * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -321,12 +321,16 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
BN_zero(&group->cofactor);
/*
- * We ignore the return value because some groups have an order with
+ * Some groups have an order with
* factors of two, which makes the Montgomery setup fail.
* |group->mont_data| will be NULL in this case.
*/
- ec_precompute_mont_data(group);
+ if (BN_is_odd(&group->order)) {
+ return ec_precompute_mont_data(group);
+ }
+ BN_MONT_CTX_free(group->mont_data);
+ group->mont_data = NULL;
return 1;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c b/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c
index 27c0e870..9be2f5d9 100644
--- a/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c
+++ b/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c
@@ -1120,23 +1120,32 @@ static int ecp_nistz256_set_from_affine(EC_POINT *out, const EC_GROUP *group,
const P256_POINT_AFFINE *in,
BN_CTX *ctx)
{
- BIGNUM x, y;
- BN_ULONG d_x[P256_LIMBS], d_y[P256_LIMBS];
+ BIGNUM x, y, z;
int ret = 0;
- memcpy(d_x, in->X, sizeof(d_x));
- x.d = d_x;
+ /*
+ * |const| qualifier omission is compensated by BN_FLG_STATIC_DATA
+ * flag, which effectively means "read-only data".
+ */
+ x.d = (BN_ULONG *)in->X;
x.dmax = x.top = P256_LIMBS;
x.neg = 0;
x.flags = BN_FLG_STATIC_DATA;
- memcpy(d_y, in->Y, sizeof(d_y));
- y.d = d_y;
+ y.d = (BN_ULONG *)in->Y;
y.dmax = y.top = P256_LIMBS;
y.neg = 0;
y.flags = BN_FLG_STATIC_DATA;
- ret = EC_POINT_set_affine_coordinates_GFp(group, out, &x, &y, ctx);
+ z.d = (BN_ULONG *)ONE;
+ z.dmax = z.top = P256_LIMBS;
+ z.neg = 0;
+ z.flags = BN_FLG_STATIC_DATA;
+
+ if ((ret = (BN_copy(&out->X, &x) != NULL))
+ && (ret = (BN_copy(&out->Y, &y) != NULL))
+ && (ret = (BN_copy(&out->Z, &z) != NULL)))
+ out->Z_is_one = 1;
return ret;
}
diff --git a/freebsd/crypto/openssl/crypto/ecdsa/ecdsatest.c b/freebsd/crypto/openssl/crypto/ecdsa/ecdsatest.c
index 7ef6f3e6..13602806 100644
--- a/freebsd/crypto/openssl/crypto/ecdsa/ecdsatest.c
+++ b/freebsd/crypto/openssl/crypto/ecdsa/ecdsatest.c
@@ -5,7 +5,7 @@
* Written by Nils Larsch for the OpenSSL project.
*/
/* ====================================================================
- * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2000-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -139,7 +139,7 @@ int restore_rand(void)
return 1;
}
-static int fbytes_counter = 0;
+static int fbytes_counter = 0, use_fake = 0;
static const char *numbers[8] = {
"651056770906015076056810763456358567190100156695615665659",
"6140507067065001063065065565667405560006161556565665656654",
@@ -160,6 +160,11 @@ int fbytes(unsigned char *buf, int num)
int ret;
BIGNUM *tmp = NULL;
+ if (use_fake == 0)
+ return old_rand->bytes(buf, num);
+
+ use_fake = 0;
+
if (fbytes_counter >= 8)
return 0;
tmp = BN_new();
@@ -201,11 +206,13 @@ int x9_62_test_internal(BIO *out, int nid, const char *r_in, const char *s_in)
/* create the key */
if ((key = EC_KEY_new_by_curve_name(nid)) == NULL)
goto x962_int_err;
+ use_fake = 1;
if (!EC_KEY_generate_key(key))
goto x962_int_err;
BIO_printf(out, ".");
(void)BIO_flush(out);
/* create the signature */
+ use_fake = 1;
signature = ECDSA_do_sign(digest, 20, key);
if (signature == NULL)
goto x962_int_err;
diff --git a/freebsd/crypto/openssl/crypto/ecdsa/ecs_ossl.c b/freebsd/crypto/openssl/crypto/ecdsa/ecs_ossl.c
index ccc1d30a..587ba6bd 100644
--- a/freebsd/crypto/openssl/crypto/ecdsa/ecs_ossl.c
+++ b/freebsd/crypto/openssl/crypto/ecdsa/ecs_ossl.c
@@ -5,7 +5,7 @@
* Written by Nils Larsch for the OpenSSL project
*/
/* ====================================================================
- * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -62,6 +62,7 @@
#include <openssl/err.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
+#include "bn_int.h"
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen,
const BIGNUM *, const BIGNUM *,
@@ -253,13 +254,14 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
EC_KEY *eckey)
{
int ok = 0, i;
- BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
+ BIGNUM *kinv = NULL, *s, *m = NULL, *order = NULL;
const BIGNUM *ckinv;
BN_CTX *ctx = NULL;
const EC_GROUP *group;
ECDSA_SIG *ret;
ECDSA_DATA *ecdsa;
const BIGNUM *priv_key;
+ BN_MONT_CTX *mont_data;
ecdsa = ecdsa_check(eckey);
group = EC_KEY_get0_group(eckey);
@@ -278,7 +280,7 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
s = ret->s;
if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
- (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
+ (m = BN_new()) == NULL) {
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -287,6 +289,8 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
goto err;
}
+ mont_data = EC_GROUP_get_mont_data(group);
+
i = BN_num_bits(order);
/*
* Need to truncate digest if it is too long: first truncate whole bytes.
@@ -317,15 +321,27 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
}
}
- if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+ /*
+ * With only one multiplicant being in Montgomery domain
+ * multiplication yields real result without post-conversion.
+ * Also note that all operations but last are performed with
+ * zero-padded vectors. Last operation, BN_mod_mul_montgomery
+ * below, returns user-visible value with removed zero padding.
+ */
+ if (!bn_to_mont_fixed_top(s, ret->r, mont_data, ctx)
+ || !bn_mul_mont_fixed_top(s, s, priv_key, mont_data, ctx)) {
goto err;
}
- if (!BN_mod_add_quick(s, tmp, m, order)) {
+ if (!bn_mod_add_fixed_top(s, s, m, order)) {
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
- if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
+ /*
+ * |s| can still be larger than modulus, because |m| can be. In
+ * such case we count on Montgomery reduction to tie it up.
+ */
+ if (!bn_to_mont_fixed_top(s, s, mont_data, ctx)
+ || !BN_mod_mul_montgomery(s, s, ckinv, mont_data, ctx)) {
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
@@ -355,8 +371,6 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
BN_CTX_free(ctx);
if (m)
BN_clear_free(m);
- if (tmp)
- BN_clear_free(tmp);
if (order)
BN_free(order);
if (kinv)
diff --git a/freebsd/crypto/openssl/crypto/engine/eng_lib.c b/freebsd/crypto/openssl/crypto/engine/eng_lib.c
index c8b594d4..34c6d479 100644
--- a/freebsd/crypto/openssl/crypto/engine/eng_lib.c
+++ b/freebsd/crypto/openssl/crypto/engine/eng_lib.c
@@ -6,7 +6,7 @@
* 2000.
*/
/* ====================================================================
- * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -190,8 +190,10 @@ void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
if (!int_cleanup_check(1))
return;
item = int_cleanup_item(cb);
- if (item)
- sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item);
+ if (item != NULL) {
+ if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0)
+ OPENSSL_free(item);
+ }
}
/* The API function that performs all cleanup */
diff --git a/freebsd/crypto/openssl/crypto/engine/tb_asnmth.c b/freebsd/crypto/openssl/crypto/engine/tb_asnmth.c
index 1c2d4dc6..82dd9e48 100644
--- a/freebsd/crypto/openssl/crypto/engine/tb_asnmth.c
+++ b/freebsd/crypto/openssl/crypto/engine/tb_asnmth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -217,7 +217,7 @@ static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
ENGINE *e = sk_ENGINE_value(sk, i);
EVP_PKEY_ASN1_METHOD *ameth;
e->pkey_asn1_meths(e, &ameth, NULL, nid);
- if (((int)strlen(ameth->pem_str) == lk->len) &&
+ if (ameth != NULL && ((int)strlen(ameth->pem_str) == lk->len) &&
!strncasecmp(ameth->pem_str, lk->str, lk->len)) {
lk->e = e;
lk->ameth = ameth;
diff --git a/freebsd/crypto/openssl/crypto/o_time.c b/freebsd/crypto/openssl/crypto/o_time.c
index 5ec10108..111719f6 100644
--- a/freebsd/crypto/openssl/crypto/o_time.c
+++ b/freebsd/crypto/openssl/crypto/o_time.c
@@ -111,6 +111,10 @@ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result)
if (gmtime_r(timer, result) == NULL)
return NULL;
ts = result;
+#elif defined (OPENSSL_SYS_WINDOWS) && defined(_MSC_VER) && _MSC_VER >= 1400
+ if (gmtime_s(result, timer))
+ return NULL;
+ ts = result;
#elif !defined(OPENSSL_SYS_VMS) || defined(VMS_GMTIME_OK)
ts = gmtime(timer);
if (ts == NULL)
diff --git a/freebsd/crypto/openssl/crypto/opensslv.h b/freebsd/crypto/openssl/crypto/opensslv.h
index 668757f4..68e558c7 100644
--- a/freebsd/crypto/openssl/crypto/opensslv.h
+++ b/freebsd/crypto/openssl/crypto/opensslv.h
@@ -30,11 +30,11 @@ extern "C" {
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
* major minor fix final patch/beta)
*/
-# define OPENSSL_VERSION_NUMBER 0x100020ffL
+# define OPENSSL_VERSION_NUMBER 0x1000210fL
# ifdef OPENSSL_FIPS
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2o-fips 27 Mar 2018"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2p-fips 14 Aug 2018"
# else
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2o-freebsd 27 Mar 2018"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2p-freebsd 14 Aug 2018"
# endif
# define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
diff --git a/freebsd/crypto/openssl/crypto/pem/pem.h b/freebsd/crypto/openssl/crypto/pem/pem.h
index aac72fb2..9c1d939a 100644
--- a/freebsd/crypto/openssl/crypto/pem/pem.h
+++ b/freebsd/crypto/openssl/crypto/pem/pem.h
@@ -442,7 +442,8 @@ void PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt);
int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
unsigned int *siglen, EVP_PKEY *pkey);
-int PEM_def_callback(char *buf, int num, int w, void *key);
+/* The default pem_password_cb that's used internally */
+int PEM_def_callback(char *buf, int num, int rwflag, void *userdata);
void PEM_proc_type(char *buf, int type);
void PEM_dek_info(char *buf, const char *type, int len, char *str);
diff --git a/freebsd/crypto/openssl/crypto/pem/pem_lib.c b/freebsd/crypto/openssl/crypto/pem/pem_lib.c
index 53e44553..9af24f46 100644
--- a/freebsd/crypto/openssl/crypto/pem/pem_lib.c
+++ b/freebsd/crypto/openssl/crypto/pem/pem_lib.c
@@ -84,51 +84,39 @@ static int load_iv(char **fromp, unsigned char *to, int num);
static int check_pem(const char *nm, const char *name);
int pem_check_suffix(const char *pem_str, const char *suffix);
-int PEM_def_callback(char *buf, int num, int w, void *key)
+int PEM_def_callback(char *buf, int num, int rwflag, void *userdata)
{
-#ifdef OPENSSL_NO_FP_API
- /*
- * We should not ever call the default callback routine from windows.
- */
- PEMerr(PEM_F_PEM_DEF_CALLBACK, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return (-1);
-#else
- int i, j;
+ int i, min_len;
const char *prompt;
- if (key) {
- i = strlen(key);
+
+ /* We assume that the user passes a default password as userdata */
+ if (userdata) {
+ i = strlen(userdata);
i = (i > num) ? num : i;
- memcpy(buf, key, i);
- return (i);
+ memcpy(buf, userdata, i);
+ return i;
}
prompt = EVP_get_pw_prompt();
if (prompt == NULL)
prompt = "Enter PEM pass phrase:";
- for (;;) {
- /*
- * We assume that w == 0 means decryption,
- * while w == 1 means encryption
- */
- int min_len = w ? MIN_LENGTH : 0;
+ /*
+ * rwflag == 0 means decryption
+ * rwflag == 1 means encryption
+ *
+ * We assume that for encryption, we want a minimum length, while for
+ * decryption, we cannot know any minimum length, so we assume zero.
+ */
+ min_len = rwflag ? MIN_LENGTH : 0;
- i = EVP_read_pw_string_min(buf, min_len, num, prompt, w);
- if (i != 0) {
- PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD);
- memset(buf, 0, (unsigned int)num);
- return (-1);
- }
- j = strlen(buf);
- if (min_len && j < min_len) {
- fprintf(stderr,
- "phrase is too short, needs to be at least %d chars\n",
- min_len);
- } else
- break;
+ i = EVP_read_pw_string_min(buf, min_len, num, prompt, rwflag);
+ if (i != 0) {
+ PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD);
+ memset(buf, 0, (unsigned int)num);
+ return -1;
}
- return (j);
-#endif
+ return strlen(buf);
}
void PEM_proc_type(char *buf, int type)
@@ -461,7 +449,7 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
klen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u);
else
klen = callback(buf, PEM_BUFSIZE, 0, u);
- if (klen <= 0) {
+ if (klen < 0) {
PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ);
return (0);
}
@@ -501,6 +489,7 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
char **header_pp = &header;
cipher->cipher = NULL;
+ memset(cipher->iv, 0, sizeof(cipher->iv));
if ((header == NULL) || (*header == '\0') || (*header == '\n'))
return (1);
if (strncmp(header, "Proc-Type: ", 11) != 0) {
diff --git a/freebsd/crypto/openssl/crypto/pem/pem_pk8.c b/freebsd/crypto/openssl/crypto/pem/pem_pk8.c
index f0e375c8..60eda58a 100644
--- a/freebsd/crypto/openssl/crypto/pem/pem_pk8.c
+++ b/freebsd/crypto/openssl/crypto/pem/pem_pk8.c
@@ -173,7 +173,7 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
klen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
- if (klen <= 0) {
+ if (klen < 0) {
PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ);
X509_SIG_free(p8);
return NULL;
diff --git a/freebsd/crypto/openssl/crypto/pem/pem_pkey.c b/freebsd/crypto/openssl/crypto/pem/pem_pkey.c
index 839e7bf6..7c136eec 100644
--- a/freebsd/crypto/openssl/crypto/pem/pem_pkey.c
+++ b/freebsd/crypto/openssl/crypto/pem/pem_pkey.c
@@ -115,7 +115,7 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
klen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
- if (klen <= 0) {
+ if (klen < 0) {
PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ);
X509_SIG_free(p8);
goto err;
diff --git a/freebsd/crypto/openssl/crypto/pem/pvkfmt.c b/freebsd/crypto/openssl/crypto/pem/pvkfmt.c
index 07eadeff..3ae863e6 100644
--- a/freebsd/crypto/openssl/crypto/pem/pvkfmt.c
+++ b/freebsd/crypto/openssl/crypto/pem/pvkfmt.c
@@ -5,7 +5,7 @@
* 2005.
*/
/* ====================================================================
- * Copyright (c) 2005 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2005-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -704,7 +704,7 @@ static EVP_PKEY *do_PVK_body(const unsigned char **in,
inlen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
- if (inlen <= 0) {
+ if (inlen < 0) {
PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ);
goto err;
}
diff --git a/freebsd/crypto/openssl/crypto/pkcs12/p12_asn.c b/freebsd/crypto/openssl/crypto/pkcs12/p12_asn.c
index 91a09bfb..7898350d 100644
--- a/freebsd/crypto/openssl/crypto/pkcs12/p12_asn.c
+++ b/freebsd/crypto/openssl/crypto/pkcs12/p12_asn.c
@@ -6,7 +6,7 @@
* 1999.
*/
/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -102,7 +102,7 @@ ASN1_ADB_TEMPLATE(safebag_default) = ASN1_EXP(PKCS12_SAFEBAG, value.other, ASN1_
ASN1_ADB(PKCS12_SAFEBAG) = {
ADB_ENTRY(NID_keyBag, ASN1_EXP(PKCS12_SAFEBAG, value.keybag, PKCS8_PRIV_KEY_INFO, 0)),
ADB_ENTRY(NID_pkcs8ShroudedKeyBag, ASN1_EXP(PKCS12_SAFEBAG, value.shkeybag, X509_SIG, 0)),
- ADB_ENTRY(NID_safeContentsBag, ASN1_EXP_SET_OF(PKCS12_SAFEBAG, value.safes, PKCS12_SAFEBAG, 0)),
+ ADB_ENTRY(NID_safeContentsBag, ASN1_EXP_SEQUENCE_OF(PKCS12_SAFEBAG, value.safes, PKCS12_SAFEBAG, 0)),
ADB_ENTRY(NID_certBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)),
ADB_ENTRY(NID_crlBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)),
ADB_ENTRY(NID_secretBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0))
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_eay.c b/freebsd/crypto/openssl/crypto/rsa/rsa_eay.c
index 279e4df3..30a9c82b 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_eay.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_eay.c
@@ -58,7 +58,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -116,6 +116,7 @@
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
+#include "bn_int.h"
#ifndef RSA_NULL
@@ -158,7 +159,7 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
- int i, j, k, num = 0, r = -1;
+ int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
@@ -234,15 +235,10 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
goto err;
/*
- * put in leading 0 bytes if the number is less than the length of the
- * modulus
+ * BN_bn2binpad puts in leading 0 bytes if the number is less than
+ * the length of the modulus.
*/
- j = BN_num_bytes(ret);
- i = BN_bn2bin(ret, &(to[num - j]));
- for (k = 0; k < (num - i); k++)
- to[k] = 0;
-
- r = num;
+ r = bn_bn2binpad(ret, to, num);
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
@@ -351,7 +347,7 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret, *res;
- int i, j, k, num = 0, r = -1;
+ int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
int local_blinding = 0;
@@ -461,15 +457,10 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
res = ret;
/*
- * put in leading 0 bytes if the number is less than the length of the
- * modulus
+ * BN_bn2binpad puts in leading 0 bytes if the number is less than
+ * the length of the modulus.
*/
- j = BN_num_bytes(res);
- i = BN_bn2bin(res, &(to[num - j]));
- for (k = 0; k < (num - i); k++)
- to[k] = 0;
-
- r = num;
+ r = bn_bn2binpad(res, to, num);
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
@@ -487,7 +478,6 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
{
BIGNUM *f, *ret;
int j, num = 0, r = -1;
- unsigned char *p;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
int local_blinding = 0;
@@ -578,8 +568,7 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
- p = buf;
- j = BN_bn2bin(ret, p); /* j is only used with no-padding mode */
+ j = bn_bn2binpad(ret, buf, num);
switch (padding) {
case RSA_PKCS1_PADDING:
@@ -594,7 +583,7 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
r = RSA_padding_check_SSLv23(to, num, buf, j, num);
break;
case RSA_NO_PADDING:
- r = RSA_padding_check_none(to, num, buf, j, num);
+ memcpy(to, buf, (r = j));
break;
default:
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
@@ -621,7 +610,6 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
{
BIGNUM *f, *ret;
int i, num = 0, r = -1;
- unsigned char *p;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
@@ -686,8 +674,7 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
if (!BN_sub(ret, rsa->n, ret))
goto err;
- p = buf;
- i = BN_bn2bin(ret, p);
+ i = bn_bn2binpad(ret, buf, num);
switch (padding) {
case RSA_PKCS1_PADDING:
@@ -697,7 +684,7 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
r = RSA_padding_check_X931(to, num, buf, i, num);
break;
case RSA_NO_PADDING:
- r = RSA_padding_check_none(to, num, buf, i, num);
+ memcpy(to, buf, (r = i));
break;
default:
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c b/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c
index 36dea9e1..44238de9 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c
@@ -158,6 +158,8 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
if (BN_copy(rsa->e, e_value) == NULL)
goto err;
+ BN_set_flags(rsa->p, BN_FLG_CONSTTIME);
+ BN_set_flags(rsa->q, BN_FLG_CONSTTIME);
BN_set_flags(r2, BN_FLG_CONSTTIME);
/* generate p and q */
for (;;) {
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c b/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c
index b4f1aa59..fbd6e996 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c
@@ -122,7 +122,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
int plen, const EVP_MD *md,
const EVP_MD *mgf1md)
{
- int i, dblen, mlen = -1, one_index = 0, msg_index;
+ int i, dblen = 0, mlen = -1, one_index = 0, msg_index;
unsigned int good, found_one_byte;
const unsigned char *maskedseed, *maskeddb;
/*
@@ -155,32 +155,41 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
dblen = num - mdlen - 1;
db = OPENSSL_malloc(dblen);
- em = OPENSSL_malloc(num);
- if (db == NULL || em == NULL) {
+ if (db == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
goto cleanup;
}
- /*
- * Always do this zero-padding copy (even when num == flen) to avoid
- * leaking that information. The copy still leaks some side-channel
- * information, but it's impossible to have a fixed memory access
- * pattern since we can't read out of the bounds of |from|.
- *
- * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
- */
- memset(em, 0, num);
- memcpy(em + num - flen, from, flen);
+ if (flen != num) {
+ em = OPENSSL_malloc(num);
+ if (em == NULL) {
+ RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
+ ERR_R_MALLOC_FAILURE);
+ goto cleanup;
+ }
+
+ /*
+ * Caller is encouraged to pass zero-padded message created with
+ * BN_bn2binpad, but if it doesn't, we do this zero-padding copy
+ * to avoid leaking that information. The copy still leaks some
+ * side-channel information, but it's impossible to have a fixed
+ * memory access pattern since we can't read out of the bounds of
+ * |from|.
+ */
+ memset(em, 0, num);
+ memcpy(em + num - flen, from, flen);
+ from = em;
+ }
/*
* The first byte must be zero, however we must not leak if this is
* true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
*/
- good = constant_time_is_zero(em[0]);
+ good = constant_time_is_zero(from[0]);
- maskedseed = em + 1;
- maskeddb = em + 1 + mdlen;
+ maskedseed = from + 1;
+ maskeddb = from + 1 + mdlen;
if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
goto cleanup;
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c b/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c
index 0dd288b1..553c7b7f 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c
@@ -100,6 +100,27 @@ int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *p;
p = from;
+
+ /*
+ * The format is
+ * 00 || 01 || PS || 00 || D
+ * PS - padding string, at least 8 bytes of FF
+ * D - data.
+ */
+
+ if (num < 11)
+ return -1;
+
+ /* Accept inputs with and without the leading 0-byte. */
+ if (num == flen) {
+ if ((*p++) != 0x00) {
+ RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
+ RSA_R_INVALID_PADDING);
+ return -1;
+ }
+ flen--;
+ }
+
if ((num != (flen + 1)) || (*(p++) != 01)) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
RSA_R_BLOCK_TYPE_IS_NOT_01);
@@ -205,28 +226,31 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
if (num < 11)
goto err;
- em = OPENSSL_malloc(num);
- if (em == NULL) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
- return -1;
+ if (flen != num) {
+ em = OPENSSL_malloc(num);
+ if (em == NULL) {
+ RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ /*
+ * Caller is encouraged to pass zero-padded message created with
+ * BN_bn2binpad, but if it doesn't, we do this zero-padding copy
+ * to avoid leaking that information. The copy still leaks some
+ * side-channel information, but it's impossible to have a fixed
+ * memory access pattern since we can't read out of the bounds of
+ * |from|.
+ */
+ memset(em, 0, num);
+ memcpy(em + num - flen, from, flen);
+ from = em;
}
- memset(em, 0, num);
- /*
- * Always do this zero-padding copy (even when num == flen) to avoid
- * leaking that information. The copy still leaks some side-channel
- * information, but it's impossible to have a fixed memory access
- * pattern since we can't read out of the bounds of |from|.
- *
- * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
- */
- memcpy(em + num - flen, from, flen);
- good = constant_time_is_zero(em[0]);
- good &= constant_time_eq(em[1], 2);
+ good = constant_time_is_zero(from[0]);
+ good &= constant_time_eq(from[1], 2);
found_zero_byte = 0;
for (i = 2; i < num; i++) {
- unsigned int equals0 = constant_time_is_zero(em[i]);
+ unsigned int equals0 = constant_time_is_zero(from[i]);
zero_index =
constant_time_select_int(~found_zero_byte & equals0, i,
zero_index);
@@ -234,7 +258,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |em|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |from|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
@@ -263,7 +287,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
goto err;
}
- memcpy(to, em + msg_index, mlen);
+ memcpy(to, from + msg_index, mlen);
err:
if (em != NULL) {
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_sign.c b/freebsd/crypto/openssl/crypto/rsa/rsa_sign.c
index afab2826..4d03b3c5 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_sign.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_sign.c
@@ -86,7 +86,7 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
return 0;
}
#endif
- if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) {
+ if ((rsa->meth->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) {
return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
}
/* Special case: SSL signature, just check the length */
@@ -295,7 +295,7 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
{
- if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) {
+ if ((rsa->meth->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) {
return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa);
}
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c
index a3f6cf76..b49d9c69 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c
@@ -114,6 +114,14 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
return (-1);
}
+ /* Accept even zero-padded input */
+ if (flen == num) {
+ if (*(p++) != 0) {
+ RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_BLOCK_TYPE_IS_NOT_02);
+ return -1;
+ }
+ flen--;
+ }
if ((num != (flen + 1)) || (*(p++) != 02)) {
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_BLOCK_TYPE_IS_NOT_02);
return (-1);
diff --git a/freebsd/crypto/openssl/crypto/ui/ui_openssl.c b/freebsd/crypto/openssl/crypto/ui/ui_openssl.c
index cc6e2175..47b9c21f 100644
--- a/freebsd/crypto/openssl/crypto/ui/ui_openssl.c
+++ b/freebsd/crypto/openssl/crypto/ui/ui_openssl.c
@@ -6,7 +6,7 @@
* OpenSSL project 2001.
*/
/* ====================================================================
- * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2001-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -569,17 +569,13 @@ static int echo_console(UI *ui)
{
#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
- tty_new.TTY_FLAGS |= ECHO;
-#endif
-
-#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1))
return 0;
#endif
#ifdef OPENSSL_SYS_VMS
if (is_a_tty) {
tty_new[0] = tty_orig[0];
- tty_new[1] = tty_orig[1] & ~TT$M_NOECHO;
+ tty_new[1] = tty_orig[1];
tty_new[2] = tty_orig[2];
status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
0, 0, 0, 0);
diff --git a/freebsd/crypto/openssl/crypto/x509/x509_cmp.c b/freebsd/crypto/openssl/crypto/x509/x509_cmp.c
index 2d010d0e..600573ac 100644
--- a/freebsd/crypto/openssl/crypto/x509/x509_cmp.c
+++ b/freebsd/crypto/openssl/crypto/x509/x509_cmp.c
@@ -221,7 +221,7 @@ int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
ret = a->canon_enclen - b->canon_enclen;
- if (ret)
+ if (ret != 0 || a->canon_enclen == 0)
return ret;
return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
diff --git a/freebsd/crypto/openssl/crypto/x509/x509_lu.c b/freebsd/crypto/openssl/crypto/x509/x509_lu.c
index 5e01c812..942b11da 100644
--- a/freebsd/crypto/openssl/crypto/x509/x509_lu.c
+++ b/freebsd/crypto/openssl/crypto/x509/x509_lu.c
@@ -313,7 +313,11 @@ int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
X509_OBJECT stmp, *tmp;
int i, j;
+ if (ctx == NULL)
+ return 0;
+
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+
tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
@@ -508,6 +512,10 @@ STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
STACK_OF(X509) *sk;
X509 *x;
X509_OBJECT *obj;
+
+ if (ctx->ctx == NULL)
+ return NULL;
+
sk = sk_X509_new_null();
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
@@ -553,6 +561,11 @@ STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
STACK_OF(X509_CRL) *sk;
X509_CRL *x;
X509_OBJECT *obj, xobj;
+
+
+ if (ctx->ctx == NULL)
+ return NULL;
+
sk = sk_X509_CRL_new_null();
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
@@ -653,6 +666,9 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
}
X509_OBJECT_free_contents(&obj);
+ if (ctx->ctx == NULL)
+ return 0;
+
/* Else find index of first cert accepted by 'check_issued' */
ret = 0;
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
diff --git a/freebsd/crypto/openssl/crypto/x509/x509_vfy.c b/freebsd/crypto/openssl/crypto/x509/x509_vfy.c
index 5ef49a6b..5765100e 100644
--- a/freebsd/crypto/openssl/crypto/x509/x509_vfy.c
+++ b/freebsd/crypto/openssl/crypto/x509/x509_vfy.c
@@ -58,6 +58,7 @@
* [including the GNU Public Licence.]
*/
+#include <ctype.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
@@ -1939,119 +1940,67 @@ int X509_cmp_current_time(const ASN1_TIME *ctm)
int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
- char *str;
- ASN1_TIME atm;
- long offset;
- char buff1[24], buff2[24], *p;
- int i, j, remaining;
+ static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1;
+ static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1;
+ ASN1_TIME *asn1_cmp_time = NULL;
+ int i, day, sec, ret = 0;
- p = buff1;
- remaining = ctm->length;
- str = (char *)ctm->data;
/*
- * Note that the following (historical) code allows much more slack in the
- * time format than RFC5280. In RFC5280, the representation is fixed:
+ * Note that ASN.1 allows much more slack in the time format than RFC5280.
+ * In RFC5280, the representation is fixed:
* UTCTime: YYMMDDHHMMSSZ
* GeneralizedTime: YYYYMMDDHHMMSSZ
+ *
+ * We do NOT currently enforce the following RFC 5280 requirement:
+ * "CAs conforming to this profile MUST always encode certificate
+ * validity dates through the year 2049 as UTCTime; certificate validity
+ * dates in 2050 or later MUST be encoded as GeneralizedTime."
*/
- if (ctm->type == V_ASN1_UTCTIME) {
- /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
- int min_length = sizeof("YYMMDDHHMMZ") - 1;
- int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
- if (remaining < min_length || remaining > max_length)
+ switch (ctm->type) {
+ case V_ASN1_UTCTIME:
+ if (ctm->length != (int)(utctime_length))
return 0;
- memcpy(p, str, 10);
- p += 10;
- str += 10;
- remaining -= 10;
- } else {
- /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
- int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
- int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
- if (remaining < min_length || remaining > max_length)
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ if (ctm->length != (int)(generalizedtime_length))
return 0;
- memcpy(p, str, 12);
- p += 12;
- str += 12;
- remaining -= 12;
+ break;
+ default:
+ return 0;
}
- if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
- *(p++) = '0';
- *(p++) = '0';
- } else {
- /* SS (seconds) */
- if (remaining < 2)
+ /**
+ * Verify the format: the ASN.1 functions we use below allow a more
+ * flexible format than what's mandated by RFC 5280.
+ * Digit and date ranges will be verified in the conversion methods.
+ */
+ for (i = 0; i < ctm->length - 1; i++) {
+ if (!isdigit(ctm->data[i]))
return 0;
- *(p++) = *(str++);
- *(p++) = *(str++);
- remaining -= 2;
- /*
- * Skip any (up to three) fractional seconds...
- * TODO(emilia): in RFC5280, fractional seconds are forbidden.
- * Can we just kill them altogether?
- */
- if (remaining && *str == '.') {
- str++;
- remaining--;
- for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
- if (*str < '0' || *str > '9')
- break;
- }
- }
-
}
- *(p++) = 'Z';
- *(p++) = '\0';
-
- /* We now need either a terminating 'Z' or an offset. */
- if (!remaining)
+ if (ctm->data[ctm->length - 1] != 'Z')
return 0;
- if (*str == 'Z') {
- if (remaining != 1)
- return 0;
- offset = 0;
- } else {
- /* (+-)HHMM */
- if ((*str != '+') && (*str != '-'))
- return 0;
- /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
- if (remaining != 5)
- return 0;
- if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
- str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
- return 0;
- offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
- offset += (str[3] - '0') * 10 + (str[4] - '0');
- if (*str == '-')
- offset = -offset;
- }
- atm.type = ctm->type;
- atm.flags = 0;
- atm.length = sizeof(buff2);
- atm.data = (unsigned char *)buff2;
- if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
- return 0;
+ /*
+ * There is ASN1_UTCTIME_cmp_time_t but no
+ * ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t,
+ * so we go through ASN.1
+ */
+ asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time);
+ if (asn1_cmp_time == NULL)
+ goto err;
+ if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time))
+ goto err;
- if (ctm->type == V_ASN1_UTCTIME) {
- i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
- if (i < 50)
- i += 100; /* cf. RFC 2459 */
- j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
- if (j < 50)
- j += 100;
-
- if (i < j)
- return -1;
- if (i > j)
- return 1;
- }
- i = strcmp(buff1, buff2);
- if (i == 0) /* wait a second then return younger :-) */
- return -1;
- else
- return i;
+ /*
+ * X509_cmp_time comparison is <=.
+ * The return value 0 is reserved for errors.
+ */
+ ret = (day >= 0 && sec >= 0) ? -1 : 1;
+
+ err:
+ ASN1_TIME_free(asn1_cmp_time);
+ return ret;
}
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
diff --git a/freebsd/crypto/openssl/crypto/x509v3/v3_purp.c b/freebsd/crypto/openssl/crypto/x509v3/v3_purp.c
index 9e14767e..655e963e 100644
--- a/freebsd/crypto/openssl/crypto/x509v3/v3_purp.c
+++ b/freebsd/crypto/openssl/crypto/x509v3/v3_purp.c
@@ -6,7 +6,7 @@
* 2001.
*/
/* ====================================================================
- * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -130,11 +130,10 @@ int X509_check_purpose(X509 *x, int id, int ca)
{
int idx;
const X509_PURPOSE *pt;
- if (!(x->ex_flags & EXFLAG_SET)) {
- CRYPTO_w_lock(CRYPTO_LOCK_X509);
- x509v3_cache_extensions(x);
- CRYPTO_w_unlock(CRYPTO_LOCK_X509);
- }
+
+ x509v3_cache_extensions(x);
+
+ /* Return if side-effect only call */
if (id == -1)
return 1;
idx = X509_PURPOSE_get_by_id(id);
@@ -401,8 +400,16 @@ static void x509v3_cache_extensions(X509 *x)
X509_EXTENSION *ex;
int i;
+
if (x->ex_flags & EXFLAG_SET)
return;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_X509);
+ if (x->ex_flags & EXFLAG_SET) {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509);
+ return;
+ }
+
#ifndef OPENSSL_NO_SHA
X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
#endif
@@ -538,6 +545,7 @@ static void x509v3_cache_extensions(X509 *x)
}
}
x->ex_flags |= EXFLAG_SET;
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509);
}
/*-
@@ -580,11 +588,7 @@ static int check_ca(const X509 *x)
int X509_check_ca(X509 *x)
{
- if (!(x->ex_flags & EXFLAG_SET)) {
- CRYPTO_w_lock(CRYPTO_LOCK_X509);
- x509v3_cache_extensions(x);
- CRYPTO_w_unlock(CRYPTO_LOCK_X509);
- }
+ x509v3_cache_extensions(x);
return check_ca(x);
}
@@ -798,6 +802,7 @@ int X509_check_issued(X509 *issuer, X509 *subject)
if (X509_NAME_cmp(X509_get_subject_name(issuer),
X509_get_issuer_name(subject)))
return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+
x509v3_cache_extensions(issuer);
x509v3_cache_extensions(subject);
diff --git a/freebsd/crypto/openssl/ssl/d1_both.c b/freebsd/crypto/openssl/ssl/d1_both.c
index 2b6439dc..58d71aef 100644
--- a/freebsd/crypto/openssl/ssl/d1_both.c
+++ b/freebsd/crypto/openssl/ssl/d1_both.c
@@ -6,7 +6,7 @@
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
- * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -658,7 +658,8 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
al = dtls1_preprocess_fragment(s, &frag->msg_header, max);
- if (al == 0) { /* no alert */
+ /* al will be 0 if no alert */
+ if (al == 0 && frag->msg_header.frag_len > 0) {
unsigned char *p =
(unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
memcpy(&p[frag->msg_header.frag_off], frag->fragment,
diff --git a/freebsd/crypto/openssl/ssl/s3_lib.c b/freebsd/crypto/openssl/ssl/s3_lib.c
index 0fb5d354..0b53bd4e 100644
--- a/freebsd/crypto/openssl/ssl/s3_lib.c
+++ b/freebsd/crypto/openssl/ssl/s3_lib.c
@@ -58,7 +58,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -4230,8 +4230,13 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
#ifndef OPENSSL_NO_ECDSA
int have_ecdsa_sign = 0;
#endif
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
int nostrict = 1;
+#endif
+#if !defined(OPENSSL_NO_GOST) || !defined(OPENSSL_NO_DH) || \
+ !defined(OPENSSL_NO_ECDH)
unsigned long alg_k;
+#endif
/* If we have custom certificate types set, use them */
if (s->cert->ctypes) {
@@ -4240,8 +4245,10 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
}
/* get configured sigalgs */
siglen = tls12_get_psigalgs(s, 1, &sig);
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
nostrict = 0;
+#endif
for (i = 0; i < siglen; i += 2, sig += 2) {
switch (sig[1]) {
case TLSEXT_signature_rsa:
@@ -4259,7 +4266,10 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
}
}
+#if !defined(OPENSSL_NO_GOST) || !defined(OPENSSL_NO_DH) || \
+ !defined(OPENSSL_NO_ECDH)
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+#endif
#ifndef OPENSSL_NO_GOST
if (s->version >= TLS1_VERSION) {
diff --git a/freebsd/crypto/openssl/ssl/s3_srvr.c b/freebsd/crypto/openssl/ssl/s3_srvr.c
index 40524d99..5916d77d 100644
--- a/freebsd/crypto/openssl/ssl/s3_srvr.c
+++ b/freebsd/crypto/openssl/ssl/s3_srvr.c
@@ -58,7 +58,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1961,11 +1961,12 @@ int ssl3_send_server_key_exchange(SSL *s)
#ifndef OPENSSL_NO_PSK
if (type & SSL_kPSK) {
+ size_t len = strlen(s->ctx->psk_identity_hint);
+
/* copy PSK identity hint */
- s2n(strlen(s->ctx->psk_identity_hint), p);
- strncpy((char *)p, s->ctx->psk_identity_hint,
- strlen(s->ctx->psk_identity_hint));
- p += strlen(s->ctx->psk_identity_hint);
+ s2n(len, p);
+ memcpy(p, s->ctx->psk_identity_hint, len);
+ p += len;
}
#endif
@@ -2092,6 +2093,11 @@ int ssl3_send_certificate_request(SSL *s)
if (SSL_USE_SIGALGS(s)) {
const unsigned char *psigs;
nl = tls12_get_psigalgs(s, 1, &psigs);
+ if (nl > SSL_MAX_2_BYTE_LEN) {
+ SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_TOO_LONG);
+ goto err;
+ }
s2n(nl, p);
memcpy(p, psigs, nl);
p += nl;
@@ -2108,6 +2114,11 @@ int ssl3_send_certificate_request(SSL *s)
for (i = 0; i < sk_X509_NAME_num(sk); i++) {
name = sk_X509_NAME_value(sk, i);
j = i2d_X509_NAME(name, NULL);
+ if (j > SSL_MAX_2_BYTE_LEN) {
+ SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_TOO_LONG);
+ goto err;
+ }
if (!BUF_MEM_grow_clean
(buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) {
SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,
@@ -2129,6 +2140,11 @@ int ssl3_send_certificate_request(SSL *s)
n += j;
nl += j;
}
+ if (nl > SSL_MAX_2_BYTE_LEN) {
+ SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_TOO_LONG);
+ goto err;
+ }
}
}
/* else no CA names */
diff --git a/freebsd/crypto/openssl/ssl/ssl.h b/freebsd/crypto/openssl/ssl/ssl.h
index 3cf96a23..4bc1f4e6 100644
--- a/freebsd/crypto/openssl/ssl/ssl.h
+++ b/freebsd/crypto/openssl/ssl/ssl.h
@@ -56,7 +56,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -548,7 +548,7 @@ struct ssl_session_st {
const SSL_CIPHER *cipher;
unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used
* to load the 'cipher' structure */
- STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
+ STACK_OF(SSL_CIPHER) *ciphers; /* ciphers offered by the client */
CRYPTO_EX_DATA ex_data; /* application specific data */
/*
* These are used to make removal of session-ids more efficient and to
@@ -2149,7 +2149,7 @@ int SSL_get_fd(const SSL *s);
int SSL_get_rfd(const SSL *s);
int SSL_get_wfd(const SSL *s);
const char *SSL_get_cipher_list(const SSL *s, int n);
-char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
+char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
int SSL_get_read_ahead(const SSL *s);
int SSL_pending(const SSL *s);
# ifndef OPENSSL_NO_SOCK
@@ -2954,6 +2954,7 @@ void ERR_load_SSL_strings(void);
# define SSL_R_KRB5_S_TKT_NYV 294
# define SSL_R_KRB5_S_TKT_SKEW 295
# define SSL_R_LENGTH_MISMATCH 159
+# define SSL_R_LENGTH_TOO_LONG 404
# define SSL_R_LENGTH_TOO_SHORT 160
# define SSL_R_LIBRARY_BUG 274
# define SSL_R_LIBRARY_HAS_NO_CIPHERS 161
diff --git a/freebsd/crypto/openssl/ssl/ssl_lib.c b/freebsd/crypto/openssl/ssl/ssl_lib.c
index cbcecb77..c7efc0ec 100644
--- a/freebsd/crypto/openssl/ssl/ssl_lib.c
+++ b/freebsd/crypto/openssl/ssl/ssl_lib.c
@@ -60,7 +60,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1406,28 +1406,37 @@ int SSL_set_cipher_list(SSL *s, const char *str)
}
/* works well for SSLv2, not so good for SSLv3 */
-char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len)
+char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size)
{
char *p;
- STACK_OF(SSL_CIPHER) *sk;
+ STACK_OF(SSL_CIPHER) *clntsk, *srvrsk;
SSL_CIPHER *c;
int i;
- if ((s->session == NULL) || (s->session->ciphers == NULL) || (len < 2))
- return (NULL);
+ if (!s->server
+ || s->session == NULL
+ || s->session->ciphers == NULL
+ || size < 2)
+ return NULL;
p = buf;
- sk = s->session->ciphers;
+ clntsk = s->session->ciphers;
+ srvrsk = SSL_get_ciphers(s);
+ if (clntsk == NULL || srvrsk == NULL)
+ return NULL;
- if (sk_SSL_CIPHER_num(sk) == 0)
+ if (sk_SSL_CIPHER_num(clntsk) == 0 || sk_SSL_CIPHER_num(srvrsk) == 0)
return NULL;
- for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ for (i = 0; i < sk_SSL_CIPHER_num(clntsk); i++) {
int n;
- c = sk_SSL_CIPHER_value(sk, i);
+ c = sk_SSL_CIPHER_value(clntsk, i);
+ if (sk_SSL_CIPHER_find(srvrsk, c) < 0)
+ continue;
+
n = strlen(c->name);
- if (n + 1 > len) {
+ if (n + 1 > size) {
if (p != buf)
--p;
*p = '\0';
@@ -1436,7 +1445,7 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len)
strcpy(p, c->name);
p += n;
*(p++) = ':';
- len -= n + 1;
+ size -= n + 1;
}
p[-1] = '\0';
return (buf);
diff --git a/freebsd/crypto/openssl/ssl/ssl_locl.h b/freebsd/crypto/openssl/ssl/ssl_locl.h
index aeffc006..43789ad7 100644
--- a/freebsd/crypto/openssl/ssl/ssl_locl.h
+++ b/freebsd/crypto/openssl/ssl/ssl_locl.h
@@ -56,7 +56,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -259,6 +259,8 @@
c[1]=(unsigned char)(((l)>> 8)&0xff), \
c[2]=(unsigned char)(((l) )&0xff)),c+=3)
+# define SSL_MAX_2_BYTE_LEN (0xffff)
+
/* LOCAL STUFF */
# define SSL_DECRYPT 0
diff --git a/freebsd/crypto/openssl/ssl/t1_lib.c b/freebsd/crypto/openssl/ssl/t1_lib.c
index 8434aa57..6af6c5a9 100644
--- a/freebsd/crypto/openssl/ssl/t1_lib.c
+++ b/freebsd/crypto/openssl/ssl/t1_lib.c
@@ -2410,8 +2410,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
goto err;
if (!tls1_save_sigalgs(s, data, dsize))
goto err;
- } else if (type == TLSEXT_TYPE_status_request) {
-
+ } else if (type == TLSEXT_TYPE_status_request && !s->hit) {
if (size < 5)
goto err;
@@ -3168,7 +3167,7 @@ int tls1_set_server_sigalgs(SSL *s)
if (!s->cert->shared_sigalgs) {
SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
- al = SSL_AD_ILLEGAL_PARAMETER;
+ al = SSL_AD_HANDSHAKE_FAILURE;
goto err;
}
} else
diff --git a/freebsd/crypto/openssl/ssl/t1_trce.c b/freebsd/crypto/openssl/ssl/t1_trce.c
index 99028d20..c7cdc294 100644
--- a/freebsd/crypto/openssl/ssl/t1_trce.c
+++ b/freebsd/crypto/openssl/ssl/t1_trce.c
@@ -6,7 +6,7 @@
* project.
*/
/* ====================================================================
- * Copyright (c) 2012 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2012-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -647,6 +647,8 @@ static int ssl_print_extensions(BIO *bio, int indent, int server,
BIO_puts(bio, "No Extensions\n");
return 1;
}
+ if (msglen < 2)
+ return 0;
extslen = (msg[0] << 8) | msg[1];
if (extslen != msglen - 2)
return 0;
@@ -1023,6 +1025,8 @@ static int ssl_print_cert_request(BIO *bio, int indent, SSL *s,
msglen -= xlen + 2;
skip_sig:
+ if (msglen < 2)
+ return 0;
xlen = (msg[0] << 8) | msg[1];
BIO_indent(bio, indent, 80);
if (msglen < xlen + 2)
@@ -1211,7 +1215,15 @@ void SSL_trace(int write_p, int version, int content_type,
switch (content_type) {
case SSL3_RT_HEADER:
{
- int hvers = msg[1] << 8 | msg[2];
+ int hvers;
+
+ /* avoid overlapping with length at the end of buffer */
+ if (msglen < (SSL_IS_DTLS(ssl) ? 13 : 5)) {
+ BIO_puts(bio, write_p ? "Sent" : "Received");
+ ssl_print_hex(bio, 0, " too short message", msg, msglen);
+ break;
+ }
+ hvers = msg[1] << 8 | msg[2];
BIO_puts(bio, write_p ? "Sent" : "Received");
BIO_printf(bio, " Record\nHeader:\n Version = %s (0x%x)\n",
ssl_trace_str(hvers, ssl_version_tbl), hvers);
diff --git a/freebsd/include/nl_types.h b/freebsd/include/nl_types.h
new file mode 100644
index 00000000..bf88144a
--- /dev/null
+++ b/freebsd/include/nl_types.h
@@ -0,0 +1,99 @@
+/* $NetBSD: nl_types.h,v 1.9 2000/10/03 19:53:32 sommerfeld Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ *
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NL_TYPES_H_
+#define _NL_TYPES_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#ifdef _NLS_PRIVATE
+/*
+ * MESSAGE CATALOG FILE FORMAT.
+ *
+ * The NetBSD/FreeBSD message catalog format is similar to the format used by
+ * Svr4 systems. The differences are:
+ * * fixed byte order (big endian)
+ * * fixed data field sizes
+ *
+ * A message catalog contains four data types: a catalog header, one
+ * or more set headers, one or more message headers, and one or more
+ * text strings.
+ */
+
+#define _NLS_MAGIC 0xff88ff89
+
+struct _nls_cat_hdr {
+ int32_t __magic;
+ int32_t __nsets;
+ int32_t __mem;
+ int32_t __msg_hdr_offset;
+ int32_t __msg_txt_offset;
+} ;
+
+struct _nls_set_hdr {
+ int32_t __setno; /* set number: 0 < x <= NL_SETMAX */
+ int32_t __nmsgs; /* number of messages in the set */
+ int32_t __index; /* index of first msg_hdr in msg_hdr table */
+} ;
+
+struct _nls_msg_hdr {
+ int32_t __msgno; /* msg number: 0 < x <= NL_MSGMAX */
+ int32_t __msglen;
+ int32_t __offset;
+} ;
+
+#endif /* _NLS_PRIVATE */
+
+#define NL_SETD 0
+#define NL_CAT_LOCALE 1
+
+typedef struct __nl_cat_d {
+ void *__data;
+ int __size;
+} *nl_catd;
+
+#ifndef _NL_ITEM_DECLARED
+typedef __nl_item nl_item;
+#define _NL_ITEM_DECLARED
+#endif
+
+__BEGIN_DECLS
+nl_catd catopen(const char *, int);
+char *catgets(nl_catd, int, int, const char *) __format_arg(4);
+int catclose(nl_catd);
+__END_DECLS
+
+#endif /* _NL_TYPES_H_ */
diff --git a/freebsd/lib/libc/gen/err.c b/freebsd/lib/libc/gen/err.c
index 9ad0da79..1ab23a1e 100644
--- a/freebsd/lib/libc/gen/err.c
+++ b/freebsd/lib/libc/gen/err.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
+__SCCSID("@(#)err.c 8.1 (Berkeley) 6/4/93");
__FBSDID("$FreeBSD$");
#include "namespace.h"
diff --git a/freebsd/lib/libc/gen/getdomainname.c b/freebsd/lib/libc/gen/getdomainname.c
index 32dfdf01..14ede72a 100644
--- a/freebsd/lib/libc/gen/getdomainname.c
+++ b/freebsd/lib/libc/gen/getdomainname.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
+__SCCSID("@(#)gethostname.c 8.1 (Berkeley) 6/4/93");
__FBSDID("$FreeBSD$");
#include <sys/param.h>
diff --git a/freebsd/lib/libc/gen/gethostname.c b/freebsd/lib/libc/gen/gethostname.c
index 0c832be1..974b771f 100644
--- a/freebsd/lib/libc/gen/gethostname.c
+++ b/freebsd/lib/libc/gen/gethostname.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
+__SCCSID("@(#)gethostname.c 8.1 (Berkeley) 6/4/93");
__FBSDID("$FreeBSD$");
#include <sys/param.h>
diff --git a/freebsd/lib/libc/gen/sethostname.c b/freebsd/lib/libc/gen/sethostname.c
index c7185019..5ab629d8 100644
--- a/freebsd/lib/libc/gen/sethostname.c
+++ b/freebsd/lib/libc/gen/sethostname.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)sethostname.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
+__SCCSID("@(#)sethostname.c 8.1 (Berkeley) 6/4/93");
__FBSDID("$FreeBSD$");
#include <sys/param.h>
diff --git a/freebsd/lib/libc/include/libc_private.h b/freebsd/lib/libc/include/libc_private.h
index f5a2a570..8e78f556 100644
--- a/freebsd/lib/libc/include/libc_private.h
+++ b/freebsd/lib/libc/include/libc_private.h
@@ -409,8 +409,6 @@ int __sys_futimens(int fd, const struct timespec *times) __hidden;
int __sys_utimensat(int fd, const char *path,
const struct timespec *times, int flag) __hidden;
-__size_t __arc4_sysctl(unsigned char *, __size_t);
-
/* execve() with PATH processing to implement posix_spawnp() */
int _execvpe(const char *, char * const *, char * const *);
diff --git a/freebsd/lib/libc/include/namespace.h b/freebsd/lib/libc/include/namespace.h
index 252265c8..08a8c673 100644
--- a/freebsd/lib/libc/include/namespace.h
+++ b/freebsd/lib/libc/include/namespace.h
@@ -126,6 +126,7 @@
#define pthread_detach _pthread_detach
#define pthread_equal _pthread_equal
#define pthread_exit _pthread_exit
+#define pthread_get_name_np _pthread_get_name_np
#define pthread_getaffinity_np _pthread_getaffinity_np
#define pthread_getconcurrency _pthread_getconcurrency
#define pthread_getcpuclockid _pthread_getcpuclockid
diff --git a/freebsd/lib/libc/include/un-namespace.h b/freebsd/lib/libc/include/un-namespace.h
index 5089a707..33c7b00a 100644
--- a/freebsd/lib/libc/include/un-namespace.h
+++ b/freebsd/lib/libc/include/un-namespace.h
@@ -116,6 +116,7 @@
#undef pthread_detach
#undef pthread_equal
#undef pthread_exit
+#undef pthread_get_name_np
#undef pthread_getaffinity_np
#undef pthread_getconcurrency
#undef pthread_getcpuclockid
diff --git a/freebsd/lib/libc/inet/inet_addr.c b/freebsd/lib/libc/inet/inet_addr.c
index 5d8f5f1a..0ec3ee63 100644
--- a/freebsd/lib/libc/inet/inet_addr.c
+++ b/freebsd/lib/libc/inet/inet_addr.c
@@ -186,19 +186,20 @@ inet_aton(const char *cp, struct in_addr *addr) {
case 2: /*%< a.b -- 8.24 bits */
if (val > 0xffffffU)
return (0);
- val |= parts[0] << 24;
+ val |= (uint32_t)parts[0] << 24;
break;
case 3: /*%< a.b.c -- 8.8.16 bits */
if (val > 0xffffU)
return (0);
- val |= (parts[0] << 24) | (parts[1] << 16);
+ val |= ((uint32_t)parts[0] << 24) | (parts[1] << 16);
break;
case 4: /*%< a.b.c.d -- 8.8.8.8 bits */
if (val > 0xffU)
return (0);
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ val |= ((uint32_t)parts[0] << 24) | (parts[1] << 16) |
+ (parts[2] << 8);
break;
}
if (addr != NULL)
diff --git a/freebsd/lib/libc/resolv/res_init.c b/freebsd/lib/libc/resolv/res_init.c
index 815313c0..2cbaa939 100644
--- a/freebsd/lib/libc/resolv/res_init.c
+++ b/freebsd/lib/libc/resolv/res_init.c
@@ -681,6 +681,8 @@ res_setoptions(res_state statp, const char *options, const char *source)
statp->options |= RES_INSECURE2;
} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
statp->options |= RES_ROTATE;
+ } else if (!strncmp(cp, "usevc", sizeof("usevc") - 1)) {
+ statp->options |= RES_USEVC;
} else if (!strncmp(cp, "no-check-names",
sizeof("no-check-names") - 1)) {
statp->options |= RES_NOCHECKNAME;
diff --git a/freebsd/lib/libcapsicum/capsicum_helpers.h b/freebsd/lib/libcapsicum/capsicum_helpers.h
new file mode 100644
index 00000000..60c894f3
--- /dev/null
+++ b/freebsd/lib/libcapsicum/capsicum_helpers.h
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 2016 Mariusz Zaborski <oshogbo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _CAPSICUM_HELPERS_H_
+#define _CAPSICUM_HELPERS_H_
+
+#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <nl_types.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+
+#define CAPH_IGNORE_EBADF 0x0001
+#define CAPH_READ 0x0002
+#define CAPH_WRITE 0x0004
+#define CAPH_LOOKUP 0x0008
+
+__BEGIN_DECLS
+
+static __inline int
+caph_limit_stream(int fd, int flags)
+{
+ cap_rights_t rights;
+ unsigned long cmds[] = { TIOCGETA, TIOCGWINSZ, FIODTYPE };
+
+ cap_rights_init(&rights, CAP_EVENT, CAP_FCNTL, CAP_FSTAT,
+ CAP_IOCTL, CAP_SEEK);
+
+ if ((flags & CAPH_READ) != 0)
+ cap_rights_set(&rights, CAP_READ);
+ if ((flags & CAPH_WRITE) != 0)
+ cap_rights_set(&rights, CAP_WRITE);
+ if ((flags & CAPH_LOOKUP) != 0)
+ cap_rights_set(&rights, CAP_LOOKUP);
+
+ if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) {
+ if (errno == EBADF && (flags & CAPH_IGNORE_EBADF) != 0)
+ return (0);
+ return (-1);
+ }
+
+ if (cap_ioctls_limit(fd, cmds, nitems(cmds)) < 0 && errno != ENOSYS)
+ return (-1);
+
+ if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS)
+ return (-1);
+
+ return (0);
+}
+
+static __inline int
+caph_limit_stdin(void)
+{
+
+ return (caph_limit_stream(STDIN_FILENO, CAPH_READ));
+}
+
+static __inline int
+caph_limit_stderr(void)
+{
+
+ return (caph_limit_stream(STDERR_FILENO, CAPH_WRITE));
+}
+
+static __inline int
+caph_limit_stdout(void)
+{
+
+ return (caph_limit_stream(STDOUT_FILENO, CAPH_WRITE));
+}
+
+static __inline int
+caph_limit_stdio(void)
+{
+ const int iebadf = CAPH_IGNORE_EBADF;
+
+ if (caph_limit_stream(STDIN_FILENO, CAPH_READ | iebadf) == -1 ||
+ caph_limit_stream(STDOUT_FILENO, CAPH_WRITE | iebadf) == -1 ||
+ caph_limit_stream(STDERR_FILENO, CAPH_WRITE | iebadf) == -1)
+ return (-1);
+ return (0);
+}
+
+static __inline void
+caph_cache_tzdata(void)
+{
+
+ tzset();
+}
+
+static __inline void
+caph_cache_catpages(void)
+{
+
+ (void)catopen("libc", NL_CAT_LOCALE);
+}
+
+static __inline int
+caph_enter(void)
+{
+
+ if (cap_enter() < 0 && errno != ENOSYS)
+ return (-1);
+
+ return (0);
+}
+
+
+static __inline int
+caph_enter_casper(void)
+{
+
+ return (CASPER_SUPPORT == 0 ? 0 : caph_enter());
+}
+
+__END_DECLS
+
+#endif /* _CAPSICUM_HELPERS_H_ */
diff --git a/freebsd/lib/libcasper/libcasper/libcasper.h b/freebsd/lib/libcasper/libcasper/libcasper.h
index 81d65f56..c8ed184d 100644
--- a/freebsd/lib/libcasper/libcasper/libcasper.h
+++ b/freebsd/lib/libcasper/libcasper/libcasper.h
@@ -71,6 +71,8 @@ typedef struct cap_channel cap_channel_t;
#endif /* ! WITH_CASPER */
#endif /* ! _CAP_CHANNEL_T_DECLARED */
+__BEGIN_DECLS
+
#ifdef WITH_CASPER
int cap_channel_flags(const cap_channel_t *chan);
#else
@@ -105,7 +107,7 @@ cap_init(void)
{
cap_channel_t *chan;
- chan = malloc(sizeof(*chan));
+ chan = (cap_channel_t *)malloc(sizeof(*chan));
if (chan != NULL) {
chan->cch_fd = -1;
}
@@ -279,4 +281,6 @@ cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl)
}
#endif
+__END_DECLS
+
#endif /* !_LIBCASPER_H_ */
diff --git a/freebsd/lib/libkvm/kvm.h b/freebsd/lib/libkvm/kvm.h
index c5d46f9f..823e40a7 100644
--- a/freebsd/lib/libkvm/kvm.h
+++ b/freebsd/lib/libkvm/kvm.h
@@ -61,10 +61,6 @@ typedef __ssize_t ssize_t;
#define _SSIZE_T_DECLARED
#endif
-#ifndef __rtems__
-typedef uint64_t kvaddr_t; /* An address in a target image. */
-#endif /* __rtems__ */
-
struct kvm_nlist {
const char *n_name;
unsigned char n_type;
diff --git a/freebsd/lib/libutil/libutil.h b/freebsd/lib/libutil/libutil.h
index c79eaac5..2ac5e975 100644
--- a/freebsd/lib/libutil/libutil.h
+++ b/freebsd/lib/libutil/libutil.h
@@ -155,6 +155,7 @@ int pw_edit(int _notsetuid);
int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2);
void pw_fini(void);
int pw_init(const char *_dir, const char *_master);
+void pw_initpwd(struct passwd *_pw);
char *pw_make(const struct passwd *_pw);
char *pw_make_v7(const struct passwd *_pw);
int pw_mkdb(const char *_user);
diff --git a/freebsd/sbin/dhclient/bpf.c b/freebsd/sbin/dhclient/bpf.c
index 978faa58..e1bfacdc 100644
--- a/freebsd/sbin/dhclient/bpf.c
+++ b/freebsd/sbin/dhclient/bpf.c
@@ -97,7 +97,7 @@ if_register_bpf(struct interface_info *info, int flags)
* Packet write filter program:
* 'ip and udp and src port bootps and dst port (bootps or bootpc)'
*/
-struct bpf_insn dhcp_bpf_wfilter[] = {
+static struct bpf_insn dhcp_bpf_wfilter[] = {
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12),
@@ -131,7 +131,7 @@ struct bpf_insn dhcp_bpf_wfilter[] = {
BPF_STMT(BPF_RET+BPF_K, 0),
};
-int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn);
+static int dhcp_bpf_wfilter_len = nitems(dhcp_bpf_wfilter);
void
if_register_send(struct interface_info *info)
@@ -186,7 +186,7 @@ if_register_send(struct interface_info *info)
* XXX: Changes to the filter program may require changes to the
* constant offsets used in if_register_send to patch the BPF program!
*/
-struct bpf_insn dhcp_bpf_filter[] = {
+static struct bpf_insn dhcp_bpf_filter[] = {
/* Make sure this is an IP packet... */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
@@ -213,7 +213,7 @@ struct bpf_insn dhcp_bpf_filter[] = {
BPF_STMT(BPF_RET+BPF_K, 0),
};
-int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn);
+static int dhcp_bpf_filter_len = nitems(dhcp_bpf_filter);
void
if_register_receive(struct interface_info *info)
diff --git a/freebsd/sbin/dhclient/clparse.c b/freebsd/sbin/dhclient/clparse.c
index 05343067..9ed7ae89 100644
--- a/freebsd/sbin/dhclient/clparse.c
+++ b/freebsd/sbin/dhclient/clparse.c
@@ -51,10 +51,9 @@ __FBSDID("$FreeBSD$");
#include "dhctoken.h"
struct client_config top_level_config;
-struct interface_info *dummy_interfaces;
-extern struct interface_info *ifi;
+static struct interface_info *dummy_interfaces;
-char client_script_name[] = "/sbin/dhclient-script";
+static char client_script_name[] = "/sbin/dhclient-script";
/*
* client-conf-file :== client-declarations EOF
diff --git a/freebsd/sbin/dhclient/conflex.c b/freebsd/sbin/dhclient/conflex.c
index b8bf541a..780ecacd 100644
--- a/freebsd/sbin/dhclient/conflex.c
+++ b/freebsd/sbin/dhclient/conflex.c
@@ -55,8 +55,8 @@ __FBSDID("$FreeBSD$");
int lexline;
int lexchar;
char *token_line;
-char *prev_line;
-char *cur_line;
+static char *prev_line;
+static char *cur_line;
const char *tlname;
int eol_token;
@@ -349,6 +349,7 @@ intern(char *atom, int dfv)
return (BOOTING);
if (!strcasecmp(atom + 1, "oot-unknown-clients"))
return (BOOT_UNKNOWN_CLIENTS);
+ break;
case 'c':
if (!strcasecmp(atom + 1, "lass"))
return (CLASS);
diff --git a/freebsd/sbin/dhclient/dhclient.c b/freebsd/sbin/dhclient/dhclient.c
index e0af9431..d155d454 100644
--- a/freebsd/sbin/dhclient/dhclient.c
+++ b/freebsd/sbin/dhclient/dhclient.c
@@ -66,8 +66,12 @@ __FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/endian.h>
+#include <capsicum_helpers.h>
+#include <libgen.h>
+
#include <net80211/ieee80211_freebsd.h>
+
#ifndef _PATH_VAREMPTY
#define _PATH_VAREMPTY "/var/empty"
#endif
@@ -91,21 +95,21 @@ __FBSDID("$FreeBSD$");
cap_channel_t *capsyslog;
time_t cur_time;
-time_t default_lease_time = 43200; /* 12 hours... */
+static time_t default_lease_time = 43200; /* 12 hours... */
const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
char *path_dhclient_db = NULL;
int log_perror = 1;
-int privfd;
-int nullfd = -1;
+static int privfd;
+static int nullfd = -1;
-char hostname[_POSIX_HOST_NAME_MAX + 1];
+static char hostname[_POSIX_HOST_NAME_MAX + 1];
-struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
-struct in_addr inaddr_any, inaddr_broadcast;
+static struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
+static struct in_addr inaddr_any, inaddr_broadcast;
-char *path_dhclient_pidfile;
+static char *path_dhclient_pidfile;
struct pidfh *pidfile;
/*
@@ -121,9 +125,9 @@ struct pidfh *pidfile;
#define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
int log_priority;
-int no_daemon;
-int unknown_ok = 1;
-int routefd;
+static int no_daemon;
+static int unknown_ok = 1;
+static int routefd;
struct interface_info *ifi;
@@ -197,8 +201,8 @@ get_ifa(char *cp, int n)
return (NULL);
}
-struct iaddr defaddr = { .len = 4 };
-uint8_t curbssid[6];
+static struct iaddr defaddr = { .len = 4 };
+static uint8_t curbssid[6];
static void
disassoc(void *arg)
@@ -369,7 +373,7 @@ init_casper(void)
int
main(int argc, char *argv[])
{
- extern char *__progname;
+ u_int capmode;
int ch, fd, quiet = 0, i = 0;
int pipe_fd[2];
int immediate_daemon = 0;
@@ -380,7 +384,7 @@ main(int argc, char *argv[])
init_casper();
/* Initially, log errors to stderr as well as to syslogd. */
- cap_openlog(capsyslog, __progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
+ cap_openlog(capsyslog, getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
@@ -418,7 +422,7 @@ main(int argc, char *argv[])
if (path_dhclient_pidfile == NULL) {
asprintf(&path_dhclient_pidfile,
- "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
+ "%s/dhclient/dhclient.%s.pid", _PATH_VARRUN, *argv);
if (path_dhclient_pidfile == NULL)
error("asprintf");
}
@@ -527,23 +531,33 @@ main(int argc, char *argv[])
if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
error("can't limit route socket: %m");
- if (chroot(_PATH_VAREMPTY) == -1)
- error("chroot");
- if (chdir("/") == -1)
- error("chdir(\"/\")");
-
- if (setgroups(1, &pw->pw_gid) ||
- setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
- seteuid(pw->pw_uid) || setuid(pw->pw_uid))
- error("can't drop privileges: %m");
-
endpwent();
setproctitle("%s", ifi->name);
- if (CASPER_SUPPORT && cap_enter() < 0 && errno != ENOSYS)
+ /* setgroups(2) is not permitted in capability mode. */
+ if (setgroups(1, &pw->pw_gid) != 0)
+ error("can't restrict groups: %m");
+
+ if (caph_enter_casper() < 0)
error("can't enter capability mode: %m");
+ /*
+ * If we are not in capability mode (i.e., Capsicum or libcasper is
+ * disabled), try to restrict filesystem access. This will fail if
+ * kern.chroot_allow_open_directories is 0 or the process is jailed.
+ */
+ if (cap_getmode(&capmode) < 0 || capmode == 0) {
+ if (chroot(_PATH_VAREMPTY) == -1)
+ error("chroot");
+ if (chdir("/") == -1)
+ error("chdir(\"/\")");
+ }
+
+ if (setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
+ seteuid(pw->pw_uid) || setuid(pw->pw_uid))
+ error("can't drop privileges: %m");
+
if (immediate_daemon)
go_daemon();
@@ -561,9 +575,8 @@ main(int argc, char *argv[])
void
usage(void)
{
- extern char *__progname;
- fprintf(stderr, "usage: %s [-bdqu] ", __progname);
+ fprintf(stderr, "usage: %s [-bdqu] ", getprogname());
fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
exit(1);
}
@@ -1903,7 +1916,7 @@ free_client_lease(struct client_lease *lease)
free(lease);
}
-FILE *leaseFile;
+static FILE *leaseFile;
void
rewrite_client_leases(void)
@@ -2449,13 +2462,8 @@ go_daemon(void)
cap_rights_init(&rights);
- if (pidfile != NULL) {
+ if (pidfile != NULL)
pidfile_write(pidfile);
- if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
- errno != ENOSYS) {
- error("can't limit pidfile descriptor: %m");
- }
- }
if (nullfd != -1) {
close(nullfd);
diff --git a/freebsd/sbin/dhclient/dhcpd.h b/freebsd/sbin/dhclient/dhcpd.h
index 8f9071aa..240a3ae2 100644
--- a/freebsd/sbin/dhclient/dhcpd.h
+++ b/freebsd/sbin/dhclient/dhcpd.h
@@ -265,7 +265,7 @@ void do_packet(struct interface_info *, struct dhcp_packet *,
/* errwarn.c */
extern int warnings_occurred;
-void error(const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+void error(const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2))) __dead2;
int warning(const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
int note(const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
int debug(const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
@@ -369,6 +369,8 @@ extern struct client_config top_level_config;
extern struct pidfh *pidfile;
+extern struct interface_info *ifi;
+
void dhcpoffer(struct packet *);
void dhcpack(struct packet *);
void dhcpnak(struct packet *);
diff --git a/freebsd/sbin/dhclient/dispatch.c b/freebsd/sbin/dhclient/dispatch.c
index a9cc65b7..b815e6b8 100644
--- a/freebsd/sbin/dhclient/dispatch.c
+++ b/freebsd/sbin/dhclient/dispatch.c
@@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$");
/* Assert that pointer p is aligned to at least align bytes */
#define assert_aligned(p, align) assert((((uintptr_t)p) & ((align) - 1)) == 0)
-struct protocol *protocols;
-struct timeout *timeouts;
+static struct protocol *protocols;
+static struct timeout *timeouts;
static struct timeout *free_timeouts;
static int interfaces_invalidated;
void (*bootp_packet_handler)(struct interface_info *,
@@ -549,17 +549,29 @@ interface_set_mtu_priv(char *ifname, u_int16_t mtu)
{
struct ifreq ifr;
int sock;
+ u_int16_t old_mtu;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
error("Can't create socket");
memset(&ifr, 0, sizeof(ifr));
+ old_mtu = 0;
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- ifr.ifr_mtu = mtu;
- if (ioctl(sock, SIOCSIFMTU, &ifr) == -1)
- warning("SIOCSIFMTU failed (%d): %s", mtu,
+ if (ioctl(sock, SIOCGIFMTU, (caddr_t)&ifr) == -1)
+ warning("SIOCGIFMTU failed (%s): %s", ifname,
strerror(errno));
+ else
+ old_mtu = ifr.ifr_mtu;
+
+ if (mtu != old_mtu) {
+ ifr.ifr_mtu = mtu;
+
+ if (ioctl(sock, SIOCSIFMTU, &ifr) == -1)
+ warning("SIOCSIFMTU failed (%d): %s", mtu,
+ strerror(errno));
+ }
+
close(sock);
}
diff --git a/freebsd/sbin/dhclient/options.c b/freebsd/sbin/dhclient/options.c
index 209b6536..b31ab32a 100644
--- a/freebsd/sbin/dhclient/options.c
+++ b/freebsd/sbin/dhclient/options.c
@@ -52,8 +52,8 @@ __FBSDID("$FreeBSD$");
#define DHCP_OPTION_DATA
#include "dhcpd.h"
-int bad_options = 0;
-int bad_options_max = 5;
+static int bad_options = 0;
+static int bad_options_max = 5;
void parse_options(struct packet *);
void parse_option_buffer(struct packet *, unsigned char *, int);
diff --git a/freebsd/sbin/dhclient/privsep.c b/freebsd/sbin/dhclient/privsep.c
index f76d2d5f..847ea080 100644
--- a/freebsd/sbin/dhclient/privsep.c
+++ b/freebsd/sbin/dhclient/privsep.c
@@ -104,7 +104,7 @@ buf_read(int sock, void *buf, size_t nbytes)
}
void
-dispatch_imsg(struct interface_info *ifi, int fd)
+dispatch_imsg(struct interface_info *ifix, int fd)
{
struct imsg_hdr hdr;
char *medium, *reason, *filename,
@@ -237,14 +237,14 @@ dispatch_imsg(struct interface_info *ifi, int fd)
error("buf_close: %m");
break;
case IMSG_SEND_PACKET:
- send_packet_priv(ifi, &hdr, fd);
+ send_packet_priv(ifix, &hdr, fd);
break;
case IMSG_SET_INTERFACE_MTU:
if (hdr.len < sizeof(hdr) + sizeof(u_int16_t))
error("corrupted message received");
buf_read(fd, &mtu, sizeof(u_int16_t));
- interface_set_mtu_priv(ifi->name, mtu);
+ interface_set_mtu_priv(ifix->name, mtu);
break;
default:
error("received unknown message, code %d", hdr.code);
diff --git a/freebsd/sbin/dhclient/privsep.h b/freebsd/sbin/dhclient/privsep.h
index 41b8267e..db6ec9b4 100644
--- a/freebsd/sbin/dhclient/privsep.h
+++ b/freebsd/sbin/dhclient/privsep.h
@@ -44,8 +44,3 @@ struct imsg_hdr {
enum imsg_code code;
size_t len;
};
-
-struct buf *buf_open(size_t);
-int buf_add(struct buf *, const void *, size_t);
-int buf_close(int, struct buf *);
-ssize_t buf_read(int sock, void *, size_t);
diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c
index 56b4f6d7..03d916a1 100644
--- a/freebsd/sbin/ifconfig/ifconfig.c
+++ b/freebsd/sbin/ifconfig/ifconfig.c
@@ -127,7 +127,7 @@ static int ifconfig(int argc, char *const *argv, int iscreate,
static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
struct ifaddrs *ifa);
static void tunnel_status(int s);
-static _Noreturn void usage(void);
+static _Noreturn void usage(void);
static struct afswtch *af_getbyname(const char *name);
static struct afswtch *af_getbyfamily(int af);
diff --git a/freebsd/sbin/ifconfig/ifieee80211.c b/freebsd/sbin/ifconfig/ifieee80211.c
index 8faeca23..fa407957 100644
--- a/freebsd/sbin/ifconfig/ifieee80211.c
+++ b/freebsd/sbin/ifconfig/ifieee80211.c
@@ -99,6 +99,8 @@
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h> /* NB: for offsetof */
+#include <locale.h>
+#include <langinfo.h>
#include "ifconfig.h"
@@ -3510,7 +3512,7 @@ list_scan(int s)
#endif /* __rtems__ */
char ssid[IEEE80211_NWID_LEN+1];
const uint8_t *cp;
- int len, ssidmax, idlen;
+ int len, idlen;
if (get80211len(s, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf), &len) < 0)
errx(1, "unable to get scan results");
@@ -3519,9 +3521,8 @@ list_scan(int s)
getchaninfo(s);
- ssidmax = verbose ? IEEE80211_NWID_LEN : 32;
printf("%-*.*s %-17.17s %4s %4s %-7s %3s %4s\n"
- , ssidmax, ssidmax, "SSID/MESH ID"
+ , IEEE80211_NWID_LEN, IEEE80211_NWID_LEN, "SSID/MESH ID"
, "BSSID"
, "CHAN"
, "RATE"
@@ -3544,8 +3545,8 @@ list_scan(int s)
idlen = sr->isr_ssid_len;
}
printf("%-*.*s %s %3d %3dM %4d:%-4d %4d %-4.4s"
- , ssidmax
- , copy_essid(ssid, ssidmax, idp, idlen)
+ , IEEE80211_NWID_LEN
+ , copy_essid(ssid, IEEE80211_NWID_LEN, idp, idlen)
, ssid
, ether_ntoa((const struct ether_addr *) sr->isr_bssid)
, ieee80211_mhz2ieee(sr->isr_freq, sr->isr_flags)
@@ -5399,16 +5400,21 @@ print_string(const u_int8_t *buf, int len)
{
int i;
int hasspc;
+ int utf8;
i = 0;
hasspc = 0;
+
+ setlocale(LC_CTYPE, "");
+ utf8 = strncmp("UTF-8", nl_langinfo(CODESET), 5) == 0;
+
for (; i < len; i++) {
- if (!isprint(buf[i]) && buf[i] != '\0')
+ if (!isprint(buf[i]) && buf[i] != '\0' && !utf8)
break;
if (isspace(buf[i]))
hasspc++;
}
- if (i == len) {
+ if (i == len || utf8) {
if (hasspc || len == 0 || buf[0] == '\0')
printf("\"%.*s\"", len, buf);
else
diff --git a/freebsd/sbin/pfctl/parse.c b/freebsd/sbin/pfctl/parse.c
index 76ca5c7e..83002a82 100644
--- a/freebsd/sbin/pfctl/parse.c
+++ b/freebsd/sbin/pfctl/parse.c
@@ -105,16 +105,19 @@
#ifdef __rtems__
#include "rtems-bsd-pfctl-namespace.h"
-#endif /* __rtems__ */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#ifdef __rtems__
-#include <machine/rtems-bsd-program.h>
+/* Provided by kernel-space modules */
#define pf_find_or_create_ruleset _bsd_pf_find_or_create_ruleset
#define pf_anchor_setup _bsd_pf_anchor_setup
#define pf_remove_if_empty_ruleset _bsd_pf_remove_if_empty_ruleset
+
+#include <machine/rtems-bsd-program.h>
#endif /* __rtems__ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define PFIOC_USE_LATEST
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -165,6 +168,7 @@ static u_int16_t returnicmpdefault =
static u_int16_t returnicmp6default =
(ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
static int blockpolicy = PFRULE_DROP;
+static int failpolicy = PFRULE_DROP;
static int require_order = 1;
static int default_statelock;
@@ -371,7 +375,7 @@ static struct queue_opts {
struct node_queue_bw queue_bwspec;
struct node_queue_opt scheduler;
int priority;
- int tbrsize;
+ unsigned int tbrsize;
int qlimit;
} queue_opts;
@@ -533,7 +537,7 @@ int parseport(char *, struct range *r, int);
(!((addr).iflags & PFI_AFLAG_NOALIAS) || \
!isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
-#line 537 "parse.c"
+#line 541 "parse.c"
/* compatibility with bison */
#ifdef YYPARSE_PARAM
@@ -633,69 +637,70 @@ extern int YYPARSE_DECL();
#define LIMIT 321
#define LOGINTERFACE 322
#define BLOCKPOLICY 323
-#define RANDOMID 324
-#define REQUIREORDER 325
-#define SYNPROXY 326
-#define FINGERPRINTS 327
-#define NOSYNC 328
-#define DEBUG 329
-#define SKIP 330
-#define HOSTID 331
-#define ANTISPOOF 332
-#define FOR 333
-#define INCLUDE 334
-#define BITMASK 335
-#define RANDOM 336
-#define SOURCEHASH 337
-#define ROUNDROBIN 338
-#define STATICPORT 339
-#define PROBABILITY 340
-#define ALTQ 341
-#define CBQ 342
-#define CODEL 343
-#define PRIQ 344
-#define HFSC 345
-#define FAIRQ 346
-#define BANDWIDTH 347
-#define TBRSIZE 348
-#define LINKSHARE 349
-#define REALTIME 350
-#define UPPERLIMIT 351
-#define QUEUE 352
-#define PRIORITY 353
-#define QLIMIT 354
-#define HOGS 355
-#define BUCKETS 356
-#define RTABLE 357
-#define TARGET 358
-#define INTERVAL 359
-#define LOAD 360
-#define RULESET_OPTIMIZATION 361
-#define PRIO 362
-#define STICKYADDRESS 363
-#define MAXSRCSTATES 364
-#define MAXSRCNODES 365
-#define SOURCETRACK 366
-#define GLOBAL 367
-#define RULE 368
-#define MAXSRCCONN 369
-#define MAXSRCCONNRATE 370
-#define OVERLOAD 371
-#define FLUSH 372
-#define SLOPPY 373
-#define TAGGED 374
-#define TAG 375
-#define IFBOUND 376
-#define FLOATING 377
-#define STATEPOLICY 378
-#define STATEDEFAULTS 379
-#define ROUTE 380
-#define SETTOS 381
-#define DIVERTTO 382
-#define DIVERTREPLY 383
-#define STRING 384
-#define NUMBER 385
-#define PORTBINARY 386
+#define FAILPOLICY 324
+#define RANDOMID 325
+#define REQUIREORDER 326
+#define SYNPROXY 327
+#define FINGERPRINTS 328
+#define NOSYNC 329
+#define DEBUG 330
+#define SKIP 331
+#define HOSTID 332
+#define ANTISPOOF 333
+#define FOR 334
+#define INCLUDE 335
+#define BITMASK 336
+#define RANDOM 337
+#define SOURCEHASH 338
+#define ROUNDROBIN 339
+#define STATICPORT 340
+#define PROBABILITY 341
+#define ALTQ 342
+#define CBQ 343
+#define CODEL 344
+#define PRIQ 345
+#define HFSC 346
+#define FAIRQ 347
+#define BANDWIDTH 348
+#define TBRSIZE 349
+#define LINKSHARE 350
+#define REALTIME 351
+#define UPPERLIMIT 352
+#define QUEUE 353
+#define PRIORITY 354
+#define QLIMIT 355
+#define HOGS 356
+#define BUCKETS 357
+#define RTABLE 358
+#define TARGET 359
+#define INTERVAL 360
+#define LOAD 361
+#define RULESET_OPTIMIZATION 362
+#define PRIO 363
+#define STICKYADDRESS 364
+#define MAXSRCSTATES 365
+#define MAXSRCNODES 366
+#define SOURCETRACK 367
+#define GLOBAL 368
+#define RULE 369
+#define MAXSRCCONN 370
+#define MAXSRCCONNRATE 371
+#define OVERLOAD 372
+#define FLUSH 373
+#define SLOPPY 374
+#define TAGGED 375
+#define TAG 376
+#define IFBOUND 377
+#define FLOATING 378
+#define STATEPOLICY 379
+#define STATEDEFAULTS 380
+#define ROUTE 381
+#define SETTOS 382
+#define DIVERTTO 383
+#define DIVERTREPLY 384
+#define STRING 385
+#define NUMBER 386
+#define PORTBINARY 387
#define YYERRCODE 256
typedef int YYINT;
static const YYINT pfctlylhs[] = { -1,
@@ -703,1354 +708,1362 @@ static const YYINT pfctlylhs[] = { -1,
0, 0, 0, 0, 0, 0, 0, 137, 150, 150,
150, 150, 150, 150, 18, 138, 138, 138, 138, 138,
138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
- 138, 77, 77, 80, 80, 81, 81, 82, 82, 147,
- 79, 79, 156, 156, 156, 156, 158, 157, 157, 143,
- 143, 143, 143, 144, 26, 139, 159, 126, 126, 128,
- 128, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 17, 17, 17, 148, 92, 92, 93, 93, 94, 94,
- 161, 120, 120, 122, 122, 121, 121, 11, 11, 149,
- 162, 129, 129, 131, 131, 130, 130, 130, 130, 145,
- 146, 163, 123, 123, 125, 125, 124, 124, 124, 124,
- 124, 113, 113, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 100, 100, 101, 102, 102, 103, 164,
- 106, 104, 104, 105, 105, 105, 105, 105, 105, 105,
- 165, 109, 107, 107, 108, 108, 108, 108, 108, 166,
- 112, 110, 110, 111, 111, 111, 96, 96, 96, 97,
- 97, 98, 142, 167, 114, 114, 116, 116, 115, 115,
+ 138, 138, 138, 77, 77, 80, 80, 81, 81, 82,
+ 82, 147, 79, 79, 156, 156, 156, 156, 158, 157,
+ 157, 143, 143, 143, 143, 144, 26, 139, 159, 126,
+ 126, 128, 128, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 17, 17, 17, 148, 92, 92, 93, 93,
+ 94, 94, 161, 120, 120, 122, 122, 121, 121, 11,
+ 11, 149, 162, 129, 129, 131, 131, 130, 130, 130,
+ 130, 145, 146, 163, 123, 123, 125, 125, 124, 124,
+ 124, 124, 124, 113, 113, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 100, 100, 101, 102, 102,
+ 103, 164, 106, 104, 104, 105, 105, 105, 105, 105,
+ 105, 105, 165, 109, 107, 107, 108, 108, 108, 108,
+ 108, 166, 112, 110, 110, 111, 111, 111, 96, 96,
+ 96, 97, 97, 98, 142, 167, 114, 114, 116, 116,
115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
- 115, 115, 115, 115, 115, 115, 115, 117, 117, 119,
- 119, 118, 30, 30, 13, 13, 23, 23, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 44, 44,
- 45, 45, 15, 15, 15, 88, 88, 87, 87, 87,
- 87, 87, 89, 89, 90, 90, 91, 91, 91, 91,
- 1, 1, 1, 2, 2, 3, 4, 16, 16, 16,
- 35, 35, 35, 36, 36, 37, 38, 38, 46, 46,
- 61, 61, 61, 62, 63, 63, 48, 48, 49, 49,
- 47, 47, 47, 152, 152, 50, 50, 50, 51, 51,
- 55, 55, 52, 52, 52, 53, 53, 53, 53, 53,
- 53, 53, 5, 5, 54, 64, 64, 65, 65, 66,
- 66, 66, 31, 33, 67, 67, 68, 68, 69, 69,
- 69, 8, 8, 70, 70, 71, 71, 72, 72, 72,
- 9, 9, 28, 27, 27, 27, 39, 39, 39, 39,
- 40, 40, 42, 42, 41, 41, 41, 43, 43, 43,
- 6, 6, 7, 7, 10, 10, 19, 19, 19, 22,
- 22, 83, 83, 83, 83, 20, 20, 20, 84, 84,
- 85, 85, 86, 86, 86, 86, 86, 86, 86, 86,
- 86, 86, 86, 76, 95, 95, 95, 14, 14, 32,
- 57, 57, 56, 56, 75, 75, 75, 34, 34, 168,
- 132, 132, 134, 134, 133, 133, 133, 133, 133, 133,
- 74, 74, 74, 25, 25, 25, 25, 24, 24, 140,
- 141, 78, 78, 135, 135, 136, 136, 58, 58, 59,
- 59, 60, 60, 73, 73, 73, 73, 73, 151, 151,
- 153, 153, 154, 155, 155, 160, 160, 12, 12, 21,
- 21, 21, 21, 21, 21,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 117,
+ 117, 119, 119, 118, 30, 30, 13, 13, 23, 23,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 44, 44, 45, 45, 15, 15, 15, 88, 88, 87,
+ 87, 87, 87, 87, 89, 89, 90, 90, 91, 91,
+ 91, 91, 1, 1, 1, 2, 2, 3, 4, 16,
+ 16, 16, 35, 35, 35, 36, 36, 37, 38, 38,
+ 46, 46, 61, 61, 61, 62, 63, 63, 48, 48,
+ 49, 49, 47, 47, 47, 152, 152, 50, 50, 50,
+ 51, 51, 55, 55, 52, 52, 52, 53, 53, 53,
+ 53, 53, 53, 53, 5, 5, 54, 64, 64, 65,
+ 65, 66, 66, 66, 31, 33, 67, 67, 68, 68,
+ 69, 69, 69, 8, 8, 70, 70, 71, 71, 72,
+ 72, 72, 9, 9, 28, 27, 27, 27, 39, 39,
+ 39, 39, 40, 40, 42, 42, 41, 41, 41, 43,
+ 43, 43, 6, 6, 7, 7, 10, 10, 19, 19,
+ 19, 22, 22, 83, 83, 83, 83, 20, 20, 20,
+ 84, 84, 85, 85, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 76, 95, 95, 95, 14,
+ 14, 32, 57, 57, 56, 56, 75, 75, 75, 34,
+ 34, 168, 132, 132, 134, 134, 133, 133, 133, 133,
+ 133, 133, 74, 74, 74, 25, 25, 25, 25, 24,
+ 24, 140, 141, 78, 78, 135, 135, 136, 136, 58,
+ 58, 59, 59, 60, 60, 73, 73, 73, 73, 73,
+ 151, 151, 153, 153, 154, 155, 155, 160, 160, 12,
+ 12, 21, 21, 21, 21, 21, 21,
};
static const YYINT pfctlylen[] = { 2,
0, 3, 2, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 4, 3, 2, 2, 3,
3, 3, 3, 3, 1, 3, 3, 3, 6, 3,
6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 1, 1, 2, 1, 2, 1, 1, 1, 3,
- 1, 0, 0, 2, 3, 3, 0, 5, 0, 10,
- 7, 7, 7, 5, 2, 8, 0, 2, 0, 2,
- 1, 1, 2, 2, 2, 1, 2, 1, 2, 3,
- 2, 2, 2, 5, 2, 5, 2, 4, 1, 3,
- 0, 2, 0, 2, 1, 1, 2, 1, 0, 5,
- 0, 2, 0, 2, 1, 1, 3, 4, 2, 5,
- 5, 0, 2, 0, 2, 1, 2, 2, 2, 1,
- 2, 1, 1, 1, 4, 1, 4, 1, 4, 1,
- 4, 1, 4, 1, 3, 1, 1, 3, 1, 0,
- 2, 1, 3, 2, 8, 2, 8, 2, 8, 1,
- 0, 2, 1, 3, 2, 6, 2, 2, 1, 0,
- 2, 1, 3, 2, 2, 1, 0, 1, 4, 2,
- 4, 1, 9, 0, 2, 0, 2, 1, 2, 2,
- 1, 1, 2, 2, 1, 1, 1, 1, 1, 2,
- 3, 2, 2, 2, 4, 1, 1, 4, 2, 3,
- 1, 1, 2, 6, 1, 1, 1, 2, 0, 1,
- 1, 5, 1, 1, 4, 4, 6, 1, 1, 1,
- 1, 1, 0, 1, 1, 0, 1, 0, 1, 1,
- 2, 2, 1, 4, 1, 3, 1, 1, 1, 2,
- 0, 2, 5, 2, 4, 2, 1, 0, 1, 1,
- 0, 2, 5, 2, 4, 1, 1, 1, 1, 3,
- 0, 2, 5, 1, 2, 4, 0, 2, 0, 2,
- 1, 3, 2, 2, 0, 1, 1, 4, 2, 0,
- 2, 4, 2, 2, 2, 1, 3, 3, 3, 1,
- 3, 3, 1, 1, 3, 1, 4, 2, 4, 1,
- 2, 3, 1, 1, 1, 4, 2, 4, 1, 2,
- 3, 1, 1, 1, 4, 2, 4, 1, 2, 3,
- 1, 1, 1, 4, 3, 2, 2, 5, 2, 5,
- 2, 4, 2, 4, 1, 3, 3, 1, 3, 3,
- 1, 1, 1, 1, 1, 1, 1, 2, 2, 1,
- 1, 2, 3, 3, 3, 0, 1, 2, 3, 0,
- 1, 3, 2, 1, 2, 2, 4, 5, 2, 1,
- 1, 1, 2, 2, 2, 4, 6, 0, 1, 1,
- 1, 4, 2, 4, 0, 2, 4, 0, 1, 0,
- 2, 0, 2, 1, 1, 1, 2, 1, 1, 1,
- 0, 2, 4, 0, 1, 2, 1, 3, 3, 10,
- 13, 0, 2, 0, 3, 0, 2, 1, 4, 2,
- 4, 1, 4, 0, 1, 3, 3, 3, 2, 2,
- 4, 2, 2, 4, 2, 1, 0, 1, 1, 1,
- 2, 2, 1, 2, 1,
+ 3, 3, 3, 1, 1, 2, 1, 2, 1, 1,
+ 1, 3, 1, 0, 0, 2, 3, 3, 0, 5,
+ 0, 10, 7, 7, 7, 5, 2, 8, 0, 2,
+ 0, 2, 1, 1, 2, 2, 2, 1, 2, 1,
+ 2, 3, 2, 2, 2, 5, 2, 5, 2, 4,
+ 1, 3, 0, 2, 0, 2, 1, 1, 2, 1,
+ 0, 5, 0, 2, 0, 2, 1, 1, 3, 4,
+ 2, 5, 5, 0, 2, 0, 2, 1, 2, 2,
+ 2, 1, 2, 1, 1, 1, 4, 1, 4, 1,
+ 4, 1, 4, 1, 4, 1, 3, 1, 1, 3,
+ 1, 0, 2, 1, 3, 2, 8, 2, 8, 2,
+ 8, 1, 0, 2, 1, 3, 2, 6, 2, 2,
+ 1, 0, 2, 1, 3, 2, 2, 1, 0, 1,
+ 4, 2, 4, 1, 9, 0, 2, 0, 2, 1,
+ 2, 2, 1, 1, 2, 2, 1, 1, 1, 1,
+ 1, 2, 3, 2, 2, 2, 4, 1, 1, 4,
+ 2, 3, 1, 1, 2, 6, 1, 1, 1, 2,
+ 0, 1, 1, 5, 1, 1, 4, 4, 6, 1,
+ 1, 1, 1, 1, 0, 1, 1, 0, 1, 0,
+ 1, 1, 2, 2, 1, 4, 1, 3, 1, 1,
+ 1, 2, 0, 2, 5, 2, 4, 2, 1, 0,
+ 1, 1, 0, 2, 5, 2, 4, 1, 1, 1,
+ 1, 3, 0, 2, 5, 1, 2, 4, 0, 2,
+ 0, 2, 1, 3, 2, 2, 0, 1, 1, 4,
+ 2, 0, 2, 4, 2, 2, 2, 1, 3, 3,
+ 3, 1, 3, 3, 1, 1, 3, 1, 4, 2,
+ 4, 1, 2, 3, 1, 1, 1, 4, 2, 4,
+ 1, 2, 3, 1, 1, 1, 4, 2, 4, 1,
+ 2, 3, 1, 1, 1, 4, 3, 2, 2, 5,
+ 2, 5, 2, 4, 2, 4, 1, 3, 3, 1,
+ 3, 3, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 1, 1, 2, 3, 3, 3, 0, 1, 2,
+ 3, 0, 1, 3, 2, 1, 2, 2, 4, 5,
+ 2, 1, 1, 1, 2, 2, 2, 4, 6, 0,
+ 1, 1, 1, 4, 2, 4, 0, 2, 4, 0,
+ 1, 0, 2, 0, 2, 1, 1, 1, 2, 1,
+ 1, 1, 0, 2, 4, 0, 1, 2, 1, 3,
+ 3, 10, 13, 0, 2, 0, 3, 0, 2, 1,
+ 4, 2, 4, 1, 4, 0, 1, 3, 3, 3,
+ 2, 2, 4, 2, 2, 4, 2, 1, 0, 1,
+ 1, 1, 2, 2, 1, 2, 1,
};
static const YYINT pfctlydefred[] = { 0,
- 0, 0, 0, 0, 207, 0, 379, 0, 0, 0,
+ 0, 0, 0, 0, 209, 0, 381, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 19, 0,
- 0, 0, 0, 0, 0, 17, 218, 0, 0, 0,
- 210, 208, 0, 51, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 17, 220, 0, 0, 0,
+ 212, 210, 0, 53, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 18, 0, 0, 0,
- 0, 0, 65, 0, 0, 0, 224, 225, 0, 0,
- 0, 2, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 24, 16, 22, 21, 23, 20,
- 0, 0, 0, 0, 0, 44, 0, 0, 0, 26,
- 0, 0, 0, 28, 0, 0, 30, 43, 42, 32,
- 35, 34, 438, 439, 36, 37, 39, 40, 294, 293,
- 33, 27, 25, 350, 351, 38, 0, 364, 0, 0,
- 0, 0, 0, 0, 372, 0, 370, 371, 0, 361,
- 0, 232, 0, 0, 231, 0, 98, 242, 0, 0,
- 0, 0, 0, 49, 48, 50, 0, 0, 409, 407,
- 408, 0, 0, 249, 250, 0, 0, 0, 219, 220,
- 0, 221, 222, 0, 0, 227, 0, 0, 0, 0,
- 430, 429, 0, 0, 433, 0, 363, 365, 369, 348,
- 349, 366, 0, 0, 373, 436, 0, 0, 237, 238,
- 239, 0, 235, 247, 0, 0, 89, 85, 0, 0,
- 246, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 120, 116, 0, 0, 0, 46, 406, 0, 0,
- 0, 0, 0, 0, 215, 0, 216, 100, 0, 0,
- 0, 0, 0, 274, 0, 0, 0, 0, 0, 0,
- 362, 240, 234, 0, 0, 0, 84, 0, 0, 0,
- 172, 0, 110, 168, 0, 160, 0, 140, 151, 122,
- 123, 117, 121, 118, 119, 115, 111, 64, 0, 425,
- 0, 0, 0, 0, 257, 258, 0, 252, 256, 0,
- 259, 0, 0, 0, 212, 0, 0, 106, 0, 105,
- 0, 0, 0, 0, 0, 432, 29, 0, 435, 31,
- 0, 367, 0, 236, 0, 0, 90, 0, 0, 96,
- 95, 0, 243, 0, 244, 0, 136, 0, 134, 0,
- 0, 139, 0, 137, 0, 0, 0, 0, 0, 418,
- 0, 0, 422, 0, 0, 0, 0, 0, 276, 0,
- 0, 0, 268, 0, 277, 0, 0, 0, 0, 0,
- 217, 109, 0, 104, 0, 0, 61, 62, 63, 0,
- 0, 0, 368, 86, 0, 87, 374, 97, 94, 0,
- 0, 0, 125, 0, 133, 0, 0, 166, 0, 162,
- 127, 0, 129, 0, 0, 0, 150, 0, 142, 131,
- 0, 0, 0, 159, 0, 153, 0, 0, 0, 426,
- 0, 428, 427, 0, 0, 0, 0, 440, 0, 0,
- 0, 0, 0, 273, 296, 304, 0, 284, 285, 0,
- 0, 0, 0, 283, 0, 0, 413, 0, 0, 264,
- 0, 262, 0, 260, 0, 107, 0, 0, 0, 417,
- 431, 434, 358, 0, 245, 169, 0, 170, 135, 165,
- 164, 0, 138, 0, 144, 0, 146, 0, 148, 0,
- 0, 155, 157, 158, 0, 0, 0, 0, 0, 395,
- 396, 0, 398, 399, 400, 394, 0, 0, 253, 0,
- 254, 0, 441, 442, 444, 301, 0, 0, 0, 0,
- 0, 0, 0, 0, 272, 0, 0, 0, 270, 66,
- 0, 281, 108, 0, 0, 0, 88, 0, 163, 0,
- 0, 0, 143, 0, 154, 0, 0, 420, 423, 0,
- 419, 397, 389, 393, 173, 0, 0, 0, 302, 278,
- 287, 288, 289, 295, 292, 291, 415, 0, 0, 0,
- 0, 72, 0, 0, 0, 0, 78, 0, 0, 0,
- 76, 71, 0, 0, 57, 60, 0, 0, 0, 0,
- 0, 187, 0, 186, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 196, 0, 181, 182, 188,
- 185, 189, 178, 0, 197, 171, 0, 0, 0, 0,
- 279, 0, 0, 255, 297, 0, 298, 0, 381, 0,
- 410, 265, 263, 0, 73, 81, 83, 82, 74, 77,
- 79, 345, 346, 75, 0, 70, 282, 0, 326, 323,
- 0, 0, 341, 342, 0, 0, 327, 343, 344, 0,
- 0, 329, 0, 0, 352, 312, 313, 0, 0, 0,
- 179, 305, 321, 322, 0, 0, 0, 180, 314, 184,
- 0, 0, 202, 199, 0, 205, 206, 192, 375, 0,
- 193, 183, 190, 0, 194, 303, 0, 177, 0, 0,
- 0, 0, 0, 421, 0, 0, 0, 0, 80, 53,
- 325, 0, 0, 0, 0, 0, 0, 353, 354, 0,
- 0, 310, 0, 0, 319, 203, 0, 201, 0, 355,
- 0, 0, 191, 0, 0, 0, 156, 0, 299, 0,
- 0, 387, 380, 266, 0, 324, 0, 0, 336, 337,
- 0, 0, 339, 340, 0, 0, 0, 311, 0, 0,
- 320, 0, 198, 0, 376, 0, 195, 0, 0, 0,
- 0, 411, 383, 382, 0, 54, 58, 0, 0, 328,
- 0, 331, 330, 0, 333, 359, 306, 0, 307, 315,
- 0, 316, 0, 200, 0, 145, 147, 149, 0, 0,
- 55, 56, 0, 0, 0, 0, 0, 377, 0, 384,
- 332, 334, 308, 317, 204, 403,
+ 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
+ 0, 0, 0, 67, 0, 0, 0, 226, 227, 0,
+ 0, 0, 2, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 24, 16, 22, 21, 23,
+ 20, 0, 0, 0, 0, 0, 46, 0, 0, 0,
+ 26, 0, 0, 0, 28, 0, 0, 30, 45, 44,
+ 32, 35, 34, 37, 36, 440, 441, 38, 39, 41,
+ 42, 296, 295, 33, 27, 25, 352, 353, 40, 0,
+ 366, 0, 0, 0, 0, 0, 0, 374, 0, 372,
+ 373, 0, 363, 0, 234, 0, 0, 233, 0, 100,
+ 244, 0, 0, 0, 0, 0, 51, 50, 52, 0,
+ 0, 411, 409, 410, 0, 0, 251, 252, 0, 0,
+ 0, 221, 222, 0, 223, 224, 0, 0, 229, 0,
+ 0, 0, 0, 432, 431, 0, 0, 435, 0, 365,
+ 367, 371, 350, 351, 368, 0, 0, 375, 438, 0,
+ 0, 239, 240, 241, 0, 237, 249, 0, 0, 91,
+ 87, 0, 0, 248, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 122, 118, 0, 0, 0, 48,
+ 408, 0, 0, 0, 0, 0, 0, 217, 0, 218,
+ 102, 0, 0, 0, 0, 0, 276, 0, 0, 0,
+ 0, 0, 0, 364, 242, 236, 0, 0, 0, 86,
+ 0, 0, 0, 174, 0, 112, 170, 0, 162, 0,
+ 142, 153, 124, 125, 119, 123, 120, 121, 117, 113,
+ 66, 0, 427, 0, 0, 0, 0, 259, 260, 0,
+ 254, 258, 0, 261, 0, 0, 0, 214, 0, 0,
+ 108, 0, 107, 0, 0, 0, 0, 0, 434, 29,
+ 0, 437, 31, 0, 369, 0, 238, 0, 0, 92,
+ 0, 0, 98, 97, 0, 245, 0, 246, 0, 138,
+ 0, 136, 0, 0, 141, 0, 139, 0, 0, 0,
+ 0, 0, 420, 0, 0, 424, 0, 0, 0, 0,
+ 0, 278, 0, 0, 0, 270, 0, 279, 0, 0,
+ 0, 0, 0, 219, 111, 0, 106, 0, 0, 63,
+ 64, 65, 0, 0, 0, 370, 88, 0, 89, 376,
+ 99, 96, 0, 0, 0, 127, 0, 135, 0, 0,
+ 168, 0, 164, 129, 0, 131, 0, 0, 0, 152,
+ 0, 144, 133, 0, 0, 0, 161, 0, 155, 0,
+ 0, 0, 428, 0, 430, 429, 0, 0, 0, 0,
+ 442, 0, 0, 0, 0, 0, 275, 298, 306, 0,
+ 286, 287, 0, 0, 0, 0, 285, 0, 0, 415,
+ 0, 0, 266, 0, 264, 0, 262, 0, 109, 0,
+ 0, 0, 419, 433, 436, 360, 0, 247, 171, 0,
+ 172, 137, 167, 166, 0, 140, 0, 146, 0, 148,
+ 0, 150, 0, 0, 157, 159, 160, 0, 0, 0,
+ 0, 0, 397, 398, 0, 400, 401, 402, 396, 0,
+ 0, 255, 0, 256, 0, 443, 444, 446, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 274, 0, 0,
+ 0, 272, 68, 0, 283, 110, 0, 0, 0, 90,
+ 0, 165, 0, 0, 0, 145, 0, 156, 0, 0,
+ 422, 425, 0, 421, 399, 391, 395, 175, 0, 0,
+ 0, 304, 280, 289, 290, 291, 297, 294, 293, 417,
+ 0, 0, 0, 0, 74, 0, 0, 0, 0, 80,
+ 0, 0, 0, 78, 73, 0, 0, 59, 62, 0,
+ 0, 0, 0, 0, 189, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 198, 0,
+ 183, 184, 190, 187, 191, 180, 0, 199, 173, 0,
+ 0, 0, 0, 281, 0, 0, 257, 299, 0, 300,
+ 0, 383, 0, 412, 267, 265, 0, 75, 83, 85,
+ 84, 76, 79, 81, 347, 348, 77, 0, 72, 284,
+ 0, 328, 325, 0, 0, 343, 344, 0, 0, 329,
+ 345, 346, 0, 0, 331, 0, 0, 354, 314, 315,
+ 0, 0, 0, 181, 307, 323, 324, 0, 0, 0,
+ 182, 316, 186, 0, 0, 204, 201, 0, 207, 208,
+ 194, 377, 0, 195, 185, 192, 0, 196, 305, 0,
+ 179, 0, 0, 0, 0, 0, 423, 0, 0, 0,
+ 0, 82, 55, 327, 0, 0, 0, 0, 0, 0,
+ 355, 356, 0, 0, 312, 0, 0, 321, 205, 0,
+ 203, 0, 357, 0, 0, 193, 0, 0, 0, 158,
+ 0, 301, 0, 0, 389, 382, 268, 0, 326, 0,
+ 0, 338, 339, 0, 0, 341, 342, 0, 0, 0,
+ 313, 0, 0, 322, 0, 200, 0, 378, 0, 197,
+ 0, 0, 0, 0, 413, 385, 384, 0, 56, 60,
+ 0, 0, 330, 0, 333, 332, 0, 335, 361, 308,
+ 0, 309, 317, 0, 318, 0, 202, 0, 147, 149,
+ 151, 0, 0, 57, 58, 0, 0, 0, 0, 0,
+ 379, 0, 386, 334, 336, 310, 319, 206, 405,
};
static const YYINT pfctlydgoto[] = { 2,
- 79, 279, 168, 227, 141, 656, 661, 669, 676, 644,
- 372, 135, 688, 21, 89, 186, 581, 142, 157, 393,
- 442, 158, 22, 23, 179, 24, 608, 652, 52, 683,
- 695, 742, 443, 552, 252, 435, 308, 309, 609, 747,
- 657, 751, 662, 191, 194, 312, 373, 313, 464, 374,
- 547, 375, 454, 455, 468, 741, 630, 363, 498, 364,
- 379, 462, 571, 444, 557, 445, 671, 756, 672, 678,
- 759, 679, 304, 772, 569, 340, 130, 377, 55, 57,
- 176, 446, 611, 718, 159, 160, 75, 197, 76, 222,
- 223, 164, 335, 228, 612, 283, 401, 284, 242, 348,
- 349, 353, 354, 418, 419, 355, 425, 426, 357, 409,
- 410, 350, 292, 535, 613, 614, 615, 684, 729, 277,
- 341, 342, 170, 243, 244, 530, 582, 583, 258, 320,
- 321, 430, 506, 507, 459, 387, 25, 26, 27, 28,
+ 80, 282, 171, 230, 144, 659, 664, 672, 679, 647,
+ 375, 138, 691, 21, 90, 189, 584, 145, 160, 396,
+ 445, 161, 22, 23, 182, 24, 611, 655, 52, 686,
+ 698, 745, 446, 555, 255, 438, 311, 312, 612, 750,
+ 660, 754, 665, 194, 197, 315, 376, 316, 467, 377,
+ 550, 378, 457, 458, 471, 744, 633, 366, 501, 367,
+ 382, 465, 574, 447, 560, 448, 674, 759, 675, 681,
+ 762, 682, 307, 775, 572, 343, 131, 380, 55, 57,
+ 179, 449, 614, 721, 162, 163, 76, 200, 77, 225,
+ 226, 167, 338, 231, 615, 286, 404, 287, 245, 351,
+ 352, 356, 357, 421, 422, 358, 428, 429, 360, 412,
+ 413, 353, 295, 538, 616, 617, 618, 687, 732, 280,
+ 344, 345, 173, 246, 247, 533, 585, 586, 261, 323,
+ 324, 433, 509, 510, 462, 390, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 3,
- 124, 204, 266, 127, 268, 745, 586, 648, 531, 217,
- 278, 259, 171, 356, 358, 351, 536, 431,
+ 125, 207, 269, 128, 271, 748, 589, 651, 534, 220,
+ 281, 262, 174, 359, 361, 354, 539, 434,
};
-static const YYINT pfctlysindex[] = { -48,
- 0, 118, 1618, 71, 0, 604, 0, 35, -280, -218,
- -218, -218, 1838, -9, -163, -21, -133, -49, 418, 0,
- 680, 86, -21, 86, 504, 519, 525, 569, 580, 610,
- 618, 634, 646, 651, 664, 670, 684, 711, 0, 714,
- 424, 716, 755, 760, 764, 0, 0, 484, 508, 600,
- 0, 0, 230, 0, 86, -218, -21, -21, -21, 313,
- -93, -72, -226, -66, -230, 357, 375, -21, 428, -218,
- 371, 1487, 738, 523, 471, 554, 0, 27, 0, -21,
- -218, 475, 0, 21, 21, 21, 0, 0, -9, 633,
- -9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+static const YYINT pfctlysindex[] = { -37,
+ 0, 118, 1390, 90, 0, 551, 0, 60, -179, -170,
+ -170, -170, 2646, 237, -158, -44, -139, 1, 205, 0,
+ 504, 372, -44, 372, 315, 321, 331, 338, 405, 465,
+ 480, 501, 578, 618, 637, 645, 660, 664, 0, 681,
+ 577, 687, 700, 719, 731, 0, 0, 571, 626, 736,
+ 0, 0, 158, 0, 372, -170, -44, -44, -44, 164,
+ -48, -79, -184, -196, -61, -269, 403, 411, -44, 317,
+ -170, 371, 1550, 765, 553, 486, 565, 0, 52, 0,
+ -44, -170, 380, 0, -154, -154, -154, 0, 0, 237,
+ 485, 237, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 534, 387, 423, 804, 611, 0, 485, 485, 485,
+ 0, 484, 492, 888, 0, 516, 888, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 516, 532, 535, 759, 565, 0, 633, 633, 633, 0,
- 481, 492, 871, 0, 529, 871, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 518,
+ 0, 541, 561, 467, 563, 574, 840, 0, 584, 0,
+ 0, 893, 0, 374, 0, -21, 485, 0, 888, 0,
+ 0, 558, 663, 987, 0, 684, 0, 0, 0, 380,
+ 553, 0, 0, 0, -44, -44, 0, 0, 740, -44,
+ 636, 0, 0, 64, 0, 0, 1008, 0, 0, -44,
+ 740, 740, 740, 0, 0, 888, 123, 0, 665, 0,
+ 0, 0, 0, 0, 0, 1009, 679, 0, 0, 1550,
+ -170, 0, 0, 0, 188, 0, 0, 888, 558, 0,
+ 0, 0, 1022, 0, -68, 1031, 1037, 1038, 1039, 1040,
+ 488, 695, 696, 698, 0, 0, 987, -68, -170, 0,
+ 0, 485, 670, -96, 42, 485, 1029, 0, 423, 0,
+ 0, -86, 485, 42, 42, 42, 0, 888, 57, 888,
+ 92, 699, 1025, 0, 0, 0, 374, 54, 1052, 0,
+ -232, 96, 888, 0, 888, 0, 0, 709, 0, 713,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 555, 0, 559, 567,
- 558, 577, 587, 833, 0, 590, 0, 0, 857, 0,
- 347, 0, 19, 633, 0, 871, 0, 0, 611, 655,
- 1735, 0, 744, 0, 0, 0, 475, 523, 0, 0,
- 0, -21, -21, 0, 0, 747, -21, 632, 0, 0,
- 679, 0, 0, 988, 0, 0, -21, 747, 747, 747,
- 0, 0, 871, -96, 0, 657, 0, 0, 0, 0,
- 0, 0, 1006, 678, 0, 0, 1487, -218, 0, 0,
- 0, 689, 0, 0, 871, 611, 0, 0, 0, 1031,
- 0, -57, 1028, 1033, 1035, 1050, 1052, 550, 713, 775,
- 776, 0, 0, 1735, -57, -218, 0, 0, 633, 382,
- -47, -187, 633, 1067, 0, 535, 0, 0, -81, 633,
- -187, -187, -187, 0, 871, 13, 871, 49, 782, 1034,
- 0, 0, 0, 347, 34, 1088, 0, -97, 82, 871,
- 0, 871, 0, 0, 789, 0, 790, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 747, 0,
- 39, 39, 39, 633, 0, 0, 871, 0, 0, 192,
- 0, 800, 914, 747, 0, 1140, 798, 0, 871, 0,
- -81, 747, 826, 826, 826, 0, 0, -96, 0, 0,
- 657, 0, 817, 0, 97, 871, 0, 807, 809, 0,
- 0, -97, 0, 1031, 0, 808, 0, 731, 0, 1159,
- 410, 0, 773, 0, 1160, 483, 1163, 352, 930, 0,
- 871, 821, 0, 0, 0, 0, 747, 562, 0, 83,
- 871, 246, 0, 923, 0, 824, 1031, -45, 946, -187,
- 0, 0, 28, 0, -187, 837, 0, 0, 0, 871,
- 871, 856, 0, 0, 34, 0, 0, 0, 0, 871,
- 108, 871, 0, 789, 0, 428, 428, 0, 857, 0,
- 0, 790, 0, 24, 187, 214, 0, 857, 0, 0,
- 224, 550, 428, 0, 857, 0, 32, 56, 190, 0,
- 765, 0, 0, -187, 136, 871, 871, 0, 1157, 1166,
- 1168, 475, 840, 0, 0, 0, 32, 0, 0, 538,
- 1183, 848, 849, 0, 1187, 83, 0, 864, 826, 0,
- 871, 0, 192, 0, 0, 0, 871, 137, 0, 0,
- 0, 0, 0, 871, 0, 0, 808, 0, 0, 0,
- 0, 410, 0, 550, 0, 550, 0, 550, 0, 483,
- 550, 0, 0, 0, 352, 972, 871, 155, 1200, 0,
- 0, -218, 0, 0, 0, 0, 765, 0, 0, 562,
- 0, 61, 0, 0, 0, 0, 475, 200, 858, 860,
- 863, 1210, 1190, 868, 0, -218, 966, 874, 0, 0,
- 1405, 0, 0, 32, 1132, 4400, 0, 871, 0, 857,
- 857, 857, 0, 428, 0, 32, 800, 0, 0, 56,
- 0, 0, 0, 0, 0, 871, 363, 871, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 417, 0, 871,
- 385, 0, 876, 712, 877, 875, 0, 879, 570, 891,
- 0, 0, 1405, 871, 0, 0, 235, 361, 376, 985,
- 990, 0, 994, 0, 135, 283, 570, 37, 995, 575,
- 69, 890, 895, -218, 595, 0, 907, 0, 0, 0,
- 0, 0, 0, 4400, 0, 0, 902, 903, 904, 550,
- 0, 1031, 871, 0, 0, 61, 0, 871, 0, 1011,
- 0, 0, 0, 874, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -218, 0, 0, 1280, 0, 0,
- 912, 1250, 0, 0, 871, 1018, 0, 0, 0, 871,
- 1023, 0, 1264, 1264, 0, 0, 0, 871, 919, 630,
- 0, 0, 0, 0, 871, 920, 659, 0, 0, 0,
- -16, 948, 0, 0, 1264, 0, 0, 0, 0, 927,
- 0, 0, 0, 1029, 0, 0, -218, 0, 857, 857,
- 857, 1271, 826, 0, 871, 190, 475, 871, 0, 0,
- 0, 912, 661, 665, 687, 697, 1487, 0, 0, 116,
- 630, 0, 158, 659, 0, 0, 929, 0, 812, 0,
- 813, 475, 0, 550, 550, 550, 0, 1030, 0, 871,
- 429, 0, 0, 0, 654, 0, 452, 871, 0, 0,
- 472, 871, 0, 0, 862, 501, 871, 0, 518, 871,
- 0, 857, 0, 948, 0, 931, 0, 1276, 1278, 1281,
- 190, 0, 0, 0, 190, 0, 0, 1311, 1313, 0,
- 661, 0, 0, 687, 0, 0, 0, 116, 0, 0,
- 158, 0, 941, 0, 1287, 0, 0, 0, 1047, 871,
- 0, 0, 871, 871, 871, 871, 1291, 0, 475, 0,
- 0, 0, 0, 0, 0, 0,
+ 0, 740, 0, 6, 6, 6, 485, 0, 0, 888,
+ 0, 0, 229, 0, 727, 833, 740, 0, 1066, 729,
+ 0, 888, 0, -86, 740, 759, 759, 759, 0, 0,
+ 123, 0, 0, 665, 0, 751, 0, 106, 888, 0,
+ 733, 742, 0, 0, -232, 0, 1022, 0, 744, 0,
+ 298, 0, 1089, 533, 0, 602, 0, 1091, 362, 1092,
+ 412, 871, 0, 888, 761, 0, 0, 0, 0, 740,
+ 495, 0, 110, 888, 165, 0, 868, 0, 771, 1022,
+ -52, 889, 42, 0, 0, 211, 0, 42, 772, 0,
+ 0, 0, 888, 888, 792, 0, 0, 54, 0, 0,
+ 0, 0, 888, 191, 888, 0, 709, 0, 317, 317,
+ 0, 893, 0, 0, 713, 0, 33, 39, 44, 0,
+ 893, 0, 0, 113, 488, 317, 0, 893, 0, 10,
+ 56, 137, 0, 883, 0, 0, 42, 213, 888, 888,
+ 0, 1104, 1106, 1107, 380, 786, 0, 0, 0, 10,
+ 0, 0, 592, 1128, 793, 797, 0, 1130, 110, 0,
+ 808, 759, 0, 888, 0, 229, 0, 0, 0, 888,
+ 215, 0, 0, 0, 0, 0, 888, 0, 0, 744,
+ 0, 0, 0, 0, 533, 0, 488, 0, 488, 0,
+ 488, 0, 362, 488, 0, 0, 0, 412, 919, 888,
+ 219, 1148, 0, 0, -170, 0, 0, 0, 0, 883,
+ 0, 0, 495, 0, 28, 0, 0, 0, 0, 380,
+ 221, 806, 811, 815, 1153, 1140, 819, 0, -170, 922,
+ 826, 0, 0, 1406, 0, 0, 10, 1093, 4438, 0,
+ 888, 0, 893, 893, 893, 0, 317, 0, 10, 727,
+ 0, 0, 56, 0, 0, 0, 0, 0, 888, 471,
+ 888, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 77, 0, 888, 494, 0, 842, 598, 843, 827, 0,
+ 845, 510, 851, 0, 0, 1406, 888, 0, 0, 241,
+ -91, -82, 951, 952, 0, 953, 0, 119, 124, 510,
+ -16, 955, 538, 58, 857, 860, -170, 545, 0, 879,
+ 0, 0, 0, 0, 0, 0, 4438, 0, 0, 870,
+ 873, 874, 488, 0, 1022, 888, 0, 0, 28, 0,
+ 888, 0, 973, 0, 0, 0, 826, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -170, 0, 0,
+ 1253, 0, 0, 890, 1221, 0, 0, 888, 984, 0,
+ 0, 0, 888, 994, 0, 1237, 1237, 0, 0, 0,
+ 888, 891, 554, 0, 0, 0, 0, 888, 896, 589,
+ 0, 0, 0, -17, 929, 0, 0, 1237, 0, 0,
+ 0, 0, 900, 0, 0, 0, 1007, 0, 0, -170,
+ 0, 893, 893, 893, 1252, 759, 0, 888, 137, 380,
+ 888, 0, 0, 0, 890, 601, 605, 614, 624, 1550,
+ 0, 0, 134, 554, 0, 150, 589, 0, 0, 910,
+ 0, 623, 0, 667, 380, 0, 488, 488, 488, 0,
+ 1010, 0, 888, 513, 0, 0, 0, 794, 0, 523,
+ 888, 0, 0, 527, 888, 0, 0, 686, 568, 888,
+ 0, 579, 888, 0, 893, 0, 929, 0, 915, 0,
+ 1256, 1260, 1261, 137, 0, 0, 0, 137, 0, 0,
+ 1297, 1299, 0, 601, 0, 0, 614, 0, 0, 0,
+ 134, 0, 0, 150, 0, 925, 0, 1271, 0, 0,
+ 0, 1033, 888, 0, 0, 888, 888, 888, 888, 1272,
+ 0, 380, 0, 0, 0, 0, 0, 0, 0,
};
-static const YYINT pfctlyrindex[] = { 36,
- 0, 723, 741, 0, 0, 1644, 0, 0, 2743, 0,
- 0, 0, 0, 1000, 0, 1156, 0, 0, 0, 0,
- 0, 2290, 2701, 4182, 0, 0, 0, 0, 0, 0,
+static const YYINT pfctlyrindex[] = { 70,
+ 0, 539, 717, 0, 0, 1829, 0, 0, 2866, 0,
+ 0, 0, 0, 980, 0, 1609, 0, 0, 0, 0,
+ 0, 2469, 4357, 2079, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1898, 2022, 2148,
+ 0, 0, 0, 0, 3145, 1454, 5, 5, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1305, 0,
+ 0, 0, 0, 1318, 1585, 0, 1704, 0, 933, 1728,
+ 1204, 0, 0, 0, 4303, 4303, 710, 0, 0, 2913,
+ 912, 4230, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1712, 1836, 1959,
- 0, 0, 0, 0, 3033, 1283, 1115, 1115, 1115, 0,
- 0, 0, 0, 0, 0, 0, 0, 1331, 0, 0,
- 0, 0, 1155, 1394, 0, 1521, 0, 963, 1697, 1027,
- 0, 0, 0, 4235, 4235, 878, 0, 0, 2811, 4313,
- 4202, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3192, 0, 46, 46, 46,
+ 0, 0, 0, 210, 0, 0, 934, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 3144, 0, 629, 629, 629, 0,
- 0, 0, 263, 0, 0, 964, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 115, 0, 0, 0, 0, 0, 0,
+ 0, 777, 0, 0, 0, 0, 50, 0, -26, 0,
+ 0, 0, 0, 0, 1217, 0, 0, 0, 0, 1310,
+ 4347, 0, 0, 0, 745, 3025, 0, 0, 2231, 4278,
+ 0, 0, 0, 647, 0, 0, 0, 8, 0, 3315,
+ 301, 301, 301, 0, 0, 1385, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 289, 0, 0, 0, 0, 0, 0, 0, 793, 0,
- 0, 0, 0, 15, 0, -23, 0, 0, 0, 0,
- 0, 1055, 0, 0, 0, 0, 1339, 4267, 0, 0,
- 0, 533, 2922, 0, 0, 4320, 3576, 0, 0, 0,
- 710, 0, 0, 0, 2, 0, 3255, 219, 219, 219,
- 0, 0, 1481, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 503, 0, 0, 74, 0, 0,
+ 0, 112, 933, 0, 1312, 260, 714, 1030, 1135, 1183,
+ 0, 0, 0, 0, 0, 0, 7, 1312, 0, 0,
+ 0, -43, 3362, 0, 62, 639, 0, 0, 0, 0,
+ 0, 0, 3526, -4, -4, -4, 0, 509, 240, 91,
+ 938, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -12, -13, 0, 934, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 459, 0, 0, 78, 0, 0, 0, 30, 963,
- 0, 1351, 258, 438, 795, 992, 1012, 0, 0, 0,
- 0, 0, 0, 6, 1351, 0, 0, 0, -204, 3323,
- 0, 505, 2139, 0, 0, 0, 0, 0, 0, 3459,
- 73, 73, 73, 0, 574, 273, -27, 978, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -13, -18,
- 0, 964, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1096, 0,
- 0, 0, 0, 3528, 0, 0, 733, 0, 0, 510,
- 0, 154, 2167, 8, 0, 0, 0, 0, 1352, 0,
- 664, 3645, 1357, 1357, 1357, 0, 0, 0, 0, 0,
- 0, 0, 572, 0, 80, -17, 0, 0, 0, 0,
- 0, 504, 0, 963, 0, 0, 0, 978, 0, 0,
- 0, 0, 978, 0, 0, 0, 0, 0, 0, 0,
- 78, 0, 0, 2499, 2499, 2499, 3697, 0, 0, 0,
- 59, 0, 0, 2057, 0, 0, 748, 0, 2388, 2543,
- 0, 0, 510, 0, 3795, 0, 0, 0, 0, 574,
- -27, 690, 0, 0, 0, 0, 0, 0, 0, -18,
- 978, -27, 0, 0, 0, 0, 0, 0, 287, 0,
- 0, 0, 0, 0, 0, 0, 0, 285, 0, 0,
- 0, 0, 0, 0, 514, 0, 510, 0, 0, 0,
- 0, 0, 0, 3846, 710, 142, 175, 0, 0, 739,
- 749, 0, 695, 0, 0, 0, 510, 0, 0, 414,
- 0, 0, 0, 0, 547, 0, 0, 0, 195, 0,
- 964, 0, 510, 0, 882, 0, 1184, 704, 3935, 0,
- 0, 0, 0, -17, 0, 0, 0, 0, 0, 0,
+ 0, 1058, 0, 0, 0, 0, 3570, 0, 0, 651,
+ 0, 0, 245, 0, 109, 2346, 928, 0, 0, 0,
+ 0, 1239, 0, 645, 3690, 1319, 1319, 1319, 0, 0,
+ 0, 0, 0, 0, 0, 208, 0, 87, 67, 0,
+ 0, 0, 0, 0, 321, 0, 933, 0, 0, 0,
+ 938, 0, 0, 0, 0, 938, 0, 0, 0, 0,
+ 0, 0, 0, 74, 0, 0, 2622, 2622, 2622, 3737,
+ 0, 0, 0, 620, 0, 0, 2247, 0, 0, 507,
+ 0, 2510, 1941, 0, 0, 245, 0, 3837, 0, 0,
+ 0, 0, 509, 91, 291, 0, 0, 0, 0, 0,
+ 0, 0, -13, 938, 91, 0, 0, 0, 0, 0,
+ 0, 557, 0, 0, 0, 0, 0, 0, 0, 0,
+ 266, 0, 0, 0, 0, 0, 0, 376, 0, 245,
+ 0, 0, 0, 0, 0, 0, 3881, 647, 143, 176,
+ 0, 0, 653, 656, 0, 690, 0, 0, 0, 245,
+ 0, 0, 417, 0, 0, 0, 0, 550, 0, 0,
+ 0, 617, 0, 934, 0, 245, 0, 1458, 0, 734,
+ 839, 3968, 0, 0, 0, 0, 67, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 23, -17, 80, 0, 0,
- 0, 2610, 0, 0, 0, 0, 3391, 4079, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 704, 0, 0,
- 0, 0, 0, 0, 0, 0, 75, 0, 0, 0,
- 1004, 0, 0, 510, 1358, 1004, 0, -27, 0, 999,
- 999, 999, 0, 0, 0, 510, -1, 0, 0, 0,
- 0, 0, 0, 0, 0, 142, 240, 10, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 229, -27,
- 978, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 11, 1184, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -5, 67,
+ 87, 0, 0, 0, 2742, 0, 0, 0, 0, 3482,
+ 4132, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 839, 0, 0, 0, 0, 0, 0, 0, 0, 194,
+ 0, 0, 0, 962, 0, 0, 245, 1334, 962, 0,
+ 91, 0, 959, 959, 959, 0, 0, 0, 245, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 143, 236,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 400, 91, 938, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 734, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 9, 0, 0, 0, 0, 0, 0,
- 0, 43, -17, 0, 0, 0, 0, 209, 0, 653,
+ 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
+ 0, 0, 0, 0, 4, 67, 0, 0, 0, 0,
+ 179, 0, 446, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 651, 1090, 0,
+ 0, 0, 651, 1159, 0, 4000, 4000, 0, 0, 0,
+ 176, 823, 0, 0, 0, 0, 0, 176, 963, 0,
+ 0, 0, 0, 0, 0, 0, 0, 4000, 0, 0,
+ 0, 0, 0, 0, 0, 0, 4100, 0, 0, 0,
+ 0, 647, 647, 647, 0, 12, 0, 21, 0, 0,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 733, 917, 0, 0, 0, 733,
- 968, 0, 3981, 3981, 0, 0, 0, 175, 123, 0,
- 0, 0, 0, 0, 175, 828, 0, 0, 0, 0,
- 0, 0, 0, 0, 3981, 0, 0, 0, 0, 0,
- 0, 0, 0, 4033, 0, 0, 0, 0, 710, 710,
- 710, 0, 1, 0, 10, 0, 0, -27, 0, 0,
+ 0, 989, 0, 938, 0, 0, 0, 0, 0, 0,
+ 1340, 0, 9, 216, 0, 0, 0, 0, 0, 647,
+ 143, 0, 0, 647, 143, 0, 0, 1669, 236, 21,
+ 0, 236, 21, 0, 959, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1017, 0,
- 978, 0, 0, 0, 0, 0, 0, 1376, 0, 87,
- 264, 0, 0, 0, 0, 0, 710, 142, 0, 0,
- 710, 142, 0, 0, 1689, 240, 10, 0, 240, 10,
- 0, 999, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1377, 87,
- 0, 0, 142, 142, 10, 10, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
+ 0, 1343, 9, 0, 0, 143, 143, 21, 21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static const YYINT pfctlygindex[] = { 0,
- 1557, 0, -208, -102, -320, 0, 0, -480, -619, 796,
- -70, 0, 0, 1391, 204, 1165, 0, 0, 0, 0,
- 328, 1324, 0, 0, 953, 0, 0, -612, 0, 0,
- 673, 598, -325, 0, -88, 0, -331, 0, 0, 0,
- -668, 0, -581, 0, 1154, 851, 950, 0, 0, -345,
- 0, 0, -315, 0, 969, 0, 0, -379, 0, 853,
- 0, -497, 0, 959, 0, -457, 0, 0, -590, 0,
- 0, -514, 0, 0, 0, -421, 0, 872, 0, -8,
- 1249, -80, 0, -182, 715, 1218, 599, 0, 130, 0,
- 1167, 0, 0, -223, 0, 1195, 0, -312, 0, 0,
- 1038, 0, 1037, 0, 956, 0, 0, 960, 0, 0,
- 974, 0, 1472, 954, 850, 0, 0, -591, 0, 0,
- 1123, 0, 1295, 1224, 0, 0, 887, 0, 0, 1150,
- 0, -337, 967, 0, 854, -319, 0, 0, 0, 1475,
- 1477, -3, -2, 0, 0, 0, 0, 0, 0, 0,
- -169, -119, 0, -192, 0, 0, 0, 0, 0, -178,
+ 1611, 0, -199, 319, -358, 0, 0, -471, -186, 754,
+ -70, 0, 0, 1352, 199, 1017, 0, 0, 0, 0,
+ 514, 1284, 0, 0, 958, 0, 0, -464, 0, 0,
+ 622, 546, -322, 0, -163, 0, -345, 0, 0, 0,
+ -610, 0, -640, 0, 1101, 906, 895, 0, 0, -309,
+ 0, 0, -300, 0, 913, 0, 0, -365, 0, 741,
+ 0, -472, 0, 907, 0, -453, 0, 0, -647, 0,
+ 0, -512, 0, 0, 0, -424, 0, 817, 0, -8,
+ 1185, -81, 0, -570, 650, 1160, 724, 0, 596, 0,
+ 1109, 0, 0, -243, 0, 1133, 0, -319, 0, 0,
+ 983, 0, 972, 0, 898, 0, 0, 897, 0, 0,
+ 911, 0, 672, 886, 782, 0, 0, -643, 0, 0,
+ 1056, 0, 1227, 1156, 0, 0, 818, 0, 0, 1081,
+ 0, -311, 902, 0, 781, -317, 0, 0, 0, 1404,
+ 1410, -3, -2, 0, 0, 0, 0, 0, 0, 0,
+ -162, -119, 0, -176, 0, 0, 0, 0, 0, -178,
0, 0, 0, 0, 0, 0, 0, 0,
};
-#define YYTABLESIZE 4783
+#define YYTABLESIZE 4822
static const YYINT pfctlytable[] = { 44,
- 45, 177, 58, 59, 388, 389, 206, 169, 412, 275,
- 416, 103, 256, 267, 275, 113, 275, 251, 175, 437,
- 68, 280, 275, 727, 248, 275, 275, 432, 433, 123,
- 570, 412, 280, 402, 265, 1, 436, 467, 711, 93,
- 251, 319, 275, 274, 748, 1, 230, 116, 497, 128,
- 126, 336, 414, 275, 558, 280, 216, 725, 226, 167,
- 167, 143, 248, 484, 167, 282, 231, 133, 248, 275,
- 275, 275, 173, 226, 1, 307, 682, 461, 362, 310,
- 46, 496, 267, 264, 385, 480, 481, 328, 311, 331,
- 728, 275, 216, 439, 53, 362, 177, 275, 275, 746,
- 344, 467, 494, 54, 761, 275, 275, 275, 690, 261,
- 262, 263, 803, 499, 610, 439, 516, 275, 275, 437,
- 440, 438, 441, 276, 101, 216, 275, 20, 113, 757,
- 275, 175, 309, 752, 275, 400, 708, 327, 391, 527,
- 216, 225, 440, 438, 441, 326, 275, 329, 439, 166,
- 371, 216, 466, 134, 371, 309, 395, 129, 390, 169,
- 345, 361, 346, 412, 538, 56, 309, 439, 705, 404,
- 623, 474, 794, 330, 412, 440, 438, 441, 556, 216,
- 216, 275, 309, 309, 309, 275, 412, 368, 584, 722,
- 439, 559, 610, 131, 440, 438, 441, 805, 216, 383,
- 621, 338, 804, 162, 416, 437, 343, 275, 760, 272,
- 359, 275, 317, 180, 180, 180, 396, 440, 438, 441,
- 77, 394, 477, 620, 167, 380, 486, 91, 251, 452,
- 482, 631, 476, 385, 275, 275, 275, 298, 392, 490,
- 758, 428, 132, 216, 78, 309, 495, 309, 275, 453,
- 80, 447, 629, 488, 73, 74, 510, 668, 115, 339,
- 509, 533, 121, 491, 81, 121, 275, 124, 275, 251,
- 471, 472, 437, 169, 251, 251, 806, 178, 434, 549,
- 475, 651, 478, 251, 73, 452, 412, 122, 416, 534,
- 122, 1, 1, 1, 1, 101, 251, 251, 347, 437,
- 437, 437, 318, 437, 369, 453, 458, 248, 369, 251,
- 280, 125, 251, 248, 371, 439, 511, 512, 251, 550,
- 1, 1, 1, 437, 560, 141, 281, 161, 91, 347,
- 414, 251, 347, 1, 267, 275, 305, 306, 460, 534,
- 267, 528, 440, 438, 441, 1, 87, 532, 88, 1,
- 1, 1, 1, 1, 537, 412, 275, 113, 275, 275,
- 275, 617, 618, 619, 251, 275, 275, 1, 726, 1,
- 437, 248, 412, 4, 5, 6, 1, 548, 626, 280,
- 124, 251, 99, 738, 99, 101, 91, 1, 251, 113,
- 740, 309, 634, 275, 275, 1, 280, 280, 681, 414,
- 309, 309, 224, 309, 309, 675, 216, 290, 291, 385,
- 385, 385, 385, 385, 309, 7, 99, 224, 616, 1,
- 309, 309, 360, 286, 309, 309, 309, 8, 216, 267,
- 309, 9, 10, 11, 12, 13, 624, 385, 627, 360,
- 309, 412, 275, 275, 174, 175, 286, 132, 309, 14,
- 632, 15, 689, 286, 286, 799, 452, 286, 16, 800,
- 580, 275, 309, 437, 647, 607, 174, 175, 369, 17,
- 275, 275, 216, 286, 309, 370, 453, 18, 82, 309,
- 251, 719, 416, 655, 309, 251, 251, 625, 412, 412,
- 412, 412, 412, 553, 251, 216, 309, 309, 660, 666,
- 667, 19, 730, 704, 309, 309, 309, 309, 706, 633,
- 412, 649, 580, 92, 267, 216, 412, 567, 666, 667,
- 734, 735, 736, 111, 696, 275, 275, 412, 93, 416,
- 416, 416, 416, 416, 94, 713, 286, 267, 286, 628,
- 715, 673, 674, 607, 216, 448, 449, 112, 720, 99,
- 764, 458, 766, 774, 152, 723, 290, 416, 275, 275,
- 132, 216, 775, 390, 390, 390, 390, 390, 781, 99,
- 290, 291, 784, 450, 451, 251, 780, 788, 95, 290,
- 791, 356, 519, 793, 520, 739, 290, 290, 744, 96,
- 290, 390, 275, 275, 347, 693, 783, 290, 291, 124,
- 124, 124, 124, 124, 124, 124, 290, 290, 291, 124,
- 124, 124, 356, 114, 218, 356, 347, 275, 650, 97,
- 773, 275, 219, 437, 437, 787, 743, 98, 782, 450,
- 451, 437, 785, 437, 437, 437, 709, 789, 248, 113,
- 792, 124, 790, 99, 437, 437, 275, 437, 437, 220,
- 221, 696, 347, 347, 347, 100, 437, 347, 347, 347,
- 101, 347, 386, 776, 347, 347, 673, 674, 437, 290,
- 437, 290, 347, 102, 300, 286, 301, 302, 303, 103,
- 810, 286, 286, 811, 812, 813, 814, 183, 733, 187,
- 286, 286, 286, 104, 286, 286, 120, 286, 275, 357,
- 421, 286, 286, 286, 300, 286, 422, 423, 84, 85,
- 86, 286, 286, 286, 286, 286, 286, 286, 286, 255,
- 105, 286, 216, 106, 286, 107, 437, 300, 743, 273,
- 357, 286, 216, 357, 437, 424, 437, 286, 300, 286,
- 136, 778, 779, 437, 653, 654, 144, 145, 286, 286,
- 286, 286, 286, 286, 300, 300, 300, 414, 137, 658,
- 659, 437, 437, 437, 108, 286, 267, 406, 407, 109,
- 286, 403, 267, 110, 216, 286, 286, 161, 777, 132,
- 132, 132, 132, 132, 132, 132, 73, 286, 286, 132,
- 132, 132, 267, 408, 286, 286, 286, 286, 286, 241,
- 450, 451, 41, 163, 126, 241, 241, 241, 290, 99,
- 99, 139, 140, 411, 290, 290, 216, 300, 165, 300,
- 195, 132, 188, 290, 290, 290, 437, 290, 290, 196,
- 290, 414, 415, 416, 290, 290, 290, 318, 290, 267,
- 267, 267, 267, 267, 290, 290, 290, 290, 290, 290,
- 290, 290, 763, 765, 290, 216, 216, 290, 174, 175,
- 318, 267, 437, 47, 290, 201, 417, 267, 437, 437,
- 290, 318, 290, 48, 49, 50, 202, 356, 267, 267,
- 203, 290, 290, 290, 290, 290, 290, 318, 318, 318,
- 248, 69, 214, 99, 99, 248, 248, 437, 290, 356,
- 216, 248, 786, 290, 248, 216, 184, 185, 290, 290,
- 5, 6, 51, 205, 67, 189, 190, 126, 192, 193,
- 290, 290, 670, 677, 210, 211, 335, 290, 290, 290,
- 290, 290, 275, 290, 291, 356, 356, 356, 83, 207,
- 356, 356, 356, 208, 356, 305, 306, 356, 356, 335,
- 318, 209, 318, 642, 643, 356, 300, 275, 686, 687,
- 335, 212, 300, 300, 84, 85, 86, 9, 10, 11,
- 12, 213, 300, 300, 215, 300, 300, 338, 694, 175,
- 437, 378, 300, 300, 300, 248, 300, 386, 386, 386,
- 386, 386, 300, 300, 224, 357, 300, 300, 300, 300,
- 338, 128, 300, 437, 437, 300, 232, 378, 378, 378,
- 246, 338, 300, 666, 667, 386, 254, 357, 300, 251,
- 300, 130, 636, 637, 638, 378, 378, 378, 257, 300,
- 300, 300, 300, 300, 300, 414, 241, 181, 182, 335,
- 125, 335, 673, 674, 653, 654, 300, 670, 749, 750,
- 677, 300, 269, 357, 357, 357, 300, 300, 357, 357,
- 357, 270, 357, 167, 114, 357, 357, 285, 300, 300,
- 658, 659, 286, 357, 287, 300, 300, 300, 300, 300,
- 753, 754, 414, 414, 414, 414, 414, 437, 437, 288,
- 338, 289, 338, 437, 437, 333, 318, 293, 437, 500,
- 501, 502, 503, 504, 414, 318, 318, 315, 318, 318,
- 414, 323, 324, 325, 128, 670, 275, 275, 677, 318,
- 437, 99, 443, 443, 241, 318, 318, 505, 337, 318,
- 318, 318, 445, 445, 130, 318, 126, 126, 126, 126,
- 126, 126, 126, 404, 404, 318, 126, 126, 126, 241,
- 404, 404, 404, 318, 365, 366, 437, 437, 437, 294,
- 295, 437, 437, 437, 233, 437, 332, 318, 437, 437,
- 67, 67, 347, 352, 376, 378, 437, 114, 126, 318,
- 381, 382, 386, 67, 318, 335, 67, 233, 392, 318,
- 397, 281, 67, 398, 335, 335, 427, 335, 335, 405,
- 413, 318, 318, 420, 429, 67, 456, 457, 335, 318,
- 318, 318, 318, 463, 335, 335, 275, 513, 335, 335,
- 335, 470, 473, 275, 335, 517, 514, 275, 515, 521,
- 465, 522, 523, 524, 335, 469, 338, 526, 67, 546,
- 551, 561, 335, 275, 562, 338, 338, 563, 338, 338,
- 564, 565, 566, 568, 585, 67, 335, 460, 640, 338,
- 635, 639, 67, 641, 645, 338, 338, 663, 335, 338,
- 338, 338, 664, 335, 691, 338, 665, 685, 335, 692,
- 697, 198, 199, 200, 508, 338, 699, 700, 701, 710,
- 335, 335, 45, 338, 707, 650, 712, 714, 335, 335,
- 335, 335, 716, 717, 721, 724, 275, 338, 275, 681,
- 731, 737, 732, 762, 795, 45, 796, 771, 797, 338,
- 801, 798, 802, 45, 338, 807, 45, 808, 229, 338,
- 809, 815, 228, 128, 128, 128, 128, 128, 128, 128,
- 241, 338, 338, 128, 128, 128, 99, 275, 47, 338,
- 338, 338, 338, 130, 130, 130, 130, 130, 130, 130,
- 167, 437, 251, 130, 130, 130, 416, 59, 241, 241,
- 241, 241, 241, 241, 241, 128, 241, 99, 437, 241,
- 241, 241, 241, 437, 275, 401, 402, 241, 241, 241,
- 241, 275, 680, 41, 146, 130, 112, 112, 112, 112,
- 112, 112, 112, 230, 767, 45, 816, 112, 112, 316,
- 241, 275, 529, 299, 525, 518, 233, 314, 622, 233,
- 233, 233, 233, 233, 322, 247, 230, 233, 233, 233,
- 233, 755, 233, 233, 271, 233, 233, 167, 114, 297,
- 334, 479, 233, 233, 233, 543, 233, 233, 483, 233,
- 233, 233, 233, 233, 545, 539, 233, 233, 233, 233,
- 275, 555, 233, 698, 399, 233, 245, 296, 367, 646,
- 384, 241, 233, 554, 275, 703, 275, 42, 233, 43,
- 233, 0, 0, 275, 275, 0, 0, 233, 0, 233,
- 233, 233, 233, 233, 233, 0, 0, 241, 241, 241,
- 241, 241, 241, 241, 0, 0, 233, 241, 241, 241,
- 0, 233, 0, 275, 0, 0, 233, 233, 0, 0,
- 275, 0, 0, 0, 275, 0, 0, 0, 233, 233,
- 229, 0, 0, 0, 0, 233, 233, 233, 0, 0,
- 275, 275, 275, 0, 45, 0, 0, 0, 45, 45,
- 45, 45, 0, 229, 0, 45, 45, 45, 45, 0,
- 45, 45, 0, 45, 45, 0, 0, 275, 275, 0,
- 45, 45, 45, 0, 45, 0, 0, 0, 0, 90,
- 45, 45, 0, 0, 45, 45, 45, 45, 0, 0,
- 45, 0, 0, 45, 0, 0, 0, 0, 0, 0,
- 45, 0, 0, 275, 0, 275, 45, 0, 45, 0,
- 0, 0, 0, 117, 118, 119, 0, 45, 45, 45,
- 45, 45, 45, 0, 138, 0, 0, 39, 275, 0,
- 0, 0, 0, 0, 45, 0, 172, 0, 0, 45,
- 0, 0, 0, 0, 45, 45, 0, 0, 0, 0,
- 0, 275, 275, 209, 0, 230, 45, 45, 0, 230,
- 230, 230, 230, 45, 45, 45, 230, 230, 230, 230,
- 0, 230, 230, 0, 230, 230, 209, 0, 0, 0,
- 0, 0, 230, 230, 0, 230, 230, 0, 230, 230,
- 230, 230, 230, 572, 573, 230, 230, 230, 230, 0,
- 0, 230, 0, 0, 230, 0, 574, 0, 0, 575,
- 0, 230, 0, 0, 0, 576, 0, 230, 0, 230,
- 0, 211, 0, 0, 0, 0, 230, 0, 577, 0,
- 0, 0, 0, 230, 0, 275, 275, 0, 249, 250,
- 0, 0, 40, 253, 211, 230, 0, 0, 0, 0,
- 230, 0, 0, 260, 0, 230, 0, 275, 0, 0,
- 0, 578, 0, 0, 0, 0, 0, 230, 230, 0,
- 0, 0, 0, 0, 230, 230, 230, 0, 0, 0,
- 275, 275, 229, 0, 0, 579, 229, 229, 229, 229,
- 0, 0, 147, 229, 229, 229, 229, 0, 229, 229,
- 0, 229, 229, 0, 0, 0, 0, 0, 0, 229,
- 229, 0, 229, 229, 148, 229, 229, 229, 229, 229,
- 0, 0, 229, 229, 229, 229, 0, 0, 229, 0,
- 0, 229, 0, 0, 0, 0, 0, 0, 229, 275,
- 0, 0, 0, 0, 229, 213, 229, 0, 0, 0,
- 149, 150, 151, 229, 0, 152, 153, 154, 0, 155,
- 229, 0, 144, 145, 275, 275, 0, 0, 213, 0,
- 156, 0, 229, 38, 5, 6, 0, 229, 0, 0,
- 0, 0, 229, 0, 0, 485, 487, 489, 0, 0,
- 0, 0, 492, 493, 229, 229, 0, 0, 0, 0,
- 0, 229, 229, 229, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 0, 0, 7, 209, 209, 209, 209,
- 0, 209, 209, 0, 209, 209, 0, 0, 0, 0,
- 0, 9, 10, 11, 12, 209, 209, 0, 209, 209,
- 209, 209, 209, 0, 0, 209, 209, 209, 0, 0,
- 0, 209, 0, 0, 0, 540, 0, 541, 0, 542,
- 0, 209, 544, 0, 0, 0, 0, 0, 214, 209,
- 0, 0, 211, 211, 211, 211, 211, 211, 211, 211,
- 211, 0, 0, 209, 211, 211, 211, 211, 0, 211,
- 211, 214, 211, 211, 437, 209, 0, 0, 0, 0,
- 209, 0, 0, 211, 211, 209, 211, 211, 211, 211,
- 211, 0, 0, 211, 211, 211, 437, 209, 209, 211,
- 0, 0, 0, 0, 0, 209, 209, 0, 0, 211,
- 0, 0, 0, 0, 0, 0, 0, 211, 112, 112,
- 112, 112, 112, 112, 112, 0, 0, 0, 114, 112,
- 112, 211, 437, 437, 437, 0, 0, 437, 437, 437,
- 0, 437, 0, 211, 437, 437, 271, 0, 211, 0,
- 0, 0, 437, 211, 0, 0, 233, 234, 235, 236,
- 237, 238, 239, 0, 0, 211, 211, 240, 241, 271,
- 0, 702, 0, 211, 211, 0, 213, 213, 213, 213,
- 213, 213, 213, 213, 213, 0, 0, 0, 213, 213,
- 213, 213, 0, 213, 213, 0, 213, 213, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 213, 213, 0,
- 213, 213, 213, 213, 213, 0, 0, 213, 213, 213,
- 0, 0, 0, 213, 0, 0, 0, 0, 248, 0,
- 0, 0, 0, 213, 0, 0, 60, 61, 62, 63,
- 64, 213, 65, 0, 66, 0, 67, 68, 69, 0,
- 0, 248, 0, 0, 0, 213, 261, 0, 0, 271,
- 0, 0, 0, 0, 0, 0, 0, 213, 0, 0,
- 0, 0, 213, 0, 0, 0, 0, 213, 70, 261,
- 0, 0, 0, 0, 0, 768, 769, 770, 0, 213,
- 213, 0, 0, 0, 0, 71, 72, 213, 213, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 0, 0,
- 0, 214, 214, 214, 214, 0, 214, 214, 0, 214,
- 214, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 214, 214, 0, 214, 214, 214, 214, 214, 0, 0,
- 214, 214, 214, 0, 0, 0, 214, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 214, 0, 0, 0,
- 0, 0, 0, 0, 214, 0, 0, 0, 0, 261,
- 0, 0, 0, 0, 0, 0, 0, 0, 214, 223,
+ 45, 180, 58, 59, 282, 269, 277, 209, 172, 391,
+ 392, 70, 414, 416, 243, 259, 115, 105, 229, 277,
+ 439, 418, 730, 685, 177, 439, 310, 282, 136, 405,
+ 277, 658, 270, 283, 339, 414, 322, 264, 265, 266,
+ 663, 731, 170, 127, 268, 365, 277, 117, 277, 233,
+ 483, 484, 277, 277, 285, 250, 435, 436, 573, 250,
+ 442, 561, 146, 132, 277, 500, 341, 497, 277, 1,
+ 464, 269, 487, 176, 124, 760, 470, 755, 489, 1,
+ 277, 277, 277, 491, 170, 1, 267, 443, 441, 444,
+ 331, 129, 334, 229, 269, 365, 722, 693, 180, 46,
+ 219, 228, 181, 347, 258, 751, 277, 219, 278, 74,
+ 277, 277, 133, 277, 613, 137, 455, 733, 414, 53,
+ 499, 95, 519, 797, 349, 342, 439, 20, 364, 115,
+ 103, 502, 374, 277, 277, 219, 456, 177, 362, 219,
+ 470, 414, 442, 808, 530, 277, 807, 403, 329, 219,
+ 332, 442, 494, 383, 477, 349, 442, 394, 349, 398,
+ 541, 388, 172, 348, 711, 349, 442, 559, 393, 443,
+ 441, 444, 407, 806, 169, 708, 455, 415, 443, 441,
+ 444, 330, 442, 443, 441, 444, 277, 626, 623, 714,
+ 371, 277, 613, 443, 441, 444, 456, 562, 134, 631,
+ 130, 725, 386, 387, 455, 54, 437, 320, 277, 443,
+ 441, 444, 275, 763, 56, 277, 333, 358, 277, 399,
+ 346, 79, 92, 250, 456, 480, 78, 587, 276, 250,
+ 397, 219, 440, 485, 219, 277, 277, 277, 277, 624,
+ 301, 671, 493, 170, 431, 81, 678, 135, 358, 498,
+ 749, 358, 761, 116, 450, 439, 219, 269, 219, 513,
+ 634, 170, 219, 269, 219, 83, 243, 277, 439, 126,
+ 632, 243, 243, 474, 475, 439, 172, 243, 243, 243,
+ 243, 809, 282, 478, 101, 481, 372, 654, 308, 309,
+ 414, 416, 537, 656, 657, 439, 439, 439, 321, 418,
+ 359, 103, 661, 662, 101, 126, 143, 250, 313, 461,
+ 253, 122, 250, 250, 82, 479, 284, 314, 250, 514,
+ 515, 250, 553, 269, 93, 1, 1, 1, 1, 269,
+ 94, 359, 463, 374, 359, 469, 123, 512, 406, 536,
+ 95, 219, 537, 552, 531, 563, 684, 96, 250, 269,
+ 535, 374, 282, 269, 1, 1, 1, 540, 277, 115,
+ 414, 416, 243, 227, 620, 621, 622, 1, 729, 282,
+ 282, 277, 439, 4, 5, 6, 101, 414, 101, 1,
+ 551, 629, 126, 1, 1, 1, 1, 1, 741, 101,
+ 363, 115, 103, 277, 277, 637, 414, 269, 269, 269,
+ 269, 269, 1, 250, 1, 277, 277, 250, 743, 394,
+ 93, 1, 177, 178, 97, 7, 154, 293, 294, 269,
+ 349, 619, 1, 293, 294, 269, 288, 8, 293, 294,
+ 1, 9, 10, 11, 12, 13, 269, 269, 227, 627,
+ 363, 630, 692, 349, 414, 414, 414, 414, 414, 288,
+ 14, 277, 15, 635, 1, 388, 288, 288, 277, 16,
+ 288, 453, 454, 583, 451, 452, 414, 650, 610, 93,
+ 17, 439, 414, 802, 98, 277, 288, 803, 18, 349,
+ 349, 349, 122, 414, 349, 349, 349, 372, 349, 99,
+ 234, 349, 349, 728, 177, 178, 556, 293, 294, 349,
+ 74, 75, 19, 669, 670, 372, 707, 123, 676, 677,
+ 100, 709, 373, 358, 219, 583, 416, 652, 669, 670,
+ 570, 453, 454, 737, 738, 739, 699, 277, 277, 387,
+ 387, 387, 387, 387, 676, 677, 358, 219, 716, 288,
+ 764, 288, 115, 718, 101, 101, 610, 279, 121, 453,
+ 454, 723, 277, 767, 461, 769, 219, 387, 726, 292,
+ 277, 277, 253, 277, 277, 778, 219, 253, 253, 277,
+ 219, 784, 358, 358, 358, 787, 253, 358, 358, 358,
+ 791, 358, 292, 794, 358, 358, 796, 101, 742, 292,
+ 292, 747, 358, 292, 277, 628, 359, 163, 696, 439,
+ 439, 439, 126, 126, 126, 126, 126, 126, 126, 292,
+ 112, 219, 126, 126, 126, 439, 439, 439, 636, 359,
+ 439, 439, 219, 776, 439, 653, 418, 102, 746, 101,
+ 101, 785, 88, 277, 89, 788, 522, 777, 523, 712,
+ 792, 221, 414, 795, 126, 219, 103, 783, 250, 222,
+ 439, 786, 277, 699, 104, 359, 359, 359, 253, 277,
+ 359, 359, 359, 766, 359, 113, 219, 359, 359, 105,
+ 165, 250, 292, 106, 292, 359, 223, 224, 288, 277,
+ 183, 183, 183, 813, 288, 288, 814, 815, 816, 817,
+ 107, 736, 790, 288, 288, 288, 108, 288, 288, 302,
+ 288, 142, 143, 793, 288, 288, 288, 768, 288, 109,
+ 219, 417, 418, 419, 288, 288, 288, 288, 288, 288,
+ 288, 288, 302, 134, 288, 439, 789, 288, 110, 219,
+ 746, 439, 439, 302, 288, 392, 392, 392, 392, 392,
+ 111, 288, 277, 288, 781, 782, 420, 147, 148, 302,
+ 302, 302, 288, 288, 288, 288, 288, 288, 187, 188,
+ 439, 424, 84, 392, 177, 178, 277, 425, 426, 288,
+ 439, 192, 193, 277, 288, 114, 251, 277, 439, 288,
+ 288, 388, 388, 388, 388, 388, 43, 139, 85, 86,
+ 87, 288, 288, 277, 416, 140, 427, 380, 288, 288,
+ 288, 288, 288, 779, 164, 439, 439, 195, 196, 388,
+ 47, 292, 302, 186, 302, 190, 74, 292, 292, 166,
+ 48, 49, 50, 380, 380, 380, 292, 292, 292, 168,
+ 292, 292, 311, 292, 213, 214, 134, 292, 292, 292,
+ 191, 292, 416, 416, 416, 416, 416, 292, 292, 292,
+ 292, 292, 292, 292, 292, 311, 277, 292, 277, 51,
+ 292, 85, 86, 87, 416, 198, 311, 292, 277, 204,
+ 416, 439, 293, 294, 292, 199, 292, 205, 439, 308,
+ 309, 101, 311, 311, 311, 292, 292, 292, 292, 292,
+ 292, 409, 410, 277, 645, 646, 277, 206, 439, 217,
+ 250, 208, 292, 210, 418, 250, 250, 292, 639, 640,
+ 641, 250, 292, 292, 250, 439, 439, 411, 780, 277,
+ 277, 250, 689, 690, 292, 292, 211, 250, 250, 697,
+ 178, 292, 292, 292, 292, 292, 219, 253, 669, 670,
+ 250, 439, 227, 250, 250, 311, 212, 311, 215, 250,
+ 249, 302, 418, 418, 418, 418, 418, 302, 302, 216,
+ 253, 439, 303, 250, 304, 305, 306, 302, 302, 218,
+ 302, 302, 320, 676, 677, 406, 406, 302, 302, 302,
+ 418, 302, 406, 406, 406, 656, 657, 302, 302, 752,
+ 753, 302, 302, 302, 302, 320, 250, 302, 661, 662,
+ 302, 380, 380, 380, 277, 277, 320, 302, 756, 757,
+ 277, 243, 254, 250, 302, 235, 302, 243, 243, 243,
+ 250, 257, 320, 320, 320, 302, 302, 302, 302, 302,
+ 302, 439, 439, 277, 277, 277, 277, 445, 445, 128,
+ 447, 447, 302, 184, 185, 368, 369, 302, 260, 126,
+ 5, 6, 302, 302, 170, 272, 134, 134, 134, 134,
+ 134, 134, 134, 273, 302, 302, 134, 134, 134, 318,
+ 288, 302, 302, 302, 302, 302, 289, 290, 291, 292,
+ 296, 297, 439, 298, 335, 320, 336, 320, 488, 490,
+ 492, 311, 340, 350, 381, 495, 496, 355, 134, 337,
+ 311, 311, 379, 311, 311, 439, 384, 9, 10, 11,
+ 12, 673, 680, 385, 311, 439, 389, 400, 277, 277,
+ 311, 311, 337, 395, 311, 311, 311, 401, 284, 408,
+ 311, 416, 423, 337, 201, 202, 203, 430, 439, 439,
+ 311, 439, 439, 439, 130, 432, 439, 439, 439, 311,
+ 439, 459, 128, 439, 439, 460, 466, 473, 543, 476,
+ 544, 439, 545, 311, 516, 547, 517, 518, 340, 326,
+ 327, 328, 520, 250, 524, 311, 527, 525, 250, 250,
+ 311, 526, 529, 232, 250, 311, 549, 250, 554, 253,
+ 564, 340, 132, 567, 253, 253, 565, 311, 311, 250,
+ 566, 568, 340, 253, 569, 311, 311, 311, 311, 571,
+ 463, 643, 337, 243, 337, 588, 253, 253, 503, 504,
+ 505, 506, 507, 439, 439, 648, 116, 638, 642, 253,
+ 644, 320, 253, 666, 667, 668, 673, 688, 253, 680,
+ 320, 320, 694, 320, 320, 695, 508, 250, 250, 250,
+ 250, 250, 253, 700, 320, 702, 710, 130, 703, 704,
+ 320, 320, 713, 717, 320, 320, 320, 715, 302, 250,
+ 320, 277, 317, 719, 653, 250, 720, 724, 277, 325,
+ 320, 340, 727, 340, 734, 253, 250, 250, 468, 320,
+ 735, 684, 740, 472, 705, 765, 799, 774, 277, 798,
+ 800, 801, 253, 320, 673, 132, 804, 680, 805, 253,
+ 810, 811, 818, 230, 243, 320, 812, 101, 277, 49,
+ 320, 169, 439, 370, 253, 320, 243, 235, 418, 236,
+ 237, 238, 239, 240, 241, 242, 101, 320, 320, 116,
+ 243, 244, 511, 61, 439, 320, 320, 320, 320, 403,
+ 235, 439, 404, 683, 41, 149, 770, 819, 337, 319,
+ 532, 277, 521, 277, 250, 528, 625, 337, 337, 758,
+ 337, 337, 128, 128, 128, 128, 128, 128, 128, 274,
+ 300, 337, 128, 128, 128, 337, 486, 337, 337, 482,
+ 546, 337, 337, 337, 548, 542, 558, 337, 701, 39,
+ 402, 248, 299, 649, 387, 706, 42, 337, 771, 772,
+ 773, 557, 43, 0, 128, 0, 337, 277, 0, 0,
+ 0, 0, 0, 0, 277, 0, 0, 340, 277, 0,
+ 337, 0, 0, 0, 0, 0, 340, 340, 170, 340,
+ 340, 0, 337, 0, 277, 277, 277, 337, 0, 0,
+ 340, 0, 337, 0, 0, 0, 340, 340, 0, 0,
+ 340, 340, 340, 47, 337, 337, 340, 71, 0, 0,
+ 0, 0, 337, 337, 337, 337, 340, 130, 130, 130,
+ 130, 130, 130, 130, 0, 340, 47, 130, 130, 130,
+ 69, 0, 0, 0, 47, 0, 0, 47, 0, 340,
+ 0, 0, 0, 0, 0, 0, 0, 277, 0, 277,
+ 0, 340, 0, 0, 40, 277, 340, 0, 0, 130,
+ 0, 340, 0, 0, 0, 132, 132, 132, 132, 132,
+ 132, 132, 0, 340, 340, 132, 132, 132, 277, 277,
+ 0, 340, 340, 340, 340, 0, 243, 243, 243, 243,
+ 243, 243, 243, 0, 0, 0, 0, 243, 243, 114,
+ 114, 114, 114, 114, 114, 114, 0, 132, 0, 0,
+ 114, 114, 0, 0, 0, 0, 47, 0, 0, 235,
+ 0, 0, 235, 235, 235, 235, 235, 0, 243, 0,
+ 235, 235, 235, 235, 232, 235, 235, 0, 235, 235,
+ 0, 116, 0, 0, 0, 235, 235, 235, 0, 235,
+ 235, 0, 235, 235, 235, 235, 235, 232, 0, 235,
+ 235, 235, 235, 277, 277, 235, 0, 0, 235, 0,
+ 0, 0, 0, 91, 0, 235, 0, 0, 0, 0,
+ 0, 0, 235, 0, 235, 38, 5, 6, 0, 0,
+ 0, 235, 0, 235, 235, 235, 235, 235, 235, 0,
+ 0, 277, 0, 0, 0, 0, 0, 118, 119, 120,
+ 235, 0, 0, 0, 0, 235, 0, 0, 0, 141,
+ 235, 235, 0, 0, 277, 277, 0, 7, 0, 0,
+ 0, 175, 235, 235, 575, 576, 0, 0, 0, 235,
+ 235, 235, 0, 9, 10, 11, 12, 577, 0, 0,
+ 578, 0, 0, 231, 0, 47, 579, 0, 0, 47,
+ 47, 47, 47, 0, 0, 0, 47, 47, 47, 47,
+ 580, 47, 47, 0, 47, 47, 231, 0, 0, 0,
+ 0, 47, 47, 47, 277, 47, 69, 69, 0, 0,
+ 0, 47, 47, 0, 0, 47, 47, 47, 47, 69,
+ 0, 47, 69, 581, 47, 0, 0, 0, 69, 277,
+ 277, 47, 0, 0, 0, 0, 0, 0, 47, 0,
+ 47, 0, 69, 0, 0, 0, 0, 582, 0, 47,
+ 47, 47, 47, 47, 47, 252, 253, 0, 0, 0,
+ 256, 0, 0, 0, 0, 0, 47, 0, 0, 0,
+ 263, 47, 0, 0, 0, 69, 47, 47, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 47, 47,
+ 0, 0, 69, 0, 0, 47, 47, 47, 211, 69,
+ 0, 0, 0, 0, 0, 0, 232, 0, 0, 0,
+ 232, 232, 232, 232, 0, 150, 0, 232, 232, 232,
+ 232, 211, 232, 232, 0, 232, 232, 0, 0, 0,
+ 0, 0, 0, 232, 232, 0, 232, 232, 151, 232,
+ 232, 232, 232, 232, 0, 0, 232, 232, 232, 232,
+ 0, 0, 232, 0, 0, 232, 0, 0, 0, 0,
+ 0, 0, 232, 0, 0, 0, 0, 213, 0, 232,
+ 0, 232, 0, 0, 152, 153, 154, 0, 232, 155,
+ 156, 157, 0, 158, 0, 232, 147, 148, 0, 0,
+ 213, 0, 0, 0, 159, 0, 0, 232, 0, 0,
+ 0, 0, 232, 0, 0, 0, 0, 232, 0, 0,
+ 269, 243, 243, 243, 243, 243, 243, 243, 0, 232,
+ 232, 243, 243, 243, 0, 231, 232, 232, 232, 231,
+ 231, 231, 231, 269, 439, 0, 231, 231, 231, 231,
+ 0, 231, 231, 0, 231, 231, 0, 0, 0, 0,
+ 0, 0, 231, 231, 0, 231, 231, 439, 231, 231,
+ 231, 231, 231, 0, 0, 231, 231, 231, 231, 0,
+ 0, 231, 0, 0, 231, 0, 0, 0, 0, 0,
+ 0, 231, 0, 0, 0, 0, 0, 0, 231, 0,
+ 231, 215, 0, 439, 439, 439, 0, 231, 439, 439,
+ 439, 0, 439, 0, 231, 439, 439, 0, 0, 0,
+ 0, 0, 0, 439, 215, 0, 231, 0, 0, 0,
+ 0, 231, 0, 0, 0, 0, 231, 0, 0, 0,
+ 114, 114, 114, 114, 114, 114, 114, 0, 231, 231,
+ 116, 114, 114, 0, 0, 231, 231, 231, 225, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 0, 0,
+ 0, 211, 211, 211, 211, 0, 211, 211, 0, 211,
+ 211, 225, 0, 0, 0, 0, 0, 0, 0, 0,
+ 211, 211, 0, 211, 211, 211, 211, 211, 0, 0,
+ 211, 211, 211, 0, 0, 0, 211, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 211, 0, 0, 0,
+ 0, 0, 0, 0, 0, 211, 0, 216, 213, 213,
+ 213, 213, 213, 213, 213, 213, 213, 0, 0, 211,
+ 213, 213, 213, 213, 0, 213, 213, 0, 213, 213,
+ 216, 211, 0, 0, 0, 0, 211, 0, 0, 213,
+ 213, 211, 213, 213, 213, 213, 213, 0, 0, 213,
+ 213, 213, 269, 211, 211, 213, 0, 0, 269, 0,
+ 0, 211, 211, 0, 0, 213, 0, 0, 0, 0,
+ 0, 0, 0, 0, 213, 0, 0, 0, 0, 269,
+ 269, 0, 0, 0, 0, 0, 0, 0, 213, 0,
+ 253, 0, 269, 0, 0, 269, 0, 0, 0, 0,
+ 213, 269, 0, 0, 0, 213, 273, 0, 0, 0,
+ 213, 0, 0, 253, 0, 269, 0, 0, 0, 0,
+ 0, 0, 213, 213, 0, 0, 0, 0, 0, 273,
+ 213, 213, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 0, 0, 0, 215, 215, 215, 215, 269, 215,
+ 215, 0, 215, 215, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 215, 215, 269, 215, 215, 215, 215,
+ 215, 0, 269, 215, 215, 215, 0, 0, 0, 215,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 215,
+ 225, 0, 225, 225, 225, 225, 225, 0, 215, 0,
+ 0, 225, 225, 225, 225, 263, 0, 0, 0, 0,
+ 0, 0, 215, 0, 0, 0, 0, 225, 225, 273,
+ 0, 0, 0, 0, 215, 0, 0, 0, 263, 215,
+ 225, 0, 0, 225, 215, 0, 0, 0, 0, 225,
+ 0, 0, 0, 0, 0, 0, 215, 215, 0, 0,
+ 0, 0, 0, 225, 215, 215, 0, 0, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 0, 0, 0,
+ 216, 216, 216, 216, 0, 216, 216, 0, 216, 216,
+ 0, 0, 0, 0, 0, 0, 225, 0, 0, 216,
+ 216, 0, 216, 216, 216, 216, 216, 0, 0, 216,
+ 216, 216, 0, 225, 0, 216, 0, 0, 0, 0,
+ 225, 0, 0, 0, 0, 216, 0, 0, 263, 0,
+ 0, 0, 0, 0, 216, 0, 0, 0, 225, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 216, 0,
+ 0, 0, 253, 0, 0, 0, 0, 253, 253, 0,
+ 216, 225, 0, 0, 0, 216, 253, 0, 273, 0,
+ 216, 0, 0, 0, 273, 273, 0, 0, 253, 271,
+ 0, 0, 216, 216, 273, 273, 0, 273, 273, 0,
+ 216, 216, 0, 0, 273, 273, 273, 0, 273, 0,
+ 0, 0, 271, 0, 273, 273, 0, 0, 273, 273,
+ 273, 273, 0, 0, 273, 0, 0, 273, 0, 0,
+ 0, 0, 0, 0, 273, 0, 253, 253, 253, 253,
+ 253, 273, 0, 273, 0, 0, 0, 0, 0, 0,
+ 0, 0, 273, 273, 273, 273, 273, 273, 253, 0,
+ 0, 0, 0, 0, 253, 0, 0, 0, 0, 273,
+ 0, 0, 0, 0, 273, 253, 253, 0, 0, 273,
+ 273, 0, 0, 263, 263, 0, 0, 0, 0, 0,
+ 0, 273, 273, 263, 263, 0, 263, 263, 273, 273,
+ 273, 394, 271, 263, 263, 263, 0, 263, 0, 0,
+ 0, 0, 0, 263, 263, 0, 0, 263, 263, 263,
+ 263, 0, 0, 263, 394, 0, 263, 0, 0, 0,
+ 0, 0, 0, 263, 0, 0, 0, 0, 0, 0,
+ 263, 0, 263, 0, 0, 0, 0, 0, 0, 0,
+ 0, 263, 263, 263, 263, 263, 263, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 263, 0,
+ 0, 0, 0, 263, 0, 0, 0, 0, 263, 263,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 214, 0, 0, 0, 0, 214, 0, 0, 271, 0,
- 214, 0, 223, 0, 271, 271, 0, 0, 0, 0,
- 0, 0, 214, 214, 271, 271, 0, 271, 271, 0,
- 214, 214, 0, 0, 271, 271, 271, 0, 271, 0,
- 0, 0, 0, 0, 271, 271, 0, 0, 271, 271,
- 271, 271, 0, 0, 271, 0, 0, 271, 0, 0,
- 0, 0, 0, 0, 271, 0, 0, 0, 0, 0,
- 271, 0, 271, 0, 0, 0, 0, 0, 0, 0,
- 0, 271, 271, 271, 271, 271, 271, 269, 0, 0,
- 248, 0, 0, 0, 0, 248, 248, 0, 271, 0,
- 0, 248, 0, 271, 248, 0, 0, 0, 271, 271,
- 269, 0, 0, 0, 0, 0, 0, 248, 248, 0,
- 271, 271, 0, 0, 261, 261, 0, 271, 271, 271,
- 248, 0, 0, 248, 261, 261, 0, 261, 261, 248,
- 0, 0, 0, 0, 261, 261, 261, 0, 261, 0,
- 0, 0, 248, 0, 261, 261, 0, 0, 261, 261,
- 261, 261, 0, 0, 261, 0, 0, 261, 0, 0,
- 0, 0, 0, 0, 261, 0, 0, 0, 0, 0,
- 261, 0, 261, 0, 0, 248, 0, 0, 0, 0,
- 0, 261, 261, 261, 261, 261, 261, 0, 392, 0,
- 269, 0, 248, 0, 0, 0, 0, 0, 261, 248,
- 0, 0, 0, 261, 0, 0, 0, 0, 261, 261,
- 0, 392, 0, 0, 0, 0, 0, 0, 0, 0,
- 261, 261, 0, 0, 0, 0, 0, 261, 261, 261,
- 0, 223, 267, 223, 223, 223, 223, 223, 223, 0,
- 0, 0, 223, 223, 223, 223, 0, 223, 223, 0,
- 223, 223, 0, 0, 0, 267, 0, 0, 0, 0,
- 0, 223, 223, 0, 223, 223, 223, 223, 223, 0,
- 0, 223, 223, 223, 0, 0, 0, 223, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 223, 0, 0,
- 0, 0, 0, 0, 0, 223, 0, 0, 0, 388,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 223,
+ 263, 263, 0, 0, 0, 0, 0, 263, 263, 263,
+ 225, 0, 225, 225, 225, 225, 225, 225, 0, 0,
+ 0, 225, 225, 225, 225, 0, 225, 225, 0, 225,
+ 225, 390, 0, 0, 0, 0, 0, 0, 0, 0,
+ 225, 225, 0, 225, 225, 225, 225, 225, 0, 0,
+ 225, 225, 225, 0, 390, 0, 225, 0, 271, 0,
+ 0, 0, 0, 0, 0, 0, 225, 271, 271, 0,
+ 271, 271, 0, 0, 0, 225, 0, 271, 271, 271,
+ 0, 271, 0, 0, 0, 0, 0, 271, 271, 225,
+ 0, 271, 271, 271, 271, 0, 0, 271, 0, 0,
+ 271, 225, 0, 0, 0, 0, 225, 271, 0, 0,
+ 0, 225, 0, 0, 271, 0, 271, 0, 0, 0,
+ 0, 0, 0, 225, 225, 271, 271, 271, 271, 271,
+ 271, 225, 225, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 271, 0, 0, 0, 0, 271, 0, 0,
+ 0, 0, 271, 271, 0, 54, 0, 0, 0, 0,
+ 0, 0, 0, 394, 271, 271, 0, 0, 394, 394,
+ 394, 271, 271, 271, 394, 394, 394, 394, 54, 394,
+ 394, 0, 394, 394, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 394, 0, 0, 0, 0, 0, 394,
+ 394, 0, 230, 394, 394, 394, 0, 0, 0, 394,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 394,
+ 0, 0, 0, 0, 0, 230, 0, 0, 394, 0,
+ 0, 0, 0, 0, 0, 0, 0, 392, 392, 392,
+ 392, 392, 394, 0, 60, 61, 62, 63, 64, 65,
+ 0, 66, 0, 67, 394, 68, 69, 70, 0, 394,
+ 0, 0, 0, 0, 394, 392, 0, 0, 54, 0,
+ 0, 0, 0, 0, 0, 0, 394, 394, 0, 0,
+ 0, 0, 0, 390, 394, 394, 0, 71, 390, 390,
+ 390, 0, 0, 0, 390, 390, 390, 390, 0, 390,
+ 390, 0, 390, 390, 72, 73, 0, 0, 0, 0,
+ 0, 0, 0, 390, 243, 0, 0, 0, 0, 390,
+ 390, 0, 0, 390, 390, 390, 0, 0, 0, 390,
+ 0, 0, 0, 0, 0, 0, 0, 243, 0, 390,
+ 0, 0, 0, 0, 0, 0, 0, 0, 390, 0,
+ 0, 0, 0, 0, 0, 0, 0, 390, 390, 390,
+ 390, 390, 390, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 390, 0, 0, 0, 0, 390,
+ 0, 0, 0, 0, 390, 390, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 390, 390, 0, 0,
+ 0, 0, 0, 0, 390, 390, 54, 54, 54, 0,
+ 54, 54, 54, 54, 54, 0, 0, 0, 54, 54,
+ 54, 54, 0, 54, 54, 0, 54, 54, 0, 0,
+ 0, 0, 0, 0, 225, 0, 0, 54, 0, 0,
+ 0, 0, 0, 54, 54, 0, 0, 54, 54, 54,
+ 0, 0, 0, 54, 230, 0, 0, 225, 230, 230,
+ 230, 230, 0, 54, 0, 230, 230, 230, 230, 0,
+ 230, 230, 54, 230, 230, 0, 0, 0, 0, 0,
+ 0, 228, 0, 0, 230, 230, 54, 230, 230, 230,
+ 230, 230, 0, 0, 230, 230, 230, 0, 54, 0,
+ 230, 0, 0, 54, 228, 0, 0, 0, 54, 0,
+ 230, 0, 0, 0, 0, 0, 0, 0, 0, 230,
+ 54, 54, 0, 0, 0, 0, 0, 0, 54, 54,
+ 0, 0, 0, 230, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 230, 0, 225, 0, 0,
+ 230, 0, 0, 0, 0, 230, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 243, 230, 230, 0,
+ 0, 243, 243, 243, 0, 230, 230, 243, 243, 243,
+ 243, 0, 243, 243, 0, 243, 243, 0, 0, 0,
+ 0, 0, 0, 0, 228, 0, 243, 243, 0, 243,
+ 243, 243, 243, 243, 243, 0, 243, 243, 243, 0,
+ 0, 0, 243, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 243, 0, 0, 0, 0, 243, 0, 0,
+ 0, 243, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 243, 0, 0, 0, 0,
+ 0, 426, 0, 0, 0, 0, 0, 243, 0, 0,
+ 0, 0, 243, 0, 0, 0, 0, 243, 0, 0,
+ 0, 0, 0, 0, 426, 0, 0, 0, 0, 243,
+ 243, 0, 0, 0, 0, 0, 225, 243, 243, 225,
+ 225, 225, 225, 225, 0, 0, 0, 225, 225, 225,
+ 225, 0, 225, 225, 0, 225, 225, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 225, 243, 0, 0,
+ 0, 0, 225, 225, 0, 0, 225, 225, 225, 0,
+ 0, 0, 225, 228, 0, 0, 0, 228, 228, 228,
+ 228, 0, 225, 0, 228, 228, 228, 228, 0, 228,
+ 228, 225, 228, 228, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 228, 0, 225, 0, 0, 0, 228,
+ 228, 393, 0, 228, 228, 228, 0, 225, 0, 228,
+ 0, 0, 225, 0, 0, 0, 0, 225, 0, 228,
+ 0, 0, 0, 0, 393, 0, 0, 0, 228, 225,
+ 225, 0, 0, 0, 0, 0, 0, 225, 225, 0,
+ 0, 0, 228, 0, 0, 250, 0, 0, 0, 0,
+ 0, 0, 0, 0, 228, 0, 0, 0, 0, 228,
+ 0, 0, 0, 0, 228, 0, 0, 0, 250, 0,
+ 0, 0, 0, 0, 0, 0, 228, 228, 0, 0,
+ 0, 0, 0, 0, 228, 228, 243, 0, 0, 250,
+ 0, 243, 243, 243, 0, 0, 0, 243, 243, 243,
+ 243, 0, 243, 243, 0, 243, 243, 0, 0, 0,
+ 0, 0, 250, 0, 0, 0, 243, 0, 0, 0,
+ 0, 0, 243, 243, 0, 0, 243, 243, 243, 0,
+ 0, 0, 243, 426, 0, 0, 0, 0, 426, 426,
+ 426, 0, 243, 0, 426, 426, 426, 426, 0, 426,
+ 426, 243, 426, 426, 0, 0, 0, 0, 250, 0,
+ 0, 0, 0, 426, 0, 243, 0, 0, 0, 426,
+ 426, 0, 0, 426, 426, 426, 0, 243, 0, 426,
+ 0, 0, 243, 0, 0, 0, 0, 243, 0, 426,
+ 0, 0, 0, 0, 0, 0, 0, 0, 426, 243,
+ 243, 0, 0, 0, 0, 0, 0, 243, 243, 253,
+ 0, 0, 426, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 426, 0, 0, 0, 0, 426,
+ 0, 0, 253, 0, 426, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 426, 426, 0, 0,
+ 0, 0, 0, 393, 426, 426, 253, 0, 393, 393,
+ 393, 0, 0, 0, 393, 393, 393, 393, 0, 393,
+ 393, 0, 393, 393, 0, 0, 0, 0, 0, 253,
+ 0, 0, 0, 393, 0, 0, 0, 0, 0, 393,
+ 393, 0, 0, 393, 393, 393, 0, 250, 0, 393,
+ 0, 0, 250, 250, 250, 0, 0, 0, 250, 393,
+ 0, 250, 0, 250, 250, 0, 250, 250, 393, 0,
+ 0, 0, 253, 0, 0, 0, 0, 250, 0, 0,
+ 0, 0, 393, 250, 250, 0, 0, 250, 250, 250,
+ 0, 250, 0, 250, 393, 0, 250, 250, 250, 393,
+ 0, 0, 250, 250, 393, 250, 269, 250, 250, 0,
+ 250, 250, 250, 0, 0, 0, 393, 393, 0, 0,
+ 0, 250, 0, 0, 393, 393, 250, 250, 250, 269,
+ 0, 250, 250, 250, 0, 0, 0, 250, 250, 0,
+ 0, 0, 0, 250, 0, 0, 0, 250, 250, 0,
+ 269, 0, 0, 0, 0, 0, 250, 0, 0, 0,
+ 250, 250, 0, 0, 0, 0, 0, 0, 250, 250,
+ 250, 0, 0, 269, 0, 0, 0, 0, 0, 0,
+ 0, 0, 250, 0, 0, 0, 0, 250, 0, 0,
+ 0, 0, 250, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 250, 250, 0, 0, 0, 0,
+ 0, 253, 250, 250, 0, 0, 253, 253, 253, 269,
+ 0, 0, 0, 0, 0, 253, 0, 253, 253, 0,
+ 253, 253, 0, 0, 0, 0, 0, 178, 0, 0,
+ 0, 253, 0, 0, 0, 0, 0, 253, 253, 0,
+ 0, 253, 253, 253, 0, 0, 0, 253, 253, 0,
+ 176, 0, 0, 253, 253, 253, 0, 253, 0, 362,
+ 0, 0, 253, 0, 253, 253, 253, 253, 253, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 253, 0,
+ 253, 0, 362, 0, 253, 253, 0, 0, 253, 253,
+ 253, 0, 253, 0, 253, 0, 0, 253, 0, 0,
+ 0, 0, 253, 0, 253, 0, 0, 0, 0, 0,
+ 0, 0, 0, 253, 253, 253, 0, 0, 0, 0,
+ 0, 0, 253, 253, 0, 0, 0, 253, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 253,
+ 178, 0, 0, 0, 253, 0, 0, 0, 269, 253,
+ 0, 0, 0, 0, 269, 269, 0, 0, 0, 51,
+ 0, 253, 253, 0, 269, 269, 0, 269, 269, 253,
+ 253, 0, 362, 0, 0, 0, 0, 0, 269, 0,
+ 0, 0, 51, 0, 269, 269, 0, 0, 269, 269,
+ 269, 178, 269, 0, 269, 0, 0, 0, 269, 269,
+ 0, 0, 0, 0, 269, 0, 0, 0, 269, 269,
+ 0, 269, 269, 269, 176, 0, 0, 0, 0, 0,
+ 0, 0, 269, 0, 0, 0, 0, 269, 269, 269,
+ 0, 0, 269, 269, 269, 0, 0, 0, 269, 269,
+ 0, 0, 0, 0, 269, 0, 0, 0, 269, 269,
+ 0, 0, 0, 0, 0, 0, 0, 269, 0, 0,
+ 0, 269, 269, 0, 0, 0, 0, 0, 0, 269,
+ 269, 269, 51, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 269, 0, 0, 176, 0, 269, 230,
+ 0, 0, 0, 269, 0, 176, 176, 0, 176, 176,
+ 0, 0, 0, 0, 0, 269, 269, 0, 0, 176,
+ 0, 0, 230, 269, 269, 176, 176, 0, 362, 176,
+ 176, 176, 0, 0, 0, 176, 0, 362, 362, 0,
+ 362, 362, 0, 0, 0, 176, 0, 243, 0, 0,
+ 0, 362, 0, 0, 176, 0, 0, 362, 362, 0,
+ 0, 362, 362, 362, 0, 0, 0, 362, 176, 0,
+ 243, 0, 406, 0, 0, 0, 0, 362, 0, 0,
+ 176, 0, 0, 0, 0, 176, 362, 0, 0, 0,
+ 176, 0, 0, 0, 0, 406, 0, 0, 0, 0,
+ 362, 0, 176, 176, 0, 0, 0, 0, 0, 0,
+ 176, 176, 362, 0, 0, 0, 407, 362, 0, 0,
+ 0, 0, 362, 0, 0, 0, 243, 0, 51, 0,
+ 0, 0, 0, 0, 362, 362, 0, 51, 51, 407,
+ 51, 51, 362, 362, 0, 0, 0, 0, 0, 243,
+ 0, 51, 0, 0, 0, 0, 0, 51, 51, 0,
+ 176, 51, 51, 51, 0, 0, 0, 51, 0, 176,
+ 176, 0, 176, 176, 0, 0, 0, 51, 0, 0,
+ 0, 0, 0, 176, 0, 0, 51, 0, 0, 176,
+ 176, 0, 0, 176, 176, 176, 0, 0, 0, 176,
+ 51, 0, 0, 0, 0, 0, 0, 0, 0, 176,
+ 0, 0, 51, 0, 0, 0, 0, 51, 176, 0,
+ 0, 0, 51, 0, 0, 0, 0, 0, 0, 0,
+ 170, 0, 176, 0, 51, 51, 0, 0, 0, 0,
+ 0, 0, 51, 51, 176, 0, 0, 0, 0, 176,
+ 0, 230, 0, 0, 176, 230, 230, 230, 0, 0,
+ 0, 0, 230, 230, 230, 230, 176, 176, 0, 0,
+ 0, 0, 0, 0, 176, 176, 0, 0, 230, 230,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 223, 388, 0, 0, 0, 223, 0, 0, 0,
- 0, 223, 0, 0, 0, 0, 269, 0, 0, 0,
- 0, 0, 0, 223, 223, 269, 269, 0, 269, 269,
- 0, 223, 223, 0, 0, 269, 269, 269, 0, 269,
- 0, 0, 0, 0, 0, 269, 269, 0, 0, 269,
- 269, 269, 269, 0, 0, 269, 0, 0, 269, 0,
- 0, 0, 0, 0, 0, 269, 0, 0, 0, 0,
- 241, 269, 0, 269, 0, 0, 0, 0, 0, 0,
- 0, 0, 269, 269, 269, 269, 269, 269, 0, 0,
- 0, 0, 0, 241, 0, 0, 0, 0, 0, 269,
- 0, 0, 0, 0, 269, 0, 0, 0, 0, 269,
- 269, 0, 52, 0, 0, 0, 0, 0, 0, 0,
- 392, 269, 269, 0, 0, 392, 392, 392, 269, 269,
- 269, 392, 392, 392, 392, 52, 392, 392, 0, 392,
- 392, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 392, 0, 0, 0, 0, 0, 392, 392, 0, 0,
- 392, 392, 392, 0, 267, 0, 392, 0, 0, 0,
- 267, 0, 0, 0, 0, 0, 392, 0, 0, 0,
- 228, 0, 0, 0, 392, 0, 0, 0, 0, 0,
- 0, 267, 267, 390, 390, 390, 390, 390, 392, 0,
- 0, 0, 0, 228, 267, 0, 0, 267, 0, 0,
- 392, 0, 0, 267, 0, 392, 0, 0, 0, 0,
- 392, 390, 0, 0, 0, 52, 267, 0, 0, 0,
- 0, 388, 392, 392, 0, 0, 388, 388, 388, 0,
- 392, 392, 388, 388, 388, 388, 0, 388, 388, 0,
- 388, 388, 0, 0, 0, 0, 0, 0, 0, 267,
- 0, 388, 0, 0, 0, 0, 0, 388, 388, 0,
- 0, 388, 388, 388, 0, 0, 267, 388, 0, 0,
- 0, 0, 0, 267, 0, 0, 0, 388, 0, 0,
- 0, 241, 0, 0, 0, 388, 0, 0, 0, 0,
- 0, 0, 0, 0, 388, 388, 388, 388, 388, 388,
- 0, 0, 0, 0, 241, 0, 0, 0, 0, 0,
- 0, 388, 241, 0, 0, 0, 388, 241, 241, 0,
- 0, 388, 388, 241, 241, 241, 241, 0, 0, 0,
- 0, 0, 0, 388, 388, 0, 0, 0, 241, 0,
- 0, 388, 388, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 52, 52, 52, 0, 52, 52, 52,
- 52, 52, 0, 0, 0, 52, 52, 52, 52, 0,
- 52, 52, 0, 52, 52, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 52, 241, 241, 241, 241, 241,
- 52, 52, 223, 0, 52, 52, 52, 0, 0, 0,
- 52, 0, 0, 0, 0, 0, 0, 241, 0, 0,
- 52, 0, 0, 241, 0, 223, 0, 0, 52, 0,
- 0, 0, 228, 0, 241, 241, 228, 228, 228, 228,
- 0, 0, 52, 228, 228, 228, 228, 0, 228, 228,
- 0, 228, 228, 0, 52, 0, 0, 0, 0, 52,
- 0, 0, 228, 228, 52, 228, 228, 228, 228, 228,
- 0, 0, 228, 228, 228, 0, 52, 52, 228, 0,
- 0, 0, 0, 0, 52, 52, 0, 0, 228, 0,
- 0, 0, 0, 0, 0, 0, 228, 0, 0, 0,
+ 0, 230, 0, 0, 230, 0, 0, 0, 0, 243,
+ 230, 0, 0, 0, 243, 243, 0, 0, 0, 0,
+ 243, 243, 243, 243, 230, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 406, 0, 243, 243, 406, 406,
+ 406, 0, 0, 0, 0, 406, 406, 406, 406, 243,
+ 0, 0, 243, 0, 0, 0, 0, 230, 243, 0,
+ 406, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 243, 0, 230, 0, 0, 0, 407, 0,
+ 0, 230, 407, 407, 407, 0, 0, 0, 243, 407,
+ 407, 407, 407, 243, 243, 0, 0, 0, 0, 243,
+ 243, 243, 243, 0, 407, 243, 0, 0, 406, 406,
+ 406, 406, 406, 0, 243, 0, 0, 0, 0, 0,
+ 0, 0, 243, 0, 0, 0, 0, 0, 0, 243,
+ 406, 0, 0, 0, 0, 0, 406, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 406, 406, 0,
+ 0, 0, 407, 407, 407, 407, 407, 0, 0, 0,
+ 0, 0, 243, 243, 243, 243, 243, 0, 0, 0,
+ 0, 0, 0, 0, 407, 0, 590, 0, 0, 0,
+ 407, 0, 0, 0, 243, 591, 592, 0, 593, 594,
+ 243, 407, 407, 0, 0, 0, 0, 0, 0, 595,
+ 0, 243, 243, 0, 0, 596, 341, 0, 0, 597,
+ 598, 599, 0, 0, 0, 600, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 601, 0, 0, 0, 0,
+ 0, 0, 0, 0, 602, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 603, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 228, 0, 0, 226, 0, 223, 0, 0, 0, 0,
- 0, 0, 228, 0, 0, 0, 0, 228, 0, 0,
- 0, 0, 228, 0, 0, 0, 226, 0, 0, 0,
- 0, 0, 0, 241, 228, 228, 0, 0, 241, 241,
- 241, 0, 228, 228, 241, 241, 241, 241, 0, 241,
- 241, 0, 241, 241, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 241, 241, 0, 241, 241, 241, 241,
- 241, 0, 0, 241, 241, 241, 0, 0, 0, 241,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 241,
- 0, 0, 0, 0, 0, 0, 0, 241, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 241, 0, 0, 241, 0, 226, 0, 0, 0,
- 0, 0, 0, 241, 0, 0, 0, 0, 241, 0,
- 0, 0, 0, 241, 0, 0, 0, 241, 0, 0,
- 0, 0, 0, 0, 223, 241, 241, 223, 223, 223,
- 223, 223, 0, 241, 241, 223, 223, 223, 223, 0,
- 223, 223, 0, 223, 223, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 223, 0, 0, 0, 0, 0,
- 223, 223, 424, 0, 223, 223, 223, 0, 0, 0,
- 223, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 223, 0, 0, 0, 0, 424, 0, 0, 223, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 223, 0, 0, 0, 0, 241, 0, 0,
- 0, 0, 0, 0, 223, 0, 0, 0, 0, 223,
- 0, 0, 0, 0, 223, 0, 0, 0, 0, 0,
- 391, 0, 0, 0, 0, 226, 223, 223, 0, 226,
- 226, 226, 226, 0, 223, 223, 226, 226, 226, 226,
- 0, 226, 226, 391, 226, 226, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 226, 0, 0, 0, 0,
- 0, 226, 226, 0, 0, 226, 226, 226, 0, 0,
- 0, 226, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 226, 0, 0, 0, 0, 0, 0, 248, 226,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 226, 0, 0, 0, 0, 0, 0,
- 0, 248, 0, 0, 0, 226, 0, 0, 0, 0,
- 226, 0, 0, 0, 0, 226, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 241, 226, 226, 0,
- 0, 241, 241, 241, 0, 226, 226, 241, 241, 241,
- 241, 0, 241, 241, 0, 241, 241, 248, 0, 0,
- 0, 0, 0, 0, 0, 0, 241, 0, 0, 0,
- 0, 0, 241, 241, 0, 0, 241, 241, 241, 0,
- 248, 0, 241, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 241, 0, 0, 0, 0, 0, 0, 0,
- 241, 248, 0, 0, 424, 241, 0, 0, 0, 424,
- 424, 424, 0, 0, 241, 424, 424, 424, 424, 0,
- 424, 424, 0, 424, 424, 0, 241, 0, 241, 0,
- 0, 241, 0, 0, 424, 0, 241, 0, 0, 0,
- 424, 424, 0, 0, 424, 424, 424, 0, 241, 241,
- 424, 0, 0, 0, 0, 0, 241, 241, 0, 0,
- 424, 0, 0, 0, 0, 0, 0, 0, 424, 0,
- 0, 0, 391, 0, 251, 0, 0, 391, 391, 391,
- 0, 0, 424, 391, 391, 391, 391, 0, 391, 391,
- 0, 391, 391, 0, 424, 0, 0, 251, 0, 424,
- 0, 0, 391, 0, 424, 0, 0, 0, 391, 391,
- 0, 0, 391, 391, 391, 0, 424, 424, 391, 0,
- 0, 0, 0, 0, 424, 424, 251, 0, 391, 0,
- 0, 0, 0, 0, 0, 0, 391, 0, 0, 0,
- 248, 0, 0, 0, 0, 248, 248, 248, 0, 251,
- 391, 248, 0, 0, 248, 0, 248, 248, 0, 248,
- 248, 0, 391, 0, 0, 0, 0, 391, 0, 0,
- 248, 0, 391, 0, 0, 0, 248, 248, 0, 0,
- 248, 248, 248, 0, 391, 391, 248, 251, 0, 0,
- 0, 0, 391, 391, 0, 0, 248, 0, 0, 0,
- 0, 0, 0, 0, 248, 0, 0, 0, 0, 248,
- 0, 0, 0, 0, 248, 248, 248, 0, 248, 0,
- 248, 0, 0, 248, 267, 248, 248, 0, 248, 248,
- 248, 0, 0, 0, 0, 248, 0, 0, 0, 248,
- 248, 0, 0, 0, 0, 248, 248, 267, 0, 248,
- 248, 248, 248, 248, 0, 248, 0, 241, 0, 0,
- 248, 248, 241, 241, 0, 248, 0, 0, 241, 241,
- 241, 241, 0, 248, 0, 267, 0, 0, 0, 0,
- 0, 0, 0, 0, 241, 241, 0, 248, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 241, 267, 248,
- 241, 0, 0, 0, 248, 0, 241, 0, 0, 248,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 241,
- 0, 248, 248, 0, 0, 0, 251, 0, 0, 248,
- 248, 251, 251, 251, 0, 0, 0, 267, 0, 0,
- 251, 0, 251, 251, 0, 251, 251, 0, 0, 0,
- 0, 0, 241, 0, 0, 0, 251, 0, 0, 0,
- 0, 0, 251, 251, 176, 0, 251, 251, 251, 241,
- 0, 0, 251, 0, 0, 0, 241, 0, 251, 0,
- 0, 0, 251, 251, 251, 251, 0, 174, 0, 0,
- 251, 0, 251, 0, 251, 251, 0, 251, 251, 0,
- 0, 0, 0, 0, 251, 0, 0, 0, 251, 0,
- 360, 0, 0, 0, 251, 251, 251, 0, 251, 251,
- 251, 251, 0, 0, 251, 0, 251, 0, 0, 0,
- 0, 0, 0, 360, 251, 0, 0, 0, 251, 251,
- 0, 0, 251, 0, 0, 0, 251, 251, 0, 0,
- 0, 0, 0, 0, 0, 0, 251, 0, 0, 0,
- 0, 0, 49, 0, 0, 0, 0, 0, 251, 0,
- 0, 0, 0, 251, 0, 0, 267, 176, 251, 0,
- 0, 0, 267, 267, 0, 49, 0, 0, 0, 0,
- 251, 251, 267, 267, 0, 267, 267, 0, 251, 251,
- 0, 0, 0, 0, 0, 0, 267, 0, 176, 0,
- 0, 0, 267, 267, 0, 0, 267, 267, 267, 0,
- 0, 0, 267, 360, 0, 0, 0, 267, 0, 0,
- 0, 174, 267, 267, 267, 0, 0, 0, 0, 0,
- 267, 0, 0, 267, 267, 0, 267, 267, 0, 0,
- 0, 0, 0, 0, 267, 0, 0, 267, 0, 0,
- 0, 0, 0, 267, 267, 0, 267, 267, 267, 267,
- 0, 267, 0, 267, 0, 49, 267, 0, 0, 0,
- 0, 0, 0, 267, 0, 0, 0, 0, 267, 267,
- 0, 267, 0, 0, 0, 0, 267, 267, 0, 0,
- 0, 0, 0, 0, 0, 267, 0, 0, 0, 0,
- 0, 223, 0, 0, 0, 0, 0, 267, 0, 0,
- 0, 0, 267, 174, 0, 0, 0, 267, 0, 0,
- 0, 228, 174, 174, 223, 174, 174, 0, 0, 267,
- 267, 0, 0, 0, 0, 0, 174, 267, 267, 0,
- 0, 0, 174, 174, 228, 0, 174, 174, 174, 0,
- 0, 0, 174, 0, 404, 0, 0, 0, 0, 360,
- 0, 0, 174, 0, 0, 0, 0, 0, 360, 360,
- 174, 360, 360, 0, 0, 0, 0, 404, 0, 0,
- 0, 0, 360, 0, 174, 0, 405, 0, 360, 360,
- 0, 0, 360, 360, 360, 0, 174, 0, 360, 0,
- 0, 174, 0, 0, 0, 0, 174, 0, 360, 405,
- 0, 49, 0, 0, 0, 0, 360, 0, 174, 174,
- 49, 49, 0, 49, 49, 0, 174, 174, 0, 0,
- 360, 0, 248, 0, 49, 0, 0, 0, 0, 251,
- 49, 49, 360, 0, 49, 49, 49, 360, 0, 0,
- 49, 0, 360, 0, 0, 248, 0, 174, 0, 0,
- 49, 0, 251, 0, 360, 360, 174, 174, 49, 174,
- 174, 0, 360, 360, 0, 0, 0, 0, 0, 0,
- 174, 0, 49, 0, 0, 0, 174, 174, 0, 0,
- 174, 174, 174, 0, 49, 0, 174, 0, 0, 49,
- 0, 0, 0, 0, 49, 0, 174, 0, 0, 0,
- 0, 0, 0, 0, 174, 0, 49, 49, 0, 0,
- 0, 0, 0, 0, 49, 49, 0, 0, 174, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 174, 0, 167, 0, 0, 174, 0, 0, 0, 0,
- 174, 0, 0, 223, 0, 223, 223, 223, 223, 223,
- 0, 0, 174, 174, 223, 223, 223, 223, 0, 0,
- 174, 174, 0, 228, 0, 0, 0, 228, 228, 228,
- 223, 223, 0, 0, 228, 228, 228, 228, 0, 0,
- 0, 0, 0, 223, 0, 0, 223, 0, 0, 0,
- 228, 228, 223, 0, 0, 0, 404, 0, 0, 0,
- 404, 404, 404, 228, 0, 223, 228, 404, 404, 404,
- 404, 0, 228, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 404, 0, 0, 228, 0, 0, 405, 0,
- 0, 0, 405, 405, 405, 0, 0, 0, 223, 405,
- 405, 405, 405, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 405, 223, 0, 0, 228, 0,
- 0, 0, 223, 0, 0, 0, 0, 0, 0, 404,
- 404, 404, 404, 404, 248, 228, 0, 0, 0, 248,
- 248, 251, 228, 0, 0, 248, 251, 251, 248, 0,
- 0, 404, 0, 0, 0, 251, 0, 404, 0, 0,
- 248, 405, 405, 405, 405, 405, 0, 251, 404, 404,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 405, 0, 0, 0, 0, 0, 405,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 405, 405, 0, 0, 0, 0, 0, 248, 248, 248,
- 248, 248, 0, 0, 251, 251, 251, 251, 251, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 587, 248,
- 0, 0, 0, 0, 0, 248, 251, 588, 589, 0,
- 590, 591, 251, 0, 0, 0, 248, 248, 0, 0,
- 0, 592, 0, 251, 251, 0, 0, 593, 338, 0,
- 0, 594, 595, 596, 0, 0, 0, 597, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 598, 0, 0,
- 0, 0, 0, 0, 0, 599, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 600,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 601, 0, 0, 0, 0, 602, 0, 0, 0,
- 0, 603, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 604, 0, 0, 0, 0, 0,
- 0, 605, 606,
+ 604, 0, 0, 0, 0, 605, 0, 0, 0, 0,
+ 606, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 607, 0, 0, 0, 0, 0, 0,
+ 608, 609,
};
static const YYINT pfctlycheck[] = { 3,
- 3, 82, 11, 12, 324, 325, 126, 78, 10, 33,
- 10, 10, 191, 206, 33, 10, 44, 10, 10, 33,
- 10, 230, 40, 40, 10, 44, 44, 365, 366, 123,
- 528, 33, 10, 346, 204, 0, 368, 383, 651, 10,
- 33, 123, 33, 222, 713, 10, 166, 56, 428, 276,
- 123, 275, 10, 44, 512, 33, 44, 677, 40, 33,
- 33, 70, 267, 40, 33, 123, 169, 298, 273, 60,
- 61, 62, 81, 40, 123, 123, 40, 123, 40, 267,
- 10, 427, 10, 203, 10, 406, 407, 266, 276, 268,
- 682, 33, 44, 33, 60, 40, 177, 125, 40, 712,
- 279, 447, 423, 384, 724, 225, 125, 125, 40, 198,
- 199, 200, 781, 429, 536, 33, 442, 40, 60, 40,
- 60, 61, 62, 226, 123, 44, 40, 10, 123, 720,
- 44, 123, 10, 715, 125, 344, 634, 125, 331, 459,
- 44, 123, 60, 61, 62, 265, 60, 267, 33, 123,
- 123, 44, 125, 384, 123, 33, 335, 384, 328, 230,
- 280, 123, 282, 10, 477, 384, 44, 33, 626, 348,
- 550, 395, 764, 125, 353, 60, 61, 62, 510, 44,
- 44, 123, 60, 61, 62, 44, 33, 307, 534, 670,
- 33, 517, 614, 260, 60, 61, 62, 788, 44, 319,
- 546, 299, 784, 74, 10, 123, 125, 33, 723, 218,
- 299, 125, 294, 84, 85, 86, 336, 60, 61, 62,
- 384, 125, 401, 544, 33, 314, 40, 24, 10, 40,
- 409, 569, 125, 322, 60, 61, 62, 246, 10, 418,
- 721, 361, 309, 44, 266, 123, 425, 125, 40, 60,
- 384, 371, 568, 40, 264, 265, 435, 123, 55, 357,
- 125, 125, 359, 40, 314, 359, 125, 10, 60, 262,
- 390, 391, 33, 344, 267, 268, 791, 257, 367, 125,
- 400, 47, 402, 276, 264, 40, 288, 384, 288, 468,
- 384, 256, 257, 258, 259, 294, 289, 290, 10, 60,
- 61, 62, 384, 40, 277, 60, 377, 178, 277, 302,
- 288, 384, 305, 299, 123, 33, 436, 437, 311, 498,
- 285, 286, 287, 60, 125, 41, 384, 41, 299, 41,
- 288, 324, 44, 298, 262, 277, 384, 385, 384, 518,
- 268, 461, 60, 61, 62, 310, 261, 467, 263, 314,
- 315, 316, 317, 318, 474, 357, 384, 352, 300, 301,
- 384, 540, 541, 542, 357, 384, 384, 332, 385, 334,
- 384, 357, 374, 256, 257, 258, 341, 497, 557, 357,
- 123, 374, 374, 703, 374, 384, 357, 352, 381, 384,
- 706, 269, 571, 384, 385, 360, 374, 375, 362, 357,
- 278, 279, 384, 281, 282, 123, 44, 384, 385, 335,
- 336, 337, 338, 339, 292, 298, 374, 384, 538, 384,
- 298, 299, 384, 10, 302, 303, 304, 310, 44, 357,
- 308, 314, 315, 316, 317, 318, 556, 363, 558, 384,
- 318, 288, 384, 385, 384, 385, 33, 10, 326, 332,
- 570, 334, 384, 40, 41, 771, 40, 44, 341, 775,
- 531, 384, 340, 384, 584, 536, 384, 385, 277, 352,
- 384, 385, 44, 60, 352, 284, 60, 360, 61, 357,
- 262, 664, 288, 123, 362, 267, 268, 125, 335, 336,
- 337, 338, 339, 502, 276, 44, 374, 375, 123, 384,
- 385, 384, 685, 623, 382, 383, 384, 385, 628, 125,
- 357, 277, 583, 10, 10, 44, 363, 526, 384, 385,
- 699, 700, 701, 40, 605, 384, 385, 374, 10, 335,
- 336, 337, 338, 339, 10, 655, 123, 33, 125, 123,
- 660, 384, 385, 614, 44, 300, 301, 40, 668, 40,
- 729, 622, 731, 125, 41, 675, 10, 363, 384, 385,
- 123, 44, 741, 335, 336, 337, 338, 339, 747, 60,
- 384, 385, 751, 384, 385, 357, 125, 756, 10, 33,
- 759, 10, 45, 762, 47, 705, 40, 41, 708, 10,
- 44, 363, 384, 385, 306, 604, 125, 384, 385, 342,
- 343, 344, 345, 346, 347, 348, 60, 384, 385, 352,
- 353, 354, 41, 384, 268, 44, 328, 44, 384, 10,
- 740, 359, 276, 384, 385, 125, 707, 10, 748, 384,
- 385, 359, 752, 349, 350, 351, 645, 757, 10, 40,
- 760, 384, 125, 10, 358, 359, 384, 384, 385, 303,
- 304, 732, 364, 365, 366, 10, 384, 369, 370, 371,
- 10, 373, 10, 10, 376, 377, 384, 385, 384, 123,
- 384, 125, 384, 10, 293, 262, 295, 296, 297, 10,
- 800, 268, 269, 803, 804, 805, 806, 89, 697, 91,
- 277, 278, 279, 10, 281, 282, 384, 284, 125, 10,
- 349, 288, 289, 290, 10, 292, 355, 356, 285, 286,
- 287, 298, 299, 300, 301, 302, 303, 304, 305, 41,
- 10, 308, 44, 10, 311, 10, 268, 33, 809, 41,
- 41, 318, 44, 44, 276, 384, 33, 324, 44, 326,
- 384, 745, 745, 40, 384, 385, 376, 377, 335, 336,
- 337, 338, 339, 340, 60, 61, 62, 10, 384, 384,
- 385, 303, 304, 60, 10, 352, 262, 358, 359, 10,
- 357, 41, 268, 10, 44, 362, 363, 40, 125, 342,
- 343, 344, 345, 346, 347, 348, 264, 374, 375, 352,
- 353, 354, 288, 384, 381, 382, 383, 384, 385, 267,
- 384, 385, 10, 333, 10, 273, 274, 275, 262, 300,
- 301, 384, 385, 41, 268, 269, 44, 123, 265, 125,
- 62, 384, 307, 277, 278, 279, 123, 281, 282, 265,
- 284, 349, 350, 351, 288, 289, 290, 10, 292, 335,
- 336, 337, 338, 339, 298, 299, 300, 301, 302, 303,
- 304, 305, 41, 41, 308, 44, 44, 311, 384, 385,
- 33, 357, 349, 260, 318, 385, 384, 363, 355, 356,
- 324, 44, 326, 270, 271, 272, 385, 306, 374, 375,
- 10, 335, 336, 337, 338, 339, 340, 60, 61, 62,
- 262, 10, 60, 384, 385, 267, 268, 384, 352, 328,
- 44, 273, 41, 357, 276, 44, 274, 275, 362, 363,
- 257, 258, 309, 385, 33, 384, 385, 123, 384, 385,
- 374, 375, 595, 596, 367, 368, 10, 381, 382, 383,
- 384, 385, 359, 384, 385, 364, 365, 366, 259, 385,
- 369, 370, 371, 385, 373, 384, 385, 376, 377, 33,
- 123, 385, 125, 384, 385, 384, 262, 384, 384, 385,
- 44, 385, 268, 269, 285, 286, 287, 314, 315, 316,
- 317, 385, 278, 279, 385, 281, 282, 10, 384, 385,
- 277, 259, 288, 289, 290, 357, 292, 335, 336, 337,
- 338, 339, 298, 299, 384, 306, 302, 303, 304, 305,
- 33, 10, 308, 300, 301, 311, 352, 285, 286, 287,
- 267, 44, 318, 384, 385, 363, 385, 328, 324, 273,
- 326, 10, 311, 312, 313, 285, 286, 287, 41, 335,
- 336, 337, 338, 339, 340, 288, 10, 85, 86, 123,
- 384, 125, 384, 385, 384, 385, 352, 720, 384, 385,
- 723, 357, 47, 364, 365, 366, 362, 363, 369, 370,
- 371, 384, 373, 33, 10, 376, 377, 40, 374, 375,
- 384, 385, 40, 384, 40, 381, 382, 383, 384, 385,
- 384, 385, 335, 336, 337, 338, 339, 384, 385, 40,
- 123, 40, 125, 384, 385, 62, 269, 385, 306, 335,
- 336, 337, 338, 339, 357, 278, 279, 41, 281, 282,
- 363, 261, 262, 263, 123, 788, 384, 385, 791, 292,
- 328, 374, 384, 385, 10, 298, 299, 363, 41, 302,
- 303, 304, 384, 385, 123, 308, 342, 343, 344, 345,
- 346, 347, 348, 266, 267, 318, 352, 353, 354, 123,
- 273, 274, 275, 326, 302, 303, 364, 365, 366, 385,
- 385, 369, 370, 371, 10, 373, 385, 340, 376, 377,
- 289, 290, 384, 384, 375, 262, 384, 123, 384, 352,
- 41, 384, 357, 302, 357, 269, 305, 33, 372, 362,
- 384, 384, 311, 385, 278, 279, 267, 281, 282, 41,
- 41, 374, 375, 41, 384, 324, 284, 384, 292, 382,
- 383, 384, 385, 268, 298, 299, 33, 61, 302, 303,
- 304, 385, 367, 40, 308, 386, 61, 44, 61, 47,
- 380, 384, 384, 47, 318, 385, 269, 374, 357, 268,
- 41, 384, 326, 60, 385, 278, 279, 385, 281, 282,
- 41, 62, 385, 288, 123, 374, 340, 384, 384, 292,
- 385, 385, 381, 385, 374, 298, 299, 283, 352, 302,
- 303, 304, 283, 357, 385, 308, 283, 283, 362, 385,
- 374, 117, 118, 119, 434, 318, 385, 385, 385, 10,
- 374, 375, 10, 326, 284, 384, 47, 280, 382, 383,
- 384, 385, 280, 40, 386, 386, 123, 340, 125, 362,
- 384, 41, 284, 385, 384, 33, 41, 288, 41, 352,
- 10, 41, 10, 41, 357, 385, 44, 41, 164, 362,
- 284, 41, 333, 342, 343, 344, 345, 346, 347, 348,
- 10, 374, 375, 352, 353, 354, 384, 384, 10, 382,
- 383, 384, 385, 342, 343, 344, 345, 346, 347, 348,
- 10, 384, 267, 352, 353, 354, 10, 10, 342, 343,
- 344, 345, 346, 347, 348, 384, 262, 374, 362, 353,
- 354, 267, 268, 385, 33, 10, 10, 273, 274, 275,
- 276, 40, 597, 3, 71, 384, 342, 343, 344, 345,
- 346, 347, 348, 10, 732, 123, 809, 353, 354, 256,
- 384, 60, 463, 249, 456, 447, 262, 253, 547, 265,
- 266, 267, 268, 269, 260, 177, 33, 273, 274, 275,
- 276, 717, 278, 279, 217, 281, 282, 33, 384, 245,
- 274, 404, 288, 289, 290, 490, 292, 293, 412, 295,
- 296, 297, 298, 299, 495, 482, 302, 303, 304, 305,
- 277, 508, 308, 614, 342, 311, 172, 244, 304, 583,
- 321, 357, 318, 507, 123, 622, 125, 3, 324, 3,
- 326, -1, -1, 300, 301, -1, -1, 333, -1, 335,
- 336, 337, 338, 339, 340, -1, -1, 342, 343, 344,
- 345, 346, 347, 348, -1, -1, 352, 352, 353, 354,
- -1, 357, -1, 33, -1, -1, 362, 363, -1, -1,
- 40, -1, -1, -1, 44, -1, -1, -1, 374, 375,
- 10, -1, -1, -1, -1, 381, 382, 383, -1, -1,
- 60, 61, 62, -1, 262, -1, -1, -1, 266, 267,
- 268, 269, -1, 33, -1, 273, 274, 275, 276, -1,
- 278, 279, -1, 281, 282, -1, -1, 384, 385, -1,
- 288, 289, 290, -1, 292, -1, -1, -1, -1, 23,
- 298, 299, -1, -1, 302, 303, 304, 305, -1, -1,
- 308, -1, -1, 311, -1, -1, -1, -1, -1, -1,
- 318, -1, -1, 123, -1, 125, 324, -1, 326, -1,
- -1, -1, -1, 57, 58, 59, -1, 335, 336, 337,
- 338, 339, 340, -1, 68, -1, -1, 10, 277, -1,
- -1, -1, -1, -1, 352, -1, 80, -1, -1, 357,
- -1, -1, -1, -1, 362, 363, -1, -1, -1, -1,
- -1, 300, 301, 10, -1, 262, 374, 375, -1, 266,
- 267, 268, 269, 381, 382, 383, 273, 274, 275, 276,
- -1, 278, 279, -1, 281, 282, 33, -1, -1, -1,
- -1, -1, 289, 290, -1, 292, 293, -1, 295, 296,
- 297, 298, 299, 289, 290, 302, 303, 304, 305, -1,
- -1, 308, -1, -1, 311, -1, 302, -1, -1, 305,
- -1, 318, -1, -1, -1, 311, -1, 324, -1, 326,
- -1, 10, -1, -1, -1, -1, 333, -1, 324, -1,
- -1, -1, -1, 340, -1, 384, 385, -1, 182, 183,
- -1, -1, 125, 187, 33, 352, -1, -1, -1, -1,
- 357, -1, -1, 197, -1, 362, -1, 277, -1, -1,
- -1, 357, -1, -1, -1, -1, -1, 374, 375, -1,
- -1, -1, -1, -1, 381, 382, 383, -1, -1, -1,
- 300, 301, 262, -1, -1, 381, 266, 267, 268, 269,
- -1, -1, 306, 273, 274, 275, 276, -1, 278, 279,
- -1, 281, 282, -1, -1, -1, -1, -1, -1, 289,
- 290, -1, 292, 293, 328, 295, 296, 297, 298, 299,
- -1, -1, 302, 303, 304, 305, -1, -1, 308, -1,
- -1, 311, -1, -1, -1, -1, -1, -1, 318, 359,
- -1, -1, -1, -1, 324, 10, 326, -1, -1, -1,
- 364, 365, 366, 333, -1, 369, 370, 371, -1, 373,
- 340, -1, 376, 377, 384, 385, -1, -1, 33, -1,
- 384, -1, 352, 256, 257, 258, -1, 357, -1, -1,
- -1, -1, 362, -1, -1, 414, 415, 416, -1, -1,
- -1, -1, 421, 422, 374, 375, -1, -1, -1, -1,
- -1, 381, 382, 383, 261, 262, 263, 264, 265, 266,
- 267, 268, 269, -1, -1, 298, 273, 274, 275, 276,
+ 3, 83, 11, 12, 10, 10, 33, 127, 79, 327,
+ 328, 10, 10, 10, 10, 194, 10, 10, 40, 33,
+ 33, 10, 40, 40, 10, 371, 123, 33, 298, 349,
+ 44, 123, 209, 233, 278, 33, 123, 201, 202, 203,
+ 123, 685, 33, 123, 207, 40, 225, 56, 40, 169,
+ 409, 410, 44, 33, 123, 10, 368, 369, 531, 10,
+ 33, 515, 71, 260, 44, 431, 299, 426, 60, 0,
+ 123, 10, 40, 82, 123, 723, 386, 718, 40, 10,
+ 60, 61, 62, 40, 33, 123, 206, 60, 61, 62,
+ 269, 276, 271, 40, 33, 40, 667, 40, 180, 10,
+ 44, 123, 257, 282, 41, 716, 40, 44, 228, 264,
+ 44, 125, 309, 40, 539, 385, 40, 688, 10, 60,
+ 430, 10, 445, 767, 10, 358, 40, 10, 123, 123,
+ 123, 432, 123, 125, 44, 44, 60, 123, 302, 44,
+ 450, 33, 33, 791, 462, 125, 787, 347, 268, 44,
+ 270, 33, 40, 317, 398, 41, 33, 334, 44, 338,
+ 480, 325, 233, 283, 637, 285, 33, 513, 331, 60,
+ 61, 62, 351, 784, 123, 629, 40, 356, 60, 61,
+ 62, 125, 33, 60, 61, 62, 44, 553, 547, 654,
+ 310, 125, 617, 60, 61, 62, 60, 520, 260, 123,
+ 385, 673, 322, 10, 40, 385, 370, 294, 33, 60,
+ 61, 62, 221, 726, 385, 125, 125, 10, 40, 339,
+ 125, 266, 24, 267, 60, 404, 385, 537, 41, 273,
+ 125, 44, 123, 412, 44, 60, 61, 62, 60, 549,
+ 249, 123, 421, 33, 364, 385, 123, 309, 41, 428,
+ 715, 44, 724, 55, 374, 40, 44, 262, 44, 438,
+ 572, 33, 44, 268, 44, 61, 262, 125, 33, 10,
+ 571, 267, 268, 393, 394, 60, 347, 273, 274, 275,
+ 276, 794, 288, 403, 40, 405, 277, 47, 385, 386,
+ 288, 288, 471, 385, 386, 60, 61, 62, 385, 288,
+ 10, 294, 385, 386, 60, 385, 41, 262, 267, 380,
+ 10, 360, 267, 268, 314, 125, 385, 276, 273, 439,
+ 440, 276, 501, 262, 10, 256, 257, 258, 259, 268,
+ 10, 41, 385, 123, 44, 125, 385, 125, 41, 125,
+ 10, 44, 521, 125, 464, 125, 363, 10, 299, 288,
+ 470, 123, 358, 358, 285, 286, 287, 477, 385, 353,
+ 358, 358, 358, 385, 543, 544, 545, 298, 386, 375,
+ 376, 385, 385, 256, 257, 258, 375, 375, 375, 310,
+ 500, 560, 123, 314, 315, 316, 317, 318, 706, 375,
+ 385, 385, 385, 385, 386, 574, 288, 336, 337, 338,
+ 339, 340, 333, 358, 335, 385, 386, 358, 709, 10,
+ 299, 342, 385, 386, 10, 298, 41, 385, 386, 358,
+ 306, 541, 353, 385, 386, 364, 10, 310, 385, 386,
+ 361, 314, 315, 316, 317, 318, 375, 376, 385, 559,
+ 385, 561, 385, 329, 336, 337, 338, 339, 340, 33,
+ 333, 385, 335, 573, 385, 10, 40, 41, 385, 342,
+ 44, 385, 386, 534, 300, 301, 358, 587, 539, 358,
+ 353, 385, 364, 774, 10, 385, 60, 778, 361, 365,
+ 366, 367, 360, 375, 370, 371, 372, 277, 374, 10,
+ 172, 377, 378, 680, 385, 386, 505, 385, 386, 385,
+ 264, 265, 385, 385, 386, 277, 626, 385, 385, 386,
+ 10, 631, 284, 306, 44, 586, 10, 277, 385, 386,
+ 529, 385, 386, 702, 703, 704, 608, 385, 386, 336,
+ 337, 338, 339, 340, 385, 386, 329, 44, 658, 123,
+ 727, 125, 385, 663, 300, 301, 617, 229, 385, 385,
+ 386, 671, 44, 732, 625, 734, 44, 364, 678, 10,
+ 385, 386, 262, 385, 386, 744, 44, 267, 268, 360,
+ 44, 750, 365, 366, 367, 754, 276, 370, 371, 372,
+ 759, 374, 33, 762, 377, 378, 765, 10, 708, 40,
+ 41, 711, 385, 44, 385, 125, 306, 41, 607, 360,
+ 385, 386, 343, 344, 345, 346, 347, 348, 349, 60,
+ 40, 44, 353, 354, 355, 350, 351, 352, 125, 329,
+ 385, 386, 44, 743, 385, 385, 10, 10, 710, 385,
+ 386, 751, 261, 125, 263, 755, 45, 125, 47, 648,
+ 760, 268, 41, 763, 385, 44, 10, 125, 10, 276,
+ 385, 125, 33, 735, 10, 365, 366, 367, 358, 40,
+ 370, 371, 372, 41, 374, 40, 44, 377, 378, 10,
+ 75, 33, 123, 10, 125, 385, 303, 304, 262, 60,
+ 85, 86, 87, 803, 268, 269, 806, 807, 808, 809,
+ 10, 700, 125, 277, 278, 279, 10, 281, 282, 10,
+ 284, 385, 386, 125, 288, 289, 290, 41, 292, 10,
+ 44, 350, 351, 352, 298, 299, 300, 301, 302, 303,
+ 304, 305, 33, 10, 308, 350, 41, 311, 10, 44,
+ 812, 356, 357, 44, 318, 336, 337, 338, 339, 340,
+ 10, 325, 123, 327, 748, 748, 385, 377, 378, 60,
+ 61, 62, 336, 337, 338, 339, 340, 341, 274, 275,
+ 385, 350, 259, 364, 385, 386, 33, 356, 357, 353,
+ 268, 385, 386, 40, 358, 40, 181, 44, 276, 363,
+ 364, 336, 337, 338, 339, 340, 10, 385, 285, 286,
+ 287, 375, 376, 60, 288, 385, 385, 259, 382, 383,
+ 384, 385, 386, 10, 40, 303, 304, 385, 386, 364,
+ 260, 262, 123, 90, 125, 92, 264, 268, 269, 334,
+ 270, 271, 272, 285, 286, 287, 277, 278, 279, 265,
+ 281, 282, 10, 284, 368, 369, 123, 288, 289, 290,
+ 307, 292, 336, 337, 338, 339, 340, 298, 299, 300,
+ 301, 302, 303, 304, 305, 33, 123, 308, 125, 309,
+ 311, 285, 286, 287, 358, 62, 44, 318, 360, 386,
+ 364, 33, 385, 386, 325, 265, 327, 386, 40, 385,
+ 386, 375, 60, 61, 62, 336, 337, 338, 339, 340,
+ 341, 359, 360, 385, 385, 386, 277, 10, 60, 60,
+ 262, 386, 353, 386, 288, 267, 268, 358, 311, 312,
+ 313, 273, 363, 364, 276, 359, 360, 385, 125, 300,
+ 301, 10, 385, 386, 375, 376, 386, 289, 290, 385,
+ 386, 382, 383, 384, 385, 386, 44, 10, 385, 386,
+ 302, 385, 385, 305, 33, 123, 386, 125, 386, 311,
+ 267, 262, 336, 337, 338, 339, 340, 268, 269, 386,
+ 33, 123, 293, 325, 295, 296, 297, 278, 279, 386,
+ 281, 282, 10, 385, 386, 266, 267, 288, 289, 290,
+ 364, 292, 273, 274, 275, 385, 386, 298, 299, 385,
+ 386, 302, 303, 304, 305, 33, 358, 308, 385, 386,
+ 311, 285, 286, 287, 385, 386, 44, 318, 385, 386,
+ 277, 267, 273, 375, 325, 353, 327, 273, 274, 275,
+ 382, 386, 60, 61, 62, 336, 337, 338, 339, 340,
+ 341, 385, 386, 300, 301, 385, 386, 385, 386, 10,
+ 385, 386, 353, 86, 87, 305, 306, 358, 41, 385,
+ 257, 258, 363, 364, 33, 47, 343, 344, 345, 346,
+ 347, 348, 349, 385, 375, 376, 353, 354, 355, 41,
+ 40, 382, 383, 384, 385, 386, 40, 40, 40, 40,
+ 386, 386, 306, 386, 386, 123, 62, 125, 417, 418,
+ 419, 269, 41, 385, 262, 424, 425, 385, 385, 10,
+ 278, 279, 376, 281, 282, 329, 41, 314, 315, 316,
+ 317, 598, 599, 385, 292, 277, 358, 385, 385, 386,
+ 298, 299, 33, 373, 302, 303, 304, 386, 385, 41,
+ 308, 41, 41, 44, 118, 119, 120, 267, 300, 301,
+ 318, 365, 366, 367, 10, 385, 370, 371, 372, 327,
+ 374, 284, 123, 377, 378, 385, 268, 386, 487, 368,
+ 489, 385, 491, 341, 61, 494, 61, 61, 10, 264,
+ 265, 266, 387, 262, 47, 353, 47, 385, 267, 268,
+ 358, 385, 375, 167, 273, 363, 268, 276, 41, 262,
+ 385, 33, 10, 41, 267, 268, 386, 375, 376, 288,
+ 386, 62, 44, 276, 386, 383, 384, 385, 386, 288,
+ 385, 385, 123, 10, 125, 123, 289, 290, 336, 337,
+ 338, 339, 340, 385, 386, 375, 10, 386, 386, 302,
+ 386, 269, 305, 283, 283, 283, 723, 283, 311, 726,
+ 278, 279, 386, 281, 282, 386, 364, 336, 337, 338,
+ 339, 340, 325, 375, 292, 386, 284, 123, 386, 386,
+ 298, 299, 10, 280, 302, 303, 304, 47, 252, 358,
+ 308, 33, 256, 280, 385, 364, 40, 387, 40, 263,
+ 318, 123, 387, 125, 385, 358, 375, 376, 383, 327,
+ 284, 363, 41, 388, 623, 386, 41, 288, 60, 385,
+ 41, 41, 375, 341, 791, 123, 10, 794, 10, 382,
+ 386, 41, 41, 334, 10, 353, 284, 385, 385, 10,
+ 358, 10, 385, 307, 267, 363, 123, 10, 10, 343,
+ 344, 345, 346, 347, 348, 349, 375, 375, 376, 123,
+ 354, 355, 437, 10, 386, 383, 384, 385, 386, 10,
+ 33, 363, 10, 600, 3, 72, 735, 812, 269, 259,
+ 466, 123, 450, 125, 180, 459, 550, 278, 279, 720,
+ 281, 282, 343, 344, 345, 346, 347, 348, 349, 220,
+ 248, 292, 353, 354, 355, 277, 415, 298, 299, 407,
+ 493, 302, 303, 304, 498, 485, 511, 308, 617, 10,
+ 345, 175, 247, 586, 324, 625, 3, 318, 737, 738,
+ 739, 510, 3, -1, 385, -1, 327, 33, -1, -1,
+ -1, -1, -1, -1, 40, -1, -1, 269, 44, -1,
+ 341, -1, -1, -1, -1, -1, 278, 279, 33, 281,
+ 282, -1, 353, -1, 60, 61, 62, 358, -1, -1,
+ 292, -1, 363, -1, -1, -1, 298, 299, -1, -1,
+ 302, 303, 304, 10, 375, 376, 308, 10, -1, -1,
+ -1, -1, 383, 384, 385, 386, 318, 343, 344, 345,
+ 346, 347, 348, 349, -1, 327, 33, 353, 354, 355,
+ 33, -1, -1, -1, 41, -1, -1, 44, -1, 341,
+ -1, -1, -1, -1, -1, -1, -1, 123, -1, 125,
+ -1, 353, -1, -1, 125, 277, 358, -1, -1, 385,
+ -1, 363, -1, -1, -1, 343, 344, 345, 346, 347,
+ 348, 349, -1, 375, 376, 353, 354, 355, 300, 301,
+ -1, 383, 384, 385, 386, -1, 343, 344, 345, 346,
+ 347, 348, 349, -1, -1, -1, -1, 354, 355, 343,
+ 344, 345, 346, 347, 348, 349, -1, 385, -1, -1,
+ 354, 355, -1, -1, -1, -1, 123, -1, -1, 262,
+ -1, -1, 265, 266, 267, 268, 269, -1, 385, -1,
+ 273, 274, 275, 276, 10, 278, 279, -1, 281, 282,
+ -1, 385, -1, -1, -1, 288, 289, 290, -1, 292,
+ 293, -1, 295, 296, 297, 298, 299, 33, -1, 302,
+ 303, 304, 305, 385, 386, 308, -1, -1, 311, -1,
+ -1, -1, -1, 23, -1, 318, -1, -1, -1, -1,
+ -1, -1, 325, -1, 327, 256, 257, 258, -1, -1,
+ -1, 334, -1, 336, 337, 338, 339, 340, 341, -1,
+ -1, 277, -1, -1, -1, -1, -1, 57, 58, 59,
+ 353, -1, -1, -1, -1, 358, -1, -1, -1, 69,
+ 363, 364, -1, -1, 300, 301, -1, 298, -1, -1,
+ -1, 81, 375, 376, 289, 290, -1, -1, -1, 382,
+ 383, 384, -1, 314, 315, 316, 317, 302, -1, -1,
+ 305, -1, -1, 10, -1, 262, 311, -1, -1, 266,
+ 267, 268, 269, -1, -1, -1, 273, 274, 275, 276,
+ 325, 278, 279, -1, 281, 282, 33, -1, -1, -1,
+ -1, 288, 289, 290, 360, 292, 289, 290, -1, -1,
+ -1, 298, 299, -1, -1, 302, 303, 304, 305, 302,
+ -1, 308, 305, 358, 311, -1, -1, -1, 311, 385,
+ 386, 318, -1, -1, -1, -1, -1, -1, 325, -1,
+ 327, -1, 325, -1, -1, -1, -1, 382, -1, 336,
+ 337, 338, 339, 340, 341, 185, 186, -1, -1, -1,
+ 190, -1, -1, -1, -1, -1, 353, -1, -1, -1,
+ 200, 358, -1, -1, -1, 358, 363, 364, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 375, 376,
+ -1, -1, 375, -1, -1, 382, 383, 384, 10, 382,
+ -1, -1, -1, -1, -1, -1, 262, -1, -1, -1,
+ 266, 267, 268, 269, -1, 306, -1, 273, 274, 275,
+ 276, 33, 278, 279, -1, 281, 282, -1, -1, -1,
+ -1, -1, -1, 289, 290, -1, 292, 293, 329, 295,
+ 296, 297, 298, 299, -1, -1, 302, 303, 304, 305,
+ -1, -1, 308, -1, -1, 311, -1, -1, -1, -1,
+ -1, -1, 318, -1, -1, -1, -1, 10, -1, 325,
+ -1, 327, -1, -1, 365, 366, 367, -1, 334, 370,
+ 371, 372, -1, 374, -1, 341, 377, 378, -1, -1,
+ 33, -1, -1, -1, 385, -1, -1, 353, -1, -1,
+ -1, -1, 358, -1, -1, -1, -1, 363, -1, -1,
+ 10, 343, 344, 345, 346, 347, 348, 349, -1, 375,
+ 376, 353, 354, 355, -1, 262, 382, 383, 384, 266,
+ 267, 268, 269, 33, 306, -1, 273, 274, 275, 276,
-1, 278, 279, -1, 281, 282, -1, -1, -1, -1,
- -1, 314, 315, 316, 317, 292, 293, -1, 295, 296,
- 297, 298, 299, -1, -1, 302, 303, 304, -1, -1,
- -1, 308, -1, -1, -1, 484, -1, 486, -1, 488,
- -1, 318, 491, -1, -1, -1, -1, -1, 10, 326,
- -1, -1, 261, 262, 263, 264, 265, 266, 267, 268,
- 269, -1, -1, 340, 273, 274, 275, 276, -1, 278,
- 279, 33, 281, 282, 306, 352, -1, -1, -1, -1,
- 357, -1, -1, 292, 293, 362, 295, 296, 297, 298,
- 299, -1, -1, 302, 303, 304, 328, 374, 375, 308,
- -1, -1, -1, -1, -1, 382, 383, -1, -1, 318,
- -1, -1, -1, -1, -1, -1, -1, 326, 342, 343,
- 344, 345, 346, 347, 348, -1, -1, -1, 352, 353,
- 354, 340, 364, 365, 366, -1, -1, 369, 370, 371,
- -1, 373, -1, 352, 376, 377, 10, -1, 357, -1,
- -1, -1, 384, 362, -1, -1, 342, 343, 344, 345,
- 346, 347, 348, -1, -1, 374, 375, 353, 354, 33,
- -1, 620, -1, 382, 383, -1, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, -1, -1, -1, 273, 274,
- 275, 276, -1, 278, 279, -1, 281, 282, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 292, 293, -1,
- 295, 296, 297, 298, 299, -1, -1, 302, 303, 304,
- -1, -1, -1, 308, -1, -1, -1, -1, 10, -1,
- -1, -1, -1, 318, -1, -1, 319, 320, 321, 322,
- 323, 326, 325, -1, 327, -1, 329, 330, 331, -1,
- -1, 33, -1, -1, -1, 340, 10, -1, -1, 123,
- -1, -1, -1, -1, -1, -1, -1, 352, -1, -1,
- -1, -1, 357, -1, -1, -1, -1, 362, 361, 33,
- -1, -1, -1, -1, -1, 734, 735, 736, -1, 374,
- 375, -1, -1, -1, -1, 378, 379, 382, 383, 261,
+ -1, -1, 289, 290, -1, 292, 293, 329, 295, 296,
+ 297, 298, 299, -1, -1, 302, 303, 304, 305, -1,
+ -1, 308, -1, -1, 311, -1, -1, -1, -1, -1,
+ -1, 318, -1, -1, -1, -1, -1, -1, 325, -1,
+ 327, 10, -1, 365, 366, 367, -1, 334, 370, 371,
+ 372, -1, 374, -1, 341, 377, 378, -1, -1, -1,
+ -1, -1, -1, 385, 33, -1, 353, -1, -1, -1,
+ -1, 358, -1, -1, -1, -1, 363, -1, -1, -1,
+ 343, 344, 345, 346, 347, 348, 349, -1, 375, 376,
+ 353, 354, 355, -1, -1, 382, 383, 384, 10, 261,
262, 263, 264, 265, 266, 267, 268, 269, -1, -1,
-1, 273, 274, 275, 276, -1, 278, 279, -1, 281,
- 282, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 282, 33, -1, -1, -1, -1, -1, -1, -1, -1,
292, 293, -1, 295, 296, 297, 298, 299, -1, -1,
302, 303, 304, -1, -1, -1, 308, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 318, -1, -1, -1,
- -1, -1, -1, -1, 326, -1, -1, -1, -1, 123,
- -1, -1, -1, -1, -1, -1, -1, -1, 340, 10,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 352, -1, -1, -1, -1, 357, -1, -1, 262, -1,
- 362, -1, 33, -1, 268, 269, -1, -1, -1, -1,
- -1, -1, 374, 375, 278, 279, -1, 281, 282, -1,
- 382, 383, -1, -1, 288, 289, 290, -1, 292, -1,
- -1, -1, -1, -1, 298, 299, -1, -1, 302, 303,
- 304, 305, -1, -1, 308, -1, -1, 311, -1, -1,
- -1, -1, -1, -1, 318, -1, -1, -1, -1, -1,
- 324, -1, 326, -1, -1, -1, -1, -1, -1, -1,
- -1, 335, 336, 337, 338, 339, 340, 10, -1, -1,
- 262, -1, -1, -1, -1, 267, 268, -1, 352, -1,
- -1, 273, -1, 357, 276, -1, -1, -1, 362, 363,
- 33, -1, -1, -1, -1, -1, -1, 289, 290, -1,
- 374, 375, -1, -1, 268, 269, -1, 381, 382, 383,
- 302, -1, -1, 305, 278, 279, -1, 281, 282, 311,
- -1, -1, -1, -1, 288, 289, 290, -1, 292, -1,
- -1, -1, 324, -1, 298, 299, -1, -1, 302, 303,
+ -1, -1, -1, -1, -1, 327, -1, 10, 261, 262,
+ 263, 264, 265, 266, 267, 268, 269, -1, -1, 341,
+ 273, 274, 275, 276, -1, 278, 279, -1, 281, 282,
+ 33, 353, -1, -1, -1, -1, 358, -1, -1, 292,
+ 293, 363, 295, 296, 297, 298, 299, -1, -1, 302,
+ 303, 304, 262, 375, 376, 308, -1, -1, 268, -1,
+ -1, 383, 384, -1, -1, 318, -1, -1, -1, -1,
+ -1, -1, -1, -1, 327, -1, -1, -1, -1, 289,
+ 290, -1, -1, -1, -1, -1, -1, -1, 341, -1,
+ 10, -1, 302, -1, -1, 305, -1, -1, -1, -1,
+ 353, 311, -1, -1, -1, 358, 10, -1, -1, -1,
+ 363, -1, -1, 33, -1, 325, -1, -1, -1, -1,
+ -1, -1, 375, 376, -1, -1, -1, -1, -1, 33,
+ 383, 384, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, -1, -1, -1, 273, 274, 275, 276, 358, 278,
+ 279, -1, 281, 282, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 292, 293, 375, 295, 296, 297, 298,
+ 299, -1, 382, 302, 303, 304, -1, -1, -1, 308,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 318,
+ 262, -1, 264, 265, 266, 267, 268, -1, 327, -1,
+ -1, 273, 274, 275, 276, 10, -1, -1, -1, -1,
+ -1, -1, 341, -1, -1, -1, -1, 289, 290, 123,
+ -1, -1, -1, -1, 353, -1, -1, -1, 33, 358,
+ 302, -1, -1, 305, 363, -1, -1, -1, -1, 311,
+ -1, -1, -1, -1, -1, -1, 375, 376, -1, -1,
+ -1, -1, -1, 325, 383, 384, -1, -1, 261, 262,
+ 263, 264, 265, 266, 267, 268, 269, -1, -1, -1,
+ 273, 274, 275, 276, -1, 278, 279, -1, 281, 282,
+ -1, -1, -1, -1, -1, -1, 358, -1, -1, 292,
+ 293, -1, 295, 296, 297, 298, 299, -1, -1, 302,
+ 303, 304, -1, 375, -1, 308, -1, -1, -1, -1,
+ 382, -1, -1, -1, -1, 318, -1, -1, 123, -1,
+ -1, -1, -1, -1, 327, -1, -1, -1, 10, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 341, -1,
+ -1, -1, 262, -1, -1, -1, -1, 267, 268, -1,
+ 353, 33, -1, -1, -1, 358, 276, -1, 262, -1,
+ 363, -1, -1, -1, 268, 269, -1, -1, 288, 10,
+ -1, -1, 375, 376, 278, 279, -1, 281, 282, -1,
+ 383, 384, -1, -1, 288, 289, 290, -1, 292, -1,
+ -1, -1, 33, -1, 298, 299, -1, -1, 302, 303,
304, 305, -1, -1, 308, -1, -1, 311, -1, -1,
- -1, -1, -1, -1, 318, -1, -1, -1, -1, -1,
- 324, -1, 326, -1, -1, 357, -1, -1, -1, -1,
- -1, 335, 336, 337, 338, 339, 340, -1, 10, -1,
- 123, -1, 374, -1, -1, -1, -1, -1, 352, 381,
- -1, -1, -1, 357, -1, -1, -1, -1, 362, 363,
- -1, 33, -1, -1, -1, -1, -1, -1, -1, -1,
- 374, 375, -1, -1, -1, -1, -1, 381, 382, 383,
- -1, 262, 10, 264, 265, 266, 267, 268, 269, -1,
- -1, -1, 273, 274, 275, 276, -1, 278, 279, -1,
- 281, 282, -1, -1, -1, 33, -1, -1, -1, -1,
- -1, 292, 293, -1, 295, 296, 297, 298, 299, -1,
- -1, 302, 303, 304, -1, -1, -1, 308, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 318, -1, -1,
- -1, -1, -1, -1, -1, 326, -1, -1, -1, 10,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 340,
+ -1, -1, -1, -1, 318, -1, 336, 337, 338, 339,
+ 340, 325, -1, 327, -1, -1, -1, -1, -1, -1,
+ -1, -1, 336, 337, 338, 339, 340, 341, 358, -1,
+ -1, -1, -1, -1, 364, -1, -1, -1, -1, 353,
+ -1, -1, -1, -1, 358, 375, 376, -1, -1, 363,
+ 364, -1, -1, 268, 269, -1, -1, -1, -1, -1,
+ -1, 375, 376, 278, 279, -1, 281, 282, 382, 383,
+ 384, 10, 123, 288, 289, 290, -1, 292, -1, -1,
+ -1, -1, -1, 298, 299, -1, -1, 302, 303, 304,
+ 305, -1, -1, 308, 33, -1, 311, -1, -1, -1,
+ -1, -1, -1, 318, -1, -1, -1, -1, -1, -1,
+ 325, -1, 327, -1, -1, -1, -1, -1, -1, -1,
+ -1, 336, 337, 338, 339, 340, 341, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 353, -1,
+ -1, -1, -1, 358, -1, -1, -1, -1, 363, 364,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 352, 33, -1, -1, -1, 357, -1, -1, -1,
- -1, 362, -1, -1, -1, -1, 269, -1, -1, -1,
- -1, -1, -1, 374, 375, 278, 279, -1, 281, 282,
- -1, 382, 383, -1, -1, 288, 289, 290, -1, 292,
- -1, -1, -1, -1, -1, 298, 299, -1, -1, 302,
- 303, 304, 305, -1, -1, 308, -1, -1, 311, -1,
- -1, -1, -1, -1, -1, 318, -1, -1, -1, -1,
- 10, 324, -1, 326, -1, -1, -1, -1, -1, -1,
- -1, -1, 335, 336, 337, 338, 339, 340, -1, -1,
- -1, -1, -1, 33, -1, -1, -1, -1, -1, 352,
- -1, -1, -1, -1, 357, -1, -1, -1, -1, 362,
- 363, -1, 10, -1, -1, -1, -1, -1, -1, -1,
- 262, 374, 375, -1, -1, 267, 268, 269, 381, 382,
- 383, 273, 274, 275, 276, 33, 278, 279, -1, 281,
- 282, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 292, -1, -1, -1, -1, -1, 298, 299, -1, -1,
- 302, 303, 304, -1, 262, -1, 308, -1, -1, -1,
- 268, -1, -1, -1, -1, -1, 318, -1, -1, -1,
- 10, -1, -1, -1, 326, -1, -1, -1, -1, -1,
- -1, 289, 290, 335, 336, 337, 338, 339, 340, -1,
- -1, -1, -1, 33, 302, -1, -1, 305, -1, -1,
- 352, -1, -1, 311, -1, 357, -1, -1, -1, -1,
- 362, 363, -1, -1, -1, 123, 324, -1, -1, -1,
- -1, 262, 374, 375, -1, -1, 267, 268, 269, -1,
- 382, 383, 273, 274, 275, 276, -1, 278, 279, -1,
- 281, 282, -1, -1, -1, -1, -1, -1, -1, 357,
- -1, 292, -1, -1, -1, -1, -1, 298, 299, -1,
- -1, 302, 303, 304, -1, -1, 374, 308, -1, -1,
- -1, -1, -1, 381, -1, -1, -1, 318, -1, -1,
- -1, 10, -1, -1, -1, 326, -1, -1, -1, -1,
- -1, -1, -1, -1, 335, 336, 337, 338, 339, 340,
- -1, -1, -1, -1, 33, -1, -1, -1, -1, -1,
- -1, 352, 262, -1, -1, -1, 357, 267, 268, -1,
- -1, 362, 363, 273, 274, 275, 276, -1, -1, -1,
- -1, -1, -1, 374, 375, -1, -1, -1, 288, -1,
- -1, 382, 383, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 261, 262, 263, -1, 265, 266, 267,
- 268, 269, -1, -1, -1, 273, 274, 275, 276, -1,
- 278, 279, -1, 281, 282, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 292, 335, 336, 337, 338, 339,
- 298, 299, 10, -1, 302, 303, 304, -1, -1, -1,
- 308, -1, -1, -1, -1, -1, -1, 357, -1, -1,
- 318, -1, -1, 363, -1, 33, -1, -1, 326, -1,
- -1, -1, 262, -1, 374, 375, 266, 267, 268, 269,
- -1, -1, 340, 273, 274, 275, 276, -1, 278, 279,
- -1, 281, 282, -1, 352, -1, -1, -1, -1, 357,
- -1, -1, 292, 293, 362, 295, 296, 297, 298, 299,
- -1, -1, 302, 303, 304, -1, 374, 375, 308, -1,
- -1, -1, -1, -1, 382, 383, -1, -1, 318, -1,
- -1, -1, -1, -1, -1, -1, 326, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 340, -1, -1, 10, -1, 123, -1, -1, -1, -1,
- -1, -1, 352, -1, -1, -1, -1, 357, -1, -1,
- -1, -1, 362, -1, -1, -1, 33, -1, -1, -1,
- -1, -1, -1, 262, 374, 375, -1, -1, 267, 268,
- 269, -1, 382, 383, 273, 274, 275, 276, -1, 278,
+ 375, 376, -1, -1, -1, -1, -1, 382, 383, 384,
+ 262, -1, 264, 265, 266, 267, 268, 269, -1, -1,
+ -1, 273, 274, 275, 276, -1, 278, 279, -1, 281,
+ 282, 10, -1, -1, -1, -1, -1, -1, -1, -1,
+ 292, 293, -1, 295, 296, 297, 298, 299, -1, -1,
+ 302, 303, 304, -1, 33, -1, 308, -1, 269, -1,
+ -1, -1, -1, -1, -1, -1, 318, 278, 279, -1,
+ 281, 282, -1, -1, -1, 327, -1, 288, 289, 290,
+ -1, 292, -1, -1, -1, -1, -1, 298, 299, 341,
+ -1, 302, 303, 304, 305, -1, -1, 308, -1, -1,
+ 311, 353, -1, -1, -1, -1, 358, 318, -1, -1,
+ -1, 363, -1, -1, 325, -1, 327, -1, -1, -1,
+ -1, -1, -1, 375, 376, 336, 337, 338, 339, 340,
+ 341, 383, 384, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 353, -1, -1, -1, -1, 358, -1, -1,
+ -1, -1, 363, 364, -1, 10, -1, -1, -1, -1,
+ -1, -1, -1, 262, 375, 376, -1, -1, 267, 268,
+ 269, 382, 383, 384, 273, 274, 275, 276, 33, 278,
279, -1, 281, 282, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 292, 293, -1, 295, 296, 297, 298,
- 299, -1, -1, 302, 303, 304, -1, -1, -1, 308,
+ -1, -1, -1, 292, -1, -1, -1, -1, -1, 298,
+ 299, -1, 10, 302, 303, 304, -1, -1, -1, 308,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 318,
- -1, -1, -1, -1, -1, -1, -1, 326, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 340, -1, -1, 10, -1, 123, -1, -1, -1,
- -1, -1, -1, 352, -1, -1, -1, -1, 357, -1,
- -1, -1, -1, 362, -1, -1, -1, 33, -1, -1,
- -1, -1, -1, -1, 262, 374, 375, 265, 266, 267,
- 268, 269, -1, 382, 383, 273, 274, 275, 276, -1,
- 278, 279, -1, 281, 282, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 292, -1, -1, -1, -1, -1,
- 298, 299, 10, -1, 302, 303, 304, -1, -1, -1,
- 308, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 318, -1, -1, -1, -1, 33, -1, -1, 326, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 340, -1, -1, -1, -1, 123, -1, -1,
- -1, -1, -1, -1, 352, -1, -1, -1, -1, 357,
- -1, -1, -1, -1, 362, -1, -1, -1, -1, -1,
- 10, -1, -1, -1, -1, 262, 374, 375, -1, 266,
- 267, 268, 269, -1, 382, 383, 273, 274, 275, 276,
- -1, 278, 279, 33, 281, 282, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 292, -1, -1, -1, -1,
- -1, 298, 299, -1, -1, 302, 303, 304, -1, -1,
- -1, 308, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 318, -1, -1, -1, -1, -1, -1, 10, 326,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 340, -1, -1, -1, -1, -1, -1,
- -1, 33, -1, -1, -1, 352, -1, -1, -1, -1,
- 357, -1, -1, -1, -1, 362, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 262, 374, 375, -1,
- -1, 267, 268, 269, -1, 382, 383, 273, 274, 275,
- 276, -1, 278, 279, -1, 281, 282, 10, -1, -1,
- -1, -1, -1, -1, -1, -1, 292, -1, -1, -1,
+ -1, -1, -1, -1, -1, 33, -1, -1, 327, -1,
+ -1, -1, -1, -1, -1, -1, -1, 336, 337, 338,
+ 339, 340, 341, -1, 319, 320, 321, 322, 323, 324,
+ -1, 326, -1, 328, 353, 330, 331, 332, -1, 358,
+ -1, -1, -1, -1, 363, 364, -1, -1, 123, -1,
+ -1, -1, -1, -1, -1, -1, 375, 376, -1, -1,
+ -1, -1, -1, 262, 383, 384, -1, 362, 267, 268,
+ 269, -1, -1, -1, 273, 274, 275, 276, -1, 278,
+ 279, -1, 281, 282, 379, 380, -1, -1, -1, -1,
+ -1, -1, -1, 292, 10, -1, -1, -1, -1, 298,
+ 299, -1, -1, 302, 303, 304, -1, -1, -1, 308,
+ -1, -1, -1, -1, -1, -1, -1, 33, -1, 318,
+ -1, -1, -1, -1, -1, -1, -1, -1, 327, -1,
+ -1, -1, -1, -1, -1, -1, -1, 336, 337, 338,
+ 339, 340, 341, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 353, -1, -1, -1, -1, 358,
+ -1, -1, -1, -1, 363, 364, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 375, 376, -1, -1,
+ -1, -1, -1, -1, 383, 384, 261, 262, 263, -1,
+ 265, 266, 267, 268, 269, -1, -1, -1, 273, 274,
+ 275, 276, -1, 278, 279, -1, 281, 282, -1, -1,
+ -1, -1, -1, -1, 10, -1, -1, 292, -1, -1,
+ -1, -1, -1, 298, 299, -1, -1, 302, 303, 304,
+ -1, -1, -1, 308, 262, -1, -1, 33, 266, 267,
+ 268, 269, -1, 318, -1, 273, 274, 275, 276, -1,
+ 278, 279, 327, 281, 282, -1, -1, -1, -1, -1,
+ -1, 10, -1, -1, 292, 293, 341, 295, 296, 297,
+ 298, 299, -1, -1, 302, 303, 304, -1, 353, -1,
+ 308, -1, -1, 358, 33, -1, -1, -1, 363, -1,
+ 318, -1, -1, -1, -1, -1, -1, -1, -1, 327,
+ 375, 376, -1, -1, -1, -1, -1, -1, 383, 384,
+ -1, -1, -1, 341, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 353, -1, 123, -1, -1,
+ 358, -1, -1, -1, -1, 363, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 262, 375, 376, -1,
+ -1, 267, 268, 269, -1, 383, 384, 273, 274, 275,
+ 276, -1, 278, 279, -1, 281, 282, -1, -1, -1,
+ -1, -1, -1, -1, 123, -1, 292, 293, -1, 295,
+ 296, 297, 298, 299, 10, -1, 302, 303, 304, -1,
+ -1, -1, 308, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 318, -1, -1, -1, -1, 33, -1, -1,
+ -1, 327, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 341, -1, -1, -1, -1,
+ -1, 10, -1, -1, -1, -1, -1, 353, -1, -1,
+ -1, -1, 358, -1, -1, -1, -1, 363, -1, -1,
+ -1, -1, -1, -1, 33, -1, -1, -1, -1, 375,
+ 376, -1, -1, -1, -1, -1, 262, 383, 384, 265,
+ 266, 267, 268, 269, -1, -1, -1, 273, 274, 275,
+ 276, -1, 278, 279, -1, 281, 282, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 292, 123, -1, -1,
-1, -1, 298, 299, -1, -1, 302, 303, 304, -1,
- 33, -1, 308, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 318, -1, -1, -1, -1, -1, -1, -1,
- 326, 123, -1, -1, 262, 10, -1, -1, -1, 267,
- 268, 269, -1, -1, 340, 273, 274, 275, 276, -1,
- 278, 279, -1, 281, 282, -1, 352, -1, 33, -1,
- -1, 357, -1, -1, 292, -1, 362, -1, -1, -1,
- 298, 299, -1, -1, 302, 303, 304, -1, 374, 375,
- 308, -1, -1, -1, -1, -1, 382, 383, -1, -1,
- 318, -1, -1, -1, -1, -1, -1, -1, 326, -1,
- -1, -1, 262, -1, 10, -1, -1, 267, 268, 269,
- -1, -1, 340, 273, 274, 275, 276, -1, 278, 279,
- -1, 281, 282, -1, 352, -1, -1, 33, -1, 357,
- -1, -1, 292, -1, 362, -1, -1, -1, 298, 299,
- -1, -1, 302, 303, 304, -1, 374, 375, 308, -1,
- -1, -1, -1, -1, 382, 383, 10, -1, 318, -1,
- -1, -1, -1, -1, -1, -1, 326, -1, -1, -1,
- 262, -1, -1, -1, -1, 267, 268, 269, -1, 33,
- 340, 273, -1, -1, 276, -1, 278, 279, -1, 281,
- 282, -1, 352, -1, -1, -1, -1, 357, -1, -1,
- 292, -1, 362, -1, -1, -1, 298, 299, -1, -1,
- 302, 303, 304, -1, 374, 375, 308, 123, -1, -1,
- -1, -1, 382, 383, -1, -1, 318, -1, -1, -1,
- -1, -1, -1, -1, 326, -1, -1, -1, -1, 262,
- -1, -1, -1, -1, 267, 268, 269, -1, 340, -1,
- 273, -1, -1, 276, 10, 278, 279, -1, 281, 282,
- 352, -1, -1, -1, -1, 357, -1, -1, -1, 292,
- 362, -1, -1, -1, -1, 298, 299, 33, -1, 302,
- 303, 304, 374, 375, -1, 308, -1, 262, -1, -1,
- 382, 383, 267, 268, -1, 318, -1, -1, 273, 274,
- 275, 276, -1, 326, -1, 10, -1, -1, -1, -1,
- -1, -1, -1, -1, 289, 290, -1, 340, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 302, 33, 352,
- 305, -1, -1, -1, 357, -1, 311, -1, -1, 362,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 324,
- -1, 374, 375, -1, -1, -1, 262, -1, -1, 382,
- 383, 267, 268, 269, -1, -1, -1, 123, -1, -1,
+ -1, -1, 308, 262, -1, -1, -1, 266, 267, 268,
+ 269, -1, 318, -1, 273, 274, 275, 276, -1, 278,
+ 279, 327, 281, 282, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 292, -1, 341, -1, -1, -1, 298,
+ 299, 10, -1, 302, 303, 304, -1, 353, -1, 308,
+ -1, -1, 358, -1, -1, -1, -1, 363, -1, 318,
+ -1, -1, -1, -1, 33, -1, -1, -1, 327, 375,
+ 376, -1, -1, -1, -1, -1, -1, 383, 384, -1,
+ -1, -1, 341, -1, -1, 10, -1, -1, -1, -1,
+ -1, -1, -1, -1, 353, -1, -1, -1, -1, 358,
+ -1, -1, -1, -1, 363, -1, -1, -1, 33, -1,
+ -1, -1, -1, -1, -1, -1, 375, 376, -1, -1,
+ -1, -1, -1, -1, 383, 384, 262, -1, -1, 10,
+ -1, 267, 268, 269, -1, -1, -1, 273, 274, 275,
276, -1, 278, 279, -1, 281, 282, -1, -1, -1,
- -1, -1, 357, -1, -1, -1, 292, -1, -1, -1,
- -1, -1, 298, 299, 10, -1, 302, 303, 304, 374,
- -1, -1, 308, -1, -1, -1, 381, -1, 262, -1,
- -1, -1, 318, 267, 268, 269, -1, 33, -1, -1,
- 326, -1, 276, -1, 278, 279, -1, 281, 282, -1,
- -1, -1, -1, -1, 340, -1, -1, -1, 292, -1,
- 10, -1, -1, -1, 298, 299, 352, -1, 302, 303,
- 304, 357, -1, -1, 308, -1, 362, -1, -1, -1,
- -1, -1, -1, 33, 318, -1, -1, -1, 374, 375,
- -1, -1, 326, -1, -1, -1, 382, 383, -1, -1,
- -1, -1, -1, -1, -1, -1, 340, -1, -1, -1,
- -1, -1, 10, -1, -1, -1, -1, -1, 352, -1,
- -1, -1, -1, 357, -1, -1, 262, 123, 362, -1,
- -1, -1, 268, 269, -1, 33, -1, -1, -1, -1,
- 374, 375, 278, 279, -1, 281, 282, -1, 382, 383,
- -1, -1, -1, -1, -1, -1, 292, -1, 10, -1,
+ -1, -1, 33, -1, -1, -1, 292, -1, -1, -1,
-1, -1, 298, 299, -1, -1, 302, 303, 304, -1,
- -1, -1, 308, 123, -1, -1, -1, 262, -1, -1,
- -1, 33, 318, 268, 269, -1, -1, -1, -1, -1,
- 326, -1, -1, 278, 279, -1, 281, 282, -1, -1,
- -1, -1, -1, -1, 340, -1, -1, 292, -1, -1,
- -1, -1, -1, 298, 299, -1, 352, 302, 303, 304,
- -1, 357, -1, 308, -1, 123, 362, -1, -1, -1,
- -1, -1, -1, 318, -1, -1, -1, -1, 374, 375,
- -1, 326, -1, -1, -1, -1, 382, 383, -1, -1,
- -1, -1, -1, -1, -1, 340, -1, -1, -1, -1,
- -1, 10, -1, -1, -1, -1, -1, 352, -1, -1,
- -1, -1, 357, 269, -1, -1, -1, 362, -1, -1,
- -1, 10, 278, 279, 33, 281, 282, -1, -1, 374,
- 375, -1, -1, -1, -1, -1, 292, 382, 383, -1,
- -1, -1, 298, 299, 33, -1, 302, 303, 304, -1,
- -1, -1, 308, -1, 10, -1, -1, -1, -1, 269,
- -1, -1, 318, -1, -1, -1, -1, -1, 278, 279,
- 326, 281, 282, -1, -1, -1, -1, 33, -1, -1,
- -1, -1, 292, -1, 340, -1, 10, -1, 298, 299,
- -1, -1, 302, 303, 304, -1, 352, -1, 308, -1,
- -1, 357, -1, -1, -1, -1, 362, -1, 318, 33,
- -1, 269, -1, -1, -1, -1, 326, -1, 374, 375,
- 278, 279, -1, 281, 282, -1, 382, 383, -1, -1,
- 340, -1, 10, -1, 292, -1, -1, -1, -1, 10,
- 298, 299, 352, -1, 302, 303, 304, 357, -1, -1,
- 308, -1, 362, -1, -1, 33, -1, 269, -1, -1,
- 318, -1, 33, -1, 374, 375, 278, 279, 326, 281,
- 282, -1, 382, 383, -1, -1, -1, -1, -1, -1,
- 292, -1, 340, -1, -1, -1, 298, 299, -1, -1,
- 302, 303, 304, -1, 352, -1, 308, -1, -1, 357,
- -1, -1, -1, -1, 362, -1, 318, -1, -1, -1,
- -1, -1, -1, -1, 326, -1, 374, 375, -1, -1,
- -1, -1, -1, -1, 382, 383, -1, -1, 340, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 352, -1, 33, -1, -1, 357, -1, -1, -1, -1,
- 362, -1, -1, 262, -1, 264, 265, 266, 267, 268,
- -1, -1, 374, 375, 273, 274, 275, 276, -1, -1,
- 382, 383, -1, 262, -1, -1, -1, 266, 267, 268,
- 289, 290, -1, -1, 273, 274, 275, 276, -1, -1,
- -1, -1, -1, 302, -1, -1, 305, -1, -1, -1,
- 289, 290, 311, -1, -1, -1, 262, -1, -1, -1,
- 266, 267, 268, 302, -1, 324, 305, 273, 274, 275,
- 276, -1, 311, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 288, -1, -1, 324, -1, -1, 262, -1,
- -1, -1, 266, 267, 268, -1, -1, -1, 357, 273,
- 274, 275, 276, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 288, 374, -1, -1, 357, -1,
- -1, -1, 381, -1, -1, -1, -1, -1, -1, 335,
- 336, 337, 338, 339, 262, 374, -1, -1, -1, 267,
- 268, 262, 381, -1, -1, 273, 267, 268, 276, -1,
- -1, 357, -1, -1, -1, 276, -1, 363, -1, -1,
- 288, 335, 336, 337, 338, 339, -1, 288, 374, 375,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 357, -1, -1, -1, -1, -1, 363,
+ -1, -1, 308, 262, -1, -1, -1, -1, 267, 268,
+ 269, -1, 318, -1, 273, 274, 275, 276, -1, 278,
+ 279, 327, 281, 282, -1, -1, -1, -1, 123, -1,
+ -1, -1, -1, 292, -1, 341, -1, -1, -1, 298,
+ 299, -1, -1, 302, 303, 304, -1, 353, -1, 308,
+ -1, -1, 358, -1, -1, -1, -1, 363, -1, 318,
+ -1, -1, -1, -1, -1, -1, -1, -1, 327, 375,
+ 376, -1, -1, -1, -1, -1, -1, 383, 384, 10,
+ -1, -1, 341, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 353, -1, -1, -1, -1, 358,
+ -1, -1, 33, -1, 363, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 375, 376, -1, -1,
+ -1, -1, -1, 262, 383, 384, 10, -1, 267, 268,
+ 269, -1, -1, -1, 273, 274, 275, 276, -1, 278,
+ 279, -1, 281, 282, -1, -1, -1, -1, -1, 33,
+ -1, -1, -1, 292, -1, -1, -1, -1, -1, 298,
+ 299, -1, -1, 302, 303, 304, -1, 262, -1, 308,
+ -1, -1, 267, 268, 269, -1, -1, -1, 273, 318,
+ -1, 276, -1, 278, 279, -1, 281, 282, 327, -1,
+ -1, -1, 123, -1, -1, -1, -1, 292, -1, -1,
+ -1, -1, 341, 298, 299, -1, -1, 302, 303, 304,
+ -1, 262, -1, 308, 353, -1, 267, 268, 269, 358,
+ -1, -1, 273, 318, 363, 276, 10, 278, 279, -1,
+ 281, 282, 327, -1, -1, -1, 375, 376, -1, -1,
+ -1, 292, -1, -1, 383, 384, 341, 298, 299, 33,
+ -1, 302, 303, 304, -1, -1, -1, 308, 353, -1,
+ -1, -1, -1, 358, -1, -1, -1, 318, 363, -1,
+ 10, -1, -1, -1, -1, -1, 327, -1, -1, -1,
+ 375, 376, -1, -1, -1, -1, -1, -1, 383, 384,
+ 341, -1, -1, 33, -1, -1, -1, -1, -1, -1,
+ -1, -1, 353, -1, -1, -1, -1, 358, -1, -1,
+ -1, -1, 363, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 375, 376, -1, -1, -1, -1,
+ -1, 262, 383, 384, -1, -1, 267, 268, 269, 123,
+ -1, -1, -1, -1, -1, 276, -1, 278, 279, -1,
+ 281, 282, -1, -1, -1, -1, -1, 10, -1, -1,
+ -1, 292, -1, -1, -1, -1, -1, 298, 299, -1,
+ -1, 302, 303, 304, -1, -1, -1, 308, 262, -1,
+ 33, -1, -1, 267, 268, 269, -1, 318, -1, 10,
+ -1, -1, 276, -1, 278, 279, 327, 281, 282, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 292, -1,
+ 341, -1, 33, -1, 298, 299, -1, -1, 302, 303,
+ 304, -1, 353, -1, 308, -1, -1, 358, -1, -1,
+ -1, -1, 363, -1, 318, -1, -1, -1, -1, -1,
+ -1, -1, -1, 327, 375, 376, -1, -1, -1, -1,
+ -1, -1, 383, 384, -1, -1, -1, 341, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 123, -1, -1, -1, 358, -1, -1, -1, 262, 363,
+ -1, -1, -1, -1, 268, 269, -1, -1, -1, 10,
+ -1, 375, 376, -1, 278, 279, -1, 281, 282, 383,
+ 384, -1, 123, -1, -1, -1, -1, -1, 292, -1,
+ -1, -1, 33, -1, 298, 299, -1, -1, 302, 303,
+ 304, 10, 262, -1, 308, -1, -1, -1, 268, 269,
+ -1, -1, -1, -1, 318, -1, -1, -1, 278, 279,
+ -1, 281, 282, 327, 33, -1, -1, -1, -1, -1,
+ -1, -1, 292, -1, -1, -1, -1, 341, 298, 299,
+ -1, -1, 302, 303, 304, -1, -1, -1, 308, 353,
+ -1, -1, -1, -1, 358, -1, -1, -1, 318, 363,
+ -1, -1, -1, -1, -1, -1, -1, 327, -1, -1,
+ -1, 375, 376, -1, -1, -1, -1, -1, -1, 383,
+ 384, 341, 123, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 353, -1, -1, 269, -1, 358, 10,
+ -1, -1, -1, 363, -1, 278, 279, -1, 281, 282,
+ -1, -1, -1, -1, -1, 375, 376, -1, -1, 292,
+ -1, -1, 33, 383, 384, 298, 299, -1, 269, 302,
+ 303, 304, -1, -1, -1, 308, -1, 278, 279, -1,
+ 281, 282, -1, -1, -1, 318, -1, 10, -1, -1,
+ -1, 292, -1, -1, 327, -1, -1, 298, 299, -1,
+ -1, 302, 303, 304, -1, -1, -1, 308, 341, -1,
+ 33, -1, 10, -1, -1, -1, -1, 318, -1, -1,
+ 353, -1, -1, -1, -1, 358, 327, -1, -1, -1,
+ 363, -1, -1, -1, -1, 33, -1, -1, -1, -1,
+ 341, -1, 375, 376, -1, -1, -1, -1, -1, -1,
+ 383, 384, 353, -1, -1, -1, 10, 358, -1, -1,
+ -1, -1, 363, -1, -1, -1, 10, -1, 269, -1,
+ -1, -1, -1, -1, 375, 376, -1, 278, 279, 33,
+ 281, 282, 383, 384, -1, -1, -1, -1, -1, 33,
+ -1, 292, -1, -1, -1, -1, -1, 298, 299, -1,
+ 269, 302, 303, 304, -1, -1, -1, 308, -1, 278,
+ 279, -1, 281, 282, -1, -1, -1, 318, -1, -1,
+ -1, -1, -1, 292, -1, -1, 327, -1, -1, 298,
+ 299, -1, -1, 302, 303, 304, -1, -1, -1, 308,
+ 341, -1, -1, -1, -1, -1, -1, -1, -1, 318,
+ -1, -1, 353, -1, -1, -1, -1, 358, 327, -1,
+ -1, -1, 363, -1, -1, -1, -1, -1, -1, -1,
+ 33, -1, 341, -1, 375, 376, -1, -1, -1, -1,
+ -1, -1, 383, 384, 353, -1, -1, -1, -1, 358,
+ -1, 262, -1, -1, 363, 266, 267, 268, -1, -1,
+ -1, -1, 273, 274, 275, 276, 375, 376, -1, -1,
+ -1, -1, -1, -1, 383, 384, -1, -1, 289, 290,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 374, 375, -1, -1, -1, -1, -1, 335, 336, 337,
- 338, 339, -1, -1, 335, 336, 337, 338, 339, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 269, 357,
- -1, -1, -1, -1, -1, 363, 357, 278, 279, -1,
- 281, 282, 363, -1, -1, -1, 374, 375, -1, -1,
- -1, 292, -1, 374, 375, -1, -1, 298, 299, -1,
- -1, 302, 303, 304, -1, -1, -1, 308, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 318, -1, -1,
- -1, -1, -1, -1, -1, 326, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 340,
+ -1, 302, -1, -1, 305, -1, -1, -1, -1, 262,
+ 311, -1, -1, -1, 267, 268, -1, -1, -1, -1,
+ 273, 274, 275, 276, 325, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 262, -1, 289, 290, 266, 267,
+ 268, -1, -1, -1, -1, 273, 274, 275, 276, 302,
+ -1, -1, 305, -1, -1, -1, -1, 358, 311, -1,
+ 288, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 325, -1, 375, -1, -1, -1, 262, -1,
+ -1, 382, 266, 267, 268, -1, -1, -1, 262, 273,
+ 274, 275, 276, 267, 268, -1, -1, -1, -1, 273,
+ 274, 275, 276, -1, 288, 358, -1, -1, 336, 337,
+ 338, 339, 340, -1, 288, -1, -1, -1, -1, -1,
+ -1, -1, 375, -1, -1, -1, -1, -1, -1, 382,
+ 358, -1, -1, -1, -1, -1, 364, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 375, 376, -1,
+ -1, -1, 336, 337, 338, 339, 340, -1, -1, -1,
+ -1, -1, 336, 337, 338, 339, 340, -1, -1, -1,
+ -1, -1, -1, -1, 358, -1, 269, -1, -1, -1,
+ 364, -1, -1, -1, 358, 278, 279, -1, 281, 282,
+ 364, 375, 376, -1, -1, -1, -1, -1, -1, 292,
+ -1, 375, 376, -1, -1, 298, 299, -1, -1, 302,
+ 303, 304, -1, -1, -1, 308, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 318, -1, -1, -1, -1,
+ -1, -1, -1, -1, 327, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 341, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 352, -1, -1, -1, -1, 357, -1, -1, -1,
- -1, 362, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 375, -1, -1, -1, -1, -1,
- -1, 382, 383,
+ 353, -1, -1, -1, -1, 358, -1, -1, -1, -1,
+ 363, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 376, -1, -1, -1, -1, -1, -1,
+ 383, 384,
};
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
-#define YYMAXTOKEN 386
-#define YYUNDFTOKEN 557
+#define YYMAXTOKEN 387
+#define YYUNDFTOKEN 558
#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
#if YYDEBUG
static const char *const pfctlyname[] = {
@@ -2070,8 +2083,8 @@ static const char *const pfctlyname[] = {
"URPFFAILED","FRAGMENT","USER","GROUP","MAXMSS","MAXIMUM","TTL","TOS","DROP",
"TABLE","REASSEMBLE","FRAGDROP","FRAGCROP","ANCHOR","NATANCHOR","RDRANCHOR",
"BINATANCHOR","SET","OPTIMIZATION","TIMEOUT","LIMIT","LOGINTERFACE",
-"BLOCKPOLICY","RANDOMID","REQUIREORDER","SYNPROXY","FINGERPRINTS","NOSYNC",
-"DEBUG","SKIP","HOSTID","ANTISPOOF","FOR","INCLUDE","BITMASK","RANDOM",
+"BLOCKPOLICY","FAILPOLICY","RANDOMID","REQUIREORDER","SYNPROXY","FINGERPRINTS",
+"NOSYNC","DEBUG","SKIP","HOSTID","ANTISPOOF","FOR","INCLUDE","BITMASK","RANDOM",
"SOURCEHASH","ROUNDROBIN","STATICPORT","PROBABILITY","ALTQ","CBQ","CODEL",
"PRIQ","HFSC","FAIRQ","BANDWIDTH","TBRSIZE","LINKSHARE","REALTIME","UPPERLIMIT",
"QUEUE","PRIORITY","QLIMIT","HOGS","BUCKETS","RTABLE","TARGET","INTERVAL",
@@ -2122,6 +2135,8 @@ static const char *const pfctlyrule[] = {
"option : SET HOSTID number",
"option : SET BLOCKPOLICY DROP",
"option : SET BLOCKPOLICY RETURN",
+"option : SET FAILPOLICY DROP",
+"option : SET FAILPOLICY RETURN",
"option : SET REQUIREORDER yesno",
"option : SET FINGERPRINTS STRING",
"option : SET STATEPOLICY statelock",
@@ -2569,7 +2584,7 @@ typedef struct {
} YYSTACKDATA;
/* variables for the parser stack */
static YYSTACKDATA yystack;
-#line 4556 "parse.y"
+#line 4579 "parse.y"
#ifdef __rtems__
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static YYSTACKDATA yystack);
#endif /* __rtems__ */
@@ -3508,6 +3523,7 @@ lookup(char *s)
{ "drop", DROP},
{ "drop-ovl", FRAGDROP},
{ "dup-to", DUPTO},
+ { "fail-policy", FAILPOLICY},
{ "fairq", FAIRQ},
{ "fastroute", FASTROUTE},
{ "file", FILENAME},
@@ -3972,6 +3988,7 @@ parse_config(char *filename, struct pfctl *xpf)
returnicmp6default =
(ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
blockpolicy = PFRULE_DROP;
+ failpolicy = PFRULE_DROP;
require_order = 1;
if ((file = pushfile(filename, 0)) == NULL) {
@@ -4365,7 +4382,7 @@ rt_tableid_max(void)
return (RT_TABLEID_MAX);
#endif
}
-#line 4371 "parse.c"
+#line 4388 "parse.c"
#if YYDEBUG
#include <stdio.h> /* needed for printf */
@@ -4565,11 +4582,11 @@ yyreduce:
switch (yyn)
{
case 17:
-#line 558 "parse.y"
+#line 562 "parse.y"
{ file->errors++; }
break;
case 18:
-#line 561 "parse.y"
+#line 565 "parse.y"
{
struct file *nfile;
@@ -4585,7 +4602,7 @@ case 18:
}
break;
case 25:
-#line 588 "parse.y"
+#line 592 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "none"))
yyval.v.i = 0;
@@ -4600,7 +4617,7 @@ case 25:
}
break;
case 26:
-#line 602 "parse.y"
+#line 606 "parse.y"
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free(yystack.l_mark[0].v.string);
@@ -4615,7 +4632,7 @@ case 26:
}
break;
case 27:
-#line 614 "parse.y"
+#line 618 "parse.y"
{
if (!(pf->opts & PF_OPT_OPTIMIZE)) {
pf->opts |= PF_OPT_OPTIMIZE;
@@ -4624,7 +4641,7 @@ case 27:
}
break;
case 32:
-#line 624 "parse.y"
+#line 628 "parse.y"
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free(yystack.l_mark[0].v.string);
@@ -4639,7 +4656,7 @@ case 32:
}
break;
case 33:
-#line 636 "parse.y"
+#line 640 "parse.y"
{
if (yystack.l_mark[0].v.number == 0 || yystack.l_mark[0].v.number > UINT_MAX) {
yyerror("hostid must be non-zero");
@@ -4652,7 +4669,7 @@ case 33:
}
break;
case 34:
-#line 646 "parse.y"
+#line 650 "parse.y"
{
if (pf->opts & PF_OPT_VERBOSE)
printf("set block-policy drop\n");
@@ -4662,7 +4679,7 @@ case 34:
}
break;
case 35:
-#line 653 "parse.y"
+#line 657 "parse.y"
{
if (pf->opts & PF_OPT_VERBOSE)
printf("set block-policy return\n");
@@ -4672,7 +4689,27 @@ case 35:
}
break;
case 36:
-#line 660 "parse.y"
+#line 664 "parse.y"
+ {
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set fail-policy drop\n");
+ if (check_rulestate(PFCTL_STATE_OPTION))
+ YYERROR;
+ failpolicy = PFRULE_DROP;
+ }
+break;
+case 37:
+#line 671 "parse.y"
+ {
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set fail-policy return\n");
+ if (check_rulestate(PFCTL_STATE_OPTION))
+ YYERROR;
+ failpolicy = PFRULE_RETURN;
+ }
+break;
+case 38:
+#line 678 "parse.y"
{
if (pf->opts & PF_OPT_VERBOSE)
printf("set require-order %s\n",
@@ -4680,8 +4717,8 @@ case 36:
require_order = yystack.l_mark[0].v.number;
}
break;
-case 37:
-#line 666 "parse.y"
+case 39:
+#line 684 "parse.y"
{
if (pf->opts & PF_OPT_VERBOSE)
printf("set fingerprints \"%s\"\n", yystack.l_mark[0].v.string);
@@ -4701,8 +4738,8 @@ case 37:
free(yystack.l_mark[0].v.string);
}
break;
-case 38:
-#line 684 "parse.y"
+case 40:
+#line 702 "parse.y"
{
if (pf->opts & PF_OPT_VERBOSE)
switch (yystack.l_mark[0].v.i) {
@@ -4716,8 +4753,8 @@ case 38:
default_statelock = yystack.l_mark[0].v.i;
}
break;
-case 39:
-#line 696 "parse.y"
+case 41:
+#line 714 "parse.y"
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free(yystack.l_mark[0].v.string);
@@ -4731,8 +4768,8 @@ case 39:
free(yystack.l_mark[0].v.string);
}
break;
-case 40:
-#line 708 "parse.y"
+case 42:
+#line 726 "parse.y"
{
if (expand_skip_interface(yystack.l_mark[0].v.interface) != 0) {
yyerror("error setting skip interface(s)");
@@ -4740,8 +4777,8 @@ case 40:
}
}
break;
-case 41:
-#line 714 "parse.y"
+case 43:
+#line 732 "parse.y"
{
if (keep_state_defaults != NULL) {
yyerror("cannot redefine state-defaults");
@@ -4750,20 +4787,20 @@ case 41:
keep_state_defaults = yystack.l_mark[0].v.state_opt;
}
break;
-case 42:
-#line 723 "parse.y"
+case 44:
+#line 741 "parse.y"
{ yyval.v.string = yystack.l_mark[0].v.string; }
break;
-case 43:
-#line 724 "parse.y"
+case 45:
+#line 742 "parse.y"
{
if ((yyval.v.string = strdup("all")) == NULL) {
err(1, "stringall: strdup");
}
}
break;
-case 44:
-#line 731 "parse.y"
+case 46:
+#line 749 "parse.y"
{
if (asprintf(&yyval.v.string, "%s %s", yystack.l_mark[-1].v.string, yystack.l_mark[0].v.string) == -1)
err(1, "string: asprintf");
@@ -4771,8 +4808,8 @@ case 44:
free(yystack.l_mark[0].v.string);
}
break;
-case 46:
-#line 740 "parse.y"
+case 48:
+#line 758 "parse.y"
{
if (asprintf(&yyval.v.string, "%s %s", yystack.l_mark[-1].v.string, yystack.l_mark[0].v.string) == -1)
err(1, "string: asprintf");
@@ -4780,8 +4817,8 @@ case 46:
free(yystack.l_mark[0].v.string);
}
break;
-case 48:
-#line 749 "parse.y"
+case 50:
+#line 767 "parse.y"
{
char *s;
if (asprintf(&s, "%lld", (long long)yystack.l_mark[0].v.number) == -1) {
@@ -4791,8 +4828,8 @@ case 48:
yyval.v.string = s;
}
break;
-case 50:
-#line 760 "parse.y"
+case 52:
+#line 778 "parse.y"
{
if (pf->opts & PF_OPT_VERBOSE)
printf("%s = \"%s\"\n", yystack.l_mark[-2].v.string, yystack.l_mark[0].v.string);
@@ -4802,16 +4839,16 @@ case 50:
free(yystack.l_mark[0].v.string);
}
break;
-case 51:
-#line 770 "parse.y"
+case 53:
+#line 788 "parse.y"
{ yyval.v.string = yystack.l_mark[0].v.string; }
break;
-case 52:
-#line 771 "parse.y"
+case 54:
+#line 789 "parse.y"
{ yyval.v.string = NULL; }
break;
-case 57:
-#line 781 "parse.y"
+case 59:
+#line 799 "parse.y"
{
char ta[PF_ANCHOR_NAME_SIZE];
struct pf_ruleset *rs;
@@ -4830,16 +4867,16 @@ case 57:
pf->anchor = rs->anchor;
}
break;
-case 58:
-#line 798 "parse.y"
+case 60:
+#line 816 "parse.y"
{
pf->alast = pf->anchor;
pf->asd--;
pf->anchor = pf->astack[pf->asd];
}
break;
-case 60:
-#line 808 "parse.y"
+case 62:
+#line 826 "parse.y"
{
struct pf_rule r;
struct node_proto *proto;
@@ -4973,8 +5010,8 @@ case 60:
pf->astack[pf->asd + 1] = NULL;
}
break;
-case 61:
-#line 940 "parse.y"
+case 63:
+#line 958 "parse.y"
{
struct pf_rule r;
@@ -4997,8 +5034,8 @@ case 61:
free(yystack.l_mark[-5].v.string);
}
break;
-case 62:
-#line 961 "parse.y"
+case 64:
+#line 979 "parse.y"
{
struct pf_rule r;
@@ -5042,8 +5079,8 @@ case 62:
free(yystack.l_mark[-5].v.string);
}
break;
-case 63:
-#line 1003 "parse.y"
+case 65:
+#line 1021 "parse.y"
{
struct pf_rule r;
@@ -5080,8 +5117,8 @@ case 63:
free(yystack.l_mark[-5].v.string);
}
break;
-case 64:
-#line 1040 "parse.y"
+case 66:
+#line 1058 "parse.y"
{
struct loadanchors *loadanchor;
@@ -5113,8 +5150,8 @@ case 64:
free(yystack.l_mark[0].v.string);
}
break;
-case 65:
-#line 1071 "parse.y"
+case 67:
+#line 1089 "parse.y"
{
yyval.v.b.b2 = yyval.v.b.w = 0;
if (yystack.l_mark[-1].v.i)
@@ -5123,8 +5160,8 @@ case 65:
yyval.v.b.b1 = PF_SCRUB;
}
break;
-case 66:
-#line 1081 "parse.y"
+case 68:
+#line 1099 "parse.y"
{
struct pf_rule r;
@@ -5181,27 +5218,27 @@ case 66:
NULL, NULL, NULL, "");
}
break;
-case 67:
-#line 1138 "parse.y"
+case 69:
+#line 1156 "parse.y"
{
bzero(&scrub_opts, sizeof scrub_opts);
scrub_opts.rtableid = -1;
}
break;
-case 68:
-#line 1143 "parse.y"
+case 70:
+#line 1161 "parse.y"
{ yyval.v.scrub_opts = scrub_opts; }
break;
-case 69:
-#line 1144 "parse.y"
+case 71:
+#line 1162 "parse.y"
{
bzero(&scrub_opts, sizeof scrub_opts);
scrub_opts.rtableid = -1;
yyval.v.scrub_opts = scrub_opts;
}
break;
-case 72:
-#line 1155 "parse.y"
+case 74:
+#line 1173 "parse.y"
{
if (scrub_opts.nodf) {
yyerror("no-df cannot be respecified");
@@ -5210,8 +5247,8 @@ case 72:
scrub_opts.nodf = 1;
}
break;
-case 73:
-#line 1162 "parse.y"
+case 75:
+#line 1180 "parse.y"
{
if (scrub_opts.marker & SOM_MINTTL) {
yyerror("min-ttl cannot be respecified");
@@ -5225,8 +5262,8 @@ case 73:
scrub_opts.minttl = yystack.l_mark[0].v.number;
}
break;
-case 74:
-#line 1174 "parse.y"
+case 76:
+#line 1192 "parse.y"
{
if (scrub_opts.marker & SOM_MAXMSS) {
yyerror("max-mss cannot be respecified");
@@ -5240,8 +5277,8 @@ case 74:
scrub_opts.maxmss = yystack.l_mark[0].v.number;
}
break;
-case 75:
-#line 1186 "parse.y"
+case 77:
+#line 1204 "parse.y"
{
if (scrub_opts.marker & SOM_SETTOS) {
yyerror("set-tos cannot be respecified");
@@ -5251,8 +5288,8 @@ case 75:
scrub_opts.settos = yystack.l_mark[0].v.number;
}
break;
-case 76:
-#line 1194 "parse.y"
+case 78:
+#line 1212 "parse.y"
{
if (scrub_opts.marker & SOM_FRAGCACHE) {
yyerror("fragcache cannot be respecified");
@@ -5262,8 +5299,8 @@ case 76:
scrub_opts.fragcache = yystack.l_mark[0].v.i;
}
break;
-case 77:
-#line 1202 "parse.y"
+case 79:
+#line 1220 "parse.y"
{
if (strcasecmp(yystack.l_mark[0].v.string, "tcp") != 0) {
yyerror("scrub reassemble supports only tcp, "
@@ -5279,8 +5316,8 @@ case 77:
scrub_opts.reassemble_tcp = 1;
}
break;
-case 78:
-#line 1216 "parse.y"
+case 80:
+#line 1234 "parse.y"
{
if (scrub_opts.randomid) {
yyerror("random-id cannot be respecified");
@@ -5289,8 +5326,8 @@ case 78:
scrub_opts.randomid = 1;
}
break;
-case 79:
-#line 1223 "parse.y"
+case 81:
+#line 1241 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > rt_tableid_max()) {
yyerror("invalid rtable id");
@@ -5299,27 +5336,27 @@ case 79:
scrub_opts.rtableid = yystack.l_mark[0].v.number;
}
break;
-case 80:
-#line 1230 "parse.y"
+case 82:
+#line 1248 "parse.y"
{
scrub_opts.match_tag = yystack.l_mark[0].v.string;
scrub_opts.match_tag_not = yystack.l_mark[-2].v.number;
}
break;
-case 81:
-#line 1236 "parse.y"
+case 83:
+#line 1254 "parse.y"
{ yyval.v.i = 0; /* default */ }
break;
-case 82:
-#line 1237 "parse.y"
+case 84:
+#line 1255 "parse.y"
{ yyval.v.i = 0; }
break;
-case 83:
-#line 1238 "parse.y"
+case 85:
+#line 1256 "parse.y"
{ yyval.v.i = 0; }
break;
-case 84:
-#line 1241 "parse.y"
+case 86:
+#line 1259 "parse.y"
{
struct pf_rule r;
struct node_host *h = NULL, *hh;
@@ -5406,58 +5443,58 @@ case 84:
free(yystack.l_mark[0].v.antispoof_opts.label);
}
break;
-case 85:
-#line 1328 "parse.y"
+case 87:
+#line 1346 "parse.y"
{ yyval.v.interface = yystack.l_mark[0].v.interface; }
break;
-case 86:
-#line 1329 "parse.y"
+case 88:
+#line 1347 "parse.y"
{ yyval.v.interface = yystack.l_mark[-1].v.interface; }
break;
-case 87:
-#line 1332 "parse.y"
+case 89:
+#line 1350 "parse.y"
{ yyval.v.interface = yystack.l_mark[-1].v.interface; }
break;
-case 88:
-#line 1333 "parse.y"
+case 90:
+#line 1351 "parse.y"
{
yystack.l_mark[-3].v.interface->tail->next = yystack.l_mark[-1].v.interface;
yystack.l_mark[-3].v.interface->tail = yystack.l_mark[-1].v.interface;
yyval.v.interface = yystack.l_mark[-3].v.interface;
}
break;
-case 89:
-#line 1340 "parse.y"
+case 91:
+#line 1358 "parse.y"
{ yyval.v.interface = yystack.l_mark[0].v.interface; }
break;
-case 90:
-#line 1341 "parse.y"
+case 92:
+#line 1359 "parse.y"
{
yystack.l_mark[-1].v.interface->dynamic = 1;
yyval.v.interface = yystack.l_mark[-1].v.interface;
}
break;
-case 91:
-#line 1347 "parse.y"
+case 93:
+#line 1365 "parse.y"
{
bzero(&antispoof_opts, sizeof antispoof_opts);
antispoof_opts.rtableid = -1;
}
break;
-case 92:
-#line 1352 "parse.y"
+case 94:
+#line 1370 "parse.y"
{ yyval.v.antispoof_opts = antispoof_opts; }
break;
-case 93:
-#line 1353 "parse.y"
+case 95:
+#line 1371 "parse.y"
{
bzero(&antispoof_opts, sizeof antispoof_opts);
antispoof_opts.rtableid = -1;
yyval.v.antispoof_opts = antispoof_opts;
}
break;
-case 96:
-#line 1364 "parse.y"
+case 98:
+#line 1382 "parse.y"
{
if (antispoof_opts.label) {
yyerror("label cannot be redefined");
@@ -5466,8 +5503,8 @@ case 96:
antispoof_opts.label = yystack.l_mark[0].v.string;
}
break;
-case 97:
-#line 1371 "parse.y"
+case 99:
+#line 1389 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > rt_tableid_max()) {
yyerror("invalid rtable id");
@@ -5476,16 +5513,16 @@ case 97:
antispoof_opts.rtableid = yystack.l_mark[0].v.number;
}
break;
-case 98:
-#line 1380 "parse.y"
+case 100:
+#line 1398 "parse.y"
{ yyval.v.number = 1; }
break;
-case 99:
-#line 1381 "parse.y"
+case 101:
+#line 1399 "parse.y"
{ yyval.v.number = 0; }
break;
-case 100:
-#line 1384 "parse.y"
+case 102:
+#line 1402 "parse.y"
{
struct node_host *h, *nh;
struct node_tinit *ti, *nti;
@@ -5515,27 +5552,27 @@ case 100:
}
}
break;
-case 101:
-#line 1414 "parse.y"
+case 103:
+#line 1432 "parse.y"
{
bzero(&table_opts, sizeof table_opts);
SIMPLEQ_INIT(&table_opts.init_nodes);
}
break;
-case 102:
-#line 1419 "parse.y"
+case 104:
+#line 1437 "parse.y"
{ yyval.v.table_opts = table_opts; }
break;
-case 103:
-#line 1421 "parse.y"
+case 105:
+#line 1439 "parse.y"
{
bzero(&table_opts, sizeof table_opts);
SIMPLEQ_INIT(&table_opts.init_nodes);
yyval.v.table_opts = table_opts;
}
break;
-case 106:
-#line 1432 "parse.y"
+case 108:
+#line 1450 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "const"))
table_opts.flags |= PFR_TFLAG_CONST;
@@ -5551,12 +5588,12 @@ case 106:
free(yystack.l_mark[0].v.string);
}
break;
-case 107:
-#line 1446 "parse.y"
+case 109:
+#line 1464 "parse.y"
{ table_opts.init_addr = 1; }
break;
-case 108:
-#line 1447 "parse.y"
+case 110:
+#line 1465 "parse.y"
{
struct node_host *n;
struct node_tinit *ti;
@@ -5598,8 +5635,8 @@ case 108:
table_opts.init_addr = 1;
}
break;
-case 109:
-#line 1487 "parse.y"
+case 111:
+#line 1505 "parse.y"
{
struct node_tinit *ti;
@@ -5611,8 +5648,8 @@ case 109:
table_opts.init_addr = 1;
}
break;
-case 110:
-#line 1499 "parse.y"
+case 112:
+#line 1517 "parse.y"
{
struct pf_altq a;
@@ -5636,8 +5673,8 @@ case 110:
YYERROR;
}
break;
-case 111:
-#line 1523 "parse.y"
+case 113:
+#line 1541 "parse.y"
{
struct pf_altq a;
@@ -5674,8 +5711,8 @@ case 111:
}
}
break;
-case 112:
-#line 1560 "parse.y"
+case 114:
+#line 1578 "parse.y"
{
bzero(&queue_opts, sizeof queue_opts);
queue_opts.priority = DEFAULT_PRIORITY;
@@ -5684,12 +5721,12 @@ case 112:
queue_opts.queue_bwspec.bw_percent = 100;
}
break;
-case 113:
-#line 1568 "parse.y"
+case 115:
+#line 1586 "parse.y"
{ yyval.v.queue_opts = queue_opts; }
break;
-case 114:
-#line 1569 "parse.y"
+case 116:
+#line 1587 "parse.y"
{
bzero(&queue_opts, sizeof queue_opts);
queue_opts.priority = DEFAULT_PRIORITY;
@@ -5699,8 +5736,8 @@ case 114:
yyval.v.queue_opts = queue_opts;
}
break;
-case 117:
-#line 1583 "parse.y"
+case 119:
+#line 1601 "parse.y"
{
if (queue_opts.marker & QOM_BWSPEC) {
yyerror("bandwidth cannot be respecified");
@@ -5710,8 +5747,8 @@ case 117:
queue_opts.queue_bwspec = yystack.l_mark[0].v.queue_bwspec;
}
break;
-case 118:
-#line 1591 "parse.y"
+case 120:
+#line 1609 "parse.y"
{
if (queue_opts.marker & QOM_PRIORITY) {
yyerror("priority cannot be respecified");
@@ -5725,8 +5762,8 @@ case 118:
queue_opts.priority = yystack.l_mark[0].v.number;
}
break;
-case 119:
-#line 1603 "parse.y"
+case 121:
+#line 1621 "parse.y"
{
if (queue_opts.marker & QOM_QLIMIT) {
yyerror("qlimit cannot be respecified");
@@ -5740,8 +5777,8 @@ case 119:
queue_opts.qlimit = yystack.l_mark[0].v.number;
}
break;
-case 120:
-#line 1615 "parse.y"
+case 122:
+#line 1633 "parse.y"
{
if (queue_opts.marker & QOM_SCHEDULER) {
yyerror("scheduler cannot be respecified");
@@ -5751,23 +5788,23 @@ case 120:
queue_opts.scheduler = yystack.l_mark[0].v.queue_options;
}
break;
-case 121:
-#line 1623 "parse.y"
+case 123:
+#line 1641 "parse.y"
{
if (queue_opts.marker & QOM_TBRSIZE) {
yyerror("tbrsize cannot be respecified");
YYERROR;
}
- if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > 65535) {
- yyerror("tbrsize too big: max 65535");
+ if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
+ yyerror("tbrsize too big: max %u", UINT_MAX);
YYERROR;
}
queue_opts.marker |= QOM_TBRSIZE;
queue_opts.tbrsize = yystack.l_mark[0].v.number;
}
break;
-case 122:
-#line 1637 "parse.y"
+case 124:
+#line 1655 "parse.y"
{
double bps;
char *cp;
@@ -5809,13 +5846,13 @@ case 122:
}
}
free(yystack.l_mark[0].v.string);
- yyval.v.queue_bwspec.bw_absolute = (u_int32_t)bps;
+ yyval.v.queue_bwspec.bw_absolute = (u_int64_t)bps;
}
break;
-case 123:
-#line 1680 "parse.y"
+case 125:
+#line 1698 "parse.y"
{
- if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
+ if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number >= LLONG_MAX) {
yyerror("bandwidth number too big");
YYERROR;
}
@@ -5823,89 +5860,89 @@ case 123:
yyval.v.queue_bwspec.bw_absolute = yystack.l_mark[0].v.number;
}
break;
-case 124:
-#line 1690 "parse.y"
+case 126:
+#line 1708 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_CBQ;
yyval.v.queue_options.data.cbq_opts.flags = 0;
}
break;
-case 125:
-#line 1694 "parse.y"
+case 127:
+#line 1712 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_CBQ;
yyval.v.queue_options.data.cbq_opts.flags = yystack.l_mark[-1].v.number;
}
break;
-case 126:
-#line 1698 "parse.y"
+case 128:
+#line 1716 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_PRIQ;
yyval.v.queue_options.data.priq_opts.flags = 0;
}
break;
-case 127:
-#line 1702 "parse.y"
+case 129:
+#line 1720 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_PRIQ;
yyval.v.queue_options.data.priq_opts.flags = yystack.l_mark[-1].v.number;
}
break;
-case 128:
-#line 1706 "parse.y"
+case 130:
+#line 1724 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_HFSC;
bzero(&yyval.v.queue_options.data.hfsc_opts,
sizeof(struct node_hfsc_opts));
}
break;
-case 129:
-#line 1711 "parse.y"
+case 131:
+#line 1729 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_HFSC;
yyval.v.queue_options.data.hfsc_opts = yystack.l_mark[-1].v.hfsc_opts;
}
break;
-case 130:
-#line 1715 "parse.y"
+case 132:
+#line 1733 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_FAIRQ;
bzero(&yyval.v.queue_options.data.fairq_opts,
sizeof(struct node_fairq_opts));
}
break;
-case 131:
-#line 1720 "parse.y"
+case 133:
+#line 1738 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_FAIRQ;
yyval.v.queue_options.data.fairq_opts = yystack.l_mark[-1].v.fairq_opts;
}
break;
-case 132:
-#line 1724 "parse.y"
+case 134:
+#line 1742 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_CODEL;
bzero(&yyval.v.queue_options.data.codel_opts,
sizeof(struct codel_opts));
}
break;
-case 133:
-#line 1729 "parse.y"
+case 135:
+#line 1747 "parse.y"
{
yyval.v.queue_options.qtype = ALTQT_CODEL;
yyval.v.queue_options.data.codel_opts = yystack.l_mark[-1].v.codel_opts;
}
break;
-case 134:
-#line 1735 "parse.y"
+case 136:
+#line 1753 "parse.y"
{ yyval.v.number |= yystack.l_mark[0].v.number; }
break;
-case 135:
-#line 1736 "parse.y"
+case 137:
+#line 1754 "parse.y"
{ yyval.v.number |= yystack.l_mark[0].v.number; }
break;
-case 136:
-#line 1739 "parse.y"
+case 138:
+#line 1757 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "default"))
yyval.v.number = CBQCLF_DEFCLASS;
@@ -5927,16 +5964,16 @@ case 136:
free(yystack.l_mark[0].v.string);
}
break;
-case 137:
-#line 1761 "parse.y"
+case 139:
+#line 1779 "parse.y"
{ yyval.v.number |= yystack.l_mark[0].v.number; }
break;
-case 138:
-#line 1762 "parse.y"
+case 140:
+#line 1780 "parse.y"
{ yyval.v.number |= yystack.l_mark[0].v.number; }
break;
-case 139:
-#line 1765 "parse.y"
+case 141:
+#line 1783 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "default"))
yyval.v.number = PRCF_DEFAULTCLASS;
@@ -5956,21 +5993,21 @@ case 139:
free(yystack.l_mark[0].v.string);
}
break;
-case 140:
-#line 1785 "parse.y"
+case 142:
+#line 1803 "parse.y"
{
bzero(&hfsc_opts,
sizeof(struct node_hfsc_opts));
}
break;
-case 141:
-#line 1789 "parse.y"
+case 143:
+#line 1807 "parse.y"
{
yyval.v.hfsc_opts = hfsc_opts;
}
break;
-case 144:
-#line 1798 "parse.y"
+case 146:
+#line 1816 "parse.y"
{
if (hfsc_opts.linkshare.used) {
yyerror("linkshare already specified");
@@ -5980,8 +6017,8 @@ case 144:
hfsc_opts.linkshare.used = 1;
}
break;
-case 145:
-#line 1807 "parse.y"
+case 147:
+#line 1825 "parse.y"
{
if (yystack.l_mark[-3].v.number < 0 || yystack.l_mark[-3].v.number > INT_MAX) {
yyerror("timing in curve out of range");
@@ -5997,8 +6034,8 @@ case 145:
hfsc_opts.linkshare.used = 1;
}
break;
-case 146:
-#line 1821 "parse.y"
+case 148:
+#line 1839 "parse.y"
{
if (hfsc_opts.realtime.used) {
yyerror("realtime already specified");
@@ -6008,8 +6045,8 @@ case 146:
hfsc_opts.realtime.used = 1;
}
break;
-case 147:
-#line 1830 "parse.y"
+case 149:
+#line 1848 "parse.y"
{
if (yystack.l_mark[-3].v.number < 0 || yystack.l_mark[-3].v.number > INT_MAX) {
yyerror("timing in curve out of range");
@@ -6025,8 +6062,8 @@ case 147:
hfsc_opts.realtime.used = 1;
}
break;
-case 148:
-#line 1844 "parse.y"
+case 150:
+#line 1862 "parse.y"
{
if (hfsc_opts.upperlimit.used) {
yyerror("upperlimit already specified");
@@ -6036,8 +6073,8 @@ case 148:
hfsc_opts.upperlimit.used = 1;
}
break;
-case 149:
-#line 1853 "parse.y"
+case 151:
+#line 1871 "parse.y"
{
if (yystack.l_mark[-3].v.number < 0 || yystack.l_mark[-3].v.number > INT_MAX) {
yyerror("timing in curve out of range");
@@ -6053,8 +6090,8 @@ case 149:
hfsc_opts.upperlimit.used = 1;
}
break;
-case 150:
-#line 1867 "parse.y"
+case 152:
+#line 1885 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "default"))
hfsc_opts.flags |= HFCF_DEFAULTCLASS;
@@ -6074,21 +6111,21 @@ case 150:
free(yystack.l_mark[0].v.string);
}
break;
-case 151:
-#line 1887 "parse.y"
+case 153:
+#line 1905 "parse.y"
{
bzero(&fairq_opts,
sizeof(struct node_fairq_opts));
}
break;
-case 152:
-#line 1891 "parse.y"
+case 154:
+#line 1909 "parse.y"
{
yyval.v.fairq_opts = fairq_opts;
}
break;
-case 155:
-#line 1900 "parse.y"
+case 157:
+#line 1918 "parse.y"
{
if (fairq_opts.linkshare.used) {
yyerror("linkshare already specified");
@@ -6098,8 +6135,8 @@ case 155:
fairq_opts.linkshare.used = 1;
}
break;
-case 156:
-#line 1908 "parse.y"
+case 158:
+#line 1926 "parse.y"
{
if (fairq_opts.linkshare.used) {
yyerror("linkshare already specified");
@@ -6111,20 +6148,20 @@ case 156:
fairq_opts.linkshare.used = 1;
}
break;
-case 157:
-#line 1918 "parse.y"
+case 159:
+#line 1936 "parse.y"
{
fairq_opts.hogs_bw = yystack.l_mark[0].v.queue_bwspec;
}
break;
-case 158:
-#line 1921 "parse.y"
+case 160:
+#line 1939 "parse.y"
{
fairq_opts.nbuckets = yystack.l_mark[0].v.number;
}
break;
-case 159:
-#line 1924 "parse.y"
+case 161:
+#line 1942 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "default"))
fairq_opts.flags |= FARF_DEFAULTCLASS;
@@ -6144,21 +6181,21 @@ case 159:
free(yystack.l_mark[0].v.string);
}
break;
-case 160:
-#line 1944 "parse.y"
+case 162:
+#line 1962 "parse.y"
{
bzero(&codel_opts,
sizeof(struct codel_opts));
}
break;
-case 161:
-#line 1948 "parse.y"
+case 163:
+#line 1966 "parse.y"
{
yyval.v.codel_opts = codel_opts;
}
break;
-case 164:
-#line 1957 "parse.y"
+case 166:
+#line 1975 "parse.y"
{
if (codel_opts.interval) {
yyerror("interval already specified");
@@ -6167,8 +6204,8 @@ case 164:
codel_opts.interval = yystack.l_mark[0].v.number;
}
break;
-case 165:
-#line 1964 "parse.y"
+case 167:
+#line 1982 "parse.y"
{
if (codel_opts.target) {
yyerror("target already specified");
@@ -6177,8 +6214,8 @@ case 165:
codel_opts.target = yystack.l_mark[0].v.number;
}
break;
-case 166:
-#line 1971 "parse.y"
+case 168:
+#line 1989 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "ecn"))
codel_opts.ecn = 1;
@@ -6190,32 +6227,32 @@ case 166:
free(yystack.l_mark[0].v.string);
}
break;
-case 167:
-#line 1983 "parse.y"
+case 169:
+#line 2001 "parse.y"
{ yyval.v.queue = NULL; }
break;
-case 168:
-#line 1984 "parse.y"
+case 170:
+#line 2002 "parse.y"
{ yyval.v.queue = yystack.l_mark[0].v.queue; }
break;
-case 169:
-#line 1985 "parse.y"
+case 171:
+#line 2003 "parse.y"
{ yyval.v.queue = yystack.l_mark[-1].v.queue; }
break;
-case 170:
-#line 1988 "parse.y"
+case 172:
+#line 2006 "parse.y"
{ yyval.v.queue = yystack.l_mark[-1].v.queue; }
break;
-case 171:
-#line 1989 "parse.y"
+case 173:
+#line 2007 "parse.y"
{
yystack.l_mark[-3].v.queue->tail->next = yystack.l_mark[-1].v.queue;
yystack.l_mark[-3].v.queue->tail = yystack.l_mark[-1].v.queue;
yyval.v.queue = yystack.l_mark[-3].v.queue;
}
break;
-case 172:
-#line 1996 "parse.y"
+case 174:
+#line 2014 "parse.y"
{
yyval.v.queue = calloc(1, sizeof(struct node_queue));
if (yyval.v.queue == NULL)
@@ -6233,8 +6270,8 @@ case 172:
yyval.v.queue->tail = yyval.v.queue;
}
break;
-case 173:
-#line 2016 "parse.y"
+case 175:
+#line 2034 "parse.y"
{
struct pf_rule r;
struct node_state_opt *o;
@@ -6658,43 +6695,43 @@ case 173:
yystack.l_mark[0].v.filter_opts.uid, yystack.l_mark[0].v.filter_opts.gid, yystack.l_mark[0].v.filter_opts.icmpspec, "");
}
break;
-case 174:
-#line 2440 "parse.y"
+case 176:
+#line 2458 "parse.y"
{
bzero(&filter_opts, sizeof filter_opts);
filter_opts.rtableid = -1;
}
break;
-case 175:
-#line 2445 "parse.y"
+case 177:
+#line 2463 "parse.y"
{ yyval.v.filter_opts = filter_opts; }
break;
-case 176:
-#line 2446 "parse.y"
+case 178:
+#line 2464 "parse.y"
{
bzero(&filter_opts, sizeof filter_opts);
filter_opts.rtableid = -1;
yyval.v.filter_opts = filter_opts;
}
break;
-case 179:
-#line 2457 "parse.y"
+case 181:
+#line 2475 "parse.y"
{
if (filter_opts.uid)
yystack.l_mark[0].v.uid->tail->next = filter_opts.uid;
filter_opts.uid = yystack.l_mark[0].v.uid;
}
break;
-case 180:
-#line 2462 "parse.y"
+case 182:
+#line 2480 "parse.y"
{
if (filter_opts.gid)
yystack.l_mark[0].v.gid->tail->next = filter_opts.gid;
filter_opts.gid = yystack.l_mark[0].v.gid;
}
break;
-case 181:
-#line 2467 "parse.y"
+case 183:
+#line 2485 "parse.y"
{
if (filter_opts.marker & FOM_FLAGS) {
yyerror("flags cannot be redefined");
@@ -6707,8 +6744,8 @@ case 181:
filter_opts.flags.w2 |= yystack.l_mark[0].v.b.w2;
}
break;
-case 182:
-#line 2478 "parse.y"
+case 184:
+#line 2496 "parse.y"
{
if (filter_opts.marker & FOM_ICMP) {
yyerror("icmp-type cannot be redefined");
@@ -6718,8 +6755,8 @@ case 182:
filter_opts.icmpspec = yystack.l_mark[0].v.icmp;
}
break;
-case 183:
-#line 2486 "parse.y"
+case 185:
+#line 2504 "parse.y"
{
if (filter_opts.marker & FOM_PRIO) {
yyerror("prio cannot be redefined");
@@ -6733,8 +6770,8 @@ case 183:
filter_opts.prio = yystack.l_mark[0].v.number;
}
break;
-case 184:
-#line 2498 "parse.y"
+case 186:
+#line 2516 "parse.y"
{
if (filter_opts.marker & FOM_TOS) {
yyerror("tos cannot be redefined");
@@ -6744,8 +6781,8 @@ case 184:
filter_opts.tos = yystack.l_mark[0].v.number;
}
break;
-case 185:
-#line 2506 "parse.y"
+case 187:
+#line 2524 "parse.y"
{
if (filter_opts.marker & FOM_KEEP) {
yyerror("modulate or keep cannot be redefined");
@@ -6756,20 +6793,20 @@ case 185:
filter_opts.keep.options = yystack.l_mark[0].v.keep_state.options;
}
break;
-case 186:
-#line 2515 "parse.y"
+case 188:
+#line 2533 "parse.y"
{
filter_opts.fragment = 1;
}
break;
-case 187:
-#line 2518 "parse.y"
+case 189:
+#line 2536 "parse.y"
{
filter_opts.allowopts = 1;
}
break;
-case 188:
-#line 2521 "parse.y"
+case 190:
+#line 2539 "parse.y"
{
if (filter_opts.label) {
yyerror("label cannot be redefined");
@@ -6778,8 +6815,8 @@ case 188:
filter_opts.label = yystack.l_mark[0].v.string;
}
break;
-case 189:
-#line 2528 "parse.y"
+case 191:
+#line 2546 "parse.y"
{
if (filter_opts.queues.qname) {
yyerror("queue cannot be redefined");
@@ -6788,21 +6825,21 @@ case 189:
filter_opts.queues = yystack.l_mark[0].v.qassign;
}
break;
-case 190:
-#line 2535 "parse.y"
+case 192:
+#line 2553 "parse.y"
{
filter_opts.tag = yystack.l_mark[0].v.string;
}
break;
-case 191:
-#line 2538 "parse.y"
+case 193:
+#line 2556 "parse.y"
{
filter_opts.match_tag = yystack.l_mark[0].v.string;
filter_opts.match_tag_not = yystack.l_mark[-2].v.number;
}
break;
-case 192:
-#line 2542 "parse.y"
+case 194:
+#line 2560 "parse.y"
{
double p;
@@ -6816,8 +6853,8 @@ case 192:
filter_opts.prob = 1;
}
break;
-case 193:
-#line 2554 "parse.y"
+case 195:
+#line 2572 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > rt_tableid_max()) {
yyerror("invalid rtable id");
@@ -6826,8 +6863,8 @@ case 193:
filter_opts.rtableid = yystack.l_mark[0].v.number;
}
break;
-case 194:
-#line 2561 "parse.y"
+case 196:
+#line 2579 "parse.y"
{
#ifdef __FreeBSD__
filter_opts.divert.port = yystack.l_mark[0].v.range.a;
@@ -6838,8 +6875,8 @@ case 194:
#endif
}
break;
-case 195:
-#line 2570 "parse.y"
+case 197:
+#line 2588 "parse.y"
{
#ifndef __FreeBSD__
if ((filter_opts.divert.addr = host(yystack.l_mark[-2].v.string)) == NULL) {
@@ -6859,8 +6896,8 @@ case 195:
}
}
break;
-case 196:
-#line 2588 "parse.y"
+case 198:
+#line 2606 "parse.y"
{
#ifdef __FreeBSD__
yyerror("divert-reply has no meaning in FreeBSD pf(4)");
@@ -6870,16 +6907,16 @@ case 196:
#endif
}
break;
-case 198:
-#line 2599 "parse.y"
+case 200:
+#line 2617 "parse.y"
{ yyval.v.filter_opts = filter_opts; }
break;
-case 199:
-#line 2600 "parse.y"
+case 201:
+#line 2618 "parse.y"
{ yyval.v.filter_opts = filter_opts; }
break;
-case 202:
-#line 2607 "parse.y"
+case 204:
+#line 2625 "parse.y"
{
if (filter_opts.marker & FOM_SETPRIO) {
yyerror("prio cannot be redefined");
@@ -6890,8 +6927,8 @@ case 202:
filter_opts.set_prio[1] = yystack.l_mark[0].v.b.b2;
}
break;
-case 203:
-#line 2616 "parse.y"
+case 205:
+#line 2634 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > PF_PRIO_MAX) {
yyerror("prio must be 0 - %u", PF_PRIO_MAX);
@@ -6900,8 +6937,8 @@ case 203:
yyval.v.b.b1 = yyval.v.b.b2 = yystack.l_mark[0].v.number;
}
break;
-case 204:
-#line 2623 "parse.y"
+case 206:
+#line 2641 "parse.y"
{
if (yystack.l_mark[-3].v.number < 0 || yystack.l_mark[-3].v.number > PF_PRIO_MAX ||
yystack.l_mark[-1].v.number < 0 || yystack.l_mark[-1].v.number > PF_PRIO_MAX) {
@@ -6912,8 +6949,8 @@ case 204:
yyval.v.b.b2 = yystack.l_mark[-1].v.number;
}
break;
-case 205:
-#line 2634 "parse.y"
+case 207:
+#line 2652 "parse.y"
{
char *e;
double p = strtod(yystack.l_mark[0].v.string, &e);
@@ -6931,46 +6968,51 @@ case 205:
yyval.v.probability = p;
}
break;
-case 206:
-#line 2650 "parse.y"
+case 208:
+#line 2668 "parse.y"
{
yyval.v.probability = (double)yystack.l_mark[0].v.number;
}
break;
-case 207:
-#line 2656 "parse.y"
- { yyval.v.b.b1 = PF_PASS; yyval.v.b.b2 = yyval.v.b.w = 0; }
+case 209:
+#line 2674 "parse.y"
+ {
+ yyval.v.b.b1 = PF_PASS;
+ yyval.v.b.b2 = failpolicy;
+ yyval.v.b.w = returnicmpdefault;
+ yyval.v.b.w2 = returnicmp6default;
+ }
break;
-case 208:
-#line 2657 "parse.y"
+case 210:
+#line 2680 "parse.y"
{ yyval.v.b = yystack.l_mark[0].v.b; yyval.v.b.b1 = PF_DROP; }
break;
-case 209:
-#line 2660 "parse.y"
+case 211:
+#line 2683 "parse.y"
{
yyval.v.b.b2 = blockpolicy;
yyval.v.b.w = returnicmpdefault;
yyval.v.b.w2 = returnicmp6default;
}
break;
-case 210:
-#line 2665 "parse.y"
+case 212:
+#line 2688 "parse.y"
{
yyval.v.b.b2 = PFRULE_DROP;
yyval.v.b.w = 0;
yyval.v.b.w2 = 0;
}
break;
-case 211:
-#line 2670 "parse.y"
+case 213:
+#line 2693 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURNRST;
yyval.v.b.w = 0;
yyval.v.b.w2 = 0;
}
break;
-case 212:
-#line 2675 "parse.y"
+case 214:
+#line 2698 "parse.y"
{
if (yystack.l_mark[-1].v.number < 0 || yystack.l_mark[-1].v.number > 255) {
yyerror("illegal ttl value %d", yystack.l_mark[-1].v.number);
@@ -6981,56 +7023,56 @@ case 212:
yyval.v.b.w2 = 0;
}
break;
-case 213:
-#line 2684 "parse.y"
+case 215:
+#line 2707 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURNICMP;
yyval.v.b.w = returnicmpdefault;
yyval.v.b.w2 = returnicmp6default;
}
break;
-case 214:
-#line 2689 "parse.y"
+case 216:
+#line 2712 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURNICMP;
yyval.v.b.w = returnicmpdefault;
yyval.v.b.w2 = returnicmp6default;
}
break;
-case 215:
-#line 2694 "parse.y"
+case 217:
+#line 2717 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURNICMP;
yyval.v.b.w = yystack.l_mark[-1].v.number;
yyval.v.b.w2 = returnicmpdefault;
}
break;
-case 216:
-#line 2699 "parse.y"
+case 218:
+#line 2722 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURNICMP;
yyval.v.b.w = returnicmpdefault;
yyval.v.b.w2 = yystack.l_mark[-1].v.number;
}
break;
-case 217:
-#line 2704 "parse.y"
+case 219:
+#line 2727 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURNICMP;
yyval.v.b.w = yystack.l_mark[-3].v.number;
yyval.v.b.w2 = yystack.l_mark[-1].v.number;
}
break;
-case 218:
-#line 2709 "parse.y"
+case 220:
+#line 2732 "parse.y"
{
yyval.v.b.b2 = PFRULE_RETURN;
yyval.v.b.w = returnicmpdefault;
yyval.v.b.w2 = returnicmp6default;
}
break;
-case 219:
-#line 2716 "parse.y"
+case 221:
+#line 2739 "parse.y"
{
if (!(yyval.v.number = parseicmpspec(yystack.l_mark[0].v.string, AF_INET))) {
free(yystack.l_mark[0].v.string);
@@ -7039,8 +7081,8 @@ case 219:
free(yystack.l_mark[0].v.string);
}
break;
-case 220:
-#line 2723 "parse.y"
+case 222:
+#line 2746 "parse.y"
{
u_int8_t icmptype;
@@ -7052,8 +7094,8 @@ case 220:
yyval.v.number = (icmptype << 8 | yystack.l_mark[0].v.number);
}
break;
-case 221:
-#line 2735 "parse.y"
+case 223:
+#line 2758 "parse.y"
{
if (!(yyval.v.number = parseicmpspec(yystack.l_mark[0].v.string, AF_INET6))) {
free(yystack.l_mark[0].v.string);
@@ -7062,8 +7104,8 @@ case 221:
free(yystack.l_mark[0].v.string);
}
break;
-case 222:
-#line 2742 "parse.y"
+case 224:
+#line 2765 "parse.y"
{
u_int8_t icmptype;
@@ -7075,63 +7117,63 @@ case 222:
yyval.v.number = (icmptype << 8 | yystack.l_mark[0].v.number);
}
break;
-case 223:
-#line 2754 "parse.y"
+case 225:
+#line 2777 "parse.y"
{ yyval.v.i = PF_INOUT; }
break;
-case 224:
-#line 2755 "parse.y"
+case 226:
+#line 2778 "parse.y"
{ yyval.v.i = PF_IN; }
break;
-case 225:
-#line 2756 "parse.y"
+case 227:
+#line 2779 "parse.y"
{ yyval.v.i = PF_OUT; }
break;
-case 226:
-#line 2759 "parse.y"
+case 228:
+#line 2782 "parse.y"
{ yyval.v.logquick.quick = 0; }
break;
-case 227:
-#line 2760 "parse.y"
+case 229:
+#line 2783 "parse.y"
{ yyval.v.logquick.quick = 1; }
break;
-case 228:
-#line 2763 "parse.y"
+case 230:
+#line 2786 "parse.y"
{ yyval.v.logquick.log = 0; yyval.v.logquick.quick = 0; yyval.v.logquick.logif = 0; }
break;
-case 229:
-#line 2764 "parse.y"
+case 231:
+#line 2787 "parse.y"
{ yyval.v.logquick = yystack.l_mark[0].v.logquick; yyval.v.logquick.quick = 0; }
break;
-case 230:
-#line 2765 "parse.y"
+case 232:
+#line 2788 "parse.y"
{ yyval.v.logquick.quick = 1; yyval.v.logquick.log = 0; yyval.v.logquick.logif = 0; }
break;
-case 231:
-#line 2766 "parse.y"
+case 233:
+#line 2789 "parse.y"
{ yyval.v.logquick = yystack.l_mark[-1].v.logquick; yyval.v.logquick.quick = 1; }
break;
-case 232:
-#line 2767 "parse.y"
+case 234:
+#line 2790 "parse.y"
{ yyval.v.logquick = yystack.l_mark[0].v.logquick; yyval.v.logquick.quick = 1; }
break;
-case 233:
-#line 2770 "parse.y"
+case 235:
+#line 2793 "parse.y"
{ yyval.v.logquick.log = PF_LOG; yyval.v.logquick.logif = 0; }
break;
-case 234:
-#line 2771 "parse.y"
+case 236:
+#line 2794 "parse.y"
{
yyval.v.logquick.log = PF_LOG | yystack.l_mark[-1].v.logquick.log;
yyval.v.logquick.logif = yystack.l_mark[-1].v.logquick.logif;
}
break;
-case 235:
-#line 2777 "parse.y"
+case 237:
+#line 2800 "parse.y"
{ yyval.v.logquick = yystack.l_mark[0].v.logquick; }
break;
-case 236:
-#line 2778 "parse.y"
+case 238:
+#line 2801 "parse.y"
{
yyval.v.logquick.log = yystack.l_mark[-2].v.logquick.log | yystack.l_mark[0].v.logquick.log;
yyval.v.logquick.logif = yystack.l_mark[0].v.logquick.logif;
@@ -7139,20 +7181,20 @@ case 236:
yyval.v.logquick.logif = yystack.l_mark[-2].v.logquick.logif;
}
break;
-case 237:
-#line 2786 "parse.y"
+case 239:
+#line 2809 "parse.y"
{ yyval.v.logquick.log = PF_LOG_ALL; yyval.v.logquick.logif = 0; }
break;
-case 238:
-#line 2787 "parse.y"
+case 240:
+#line 2810 "parse.y"
{ yyval.v.logquick.log = PF_LOG_SOCKET_LOOKUP; yyval.v.logquick.logif = 0; }
break;
-case 239:
-#line 2788 "parse.y"
+case 241:
+#line 2811 "parse.y"
{ yyval.v.logquick.log = PF_LOG_SOCKET_LOOKUP; yyval.v.logquick.logif = 0; }
break;
-case 240:
-#line 2789 "parse.y"
+case 242:
+#line 2812 "parse.y"
{
const char *errstr;
u_int i;
@@ -7173,36 +7215,36 @@ case 240:
yyval.v.logquick.logif = i;
}
break;
-case 241:
-#line 2810 "parse.y"
+case 243:
+#line 2833 "parse.y"
{ yyval.v.interface = NULL; }
break;
-case 242:
-#line 2811 "parse.y"
+case 244:
+#line 2834 "parse.y"
{ yyval.v.interface = yystack.l_mark[0].v.interface; }
break;
-case 243:
-#line 2812 "parse.y"
+case 245:
+#line 2835 "parse.y"
{ yyval.v.interface = yystack.l_mark[-1].v.interface; }
break;
-case 244:
-#line 2815 "parse.y"
+case 246:
+#line 2838 "parse.y"
{ yyval.v.interface = yystack.l_mark[-1].v.interface; }
break;
-case 245:
-#line 2816 "parse.y"
+case 247:
+#line 2839 "parse.y"
{
yystack.l_mark[-3].v.interface->tail->next = yystack.l_mark[-1].v.interface;
yystack.l_mark[-3].v.interface->tail = yystack.l_mark[-1].v.interface;
yyval.v.interface = yystack.l_mark[-3].v.interface;
}
break;
-case 246:
-#line 2823 "parse.y"
+case 248:
+#line 2846 "parse.y"
{ yyval.v.interface = yystack.l_mark[0].v.interface; yyval.v.interface->not = yystack.l_mark[-1].v.number; }
break;
-case 247:
-#line 2826 "parse.y"
+case 249:
+#line 2849 "parse.y"
{
struct node_host *n;
@@ -7226,44 +7268,44 @@ case 247:
yyval.v.interface->tail = yyval.v.interface;
}
break;
-case 248:
-#line 2850 "parse.y"
+case 250:
+#line 2873 "parse.y"
{ yyval.v.i = 0; }
break;
-case 249:
-#line 2851 "parse.y"
+case 251:
+#line 2874 "parse.y"
{ yyval.v.i = AF_INET; }
break;
-case 250:
-#line 2852 "parse.y"
+case 252:
+#line 2875 "parse.y"
{ yyval.v.i = AF_INET6; }
break;
-case 251:
-#line 2855 "parse.y"
+case 253:
+#line 2878 "parse.y"
{ yyval.v.proto = NULL; }
break;
-case 252:
-#line 2856 "parse.y"
+case 254:
+#line 2879 "parse.y"
{ yyval.v.proto = yystack.l_mark[0].v.proto; }
break;
-case 253:
-#line 2857 "parse.y"
+case 255:
+#line 2880 "parse.y"
{ yyval.v.proto = yystack.l_mark[-1].v.proto; }
break;
-case 254:
-#line 2860 "parse.y"
+case 256:
+#line 2883 "parse.y"
{ yyval.v.proto = yystack.l_mark[-1].v.proto; }
break;
-case 255:
-#line 2861 "parse.y"
+case 257:
+#line 2884 "parse.y"
{
yystack.l_mark[-3].v.proto->tail->next = yystack.l_mark[-1].v.proto;
yystack.l_mark[-3].v.proto->tail = yystack.l_mark[-1].v.proto;
yyval.v.proto = yystack.l_mark[-3].v.proto;
}
break;
-case 256:
-#line 2868 "parse.y"
+case 258:
+#line 2891 "parse.y"
{
u_int8_t pr;
@@ -7280,8 +7322,8 @@ case 256:
yyval.v.proto->tail = yyval.v.proto;
}
break;
-case 257:
-#line 2885 "parse.y"
+case 259:
+#line 2908 "parse.y"
{
struct protoent *p;
@@ -7295,8 +7337,8 @@ case 257:
free(yystack.l_mark[0].v.string);
}
break;
-case 258:
-#line 2897 "parse.y"
+case 260:
+#line 2920 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > 255) {
yyerror("protocol outside range");
@@ -7304,8 +7346,8 @@ case 258:
}
}
break;
-case 259:
-#line 2905 "parse.y"
+case 261:
+#line 2928 "parse.y"
{
yyval.v.fromto.src.host = NULL;
yyval.v.fromto.src.port = NULL;
@@ -7314,28 +7356,28 @@ case 259:
yyval.v.fromto.src_os = NULL;
}
break;
-case 260:
-#line 2912 "parse.y"
+case 262:
+#line 2935 "parse.y"
{
yyval.v.fromto.src = yystack.l_mark[-2].v.peer;
yyval.v.fromto.src_os = yystack.l_mark[-1].v.os;
yyval.v.fromto.dst = yystack.l_mark[0].v.peer;
}
break;
-case 261:
-#line 2919 "parse.y"
+case 263:
+#line 2942 "parse.y"
{ yyval.v.os = NULL; }
break;
-case 262:
-#line 2920 "parse.y"
+case 264:
+#line 2943 "parse.y"
{ yyval.v.os = yystack.l_mark[0].v.os; }
break;
-case 263:
-#line 2921 "parse.y"
+case 265:
+#line 2944 "parse.y"
{ yyval.v.os = yystack.l_mark[-1].v.os; }
break;
-case 264:
-#line 2924 "parse.y"
+case 266:
+#line 2947 "parse.y"
{
yyval.v.os = calloc(1, sizeof(struct node_os));
if (yyval.v.os == NULL)
@@ -7344,40 +7386,40 @@ case 264:
yyval.v.os->tail = yyval.v.os;
}
break;
-case 265:
-#line 2933 "parse.y"
+case 267:
+#line 2956 "parse.y"
{ yyval.v.os = yystack.l_mark[-1].v.os; }
break;
-case 266:
-#line 2934 "parse.y"
+case 268:
+#line 2957 "parse.y"
{
yystack.l_mark[-3].v.os->tail->next = yystack.l_mark[-1].v.os;
yystack.l_mark[-3].v.os->tail = yystack.l_mark[-1].v.os;
yyval.v.os = yystack.l_mark[-3].v.os;
}
break;
-case 267:
-#line 2941 "parse.y"
+case 269:
+#line 2964 "parse.y"
{
yyval.v.peer.host = NULL;
yyval.v.peer.port = NULL;
}
break;
-case 268:
-#line 2945 "parse.y"
+case 270:
+#line 2968 "parse.y"
{
yyval.v.peer = yystack.l_mark[0].v.peer;
}
break;
-case 269:
-#line 2950 "parse.y"
+case 271:
+#line 2973 "parse.y"
{
yyval.v.peer.host = NULL;
yyval.v.peer.port = NULL;
}
break;
-case 270:
-#line 2954 "parse.y"
+case 272:
+#line 2977 "parse.y"
{
if (disallow_urpf_failed(yystack.l_mark[0].v.peer.host, "\"urpf-failed\" is "
"not permitted in a destination address"))
@@ -7385,53 +7427,53 @@ case 270:
yyval.v.peer = yystack.l_mark[0].v.peer;
}
break;
-case 271:
-#line 2962 "parse.y"
+case 273:
+#line 2985 "parse.y"
{
yyval.v.peer.host = yystack.l_mark[0].v.host;
yyval.v.peer.port = NULL;
}
break;
-case 272:
-#line 2966 "parse.y"
+case 274:
+#line 2989 "parse.y"
{
yyval.v.peer.host = yystack.l_mark[-2].v.host;
yyval.v.peer.port = yystack.l_mark[0].v.port;
}
break;
-case 273:
-#line 2970 "parse.y"
+case 275:
+#line 2993 "parse.y"
{
yyval.v.peer.host = NULL;
yyval.v.peer.port = yystack.l_mark[0].v.port;
}
break;
-case 276:
-#line 2980 "parse.y"
+case 278:
+#line 3003 "parse.y"
{ yyval.v.host = NULL; }
break;
-case 277:
-#line 2981 "parse.y"
+case 279:
+#line 3004 "parse.y"
{ yyval.v.host = yystack.l_mark[0].v.host; }
break;
-case 278:
-#line 2982 "parse.y"
+case 280:
+#line 3005 "parse.y"
{ yyval.v.host = yystack.l_mark[-1].v.host; }
break;
-case 279:
-#line 2985 "parse.y"
+case 281:
+#line 3008 "parse.y"
{ yyval.v.host = yystack.l_mark[0].v.host; }
break;
-case 280:
-#line 2986 "parse.y"
+case 282:
+#line 3009 "parse.y"
{ yyval.v.host = NULL; }
break;
-case 281:
-#line 2989 "parse.y"
+case 283:
+#line 3012 "parse.y"
{ yyval.v.host = yystack.l_mark[-1].v.host; }
break;
-case 282:
-#line 2990 "parse.y"
+case 284:
+#line 3013 "parse.y"
{
if (yystack.l_mark[-1].v.host == NULL)
yyval.v.host = yystack.l_mark[-3].v.host;
@@ -7444,8 +7486,8 @@ case 282:
}
}
break;
-case 283:
-#line 3003 "parse.y"
+case 285:
+#line 3026 "parse.y"
{
struct node_host *n;
@@ -7454,8 +7496,8 @@ case 283:
yyval.v.host = yystack.l_mark[0].v.host;
}
break;
-case 284:
-#line 3010 "parse.y"
+case 286:
+#line 3033 "parse.y"
{
yyval.v.host = calloc(1, sizeof(struct node_host));
if (yyval.v.host == NULL)
@@ -7466,8 +7508,8 @@ case 284:
yyval.v.host->tail = yyval.v.host;
}
break;
-case 285:
-#line 3019 "parse.y"
+case 287:
+#line 3042 "parse.y"
{
yyval.v.host = calloc(1, sizeof(struct node_host));
if (yyval.v.host == NULL)
@@ -7478,8 +7520,8 @@ case 285:
yyval.v.host->tail = yyval.v.host;
}
break;
-case 286:
-#line 3030 "parse.y"
+case 288:
+#line 3053 "parse.y"
{
if ((yyval.v.host = host(yystack.l_mark[0].v.string)) == NULL) {
/* error. "any" is handled elsewhere */
@@ -7491,8 +7533,8 @@ case 286:
}
break;
-case 287:
-#line 3040 "parse.y"
+case 289:
+#line 3063 "parse.y"
{
struct node_host *b, *e;
@@ -7527,8 +7569,8 @@ case 287:
free(yystack.l_mark[0].v.string);
}
break;
-case 288:
-#line 3073 "parse.y"
+case 290:
+#line 3096 "parse.y"
{
char *buf;
@@ -7544,8 +7586,8 @@ case 288:
free(buf);
}
break;
-case 289:
-#line 3087 "parse.y"
+case 291:
+#line 3110 "parse.y"
{
char *buf;
@@ -7565,8 +7607,8 @@ case 289:
free(buf);
}
break;
-case 291:
-#line 3106 "parse.y"
+case 293:
+#line 3129 "parse.y"
{
struct node_host *n;
@@ -7579,8 +7621,8 @@ case 291:
set_ipmask(n, yystack.l_mark[0].v.number);
}
break;
-case 292:
-#line 3117 "parse.y"
+case 294:
+#line 3140 "parse.y"
{
if (strlen(yystack.l_mark[-1].v.string) >= PF_TABLE_NAME_SIZE) {
yyerror("table name '%s' too long", yystack.l_mark[-1].v.string);
@@ -7600,8 +7642,8 @@ case 292:
yyval.v.host->tail = yyval.v.host;
}
break;
-case 294:
-#line 3138 "parse.y"
+case 296:
+#line 3161 "parse.y"
{
u_long ulval;
@@ -7614,8 +7656,8 @@ case 294:
free(yystack.l_mark[0].v.string);
}
break;
-case 295:
-#line 3151 "parse.y"
+case 297:
+#line 3174 "parse.y"
{
int flags = 0;
char *p, *op;
@@ -7669,28 +7711,28 @@ case 295:
yyval.v.host->tail = yyval.v.host;
}
break;
-case 296:
-#line 3205 "parse.y"
+case 298:
+#line 3228 "parse.y"
{ yyval.v.port = yystack.l_mark[0].v.port; }
break;
-case 297:
-#line 3206 "parse.y"
+case 299:
+#line 3229 "parse.y"
{ yyval.v.port = yystack.l_mark[-1].v.port; }
break;
-case 298:
-#line 3209 "parse.y"
+case 300:
+#line 3232 "parse.y"
{ yyval.v.port = yystack.l_mark[-1].v.port; }
break;
-case 299:
-#line 3210 "parse.y"
+case 301:
+#line 3233 "parse.y"
{
yystack.l_mark[-3].v.port->tail->next = yystack.l_mark[-1].v.port;
yystack.l_mark[-3].v.port->tail = yystack.l_mark[-1].v.port;
yyval.v.port = yystack.l_mark[-3].v.port;
}
break;
-case 300:
-#line 3217 "parse.y"
+case 302:
+#line 3240 "parse.y"
{
yyval.v.port = calloc(1, sizeof(struct node_port));
if (yyval.v.port == NULL)
@@ -7705,8 +7747,8 @@ case 300:
yyval.v.port->tail = yyval.v.port;
}
break;
-case 301:
-#line 3230 "parse.y"
+case 303:
+#line 3253 "parse.y"
{
if (yystack.l_mark[0].v.range.t) {
yyerror("':' cannot be used with an other "
@@ -7723,8 +7765,8 @@ case 301:
yyval.v.port->tail = yyval.v.port;
}
break;
-case 302:
-#line 3245 "parse.y"
+case 304:
+#line 3268 "parse.y"
{
if (yystack.l_mark[-2].v.range.t || yystack.l_mark[0].v.range.t) {
yyerror("':' cannot be used with an other "
@@ -7741,8 +7783,8 @@ case 302:
yyval.v.port->tail = yyval.v.port;
}
break;
-case 303:
-#line 3262 "parse.y"
+case 305:
+#line 3285 "parse.y"
{
if (parseport(yystack.l_mark[0].v.string, &yyval.v.range, 0) == -1) {
free(yystack.l_mark[0].v.string);
@@ -7751,8 +7793,8 @@ case 303:
free(yystack.l_mark[0].v.string);
}
break;
-case 304:
-#line 3271 "parse.y"
+case 306:
+#line 3294 "parse.y"
{
if (parseport(yystack.l_mark[0].v.string, &yyval.v.range, PPORT_RANGE) == -1) {
free(yystack.l_mark[0].v.string);
@@ -7761,28 +7803,28 @@ case 304:
free(yystack.l_mark[0].v.string);
}
break;
-case 305:
-#line 3280 "parse.y"
+case 307:
+#line 3303 "parse.y"
{ yyval.v.uid = yystack.l_mark[0].v.uid; }
break;
-case 306:
-#line 3281 "parse.y"
+case 308:
+#line 3304 "parse.y"
{ yyval.v.uid = yystack.l_mark[-1].v.uid; }
break;
-case 307:
-#line 3284 "parse.y"
+case 309:
+#line 3307 "parse.y"
{ yyval.v.uid = yystack.l_mark[-1].v.uid; }
break;
-case 308:
-#line 3285 "parse.y"
+case 310:
+#line 3308 "parse.y"
{
yystack.l_mark[-3].v.uid->tail->next = yystack.l_mark[-1].v.uid;
yystack.l_mark[-3].v.uid->tail = yystack.l_mark[-1].v.uid;
yyval.v.uid = yystack.l_mark[-3].v.uid;
}
break;
-case 309:
-#line 3292 "parse.y"
+case 311:
+#line 3315 "parse.y"
{
yyval.v.uid = calloc(1, sizeof(struct node_uid));
if (yyval.v.uid == NULL)
@@ -7794,8 +7836,8 @@ case 309:
yyval.v.uid->tail = yyval.v.uid;
}
break;
-case 310:
-#line 3302 "parse.y"
+case 312:
+#line 3325 "parse.y"
{
if (yystack.l_mark[0].v.number == UID_MAX && yystack.l_mark[-1].v.i != PF_OP_EQ && yystack.l_mark[-1].v.i != PF_OP_NE) {
yyerror("user unknown requires operator = or "
@@ -7812,8 +7854,8 @@ case 310:
yyval.v.uid->tail = yyval.v.uid;
}
break;
-case 311:
-#line 3317 "parse.y"
+case 313:
+#line 3340 "parse.y"
{
if (yystack.l_mark[-2].v.number == UID_MAX || yystack.l_mark[0].v.number == UID_MAX) {
yyerror("user unknown requires operator = or "
@@ -7830,8 +7872,8 @@ case 311:
yyval.v.uid->tail = yyval.v.uid;
}
break;
-case 312:
-#line 3334 "parse.y"
+case 314:
+#line 3357 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "unknown"))
yyval.v.number = UID_MAX;
@@ -7848,8 +7890,8 @@ case 312:
free(yystack.l_mark[0].v.string);
}
break;
-case 313:
-#line 3349 "parse.y"
+case 315:
+#line 3372 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number >= UID_MAX) {
yyerror("illegal uid value %lu", yystack.l_mark[0].v.number);
@@ -7858,28 +7900,28 @@ case 313:
yyval.v.number = yystack.l_mark[0].v.number;
}
break;
-case 314:
-#line 3358 "parse.y"
+case 316:
+#line 3381 "parse.y"
{ yyval.v.gid = yystack.l_mark[0].v.gid; }
break;
-case 315:
-#line 3359 "parse.y"
+case 317:
+#line 3382 "parse.y"
{ yyval.v.gid = yystack.l_mark[-1].v.gid; }
break;
-case 316:
-#line 3362 "parse.y"
+case 318:
+#line 3385 "parse.y"
{ yyval.v.gid = yystack.l_mark[-1].v.gid; }
break;
-case 317:
-#line 3363 "parse.y"
+case 319:
+#line 3386 "parse.y"
{
yystack.l_mark[-3].v.gid->tail->next = yystack.l_mark[-1].v.gid;
yystack.l_mark[-3].v.gid->tail = yystack.l_mark[-1].v.gid;
yyval.v.gid = yystack.l_mark[-3].v.gid;
}
break;
-case 318:
-#line 3370 "parse.y"
+case 320:
+#line 3393 "parse.y"
{
yyval.v.gid = calloc(1, sizeof(struct node_gid));
if (yyval.v.gid == NULL)
@@ -7891,8 +7933,8 @@ case 318:
yyval.v.gid->tail = yyval.v.gid;
}
break;
-case 319:
-#line 3380 "parse.y"
+case 321:
+#line 3403 "parse.y"
{
if (yystack.l_mark[0].v.number == GID_MAX && yystack.l_mark[-1].v.i != PF_OP_EQ && yystack.l_mark[-1].v.i != PF_OP_NE) {
yyerror("group unknown requires operator = or "
@@ -7909,8 +7951,8 @@ case 319:
yyval.v.gid->tail = yyval.v.gid;
}
break;
-case 320:
-#line 3395 "parse.y"
+case 322:
+#line 3418 "parse.y"
{
if (yystack.l_mark[-2].v.number == GID_MAX || yystack.l_mark[0].v.number == GID_MAX) {
yyerror("group unknown requires operator = or "
@@ -7927,8 +7969,8 @@ case 320:
yyval.v.gid->tail = yyval.v.gid;
}
break;
-case 321:
-#line 3412 "parse.y"
+case 323:
+#line 3435 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "unknown"))
yyval.v.number = GID_MAX;
@@ -7945,8 +7987,8 @@ case 321:
free(yystack.l_mark[0].v.string);
}
break;
-case 322:
-#line 3427 "parse.y"
+case 324:
+#line 3450 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number >= GID_MAX) {
yyerror("illegal gid value %lu", yystack.l_mark[0].v.number);
@@ -7955,8 +7997,8 @@ case 322:
yyval.v.number = yystack.l_mark[0].v.number;
}
break;
-case 323:
-#line 3436 "parse.y"
+case 325:
+#line 3459 "parse.y"
{
int f;
@@ -7969,60 +8011,60 @@ case 323:
yyval.v.b.b1 = f;
}
break;
-case 324:
-#line 3449 "parse.y"
+case 326:
+#line 3472 "parse.y"
{ yyval.v.b.b1 = yystack.l_mark[-2].v.b.b1; yyval.v.b.b2 = yystack.l_mark[0].v.b.b1; }
break;
-case 325:
-#line 3450 "parse.y"
+case 327:
+#line 3473 "parse.y"
{ yyval.v.b.b1 = 0; yyval.v.b.b2 = yystack.l_mark[0].v.b.b1; }
break;
-case 326:
-#line 3451 "parse.y"
+case 328:
+#line 3474 "parse.y"
{ yyval.v.b.b1 = 0; yyval.v.b.b2 = 0; }
break;
-case 327:
-#line 3454 "parse.y"
+case 329:
+#line 3477 "parse.y"
{ yyval.v.icmp = yystack.l_mark[0].v.icmp; }
break;
-case 328:
-#line 3455 "parse.y"
+case 330:
+#line 3478 "parse.y"
{ yyval.v.icmp = yystack.l_mark[-1].v.icmp; }
break;
-case 329:
-#line 3456 "parse.y"
+case 331:
+#line 3479 "parse.y"
{ yyval.v.icmp = yystack.l_mark[0].v.icmp; }
break;
-case 330:
-#line 3457 "parse.y"
+case 332:
+#line 3480 "parse.y"
{ yyval.v.icmp = yystack.l_mark[-1].v.icmp; }
break;
-case 331:
-#line 3460 "parse.y"
+case 333:
+#line 3483 "parse.y"
{ yyval.v.icmp = yystack.l_mark[-1].v.icmp; }
break;
-case 332:
-#line 3461 "parse.y"
+case 334:
+#line 3484 "parse.y"
{
yystack.l_mark[-3].v.icmp->tail->next = yystack.l_mark[-1].v.icmp;
yystack.l_mark[-3].v.icmp->tail = yystack.l_mark[-1].v.icmp;
yyval.v.icmp = yystack.l_mark[-3].v.icmp;
}
break;
-case 333:
-#line 3468 "parse.y"
+case 335:
+#line 3491 "parse.y"
{ yyval.v.icmp = yystack.l_mark[-1].v.icmp; }
break;
-case 334:
-#line 3469 "parse.y"
+case 336:
+#line 3492 "parse.y"
{
yystack.l_mark[-3].v.icmp->tail->next = yystack.l_mark[-1].v.icmp;
yystack.l_mark[-3].v.icmp->tail = yystack.l_mark[-1].v.icmp;
yyval.v.icmp = yystack.l_mark[-3].v.icmp;
}
break;
-case 335:
-#line 3476 "parse.y"
+case 337:
+#line 3499 "parse.y"
{
yyval.v.icmp = calloc(1, sizeof(struct node_icmp));
if (yyval.v.icmp == NULL)
@@ -8034,8 +8076,8 @@ case 335:
yyval.v.icmp->tail = yyval.v.icmp;
}
break;
-case 336:
-#line 3486 "parse.y"
+case 338:
+#line 3509 "parse.y"
{
const struct icmpcodeent *p;
@@ -8056,8 +8098,8 @@ case 336:
yyval.v.icmp->tail = yyval.v.icmp;
}
break;
-case 337:
-#line 3505 "parse.y"
+case 339:
+#line 3528 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > 255) {
yyerror("illegal icmp-code %lu", yystack.l_mark[0].v.number);
@@ -8073,8 +8115,8 @@ case 337:
yyval.v.icmp->tail = yyval.v.icmp;
}
break;
-case 338:
-#line 3521 "parse.y"
+case 340:
+#line 3544 "parse.y"
{
yyval.v.icmp = calloc(1, sizeof(struct node_icmp));
if (yyval.v.icmp == NULL)
@@ -8086,8 +8128,8 @@ case 338:
yyval.v.icmp->tail = yyval.v.icmp;
}
break;
-case 339:
-#line 3531 "parse.y"
+case 341:
+#line 3554 "parse.y"
{
const struct icmpcodeent *p;
@@ -8108,8 +8150,8 @@ case 339:
yyval.v.icmp->tail = yyval.v.icmp;
}
break;
-case 340:
-#line 3550 "parse.y"
+case 342:
+#line 3573 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > 255) {
yyerror("illegal icmp-code %lu", yystack.l_mark[0].v.number);
@@ -8125,8 +8167,8 @@ case 340:
yyval.v.icmp->tail = yyval.v.icmp;
}
break;
-case 341:
-#line 3566 "parse.y"
+case 343:
+#line 3589 "parse.y"
{
const struct icmptypeent *p;
@@ -8139,8 +8181,8 @@ case 341:
free(yystack.l_mark[0].v.string);
}
break;
-case 342:
-#line 3577 "parse.y"
+case 344:
+#line 3600 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > 255) {
yyerror("illegal icmp-type %lu", yystack.l_mark[0].v.number);
@@ -8149,8 +8191,8 @@ case 342:
yyval.v.number = yystack.l_mark[0].v.number + 1;
}
break;
-case 343:
-#line 3586 "parse.y"
+case 345:
+#line 3609 "parse.y"
{
const struct icmptypeent *p;
@@ -8164,8 +8206,8 @@ case 343:
free(yystack.l_mark[0].v.string);
}
break;
-case 344:
-#line 3598 "parse.y"
+case 346:
+#line 3621 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > 255) {
yyerror("illegal icmp6-type %lu", yystack.l_mark[0].v.number);
@@ -8174,8 +8216,8 @@ case 344:
yyval.v.number = yystack.l_mark[0].v.number + 1;
}
break;
-case 345:
-#line 3607 "parse.y"
+case 347:
+#line 3630 "parse.y"
{
int val;
char *end;
@@ -8197,8 +8239,8 @@ case 345:
free(yystack.l_mark[0].v.string);
}
break;
-case 346:
-#line 3627 "parse.y"
+case 348:
+#line 3650 "parse.y"
{
yyval.v.number = yystack.l_mark[0].v.number;
if (yyval.v.number < 0 || yyval.v.number > 255) {
@@ -8207,94 +8249,94 @@ case 346:
}
}
break;
-case 347:
-#line 3636 "parse.y"
+case 349:
+#line 3659 "parse.y"
{ yyval.v.i = PF_SRCTRACK; }
break;
-case 348:
-#line 3637 "parse.y"
+case 350:
+#line 3660 "parse.y"
{ yyval.v.i = PF_SRCTRACK_GLOBAL; }
break;
-case 349:
-#line 3638 "parse.y"
+case 351:
+#line 3661 "parse.y"
{ yyval.v.i = PF_SRCTRACK_RULE; }
break;
-case 350:
-#line 3641 "parse.y"
+case 352:
+#line 3664 "parse.y"
{
yyval.v.i = PFRULE_IFBOUND;
}
break;
-case 351:
-#line 3644 "parse.y"
+case 353:
+#line 3667 "parse.y"
{
yyval.v.i = 0;
}
break;
-case 352:
-#line 3649 "parse.y"
+case 354:
+#line 3672 "parse.y"
{
yyval.v.keep_state.action = 0;
yyval.v.keep_state.options = NULL;
}
break;
-case 353:
-#line 3653 "parse.y"
+case 355:
+#line 3676 "parse.y"
{
yyval.v.keep_state.action = PF_STATE_NORMAL;
yyval.v.keep_state.options = yystack.l_mark[0].v.state_opt;
}
break;
-case 354:
-#line 3657 "parse.y"
+case 356:
+#line 3680 "parse.y"
{
yyval.v.keep_state.action = PF_STATE_MODULATE;
yyval.v.keep_state.options = yystack.l_mark[0].v.state_opt;
}
break;
-case 355:
-#line 3661 "parse.y"
+case 357:
+#line 3684 "parse.y"
{
yyval.v.keep_state.action = PF_STATE_SYNPROXY;
yyval.v.keep_state.options = yystack.l_mark[0].v.state_opt;
}
break;
-case 356:
-#line 3667 "parse.y"
+case 358:
+#line 3690 "parse.y"
{ yyval.v.i = 0; }
break;
-case 357:
-#line 3668 "parse.y"
+case 359:
+#line 3691 "parse.y"
{ yyval.v.i = PF_FLUSH; }
break;
-case 358:
-#line 3669 "parse.y"
+case 360:
+#line 3692 "parse.y"
{
yyval.v.i = PF_FLUSH | PF_FLUSH_GLOBAL;
}
break;
-case 359:
-#line 3674 "parse.y"
+case 361:
+#line 3697 "parse.y"
{ yyval.v.state_opt = yystack.l_mark[-1].v.state_opt; }
break;
-case 360:
-#line 3675 "parse.y"
+case 362:
+#line 3698 "parse.y"
{ yyval.v.state_opt = NULL; }
break;
-case 361:
-#line 3678 "parse.y"
+case 363:
+#line 3701 "parse.y"
{ yyval.v.state_opt = yystack.l_mark[0].v.state_opt; }
break;
-case 362:
-#line 3679 "parse.y"
+case 364:
+#line 3702 "parse.y"
{
yystack.l_mark[-2].v.state_opt->tail->next = yystack.l_mark[0].v.state_opt;
yystack.l_mark[-2].v.state_opt->tail = yystack.l_mark[0].v.state_opt;
yyval.v.state_opt = yystack.l_mark[-2].v.state_opt;
}
break;
-case 363:
-#line 3686 "parse.y"
+case 365:
+#line 3709 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
yyerror("only positive values permitted");
@@ -8309,8 +8351,8 @@ case 363:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 364:
-#line 3699 "parse.y"
+case 366:
+#line 3722 "parse.y"
{
yyval.v.state_opt = calloc(1, sizeof(struct node_state_opt));
if (yyval.v.state_opt == NULL)
@@ -8320,8 +8362,8 @@ case 364:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 365:
-#line 3707 "parse.y"
+case 367:
+#line 3730 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
yyerror("only positive values permitted");
@@ -8336,8 +8378,8 @@ case 365:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 366:
-#line 3720 "parse.y"
+case 368:
+#line 3743 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
yyerror("only positive values permitted");
@@ -8352,8 +8394,8 @@ case 366:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 367:
-#line 3733 "parse.y"
+case 369:
+#line 3756 "parse.y"
{
if (yystack.l_mark[-2].v.number < 0 || yystack.l_mark[-2].v.number > UINT_MAX ||
yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
@@ -8370,8 +8412,8 @@ case 367:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 368:
-#line 3748 "parse.y"
+case 370:
+#line 3771 "parse.y"
{
if (strlen(yystack.l_mark[-2].v.string) >= PF_TABLE_NAME_SIZE) {
yyerror("table name '%s' too long", yystack.l_mark[-2].v.string);
@@ -8391,8 +8433,8 @@ case 368:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 369:
-#line 3766 "parse.y"
+case 371:
+#line 3789 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > UINT_MAX) {
yyerror("only positive values permitted");
@@ -8407,8 +8449,8 @@ case 369:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 370:
-#line 3779 "parse.y"
+case 372:
+#line 3802 "parse.y"
{
yyval.v.state_opt = calloc(1, sizeof(struct node_state_opt));
if (yyval.v.state_opt == NULL)
@@ -8419,8 +8461,8 @@ case 370:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 371:
-#line 3788 "parse.y"
+case 373:
+#line 3811 "parse.y"
{
yyval.v.state_opt = calloc(1, sizeof(struct node_state_opt));
if (yyval.v.state_opt == NULL)
@@ -8431,8 +8473,8 @@ case 371:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 372:
-#line 3797 "parse.y"
+case 374:
+#line 3820 "parse.y"
{
yyval.v.state_opt = calloc(1, sizeof(struct node_state_opt));
if (yyval.v.state_opt == NULL)
@@ -8442,8 +8484,8 @@ case 372:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 373:
-#line 3805 "parse.y"
+case 375:
+#line 3828 "parse.y"
{
int i;
@@ -8475,43 +8517,43 @@ case 373:
yyval.v.state_opt->tail = yyval.v.state_opt;
}
break;
-case 374:
-#line 3837 "parse.y"
+case 376:
+#line 3860 "parse.y"
{
yyval.v.string = yystack.l_mark[0].v.string;
}
break;
-case 375:
-#line 3842 "parse.y"
+case 377:
+#line 3865 "parse.y"
{
yyval.v.qassign.qname = yystack.l_mark[0].v.string;
yyval.v.qassign.pqname = NULL;
}
break;
-case 376:
-#line 3846 "parse.y"
+case 378:
+#line 3869 "parse.y"
{
yyval.v.qassign.qname = yystack.l_mark[-1].v.string;
yyval.v.qassign.pqname = NULL;
}
break;
-case 377:
-#line 3850 "parse.y"
+case 379:
+#line 3873 "parse.y"
{
yyval.v.qassign.qname = yystack.l_mark[-3].v.string;
yyval.v.qassign.pqname = yystack.l_mark[-1].v.string;
}
break;
-case 378:
-#line 3856 "parse.y"
+case 380:
+#line 3879 "parse.y"
{ yyval.v.i = 0; }
break;
-case 379:
-#line 3857 "parse.y"
+case 381:
+#line 3880 "parse.y"
{ yyval.v.i = 1; }
break;
-case 380:
-#line 3860 "parse.y"
+case 382:
+#line 3883 "parse.y"
{
if (parseport(yystack.l_mark[0].v.string, &yyval.v.range, PPORT_RANGE|PPORT_STAR) == -1) {
free(yystack.l_mark[0].v.string);
@@ -8520,32 +8562,32 @@ case 380:
free(yystack.l_mark[0].v.string);
}
break;
-case 381:
-#line 3869 "parse.y"
+case 383:
+#line 3892 "parse.y"
{ yyval.v.host = yystack.l_mark[0].v.host; }
break;
-case 382:
-#line 3870 "parse.y"
+case 384:
+#line 3893 "parse.y"
{ yyval.v.host = yystack.l_mark[-1].v.host; }
break;
-case 383:
-#line 3873 "parse.y"
+case 385:
+#line 3896 "parse.y"
{ yyval.v.host = yystack.l_mark[-1].v.host; }
break;
-case 384:
-#line 3874 "parse.y"
+case 386:
+#line 3897 "parse.y"
{
yystack.l_mark[-3].v.host->tail->next = yystack.l_mark[-1].v.host;
yystack.l_mark[-3].v.host->tail = yystack.l_mark[-1].v.host->tail;
yyval.v.host = yystack.l_mark[-3].v.host;
}
break;
-case 385:
-#line 3881 "parse.y"
+case 387:
+#line 3904 "parse.y"
{ yyval.v.redirection = NULL; }
break;
-case 386:
-#line 3882 "parse.y"
+case 388:
+#line 3905 "parse.y"
{
yyval.v.redirection = calloc(1, sizeof(struct redirection));
if (yyval.v.redirection == NULL)
@@ -8554,8 +8596,8 @@ case 386:
yyval.v.redirection->rport.a = yyval.v.redirection->rport.b = yyval.v.redirection->rport.t = 0;
}
break;
-case 387:
-#line 3889 "parse.y"
+case 389:
+#line 3912 "parse.y"
{
yyval.v.redirection = calloc(1, sizeof(struct redirection));
if (yyval.v.redirection == NULL)
@@ -8564,8 +8606,8 @@ case 387:
yyval.v.redirection->rport = yystack.l_mark[0].v.range;
}
break;
-case 388:
-#line 3899 "parse.y"
+case 390:
+#line 3922 "parse.y"
{
yyval.v.hashkey = calloc(1, sizeof(struct pf_poolhashkey));
if (yyval.v.hashkey == NULL)
@@ -8576,8 +8618,8 @@ case 388:
yyval.v.hashkey->key32[3] = arc4random();
}
break;
-case 389:
-#line 3909 "parse.y"
+case 391:
+#line 3932 "parse.y"
{
if (!strncmp(yystack.l_mark[0].v.string, "0x", 2)) {
if (strlen(yystack.l_mark[0].v.string) != 34) {
@@ -8616,23 +8658,23 @@ case 389:
free(yystack.l_mark[0].v.string);
}
break;
-case 390:
-#line 3948 "parse.y"
+case 392:
+#line 3971 "parse.y"
{ bzero(&pool_opts, sizeof pool_opts); }
break;
-case 391:
-#line 3950 "parse.y"
+case 393:
+#line 3973 "parse.y"
{ yyval.v.pool_opts = pool_opts; }
break;
-case 392:
-#line 3951 "parse.y"
+case 394:
+#line 3974 "parse.y"
{
bzero(&pool_opts, sizeof pool_opts);
yyval.v.pool_opts = pool_opts;
}
break;
-case 395:
-#line 3961 "parse.y"
+case 397:
+#line 3984 "parse.y"
{
if (pool_opts.type) {
yyerror("pool type cannot be redefined");
@@ -8641,8 +8683,8 @@ case 395:
pool_opts.type = PF_POOL_BITMASK;
}
break;
-case 396:
-#line 3968 "parse.y"
+case 398:
+#line 3991 "parse.y"
{
if (pool_opts.type) {
yyerror("pool type cannot be redefined");
@@ -8651,8 +8693,8 @@ case 396:
pool_opts.type = PF_POOL_RANDOM;
}
break;
-case 397:
-#line 3975 "parse.y"
+case 399:
+#line 3998 "parse.y"
{
if (pool_opts.type) {
yyerror("pool type cannot be redefined");
@@ -8662,8 +8704,8 @@ case 397:
pool_opts.key = yystack.l_mark[0].v.hashkey;
}
break;
-case 398:
-#line 3983 "parse.y"
+case 400:
+#line 4006 "parse.y"
{
if (pool_opts.type) {
yyerror("pool type cannot be redefined");
@@ -8672,8 +8714,8 @@ case 398:
pool_opts.type = PF_POOL_ROUNDROBIN;
}
break;
-case 399:
-#line 3990 "parse.y"
+case 401:
+#line 4013 "parse.y"
{
if (pool_opts.staticport) {
yyerror("static-port cannot be redefined");
@@ -8682,8 +8724,8 @@ case 399:
pool_opts.staticport = 1;
}
break;
-case 400:
-#line 3997 "parse.y"
+case 402:
+#line 4020 "parse.y"
{
if (filter_opts.marker & POM_STICKYADDRESS) {
yyerror("sticky-address cannot be redefined");
@@ -8693,12 +8735,12 @@ case 400:
pool_opts.opts |= PF_POOL_STICKYADDR;
}
break;
-case 401:
-#line 4007 "parse.y"
+case 403:
+#line 4030 "parse.y"
{ yyval.v.redirection = NULL; }
break;
-case 402:
-#line 4008 "parse.y"
+case 404:
+#line 4031 "parse.y"
{
yyval.v.redirection = calloc(1, sizeof(struct redirection));
if (yyval.v.redirection == NULL)
@@ -8707,8 +8749,8 @@ case 402:
yyval.v.redirection->rport.a = yyval.v.redirection->rport.b = yyval.v.redirection->rport.t = 0;
}
break;
-case 403:
-#line 4015 "parse.y"
+case 405:
+#line 4038 "parse.y"
{
yyval.v.redirection = calloc(1, sizeof(struct redirection));
if (yyval.v.redirection == NULL)
@@ -8717,24 +8759,24 @@ case 403:
yyval.v.redirection->rport = yystack.l_mark[0].v.range;
}
break;
-case 404:
-#line 4024 "parse.y"
+case 406:
+#line 4047 "parse.y"
{ yyval.v.b.b1 = yyval.v.b.b2 = 0; yyval.v.b.w2 = 0; }
break;
-case 405:
-#line 4025 "parse.y"
+case 407:
+#line 4048 "parse.y"
{ yyval.v.b.b1 = 1; yyval.v.b.b2 = 0; yyval.v.b.w2 = 0; }
break;
-case 406:
-#line 4026 "parse.y"
+case 408:
+#line 4049 "parse.y"
{ yyval.v.b.b1 = 1; yyval.v.b.b2 = yystack.l_mark[0].v.logquick.log; yyval.v.b.w2 = yystack.l_mark[0].v.logquick.logif; }
break;
-case 407:
-#line 4027 "parse.y"
+case 409:
+#line 4050 "parse.y"
{ yyval.v.b.b1 = 0; yyval.v.b.b2 = yystack.l_mark[0].v.logquick.log; yyval.v.b.w2 = yystack.l_mark[0].v.logquick.logif; }
break;
-case 408:
-#line 4030 "parse.y"
+case 410:
+#line 4053 "parse.y"
{
if (yystack.l_mark[-2].v.i && yystack.l_mark[0].v.b.b1) {
yyerror("\"pass\" not valid with \"no\"");
@@ -8749,8 +8791,8 @@ case 408:
yyval.v.b.w2 = yystack.l_mark[0].v.b.w2;
}
break;
-case 409:
-#line 4043 "parse.y"
+case 411:
+#line 4066 "parse.y"
{
if (yystack.l_mark[-2].v.i && yystack.l_mark[0].v.b.b1) {
yyerror("\"pass\" not valid with \"no\"");
@@ -8765,8 +8807,8 @@ case 409:
yyval.v.b.w2 = yystack.l_mark[0].v.b.w2;
}
break;
-case 410:
-#line 4060 "parse.y"
+case 412:
+#line 4083 "parse.y"
{
struct pf_rule r;
@@ -8923,8 +8965,8 @@ case 410:
free(yystack.l_mark[-1].v.redirection);
}
break;
-case 411:
-#line 4219 "parse.y"
+case 413:
+#line 4242 "parse.y"
{
struct pf_rule binat;
struct pf_pooladdr *pa;
@@ -9089,28 +9131,28 @@ case 411:
pfctl_add_rule(pf, &binat, "");
}
break;
-case 412:
-#line 4384 "parse.y"
+case 414:
+#line 4407 "parse.y"
{ yyval.v.string = NULL; }
break;
-case 413:
-#line 4385 "parse.y"
+case 415:
+#line 4408 "parse.y"
{ yyval.v.string = yystack.l_mark[0].v.string; }
break;
-case 414:
-#line 4388 "parse.y"
+case 416:
+#line 4411 "parse.y"
{ yyval.v.tagged.neg = 0; yyval.v.tagged.name = NULL; }
break;
-case 415:
-#line 4389 "parse.y"
+case 417:
+#line 4412 "parse.y"
{ yyval.v.tagged.neg = yystack.l_mark[-2].v.number; yyval.v.tagged.name = yystack.l_mark[0].v.string; }
break;
-case 416:
-#line 4392 "parse.y"
+case 418:
+#line 4415 "parse.y"
{ yyval.v.rtableid = -1; }
break;
-case 417:
-#line 4393 "parse.y"
+case 419:
+#line 4416 "parse.y"
{
if (yystack.l_mark[0].v.number < 0 || yystack.l_mark[0].v.number > rt_tableid_max()) {
yyerror("invalid rtable id");
@@ -9119,8 +9161,8 @@ case 417:
yyval.v.rtableid = yystack.l_mark[0].v.number;
}
break;
-case 418:
-#line 4402 "parse.y"
+case 420:
+#line 4425 "parse.y"
{
yyval.v.host = calloc(1, sizeof(struct node_host));
if (yyval.v.host == NULL)
@@ -9131,8 +9173,8 @@ case 418:
yyval.v.host->tail = yyval.v.host;
}
break;
-case 419:
-#line 4411 "parse.y"
+case 421:
+#line 4434 "parse.y"
{
struct node_host *n;
@@ -9141,12 +9183,12 @@ case 419:
n->ifname = yystack.l_mark[-2].v.string;
}
break;
-case 420:
-#line 4420 "parse.y"
+case 422:
+#line 4443 "parse.y"
{ yyval.v.host = yystack.l_mark[-1].v.host; }
break;
-case 421:
-#line 4421 "parse.y"
+case 423:
+#line 4444 "parse.y"
{
if (yystack.l_mark[-3].v.host->af == 0)
yystack.l_mark[-3].v.host->af = yystack.l_mark[-1].v.host->af;
@@ -9160,24 +9202,24 @@ case 421:
yyval.v.host = yystack.l_mark[-3].v.host;
}
break;
-case 422:
-#line 4435 "parse.y"
+case 424:
+#line 4458 "parse.y"
{ yyval.v.host = yystack.l_mark[0].v.host; }
break;
-case 423:
-#line 4436 "parse.y"
+case 425:
+#line 4459 "parse.y"
{ yyval.v.host = yystack.l_mark[-1].v.host; }
break;
-case 424:
-#line 4439 "parse.y"
+case 426:
+#line 4462 "parse.y"
{
yyval.v.route.host = NULL;
yyval.v.route.rt = 0;
yyval.v.route.pool_opts = 0;
}
break;
-case 425:
-#line 4444 "parse.y"
+case 427:
+#line 4467 "parse.y"
{
/* backwards-compat */
yyval.v.route.host = NULL;
@@ -9185,8 +9227,8 @@ case 425:
yyval.v.route.pool_opts = 0;
}
break;
-case 426:
-#line 4450 "parse.y"
+case 428:
+#line 4473 "parse.y"
{
yyval.v.route.host = yystack.l_mark[-1].v.host;
yyval.v.route.rt = PF_ROUTETO;
@@ -9195,8 +9237,8 @@ case 426:
yyval.v.route.key = yystack.l_mark[0].v.pool_opts.key;
}
break;
-case 427:
-#line 4457 "parse.y"
+case 429:
+#line 4480 "parse.y"
{
yyval.v.route.host = yystack.l_mark[-1].v.host;
yyval.v.route.rt = PF_REPLYTO;
@@ -9205,8 +9247,8 @@ case 427:
yyval.v.route.key = yystack.l_mark[0].v.pool_opts.key;
}
break;
-case 428:
-#line 4464 "parse.y"
+case 430:
+#line 4487 "parse.y"
{
yyval.v.route.host = yystack.l_mark[-1].v.host;
yyval.v.route.rt = PF_DUPTO;
@@ -9215,8 +9257,8 @@ case 428:
yyval.v.route.key = yystack.l_mark[0].v.pool_opts.key;
}
break;
-case 429:
-#line 4474 "parse.y"
+case 431:
+#line 4497 "parse.y"
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free(yystack.l_mark[-1].v.string);
@@ -9234,8 +9276,8 @@ case 429:
free(yystack.l_mark[-1].v.string);
}
break;
-case 430:
-#line 4490 "parse.y"
+case 432:
+#line 4513 "parse.y"
{
if (check_rulestate(PFCTL_STATE_OPTION))
YYERROR;
@@ -9247,8 +9289,8 @@ case 430:
YYERROR;
}
break;
-case 433:
-#line 4507 "parse.y"
+case 435:
+#line 4530 "parse.y"
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free(yystack.l_mark[-1].v.string);
@@ -9266,12 +9308,12 @@ case 433:
free(yystack.l_mark[-1].v.string);
}
break;
-case 438:
-#line 4533 "parse.y"
+case 440:
+#line 4556 "parse.y"
{ yyval.v.number = 0; }
break;
-case 439:
-#line 4534 "parse.y"
+case 441:
+#line 4557 "parse.y"
{
if (!strcmp(yystack.l_mark[0].v.string, "yes"))
yyval.v.number = 1;
@@ -9284,31 +9326,31 @@ case 439:
free(yystack.l_mark[0].v.string);
}
break;
-case 440:
-#line 4547 "parse.y"
+case 442:
+#line 4570 "parse.y"
{ yyval.v.i = PF_OP_EQ; }
break;
-case 441:
-#line 4548 "parse.y"
+case 443:
+#line 4571 "parse.y"
{ yyval.v.i = PF_OP_NE; }
break;
-case 442:
-#line 4549 "parse.y"
+case 444:
+#line 4572 "parse.y"
{ yyval.v.i = PF_OP_LE; }
break;
-case 443:
-#line 4550 "parse.y"
+case 445:
+#line 4573 "parse.y"
{ yyval.v.i = PF_OP_LT; }
break;
-case 444:
-#line 4551 "parse.y"
+case 446:
+#line 4574 "parse.y"
{ yyval.v.i = PF_OP_GE; }
break;
-case 445:
-#line 4552 "parse.y"
+case 447:
+#line 4575 "parse.y"
{ yyval.v.i = PF_OP_GT; }
break;
-#line 9314 "parse.c"
+#line 9356 "parse.c"
}
yystack.s_mark -= yym;
yystate = *yystack.s_mark;
diff --git a/freebsd/sbin/pfctl/parse.h b/freebsd/sbin/pfctl/parse.h
index 15048157..94ace2b0 100644
--- a/freebsd/sbin/pfctl/parse.h
+++ b/freebsd/sbin/pfctl/parse.h
@@ -65,66 +65,67 @@
#define LIMIT 321
#define LOGINTERFACE 322
#define BLOCKPOLICY 323
-#define RANDOMID 324
-#define REQUIREORDER 325
-#define SYNPROXY 326
-#define FINGERPRINTS 327
-#define NOSYNC 328
-#define DEBUG 329
-#define SKIP 330
-#define HOSTID 331
-#define ANTISPOOF 332
-#define FOR 333
-#define INCLUDE 334
-#define BITMASK 335
-#define RANDOM 336
-#define SOURCEHASH 337
-#define ROUNDROBIN 338
-#define STATICPORT 339
-#define PROBABILITY 340
-#define ALTQ 341
-#define CBQ 342
-#define CODEL 343
-#define PRIQ 344
-#define HFSC 345
-#define FAIRQ 346
-#define BANDWIDTH 347
-#define TBRSIZE 348
-#define LINKSHARE 349
-#define REALTIME 350
-#define UPPERLIMIT 351
-#define QUEUE 352
-#define PRIORITY 353
-#define QLIMIT 354
-#define HOGS 355
-#define BUCKETS 356
-#define RTABLE 357
-#define TARGET 358
-#define INTERVAL 359
-#define LOAD 360
-#define RULESET_OPTIMIZATION 361
-#define PRIO 362
-#define STICKYADDRESS 363
-#define MAXSRCSTATES 364
-#define MAXSRCNODES 365
-#define SOURCETRACK 366
-#define GLOBAL 367
-#define RULE 368
-#define MAXSRCCONN 369
-#define MAXSRCCONNRATE 370
-#define OVERLOAD 371
-#define FLUSH 372
-#define SLOPPY 373
-#define TAGGED 374
-#define TAG 375
-#define IFBOUND 376
-#define FLOATING 377
-#define STATEPOLICY 378
-#define STATEDEFAULTS 379
-#define ROUTE 380
-#define SETTOS 381
-#define DIVERTTO 382
-#define DIVERTREPLY 383
-#define STRING 384
-#define NUMBER 385
-#define PORTBINARY 386
+#define FAILPOLICY 324
+#define RANDOMID 325
+#define REQUIREORDER 326
+#define SYNPROXY 327
+#define FINGERPRINTS 328
+#define NOSYNC 329
+#define DEBUG 330
+#define SKIP 331
+#define HOSTID 332
+#define ANTISPOOF 333
+#define FOR 334
+#define INCLUDE 335
+#define BITMASK 336
+#define RANDOM 337
+#define SOURCEHASH 338
+#define ROUNDROBIN 339
+#define STATICPORT 340
+#define PROBABILITY 341
+#define ALTQ 342
+#define CBQ 343
+#define CODEL 344
+#define PRIQ 345
+#define HFSC 346
+#define FAIRQ 347
+#define BANDWIDTH 348
+#define TBRSIZE 349
+#define LINKSHARE 350
+#define REALTIME 351
+#define UPPERLIMIT 352
+#define QUEUE 353
+#define PRIORITY 354
+#define QLIMIT 355
+#define HOGS 356
+#define BUCKETS 357
+#define RTABLE 358
+#define TARGET 359
+#define INTERVAL 360
+#define LOAD 361
+#define RULESET_OPTIMIZATION 362
+#define PRIO 363
+#define STICKYADDRESS 364
+#define MAXSRCSTATES 365
+#define MAXSRCNODES 366
+#define SOURCETRACK 367
+#define GLOBAL 368
+#define RULE 369
+#define MAXSRCCONN 370
+#define MAXSRCCONNRATE 371
+#define OVERLOAD 372
+#define FLUSH 373
+#define SLOPPY 374
+#define TAGGED 375
+#define TAG 376
+#define IFBOUND 377
+#define FLOATING 378
+#define STATEPOLICY 379
+#define STATEDEFAULTS 380
+#define ROUTE 381
+#define SETTOS 382
+#define DIVERTTO 383
+#define DIVERTREPLY 384
+#define STRING 385
+#define NUMBER 386
+#define PORTBINARY 387
diff --git a/freebsd/sbin/pfctl/parse.y b/freebsd/sbin/pfctl/parse.y
index 11fe33b9..a321be70 100644
--- a/freebsd/sbin/pfctl/parse.y
+++ b/freebsd/sbin/pfctl/parse.y
@@ -36,16 +36,19 @@
#ifdef __rtems__
#include "rtems-bsd-pfctl-namespace.h"
-#endif /* __rtems__ */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#ifdef __rtems__
-#include <machine/rtems-bsd-program.h>
+/* Provided by kernel-space modules */
#define pf_find_or_create_ruleset _bsd_pf_find_or_create_ruleset
#define pf_anchor_setup _bsd_pf_anchor_setup
#define pf_remove_if_empty_ruleset _bsd_pf_remove_if_empty_ruleset
+
+#include <machine/rtems-bsd-program.h>
#endif /* __rtems__ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define PFIOC_USE_LATEST
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -96,6 +99,7 @@ static u_int16_t returnicmpdefault =
static u_int16_t returnicmp6default =
(ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
static int blockpolicy = PFRULE_DROP;
+static int failpolicy = PFRULE_DROP;
static int require_order = 1;
static int default_statelock;
@@ -302,7 +306,7 @@ static struct queue_opts {
struct node_queue_bw queue_bwspec;
struct node_queue_opt scheduler;
int priority;
- int tbrsize;
+ unsigned int tbrsize;
int qlimit;
} queue_opts;
@@ -472,8 +476,8 @@ int parseport(char *, struct range *r, int);
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
-%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
-%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
+%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
+%token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
%token ANTISPOOF FOR INCLUDE
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
@@ -657,6 +661,20 @@ option : SET OPTIMIZATION STRING {
YYERROR;
blockpolicy = PFRULE_RETURN;
}
+ | SET FAILPOLICY DROP {
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set fail-policy drop\n");
+ if (check_rulestate(PFCTL_STATE_OPTION))
+ YYERROR;
+ failpolicy = PFRULE_DROP;
+ }
+ | SET FAILPOLICY RETURN {
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set fail-policy return\n");
+ if (check_rulestate(PFCTL_STATE_OPTION))
+ YYERROR;
+ failpolicy = PFRULE_RETURN;
+ }
| SET REQUIREORDER yesno {
if (pf->opts & PF_OPT_VERBOSE)
printf("set require-order %s\n",
@@ -1625,8 +1643,8 @@ queue_opt : BANDWIDTH bandwidth {
yyerror("tbrsize cannot be respecified");
YYERROR;
}
- if ($2 < 0 || $2 > 65535) {
- yyerror("tbrsize too big: max 65535");
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("tbrsize too big: max %u", UINT_MAX);
YYERROR;
}
queue_opts.marker |= QOM_TBRSIZE;
@@ -1675,10 +1693,10 @@ bandwidth : STRING {
}
}
free($1);
- $$.bw_absolute = (u_int32_t)bps;
+ $$.bw_absolute = (u_int64_t)bps;
}
| NUMBER {
- if ($1 < 0 || $1 > UINT_MAX) {
+ if ($1 < 0 || $1 >= LLONG_MAX) {
yyerror("bandwidth number too big");
YYERROR;
}
@@ -2653,7 +2671,12 @@ probability : STRING {
;
-action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
+action : PASS {
+ $$.b1 = PF_PASS;
+ $$.b2 = failpolicy;
+ $$.w = returnicmpdefault;
+ $$.w2 = returnicmp6default;
+ }
| BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
;
@@ -5491,6 +5514,7 @@ lookup(char *s)
{ "drop", DROP},
{ "drop-ovl", FRAGDROP},
{ "dup-to", DUPTO},
+ { "fail-policy", FAILPOLICY},
{ "fairq", FAIRQ},
{ "fastroute", FASTROUTE},
{ "file", FILENAME},
@@ -5955,6 +5979,7 @@ parse_config(char *filename, struct pfctl *xpf)
returnicmp6default =
(ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
blockpolicy = PFRULE_DROP;
+ failpolicy = PFRULE_DROP;
require_order = 1;
if ((file = pushfile(filename, 0)) == NULL) {
diff --git a/freebsd/sbin/pfctl/pfctl.c b/freebsd/sbin/pfctl/pfctl.c
index ca7d6f38..6b57dd00 100644
--- a/freebsd/sbin/pfctl/pfctl.c
+++ b/freebsd/sbin/pfctl/pfctl.c
@@ -40,17 +40,21 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#ifdef __rtems__
#define __need_getopt_newlib
#include <getopt.h>
#include <machine/rtems-bsd-program.h>
#include <machine/rtems-bsd-commands.h>
+
+/* Provided by kernel-space modules */
#define pf_get_ruleset_number _bsd_pf_get_ruleset_number
#define pf_init_ruleset _bsd_pf_init_ruleset
#endif /* __rtems__ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define PFIOC_USE_LATEST
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -87,7 +91,7 @@ int pfctl_disable(int, int);
int pfctl_clear_stats(int, int);
int pfctl_get_skip_ifaces(void);
int pfctl_check_skip_ifaces(char *);
-int pfctl_clear_skip_ifaces(struct pfctl *);
+int pfctl_adjust_skip_ifaces(struct pfctl *);
int pfctl_clear_interface_flags(int, int);
int pfctl_clear_rules(int, int, char *);
int pfctl_clear_nat(int, int, char *);
@@ -114,6 +118,7 @@ int pfctl_show_nat(int, int, char *);
int pfctl_show_src_nodes(int, int);
int pfctl_show_states(int, const char *, int);
int pfctl_show_status(int, int);
+int pfctl_show_running(int);
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, int);
void pfctl_debug(int, u_int32_t, int);
@@ -235,7 +240,7 @@ static const char * const clearopt_list[] = {
static const char * const showopt_list[] = {
"nat", "queue", "rules", "Anchors", "Sources", "states", "info",
"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
- "all", NULL
+ "Running", "all", NULL
};
static const char * const tblcmdopt_list[] = {
@@ -340,21 +345,66 @@ int
pfctl_check_skip_ifaces(char *ifname)
{
struct pfi_kif *p;
+ struct node_host *h = NULL, *n = NULL;
- PFRB_FOREACH(p, &skip_b)
- if ((p->pfik_flags & PFI_IFLAG_SKIP) && !strcmp(ifname, p->pfik_name))
+ PFRB_FOREACH(p, &skip_b) {
+ if (!strcmp(ifname, p->pfik_name) &&
+ (p->pfik_flags & PFI_IFLAG_SKIP))
p->pfik_flags &= ~PFI_IFLAG_SKIP;
+ if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) {
+ if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL)
+ continue;
+
+ for (n = h; n != NULL; n = n->next) {
+ if (p->pfik_ifp == NULL)
+ continue;
+ if (strncmp(p->pfik_name, ifname, IFNAMSIZ))
+ continue;
+
+ p->pfik_flags &= ~PFI_IFLAG_SKIP;
+ }
+ }
+ }
return (0);
}
int
-pfctl_clear_skip_ifaces(struct pfctl *pf)
+pfctl_adjust_skip_ifaces(struct pfctl *pf)
{
- struct pfi_kif *p;
+ struct pfi_kif *p, *pp;
+ struct node_host *h = NULL, *n = NULL;
+
+ PFRB_FOREACH(p, &skip_b) {
+ if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP))
+ continue;
+
+ pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
+ if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL)
+ continue;
+
+ for (n = h; n != NULL; n = n->next)
+ PFRB_FOREACH(pp, &skip_b) {
+ if (pp->pfik_ifp == NULL)
+ continue;
+
+ if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ))
+ continue;
+
+ if (!(pp->pfik_flags & PFI_IFLAG_SKIP))
+ pfctl_set_interface_flags(pf,
+ pp->pfik_name, PFI_IFLAG_SKIP, 1);
+ if (pp->pfik_flags & PFI_IFLAG_SKIP)
+ pp->pfik_flags &= ~PFI_IFLAG_SKIP;
+ }
+ }
+
+ PFRB_FOREACH(p, &skip_b) {
+ if (p->pfik_ifp == NULL || ! (p->pfik_flags & PFI_IFLAG_SKIP))
+ continue;
+
+ pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
+ }
- PFRB_FOREACH(p, &skip_b)
- if (p->pfik_flags & PFI_IFLAG_SKIP)
- pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
return (0);
}
@@ -1181,6 +1231,20 @@ pfctl_show_status(int dev, int opts)
}
int
+pfctl_show_running(int dev)
+{
+ struct pf_status status;
+
+ if (ioctl(dev, DIOCGETSTATUS, &status)) {
+ warn("DIOCGETSTATUS");
+ return (-1);
+ }
+
+ print_running(&status);
+ return (!status.running);
+}
+
+int
pfctl_show_timeouts(int dev, int opts)
{
struct pfioc_tm pt;
@@ -1490,6 +1554,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
}
memset(&pa, 0, sizeof(pa));
+ pa.version = PFIOC_ALTQ_VERSION;
memset(&pf, 0, sizeof(pf));
memset(&trs, 0, sizeof(trs));
if ((path = calloc(1, MAXPATHLEN)) == NULL)
@@ -1548,7 +1613,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
goto _error;
}
if (loadopt & PFCTL_FLAG_OPTION)
- pfctl_clear_skip_ifaces(&pf);
+ pfctl_adjust_skip_ifaces(&pf);
if ((pf.loadopt & PFCTL_FLAG_FILTER &&
(pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) ||
@@ -1998,6 +2063,7 @@ pfctl_test_altqsupport(int dev, int opts)
{
struct pfioc_altq pa;
+ pa.version = PFIOC_ALTQ_VERSION;
if (ioctl(dev, DIOCGETALTQS, &pa)) {
if (errno == ENODEV) {
if (opts & PF_OPT_VERBOSE)
@@ -2332,6 +2398,9 @@ main(int argc, char *argv[])
case 'i':
pfctl_show_status(dev, opts);
break;
+ case 'R':
+ error = pfctl_show_running(dev);
+ break;
case 't':
pfctl_show_timeouts(dev, opts);
break;
@@ -2449,7 +2518,7 @@ main(int argc, char *argv[])
}
if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
- !anchorname[0])
+ !anchorname[0] && !(opts & PF_OPT_NOACTION))
if (pfctl_get_skip_ifaces())
error = 1;
diff --git a/freebsd/sbin/pfctl/pfctl_altq.c b/freebsd/sbin/pfctl/pfctl_altq.c
index 145d60ae..1220cfc6 100644
--- a/freebsd/sbin/pfctl/pfctl_altq.c
+++ b/freebsd/sbin/pfctl/pfctl_altq.c
@@ -24,12 +24,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#ifdef __rtems__
#include <machine/rtems-bsd-program.h>
#endif /* __rtems__ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define PFIOC_USE_LATEST
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
+#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
@@ -100,14 +103,14 @@ static int gsc_add_seg(struct gen_sc *, double, double, double,
static double sc_x2y(struct service_curve *, double);
#ifdef __FreeBSD__
-u_int32_t getifspeed(int, char *);
+u_int64_t getifspeed(int, char *);
#else
u_int32_t getifspeed(char *);
#endif
u_long getifmtu(char *);
int eval_queue_opts(struct pf_altq *, struct node_queue_opt *,
- u_int32_t);
-u_int32_t eval_bwspec(struct node_queue_bw *, u_int32_t);
+ u_int64_t);
+u_int64_t eval_bwspec(struct node_queue_bw *, u_int64_t);
void print_hfsc_sc(const char *, u_int, u_int, u_int,
const struct node_hfsc_sc *);
void print_fairq_sc(const char *, u_int, u_int, u_int,
@@ -270,7 +273,8 @@ int
eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
struct node_queue_opt *opts)
{
- u_int rate, size, errors = 0;
+ u_int64_t rate;
+ u_int size, errors = 0;
if (bw->bw_absolute > 0)
pa->ifbandwidth = bw->bw_absolute;
@@ -287,6 +291,15 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
} else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0)
pa->ifbandwidth = rate;
+ /*
+ * Limit bandwidth to UINT_MAX for schedulers that aren't 64-bit ready.
+ */
+ if ((pa->scheduler != ALTQT_HFSC) && (pa->ifbandwidth > UINT_MAX)) {
+ pa->ifbandwidth = UINT_MAX;
+ warnx("interface %s bandwidth limited to %" PRIu64 " bps "
+ "because selected scheduler is 32-bit limited\n", pa->ifname,
+ pa->ifbandwidth);
+ }
errors += eval_queue_opts(pa, opts, pa->ifbandwidth);
/* if tbrsize is not specified, use heuristics */
@@ -298,11 +311,11 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
size = 4;
else if (rate <= 200 * 1000 * 1000)
size = 8;
- else
+ else if (rate <= 2500 * 1000 * 1000ULL)
size = 24;
+ else
+ size = 128;
size = size * getifmtu(pa->ifname);
- if (size > 0xffff)
- size = 0xffff;
pa->tbrsize = size;
}
return (errors);
@@ -350,7 +363,7 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
{
/* should be merged with expand_queue */
struct pf_altq *if_pa, *parent, *altq;
- u_int32_t bwsum;
+ u_int64_t bwsum;
int error = 0;
/* find the corresponding interface and copy fields used by queues */
@@ -384,7 +397,7 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC ||
pa->scheduler == ALTQT_FAIRQ) {
pa->bandwidth = eval_bwspec(bw,
- parent == NULL ? 0 : parent->bandwidth);
+ parent == NULL ? pa->ifbandwidth : parent->bandwidth);
if (pa->bandwidth > pa->ifbandwidth) {
fprintf(stderr, "bandwidth for %s higher than "
@@ -415,7 +428,8 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
}
}
- if (eval_queue_opts(pa, opts, parent == NULL? 0 : parent->bandwidth))
+ if (eval_queue_opts(pa, opts,
+ parent == NULL ? pa->ifbandwidth : parent->bandwidth))
return (1);
switch (pa->scheduler) {
@@ -509,12 +523,13 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
* this causes integer overflow in kernel!
* (bandwidth < 6Kbps when max_pkt_size=1500)
*/
- if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0)
+ if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0) {
warnx("queue bandwidth must be larger than %s",
rate2str(ifnsPerByte * (double)opts->maxpktsize /
(double)INT_MAX * (double)pa->ifbandwidth));
fprintf(stderr, "cbq: queue %s is too slow!\n",
pa->qname);
+ }
nsPerByte = (double)(INT_MAX / opts->maxpktsize);
}
@@ -720,7 +735,7 @@ static int
eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
{
struct pf_altq *altq, *parent;
- struct hfsc_opts *opts;
+ struct hfsc_opts_v1 *opts;
struct service_curve sc;
opts = &pa->pq_u.hfsc_opts;
@@ -1012,7 +1027,7 @@ check_commit_fairq(int dev __unused, int opts __unused, struct pf_altq *pa)
static int
print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
{
- const struct hfsc_opts *opts;
+ const struct hfsc_opts_v1 *opts;
const struct node_hfsc_sc *rtsc, *lssc, *ulsc;
opts = &a->pq_u.hfsc_opts;
@@ -1333,7 +1348,7 @@ rate2str(double rate)
* FreeBSD does not have SIOCGIFDATA.
* To emulate this, DIOCGIFSPEED ioctl added to pf.
*/
-u_int32_t
+u_int64_t
getifspeed(int pfdev, char *ifname)
{
struct pf_ifspeed io;
@@ -1344,7 +1359,7 @@ getifspeed(int pfdev, char *ifname)
errx(1, "getifspeed: strlcpy");
if (ioctl(pfdev, DIOCGIFSPEED, &io) == -1)
err(1, "DIOCGIFSPEED");
- return ((u_int32_t)io.baudrate);
+ return (io.baudrate);
}
#else
u_int32_t
@@ -1399,7 +1414,7 @@ getifmtu(char *ifname)
int
eval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts,
- u_int32_t ref_bw)
+ u_int64_t ref_bw)
{
int errors = 0;
@@ -1475,11 +1490,21 @@ eval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts,
return (errors);
}
-u_int32_t
-eval_bwspec(struct node_queue_bw *bw, u_int32_t ref_bw)
+/*
+ * If absolute bandwidth if set, return the lesser of that value and the
+ * reference bandwidth. Limiting to the reference bandwidth allows simple
+ * limiting of configured bandwidth parameters for schedulers that are
+ * 32-bit limited, as the root/interface bandwidth (top-level reference
+ * bandwidth) will be properly limited in that case.
+ *
+ * Otherwise, if the absolute bandwidth is not set, return given percentage
+ * of reference bandwidth.
+ */
+u_int64_t
+eval_bwspec(struct node_queue_bw *bw, u_int64_t ref_bw)
{
if (bw->bw_absolute > 0)
- return (bw->bw_absolute);
+ return (MIN(bw->bw_absolute, ref_bw));
if (bw->bw_percent > 0)
return (ref_bw / 100 * bw->bw_percent);
diff --git a/freebsd/sbin/pfctl/pfctl_parser.c b/freebsd/sbin/pfctl/pfctl_parser.c
index 88646e79..81e23e84 100644
--- a/freebsd/sbin/pfctl/pfctl_parser.c
+++ b/freebsd/sbin/pfctl/pfctl_parser.c
@@ -629,6 +629,12 @@ print_status(struct pf_status *s, int opts)
}
void
+print_running(struct pf_status *status)
+{
+ printf("%s\n", status->running ? "Enabled" : "Disabled");
+}
+
+void
print_src_node(struct pf_src_node *sn, int opts)
{
struct pf_addr_wrap aw;
diff --git a/freebsd/sbin/pfctl/pfctl_parser.h b/freebsd/sbin/pfctl/pfctl_parser.h
index e652c97c..05ebdf29 100644
--- a/freebsd/sbin/pfctl/pfctl_parser.h
+++ b/freebsd/sbin/pfctl/pfctl_parser.h
@@ -134,7 +134,7 @@ struct node_os {
};
struct node_queue_bw {
- u_int32_t bw_absolute;
+ u_int64_t bw_absolute;
u_int16_t bw_percent;
};
@@ -257,6 +257,7 @@ void print_src_node(struct pf_src_node *, int);
void print_rule(struct pf_rule *, const char *, int, int);
void print_tabledef(const char *, int, int, struct node_tinithead *);
void print_status(struct pf_status *, int);
+void print_running(struct pf_status *);
int eval_pfaltq(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
struct node_queue_opt *);
@@ -314,6 +315,7 @@ int unmask(struct pf_addr *, sa_family_t);
void ifa_load(void);
int get_socket_domain(void);
struct node_host *ifa_exists(const char *);
+struct node_host *ifa_grouplookup(const char *ifa_name, int flags);
struct node_host *ifa_lookup(const char *, int);
struct node_host *host(const char *);
diff --git a/freebsd/sbin/pfctl/pfctl_qstats.c b/freebsd/sbin/pfctl/pfctl_qstats.c
index dda3a494..a5beb88a 100644
--- a/freebsd/sbin/pfctl/pfctl_qstats.c
+++ b/freebsd/sbin/pfctl/pfctl_qstats.c
@@ -22,12 +22,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#ifdef __rtems__
#include <machine/rtems-bsd-program.h>
#endif /* __rtems__ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define PFIOC_USE_LATEST
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -165,6 +167,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
memset(&pa, 0, sizeof(pa));
memset(&pq, 0, sizeof(pq));
memset(&qstats, 0, sizeof(qstats));
+ pa.version = PFIOC_ALTQ_VERSION;
if (ioctl(dev, DIOCGETALTQS, &pa)) {
warn("DIOCGETALTQS");
return (-1);
@@ -194,6 +197,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
pq.ticket = pa.ticket;
pq.buf = &qstats.data;
pq.nbytes = sizeof(qstats.data);
+ pq.version = altq_stats_version(pa.altq.scheduler);
if (ioctl(dev, DIOCGETQSTATS, &pq)) {
warn("DIOCGETQSTATS");
return (-1);
diff --git a/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h b/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h
index 46053fd9..1712b9e6 100644
--- a/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h
+++ b/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h
@@ -79,13 +79,13 @@
#define pfctl_add_pool _bsd_pfctl_pfctl_add_pool
#define pfctl_add_rule _bsd_pfctl_pfctl_add_rule
#define pfctl_addrprefix _bsd_pfctl_pfctl_addrprefix
+#define pfctl_adjust_skip_ifaces _bsd_pfctl_pfctl_adjust_skip_ifaces
#define pfctl_check_skip_ifaces _bsd_pfctl_pfctl_check_skip_ifaces
#define pfctl_clear_altq _bsd_pfctl_pfctl_clear_altq
#define pfctl_clear_interface_flags _bsd_pfctl_pfctl_clear_interface_flags
#define pfctl_clear_nat _bsd_pfctl_pfctl_clear_nat
#define pfctl_clear_pool _bsd_pfctl_pfctl_clear_pool
#define pfctl_clear_rules _bsd_pfctl_pfctl_clear_rules
-#define pfctl_clear_skip_ifaces _bsd_pfctl_pfctl_clear_skip_ifaces
#define pfctl_clear_src_nodes _bsd_pfctl_pfctl_clear_src_nodes
#define pfctl_clear_states _bsd_pfctl_pfctl_clear_states
#define pfctl_clear_stats _bsd_pfctl_pfctl_clear_stats
@@ -125,6 +125,7 @@
#define pfctl_show_limits _bsd_pfctl_pfctl_show_limits
#define pfctl_show_nat _bsd_pfctl_pfctl_show_nat
#define pfctl_show_rules _bsd_pfctl_pfctl_show_rules
+#define pfctl_show_running _bsd_pfctl_pfctl_show_running
#define pfctl_show_src_nodes _bsd_pfctl_pfctl_show_src_nodes
#define pfctl_show_states _bsd_pfctl_pfctl_show_states
#define pfctl_show_status _bsd_pfctl_pfctl_show_status
@@ -210,6 +211,7 @@
#define print_pool _bsd_pfctl_print_pool
#define print_port _bsd_pfctl_print_port
#define print_rule _bsd_pfctl_print_rule
+#define print_running _bsd_pfctl_print_running
#define print_src_node _bsd_pfctl_print_src_node
#define print_status _bsd_pfctl_print_status
#define print_tabledef _bsd_pfctl_print_tabledef
diff --git a/freebsd/sbin/pfctl/rtems-bsd-pfctl-parse-data.h b/freebsd/sbin/pfctl/rtems-bsd-pfctl-parse-data.h
index ec25eae1..678753ca 100644
--- a/freebsd/sbin/pfctl/rtems-bsd-pfctl-parse-data.h
+++ b/freebsd/sbin/pfctl/rtems-bsd-pfctl-parse-data.h
@@ -8,6 +8,7 @@ RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char pushback_buffer[]);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int blockpolicy);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int debug);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int default_statelock);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int failpolicy);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int parseindex);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int pushback_index);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int require_order);
diff --git a/freebsd/sbin/sysctl/sysctl.c b/freebsd/sbin/sysctl/sysctl.c
index a1b6d268..f298da0c 100644
--- a/freebsd/sbin/sysctl/sysctl.c
+++ b/freebsd/sbin/sysctl/sysctl.c
@@ -739,21 +739,22 @@ S_efi_map(size_t l2, void *p)
size_t efisz;
int ndesc, i;
- static const char *types[] = {
- "Reserved",
- "LoaderCode",
- "LoaderData",
- "BootServicesCode",
- "BootServicesData",
- "RuntimeServicesCode",
- "RuntimeServicesData",
- "ConventionalMemory",
- "UnusableMemory",
- "ACPIReclaimMemory",
- "ACPIMemoryNVS",
- "MemoryMappedIO",
- "MemoryMappedIOPortSpace",
- "PalCode"
+ static const char * const types[] = {
+ [EFI_MD_TYPE_NULL] = "Reserved",
+ [EFI_MD_TYPE_CODE] = "LoaderCode",
+ [EFI_MD_TYPE_DATA] = "LoaderData",
+ [EFI_MD_TYPE_BS_CODE] = "BootServicesCode",
+ [EFI_MD_TYPE_BS_DATA] = "BootServicesData",
+ [EFI_MD_TYPE_RT_CODE] = "RuntimeServicesCode",
+ [EFI_MD_TYPE_RT_DATA] = "RuntimeServicesData",
+ [EFI_MD_TYPE_FREE] = "ConventionalMemory",
+ [EFI_MD_TYPE_BAD] = "UnusableMemory",
+ [EFI_MD_TYPE_RECLAIM] = "ACPIReclaimMemory",
+ [EFI_MD_TYPE_FIRMWARE] = "ACPIMemoryNVS",
+ [EFI_MD_TYPE_IOMEM] = "MemoryMappedIO",
+ [EFI_MD_TYPE_IOPORT] = "MemoryMappedIOPortSpace",
+ [EFI_MD_TYPE_PALCODE] = "PalCode",
+ [EFI_MD_TYPE_PERSISTENT] = "PersistentMemory",
};
/*
@@ -766,7 +767,7 @@ S_efi_map(size_t l2, void *p)
}
efihdr = p;
efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
- map = (struct efi_md *)((uint8_t *)efihdr + efisz);
+ map = (struct efi_md *)((uint8_t *)efihdr + efisz);
if (efihdr->descriptor_size == 0)
return (0);
@@ -774,7 +775,7 @@ S_efi_map(size_t l2, void *p)
warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
efihdr->memory_size);
return (1);
- }
+ }
ndesc = efihdr->memory_size / efihdr->descriptor_size;
printf("\n%23s %12s %12s %8s %4s",
@@ -782,9 +783,10 @@ S_efi_map(size_t l2, void *p)
for (i = 0; i < ndesc; i++,
map = efi_next_descriptor(map, efihdr->descriptor_size)) {
- if (map->md_type <= EFI_MD_TYPE_PALCODE)
+ type = NULL;
+ if (map->md_type < nitems(types))
type = types[map->md_type];
- else
+ if (type == NULL)
type = "<INVALID>";
printf("\n%23s %012jx %12p %08jx ", type,
(uintmax_t)map->md_phys, map->md_virt,
diff --git a/freebsd/sys/arm/include/machine/cpufunc.h b/freebsd/sys/arm/include/machine/cpufunc.h
index e3ada92b..9dba8043 100644
--- a/freebsd/sys/arm/include/machine/cpufunc.h
+++ b/freebsd/sys/arm/include/machine/cpufunc.h
@@ -46,8 +46,8 @@
#ifndef _MACHINE_CPUFUNC_H_
#define _MACHINE_CPUFUNC_H_
-#ifdef _KERNEL
#ifndef __rtems__
+#ifdef _KERNEL
#include <sys/types.h>
#include <machine/armreg.h>
@@ -55,7 +55,7 @@
static __inline void
breakpoint(void)
{
- __asm(".word 0xe7ffffff");
+ __asm("udf 0xffff");
}
struct cpu_functions {
@@ -209,58 +209,12 @@ int set_cpufuncs (void);
#define ARCHITECTURE_NOT_SUPPORTED 2 /* not known */
void cpufunc_nullop (void);
-u_int cpu_ident (void);
u_int cpufunc_control (u_int clear, u_int bic);
void cpu_domains (u_int domains);
-u_int cpu_faultstatus (void);
-u_int cpu_faultaddress (void);
-u_int cpu_get_control (void);
-u_int cpu_pfr (int);
-
-#if defined(CPU_FA526)
-void fa526_setup (void);
-void fa526_setttb (u_int ttb);
-void fa526_context_switch (void);
-void fa526_cpu_sleep (int);
-void fa526_tlb_flushID_SE (u_int);
-
-void fa526_icache_sync_range(vm_offset_t start, vm_size_t end);
-void fa526_dcache_wbinv_all (void);
-void fa526_dcache_wbinv_range(vm_offset_t start, vm_size_t end);
-void fa526_dcache_inv_range (vm_offset_t start, vm_size_t end);
-void fa526_dcache_wb_range (vm_offset_t start, vm_size_t end);
-void fa526_idcache_wbinv_all(void);
-void fa526_idcache_wbinv_range(vm_offset_t start, vm_size_t end);
-#endif
-
-#if defined(CPU_ARM9) || defined(CPU_ARM9E)
-void arm9_setttb (u_int);
+#if defined(CPU_ARM9E)
void arm9_tlb_flushID_SE (u_int va);
void arm9_context_switch (void);
-#endif
-
-#if defined(CPU_ARM9)
-void arm9_icache_sync_range (vm_offset_t, vm_size_t);
-
-void arm9_dcache_wbinv_all (void);
-void arm9_dcache_wbinv_range (vm_offset_t, vm_size_t);
-void arm9_dcache_inv_range (vm_offset_t, vm_size_t);
-void arm9_dcache_wb_range (vm_offset_t, vm_size_t);
-
-void arm9_idcache_wbinv_all (void);
-void arm9_idcache_wbinv_range (vm_offset_t, vm_size_t);
-
-void arm9_setup (void);
-
-extern unsigned arm9_dcache_sets_max;
-extern unsigned arm9_dcache_sets_inc;
-extern unsigned arm9_dcache_index_max;
-extern unsigned arm9_dcache_index_inc;
-#endif
-
-#if defined(CPU_ARM9E)
-void arm10_setup (void);
u_int sheeva_control_ext (u_int, u_int);
void sheeva_cpu_sleep (int);
@@ -276,26 +230,14 @@ void sheeva_l2cache_wb_range (vm_offset_t, vm_size_t);
void sheeva_l2cache_wbinv_all (void);
#endif
-#if defined(CPU_MV_PJ4B)
-void armv6_idcache_wbinv_all (void);
-#endif
#if defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT)
-void armv7_idcache_wbinv_all (void);
void armv7_cpu_sleep (int);
-void armv7_setup (void);
-void armv7_drain_writebuf (void);
-
-void cortexa_setup (void);
#endif
#if defined(CPU_MV_PJ4B)
void pj4b_config (void);
-void pj4bv7_setup (void);
#endif
#if defined(CPU_ARM1176)
-void arm11_drain_writebuf (void);
-
-void arm11x6_setup (void);
void arm11x6_sleep (int); /* no ref. for errata */
#endif
@@ -311,12 +253,6 @@ void armv5_ec_dcache_wb_range(vm_offset_t, vm_size_t);
void armv5_ec_idcache_wbinv_all(void);
void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t);
-#endif
-
-#if defined(CPU_ARM9) || defined(CPU_ARM9E) || \
- defined(CPU_FA526) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_81342)
void armv4_tlb_flushID (void);
void armv4_tlb_flushD (void);
@@ -326,72 +262,6 @@ void armv4_drain_writebuf (void);
void armv4_idcache_inv_all (void);
#endif
-#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_81342)
-void xscale_cpwait (void);
-
-void xscale_cpu_sleep (int mode);
-
-u_int xscale_control (u_int clear, u_int bic);
-
-void xscale_setttb (u_int ttb);
-
-void xscale_tlb_flushID_SE (u_int va);
-
-void xscale_cache_flushID (void);
-void xscale_cache_flushI (void);
-void xscale_cache_flushD (void);
-void xscale_cache_flushD_SE (u_int entry);
-
-void xscale_cache_cleanID (void);
-void xscale_cache_cleanD (void);
-void xscale_cache_cleanD_E (u_int entry);
-
-void xscale_cache_clean_minidata (void);
-
-void xscale_cache_purgeID (void);
-void xscale_cache_purgeID_E (u_int entry);
-void xscale_cache_purgeD (void);
-void xscale_cache_purgeD_E (u_int entry);
-
-void xscale_cache_syncI (void);
-void xscale_cache_cleanID_rng (vm_offset_t start, vm_size_t end);
-void xscale_cache_cleanD_rng (vm_offset_t start, vm_size_t end);
-void xscale_cache_purgeID_rng (vm_offset_t start, vm_size_t end);
-void xscale_cache_purgeD_rng (vm_offset_t start, vm_size_t end);
-void xscale_cache_syncI_rng (vm_offset_t start, vm_size_t end);
-void xscale_cache_flushD_rng (vm_offset_t start, vm_size_t end);
-
-void xscale_context_switch (void);
-
-void xscale_setup (void);
-#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
-
-#ifdef CPU_XSCALE_81342
-
-void xscalec3_l2cache_purge (void);
-void xscalec3_cache_purgeID (void);
-void xscalec3_cache_purgeD (void);
-void xscalec3_cache_cleanID (void);
-void xscalec3_cache_cleanD (void);
-void xscalec3_cache_syncI (void);
-
-void xscalec3_cache_purgeID_rng (vm_offset_t start, vm_size_t end);
-void xscalec3_cache_purgeD_rng (vm_offset_t start, vm_size_t end);
-void xscalec3_cache_cleanID_rng (vm_offset_t start, vm_size_t end);
-void xscalec3_cache_cleanD_rng (vm_offset_t start, vm_size_t end);
-void xscalec3_cache_syncI_rng (vm_offset_t start, vm_size_t end);
-
-void xscalec3_l2cache_flush_rng (vm_offset_t, vm_size_t);
-void xscalec3_l2cache_clean_rng (vm_offset_t start, vm_size_t end);
-void xscalec3_l2cache_purge_rng (vm_offset_t start, vm_size_t end);
-
-
-void xscalec3_setttb (u_int ttb);
-void xscalec3_context_switch (void);
-
-#endif /* CPU_XSCALE_81342 */
-
/*
* Macros for manipulating CPU interrupts
*/
@@ -462,12 +332,6 @@ void set_stackptr (u_int mode, u_int address);
u_int get_stackptr (u_int mode);
/*
- * Miscellany
- */
-
-int get_pc_str_offset (void);
-
-/*
* CPU functions from locore.S
*/
@@ -496,8 +360,21 @@ extern u_int arm_cache_level;
extern u_int arm_cache_loc;
extern u_int arm_cache_type[14];
-#endif /* __rtems__ */
+#else /* !_KERNEL */
+
+static __inline void
+breakpoint(void)
+{
+
+ /*
+ * This matches the instruction used by GDB for software
+ * breakpoints.
+ */
+ __asm("udf 0xfdee");
+}
+
#endif /* _KERNEL */
+#endif /* __rtems__ */
#endif /* _MACHINE_CPUFUNC_H_ */
/* End of cpufunc.h */
diff --git a/freebsd/sys/cam/cam_ccb.h b/freebsd/sys/cam/cam_ccb.h
index 642e7862..9119468d 100644
--- a/freebsd/sys/cam/cam_ccb.h
+++ b/freebsd/sys/cam/cam_ccb.h
@@ -1372,48 +1372,6 @@ cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
u_int32_t flags, u_int8_t tag_action,
u_int8_t *data_ptr, u_int32_t dxfer_len,
u_int8_t sense_len, u_int8_t cdb_len,
- u_int32_t timeout);
-
-static __inline void
-cam_fill_nvmeio(struct ccb_nvmeio *nvmeio, u_int32_t retries,
- void (*cbfcnp)(struct cam_periph *, union ccb *),
- u_int32_t flags, u_int8_t *data_ptr, u_int32_t dxfer_len,
- u_int32_t timeout);
-
-static __inline void
-cam_fill_ctio(struct ccb_scsiio *csio, u_int32_t retries,
- void (*cbfcnp)(struct cam_periph *, union ccb *),
- u_int32_t flags, u_int tag_action, u_int tag_id,
- u_int init_id, u_int scsi_status, u_int8_t *data_ptr,
- u_int32_t dxfer_len, u_int32_t timeout);
-
-static __inline void
-cam_fill_ataio(struct ccb_ataio *ataio, u_int32_t retries,
- void (*cbfcnp)(struct cam_periph *, union ccb *),
- u_int32_t flags, u_int tag_action,
- u_int8_t *data_ptr, u_int32_t dxfer_len,
- u_int32_t timeout);
-
-static __inline void
-cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retries,
- void (*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags,
- uint8_t *smp_request, int smp_request_len,
- uint8_t *smp_response, int smp_response_len,
- uint32_t timeout);
-
-static __inline void
-cam_fill_mmcio(struct ccb_mmcio *mmcio, uint32_t retries,
- void (*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags,
- uint32_t mmc_opcode, uint32_t mmc_arg, uint32_t mmc_flags,
- struct mmc_data *mmc_d,
- uint32_t timeout);
-
-static __inline void
-cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
- void (*cbfcnp)(struct cam_periph *, union ccb *),
- u_int32_t flags, u_int8_t tag_action,
- u_int8_t *data_ptr, u_int32_t dxfer_len,
- u_int8_t sense_len, u_int8_t cdb_len,
u_int32_t timeout)
{
csio->ccb_h.func_code = XPT_SCSI_IO;
diff --git a/freebsd/sys/cam/cam_xpt.h b/freebsd/sys/cam/cam_xpt.h
index fb49c893..52af71fc 100644
--- a/freebsd/sys/cam/cam_xpt.h
+++ b/freebsd/sys/cam/cam_xpt.h
@@ -148,6 +148,7 @@ void xpt_release_path(struct cam_path *path);
const char * xpt_action_name(uint32_t action);
void xpt_pollwait(union ccb *start_ccb, uint32_t timeout);
uint32_t xpt_poll_setup(union ccb *start_ccb);
+void xpt_sim_poll(struct cam_sim *sim);
/*
* Perform a path inquiry at the request priority. The bzero may be
diff --git a/freebsd/sys/cam/mmc/mmc.h b/freebsd/sys/cam/mmc/mmc.h
index 9b9659fe..44c4aad0 100644
--- a/freebsd/sys/cam/mmc/mmc.h
+++ b/freebsd/sys/cam/mmc/mmc.h
@@ -94,4 +94,12 @@ struct mmc_params {
uint8_t sdio_func_count;
} __packed;
+/*
+ * Only one MMC card on bus is supported now.
+ * If we ever want to support multiple MMC cards on the same bus,
+ * mmc_xpt needs to be extended to issue new RCAs based on number
+ * of already probed cards. Furthermore, retuning and high-speed
+ * settings should also take all cards into account.
+ */
+#define MMC_PROPOSED_RCA 2
#endif
diff --git a/freebsd/sys/contrib/ck/include/ck_pr.h b/freebsd/sys/contrib/ck/include/ck_pr.h
index 7fa57a8e..2a8c5398 100644
--- a/freebsd/sys/contrib/ck/include/ck_pr.h
+++ b/freebsd/sys/contrib/ck/include/ck_pr.h
@@ -619,8 +619,8 @@ CK_PR_BTX_S(bts, 16, uint16_t, |,)
}
#define CK_PR_UNARY_Z(K, S, M, T, P, C, Z) \
- CK_CC_INLINE static void \
- ck_pr_##K##_##S##_zero(M *target, bool *zero) \
+ CK_CC_INLINE static bool \
+ ck_pr_##K##_##S##_is_zero(M *target) \
{ \
T previous; \
C punt; \
@@ -631,12 +631,21 @@ CK_PR_BTX_S(bts, 16, uint16_t, |,)
(C)(previous P 1), \
&previous) == false) \
ck_pr_stall(); \
- *zero = previous == (T)Z; \
+ return previous == (T)Z; \
+ }
+
+#define CK_PR_UNARY_Z_STUB(K, S, M) \
+ CK_CC_INLINE static void \
+ ck_pr_##K##_##S##_zero(M *target, bool *zero) \
+ { \
+ *zero = ck_pr_##K##_##S##_is_zero(target); \
return; \
}
#define CK_PR_UNARY_S(K, X, S, M) CK_PR_UNARY(K, X, S, M, M)
-#define CK_PR_UNARY_Z_S(K, S, M, P, Z) CK_PR_UNARY_Z(K, S, M, M, P, M, Z)
+#define CK_PR_UNARY_Z_S(K, S, M, P, Z) \
+ CK_PR_UNARY_Z(K, S, M, M, P, M, Z) \
+ CK_PR_UNARY_Z_STUB(K, S, M)
#if defined(CK_F_PR_LOAD_CHAR) && defined(CK_F_PR_CAS_CHAR_VALUE)
@@ -648,6 +657,8 @@ CK_PR_UNARY_S(inc, add, char, char)
#ifndef CK_F_PR_INC_CHAR_ZERO
#define CK_F_PR_INC_CHAR_ZERO
CK_PR_UNARY_Z_S(inc, char, char, +, -1)
+#else
+CK_PR_UNARY_Z_STUB(inc, char, char)
#endif /* CK_F_PR_INC_CHAR_ZERO */
#ifndef CK_F_PR_DEC_CHAR
@@ -658,6 +669,8 @@ CK_PR_UNARY_S(dec, sub, char, char)
#ifndef CK_F_PR_DEC_CHAR_ZERO
#define CK_F_PR_DEC_CHAR_ZERO
CK_PR_UNARY_Z_S(dec, char, char, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, char, char)
#endif /* CK_F_PR_DEC_CHAR_ZERO */
#endif /* CK_F_PR_LOAD_CHAR && CK_F_PR_CAS_CHAR_VALUE */
@@ -672,6 +685,8 @@ CK_PR_UNARY_S(inc, add, int, int)
#ifndef CK_F_PR_INC_INT_ZERO
#define CK_F_PR_INC_INT_ZERO
CK_PR_UNARY_Z_S(inc, int, int, +, -1)
+#else
+CK_PR_UNARY_Z_STUB(inc, int, int)
#endif /* CK_F_PR_INC_INT_ZERO */
#ifndef CK_F_PR_DEC_INT
@@ -682,6 +697,8 @@ CK_PR_UNARY_S(dec, sub, int, int)
#ifndef CK_F_PR_DEC_INT_ZERO
#define CK_F_PR_DEC_INT_ZERO
CK_PR_UNARY_Z_S(dec, int, int, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, int, int)
#endif /* CK_F_PR_DEC_INT_ZERO */
#endif /* CK_F_PR_LOAD_INT && CK_F_PR_CAS_INT_VALUE */
@@ -711,6 +728,8 @@ CK_PR_UNARY_S(inc, add, uint, unsigned int)
#ifndef CK_F_PR_INC_UINT_ZERO
#define CK_F_PR_INC_UINT_ZERO
CK_PR_UNARY_Z_S(inc, uint, unsigned int, +, UINT_MAX)
+#else
+CK_PR_UNARY_Z_STUB(inc, uint, unsigned int)
#endif /* CK_F_PR_INC_UINT_ZERO */
#ifndef CK_F_PR_DEC_UINT
@@ -721,6 +740,8 @@ CK_PR_UNARY_S(dec, sub, uint, unsigned int)
#ifndef CK_F_PR_DEC_UINT_ZERO
#define CK_F_PR_DEC_UINT_ZERO
CK_PR_UNARY_Z_S(dec, uint, unsigned int, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, uint, unsigned int)
#endif /* CK_F_PR_DEC_UINT_ZERO */
#endif /* CK_F_PR_LOAD_UINT && CK_F_PR_CAS_UINT_VALUE */
@@ -735,6 +756,8 @@ CK_PR_UNARY(inc, add, ptr, void, uintptr_t)
#ifndef CK_F_PR_INC_PTR_ZERO
#define CK_F_PR_INC_PTR_ZERO
CK_PR_UNARY_Z(inc, ptr, void, uintptr_t, +, void *, UINT_MAX)
+#else
+CK_PR_UNARY_Z_STUB(inc, ptr, void)
#endif /* CK_F_PR_INC_PTR_ZERO */
#ifndef CK_F_PR_DEC_PTR
@@ -745,6 +768,8 @@ CK_PR_UNARY(dec, sub, ptr, void, uintptr_t)
#ifndef CK_F_PR_DEC_PTR_ZERO
#define CK_F_PR_DEC_PTR_ZERO
CK_PR_UNARY_Z(dec, ptr, void, uintptr_t, -, void *, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, ptr, void)
#endif /* CK_F_PR_DEC_PTR_ZERO */
#endif /* CK_F_PR_LOAD_PTR && CK_F_PR_CAS_PTR_VALUE */
@@ -759,6 +784,8 @@ CK_PR_UNARY_S(inc, add, 64, uint64_t)
#ifndef CK_F_PR_INC_64_ZERO
#define CK_F_PR_INC_64_ZERO
CK_PR_UNARY_Z_S(inc, 64, uint64_t, +, UINT64_MAX)
+#else
+CK_PR_UNARY_Z_STUB(inc, 64, uint64_t)
#endif /* CK_F_PR_INC_64_ZERO */
#ifndef CK_F_PR_DEC_64
@@ -769,6 +796,8 @@ CK_PR_UNARY_S(dec, sub, 64, uint64_t)
#ifndef CK_F_PR_DEC_64_ZERO
#define CK_F_PR_DEC_64_ZERO
CK_PR_UNARY_Z_S(dec, 64, uint64_t, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, 64, uint64_t)
#endif /* CK_F_PR_DEC_64_ZERO */
#endif /* CK_F_PR_LOAD_64 && CK_F_PR_CAS_64_VALUE */
@@ -783,6 +812,8 @@ CK_PR_UNARY_S(inc, add, 32, uint32_t)
#ifndef CK_F_PR_INC_32_ZERO
#define CK_F_PR_INC_32_ZERO
CK_PR_UNARY_Z_S(inc, 32, uint32_t, +, UINT32_MAX)
+#else
+CK_PR_UNARY_Z_STUB(inc, 32, uint32_t)
#endif /* CK_F_PR_INC_32_ZERO */
#ifndef CK_F_PR_DEC_32
@@ -793,6 +824,8 @@ CK_PR_UNARY_S(dec, sub, 32, uint32_t)
#ifndef CK_F_PR_DEC_32_ZERO
#define CK_F_PR_DEC_32_ZERO
CK_PR_UNARY_Z_S(dec, 32, uint32_t, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, 32, uint32_t)
#endif /* CK_F_PR_DEC_32_ZERO */
#endif /* CK_F_PR_LOAD_32 && CK_F_PR_CAS_32_VALUE */
@@ -807,6 +840,8 @@ CK_PR_UNARY_S(inc, add, 16, uint16_t)
#ifndef CK_F_PR_INC_16_ZERO
#define CK_F_PR_INC_16_ZERO
CK_PR_UNARY_Z_S(inc, 16, uint16_t, +, UINT16_MAX)
+#else
+CK_PR_UNARY_Z_STUB(inc, 16, uint16_t)
#endif /* CK_F_PR_INC_16_ZERO */
#ifndef CK_F_PR_DEC_16
@@ -817,6 +852,8 @@ CK_PR_UNARY_S(dec, sub, 16, uint16_t)
#ifndef CK_F_PR_DEC_16_ZERO
#define CK_F_PR_DEC_16_ZERO
CK_PR_UNARY_Z_S(dec, 16, uint16_t, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, 16, uint16_t)
#endif /* CK_F_PR_DEC_16_ZERO */
#endif /* CK_F_PR_LOAD_16 && CK_F_PR_CAS_16_VALUE */
@@ -831,6 +868,8 @@ CK_PR_UNARY_S(inc, add, 8, uint8_t)
#ifndef CK_F_PR_INC_8_ZERO
#define CK_F_PR_INC_8_ZERO
CK_PR_UNARY_Z_S(inc, 8, uint8_t, +, UINT8_MAX)
+#else
+CK_PR_UNARY_Z_STUB(inc, 8, uint8_t)
#endif /* CK_F_PR_INC_8_ZERO */
#ifndef CK_F_PR_DEC_8
@@ -841,6 +880,8 @@ CK_PR_UNARY_S(dec, sub, 8, uint8_t)
#ifndef CK_F_PR_DEC_8_ZERO
#define CK_F_PR_DEC_8_ZERO
CK_PR_UNARY_Z_S(dec, 8, uint8_t, -, 1)
+#else
+CK_PR_UNARY_Z_STUB(dec, 8, uint8_t)
#endif /* CK_F_PR_DEC_8_ZERO */
#endif /* CK_F_PR_LOAD_8 && CK_F_PR_CAS_8_VALUE */
diff --git a/freebsd/sys/contrib/ck/include/ck_queue.h b/freebsd/sys/contrib/ck/include/ck_queue.h
index faf96a17..3f503aa6 100644
--- a/freebsd/sys/contrib/ck/include/ck_queue.h
+++ b/freebsd/sys/contrib/ck/include/ck_queue.h
@@ -180,8 +180,14 @@ struct { \
ck_pr_store_ptr(&(head)->cslh_first, elm); \
} while (0)
+#define CK_SLIST_INSERT_PREVPTR(prevp, slistelm, elm, field) do { \
+ (elm)->field.csle_next = (slistelm); \
+ ck_pr_fence_store(); \
+ ck_pr_store_ptr(prevp, elm); \
+} while (0)
+
#define CK_SLIST_REMOVE_AFTER(elm, field) do { \
- ck_pr_store_ptr(&(elm)->field.csle_next, \
+ ck_pr_store_ptr(&(elm)->field.csle_next, \
(elm)->field.csle_next->field.csle_next); \
} while (0)
@@ -190,7 +196,7 @@ struct { \
CK_SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->cslh_first; \
- while (curelm->field.csle_next != (elm)) \
+ while (curelm->field.csle_next != (elm)) \
curelm = curelm->field.csle_next; \
CK_SLIST_REMOVE_AFTER(curelm, field); \
} \
@@ -201,6 +207,10 @@ struct { \
(head)->cslh_first->field.csle_next); \
} while (0)
+#define CK_SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \
+ ck_pr_store_ptr(prevptr, (elm)->field.csle_next); \
+} while (0)
+
#define CK_SLIST_MOVE(head1, head2, field) do { \
ck_pr_store_ptr(&(head1)->cslh_first, (head2)->cslh_first); \
} while (0)
diff --git a/freebsd/sys/contrib/ck/include/gcc/ppc/ck_pr.h b/freebsd/sys/contrib/ck/include/gcc/ppc/ck_pr.h
index cd7935dd..73f0cb78 100644
--- a/freebsd/sys/contrib/ck/include/gcc/ppc/ck_pr.h
+++ b/freebsd/sys/contrib/ck/include/gcc/ppc/ck_pr.h
@@ -67,21 +67,29 @@ ck_pr_stall(void)
__asm__ __volatile__(I ::: "memory"); \
}
-CK_PR_FENCE(atomic, "lwsync")
-CK_PR_FENCE(atomic_store, "lwsync")
+#ifdef CK_MD_PPC32_LWSYNC
+#define CK_PR_LWSYNCOP "lwsync"
+#else /* CK_MD_PPC32_LWSYNC_DISABLE */
+#define CK_PR_LWSYNCOP "sync"
+#endif
+
+CK_PR_FENCE(atomic, CK_PR_LWSYNCOP)
+CK_PR_FENCE(atomic_store, CK_PR_LWSYNCOP)
CK_PR_FENCE(atomic_load, "sync")
-CK_PR_FENCE(store_atomic, "lwsync")
-CK_PR_FENCE(load_atomic, "lwsync")
-CK_PR_FENCE(store, "lwsync")
+CK_PR_FENCE(store_atomic, CK_PR_LWSYNCOP)
+CK_PR_FENCE(load_atomic, CK_PR_LWSYNCOP)
+CK_PR_FENCE(store, CK_PR_LWSYNCOP)
CK_PR_FENCE(store_load, "sync")
-CK_PR_FENCE(load, "lwsync")
-CK_PR_FENCE(load_store, "lwsync")
+CK_PR_FENCE(load, CK_PR_LWSYNCOP)
+CK_PR_FENCE(load_store, CK_PR_LWSYNCOP)
CK_PR_FENCE(memory, "sync")
-CK_PR_FENCE(acquire, "lwsync")
-CK_PR_FENCE(release, "lwsync")
-CK_PR_FENCE(acqrel, "lwsync")
-CK_PR_FENCE(lock, "lwsync")
-CK_PR_FENCE(unlock, "lwsync")
+CK_PR_FENCE(acquire, CK_PR_LWSYNCOP)
+CK_PR_FENCE(release, CK_PR_LWSYNCOP)
+CK_PR_FENCE(acqrel, CK_PR_LWSYNCOP)
+CK_PR_FENCE(lock, CK_PR_LWSYNCOP)
+CK_PR_FENCE(unlock, CK_PR_LWSYNCOP)
+
+#undef CK_PR_LWSYNCOP
#undef CK_PR_FENCE
diff --git a/freebsd/sys/contrib/ck/include/gcc/x86/ck_pr.h b/freebsd/sys/contrib/ck/include/gcc/x86/ck_pr.h
index 3e36376f..e678e830 100644
--- a/freebsd/sys/contrib/ck/include/gcc/x86/ck_pr.h
+++ b/freebsd/sys/contrib/ck/include/gcc/x86/ck_pr.h
@@ -233,18 +233,18 @@ CK_PR_FAA_S(8, uint8_t, "xaddb")
}
#define CK_PR_UNARY_V(K, S, T, C, I) \
- CK_CC_INLINE static void \
- ck_pr_##K##_##S##_zero(T *target, bool *r) \
+ CK_CC_INLINE static bool \
+ ck_pr_##K##_##S##_is_zero(T *target) \
{ \
+ bool ret; \
__asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
: "+m" (*(C *)target), \
- "=m" (*r) \
+ "=rm" (ret) \
: \
: "memory", "cc"); \
- return; \
+ return ret; \
}
-
#define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I)
#define CK_PR_GENERATE(K) \
diff --git a/freebsd/sys/contrib/ck/include/gcc/x86_64/ck_pr.h b/freebsd/sys/contrib/ck/include/gcc/x86_64/ck_pr.h
index 4de13329..fb2804e8 100644
--- a/freebsd/sys/contrib/ck/include/gcc/x86_64/ck_pr.h
+++ b/freebsd/sys/contrib/ck/include/gcc/x86_64/ck_pr.h
@@ -332,18 +332,18 @@ CK_PR_FAA_S(8, uint8_t, "xaddb")
}
#define CK_PR_UNARY_V(K, S, T, C, I) \
- CK_CC_INLINE static void \
- ck_pr_##K##_##S##_zero(T *target, bool *r) \
+ CK_CC_INLINE static bool \
+ ck_pr_##K##_##S##_is_zero(T *target) \
{ \
+ bool ret; \
__asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
: "+m" (*(C *)target), \
- "=m" (*r) \
+ "=rm" (ret) \
: \
: "memory", "cc"); \
- return; \
+ return ret; \
}
-
#define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I)
#define CK_PR_GENERATE(K) \
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c
new file mode 100644
index 00000000..f7b0c244
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c
@@ -0,0 +1,126 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+
+#include "poly1305_donna.h"
+#include "crypto_verify_16.h"
+#include "private/common.h"
+#include "utils.h"
+
+#ifdef HAVE_TI_MODE
+#include "poly1305_donna64.h"
+#else
+#include "poly1305_donna32.h"
+#endif
+#include "../onetimeauth_poly1305.h"
+
+static void
+poly1305_update(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ unsigned long long i;
+
+ /* handle leftover */
+ if (st->leftover) {
+ unsigned long long want = (poly1305_block_size - st->leftover);
+
+ if (want > bytes) {
+ want = bytes;
+ }
+ for (i = 0; i < want; i++) {
+ st->buffer[st->leftover + i] = m[i];
+ }
+ bytes -= want;
+ m += want;
+ st->leftover += want;
+ if (st->leftover < poly1305_block_size) {
+ return;
+ }
+ poly1305_blocks(st, st->buffer, poly1305_block_size);
+ st->leftover = 0;
+ }
+
+ /* process full blocks */
+ if (bytes >= poly1305_block_size) {
+ unsigned long long want = (bytes & ~(poly1305_block_size - 1));
+
+ poly1305_blocks(st, m, want);
+ m += want;
+ bytes -= want;
+ }
+
+ /* store leftover */
+ if (bytes) {
+ for (i = 0; i < bytes; i++) {
+ st->buffer[st->leftover + i] = m[i];
+ }
+ st->leftover += bytes;
+ }
+}
+
+static int
+crypto_onetimeauth_poly1305_donna(unsigned char *out, const unsigned char *m,
+ unsigned long long inlen,
+ const unsigned char *key)
+{
+ CRYPTO_ALIGN(64) poly1305_state_internal_t state;
+
+ poly1305_init(&state, key);
+ poly1305_update(&state, m, inlen);
+ poly1305_finish(&state, out);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key)
+{
+ COMPILER_ASSERT(sizeof(crypto_onetimeauth_poly1305_state) >=
+ sizeof(poly1305_state_internal_t));
+ poly1305_init((poly1305_state_internal_t *) (void *) state, key);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_update(
+ crypto_onetimeauth_poly1305_state *state, const unsigned char *in,
+ unsigned long long inlen)
+{
+ poly1305_update((poly1305_state_internal_t *) (void *) state, in, inlen);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_final(
+ crypto_onetimeauth_poly1305_state *state, unsigned char *out)
+{
+ poly1305_finish((poly1305_state_internal_t *) (void *) state, out);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+{
+ unsigned char correct[16];
+
+ crypto_onetimeauth_poly1305_donna(correct, in, inlen, k);
+
+ return crypto_verify_16(h, correct);
+}
+
+struct crypto_onetimeauth_poly1305_implementation
+ crypto_onetimeauth_poly1305_donna_implementation = {
+ SODIUM_C99(.onetimeauth =) crypto_onetimeauth_poly1305_donna,
+ SODIUM_C99(.onetimeauth_verify =)
+ crypto_onetimeauth_poly1305_donna_verify,
+ SODIUM_C99(.onetimeauth_init =) crypto_onetimeauth_poly1305_donna_init,
+ SODIUM_C99(.onetimeauth_update =)
+ crypto_onetimeauth_poly1305_donna_update,
+ SODIUM_C99(.onetimeauth_final =) crypto_onetimeauth_poly1305_donna_final
+ };
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h
new file mode 100644
index 00000000..d6474b3a
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h
@@ -0,0 +1,12 @@
+#ifndef poly1305_donna_H
+#define poly1305_donna_H
+
+#include <stddef.h>
+
+#include "../onetimeauth_poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+
+extern struct crypto_onetimeauth_poly1305_implementation
+ crypto_onetimeauth_poly1305_donna_implementation;
+
+#endif /* poly1305_donna_H */
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h
new file mode 100644
index 00000000..cef64480
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h
@@ -0,0 +1,235 @@
+/*
+ poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication
+ and 64 bit addition
+*/
+
+#if defined(_MSC_VER)
+# define POLY1305_NOINLINE __declspec(noinline)
+#elif defined(__clang__) || defined(__GNUC__)
+# define POLY1305_NOINLINE __attribute__((noinline))
+#else
+# define POLY1305_NOINLINE
+#endif
+
+#include "private/common.h"
+
+#define poly1305_block_size 16
+
+/* 17 + sizeof(unsigned long long) + 14*sizeof(unsigned long) */
+typedef struct poly1305_state_internal_t {
+ unsigned long r[5];
+ unsigned long h[5];
+ unsigned long pad[4];
+ unsigned long long leftover;
+ unsigned char buffer[poly1305_block_size];
+ unsigned char final;
+} poly1305_state_internal_t;
+
+static void
+poly1305_init(poly1305_state_internal_t *st, const unsigned char key[32])
+{
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff - wiped after finalization */
+ st->r[0] = (LOAD32_LE(&key[0])) & 0x3ffffff;
+ st->r[1] = (LOAD32_LE(&key[3]) >> 2) & 0x3ffff03;
+ st->r[2] = (LOAD32_LE(&key[6]) >> 4) & 0x3ffc0ff;
+ st->r[3] = (LOAD32_LE(&key[9]) >> 6) & 0x3f03fff;
+ st->r[4] = (LOAD32_LE(&key[12]) >> 8) & 0x00fffff;
+
+ /* h = 0 */
+ st->h[0] = 0;
+ st->h[1] = 0;
+ st->h[2] = 0;
+ st->h[3] = 0;
+ st->h[4] = 0;
+
+ /* save pad for later */
+ st->pad[0] = LOAD32_LE(&key[16]);
+ st->pad[1] = LOAD32_LE(&key[20]);
+ st->pad[2] = LOAD32_LE(&key[24]);
+ st->pad[3] = LOAD32_LE(&key[28]);
+
+ st->leftover = 0;
+ st->final = 0;
+}
+
+static void
+poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ const unsigned long hibit = (st->final) ? 0UL : (1UL << 24); /* 1 << 128 */
+ unsigned long r0, r1, r2, r3, r4;
+ unsigned long s1, s2, s3, s4;
+ unsigned long h0, h1, h2, h3, h4;
+ unsigned long long d0, d1, d2, d3, d4;
+ unsigned long c;
+
+ r0 = st->r[0];
+ r1 = st->r[1];
+ r2 = st->r[2];
+ r3 = st->r[3];
+ r4 = st->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+ h3 = st->h[3];
+ h4 = st->h[4];
+
+ while (bytes >= poly1305_block_size) {
+ /* h += m[i] */
+ h0 += (LOAD32_LE(m + 0)) & 0x3ffffff;
+ h1 += (LOAD32_LE(m + 3) >> 2) & 0x3ffffff;
+ h2 += (LOAD32_LE(m + 6) >> 4) & 0x3ffffff;
+ h3 += (LOAD32_LE(m + 9) >> 6) & 0x3ffffff;
+ h4 += (LOAD32_LE(m + 12) >> 8) | hibit;
+
+ /* h *= r */
+ d0 = ((unsigned long long) h0 * r0) + ((unsigned long long) h1 * s4) +
+ ((unsigned long long) h2 * s3) + ((unsigned long long) h3 * s2) +
+ ((unsigned long long) h4 * s1);
+ d1 = ((unsigned long long) h0 * r1) + ((unsigned long long) h1 * r0) +
+ ((unsigned long long) h2 * s4) + ((unsigned long long) h3 * s3) +
+ ((unsigned long long) h4 * s2);
+ d2 = ((unsigned long long) h0 * r2) + ((unsigned long long) h1 * r1) +
+ ((unsigned long long) h2 * r0) + ((unsigned long long) h3 * s4) +
+ ((unsigned long long) h4 * s3);
+ d3 = ((unsigned long long) h0 * r3) + ((unsigned long long) h1 * r2) +
+ ((unsigned long long) h2 * r1) + ((unsigned long long) h3 * r0) +
+ ((unsigned long long) h4 * s4);
+ d4 = ((unsigned long long) h0 * r4) + ((unsigned long long) h1 * r3) +
+ ((unsigned long long) h2 * r2) + ((unsigned long long) h3 * r1) +
+ ((unsigned long long) h4 * r0);
+
+ /* (partial) h %= p */
+ c = (unsigned long) (d0 >> 26);
+ h0 = (unsigned long) d0 & 0x3ffffff;
+ d1 += c;
+ c = (unsigned long) (d1 >> 26);
+ h1 = (unsigned long) d1 & 0x3ffffff;
+ d2 += c;
+ c = (unsigned long) (d2 >> 26);
+ h2 = (unsigned long) d2 & 0x3ffffff;
+ d3 += c;
+ c = (unsigned long) (d3 >> 26);
+ h3 = (unsigned long) d3 & 0x3ffffff;
+ d4 += c;
+ c = (unsigned long) (d4 >> 26);
+ h4 = (unsigned long) d4 & 0x3ffffff;
+ h0 += c * 5;
+ c = (h0 >> 26);
+ h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ m += poly1305_block_size;
+ bytes -= poly1305_block_size;
+ }
+
+ st->h[0] = h0;
+ st->h[1] = h1;
+ st->h[2] = h2;
+ st->h[3] = h3;
+ st->h[4] = h4;
+}
+
+static POLY1305_NOINLINE void
+poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
+{
+ unsigned long h0, h1, h2, h3, h4, c;
+ unsigned long g0, g1, g2, g3, g4;
+ unsigned long long f;
+ unsigned long mask;
+
+ /* process the remaining block */
+ if (st->leftover) {
+ unsigned long long i = st->leftover;
+
+ st->buffer[i++] = 1;
+ for (; i < poly1305_block_size; i++) {
+ st->buffer[i] = 0;
+ }
+ st->final = 1;
+ poly1305_blocks(st, st->buffer, poly1305_block_size);
+ }
+
+ /* fully carry h */
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+ h3 = st->h[3];
+ h4 = st->h[4];
+
+ c = h1 >> 26;
+ h1 = h1 & 0x3ffffff;
+ h2 += c;
+ c = h2 >> 26;
+ h2 = h2 & 0x3ffffff;
+ h3 += c;
+ c = h3 >> 26;
+ h3 = h3 & 0x3ffffff;
+ h4 += c;
+ c = h4 >> 26;
+ h4 = h4 & 0x3ffffff;
+ h0 += c * 5;
+ c = h0 >> 26;
+ h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ /* compute h + -p */
+ g0 = h0 + 5;
+ c = g0 >> 26;
+ g0 &= 0x3ffffff;
+ g1 = h1 + c;
+ c = g1 >> 26;
+ g1 &= 0x3ffffff;
+ g2 = h2 + c;
+ c = g2 >> 26;
+ g2 &= 0x3ffffff;
+ g3 = h3 + c;
+ c = g3 >> 26;
+ g3 &= 0x3ffffff;
+ g4 = h4 + c - (1UL << 26);
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ h0 = ((h0) | (h1 << 26)) & 0xffffffff;
+ h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
+ h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+ h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
+
+ /* mac = (h + pad) % (2^128) */
+ f = (unsigned long long) h0 + st->pad[0];
+ h0 = (unsigned long) f;
+ f = (unsigned long long) h1 + st->pad[1] + (f >> 32);
+ h1 = (unsigned long) f;
+ f = (unsigned long long) h2 + st->pad[2] + (f >> 32);
+ h2 = (unsigned long) f;
+ f = (unsigned long long) h3 + st->pad[3] + (f >> 32);
+ h3 = (unsigned long) f;
+
+ STORE32_LE(mac + 0, (uint32_t) h0);
+ STORE32_LE(mac + 4, (uint32_t) h1);
+ STORE32_LE(mac + 8, (uint32_t) h2);
+ STORE32_LE(mac + 12, (uint32_t) h3);
+
+ /* zero out the state */
+ sodium_memzero((void *) st, sizeof *st);
+}
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c
new file mode 100644
index 00000000..2aed7762
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c
@@ -0,0 +1,92 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+
+#include "onetimeauth_poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "private/common.h"
+#include "private/implementations.h"
+#include "randombytes.h"
+#include "runtime.h"
+
+#include "donna/poly1305_donna.h"
+#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
+# include "sse2/poly1305_sse2.h"
+#endif
+
+static const crypto_onetimeauth_poly1305_implementation *implementation =
+ &crypto_onetimeauth_poly1305_donna_implementation;
+
+int
+crypto_onetimeauth_poly1305(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ return implementation->onetimeauth(out, in, inlen, k);
+}
+
+int
+crypto_onetimeauth_poly1305_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+{
+ return implementation->onetimeauth_verify(h, in, inlen, k);
+}
+
+int
+crypto_onetimeauth_poly1305_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key)
+{
+ return implementation->onetimeauth_init(state, key);
+}
+
+int
+crypto_onetimeauth_poly1305_update(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *in,
+ unsigned long long inlen)
+{
+ return implementation->onetimeauth_update(state, in, inlen);
+}
+
+int
+crypto_onetimeauth_poly1305_final(crypto_onetimeauth_poly1305_state *state,
+ unsigned char *out)
+{
+ return implementation->onetimeauth_final(state, out);
+}
+
+size_t
+crypto_onetimeauth_poly1305_bytes(void)
+{
+ return crypto_onetimeauth_poly1305_BYTES;
+}
+
+size_t
+crypto_onetimeauth_poly1305_keybytes(void)
+{
+ return crypto_onetimeauth_poly1305_KEYBYTES;
+}
+
+size_t
+crypto_onetimeauth_poly1305_statebytes(void)
+{
+ return sizeof(crypto_onetimeauth_poly1305_state);
+}
+
+void
+crypto_onetimeauth_poly1305_keygen(
+ unsigned char k[crypto_onetimeauth_poly1305_KEYBYTES])
+{
+ randombytes_buf(k, crypto_onetimeauth_poly1305_KEYBYTES);
+}
+
+int
+_crypto_onetimeauth_poly1305_pick_best_implementation(void)
+{
+ implementation = &crypto_onetimeauth_poly1305_donna_implementation;
+#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
+ if (sodium_runtime_has_sse2()) {
+ implementation = &crypto_onetimeauth_poly1305_sse2_implementation;
+ }
+#endif
+ return 0;
+}
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h
new file mode 100644
index 00000000..243eadd5
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h
@@ -0,0 +1,21 @@
+
+#ifndef onetimeauth_poly1305_H
+#define onetimeauth_poly1305_H
+
+#include "crypto_onetimeauth_poly1305.h"
+
+typedef struct crypto_onetimeauth_poly1305_implementation {
+ int (*onetimeauth)(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+ int (*onetimeauth_verify)(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+ int (*onetimeauth_init)(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char * key);
+ int (*onetimeauth_update)(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char * in,
+ unsigned long long inlen);
+ int (*onetimeauth_final)(crypto_onetimeauth_poly1305_state *state,
+ unsigned char * out);
+} crypto_onetimeauth_poly1305_implementation;
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c
new file mode 100644
index 00000000..64d9d11e
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c
@@ -0,0 +1,100 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "crypto_verify_16.h"
+#include "crypto_verify_32.h"
+#include "crypto_verify_64.h"
+
+size_t
+crypto_verify_16_bytes(void)
+{
+ return crypto_verify_16_BYTES;
+}
+
+size_t
+crypto_verify_32_bytes(void)
+{
+ return crypto_verify_32_BYTES;
+}
+
+size_t
+crypto_verify_64_bytes(void)
+{
+ return crypto_verify_64_BYTES;
+}
+
+#if defined(HAVE_EMMINTRIN_H) && defined(__SSE2__)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# endif
+# include <emmintrin.h>
+
+static inline int
+crypto_verify_n(const unsigned char *x_, const unsigned char *y_,
+ const int n)
+{
+ const __m128i zero = _mm_setzero_si128();
+ volatile __m128i v1, v2, z;
+ volatile int m;
+ int i;
+
+ const volatile __m128i *volatile x =
+ (const volatile __m128i *volatile) (const void *) x_;
+ const volatile __m128i *volatile y =
+ (const volatile __m128i *volatile) (const void *) y_;
+ v1 = _mm_loadu_si128((const __m128i *) &x[0]);
+ v2 = _mm_loadu_si128((const __m128i *) &y[0]);
+ z = _mm_xor_si128(v1, v2);
+ for (i = 1; i < n / 16; i++) {
+ v1 = _mm_loadu_si128((const __m128i *) &x[i]);
+ v2 = _mm_loadu_si128((const __m128i *) &y[i]);
+ z = _mm_or_si128(z, _mm_xor_si128(v1, v2));
+ }
+ m = _mm_movemask_epi8(_mm_cmpeq_epi32(z, zero));
+ v1 = zero; v2 = zero; z = zero;
+
+ return (int) (((uint32_t) m + 1U) >> 16) - 1;
+}
+
+#else
+
+static inline int
+crypto_verify_n(const unsigned char *x_, const unsigned char *y_,
+ const int n)
+{
+ const volatile unsigned char *volatile x =
+ (const volatile unsigned char *volatile) x_;
+ const volatile unsigned char *volatile y =
+ (const volatile unsigned char *volatile) y_;
+ volatile uint_fast16_t d = 0U;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ d |= x[i] ^ y[i];
+ }
+ return (1 & ((d - 1) >> 8)) - 1;
+}
+
+#endif
+
+int
+crypto_verify_16(const unsigned char *x, const unsigned char *y)
+{
+ return crypto_verify_n(x, y, crypto_verify_16_BYTES);
+}
+
+int
+crypto_verify_32(const unsigned char *x, const unsigned char *y)
+{
+ return crypto_verify_n(x, y, crypto_verify_32_BYTES);
+}
+
+int
+crypto_verify_64(const unsigned char *x, const unsigned char *y)
+{
+ return crypto_verify_n(x, y, crypto_verify_64_BYTES);
+}
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h
new file mode 100644
index 00000000..4b89c4f0
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h
@@ -0,0 +1,67 @@
+#ifndef crypto_onetimeauth_poly1305_H
+#define crypto_onetimeauth_poly1305_H
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#include "export.h"
+
+typedef struct CRYPTO_ALIGN(16) crypto_onetimeauth_poly1305_state {
+ unsigned char opaque[256];
+} crypto_onetimeauth_poly1305_state;
+
+SODIUM_EXPORT
+size_t crypto_onetimeauth_poly1305_statebytes(void);
+
+#define crypto_onetimeauth_poly1305_BYTES 16U
+SODIUM_EXPORT
+size_t crypto_onetimeauth_poly1305_bytes(void);
+
+#define crypto_onetimeauth_poly1305_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_onetimeauth_poly1305_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305(unsigned char *out,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_update(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_final(crypto_onetimeauth_poly1305_state *state,
+ unsigned char *out);
+
+SODIUM_EXPORT
+void crypto_onetimeauth_poly1305_keygen(unsigned char k[crypto_onetimeauth_poly1305_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_16.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_16.h
new file mode 100644
index 00000000..5e9eeabe
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_16.h
@@ -0,0 +1,23 @@
+#ifndef crypto_verify_16_H
+#define crypto_verify_16_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_verify_16_BYTES 16U
+SODIUM_EXPORT
+size_t crypto_verify_16_bytes(void);
+
+SODIUM_EXPORT
+int crypto_verify_16(const unsigned char *x, const unsigned char *y)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_32.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_32.h
new file mode 100644
index 00000000..281b5a1b
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_32.h
@@ -0,0 +1,23 @@
+#ifndef crypto_verify_32_H
+#define crypto_verify_32_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_verify_32_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_verify_32_bytes(void);
+
+SODIUM_EXPORT
+int crypto_verify_32(const unsigned char *x, const unsigned char *y)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_64.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_64.h
new file mode 100644
index 00000000..0dc7c304
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_64.h
@@ -0,0 +1,23 @@
+#ifndef crypto_verify_64_H
+#define crypto_verify_64_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_verify_64_BYTES 64U
+SODIUM_EXPORT
+size_t crypto_verify_64_bytes(void);
+
+SODIUM_EXPORT
+int crypto_verify_64(const unsigned char *x, const unsigned char *y)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/export.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/export.h
new file mode 100644
index 00000000..a0074fc9
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/export.h
@@ -0,0 +1,57 @@
+
+#ifndef sodium_export_H
+#define sodium_export_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <limits.h>
+
+#if !defined(__clang__) && !defined(__GNUC__)
+# ifdef __attribute__
+# undef __attribute__
+# endif
+# define __attribute__(a)
+#endif
+
+#ifdef SODIUM_STATIC
+# define SODIUM_EXPORT
+# define SODIUM_EXPORT_WEAK
+#else
+# if defined(_MSC_VER)
+# ifdef SODIUM_DLL_EXPORT
+# define SODIUM_EXPORT __declspec(dllexport)
+# else
+# define SODIUM_EXPORT __declspec(dllimport)
+# endif
+# else
+# if defined(__SUNPRO_C)
+# ifndef __GNU_C__
+# define SODIUM_EXPORT __attribute__ (visibility(__global))
+# else
+# define SODIUM_EXPORT __attribute__ __global
+# endif
+# elif defined(_MSG_VER)
+# define SODIUM_EXPORT extern __declspec(dllexport)
+# else
+# define SODIUM_EXPORT __attribute__ ((visibility ("default")))
+# endif
+# endif
+# if defined(__ELF__) && !defined(SODIUM_DISABLE_WEAK_FUNCTIONS)
+# define SODIUM_EXPORT_WEAK SODIUM_EXPORT __attribute__((weak))
+# else
+# define SODIUM_EXPORT_WEAK SODIUM_EXPORT
+# endif
+#endif
+
+#ifndef CRYPTO_ALIGN
+# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+# define CRYPTO_ALIGN(x) __declspec(align(x))
+# else
+# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x)))
+# endif
+#endif
+
+#define SODIUM_MIN(A, B) ((A) < (B) ? (A) : (B))
+#define SODIUM_SIZE_MAX SODIUM_MIN(UINT64_MAX, SIZE_MAX)
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/common.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/common.h
new file mode 100644
index 00000000..632fc8a7
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/common.h
@@ -0,0 +1,246 @@
+#ifndef common_H
+#define common_H 1
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
+
+#ifdef HAVE_TI_MODE
+# if defined(__SIZEOF_INT128__)
+typedef unsigned __int128 uint128_t;
+# else
+typedef unsigned uint128_t __attribute__((mode(TI)));
+# endif
+#endif
+
+#define ROTL32(X, B) rotl32((X), (B))
+static inline uint32_t
+rotl32(const uint32_t x, const int b)
+{
+ return (x << b) | (x >> (32 - b));
+}
+
+#define ROTL64(X, B) rotl64((X), (B))
+static inline uint64_t
+rotl64(const uint64_t x, const int b)
+{
+ return (x << b) | (x >> (64 - b));
+}
+
+#define ROTR32(X, B) rotr32((X), (B))
+static inline uint32_t
+rotr32(const uint32_t x, const int b)
+{
+ return (x >> b) | (x << (32 - b));
+}
+
+#define ROTR64(X, B) rotr64((X), (B))
+static inline uint64_t
+rotr64(const uint64_t x, const int b)
+{
+ return (x >> b) | (x << (64 - b));
+}
+
+#define LOAD64_LE(SRC) load64_le(SRC)
+static inline uint64_t
+load64_le(const uint8_t src[8])
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint64_t w = (uint64_t) src[0];
+ w |= (uint64_t) src[1] << 8;
+ w |= (uint64_t) src[2] << 16;
+ w |= (uint64_t) src[3] << 24;
+ w |= (uint64_t) src[4] << 32;
+ w |= (uint64_t) src[5] << 40;
+ w |= (uint64_t) src[6] << 48;
+ w |= (uint64_t) src[7] << 56;
+ return w;
+#endif
+}
+
+#define STORE64_LE(DST, W) store64_le((DST), (W))
+static inline void
+store64_le(uint8_t dst[8], uint64_t w)
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[0] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[4] = (uint8_t) w; w >>= 8;
+ dst[5] = (uint8_t) w; w >>= 8;
+ dst[6] = (uint8_t) w; w >>= 8;
+ dst[7] = (uint8_t) w;
+#endif
+}
+
+#define LOAD32_LE(SRC) load32_le(SRC)
+static inline uint32_t
+load32_le(const uint8_t src[4])
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint32_t w = (uint32_t) src[0];
+ w |= (uint32_t) src[1] << 8;
+ w |= (uint32_t) src[2] << 16;
+ w |= (uint32_t) src[3] << 24;
+ return w;
+#endif
+}
+
+#define STORE32_LE(DST, W) store32_le((DST), (W))
+static inline void
+store32_le(uint8_t dst[4], uint32_t w)
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[0] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[3] = (uint8_t) w;
+#endif
+}
+
+/* ----- */
+
+#define LOAD64_BE(SRC) load64_be(SRC)
+static inline uint64_t
+load64_be(const uint8_t src[8])
+{
+#ifdef NATIVE_BIG_ENDIAN
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint64_t w = (uint64_t) src[7];
+ w |= (uint64_t) src[6] << 8;
+ w |= (uint64_t) src[5] << 16;
+ w |= (uint64_t) src[4] << 24;
+ w |= (uint64_t) src[3] << 32;
+ w |= (uint64_t) src[2] << 40;
+ w |= (uint64_t) src[1] << 48;
+ w |= (uint64_t) src[0] << 56;
+ return w;
+#endif
+}
+
+#define STORE64_BE(DST, W) store64_be((DST), (W))
+static inline void
+store64_be(uint8_t dst[8], uint64_t w)
+{
+#ifdef NATIVE_BIG_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[7] = (uint8_t) w; w >>= 8;
+ dst[6] = (uint8_t) w; w >>= 8;
+ dst[5] = (uint8_t) w; w >>= 8;
+ dst[4] = (uint8_t) w; w >>= 8;
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[0] = (uint8_t) w;
+#endif
+}
+
+#define LOAD32_BE(SRC) load32_be(SRC)
+static inline uint32_t
+load32_be(const uint8_t src[4])
+{
+#ifdef NATIVE_BIG_ENDIAN
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint32_t w = (uint32_t) src[3];
+ w |= (uint32_t) src[2] << 8;
+ w |= (uint32_t) src[1] << 16;
+ w |= (uint32_t) src[0] << 24;
+ return w;
+#endif
+}
+
+#define STORE32_BE(DST, W) store32_be((DST), (W))
+static inline void
+store32_be(uint8_t dst[4], uint32_t w)
+{
+#ifdef NATIVE_BIG_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[0] = (uint8_t) w;
+#endif
+}
+
+#define XOR_BUF(OUT, IN, N) xor_buf((OUT), (IN), (N))
+static inline void
+xor_buf(unsigned char *out, const unsigned char *in, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ out[i] ^= in[i];
+ }
+}
+
+#if !defined(__clang__) && !defined(__GNUC__)
+# ifdef __attribute__
+# undef __attribute__
+# endif
+# define __attribute__(a)
+#endif
+
+#ifndef CRYPTO_ALIGN
+# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+# define CRYPTO_ALIGN(x) __declspec(align(x))
+# else
+# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x)))
+# endif
+#endif
+
+#if defined(_MSC_VER) && \
+ (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86))
+
+# include <intrin.h>
+
+# define HAVE_INTRIN_H 1
+# define HAVE_MMINTRIN_H 1
+# define HAVE_EMMINTRIN_H 1
+# define HAVE_PMMINTRIN_H 1
+# define HAVE_TMMINTRIN_H 1
+# define HAVE_SMMINTRIN_H 1
+# define HAVE_AVXINTRIN_H 1
+# if _MSC_VER >= 1600
+# define HAVE_WMMINTRIN_H 1
+# endif
+# if _MSC_VER >= 1700 && defined(_M_X64)
+# define HAVE_AVX2INTRIN_H 1
+# endif
+#elif defined(HAVE_INTRIN_H)
+# include <intrin.h>
+#endif
+
+#ifdef HAVE_LIBCTGRIND
+extern void ct_poison (const void *, size_t);
+extern void ct_unpoison(const void *, size_t);
+# define POISON(X, L) ct_poison((X), (L))
+# define UNPOISON(X, L) ct_unpoison((X), (L))
+#else
+# define POISON(X, L) (void) 0
+# define UNPOISON(X, L) (void) 0
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/implementations.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/implementations.h
new file mode 100644
index 00000000..c7237f85
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/implementations.h
@@ -0,0 +1,11 @@
+#ifndef implementations_H
+#define implementations_H
+
+int _crypto_generichash_blake2b_pick_best_implementation(void);
+int _crypto_onetimeauth_poly1305_pick_best_implementation(void);
+int _crypto_pwhash_argon2_pick_best_implementation(void);
+int _crypto_scalarmult_curve25519_pick_best_implementation(void);
+int _crypto_stream_chacha20_pick_best_implementation(void);
+int _crypto_stream_salsa20_pick_best_implementation(void);
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/randombytes.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/randombytes.h
new file mode 100644
index 00000000..d19f684e
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/randombytes.h
@@ -0,0 +1,68 @@
+
+#ifndef randombytes_H
+#define randombytes_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/types.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef struct randombytes_implementation {
+ const char *(*implementation_name)(void); /* required */
+ uint32_t (*random)(void); /* required */
+ void (*stir)(void); /* optional */
+ uint32_t (*uniform)(const uint32_t upper_bound); /* optional, a default implementation will be used if NULL */
+ void (*buf)(void * const buf, const size_t size); /* required */
+ int (*close)(void); /* optional */
+} randombytes_implementation;
+
+#define randombytes_BYTES_MAX SODIUM_MIN(SODIUM_SIZE_MAX, 0xffffffffUL)
+
+#define randombytes_SEEDBYTES 32U
+SODIUM_EXPORT
+size_t randombytes_seedbytes(void);
+
+SODIUM_EXPORT
+void randombytes_buf(void * const buf, const size_t size);
+
+SODIUM_EXPORT
+void randombytes_buf_deterministic(void * const buf, const size_t size,
+ const unsigned char seed[randombytes_SEEDBYTES]);
+
+SODIUM_EXPORT
+uint32_t randombytes_random(void);
+
+SODIUM_EXPORT
+uint32_t randombytes_uniform(const uint32_t upper_bound);
+
+SODIUM_EXPORT
+void randombytes_stir(void);
+
+SODIUM_EXPORT
+int randombytes_close(void);
+
+SODIUM_EXPORT
+int randombytes_set_implementation(randombytes_implementation *impl);
+
+SODIUM_EXPORT
+const char *randombytes_implementation_name(void);
+
+/* -- NaCl compatibility interface -- */
+
+SODIUM_EXPORT
+void randombytes(unsigned char * const buf, const unsigned long long buf_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/runtime.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/runtime.h
new file mode 100644
index 00000000..7f15d58e
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/runtime.h
@@ -0,0 +1,52 @@
+
+#ifndef sodium_runtime_H
+#define sodium_runtime_H
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_neon(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_sse2(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_sse3(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_ssse3(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_sse41(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_avx(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_avx2(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_avx512f(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_pclmul(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_aesni(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_rdrand(void);
+
+/* ------------------------------------------------------------------------- */
+
+int _sodium_runtime_get_cpu_features(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/utils.h b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/utils.h
new file mode 100644
index 00000000..46eb331c
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/utils.h
@@ -0,0 +1,170 @@
+
+#ifndef sodium_utils_H
+#define sodium_utils_H
+
+#include <stddef.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SODIUM_C99
+# if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+# define SODIUM_C99(X)
+# else
+# define SODIUM_C99(X) X
+# endif
+#endif
+
+SODIUM_EXPORT
+void sodium_memzero(void * const pnt, const size_t len);
+
+SODIUM_EXPORT
+void sodium_stackzero(const size_t len);
+
+/*
+ * WARNING: sodium_memcmp() must be used to verify if two secret keys
+ * are equal, in constant time.
+ * It returns 0 if the keys are equal, and -1 if they differ.
+ * This function is not designed for lexicographical comparisons.
+ */
+SODIUM_EXPORT
+int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len)
+ __attribute__ ((warn_unused_result));
+
+/*
+ * sodium_compare() returns -1 if b1_ < b2_, 1 if b1_ > b2_ and 0 if b1_ == b2_
+ * It is suitable for lexicographical comparisons, or to compare nonces
+ * and counters stored in little-endian format.
+ * However, it is slower than sodium_memcmp().
+ */
+SODIUM_EXPORT
+int sodium_compare(const unsigned char *b1_, const unsigned char *b2_,
+ size_t len)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int sodium_is_zero(const unsigned char *n, const size_t nlen);
+
+SODIUM_EXPORT
+void sodium_increment(unsigned char *n, const size_t nlen);
+
+SODIUM_EXPORT
+void sodium_add(unsigned char *a, const unsigned char *b, const size_t len);
+
+SODIUM_EXPORT
+char *sodium_bin2hex(char * const hex, const size_t hex_maxlen,
+ const unsigned char * const bin, const size_t bin_len);
+
+SODIUM_EXPORT
+int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const hex, const size_t hex_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const hex_end);
+
+#define sodium_base64_VARIANT_ORIGINAL 1
+#define sodium_base64_VARIANT_ORIGINAL_NO_PADDING 3
+#define sodium_base64_VARIANT_URLSAFE 5
+#define sodium_base64_VARIANT_URLSAFE_NO_PADDING 7
+
+/*
+ * Computes the required length to encode BIN_LEN bytes as a base64 string
+ * using the given variant. The computed length includes a trailing \0.
+ */
+#define sodium_base64_ENCODED_LEN(BIN_LEN, VARIANT) \
+ (((BIN_LEN) / 3U) * 4U + \
+ ((((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) | (((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) >> 1)) & 1U) * \
+ (4U - (~((((VARIANT) & 2U) >> 1) - 1U) & (3U - ((BIN_LEN) - ((BIN_LEN) / 3U) * 3U)))) + 1U)
+
+SODIUM_EXPORT
+size_t sodium_base64_encoded_len(const size_t bin_len, const int variant);
+
+SODIUM_EXPORT
+char *sodium_bin2base64(char * const b64, const size_t b64_maxlen,
+ const unsigned char * const bin, const size_t bin_len,
+ const int variant);
+
+SODIUM_EXPORT
+int sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const b64, const size_t b64_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const b64_end, const int variant);
+
+SODIUM_EXPORT
+int sodium_mlock(void * const addr, const size_t len);
+
+SODIUM_EXPORT
+int sodium_munlock(void * const addr, const size_t len);
+
+/* WARNING: sodium_malloc() and sodium_allocarray() are not general-purpose
+ * allocation functions.
+ *
+ * They return a pointer to a region filled with 0xd0 bytes, immediately
+ * followed by a guard page.
+ * As a result, accessing a single byte after the requested allocation size
+ * will intentionally trigger a segmentation fault.
+ *
+ * A canary and an additional guard page placed before the beginning of the
+ * region may also kill the process if a buffer underflow is detected.
+ *
+ * The memory layout is:
+ * [unprotected region size (read only)][guard page (no access)][unprotected pages (read/write)][guard page (no access)]
+ * With the layout of the unprotected pages being:
+ * [optional padding][16-bytes canary][user region]
+ *
+ * However:
+ * - These functions are significantly slower than standard functions
+ * - Each allocation requires 3 or 4 additional pages
+ * - The returned address will not be aligned if the allocation size is not
+ * a multiple of the required alignment. For this reason, these functions
+ * are designed to store data, such as secret keys and messages.
+ *
+ * sodium_malloc() can be used to allocate any libsodium data structure.
+ *
+ * The crypto_generichash_state structure is packed and its length is
+ * either 357 or 361 bytes. For this reason, when using sodium_malloc() to
+ * allocate a crypto_generichash_state structure, padding must be added in
+ * order to ensure proper alignment. crypto_generichash_statebytes()
+ * returns the rounded up structure size, and should be prefered to sizeof():
+ * state = sodium_malloc(crypto_generichash_statebytes());
+ */
+
+SODIUM_EXPORT
+void *sodium_malloc(const size_t size)
+ __attribute__ ((malloc));
+
+SODIUM_EXPORT
+void *sodium_allocarray(size_t count, size_t size)
+ __attribute__ ((malloc));
+
+SODIUM_EXPORT
+void sodium_free(void *ptr);
+
+SODIUM_EXPORT
+int sodium_mprotect_noaccess(void *ptr);
+
+SODIUM_EXPORT
+int sodium_mprotect_readonly(void *ptr);
+
+SODIUM_EXPORT
+int sodium_mprotect_readwrite(void *ptr);
+
+SODIUM_EXPORT
+int sodium_pad(size_t *padded_buflen_p, unsigned char *buf,
+ size_t unpadded_buflen, size_t blocksize, size_t max_buflen);
+
+SODIUM_EXPORT
+int sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf,
+ size_t padded_buflen, size_t blocksize);
+
+/* -------- */
+
+int _sodium_alloc_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/freebsd/sys/crypto/chacha20/chacha.c b/freebsd/sys/crypto/chacha20/chacha.c
index 74d7fe02..3ce5310a 100644
--- a/freebsd/sys/crypto/chacha20/chacha.c
+++ b/freebsd/sys/crypto/chacha20/chacha.c
@@ -16,7 +16,6 @@ __FBSDID("$FreeBSD$");
#include <crypto/chacha20/chacha.h>
-
typedef uint8_t u8;
typedef uint32_t u32;
@@ -59,7 +58,7 @@ typedef struct chacha_ctx chacha_ctx;
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
-void
+LOCAL void
#ifndef __rtems__
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
#else /* __rtems__ */
@@ -88,7 +87,7 @@ chacha_keysetup(chacha_ctx *x,const u8 *k,u_int kbits)
x->input[3] = U8TO32_LITTLE(constants + 12);
}
-void
+LOCAL void
chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
{
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
@@ -97,7 +96,7 @@ chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
x->input[15] = U8TO32_LITTLE(iv + 4);
}
-void
+LOCAL void
#ifndef __rtems__
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
#else /* __rtems__ */
@@ -179,6 +178,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u_int bytes)
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
+#ifndef KEYSTREAM_ONLY
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
@@ -195,6 +195,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u_int bytes)
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
j12 = PLUSONE(j12);
if (!j12) {
@@ -229,6 +230,8 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u_int bytes)
}
bytes -= 64;
c += 64;
+#ifndef KEYSTREAM_ONLY
m += 64;
+#endif
}
}
diff --git a/freebsd/sys/crypto/chacha20/chacha.h b/freebsd/sys/crypto/chacha20/chacha.h
index 02106eaa..e67cc812 100644
--- a/freebsd/sys/crypto/chacha20/chacha.h
+++ b/freebsd/sys/crypto/chacha20/chacha.h
@@ -23,9 +23,15 @@ struct chacha_ctx {
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
-void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);
-void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);
-void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
+#ifdef _KERNEL
+#define LOCAL
+#else
+#define LOCAL static
+#endif
+
+LOCAL void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);
+LOCAL void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);
+LOCAL void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
u_char *c, u_int bytes);
#endif /* CHACHA_H */
diff --git a/freebsd/sys/crypto/libsodium/utils.c b/freebsd/sys/crypto/libsodium/utils.c
new file mode 100644
index 00000000..8c6dfc36
--- /dev/null
+++ b/freebsd/sys/crypto/libsodium/utils.c
@@ -0,0 +1,16 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/* This file is in the public domain. */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <sodium/utils.h>
+
+void
+sodium_memzero(void *b, size_t n)
+{
+ explicit_bzero(b, n);
+}
diff --git a/freebsd/sys/crypto/sha2/sha224.h b/freebsd/sys/crypto/sha2/sha224.h
new file mode 100644
index 00000000..c2833543
--- /dev/null
+++ b/freebsd/sys/crypto/sha2/sha224.h
@@ -0,0 +1,96 @@
+/*-
+ * Copyright 2005 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SHA224_H_
+#define _SHA224_H_
+
+#ifndef _KERNEL
+#include <sys/types.h>
+#endif
+
+#define SHA224_BLOCK_LENGTH 64
+#define SHA224_DIGEST_LENGTH 28
+#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
+
+typedef struct SHA224Context {
+ uint32_t state[8];
+ uint64_t count;
+ uint8_t buf[SHA224_BLOCK_LENGTH];
+} SHA224_CTX;
+
+__BEGIN_DECLS
+
+/* Ensure libmd symbols do not clash with libcrypto */
+
+#ifndef SHA224_Init
+#define SHA224_Init _libmd_SHA224_Init
+#endif
+#ifndef SHA224_Update
+#define SHA224_Update _libmd_SHA224_Update
+#endif
+#ifndef SHA224_Final
+#define SHA224_Final _libmd_SHA224_Final
+#endif
+#ifndef SHA224_End
+#define SHA224_End _libmd_SHA224_End
+#endif
+#ifndef SHA224_Fd
+#define SHA224_Fd _libmd_SHA224_Fd
+#endif
+#ifndef SHA224_FdChunk
+#define SHA224_FdChunk _libmd_SHA224_FdChunk
+#endif
+#ifndef SHA224_File
+#define SHA224_File _libmd_SHA224_File
+#endif
+#ifndef SHA224_FileChunk
+#define SHA224_FileChunk _libmd_SHA224_FileChunk
+#endif
+#ifndef SHA224_Data
+#define SHA224_Data _libmd_SHA224_Data
+#endif
+
+#ifndef SHA224_version
+#define SHA224_version _libmd_SHA224_version
+#endif
+
+void SHA224_Init(SHA224_CTX *);
+void SHA224_Update(SHA224_CTX *, const void *, size_t);
+void SHA224_Final(unsigned char [__min_size(SHA224_DIGEST_LENGTH)],
+ SHA224_CTX *);
+#ifndef _KERNEL
+char *SHA224_End(SHA224_CTX *, char *);
+char *SHA224_Data(const void *, unsigned int, char *);
+char *SHA224_Fd(int, char *);
+char *SHA224_FdChunk(int, char *, off_t, off_t);
+char *SHA224_File(const char *, char *);
+char *SHA224_FileChunk(const char *, char *, off_t, off_t);
+#endif
+__END_DECLS
+
+#endif /* !_SHA224_H_ */
diff --git a/freebsd/sys/crypto/sha2/sha256c.c b/freebsd/sys/crypto/sha2/sha256c.c
index ea389694..dbba6d35 100644
--- a/freebsd/sys/crypto/sha2/sha256c.c
+++ b/freebsd/sys/crypto/sha2/sha256c.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#endif
+#include "sha224.h"
#include "sha256.h"
#if BYTE_ORDER == BIG_ENDIAN
@@ -299,7 +300,57 @@ SHA256_Final(unsigned char digest[static SHA256_DIGEST_LENGTH], SHA256_CTX *ctx)
be32enc_vect(digest, ctx->state, SHA256_DIGEST_LENGTH);
/* Clear the context state */
- memset(ctx, 0, sizeof(*ctx));
+ explicit_bzero(ctx, sizeof(*ctx));
+}
+
+/*** SHA-224: *********************************************************/
+/*
+ * the SHA224 and SHA256 transforms are identical
+ */
+
+/* SHA-224 initialization. Begins a SHA-224 operation. */
+void
+SHA224_Init(SHA224_CTX * ctx)
+{
+
+ /* Zero bits processed so far */
+ ctx->count = 0;
+
+ /* Magic initialization constants */
+ ctx->state[0] = 0xC1059ED8;
+ ctx->state[1] = 0x367CD507;
+ ctx->state[2] = 0x3070DD17;
+ ctx->state[3] = 0xF70E5939;
+ ctx->state[4] = 0xFFC00B31;
+ ctx->state[5] = 0x68581511;
+ ctx->state[6] = 0x64f98FA7;
+ ctx->state[7] = 0xBEFA4FA4;
+}
+
+/* Add bytes into the SHA-224 hash */
+void
+SHA224_Update(SHA224_CTX * ctx, const void *in, size_t len)
+{
+
+ SHA256_Update((SHA256_CTX *)ctx, in, len);
+}
+
+/*
+ * SHA-224 finalization. Pads the input data, exports the hash value,
+ * and clears the context state.
+ */
+void
+SHA224_Final(unsigned char digest[static SHA224_DIGEST_LENGTH], SHA224_CTX *ctx)
+{
+
+ /* Add padding */
+ SHA256_Pad((SHA256_CTX *)ctx);
+
+ /* Write the hash */
+ be32enc_vect(digest, ctx->state, SHA224_DIGEST_LENGTH);
+
+ /* Clear the context state */
+ explicit_bzero(ctx, sizeof(*ctx));
}
#ifdef WEAK_REFS
@@ -315,4 +366,11 @@ __weak_reference(_libmd_SHA256_Update, SHA256_Update);
__weak_reference(_libmd_SHA256_Final, SHA256_Final);
#undef SHA256_Transform
__weak_reference(_libmd_SHA256_Transform, SHA256_Transform);
+
+#undef SHA224_Init
+__weak_reference(_libmd_SHA224_Init, SHA224_Init);
+#undef SHA224_Update
+__weak_reference(_libmd_SHA224_Update, SHA224_Update);
+#undef SHA224_Final
+__weak_reference(_libmd_SHA224_Final, SHA224_Final);
#endif
diff --git a/freebsd/sys/crypto/sha2/sha512c.c b/freebsd/sys/crypto/sha2/sha512c.c
index 7aa4bf52..4e7de3ee 100644
--- a/freebsd/sys/crypto/sha2/sha512c.c
+++ b/freebsd/sys/crypto/sha2/sha512c.c
@@ -333,7 +333,7 @@ SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH], SHA512_CTX *ctx)
be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH);
/* Clear the context state */
- memset(ctx, 0, sizeof(*ctx));
+ explicit_bzero(ctx, sizeof(*ctx));
}
/*** SHA-512t: *********************************************************/
@@ -376,7 +376,7 @@ SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH], SHA512_C
be64enc_vect(digest, ctx->state, SHA512_224_DIGEST_LENGTH);
/* Clear the context state */
- memset(ctx, 0, sizeof(*ctx));
+ explicit_bzero(ctx, sizeof(*ctx));
}
void
@@ -415,7 +415,7 @@ SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH], SHA512_C
be64enc_vect(digest, ctx->state, SHA512_256_DIGEST_LENGTH);
/* Clear the context state */
- memset(ctx, 0, sizeof(*ctx));
+ explicit_bzero(ctx, sizeof(*ctx));
}
/*** SHA-384: *********************************************************/
@@ -465,7 +465,7 @@ SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH], SHA384_CTX *ctx)
be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH);
/* Clear the context state */
- memset(ctx, 0, sizeof(*ctx));
+ explicit_bzero(ctx, sizeof(*ctx));
}
#ifdef WEAK_REFS
diff --git a/freebsd/sys/crypto/skein/skein.c b/freebsd/sys/crypto/skein/skein.c
index c13f9ad4..e444837a 100644
--- a/freebsd/sys/crypto/skein/skein.c
+++ b/freebsd/sys/crypto/skein/skein.c
@@ -814,6 +814,7 @@ SKEIN256_Final(unsigned char digest[static SKEIN_256_BLOCK_BYTES], SKEIN256_CTX
{
Skein_256_Final(ctx, digest);
+ explicit_bzero(ctx, sizeof(*ctx));
}
void
@@ -821,6 +822,7 @@ SKEIN512_Final(unsigned char digest[static SKEIN_512_BLOCK_BYTES], SKEIN512_CTX
{
Skein_512_Final(ctx, digest);
+ explicit_bzero(ctx, sizeof(*ctx));
}
void
@@ -828,6 +830,7 @@ SKEIN1024_Final(unsigned char digest[static SKEIN1024_BLOCK_BYTES], SKEIN1024_CT
{
Skein1024_Final(ctx, digest);
+ explicit_bzero(ctx, sizeof(*ctx));
}
#ifdef WEAK_REFS
diff --git a/freebsd/sys/dev/bfe/if_bfe.c b/freebsd/sys/dev/bfe/if_bfe.c
index c07d87fb..f1586d59 100644
--- a/freebsd/sys/dev/bfe/if_bfe.c
+++ b/freebsd/sys/dev/bfe/if_bfe.c
@@ -159,6 +159,8 @@ static driver_t bfe_driver = {
static devclass_t bfe_devclass;
DRIVER_MODULE(bfe, pci, bfe_driver, bfe_devclass, 0, 0);
+MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, bfe, bfe_devs,
+ sizeof(bfe_devs[0]), nitems(bfe_devs) - 1);
DRIVER_MODULE(miibus, bfe, miibus_driver, miibus_devclass, 0, 0);
/*
diff --git a/freebsd/sys/dev/bge/if_bge.c b/freebsd/sys/dev/bge/if_bge.c
index aba0b05d..260c6c23 100644
--- a/freebsd/sys/dev/bge/if_bge.c
+++ b/freebsd/sys/dev/bge/if_bge.c
@@ -549,6 +549,8 @@ static driver_t bge_driver = {
static devclass_t bge_devclass;
DRIVER_MODULE(bge, pci, bge_driver, bge_devclass, 0, 0);
+MODULE_PNP_INFO("U16:vendor;U16:device", pci, bge, bge_devs,
+ sizeof(bge_devs[0]), nitems(bge_devs) - 1);
DRIVER_MODULE(miibus, bge, miibus_driver, miibus_devclass, 0, 0);
static int bge_allow_asf = 1;
@@ -3212,6 +3214,14 @@ bge_can_use_msi(struct bge_softc *sc)
sc->bge_chiprev != BGE_CHIPREV_5750_BX)
can_use_msi = 1;
break;
+ case BGE_ASICREV_BCM5784:
+ /*
+ * Prevent infinite "watchdog timeout" errors
+ * in some MacBook Pro and make it work out-of-the-box.
+ */
+ if (sc->bge_chiprev == BGE_CHIPREV_5784_AX)
+ break;
+ /* FALLTHROUGH */
default:
if (BGE_IS_575X_PLUS(sc))
can_use_msi = 1;
@@ -6716,15 +6726,15 @@ bge_sysctl_mem_read(SYSCTL_HANDLER_ARGS)
static int
bge_get_eaddr_fw(struct bge_softc *sc, uint8_t ether_addr[])
{
-
+#ifdef __sparc64__
if (sc->bge_flags & BGE_FLAG_EADDR)
return (1);
-#ifdef __sparc64__
OF_getetheraddr(sc->bge_dev, ether_addr);
return (0);
-#endif
+#else
return (1);
+#endif
}
static int
diff --git a/freebsd/sys/dev/dc/if_dc.c b/freebsd/sys/dev/dc/if_dc.c
index ac34a20a..14023e54 100644
--- a/freebsd/sys/dev/dc/if_dc.c
+++ b/freebsd/sys/dev/dc/if_dc.c
@@ -361,6 +361,8 @@ static devclass_t dc_devclass;
DRIVER_MODULE_ORDERED(dc, pci, dc_driver, dc_devclass, NULL, NULL,
SI_ORDER_ANY);
+MODULE_PNP_INFO("W32:vendor/device;U8:revision;D:#", pci, dc, dc_devs,
+ sizeof(dc_devs[0]), nitems(dc_devs) - 1);
DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, NULL, NULL);
#define DC_SETBIT(sc, reg, x) \
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c
index 72711a6e..4fe66dfc 100644
--- a/freebsd/sys/dev/e1000/if_em.c
+++ b/freebsd/sys/dev/e1000/if_em.c
@@ -412,7 +412,6 @@ static driver_t em_if_driver = {
#define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000)
#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
-#define M_TSO_LEN 66
#define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256))
@@ -422,8 +421,6 @@ static driver_t em_if_driver = {
#define CSUM_TSO 0
#endif
-#define TSO_WORKAROUND 4
-
static SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters");
static int em_disable_crc_stripping = 0;
@@ -486,8 +483,10 @@ extern struct if_txrx lem_txrx;
static struct if_shared_ctx em_sctx_init = {
.isc_magic = IFLIB_MAGIC,
.isc_q_align = PAGE_SIZE,
- .isc_tx_maxsize = EM_TSO_SIZE,
+ .isc_tx_maxsize = EM_TSO_SIZE + sizeof(struct ether_vlan_header),
.isc_tx_maxsegsize = PAGE_SIZE,
+ .isc_tso_maxsize = EM_TSO_SIZE + sizeof(struct ether_vlan_header),
+ .isc_tso_maxsegsize = EM_TSO_SEG_SIZE,
.isc_rx_maxsize = MJUM9BYTES,
.isc_rx_nsegments = 1,
.isc_rx_maxsegsize = MJUM9BYTES,
@@ -510,12 +509,13 @@ static struct if_shared_ctx em_sctx_init = {
if_shared_ctx_t em_sctx = &em_sctx_init;
-
static struct if_shared_ctx igb_sctx_init = {
.isc_magic = IFLIB_MAGIC,
.isc_q_align = PAGE_SIZE,
- .isc_tx_maxsize = EM_TSO_SIZE,
+ .isc_tx_maxsize = EM_TSO_SIZE + sizeof(struct ether_vlan_header),
.isc_tx_maxsegsize = PAGE_SIZE,
+ .isc_tso_maxsize = EM_TSO_SIZE + sizeof(struct ether_vlan_header),
+ .isc_tso_maxsegsize = EM_TSO_SEG_SIZE,
.isc_rx_maxsize = MJUM9BYTES,
.isc_rx_nsegments = 1,
.isc_rx_maxsegsize = MJUM9BYTES,
@@ -699,16 +699,19 @@ em_set_num_queues(if_ctx_t ctx)
return (maxqueues);
}
+#define LEM_CAPS \
+ IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \
+ IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER
-#define EM_CAPS \
- IFCAP_TSO4 | IFCAP_TXCSUM | IFCAP_LRO | IFCAP_RXCSUM | IFCAP_VLAN_HWFILTER | IFCAP_WOL_MAGIC | \
- IFCAP_WOL_MCAST | IFCAP_WOL | IFCAP_VLAN_HWTSO | IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | \
- IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU;
+#define EM_CAPS \
+ IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \
+ IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER | IFCAP_TSO4 | \
+ IFCAP_LRO | IFCAP_VLAN_HWTSO
-#define IGB_CAPS \
- IFCAP_TSO4 | IFCAP_TXCSUM | IFCAP_LRO | IFCAP_RXCSUM | IFCAP_VLAN_HWFILTER | IFCAP_WOL_MAGIC | \
- IFCAP_WOL_MCAST | IFCAP_WOL | IFCAP_VLAN_HWTSO | IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | \
- IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU | IFCAP_TXCSUM_IPV6 | IFCAP_HWCSUM_IPV6 | IFCAP_JUMBO_MTU;
+#define IGB_CAPS \
+ IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \
+ IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER | IFCAP_TSO4 | \
+ IFCAP_LRO | IFCAP_VLAN_HWTSO | IFCAP_JUMBO_MTU | IFCAP_HWCSUM_IPV6;
/*********************************************************************
* Device initialization routine
@@ -775,18 +778,11 @@ em_if_attach_pre(if_ctx_t ctx)
/* Determine hardware and mac info */
em_identify_hardware(ctx);
- /* Set isc_msix_bar */
scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR);
scctx->isc_tx_nsegments = EM_MAX_SCATTER;
- scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments;
- scctx->isc_tx_tso_size_max = EM_TSO_SIZE;
- scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE;
scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx);
device_printf(dev, "attach_pre capping queues at %d\n", scctx->isc_ntxqsets_max);
- scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO;
-
-
if (adapter->hw.mac.type >= igb_mac_min) {
int try_second_bar;
@@ -795,9 +791,12 @@ em_if_attach_pre(if_ctx_t ctx)
scctx->isc_txd_size[0] = sizeof(union e1000_adv_tx_desc);
scctx->isc_rxd_size[0] = sizeof(union e1000_adv_rx_desc);
scctx->isc_txrx = &igb_txrx;
- scctx->isc_capenable = IGB_CAPS;
- scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_IP6_TCP \
- | CSUM_IP6_UDP | CSUM_IP6_TCP;
+ scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER;
+ scctx->isc_tx_tso_size_max = EM_TSO_SIZE;
+ scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE;
+ scctx->isc_capabilities = scctx->isc_capenable = IGB_CAPS;
+ scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO |
+ CSUM_IP6_TCP | CSUM_IP6_UDP;
if (adapter->hw.mac.type != e1000_82575)
scctx->isc_tx_csum_flags |= CSUM_SCTP | CSUM_IP6_SCTP;
@@ -809,26 +808,44 @@ em_if_attach_pre(if_ctx_t ctx)
try_second_bar = pci_read_config(dev, scctx->isc_msix_bar, 4);
if (try_second_bar == 0)
scctx->isc_msix_bar += 4;
-
} else if (adapter->hw.mac.type >= em_mac_min) {
scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]* sizeof(struct e1000_tx_desc), EM_DBA_ALIGN);
scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_rx_desc_extended), EM_DBA_ALIGN);
scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc);
scctx->isc_rxd_size[0] = sizeof(union e1000_rx_desc_extended);
scctx->isc_txrx = &em_txrx;
- scctx->isc_capenable = EM_CAPS;
+ scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER;
+ scctx->isc_tx_tso_size_max = EM_TSO_SIZE;
+ scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE;
+ scctx->isc_capabilities = scctx->isc_capenable = EM_CAPS;
+ /*
+ * For EM-class devices, don't enable IFCAP_{TSO4,VLAN_HWTSO}
+ * by default as we don't have workarounds for all associated
+ * silicon errata. E. g., with several MACs such as 82573E,
+ * TSO only works at Gigabit speed and otherwise can cause the
+ * hardware to hang (which also would be next to impossible to
+ * work around given that already queued TSO-using descriptors
+ * would need to be flushed and vlan(4) reconfigured at runtime
+ * in case of a link speed change). Moreover, MACs like 82579
+ * still can hang at Gigabit even with all publicly documented
+ * TSO workarounds implemented. Generally, the penality of
+ * these workarounds is rather high and may involve copying
+ * mbuf data around so advantages of TSO lapse. Still, TSO may
+ * work for a few MACs of this class - at least when sticking
+ * with Gigabit - in which case users may enable TSO manually.
+ */
+ scctx->isc_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO);
scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO;
} else {
scctx->isc_txqsizes[0] = roundup2((scctx->isc_ntxd[0] + 1) * sizeof(struct e1000_tx_desc), EM_DBA_ALIGN);
scctx->isc_rxqsizes[0] = roundup2((scctx->isc_nrxd[0] + 1) * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN);
scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc);
scctx->isc_rxd_size[0] = sizeof(struct e1000_rx_desc);
- scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO;
+ scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP;
scctx->isc_txrx = &lem_txrx;
- scctx->isc_capenable = EM_CAPS;
+ scctx->isc_capabilities = scctx->isc_capenable = LEM_CAPS;
if (adapter->hw.mac.type < e1000_82543)
scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM);
- scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO;
scctx->isc_msix_bar = 0;
}
@@ -1009,6 +1026,11 @@ em_if_attach_pre(if_ctx_t ctx)
*/
em_get_wakeup(ctx);
+ /* Enable only WOL MAGIC by default */
+ scctx->isc_capenable &= ~IFCAP_WOL;
+ if (adapter->wol != 0)
+ scctx->isc_capenable |= IFCAP_WOL_MAGIC;
+
iflib_set_mac(ctx, hw->mac.addr);
return (0);
@@ -1702,7 +1724,6 @@ em_if_update_admin_status(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
struct e1000_hw *hw = &adapter->hw;
- struct ifnet *ifp = iflib_get_ifp(ctx);
device_t dev = iflib_get_dev(ctx);
u32 link_check, thstat, ctrl;
@@ -1766,8 +1787,8 @@ em_if_update_admin_status(if_ctx_t ctx)
"Full Duplex" : "Half Duplex"));
adapter->link_active = 1;
adapter->smartspeed = 0;
- if_setbaudrate(ifp, adapter->link_speed * 1000000);
- if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
+ if ((ctrl & E1000_CTRL_EXT_LINK_MODE_MASK) ==
+ E1000_CTRL_EXT_LINK_MODE_GMII &&
(thstat & E1000_THSTAT_LINK_THROTTLE))
device_printf(dev, "Link: thermal downshift\n");
/* Delay Link Up for Phy update */
@@ -1782,17 +1803,15 @@ em_if_update_admin_status(if_ctx_t ctx)
adapter->flags |= IGB_MEDIA_RESET;
em_reset(ctx);
}
- iflib_link_state_change(ctx, LINK_STATE_UP, ifp->if_baudrate);
+ iflib_link_state_change(ctx, LINK_STATE_UP,
+ IF_Mbps(adapter->link_speed));
printf("Link state changed to up\n");
} else if (!link_check && (adapter->link_active == 1)) {
- if_setbaudrate(ifp, 0);
adapter->link_speed = 0;
adapter->link_duplex = 0;
- if (bootverbose)
- device_printf(dev, "Link is Down\n");
adapter->link_active = 0;
- iflib_link_state_change(ctx, LINK_STATE_DOWN, ifp->if_baudrate);
- printf("link state changed to down\n");
+ iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
+ printf("Link state changed to down\n");
}
em_update_stats_counters(adapter);
@@ -1965,7 +1984,6 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix)
vector = 0;
for (i = 0; i < adapter->tx_num_queues; i++, tx_que++, vector++) {
- rid = vector + 1;
snprintf(buf, sizeof(buf), "txq%d", i);
tx_que = &adapter->tx_queues[i];
iflib_softirq_alloc_generic(ctx,
@@ -2304,7 +2322,7 @@ igb_init_dmac(struct adapter *adapter, u32 pba)
dmac = pba - 10;
reg = E1000_READ_REG(hw, E1000_DMACR);
reg &= ~E1000_DMACR_DMACTHR_MASK;
- reg = ((dmac << E1000_DMACR_DMACTHR_SHIFT)
+ reg |= ((dmac << E1000_DMACR_DMACTHR_SHIFT)
& E1000_DMACR_DMACTHR_MASK);
/* transition to L0x or L1 if available..*/
@@ -2752,51 +2770,15 @@ em_setup_interface(if_ctx_t ctx)
struct ifnet *ifp = iflib_get_ifp(ctx);
struct adapter *adapter = iflib_get_softc(ctx);
if_softc_ctx_t scctx = adapter->shared;
- uint64_t cap = 0;
INIT_DEBUGOUT("em_setup_interface: begin");
- /* TSO parameters */
- if_sethwtsomax(ifp, IP_MAXPACKET);
- /* Take m_pullup(9)'s in em_xmit() w/ TSO into acount. */
- if_sethwtsomaxsegcount(ifp, EM_MAX_SCATTER - 5);
- if_sethwtsomaxsegsize(ifp, EM_TSO_SEG_SIZE);
-
/* Single Queue */
if (adapter->tx_num_queues == 1) {
if_setsendqlen(ifp, scctx->isc_ntxd[0] - 1);
if_setsendqready(ifp);
}
- cap = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | IFCAP_TSO4;
- cap |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU;
-
- /*
- * Tell the upper layer(s) we
- * support full VLAN capability
- */
- if_setifheaderlen(ifp, sizeof(struct ether_vlan_header));
- if_setcapabilitiesbit(ifp, cap, 0);
-
- /*
- * Don't turn this on by default, if vlans are
- * created on another pseudo device (eg. lagg)
- * then vlan events are not passed thru, breaking
- * operation, but with HW FILTER off it works. If
- * using vlans directly on the em driver you can
- * enable this and get full hardware tag filtering.
- */
- if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWFILTER,0);
-
- /* Enable only WOL MAGIC by default */
- if (adapter->wol) {
- if_setcapenablebit(ifp, IFCAP_WOL_MAGIC,
- IFCAP_WOL_MCAST| IFCAP_WOL_UCAST);
- } else {
- if_setcapenablebit(ifp, 0, IFCAP_WOL_MAGIC |
- IFCAP_WOL_MCAST| IFCAP_WOL_UCAST);
- }
-
/*
* Specify the media types supported by this adapter and register
* callbacks to update media and link information
diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h
index 0c892947..26bdcb2e 100644
--- a/freebsd/sys/dev/e1000/if_em.h
+++ b/freebsd/sys/dev/e1000/if_em.h
@@ -250,11 +250,6 @@
#define IGB_LINK_ITR 2000
#define I210_LINK_DELAY 1000
-#define IGB_MAX_SCATTER 40
-#define IGB_VFTA_SIZE 128
-#define IGB_BR_SIZE 4096 /* ring buf size */
-#define IGB_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
-#define IGB_TSO_SEG_SIZE 4096 /* Max dma segment size */
#define IGB_TXPBSIZE 20408
#define IGB_HDR_BUF 128
#define IGB_PKTTYPE_MASK 0x0000FFF0
@@ -340,7 +335,7 @@
#define EM_MAX_SCATTER 40
#define EM_VFTA_SIZE 128
-#define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
+#define EM_TSO_SIZE 65535
#define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */
#define EM_MSIX_MASK 0x01F00000 /* For 82574 use */
#define EM_MSIX_LINK 0x01000000 /* For 82574 use */
diff --git a/freebsd/sys/dev/evdev/cdev.c b/freebsd/sys/dev/evdev/cdev.c
index 10f4e77e..5ae14fed 100644
--- a/freebsd/sys/dev/evdev/cdev.c
+++ b/freebsd/sys/dev/evdev/cdev.c
@@ -421,7 +421,7 @@ evdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
return (ENOTSUP);
ke = (struct input_keymap_entry *)data;
- evdev->ev_methods->ev_get_keycode(evdev, evdev->ev_softc, ke);
+ evdev->ev_methods->ev_get_keycode(evdev, ke);
return (0);
case EVIOCSKEYCODE:
@@ -434,7 +434,7 @@ evdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
return (ENOTSUP);
ke = (struct input_keymap_entry *)data;
- evdev->ev_methods->ev_set_keycode(evdev, evdev->ev_softc, ke);
+ evdev->ev_methods->ev_set_keycode(evdev, ke);
return (0);
case EVIOCGABS(0) ... EVIOCGABS(ABS_MAX):
diff --git a/freebsd/sys/dev/evdev/evdev.c b/freebsd/sys/dev/evdev/evdev.c
index 6c2976d7..a355ec50 100644
--- a/freebsd/sys/dev/evdev/evdev.c
+++ b/freebsd/sys/dev/evdev/evdev.c
@@ -343,6 +343,13 @@ evdev_set_methods(struct evdev_dev *evdev, void *softc,
evdev->ev_softc = softc;
}
+inline void *
+evdev_get_softc(struct evdev_dev *evdev)
+{
+
+ return (evdev->ev_softc);
+}
+
inline void
evdev_support_prop(struct evdev_dev *evdev, uint16_t prop)
{
@@ -804,8 +811,7 @@ evdev_inject_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
case EV_FF:
if (evdev->ev_methods != NULL &&
evdev->ev_methods->ev_event != NULL)
- evdev->ev_methods->ev_event(evdev, evdev->ev_softc,
- type, code, value);
+ evdev->ev_methods->ev_event(evdev, type, code, value);
/*
* Leds and driver repeats should be reported in ev_event
* method body to interoperate with kbdmux states and rates
@@ -848,7 +854,7 @@ evdev_register_client(struct evdev_dev *evdev, struct evdev_client *client)
evdev->ev_methods->ev_open != NULL) {
debugf(evdev, "calling ev_open() on device %s",
evdev->ev_shortname);
- ret = evdev->ev_methods->ev_open(evdev, evdev->ev_softc);
+ ret = evdev->ev_methods->ev_open(evdev);
}
if (ret == 0)
LIST_INSERT_HEAD(&evdev->ev_clients, client, ec_link);
@@ -866,7 +872,7 @@ evdev_dispose_client(struct evdev_dev *evdev, struct evdev_client *client)
if (LIST_EMPTY(&evdev->ev_clients)) {
if (evdev->ev_methods != NULL &&
evdev->ev_methods->ev_close != NULL)
- evdev->ev_methods->ev_close(evdev, evdev->ev_softc);
+ (void)evdev->ev_methods->ev_close(evdev);
if (evdev_event_supported(evdev, EV_REP) &&
bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT))
evdev_stop_repeat(evdev);
diff --git a/freebsd/sys/dev/evdev/evdev.h b/freebsd/sys/dev/evdev/evdev.h
index 31f0c2c3..b897a465 100644
--- a/freebsd/sys/dev/evdev/evdev.h
+++ b/freebsd/sys/dev/evdev/evdev.h
@@ -38,11 +38,10 @@
struct evdev_dev;
-typedef int (evdev_open_t)(struct evdev_dev *, void *);
-typedef void (evdev_close_t)(struct evdev_dev *, void *);
-typedef void (evdev_event_t)(struct evdev_dev *, void *, uint16_t,
- uint16_t, int32_t);
-typedef void (evdev_keycode_t)(struct evdev_dev *, void *,
+typedef int (evdev_open_t)(struct evdev_dev *);
+typedef int (evdev_close_t)(struct evdev_dev *);
+typedef void (evdev_event_t)(struct evdev_dev *, uint16_t, uint16_t, int32_t);
+typedef void (evdev_keycode_t)(struct evdev_dev *,
struct input_keymap_entry *);
/*
@@ -126,6 +125,7 @@ void evdev_support_sw(struct evdev_dev *, uint16_t);
void evdev_set_repeat_params(struct evdev_dev *, uint16_t, int);
int evdev_set_report_size(struct evdev_dev *, size_t);
void evdev_set_flag(struct evdev_dev *, uint16_t);
+void *evdev_get_softc(struct evdev_dev *);
/* Multitouch related functions: */
int32_t evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
@@ -141,7 +141,6 @@ uint16_t evdev_scancode2key(int *, int);
void evdev_push_mouse_btn(struct evdev_dev *, int);
void evdev_push_leds(struct evdev_dev *, int);
void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
-evdev_event_t evdev_ev_kbd_event;
/* Event reporting shortcuts: */
static __inline int
diff --git a/freebsd/sys/dev/evdev/evdev_utils.c b/freebsd/sys/dev/evdev/evdev_utils.c
index 9814ffeb..17a815fb 100644
--- a/freebsd/sys/dev/evdev/evdev_utils.c
+++ b/freebsd/sys/dev/evdev/evdev_utils.c
@@ -42,8 +42,6 @@
#include <dev/evdev/evdev.h>
#include <dev/evdev/input.h>
-#include <dev/kbd/kbdreg.h>
-
#define NONE KEY_RESERVED
static uint16_t evdev_usb_scancodes[256] = {
@@ -301,43 +299,3 @@ evdev_push_repeats(struct evdev_dev *evdev, keyboard_t *kbd)
evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
}
-
-void
-evdev_ev_kbd_event(struct evdev_dev *evdev, void *softc, uint16_t type,
- uint16_t code, int32_t value)
-{
- keyboard_t *kbd = (keyboard_t *)softc;
- int delay[2], leds, oleds;
- size_t i;
-
- if (type == EV_LED) {
- leds = oleds = KBD_LED_VAL(kbd);
- for (i = 0; i < nitems(evdev_led_codes); i++) {
- if (evdev_led_codes[i] == code) {
- if (value)
- leds |= 1 << i;
- else
- leds &= ~(1 << i);
- if (leds != oleds) {
- mtx_lock(&Giant);
- kbdd_ioctl(kbd, KDSETLED,
- (caddr_t)&leds);
- mtx_unlock(&Giant);
- }
- break;
- }
- }
- } else if (type == EV_REP && code == REP_DELAY) {
- delay[0] = value;
- delay[1] = kbd->kb_delay2;
- mtx_lock(&Giant);
- kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
- mtx_unlock(&Giant);
- } else if (type == EV_REP && code == REP_PERIOD) {
- delay[0] = kbd->kb_delay1;
- delay[1] = value;
- mtx_lock(&Giant);
- kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
- mtx_unlock(&Giant);
- }
-}
diff --git a/freebsd/sys/dev/evdev/input-event-codes.h b/freebsd/sys/dev/evdev/input-event-codes.h
index cc1528f6..61c9000b 100644
--- a/freebsd/sys/dev/evdev/input-event-codes.h
+++ b/freebsd/sys/dev/evdev/input-event-codes.h
@@ -421,6 +421,7 @@
#define BTN_TOOL_MOUSE 0x146
#define BTN_TOOL_LENS 0x147
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
+#define BTN_STYLUS3 0x149
#define BTN_TOUCH 0x14a
#define BTN_STYLUS 0x14b
#define BTN_STYLUS2 0x14c
@@ -607,6 +608,7 @@
#define BTN_DPAD_RIGHT 0x223
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
+#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
@@ -615,6 +617,7 @@
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
+#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
@@ -626,6 +629,38 @@
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
#define KEY_KBDINPUTASSIST_CANCEL 0x265
+/* Diagonal movement keys */
+#define KEY_RIGHT_UP 0x266
+#define KEY_RIGHT_DOWN 0x267
+#define KEY_LEFT_UP 0x268
+#define KEY_LEFT_DOWN 0x269
+
+#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */
+/* Show Top Menu of the Media (e.g. DVD) */
+#define KEY_MEDIA_TOP_MENU 0x26b
+#define KEY_NUMERIC_11 0x26c
+#define KEY_NUMERIC_12 0x26d
+/*
+ * Toggle Audio Description: refers to an audio service that helps blind and
+ * visually impaired consumers understand the action in a program. Note: in
+ * some countries this is referred to as "Video Description".
+ */
+#define KEY_AUDIO_DESC 0x26e
+#define KEY_3D_MODE 0x26f
+#define KEY_NEXT_FAVORITE 0x270
+#define KEY_STOP_RECORD 0x271
+#define KEY_PAUSE_RECORD 0x272
+#define KEY_VOD 0x273 /* Video on Demand */
+#define KEY_UNMUTE 0x274
+#define KEY_FASTREVERSE 0x275
+#define KEY_SLOWREVERSE 0x276
+/*
+ * Control a data application associated with the currently viewed channel,
+ * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
+ */
+#define KEY_DATA 0x277
+#define KEY_ONSCREEN_KEYBOARD 0x278
+
#define BTN_TRIGGER_HAPPY 0x2c0
#define BTN_TRIGGER_HAPPY1 0x2c0
#define BTN_TRIGGER_HAPPY2 0x2c1
@@ -763,6 +798,7 @@
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
+#define SW_PEN_INSERTED 0x0f /* set = pen inserted */
#define SW_MAX 0x0f
#define SW_CNT (SW_MAX+1)
diff --git a/freebsd/sys/dev/evdev/input.h b/freebsd/sys/dev/evdev/input.h
index 7639e0d6..947f4643 100644
--- a/freebsd/sys/dev/evdev/input.h
+++ b/freebsd/sys/dev/evdev/input.h
@@ -38,6 +38,9 @@
#include "input-event-codes.h"
+#define input_event_sec time.tv_sec
+#define input_event_usec time.tv_usec
+
struct input_event {
struct timeval time;
uint16_t type;
@@ -138,6 +141,9 @@ struct input_keymap_entry {
#define BUS_GSC 0x1A
#define BUS_ATARI 0x1B
#define BUS_SPI 0x1C
+#define BUS_RMI 0x1D
+#define BUS_CEC 0x1E
+#define BUS_INTEL_ISHTP 0x1F
/*
* MT_TOOL types
diff --git a/freebsd/sys/dev/evdev/uinput.c b/freebsd/sys/dev/evdev/uinput.c
index 3b332d1f..28d740cc 100644
--- a/freebsd/sys/dev/evdev/uinput.c
+++ b/freebsd/sys/dev/evdev/uinput.c
@@ -161,10 +161,10 @@ uinput_knl_assert_unlocked(void *arg)
}
static void
-uinput_ev_event(struct evdev_dev *evdev, void *softc, uint16_t type,
- uint16_t code, int32_t value)
+uinput_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
{
- struct uinput_cdev_state *state = softc;
+ struct uinput_cdev_state *state = evdev_get_softc(evdev);
if (type == EV_LED)
evdev_push_event(evdev, type, code, value);
diff --git a/freebsd/sys/dev/fxp/if_fxp.c b/freebsd/sys/dev/fxp/if_fxp.c
index ca933aa8..032246d8 100644
--- a/freebsd/sys/dev/fxp/if_fxp.c
+++ b/freebsd/sys/dev/fxp/if_fxp.c
@@ -309,6 +309,8 @@ static devclass_t fxp_devclass;
DRIVER_MODULE_ORDERED(fxp, pci, fxp_driver, fxp_devclass, NULL, NULL,
SI_ORDER_ANY);
+MODULE_PNP_INFO("U16:vendor;U16:device", pci, fxp, fxp_ident_table,
+ sizeof(fxp_ident_table[0]), nitems(fxp_ident_table) - 1);
DRIVER_MODULE(miibus, fxp, miibus_driver, miibus_devclass, NULL, NULL);
static struct resource_spec fxp_res_spec_mem[] = {
diff --git a/freebsd/sys/dev/kbd/kbd.c b/freebsd/sys/dev/kbd/kbd.c
index c7512e89..b157e57e 100644
--- a/freebsd/sys/dev/kbd/kbd.c
+++ b/freebsd/sys/dev/kbd/kbd.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kbio.h>
+#include <dev/evdev/input-event-codes.h>
#include <dev/kbd/kbdreg.h>
#define KBD_INDEX(dev) dev2unit(dev)
@@ -1477,3 +1478,41 @@ genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
}
/* NOT REACHED */
}
+
+void
+kbd_ev_event(keyboard_t *kbd, uint16_t type, uint16_t code, int32_t value)
+{
+ int delay[2], led = 0, leds, oleds;
+
+ if (type == EV_LED) {
+ leds = oleds = KBD_LED_VAL(kbd);
+ switch (code) {
+ case LED_CAPSL:
+ led = CLKED;
+ break;
+ case LED_NUML:
+ led = NLKED;
+ break;
+ case LED_SCROLLL:
+ led = SLKED;
+ break;
+ }
+
+ if (value)
+ leds |= led;
+ else
+ leds &= ~led;
+
+ if (leds != oleds)
+ kbdd_ioctl(kbd, KDSETLED, (caddr_t)&leds);
+
+ } else if (type == EV_REP && code == REP_DELAY) {
+ delay[0] = value;
+ delay[1] = kbd->kb_delay2;
+ kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
+ } else if (type == EV_REP && code == REP_PERIOD) {
+ delay[0] = kbd->kb_delay1;
+ delay[1] = value;
+ kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
+ }
+}
diff --git a/freebsd/sys/dev/kbd/kbdreg.h b/freebsd/sys/dev/kbd/kbdreg.h
index 5caafdda..07c4cfd9 100644
--- a/freebsd/sys/dev/kbd/kbdreg.h
+++ b/freebsd/sys/dev/kbd/kbdreg.h
@@ -253,6 +253,10 @@ keyboard_t *kbd_get_keyboard(int index);
int kbd_configure(int flags);
/* see `kb_config' above for flag bit definitions */
+/* evdev2kbd mappings */
+void kbd_ev_event(keyboard_t *kbd, uint16_t type,
+ uint16_t code, int32_t value);
+
#ifdef KBD_INSTALL_CDEV
/* virtual keyboard cdev driver functions */
diff --git a/freebsd/sys/dev/mii/icsphy.c b/freebsd/sys/dev/mii/icsphy.c
index bde90714..183814ae 100755
--- a/freebsd/sys/dev/mii/icsphy.c
+++ b/freebsd/sys/dev/mii/icsphy.c
@@ -115,9 +115,7 @@ static const struct mii_phydesc icsphys[] = {
MII_PHY_DESC(ICS, 1890),
MII_PHY_DESC(ICS, 1892),
MII_PHY_DESC(ICS, 1893),
-#ifdef __rtems__
MII_PHY_DESC(ICS, 1893C),
-#endif /* __rtems__ */
MII_PHY_END
};
diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c
index 2c3cba3d..cfbce2a5 100644
--- a/freebsd/sys/dev/mmc/mmc.c
+++ b/freebsd/sys/dev/mmc/mmc.c
@@ -1600,10 +1600,13 @@ mmc_discover_cards(struct mmc_softc *sc)
uint32_t raw_cid[4];
struct mmc_ivars *ivar = NULL;
const struct mmc_quirk *quirk;
+ const uint8_t *ext_csd;
device_t child;
int err, host_caps, i, newcard;
uint32_t resp, sec_count, status;
uint16_t rca = 2;
+ int16_t rev;
+ uint8_t card_type;
host_caps = mmcbr_get_caps(sc->dev);
if (bootverbose || mmc_debug)
@@ -1791,6 +1794,7 @@ mmc_discover_cards(struct mmc_softc *sc)
goto free_ivar;
}
+ rev = -1;
/* Only MMC >= 4.x devices support EXT_CSD. */
if (ivar->csd.spec_vers >= 4) {
err = mmc_send_ext_csd(sc->dev, sc->dev,
@@ -1800,11 +1804,10 @@ mmc_discover_cards(struct mmc_softc *sc)
"Error reading EXT_CSD %d\n", err);
goto free_ivar;
}
+ ext_csd = ivar->raw_ext_csd;
+ rev = ext_csd[EXT_CSD_REV];
/* Handle extended capacity from EXT_CSD */
- sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] +
- (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 1] << 8) +
- (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 2] << 16) +
- (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
+ sec_count = le32dec(&ext_csd[EXT_CSD_SEC_CNT]);
if (sec_count != 0) {
ivar->sec_count = sec_count;
ivar->high_cap = 1;
@@ -1812,65 +1815,56 @@ mmc_discover_cards(struct mmc_softc *sc)
/* Find maximum supported bus width. */
ivar->bus_width = mmc_test_bus_width(sc);
/* Get device speeds beyond normal mode. */
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS_52) != 0) {
+ card_type = ext_csd[EXT_CSD_CARD_TYPE];
+ if ((card_type & EXT_CSD_CARD_TYPE_HS_52) != 0) {
setbit(&ivar->timings, bus_timing_hs);
ivar->hs_tran_speed = MMC_TYPE_HS_52_MAX;
- } else if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS_26) != 0) {
+ } else if ((card_type & EXT_CSD_CARD_TYPE_HS_26) != 0) {
setbit(&ivar->timings, bus_timing_hs);
ivar->hs_tran_speed = MMC_TYPE_HS_26_MAX;
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_DDR_52_1_2V) != 0 &&
+ if ((card_type & EXT_CSD_CARD_TYPE_DDR_52_1_2V) != 0 &&
(host_caps & MMC_CAP_SIGNALING_120) != 0) {
setbit(&ivar->timings, bus_timing_mmc_ddr52);
setbit(&ivar->vccq_120, bus_timing_mmc_ddr52);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_DDR_52_1_8V) != 0 &&
+ if ((card_type & EXT_CSD_CARD_TYPE_DDR_52_1_8V) != 0 &&
(host_caps & MMC_CAP_SIGNALING_180) != 0) {
setbit(&ivar->timings, bus_timing_mmc_ddr52);
setbit(&ivar->vccq_180, bus_timing_mmc_ddr52);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS200_1_2V) != 0 &&
+ if ((card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) != 0 &&
(host_caps & MMC_CAP_SIGNALING_120) != 0) {
setbit(&ivar->timings, bus_timing_mmc_hs200);
setbit(&ivar->vccq_120, bus_timing_mmc_hs200);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS200_1_8V) != 0 &&
+ if ((card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) != 0 &&
(host_caps & MMC_CAP_SIGNALING_180) != 0) {
setbit(&ivar->timings, bus_timing_mmc_hs200);
setbit(&ivar->vccq_180, bus_timing_mmc_hs200);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS400_1_2V) != 0 &&
+ if ((card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) != 0 &&
(host_caps & MMC_CAP_SIGNALING_120) != 0 &&
ivar->bus_width == bus_width_8) {
setbit(&ivar->timings, bus_timing_mmc_hs400);
setbit(&ivar->vccq_120, bus_timing_mmc_hs400);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS400_1_8V) != 0 &&
+ if ((card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) != 0 &&
(host_caps & MMC_CAP_SIGNALING_180) != 0 &&
ivar->bus_width == bus_width_8) {
setbit(&ivar->timings, bus_timing_mmc_hs400);
setbit(&ivar->vccq_180, bus_timing_mmc_hs400);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS400_1_2V) != 0 &&
- (ivar->raw_ext_csd[EXT_CSD_STROBE_SUPPORT] &
+ if ((card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) != 0 &&
+ (ext_csd[EXT_CSD_STROBE_SUPPORT] &
EXT_CSD_STROBE_SUPPORT_EN) != 0 &&
(host_caps & MMC_CAP_SIGNALING_120) != 0 &&
ivar->bus_width == bus_width_8) {
setbit(&ivar->timings, bus_timing_mmc_hs400es);
setbit(&ivar->vccq_120, bus_timing_mmc_hs400es);
}
- if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
- EXT_CSD_CARD_TYPE_HS400_1_8V) != 0 &&
- (ivar->raw_ext_csd[EXT_CSD_STROBE_SUPPORT] &
+ if ((card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) != 0 &&
+ (ext_csd[EXT_CSD_STROBE_SUPPORT] &
EXT_CSD_STROBE_SUPPORT_EN) != 0 &&
(host_caps & MMC_CAP_SIGNALING_180) != 0 &&
ivar->bus_width == bus_width_8) {
@@ -1882,13 +1876,13 @@ mmc_discover_cards(struct mmc_softc *sc)
* units of 10 ms), defaulting to 500 ms.
*/
ivar->cmd6_time = 500 * 1000;
- if (ivar->raw_ext_csd[EXT_CSD_REV] >= 6)
+ if (rev >= 6)
ivar->cmd6_time = 10 *
- ivar->raw_ext_csd[EXT_CSD_GEN_CMD6_TIME];
+ ext_csd[EXT_CSD_GEN_CMD6_TIME];
/* Handle HC erase sector size. */
- if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) {
+ if (ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) {
ivar->erase_sector = 1024 *
- ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE];
+ ext_csd[EXT_CSD_ERASE_GRP_SIZE];
err = mmc_switch(sc->dev, sc->dev, ivar->rca,
EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_ERASE_GRP_DEF,
@@ -1903,8 +1897,7 @@ mmc_discover_cards(struct mmc_softc *sc)
}
}
- mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid,
- ivar->raw_ext_csd[EXT_CSD_REV] >= 5);
+ mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid, rev >= 5);
child_common:
for (quirk = &mmc_quirks[0]; quirk->mid != 0x0; quirk++) {
diff --git a/freebsd/sys/dev/mmc/mmcbrvar.h b/freebsd/sys/dev/mmc/mmcbrvar.h
index 6e4bec70..acddd3a3 100644
--- a/freebsd/sys/dev/mmc/mmcbrvar.h
+++ b/freebsd/sys/dev/mmc/mmcbrvar.h
@@ -97,7 +97,6 @@ MMCBR_ACCESSOR(host_ocr, HOST_OCR, int)
MMCBR_ACCESSOR(mode, MODE, int)
MMCBR_ACCESSOR(ocr, OCR, int)
MMCBR_ACCESSOR(power_mode, POWER_MODE, int)
-MMCBR_ACCESSOR(retune_req, RETUNE_REQ, int)
MMCBR_ACCESSOR(vdd, VDD, int)
MMCBR_ACCESSOR(vccq, VCCQ, int)
MMCBR_ACCESSOR(caps, CAPS, int)
@@ -106,6 +105,20 @@ MMCBR_ACCESSOR(max_data, MAX_DATA, int)
MMCBR_ACCESSOR(max_busy_timeout, MAX_BUSY_TIMEOUT, u_int)
static int __inline
+mmcbr_get_retune_req(device_t dev)
+{
+ uintptr_t v;
+
+ if (__predict_false(BUS_READ_IVAR(device_get_parent(dev), dev,
+ MMCBR_IVAR_RETUNE_REQ, &v) != 0))
+ return (retune_req_none);
+ return ((int)v);
+}
+
+/*
+ * Convenience wrappers for the mmcbr interface
+ */
+static int __inline
mmcbr_update_ios(device_t dev)
{
diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c
index 263da55d..e469c1d5 100644
--- a/freebsd/sys/dev/mmc/mmcsd.c
+++ b/freebsd/sys/dev/mmc/mmcsd.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/endian.h>
#include <sys/fcntl.h>
#include <sys/ioccom.h>
#include <sys/kernel.h>
@@ -477,7 +478,7 @@ mmcsd_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
sc->mmcbus = mmcbus = device_get_parent(dev);
- sc->mode = mmcbr_get_mode(mmcbus);
+ sc->mode = mmc_get_card_type(dev);
/*
* Note that in principle with an SDHCI-like re-tuning implementation,
* the maximum data size can change at runtime due to a device removal/
@@ -542,10 +543,7 @@ mmcsd_attach(device_t dev)
* disabled.
*/
if (rev >= 6 && mmcsd_cache != 0) {
- size = ext_csd[EXT_CSD_CACHE_SIZE] |
- ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
- ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
- ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+ size = le32dec(&ext_csd[EXT_CSD_CACHE_SIZE]);
if (bootverbose)
device_printf(dev, "cache size %juKB\n", size);
if (size > 0) {
@@ -591,10 +589,8 @@ mmcsd_attach(device_t dev)
size *= erase_size * wp_size;
if (size != mmc_get_media_size(dev) * sector_size) {
sc->enh_size = size;
- sc->enh_base = (ext_csd[EXT_CSD_ENH_START_ADDR] +
- (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
- (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
- (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24)) *
+ sc->enh_base =
+ le32dec(&ext_csd[EXT_CSD_ENH_START_ADDR]) *
(sc->high_cap == 0 ? MMC_SECTOR_SIZE : 1);
} else if (bootverbose)
device_printf(dev,
@@ -1578,7 +1574,7 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
memset(&cmd, 0, sizeof(cmd));
cmd.mrq = &req;
req.cmd = &cmd;
- if (mmc_get_card_type(dev) == mode_sd)
+ if (sc->mode == mode_sd)
cmd.opcode = SD_ERASE_WR_BLK_START;
else
cmd.opcode = MMC_ERASE_GROUP_START;
@@ -1597,7 +1593,7 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
req.cmd = &cmd;
- if (mmc_get_card_type(dev) == mode_sd)
+ if (sc->mode == mode_sd)
cmd.opcode = SD_ERASE_WR_BLK_END;
else
cmd.opcode = MMC_ERASE_GROUP_END;
diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h
index 169f22d1..747767ce 100644
--- a/freebsd/sys/dev/nvme/nvme.h
+++ b/freebsd/sys/dev/nvme/nvme.h
@@ -110,13 +110,9 @@
/* Command field definitions */
-#define NVME_CMD_OPC_SHIFT (0)
-#define NVME_CMD_OPC_MASK (0xFF)
#define NVME_CMD_FUSE_SHIFT (8)
#define NVME_CMD_FUSE_MASK (0x3)
-#define NVME_CMD_SET_OPC(opc) (htole16(((uint16_t)(opc) & NVME_CMD_OPC_MASK) << NVME_CMD_OPC_SHIFT))
-
#define NVME_STATUS_P_SHIFT (0)
#define NVME_STATUS_P_MASK (0x1)
#define NVME_STATUS_SC_SHIFT (1)
@@ -428,7 +424,8 @@ _Static_assert(sizeof(struct nvme_registers) == 0x1008, "bad size for nvme_regis
struct nvme_command
{
/* dword 0 */
- uint16_t opc_fuse; /* opcode, fused operation */
+ uint8_t opc; /* opcode */
+ uint8_t fuse; /* fused operation */
uint16_t cid; /* command identifier */
/* dword 1 */
@@ -1288,7 +1285,7 @@ static inline
void nvme_ns_flush_cmd(struct nvme_command *cmd, uint32_t nsid)
{
- cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FLUSH);
+ cmd->opc = NVME_OPC_FLUSH;
cmd->nsid = htole32(nsid);
}
@@ -1296,7 +1293,7 @@ static inline
void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint32_t nsid,
uint64_t lba, uint32_t count)
{
- cmd->opc_fuse = NVME_CMD_SET_OPC(rwcmd);
+ cmd->opc = rwcmd;
cmd->nsid = htole32(nsid);
cmd->cdw10 = htole32(lba & 0xffffffffu);
cmd->cdw11 = htole32(lba >> 32);
@@ -1321,7 +1318,7 @@ static inline
void nvme_ns_trim_cmd(struct nvme_command *cmd, uint32_t nsid,
uint32_t num_ranges)
{
- cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DATASET_MANAGEMENT);
+ cmd->opc = NVME_OPC_DATASET_MANAGEMENT;
cmd->nsid = htole32(nsid);
cmd->cdw10 = htole32(num_ranges - 1);
cmd->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE);
diff --git a/freebsd/sys/dev/ofw/ofw_bus_subr.c b/freebsd/sys/dev/ofw/ofw_bus_subr.c
index 5038bb03..5a76e555 100644
--- a/freebsd/sys/dev/ofw/ofw_bus_subr.c
+++ b/freebsd/sys/dev/ofw/ofw_bus_subr.c
@@ -93,6 +93,9 @@ ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf,
{
*buf = '\0';
+ if (!ofw_bus_status_okay(child))
+ return (0);
+
if (ofw_bus_get_name(child) != NULL) {
strlcat(buf, "name=", buflen);
strlcat(buf, ofw_bus_get_name(child), buflen);
@@ -102,6 +105,7 @@ ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf,
strlcat(buf, " compat=", buflen);
strlcat(buf, ofw_bus_get_compat(child), buflen);
}
+
return (0);
};
diff --git a/freebsd/sys/dev/ofw/ofw_fdt.c b/freebsd/sys/dev/ofw/ofw_fdt.c
index b1bbadee..d05a5dc1 100644
--- a/freebsd/sys/dev/ofw/ofw_fdt.c
+++ b/freebsd/sys/dev/ofw/ofw_fdt.c
@@ -287,8 +287,6 @@ ofw_fdt_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
/* Emulate the 'name' property */
name = fdt_get_name(fdtp, offset, &len);
strncpy(buf, name, buflen);
- if (len + 1 > buflen)
- len = buflen;
return (len + 1);
}
@@ -307,9 +305,8 @@ ofw_fdt_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
if (prop == NULL)
return (-1);
- if (len > buflen)
- len = buflen;
- bcopy(prop, buf, len);
+ bcopy(prop, buf, min(len, buflen));
+
return (len);
}
diff --git a/freebsd/sys/dev/ofw/ofw_subr.c b/freebsd/sys/dev/ofw/ofw_subr.c
index 8359485e..4a20727c 100644
--- a/freebsd/sys/dev/ofw/ofw_subr.c
+++ b/freebsd/sys/dev/ofw/ofw_subr.c
@@ -34,6 +34,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/boot.h>
#include <sys/bus.h>
#include <sys/libkern.h>
#include <sys/reboot.h>
@@ -63,7 +64,9 @@ get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
res = OF_getprop(node, "device_type", type, sizeof(type));
if (res != -1) {
type[sizeof(type) - 1] = '\0';
- pci = (strcmp(type, "pci") == 0) ? 1 : 0;
+ if (strcmp(type, "pci") == 0 ||
+ strcmp(type, "pciex")== 0)
+ pci = 1;
}
}
if (addrp != NULL)
@@ -172,7 +175,7 @@ ofw_reg_to_paddr(phandle_t dev, int regno, bus_addr_t *paddr,
}
KASSERT(addr <= BUS_SPACE_MAXADDR,
- ("Bus sddress is too large: %jx", (uintmax_t)addr));
+ ("Bus address is too large: %jx", (uintmax_t)addr));
KASSERT(size <= BUS_SPACE_MAXSIZE,
("Bus size is too large: %jx", (uintmax_t)size));
@@ -184,44 +187,6 @@ ofw_reg_to_paddr(phandle_t dev, int regno, bus_addr_t *paddr,
return (0);
}
-/* Parse cmd line args as env - copied from xlp_machdep. */
-/* XXX-BZ this should really be centrally provided for all (boot) code. */
-static void
-_parse_bootargs(char *cmdline)
-{
- char *n, *v;
-
- while ((v = strsep(&cmdline, " \n")) != NULL) {
- if (*v == '\0')
- continue;
- if (*v == '-') {
- while (*v != '\0') {
- v++;
- switch (*v) {
- case 'a': boothowto |= RB_ASKNAME; break;
- /* Someone should simulate that ;-) */
- case 'C': boothowto |= RB_CDROM; break;
- case 'd': boothowto |= RB_KDB; break;
- case 'D': boothowto |= RB_MULTIPLE; break;
- case 'm': boothowto |= RB_MUTE; break;
- case 'g': boothowto |= RB_GDB; break;
- case 'h': boothowto |= RB_SERIAL; break;
- case 'p': boothowto |= RB_PAUSE; break;
- case 'r': boothowto |= RB_DFLTROOT; break;
- case 's': boothowto |= RB_SINGLE; break;
- case 'v': boothowto |= RB_VERBOSE; break;
- }
- }
- } else {
- n = strsep(&v, "=");
- if (v == NULL)
- kern_setenv(n, "1");
- else
- kern_setenv(n, v);
- }
- }
-}
-
/*
* This is intended to be called early on, right after the OF system is
* initialized, so pmap may not be up yet.
@@ -238,7 +203,7 @@ ofw_parse_bootargs(void)
return (chosen);
if ((err = OF_getprop(chosen, "bootargs", buf, sizeof(buf))) != -1) {
- _parse_bootargs(buf);
+ boothowto |= boot_parse_cmdline(buf);
return (0);
}
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index 55a21320..512e8636 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -401,6 +401,11 @@ static int pci_enable_ari = 1;
SYSCTL_INT(_hw_pci, OID_AUTO, enable_ari, CTLFLAG_RDTUN, &pci_enable_ari,
0, "Enable support for PCIe Alternative RID Interpretation");
+static int pci_clear_aer_on_attach = 0;
+SYSCTL_INT(_hw_pci, OID_AUTO, clear_aer_on_attach, CTLFLAG_RWTUN,
+ &pci_clear_aer_on_attach, 0,
+ "Clear port and device AER state on driver attach");
+
static int
pci_has_quirk(uint32_t devid, int quirk)
{
@@ -4214,17 +4219,98 @@ pci_create_iov_child_method(device_t bus, device_t pf, uint16_t rid,
}
#endif
+static void
+pci_add_child_clear_aer(device_t dev, struct pci_devinfo *dinfo)
+{
+ int aer;
+ uint32_t r;
+ uint16_t r2;
+
+ if (dinfo->cfg.pcie.pcie_location != 0 &&
+ dinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT) {
+ r2 = pci_read_config(dev, dinfo->cfg.pcie.pcie_location +
+ PCIER_ROOT_CTL, 2);
+ r2 &= ~(PCIEM_ROOT_CTL_SERR_CORR |
+ PCIEM_ROOT_CTL_SERR_NONFATAL | PCIEM_ROOT_CTL_SERR_FATAL);
+ pci_write_config(dev, dinfo->cfg.pcie.pcie_location +
+ PCIER_ROOT_CTL, r2, 2);
+ }
+ if (pci_find_extcap(dev, PCIZ_AER, &aer) == 0) {
+ r = pci_read_config(dev, aer + PCIR_AER_UC_STATUS, 4);
+ pci_write_config(dev, aer + PCIR_AER_UC_STATUS, r, 4);
+ if (r != 0 && bootverbose) {
+ pci_printf(&dinfo->cfg,
+ "clearing AER UC 0x%08x -> 0x%08x\n",
+ r, pci_read_config(dev, aer + PCIR_AER_UC_STATUS,
+ 4));
+ }
+
+ r = pci_read_config(dev, aer + PCIR_AER_UC_MASK, 4);
+ r &= ~(PCIM_AER_UC_TRAINING_ERROR |
+ PCIM_AER_UC_DL_PROTOCOL_ERROR |
+ PCIM_AER_UC_SURPRISE_LINK_DOWN |
+ PCIM_AER_UC_POISONED_TLP |
+ PCIM_AER_UC_FC_PROTOCOL_ERROR |
+ PCIM_AER_UC_COMPLETION_TIMEOUT |
+ PCIM_AER_UC_COMPLETER_ABORT |
+ PCIM_AER_UC_UNEXPECTED_COMPLETION |
+ PCIM_AER_UC_RECEIVER_OVERFLOW |
+ PCIM_AER_UC_MALFORMED_TLP |
+ PCIM_AER_UC_ECRC_ERROR |
+ PCIM_AER_UC_UNSUPPORTED_REQUEST |
+ PCIM_AER_UC_ACS_VIOLATION |
+ PCIM_AER_UC_INTERNAL_ERROR |
+ PCIM_AER_UC_MC_BLOCKED_TLP |
+ PCIM_AER_UC_ATOMIC_EGRESS_BLK |
+ PCIM_AER_UC_TLP_PREFIX_BLOCKED);
+ pci_write_config(dev, aer + PCIR_AER_UC_MASK, r, 4);
+
+ r = pci_read_config(dev, aer + PCIR_AER_COR_STATUS, 4);
+ pci_write_config(dev, aer + PCIR_AER_COR_STATUS, r, 4);
+ if (r != 0 && bootverbose) {
+ pci_printf(&dinfo->cfg,
+ "clearing AER COR 0x%08x -> 0x%08x\n",
+ r, pci_read_config(dev, aer + PCIR_AER_COR_STATUS,
+ 4));
+ }
+
+ r = pci_read_config(dev, aer + PCIR_AER_COR_MASK, 4);
+ r &= ~(PCIM_AER_COR_RECEIVER_ERROR |
+ PCIM_AER_COR_BAD_TLP |
+ PCIM_AER_COR_BAD_DLLP |
+ PCIM_AER_COR_REPLAY_ROLLOVER |
+ PCIM_AER_COR_REPLAY_TIMEOUT |
+ PCIM_AER_COR_ADVISORY_NF_ERROR |
+ PCIM_AER_COR_INTERNAL_ERROR |
+ PCIM_AER_COR_HEADER_LOG_OVFLOW);
+ pci_write_config(dev, aer + PCIR_AER_COR_MASK, r, 4);
+
+ r = pci_read_config(dev, dinfo->cfg.pcie.pcie_location +
+ PCIER_DEVICE_CTL, 2);
+ r |= PCIEM_CTL_COR_ENABLE | PCIEM_CTL_NFER_ENABLE |
+ PCIEM_CTL_FER_ENABLE | PCIEM_CTL_URR_ENABLE;
+ pci_write_config(dev, dinfo->cfg.pcie.pcie_location +
+ PCIER_DEVICE_CTL, r, 2);
+ }
+}
+
void
pci_add_child(device_t bus, struct pci_devinfo *dinfo)
{
- dinfo->cfg.dev = device_add_child(bus, NULL, -1);
- device_set_ivars(dinfo->cfg.dev, dinfo);
+ device_t dev;
+
+ dinfo->cfg.dev = dev = device_add_child(bus, NULL, -1);
+ device_set_ivars(dev, dinfo);
resource_list_init(&dinfo->resources);
- pci_cfg_save(dinfo->cfg.dev, dinfo, 0);
- pci_cfg_restore(dinfo->cfg.dev, dinfo);
+ pci_cfg_save(dev, dinfo, 0);
+ pci_cfg_restore(dev, dinfo);
pci_print_verbose(dinfo);
- pci_add_resources(bus, dinfo->cfg.dev, 0, 0);
+ pci_add_resources(bus, dev, 0, 0);
pci_child_added(dinfo->cfg.dev);
+
+ if (pci_clear_aer_on_attach)
+ pci_add_child_clear_aer(dev, dinfo);
+
EVENTHANDLER_INVOKE(pci_add_device, dinfo->cfg.dev);
}
@@ -6263,3 +6349,164 @@ pcie_flr(device_t dev, u_int max_delay, bool force)
pci_printf(&dinfo->cfg, "Transactions pending after FLR!\n");
return (true);
}
+
+const struct pci_device_table *
+pci_match_device(device_t child, const struct pci_device_table *id, size_t nelt)
+{
+ bool match;
+ uint16_t vendor, device, subvendor, subdevice, class, subclass, revid;
+
+ vendor = pci_get_vendor(child);
+ device = pci_get_device(child);
+ subvendor = pci_get_subvendor(child);
+ subdevice = pci_get_subdevice(child);
+ class = pci_get_class(child);
+ subclass = pci_get_subclass(child);
+ revid = pci_get_revid(child);
+ while (nelt-- > 0) {
+ match = true;
+ if (id->match_flag_vendor)
+ match &= vendor == id->vendor;
+ if (id->match_flag_device)
+ match &= device == id->device;
+ if (id->match_flag_subvendor)
+ match &= subvendor == id->subvendor;
+ if (id->match_flag_subdevice)
+ match &= subdevice == id->subdevice;
+ if (id->match_flag_class)
+ match &= class == id->class_id;
+ if (id->match_flag_subclass)
+ match &= subclass == id->subclass;
+ if (id->match_flag_revid)
+ match &= revid == id->revid;
+ if (match)
+ return (id);
+ id++;
+ }
+ return (NULL);
+}
+
+static void
+pci_print_faulted_dev_name(const struct pci_devinfo *dinfo)
+{
+ const char *dev_name;
+ device_t dev;
+
+ dev = dinfo->cfg.dev;
+ printf("pci%d:%d:%d:%d", dinfo->cfg.domain, dinfo->cfg.bus,
+ dinfo->cfg.slot, dinfo->cfg.func);
+ dev_name = device_get_name(dev);
+ if (dev_name != NULL)
+ printf(" (%s%d)", dev_name, device_get_unit(dev));
+}
+
+void
+pci_print_faulted_dev(void)
+{
+ struct pci_devinfo *dinfo;
+ device_t dev;
+ int aer, i;
+ uint32_t r1, r2;
+ uint16_t status;
+
+ STAILQ_FOREACH(dinfo, &pci_devq, pci_links) {
+ dev = dinfo->cfg.dev;
+ status = pci_read_config(dev, PCIR_STATUS, 2);
+ status &= PCIM_STATUS_MDPERR | PCIM_STATUS_STABORT |
+ PCIM_STATUS_RTABORT | PCIM_STATUS_RMABORT |
+ PCIM_STATUS_SERR | PCIM_STATUS_PERR;
+ if (status != 0) {
+ pci_print_faulted_dev_name(dinfo);
+ printf(" error 0x%04x\n", status);
+ }
+ if (dinfo->cfg.pcie.pcie_location != 0) {
+ status = pci_read_config(dev,
+ dinfo->cfg.pcie.pcie_location +
+ PCIER_DEVICE_STA, 2);
+ if ((status & (PCIEM_STA_CORRECTABLE_ERROR |
+ PCIEM_STA_NON_FATAL_ERROR | PCIEM_STA_FATAL_ERROR |
+ PCIEM_STA_UNSUPPORTED_REQ)) != 0) {
+ pci_print_faulted_dev_name(dinfo);
+ printf(" PCIe DEVCTL 0x%04x DEVSTA 0x%04x\n",
+ pci_read_config(dev,
+ dinfo->cfg.pcie.pcie_location +
+ PCIER_DEVICE_CTL, 2),
+ status);
+ }
+ }
+ if (pci_find_extcap(dev, PCIZ_AER, &aer) == 0) {
+ r1 = pci_read_config(dev, aer + PCIR_AER_UC_STATUS, 4);
+ r2 = pci_read_config(dev, aer + PCIR_AER_COR_STATUS, 4);
+ if (r1 != 0 || r2 != 0) {
+ pci_print_faulted_dev_name(dinfo);
+ printf(" AER UC 0x%08x Mask 0x%08x Svr 0x%08x\n"
+ " COR 0x%08x Mask 0x%08x Ctl 0x%08x\n",
+ r1, pci_read_config(dev, aer +
+ PCIR_AER_UC_MASK, 4),
+ pci_read_config(dev, aer +
+ PCIR_AER_UC_SEVERITY, 4),
+ r2, pci_read_config(dev, aer +
+ PCIR_AER_COR_MASK, 4),
+ pci_read_config(dev, aer +
+ PCIR_AER_CAP_CONTROL, 4));
+ for (i = 0; i < 4; i++) {
+ r1 = pci_read_config(dev, aer +
+ PCIR_AER_HEADER_LOG + i * 4, 4);
+ printf(" HL%d: 0x%08x\n", i, r1);
+ }
+ }
+ }
+ }
+}
+
+#ifdef DDB
+DB_SHOW_COMMAND(pcierr, pci_print_faulted_dev_db)
+{
+
+ pci_print_faulted_dev();
+}
+
+static void
+db_clear_pcie_errors(const struct pci_devinfo *dinfo)
+{
+ device_t dev;
+ int aer;
+ uint32_t r;
+
+ dev = dinfo->cfg.dev;
+ r = pci_read_config(dev, dinfo->cfg.pcie.pcie_location +
+ PCIER_DEVICE_STA, 2);
+ pci_write_config(dev, dinfo->cfg.pcie.pcie_location +
+ PCIER_DEVICE_STA, r, 2);
+
+ if (pci_find_extcap(dev, PCIZ_AER, &aer) != 0)
+ return;
+ r = pci_read_config(dev, aer + PCIR_AER_UC_STATUS, 4);
+ if (r != 0)
+ pci_write_config(dev, aer + PCIR_AER_UC_STATUS, r, 4);
+ r = pci_read_config(dev, aer + PCIR_AER_COR_STATUS, 4);
+ if (r != 0)
+ pci_write_config(dev, aer + PCIR_AER_COR_STATUS, r, 4);
+}
+
+DB_COMMAND(pci_clearerr, db_pci_clearerr)
+{
+ struct pci_devinfo *dinfo;
+ device_t dev;
+ uint16_t status, status1;
+
+ STAILQ_FOREACH(dinfo, &pci_devq, pci_links) {
+ dev = dinfo->cfg.dev;
+ status1 = status = pci_read_config(dev, PCIR_STATUS, 2);
+ status1 &= PCIM_STATUS_MDPERR | PCIM_STATUS_STABORT |
+ PCIM_STATUS_RTABORT | PCIM_STATUS_RMABORT |
+ PCIM_STATUS_SERR | PCIM_STATUS_PERR;
+ if (status1 != 0) {
+ status &= ~status1;
+ pci_write_config(dev, PCIR_STATUS, status, 2);
+ }
+ if (dinfo->cfg.pcie.pcie_location != 0)
+ db_clear_pcie_errors(dinfo);
+ }
+}
+#endif
diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c
index c9d500a8..b3a2e9e2 100644
--- a/freebsd/sys/dev/pci/pci_user.c
+++ b/freebsd/sys/dev/pci/pci_user.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_bus.h> /* XXX trim includes */
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -41,13 +42,19 @@ __FBSDID("$FreeBSD$");
#include <sys/fcntl.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/mman.h>
#include <sys/proc.h>
#include <sys/queue.h>
-#include <sys/types.h>
+#include <sys/rwlock.h>
+#include <sys/sglist.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
#include <sys/bus.h>
#include <machine/bus.h>
@@ -441,6 +448,14 @@ pci_conf_match(u_long cmd, struct pci_match_conf *matches, int num_matches,
}
}
+/*
+ * Like PVE_NEXT but takes an explicit length since 'pve' is a user
+ * pointer that cannot be dereferenced.
+ */
+#define PVE_NEXT_LEN(pve, datalen) \
+ ((struct pci_vpd_element *)((char *)(pve) + \
+ sizeof(struct pci_vpd_element) + (datalen)))
+
static int
pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio)
{
@@ -489,7 +504,7 @@ pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio)
strlen(vpd->vpd_ident));
if (error)
return (error);
- vpd_user = PVE_NEXT(vpd_user);
+ vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen);
vpd_element.pve_flags = 0;
for (i = 0; i < vpd->vpd_rocnt; i++) {
vpd_element.pve_keyword[0] = vpd->vpd_ros[i].keyword[0];
@@ -502,7 +517,7 @@ pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio)
vpd->vpd_ros[i].len);
if (error)
return (error);
- vpd_user = PVE_NEXT(vpd_user);
+ vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen);
}
vpd_element.pve_flags = PVE_FLAG_RW;
for (i = 0; i < vpd->vpd_wcnt; i++) {
@@ -516,7 +531,7 @@ pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio)
vpd->vpd_w[i].len);
if (error)
return (error);
- vpd_user = PVE_NEXT(vpd_user);
+ vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen);
}
KASSERT((char *)vpd_user - (char *)lvio->plvi_data == len,
("length mismatch"));
@@ -698,6 +713,79 @@ pci_conf_for_copyout(const struct pci_conf *pcp, union pci_conf_union *pcup,
}
}
+#ifndef __rtems__
+static int
+pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm)
+{
+ vm_map_t map;
+ vm_object_t obj;
+ struct thread *td;
+ struct sglist *sg;
+ struct pci_map *pm;
+ vm_paddr_t pbase;
+ vm_size_t plen;
+ vm_offset_t addr;
+ vm_prot_t prot;
+ int error, flags;
+
+ td = curthread;
+ map = &td->td_proc->p_vmspace->vm_map;
+ if ((pbm->pbm_flags & ~(PCIIO_BAR_MMAP_FIXED | PCIIO_BAR_MMAP_EXCL |
+ PCIIO_BAR_MMAP_RW | PCIIO_BAR_MMAP_ACTIVATE)) != 0 ||
+ pbm->pbm_memattr != (vm_memattr_t)pbm->pbm_memattr ||
+ !pmap_is_valid_memattr(map->pmap, pbm->pbm_memattr))
+ return (EINVAL);
+
+ /* Fetch the BAR physical base and length. */
+ pm = pci_find_bar(pcidev, pbm->pbm_reg);
+ if (pm == NULL)
+ return (EINVAL);
+ if (!pci_bar_enabled(pcidev, pm))
+ return (EBUSY); /* XXXKIB enable if _ACTIVATE */
+ if (!PCI_BAR_MEM(pm->pm_value))
+ return (EIO);
+ pbase = trunc_page(pm->pm_value);
+ plen = round_page(pm->pm_value + ((pci_addr_t)1 << pm->pm_size)) -
+ pbase;
+ prot = VM_PROT_READ | (((pbm->pbm_flags & PCIIO_BAR_MMAP_RW) != 0) ?
+ VM_PROT_WRITE : 0);
+
+ /* Create vm structures and mmap. */
+ sg = sglist_alloc(1, M_WAITOK);
+ error = sglist_append_phys(sg, pbase, plen);
+ if (error != 0)
+ goto out;
+ obj = vm_pager_allocate(OBJT_SG, sg, plen, prot, 0, td->td_ucred);
+ if (obj == NULL) {
+ error = EIO;
+ goto out;
+ }
+ obj->memattr = pbm->pbm_memattr;
+ flags = MAP_SHARED;
+ addr = 0;
+ if ((pbm->pbm_flags & PCIIO_BAR_MMAP_FIXED) != 0) {
+ addr = (uintptr_t)pbm->pbm_map_base;
+ flags |= MAP_FIXED;
+ }
+ if ((pbm->pbm_flags & PCIIO_BAR_MMAP_EXCL) != 0)
+ flags |= MAP_CHECK_EXCL;
+ error = vm_mmap_object(map, &addr, plen, prot, prot, flags, obj, 0,
+ FALSE, td);
+ if (error != 0) {
+ vm_object_deallocate(obj);
+ goto out;
+ }
+ pbm->pbm_map_base = (void *)addr;
+ pbm->pbm_map_length = plen;
+ pbm->pbm_bar_off = pm->pm_value - pbase;
+ pbm->pbm_bar_length = (pci_addr_t)1 << pm->pm_size;
+
+out:
+ sglist_free(sg);
+ return (error);
+}
+#endif /* __rtems__ */
+
static int
pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
@@ -711,6 +799,9 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
struct pci_list_vpd_io *lvio;
struct pci_match_conf *pattern_buf;
struct pci_map *pm;
+#ifndef __rtems__
+ struct pci_bar_mmap *pbm;
+#endif /* __rtems__ */
size_t confsz, iolen;
int error, ionum, i, num_patterns;
union pci_conf_union pcu;
@@ -1055,6 +1146,20 @@ getconfexit:
}
error = pci_list_vpd(pcidev, lvio);
break;
+
+#ifndef __rtems__
+ case PCIOCBARMMAP:
+ pbm = (struct pci_bar_mmap *)data;
+ if ((flag & FWRITE) == 0 &&
+ (pbm->pbm_flags & PCIIO_BAR_MMAP_RW) != 0)
+ return (EPERM);
+ pcidev = pci_find_dbsf(pbm->pbm_sel.pc_domain,
+ pbm->pbm_sel.pc_bus, pbm->pbm_sel.pc_dev,
+ pbm->pbm_sel.pc_func);
+ error = pcidev == NULL ? ENODEV : pci_bar_mmap(pcidev, pbm);
+ break;
+#endif /* __rtems__ */
+
default:
error = ENOTTY;
break;
diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h
index 492b7117..21d9bd03 100644
--- a/freebsd/sys/dev/pci/pcivar.h
+++ b/freebsd/sys/dev/pci/pcivar.h
@@ -259,6 +259,66 @@ typedef struct {
extern uint32_t pci_numdevs;
+struct pci_device_table {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint16_t
+ match_flag_vendor:1,
+ match_flag_device:1,
+ match_flag_subvendor:1,
+ match_flag_subdevice:1,
+ match_flag_class:1,
+ match_flag_subclass:1,
+ match_flag_revid:1,
+ match_flag_unused:9;
+#else
+ uint16_t
+ match_flag_unused:9,
+ match_flag_revid:1,
+ match_flag_subclass:1,
+ match_flag_class:1,
+ match_flag_subdevice:1,
+ match_flag_subvendor:1,
+ match_flag_device:1,
+ match_flag_vendor:1;
+#endif
+ uint16_t vendor;
+ uint16_t device;
+ uint16_t subvendor;
+ uint16_t subdevice;
+ uint16_t class_id;
+ uint16_t subclass;
+ uint16_t revid;
+ uint16_t unused;
+ uintptr_t driver_data;
+ char *descr;
+};
+
+#define PCI_DEV(v, d) \
+ .match_flag_vendor = 1, .vendor = (v), \
+ .match_flag_device = 1, .device = (d)
+#define PCI_SUBDEV(sv, sd) \
+ .match_flag_subvendor = 1, .subvendor = (sv), \
+ .match_flag_subdevice = 1, .subdevice = (sd)
+#define PCI_CLASS(x) \
+ .match_flag_class = 1, .class_id = (x)
+#define PCI_SUBCLASS(x) \
+ .match_flag_subclass = 1, .subclass = (x)
+#define PCI_REVID(x) \
+ .match_flag_revid = 1, .revid = (x)
+#define PCI_DESCR(x) \
+ .descr = (x)
+#define PCI_PNP_STR \
+ "M16:mask;U16:vendor;U16:device;U16:subvendor;U16:subdevice;" \
+ "U16:class;U16:subclass;U16:revid;"
+#define PCI_PNP_INFO(table) \
+ MODULE_PNP_INFO(PCI_PNP_STR, pci, table, table, sizeof(table[0]), \
+ sizeof(table) / sizeof(table[0]))
+
+const struct pci_device_table *pci_match_device(device_t child,
+ const struct pci_device_table *id, size_t nelt);
+#define PCI_MATCH(child, table) \
+ pci_match_device(child, (table), nitems(table));
+
/* Only if the prerequisites are present */
#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_)
struct pci_devinfo {
@@ -416,7 +476,7 @@ pci_get_vpd_readonly(device_t dev, const char *kw, const char **vptr)
static __inline int
pci_is_vga_ioport_range(rman_res_t start, rman_res_t end)
{
-
+
return (((start >= 0x3b0 && end <= 0x3bb) ||
(start >= 0x3c0 && end <= 0x3df)) ? 1 : 0);
}
@@ -622,6 +682,8 @@ bool pcie_flr(device_t dev, u_int max_delay, bool force);
int pcie_get_max_completion_timeout(device_t dev);
bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay);
+void pci_print_faulted_dev(void);
+
#ifdef BUS_SPACE_MAXADDR
#if (BUS_SPACE_MAXADDR > 0xFFFFFFFF)
#define PCI_DMA_BOUNDARY 0x100000000
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_reg.h b/freebsd/sys/dev/rtwn/rtl8812a/r12a_reg.h
index 41cc160f..581e7078 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_reg.h
+++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_reg.h
@@ -58,6 +58,16 @@
/* Bits for R92C_LEDCFG2. */
#define R12A_LEDCFG2_ENA 0x20
+/* Bits for R12A_RXDMA_PRO. */
+#define R12A_DMA_MODE 0x02
+#define R12A_BURST_CNT_M 0x0c
+#define R12A_BURST_CNT_S 2
+#define R12A_BURST_SZ_M 0x30
+#define R12A_BURST_SZ_S 4
+#define R12A_BURST_SZ_USB3 0
+#define R12A_BURST_SZ_USB2 1
+#define R12A_BURST_SZ_USB1 2
+
/* Bits for R12A_CCK_CHECK. */
#define R12A_CCK_CHECK_BCN1 0x20
#define R12A_CCK_CHECK_5GHZ 0x80
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au.h b/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au.h
index 55d132c7..1ea08a2d 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au.h
+++ b/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au.h
@@ -37,6 +37,7 @@
*/
/* r12au_init.c */
void r12au_init_rx_agg(struct rtwn_softc *);
+void r12au_init_burstlen_usb2(struct rtwn_softc *);
void r12au_init_burstlen(struct rtwn_softc *);
void r12au_init_ampdu_fwhw(struct rtwn_softc *);
void r12au_init_ampdu(struct rtwn_softc *);
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_init.c b/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_init.c
index 29016424..26a83ce9 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_init.c
+++ b/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_init.c
@@ -74,19 +74,32 @@ r12au_init_rx_agg(struct rtwn_softc *sc)
}
void
+r12au_init_burstlen_usb2(struct rtwn_softc *sc)
+{
+ const uint8_t dma_count = R12A_DMA_MODE | SM(R12A_BURST_CNT, 3);
+
+ if ((rtwn_read_1(sc, R92C_USB_INFO) & 0x30) == 0) {
+ /* Set burst packet length to 512 B. */
+ rtwn_setbits_1(sc, R12A_RXDMA_PRO, R12A_BURST_SZ_M,
+ dma_count | SM(R12A_BURST_SZ, R12A_BURST_SZ_USB2));
+ } else {
+ /* Set burst packet length to 64 B. */
+ rtwn_setbits_1(sc, R12A_RXDMA_PRO, R12A_BURST_SZ_M,
+ dma_count | SM(R12A_BURST_SZ, R12A_BURST_SZ_USB1));
+ }
+}
+
+void
r12au_init_burstlen(struct rtwn_softc *sc)
{
- if (rtwn_read_1(sc, R92C_TYPE_ID + 3) & 0x80) {
- if ((rtwn_read_1(sc, R92C_USB_INFO) & 0x30) == 0) {
- /* Set burst packet length to 512 B. */
- rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x20, 0x1e);
- } else {
- /* Set burst packet length to 64 B. */
- rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x10, 0x2e);
- }
- } else { /* USB 3.0 */
+ const uint8_t dma_count = R12A_DMA_MODE | SM(R12A_BURST_CNT, 3);
+
+ if (rtwn_read_1(sc, R92C_TYPE_ID + 3) & 0x80)
+ r12au_init_burstlen_usb2(sc);
+ else { /* USB 3.0 */
/* Set burst packet length to 1 KB. */
- rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x30, 0x0e);
+ rtwn_setbits_1(sc, R12A_RXDMA_PRO, R12A_BURST_SZ_M,
+ dma_count | SM(R12A_BURST_SZ, R12A_BURST_SZ_USB3));
rtwn_setbits_1(sc, 0xf008, 0x18, 0);
}
diff --git a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au.h b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au.h
index 60aa476c..a327d2ad 100644
--- a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au.h
+++ b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au.h
@@ -37,7 +37,6 @@
*/
/* r21au_init.c */
void r21au_init_tx_agg(struct rtwn_softc *);
-void r21au_init_burstlen(struct rtwn_softc *);
/* r21au_dfs.c */
void r21au_chan_check(void *, int);
diff --git a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c
index 5cf721c2..976582ae 100644
--- a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c
+++ b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c
@@ -137,7 +137,7 @@ r21a_attach_private(struct rtwn_softc *sc)
rs->rs_fix_spur = rtwn_nop_softc_chan;
rs->rs_set_band_2ghz = r21a_set_band_2ghz;
rs->rs_set_band_5ghz = r21a_set_band_5ghz;
- rs->rs_init_burstlen = r21au_init_burstlen;
+ rs->rs_init_burstlen = r12au_init_burstlen_usb2;
rs->rs_init_ampdu_fwhw = r21a_init_ampdu_fwhw;
rs->rs_crystalcap_write = r21a_crystalcap_write;
#ifndef RTWN_WITHOUT_UCODE
diff --git a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_init.c b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_init.c
index 31366e59..838e1b50 100644
--- a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_init.c
+++ b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_init.c
@@ -72,14 +72,3 @@ r21au_init_tx_agg(struct rtwn_softc *sc)
rtwn_write_1(sc, R21A_DWBCN1_CTRL, uc->tx_agg_desc_num << 1);
}
-void
-r21au_init_burstlen(struct rtwn_softc *sc)
-{
- if ((rtwn_read_1(sc, R92C_USB_INFO) & 0x30) == 0) {
- /* Set burst packet length to 512 B. */
- rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x20, 0x1e);
- } else {
- /* Set burst packet length to 64 B. */
- rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x10, 0x2e);
- }
-}
diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c
index 39b9dc91..ccbf5d85 100644
--- a/freebsd/sys/dev/sdhci/sdhci.c
+++ b/freebsd/sys/dev/sdhci/sdhci.c
@@ -92,27 +92,49 @@ SYSCTL_INT(_hw_sdhci, OID_AUTO, quirk_set, CTLFLAG_RWTUN, &sdhci_quirk_set, 0,
#define WR_MULTI_4(slot, off, ptr, count) \
SDHCI_WRITE_MULTI_4((slot)->bus, (slot), (off), (ptr), (count))
+static void sdhci_acmd_irq(struct sdhci_slot *slot, uint16_t acmd_err);
static void sdhci_card_poll(void *arg);
static void sdhci_card_task(void *arg, int pending);
+static void sdhci_cmd_irq(struct sdhci_slot *slot, uint32_t intmask);
+static void sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask);
static int sdhci_exec_tuning(struct sdhci_slot *slot, bool reset);
+static void sdhci_handle_card_present_locked(struct sdhci_slot *slot,
+ bool is_present);
+static void sdhci_finish_command(struct sdhci_slot *slot);
+static void sdhci_init(struct sdhci_slot *slot);
+static void sdhci_read_block_pio(struct sdhci_slot *slot);
+static void sdhci_req_done(struct sdhci_slot *slot);
static void sdhci_req_wakeup(struct mmc_request *req);
+static void sdhci_reset(struct sdhci_slot *slot, uint8_t mask);
static void sdhci_retune(void *arg);
static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock);
+static void sdhci_set_power(struct sdhci_slot *slot, u_char power);
+static void sdhci_set_transfer_mode(struct sdhci_slot *slot,
+ struct mmc_data *data);
static void sdhci_start(struct sdhci_slot *slot);
+static void sdhci_timeout(void *arg);
+static void sdhci_start_command(struct sdhci_slot *slot,
+ struct mmc_command *cmd);
static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data);
+static void sdhci_write_block_pio(struct sdhci_slot *slot);
+static void sdhci_transfer_pio(struct sdhci_slot *slot);
#ifdef MMCCAM
/* CAM-related */
-int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock);
-static int sdhci_cam_update_ios(struct sdhci_slot *slot);
-static int sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb);
static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb);
+static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot,
+ int proposed_clock);
+static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb);
static void sdhci_cam_poll(struct cam_sim *sim);
+static int sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb);
static int sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb);
+static int sdhci_cam_update_ios(struct sdhci_slot *slot);
#endif
/* helper routines */
static void sdhci_dumpregs(struct sdhci_slot *slot);
+static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error);
static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
__printflike(2, 3);
static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot);
@@ -1562,20 +1584,19 @@ sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data)
return;
mode = SDHCI_TRNS_BLK_CNT_EN;
- if (data->len > 512)
+ if (data->len > 512) {
mode |= SDHCI_TRNS_MULTI;
- if (data->flags & MMC_DATA_READ)
- mode |= SDHCI_TRNS_READ;
+ if (__predict_true(
#ifdef MMCCAM
- struct ccb_mmcio *mmcio;
- mmcio = &slot->ccb->mmcio;
- if (mmcio->stop.opcode == MMC_STOP_TRANSMISSION
- && !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP))
- mode |= SDHCI_TRNS_ACMD12;
+ slot->ccb->mmcio.stop.opcode == MMC_STOP_TRANSMISSION &&
#else
- if (slot->req->stop && !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP))
- mode |= SDHCI_TRNS_ACMD12;
+ slot->req->stop != NULL &&
#endif
+ !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP)))
+ mode |= SDHCI_TRNS_ACMD12;
+ }
+ if (data->flags & MMC_DATA_READ)
+ mode |= SDHCI_TRNS_READ;
if (slot->flags & SDHCI_USE_DMA)
mode |= SDHCI_TRNS_DMA;
@@ -2158,18 +2179,16 @@ done:
}
static void
-sdhci_acmd_irq(struct sdhci_slot *slot)
+sdhci_acmd_irq(struct sdhci_slot *slot, uint16_t acmd_err)
{
- uint16_t err;
- err = RD4(slot, SDHCI_ACMD12_ERR);
if (!slot->curcmd) {
slot_printf(slot, "Got AutoCMD12 error 0x%04x, but "
- "there is no active command.\n", err);
+ "there is no active command.\n", acmd_err);
sdhci_dumpregs(slot);
return;
}
- slot_printf(slot, "Got AutoCMD12 error 0x%04x\n", err);
+ slot_printf(slot, "Got AutoCMD12 error 0x%04x\n", acmd_err);
sdhci_reset(slot, SDHCI_RESET_CMD);
}
@@ -2177,6 +2196,7 @@ void
sdhci_generic_intr(struct sdhci_slot *slot)
{
uint32_t intmask, present;
+ uint16_t val16;
SDHCI_LOCK(slot);
/* Read slot interrupt status. */
@@ -2190,6 +2210,7 @@ sdhci_generic_intr(struct sdhci_slot *slot)
/* Handle tuning error interrupt. */
if (__predict_false(intmask & SDHCI_INT_TUNEERR)) {
+ WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_TUNEERR);
slot_printf(slot, "Tuning error indicated\n");
slot->retune_req |= SDHCI_RETUNE_REQ_RESET;
if (slot->curcmd) {
@@ -2227,8 +2248,10 @@ sdhci_generic_intr(struct sdhci_slot *slot)
}
/* Handle AutoCMD12 error interrupt. */
if (intmask & SDHCI_INT_ACMD12ERR) {
+ /* Clearing SDHCI_INT_ACMD12ERR may clear SDHCI_ACMD12_ERR. */
+ val16 = RD2(slot, SDHCI_ACMD12_ERR);
WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_ACMD12ERR);
- sdhci_acmd_irq(slot);
+ sdhci_acmd_irq(slot, val16);
}
/* Handle bus power interrupt. */
if (intmask & SDHCI_INT_BUS_POWER) {
@@ -2574,7 +2597,9 @@ sdhci_cam_poll(struct cam_sim *sim)
return;
}
-int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) {
+static int
+sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
+{
int max_clock, clock, i;
if (proposed_clock == 0)
diff --git a/freebsd/sys/dev/usb/controller/usb_controller.c b/freebsd/sys/dev/usb/controller/usb_controller.c
index a2633d0d..81901063 100644
--- a/freebsd/sys/dev/usb/controller/usb_controller.c
+++ b/freebsd/sys/dev/usb/controller/usb_controller.c
@@ -135,7 +135,6 @@ DRIVER_MODULE(usbus, ehci, usb_driver, usb_devclass, 0, 0);
DRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0);
/* Device Only Drivers */
-DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
DRIVER_MODULE(usbus, uss820dci, usb_driver, usb_devclass, 0, 0);
DRIVER_MODULE(usbus, octusb, usb_driver, usb_devclass, 0, 0);
diff --git a/freebsd/sys/dev/usb/input/uep.c b/freebsd/sys/dev/usb/input/uep.c
index 701c8550..247bfb9c 100644
--- a/freebsd/sys/dev/usb/input/uep.c
+++ b/freebsd/sys/dev/usb/input/uep.c
@@ -34,6 +34,8 @@
* http://www.eeti.com.tw/pdf/Software%20Programming%20Guide_v2.0.pdf
*/
+#include <rtems/bsd/local/opt_evdev.h>
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/callout.h>
@@ -51,9 +53,14 @@
#include <dev/usb/usbhid.h>
#include <rtems/bsd/local/usbdevs.h>
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#else
#include <sys/ioccom.h>
#include <sys/fcntl.h>
#include <sys/tty.h>
+#endif
#define USB_DEBUG_VAR uep_debug
#include <dev/usb/usb_debug.h>
@@ -92,11 +99,15 @@ struct uep_softc {
struct mtx mtx;
struct usb_xfer *xfer[UEP_N_TRANSFER];
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev *evdev;
+#else
struct usb_fifo_sc fifo;
u_int pollrate;
u_int state;
#define UEP_ENABLED 0x01
+#endif
/* Reassembling buffer. */
u_char buf[UEP_PACKET_LEN_MAX];
@@ -109,6 +120,18 @@ static device_probe_t uep_probe;
static device_attach_t uep_attach;
static device_detach_t uep_detach;
+#ifdef EVDEV_SUPPORT
+
+static evdev_open_t uep_ev_open;
+static evdev_close_t uep_ev_close;
+
+static const struct evdev_methods uep_evdev_methods = {
+ .ev_open = &uep_ev_open,
+ .ev_close = &uep_ev_close,
+};
+
+#else /* !EVDEV_SUPPORT */
+
static usb_fifo_cmd_t uep_start_read;
static usb_fifo_cmd_t uep_stop_read;
static usb_fifo_open_t uep_open;
@@ -123,6 +146,7 @@ static struct usb_fifo_methods uep_fifo_methods = {
.f_stop_read = &uep_stop_read,
.basename[0] = "uep",
};
+#endif /* !EVDEV_SUPPORT */
static int
get_pkt_len(u_char *buf)
@@ -156,6 +180,9 @@ static void
uep_process_pkt(struct uep_softc *sc, u_char *buf)
{
int32_t x, y;
+#ifdef EVDEV_SUPPORT
+ int touch;
+#endif
if ((buf[0] & 0xFE) != 0x80) {
DPRINTF("bad input packet format 0x%.2x\n", buf[0]);
@@ -188,7 +215,17 @@ uep_process_pkt(struct uep_softc *sc, u_char *buf)
DPRINTFN(2, "x %u y %u\n", x, y);
+#ifdef EVDEV_SUPPORT
+ touch = buf[0] & (1 << 0);
+ if (touch) {
+ evdev_push_abs(sc->evdev, ABS_X, x);
+ evdev_push_abs(sc->evdev, ABS_Y, y);
+ }
+ evdev_push_key(sc->evdev, BTN_TOUCH, touch);
+ evdev_sync(sc->evdev);
+#else
uep_put_queue(sc, buf);
+#endif
}
static void
@@ -263,12 +300,13 @@ uep_intr_callback(struct usb_xfer *xfer, usb_error_t error)
}
case USB_ST_SETUP:
tr_setup:
+#ifndef EVDEV_SUPPORT
/* check if we can put more data into the FIFO */
- if (usb_fifo_put_bytes_max(sc->fifo.fp[USB_FIFO_RX]) != 0) {
- usbd_xfer_set_frame_len(xfer, 0,
- usbd_xfer_max_len(xfer));
- usbd_transfer_submit(xfer);
- }
+ if (usb_fifo_put_bytes_max(sc->fifo.fp[USB_FIFO_RX]) == 0)
+ break;
+#endif
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
break;
default:
@@ -332,6 +370,28 @@ uep_attach(device_t dev)
goto detach;
}
+#ifdef EVDEV_SUPPORT
+ sc->evdev = evdev_alloc();
+ evdev_set_name(sc->evdev, device_get_desc(dev));
+ evdev_set_phys(sc->evdev, device_get_nameunit(dev));
+ evdev_set_id(sc->evdev, BUS_USB, uaa->info.idVendor,
+ uaa->info.idProduct, 0);
+ evdev_set_serial(sc->evdev, usb_get_serial(uaa->device));
+ evdev_set_methods(sc->evdev, sc, &uep_evdev_methods);
+ evdev_support_prop(sc->evdev, INPUT_PROP_DIRECT);
+ evdev_support_event(sc->evdev, EV_SYN);
+ evdev_support_event(sc->evdev, EV_ABS);
+ evdev_support_event(sc->evdev, EV_KEY);
+ evdev_support_key(sc->evdev, BTN_TOUCH);
+ evdev_support_abs(sc->evdev, ABS_X, 0, 0, UEP_MAX_X, 0, 0, 0);
+ evdev_support_abs(sc->evdev, ABS_Y, 0, 0, UEP_MAX_Y, 0, 0, 0);
+
+ error = evdev_register_mtx(sc->evdev, &sc->mtx);
+ if (error) {
+ DPRINTF("evdev_register_mtx error=%s\n", usbd_errstr(error));
+ goto detach;
+ }
+#else /* !EVDEV_SUPPORT */
error = usb_fifo_attach(uaa->device, sc, &sc->mtx, &uep_fifo_methods,
&sc->fifo, device_get_unit(dev), -1, uaa->info.bIfaceIndex,
UID_ROOT, GID_OPERATOR, 0644);
@@ -340,6 +400,7 @@ uep_attach(device_t dev)
DPRINTF("usb_fifo_attach error=%s\n", usbd_errstr(error));
goto detach;
}
+#endif /* !EVDEV_SUPPORT */
sc->buf_len = 0;
@@ -356,7 +417,11 @@ uep_detach(device_t dev)
{
struct uep_softc *sc = device_get_softc(dev);
+#ifdef EVDEV_SUPPORT
+ evdev_free(sc->evdev);
+#else
usb_fifo_detach(&sc->fifo);
+#endif
usbd_transfer_unsetup(sc->xfer, UEP_N_TRANSFER);
@@ -365,6 +430,32 @@ uep_detach(device_t dev)
return (0);
}
+#ifdef EVDEV_SUPPORT
+
+static int
+uep_ev_close(struct evdev_dev *evdev)
+{
+ struct uep_softc *sc = evdev_get_softc(evdev);
+
+ mtx_assert(&sc->mtx, MA_OWNED);
+ usbd_transfer_stop(sc->xfer[UEP_INTR_DT]);
+
+ return (0);
+}
+
+static int
+uep_ev_open(struct evdev_dev *evdev)
+{
+ struct uep_softc *sc = evdev_get_softc(evdev);
+
+ mtx_assert(&sc->mtx, MA_OWNED);
+ usbd_transfer_start(sc->xfer[UEP_INTR_DT]);
+
+ return (0);
+}
+
+#else /* !EVDEV_SUPPORT */
+
static void
uep_start_read(struct usb_fifo *fifo)
{
@@ -426,6 +517,7 @@ uep_close(struct usb_fifo *fifo, int fflags)
usb_fifo_free_buffer(fifo);
}
}
+#endif /* !EVDEV_SUPPORT */
static devclass_t uep_devclass;
@@ -444,5 +536,8 @@ static driver_t uep_driver = {
DRIVER_MODULE(uep, uhub, uep_driver, uep_devclass, NULL, NULL);
MODULE_DEPEND(uep, usb, 1, 1, 1);
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(uep, evdev, 1, 1, 1);
+#endif
MODULE_VERSION(uep, 1);
USB_PNP_HOST_INFO(uep_devs);
diff --git a/freebsd/sys/dev/usb/input/ukbd.c b/freebsd/sys/dev/usb/input/ukbd.c
index 76fe76b6..8fb450bc 100644
--- a/freebsd/sys/dev/usb/input/ukbd.c
+++ b/freebsd/sys/dev/usb/input/ukbd.c
@@ -367,8 +367,10 @@ static device_detach_t ukbd_detach;
static device_resume_t ukbd_resume;
#ifdef EVDEV_SUPPORT
+static evdev_event_t ukbd_ev_event;
+
static const struct evdev_methods ukbd_evdev_methods = {
- .ev_event = evdev_ev_kbd_event,
+ .ev_event = ukbd_ev_event,
};
#endif
@@ -1474,6 +1476,22 @@ ukbd_resume(device_t dev)
return (0);
}
+#ifdef EVDEV_SUPPORT
+static void
+ukbd_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
+ int32_t value)
+{
+ keyboard_t *kbd = evdev_get_softc(evdev);
+
+ if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD &&
+ (type == EV_LED || type == EV_REP)) {
+ mtx_lock(&Giant);
+ kbd_ev_event(kbd, type, code, value);
+ mtx_unlock(&Giant);
+ }
+}
+#endif
+
/* early keyboard probe, not supported */
static int
ukbd_configure(int flags)
diff --git a/freebsd/sys/dev/usb/input/ums.c b/freebsd/sys/dev/usb/input/ums.c
index 79bc2291..4a0d1f34 100644
--- a/freebsd/sys/dev/usb/input/ums.c
+++ b/freebsd/sys/dev/usb/input/ums.c
@@ -952,9 +952,9 @@ ums_reset_buf(struct ums_softc *sc)
#ifdef EVDEV_SUPPORT
static int
-ums_ev_open(struct evdev_dev *evdev, void *ev_softc)
+ums_ev_open(struct evdev_dev *evdev)
{
- struct ums_softc *sc = (struct ums_softc *)ev_softc;
+ struct ums_softc *sc = evdev_get_softc(evdev);
mtx_assert(&sc->sc_mtx, MA_OWNED);
@@ -968,10 +968,10 @@ ums_ev_open(struct evdev_dev *evdev, void *ev_softc)
return (0);
}
-static void
-ums_ev_close(struct evdev_dev *evdev, void *ev_softc)
+static int
+ums_ev_close(struct evdev_dev *evdev)
{
- struct ums_softc *sc = (struct ums_softc *)ev_softc;
+ struct ums_softc *sc = evdev_get_softc(evdev);
mtx_assert(&sc->sc_mtx, MA_OWNED);
@@ -979,6 +979,8 @@ ums_ev_close(struct evdev_dev *evdev, void *ev_softc)
if (sc->sc_fflags == 0)
ums_stop_rx(sc);
+
+ return (0);
}
#endif
diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c
index 8a88feae..bcae02cb 100644
--- a/freebsd/sys/dev/usb/net/if_ure.c
+++ b/freebsd/sys/dev/usb/net/if_ure.c
@@ -70,6 +70,7 @@ SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0,
static const STRUCT_USB_HOST_ID ure_devs[] = {
#define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
URE_DEV(LENOVO, RTL8153, 0),
+ URE_DEV(NVIDIA, RTL8153, 0),
URE_DEV(REALTEK, RTL8152, URE_FLAG_8152),
URE_DEV(REALTEK, RTL8153, 0),
URE_DEV(TPLINK, RTL8153, 0),
diff --git a/freebsd/sys/dev/usb/serial/u3g.c b/freebsd/sys/dev/usb/serial/u3g.c
index 6f1cfdb1..8d72ef49 100644
--- a/freebsd/sys/dev/usb/serial/u3g.c
+++ b/freebsd/sys/dev/usb/serial/u3g.c
@@ -210,6 +210,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(ALINK, 3G, 0),
U3G_DEV(ALINK, 3GU, 0),
U3G_DEV(ALINK, DWM652U5, 0),
+ U3G_DEV(ALINK, SIM7600E, 0),
U3G_DEV(AMOI, H01, 0),
U3G_DEV(AMOI, H01A, 0),
U3G_DEV(AMOI, H02, 0),
diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c
index c2d93f3a..7ae052b7 100644
--- a/freebsd/sys/dev/usb/usb_hid.c
+++ b/freebsd/sys/dev/usb/usb_hid.c
@@ -76,6 +76,7 @@ static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize);
#define MAXUSAGE 64
#define MAXPUSH 4
#define MAXID 16
+#define MAXLOCCNT 1024
struct hid_pos_data {
int32_t rid;
@@ -93,10 +94,10 @@ struct hid_data {
int32_t usage_last; /* last seen usage */
uint32_t loc_size; /* last seen size */
uint32_t loc_count; /* last seen count */
+ uint32_t ncount; /* end usage item count */
+ uint32_t icount; /* current usage item count */
uint8_t kindset; /* we have 5 kinds so 8 bits are enough */
uint8_t pushlevel; /* current pushlevel */
- uint8_t ncount; /* end usage item count */
- uint8_t icount; /* current usage item count */
uint8_t nusage; /* end "usages_min/max" index */
uint8_t iusage; /* current "usages_min/max" index */
uint8_t ousage; /* current "usages_min/max" offset */
@@ -349,18 +350,19 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
switch (bTag) {
case 8: /* Input */
c->kind = hid_input;
- c->flags = dval;
ret:
+ c->flags = dval;
c->loc.count = s->loc_count;
c->loc.size = s->loc_size;
if (c->flags & HIO_VARIABLE) {
/* range check usage count */
- if (c->loc.count > 255) {
+ if (c->loc.count > MAXLOCCNT) {
DPRINTFN(0, "Number of "
- "items(%u) truncated to 255\n",
- (unsigned)(c->loc.count));
- s->ncount = 255;
+ "items(%u) truncated to %u\n",
+ (unsigned)(c->loc.count),
+ MAXLOCCNT);
+ s->ncount = MAXLOCCNT;
} else
s->ncount = c->loc.count;
@@ -376,7 +378,6 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
case 9: /* Output */
c->kind = hid_output;
- c->flags = dval;
goto ret;
case 10: /* Collection */
c->kind = hid_collection;
@@ -387,7 +388,6 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
return (1);
case 11: /* Feature */
c->kind = hid_feature;
- c->flags = dval;
goto ret;
case 12: /* End collection */
c->kind = hid_endcollection;
diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c
index cb69ce0e..d2a15f3c 100644
--- a/freebsd/sys/dev/usb/usb_request.c
+++ b/freebsd/sys/dev/usb/usb_request.c
@@ -992,7 +992,7 @@ usbd_req_get_desc(struct usb_device *udev,
uint8_t retries)
{
struct usb_device_request req;
- uint8_t *buf;
+ uint8_t *buf = desc;
usb_error_t err;
DPRINTFN(4, "id=%d, type=%d, index=%d, max_len=%d\n",
@@ -1014,6 +1014,32 @@ usbd_req_get_desc(struct usb_device *udev,
err = usbd_do_request_flags(udev, mtx, &req,
desc, 0, NULL, 500 /* ms */);
+ if (err != 0 && err != USB_ERR_TIMEOUT &&
+ min_len != max_len) {
+ /* clear descriptor data */
+ memset(desc, 0, max_len);
+
+ /* try to read full descriptor length */
+ USETW(req.wLength, max_len);
+
+ err = usbd_do_request_flags(udev, mtx, &req,
+ desc, USB_SHORT_XFER_OK, NULL, 500 /* ms */);
+
+ if (err == 0) {
+ /* verify length */
+ if (buf[0] > max_len)
+ buf[0] = max_len;
+ else if (buf[0] < 2)
+ err = USB_ERR_INVAL;
+
+ min_len = buf[0];
+
+ /* enforce descriptor type */
+ buf[1] = type;
+ goto done;
+ }
+ }
+
if (err) {
if (!retries) {
goto done;
@@ -1024,7 +1050,6 @@ usbd_req_get_desc(struct usb_device *udev,
continue;
}
- buf = desc;
if (min_len == max_len) {
diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c
index 41f97ba4..3bd247e3 100644
--- a/freebsd/sys/dev/usb/wlan/if_run.c
+++ b/freebsd/sys/dev/usb/wlan/if_run.c
@@ -210,6 +210,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = {
RUN_DEV(CYBERTAN, RT2870),
RUN_DEV(DLINK, RT2870),
RUN_DEV(DLINK, RT3072),
+ RUN_DEV(DLINK, DWA125A3),
RUN_DEV(DLINK, DWA127),
RUN_DEV(DLINK, DWA140B3),
RUN_DEV(DLINK, DWA160B2),
@@ -303,6 +304,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = {
RUN_DEV(RALINK, RT3572),
RUN_DEV(RALINK, RT3573),
RUN_DEV(RALINK, RT5370),
+ RUN_DEV(RALINK, RT5372),
RUN_DEV(RALINK, RT5572),
RUN_DEV(RALINK, RT8070),
RUN_DEV(SAMSUNG, WIS09ABGN),
diff --git a/freebsd/sys/i386/include/machine/cpufunc.h b/freebsd/sys/i386/include/machine/cpufunc.h
index 0147abe9..c640b569 100644
--- a/freebsd/sys/i386/include/machine/cpufunc.h
+++ b/freebsd/sys/i386/include/machine/cpufunc.h
@@ -374,6 +374,15 @@ rdtsc(void)
return (rv);
}
+static __inline uint64_t
+rdtscp(void)
+{
+ uint64_t rv;
+
+ __asm __volatile("rdtscp" : "=A" (rv) : : "ecx");
+ return (rv);
+}
+
static __inline uint32_t
rdtsc32(void)
{
diff --git a/freebsd/sys/i386/include/machine/intr_machdep.h b/freebsd/sys/i386/include/machine/intr_machdep.h
index 1ac8f489..a0b28387 100644
--- a/freebsd/sys/i386/include/machine/intr_machdep.h
+++ b/freebsd/sys/i386/include/machine/intr_machdep.h
@@ -1,190 +1,6 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
+ * This file is in the public domain.
*/
+/* $FreeBSD$ */
-#ifndef __MACHINE_INTR_MACHDEP_H__
-#define __MACHINE_INTR_MACHDEP_H__
-
-#ifdef _KERNEL
-
-/*
- * The maximum number of I/O interrupts we allow. This number is rather
- * arbitrary as it is just the maximum IRQ resource value. The interrupt
- * source for a given IRQ maps that I/O interrupt to device interrupt
- * source whether it be a pin on an interrupt controller or an MSI interrupt.
- * The 16 ISA IRQs are assigned fixed IDT vectors, but all other device
- * interrupts allocate IDT vectors on demand. Currently we have 191 IDT
- * vectors available for device interrupts. On many systems with I/O APICs,
- * a lot of the IRQs are not used, so this number can be much larger than
- * 191 and still be safe since only interrupt sources in actual use will
- * allocate IDT vectors.
- *
- * The first 255 IRQs (0 - 254) are reserved for ISA IRQs and PCI intline IRQs.
- * IRQ values from 256 to 767 are used by MSI. When running under the Xen
- * Hypervisor, IRQ values from 768 to 4863 are available for binding to
- * event channel events. We leave 255 unused to avoid confusion since 255 is
- * used in PCI to indicate an invalid IRQ.
- */
-#define NUM_MSI_INTS 512
-#define FIRST_MSI_INT 256
-#ifdef XENHVM
-#include <xen/xen-os.h>
-#include <xen/interface/event_channel.h>
-#define NUM_EVTCHN_INTS NR_EVENT_CHANNELS
-#define FIRST_EVTCHN_INT \
- (FIRST_MSI_INT + NUM_MSI_INTS)
-#define LAST_EVTCHN_INT \
- (FIRST_EVTCHN_INT + NUM_EVTCHN_INTS - 1)
-#else /* !XENHVM */
-#define NUM_EVTCHN_INTS 0
-#endif
-#define NUM_IO_INTS (FIRST_MSI_INT + NUM_MSI_INTS + NUM_EVTCHN_INTS)
-
-/*
- * Default base address for MSI messages on x86 platforms.
- */
-#define MSI_INTEL_ADDR_BASE 0xfee00000
-
-/*
- * - 1 ??? dummy counter.
- * - 2 counters for each I/O interrupt.
- * - 1 counter for each CPU for lapic timer.
- * - 9 counters for each CPU for IPI counters for SMP.
- */
-#ifdef SMP
-#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 9) * MAXCPU)
-#else
-#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1)
-#endif
-
-#ifndef LOCORE
-
-typedef void inthand_t(void);
-
-#define IDTVEC(name) __CONCAT(X,name)
-
-struct intsrc;
-
-/*
- * Methods that a PIC provides to mask/unmask a given interrupt source,
- * "turn on" the interrupt on the CPU side by setting up an IDT entry, and
- * return the vector associated with this source.
- */
-struct pic {
- void (*pic_enable_source)(struct intsrc *);
- void (*pic_disable_source)(struct intsrc *, int);
- void (*pic_eoi_source)(struct intsrc *);
- void (*pic_enable_intr)(struct intsrc *);
- void (*pic_disable_intr)(struct intsrc *);
- int (*pic_vector)(struct intsrc *);
- int (*pic_source_pending)(struct intsrc *);
- void (*pic_suspend)(struct pic *);
- void (*pic_resume)(struct pic *, bool suspend_cancelled);
- int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
- enum intr_polarity);
- int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
- void (*pic_reprogram_pin)(struct intsrc *);
- TAILQ_ENTRY(pic) pics;
-};
-
-/* Flags for pic_disable_source() */
-enum {
- PIC_EOI,
- PIC_NO_EOI,
-};
-
-/*
- * An interrupt source. The upper-layer code uses the PIC methods to
- * control a given source. The lower-layer PIC drivers can store additional
- * private data in a given interrupt source such as an interrupt pin number
- * or an I/O APIC pointer.
- */
-struct intsrc {
- struct pic *is_pic;
- struct intr_event *is_event;
- u_long *is_count;
- u_long *is_straycount;
- u_int is_index;
- u_int is_handlers;
- u_int is_domain;
- u_int is_cpu;
-};
-
-struct trapframe;
-
-#ifdef SMP
-extern cpuset_t intr_cpus;
-#endif
-extern struct mtx icu_lock;
-extern int elcr_found;
-#ifdef SMP
-extern int msix_disable_migration;
-#endif
-
-#ifndef DEV_ATPIC
-void atpic_reset(void);
-#endif
-/* XXX: The elcr_* prototypes probably belong somewhere else. */
-int elcr_probe(void);
-enum intr_trigger elcr_read_trigger(u_int irq);
-void elcr_resume(void);
-void elcr_write_trigger(u_int irq, enum intr_trigger trigger);
-#ifdef SMP
-void intr_add_cpu(u_int cpu);
-#endif
-int intr_add_handler(const char *name, int vector, driver_filter_t filter,
- driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep,
- int domain);
-#ifdef SMP
-int intr_bind(u_int vector, u_char cpu);
-#endif
-int intr_config_intr(int vector, enum intr_trigger trig,
- enum intr_polarity pol);
-int intr_describe(u_int vector, void *ih, const char *descr);
-void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame);
-u_int intr_next_cpu(int domain);
-struct intsrc *intr_lookup_source(int vector);
-int intr_register_pic(struct pic *pic);
-int intr_register_source(struct intsrc *isrc);
-int intr_remove_handler(void *cookie);
-void intr_resume(bool suspend_cancelled);
-void intr_suspend(void);
-void intr_reprogram(void);
-void intrcnt_add(const char *name, u_long **countp);
-void nexus_add_irq(u_long irq);
-int msi_alloc(device_t dev, int count, int maxcount, int *irqs);
-void msi_init(void);
-int msi_map(int irq, uint64_t *addr, uint32_t *data);
-int msi_release(int* irqs, int count);
-int msix_alloc(device_t dev, int *irq);
-int msix_release(int irq);
-
-#endif /* !LOCORE */
-#endif /* _KERNEL */
-#endif /* !__MACHINE_INTR_MACHDEP_H__ */
+#include <x86/intr_machdep.h>
diff --git a/freebsd/sys/kern/init_main.c b/freebsd/sys/kern/init_main.c
index 42afff5e..fa4951d8 100644
--- a/freebsd/sys/kern/init_main.c
+++ b/freebsd/sys/kern/init_main.c
@@ -122,6 +122,18 @@ int bootverbose = BOOTVERBOSE;
SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0,
"Control the output of verbose kernel messages");
+#ifdef VERBOSE_SYSINIT
+/*
+ * We'll use the defined value of VERBOSE_SYSINIT from the kernel config to
+ * dictate the default VERBOSE_SYSINIT behavior. Significant values for this
+ * option and associated tunable are:
+ * - 0, 'compiled in but silent by default'
+ * - 1, 'compiled in but verbose by default' (default)
+ */
+int verbose_sysinit = VERBOSE_SYSINIT;
+TUNABLE_INT("debug.verbose_sysinit", &verbose_sysinit);
+#endif
+
#ifdef INVARIANTS
FEATURE(invariants, "Kernel compiled with INVARIANTS, may affect performance");
#endif
@@ -287,7 +299,7 @@ restart:
continue;
#if defined(VERBOSE_SYSINIT)
- if ((*sipp)->subsystem > last) {
+ if ((*sipp)->subsystem > last && verbose_sysinit != 0) {
verbose = 1;
last = (*sipp)->subsystem;
printf("subsystem %x\n", last);
@@ -526,6 +538,7 @@ proc0_init(void *dummy __unused)
p->p_peers = 0;
p->p_leader = p;
p->p_reaper = p;
+ p->p_treeflag |= P_TREE_REAPER;
LIST_INIT(&p->p_reaplist);
strncpy(p->p_comm, "kernel", sizeof (p->p_comm));
@@ -642,17 +655,23 @@ proc0_post(void *dummy __unused)
*/
sx_slock(&allproc_lock);
FOREACH_PROC_IN_SYSTEM(p) {
+ PROC_LOCK(p);
+ if (p->p_state == PRS_NEW) {
+ PROC_UNLOCK(p);
+ continue;
+ }
microuptime(&p->p_stats->p_start);
PROC_STATLOCK(p);
rufetch(p, &ru); /* Clears thread stats */
- PROC_STATUNLOCK(p);
p->p_rux.rux_runtime = 0;
p->p_rux.rux_uticks = 0;
p->p_rux.rux_sticks = 0;
p->p_rux.rux_iticks = 0;
+ PROC_STATUNLOCK(p);
FOREACH_THREAD_IN_PROC(p, td) {
td->td_runtime = 0;
}
+ PROC_UNLOCK(p);
}
sx_sunlock(&allproc_lock);
PCPU_SET(switchtime, cpu_ticks());
@@ -857,7 +876,6 @@ create_init(const void *udata __unused)
PROC_LOCK(initproc);
initproc->p_flag |= P_SYSTEM | P_INMEM;
initproc->p_treeflag |= P_TREE_REAPER;
- LIST_INSERT_HEAD(&initproc->p_reaplist, &proc0, p_reapsibling);
oldcred = initproc->p_ucred;
crcopy(newcred, oldcred);
#ifdef MAC
diff --git a/freebsd/sys/kern/kern_event.c b/freebsd/sys/kern/kern_event.c
index 33fca549..25a9518f 100644
--- a/freebsd/sys/kern/kern_event.c
+++ b/freebsd/sys/kern/kern_event.c
@@ -179,6 +179,10 @@ static int filt_fileattach(struct knote *kn);
static void filt_timerexpire(void *knx);
static int filt_timerattach(struct knote *kn);
static void filt_timerdetach(struct knote *kn);
+static void filt_timerstart(struct knote *kn, sbintime_t to);
+static void filt_timertouch(struct knote *kn, struct kevent *kev,
+ u_long type);
+static int filt_timervalidate(struct knote *kn, sbintime_t *to);
static int filt_timer(struct knote *kn, long hint);
static int filt_userattach(struct knote *kn);
static void filt_userdetach(struct knote *kn);
@@ -209,6 +213,7 @@ static struct filterops timer_filtops = {
.f_attach = filt_timerattach,
.f_detach = filt_timerdetach,
.f_event = filt_timer,
+ .f_touch = filt_timertouch,
};
static struct filterops user_filtops = {
.f_attach = filt_userattach,
@@ -738,29 +743,44 @@ filt_timerexpire(void *knx)
* data contains amount of time to sleep
*/
static int
-filt_timerattach(struct knote *kn)
+filt_timervalidate(struct knote *kn, sbintime_t *to)
{
- struct kq_timer_cb_data *kc;
struct bintime bt;
- sbintime_t to, sbt;
- unsigned int ncallouts;
+ sbintime_t sbt;
if (kn->kn_sdata < 0)
return (EINVAL);
if (kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0)
kn->kn_sdata = 1;
- /* Only precision unit are supported in flags so far */
+ /*
+ * The only fflags values supported are the timer unit
+ * (precision) and the absolute time indicator.
+ */
if ((kn->kn_sfflags & ~(NOTE_TIMER_PRECMASK | NOTE_ABSTIME)) != 0)
return (EINVAL);
- to = timer2sbintime(kn->kn_sdata, kn->kn_sfflags);
+ *to = timer2sbintime(kn->kn_sdata, kn->kn_sfflags);
if ((kn->kn_sfflags & NOTE_ABSTIME) != 0) {
getboottimebin(&bt);
sbt = bttosbt(bt);
- to -= sbt;
+ *to -= sbt;
}
- if (to < 0)
+ if (*to < 0)
return (EINVAL);
+ return (0);
+}
+
+static int
+filt_timerattach(struct knote *kn)
+{
+ struct kq_timer_cb_data *kc;
+ sbintime_t to;
+ unsigned int ncallouts;
+ int error;
+
+ error = filt_timervalidate(kn, &to);
+ if (error != 0)
+ return (error);
do {
ncallouts = kq_ncallouts;
@@ -773,6 +793,17 @@ filt_timerattach(struct knote *kn)
kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */
kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK);
callout_init(&kc->c, 1);
+ filt_timerstart(kn, to);
+
+ return (0);
+}
+
+static void
+filt_timerstart(struct knote *kn, sbintime_t to)
+{
+ struct kq_timer_cb_data *kc;
+
+ kc = kn->kn_ptr.p_v;
if ((kn->kn_sfflags & NOTE_ABSTIME) != 0) {
kc->next = to;
kc->to = 0;
@@ -782,8 +813,6 @@ filt_timerattach(struct knote *kn)
}
callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn,
PCPU_GET(cpuid), C_ABSOLUTE);
-
- return (0);
}
static void
@@ -800,6 +829,73 @@ filt_timerdetach(struct knote *kn)
kn->kn_status |= KN_DETACHED; /* knlist_remove sets it */
}
+static void
+filt_timertouch(struct knote *kn, struct kevent *kev, u_long type)
+{
+ struct kq_timer_cb_data *kc;
+ struct kqueue *kq;
+ sbintime_t to;
+ int error;
+
+ switch (type) {
+ case EVENT_REGISTER:
+ /* Handle re-added timers that update data/fflags */
+ if (kev->flags & EV_ADD) {
+ kc = kn->kn_ptr.p_v;
+
+ /* Drain any existing callout. */
+ callout_drain(&kc->c);
+
+ /* Throw away any existing undelivered record
+ * of the timer expiration. This is done under
+ * the presumption that if a process is
+ * re-adding this timer with new parameters,
+ * it is no longer interested in what may have
+ * happened under the old parameters. If it is
+ * interested, it can wait for the expiration,
+ * delete the old timer definition, and then
+ * add the new one.
+ *
+ * This has to be done while the kq is locked:
+ * - if enqueued, dequeue
+ * - make it no longer active
+ * - clear the count of expiration events
+ */
+ kq = kn->kn_kq;
+ KQ_LOCK(kq);
+ if (kn->kn_status & KN_QUEUED)
+ knote_dequeue(kn);
+
+ kn->kn_status &= ~KN_ACTIVE;
+ kn->kn_data = 0;
+ KQ_UNLOCK(kq);
+
+ /* Reschedule timer based on new data/fflags */
+ kn->kn_sfflags = kev->fflags;
+ kn->kn_sdata = kev->data;
+ error = filt_timervalidate(kn, &to);
+ if (error != 0) {
+ kn->kn_flags |= EV_ERROR;
+ kn->kn_data = error;
+ } else
+ filt_timerstart(kn, to);
+ }
+ break;
+
+ case EVENT_PROCESS:
+ *kev = kn->kn_kevent;
+ if (kn->kn_flags & EV_CLEAR) {
+ kn->kn_data = 0;
+ kn->kn_fflags = 0;
+ }
+ break;
+
+ default:
+ panic("filt_timertouch() - invalid type (%ld)", type);
+ break;
+ }
+}
+
static int
filt_timer(struct knote *kn, long hint)
{
diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c
index 8f6c2a6d..04914e93 100644
--- a/freebsd/sys/kern/kern_intr.c
+++ b/freebsd/sys/kern/kern_intr.c
@@ -175,12 +175,13 @@ ithread_update(struct intr_thread *ithd)
ie = ithd->it_event;
td = ithd->it_thread;
+ mtx_assert(&ie->ie_lock, MA_OWNED);
/* Determine the overall priority of this event. */
- if (TAILQ_EMPTY(&ie->ie_handlers))
+ if (CK_SLIST_EMPTY(&ie->ie_handlers))
pri = PRI_MAX_ITHD;
else
- pri = TAILQ_FIRST(&ie->ie_handlers)->ih_pri;
+ pri = CK_SLIST_FIRST(&ie->ie_handlers)->ih_pri;
/* Update name and priority. */
#ifndef __rtems__
@@ -218,7 +219,7 @@ intr_event_update(struct intr_event *ie)
space = 1;
/* Run through all the handlers updating values. */
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (strlen(ie->ie_fullname) + strlen(ih->ih_name) + 1 <
sizeof(ie->ie_fullname)) {
strcat(ie->ie_fullname, " ");
@@ -280,7 +281,7 @@ intr_event_create(struct intr_event **event, void *source, int flags, int irq,
ie->ie_flags = flags;
ie->ie_irq = irq;
ie->ie_cpu = NOCPU;
- TAILQ_INIT(&ie->ie_handlers);
+ CK_SLIST_INIT(&ie->ie_handlers);
mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
va_start(ap, fmt);
@@ -402,7 +403,7 @@ intr_lookup(int irq)
TAILQ_FOREACH(ie, &event_list, ie_list)
if (ie->ie_irq == irq &&
(ie->ie_flags & IE_SOFT) == 0 &&
- TAILQ_FIRST(&ie->ie_handlers) != NULL)
+ CK_SLIST_FIRST(&ie->ie_handlers) != NULL)
break;
mtx_unlock(&event_lock);
return (ie);
@@ -498,7 +499,7 @@ intr_event_destroy(struct intr_event *ie)
mtx_lock(&event_lock);
mtx_lock(&ie->ie_lock);
- if (!TAILQ_EMPTY(&ie->ie_handlers)) {
+ if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
mtx_unlock(&ie->ie_lock);
mtx_unlock(&event_lock);
return (EBUSY);
@@ -532,7 +533,7 @@ ithread_create(const char *name)
error = kproc_kthread_add(ithread_loop, ithd, &intrproc,
&td, RFSTOPPED | RFHIGHPID,
- 0, "intr", "%s", name);
+ 0, "intr", "%s", name);
if (error)
panic("kproc_create() failed with %d", error);
thread_lock(td);
@@ -573,6 +574,7 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
enum intr_type flags, void **cookiep)
{
struct intr_handler *ih, *temp_ih;
+ struct intr_handler **prevptr;
struct intr_thread *it;
if (ie == NULL || name == NULL || (handler == NULL && filter == NULL))
@@ -595,9 +597,9 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
/* We can only have one exclusive handler in a event. */
mtx_lock(&ie->ie_lock);
- if (!TAILQ_EMPTY(&ie->ie_handlers)) {
+ if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
if ((flags & INTR_EXCL) ||
- (TAILQ_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
+ (CK_SLIST_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
mtx_unlock(&ie->ie_lock);
free(ih, M_ITHREAD);
return (EINVAL);
@@ -622,14 +624,12 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
}
/* Add the new handler to the event in priority order. */
- TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) {
+ CK_SLIST_FOREACH_PREVPTR(temp_ih, prevptr, &ie->ie_handlers, ih_next) {
if (temp_ih->ih_pri > ih->ih_pri)
break;
}
- if (temp_ih == NULL)
- TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next);
- else
- TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next);
+ CK_SLIST_INSERT_PREVPTR(prevptr, temp_ih, ih, ih_next);
+
intr_event_update(ie);
CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
@@ -656,7 +656,7 @@ intr_event_describe_handler(struct intr_event *ie, void *cookie,
mtx_lock(&ie->ie_lock);
#ifdef INVARIANTS
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (ih == cookie)
break;
}
@@ -718,6 +718,45 @@ intr_handler_source(void *cookie)
}
/*
+ * If intr_event_handle() is running in the ISR context at the time of the call,
+ * then wait for it to complete.
+ */
+static void
+intr_event_barrier(struct intr_event *ie)
+{
+ int phase;
+
+ mtx_assert(&ie->ie_lock, MA_OWNED);
+ phase = ie->ie_phase;
+
+ /*
+ * Switch phase to direct future interrupts to the other active counter.
+ * Make sure that any preceding stores are visible before the switch.
+ */
+ KASSERT(ie->ie_active[!phase] == 0, ("idle phase has activity"));
+ atomic_store_rel_int(&ie->ie_phase, !phase);
+
+ /*
+ * This code cooperates with wait-free iteration of ie_handlers
+ * in intr_event_handle.
+ * Make sure that the removal and the phase update are not reordered
+ * with the active count check.
+ * Note that no combination of acquire and release fences can provide
+ * that guarantee as Store->Load sequences can always be reordered.
+ */
+ atomic_thread_fence_seq_cst();
+
+ /*
+ * Now wait on the inactive phase.
+ * The acquire fence is needed so that that all post-barrier accesses
+ * are after the check.
+ */
+ while (ie->ie_active[phase] > 0)
+ cpu_spinwait();
+ atomic_thread_fence_acq();
+}
+
+/*
* Sleep until an ithread finishes executing an interrupt handler.
*
* XXX Doesn't currently handle interrupt filters or fast interrupt
@@ -757,16 +796,14 @@ _intr_drain(int irq)
}
#endif /* __rtems__ */
-
#ifndef __rtems__
int
intr_event_remove_handler(void *cookie)
{
struct intr_handler *handler = (struct intr_handler *)cookie;
struct intr_event *ie;
-#ifdef INVARIANTS
struct intr_handler *ih;
-#endif
+ struct intr_handler **prevptr;
#ifdef notyet
int dead;
#endif
@@ -777,60 +814,48 @@ intr_event_remove_handler(void *cookie)
KASSERT(ie != NULL,
("interrupt handler \"%s\" has a NULL interrupt event",
handler->ih_name));
+
mtx_lock(&ie->ie_lock);
CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
ie->ie_name);
-#ifdef INVARIANTS
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
+ CK_SLIST_FOREACH_PREVPTR(ih, prevptr, &ie->ie_handlers, ih_next) {
if (ih == handler)
- goto ok;
- mtx_unlock(&ie->ie_lock);
- panic("interrupt handler \"%s\" not found in interrupt event \"%s\"",
- ih->ih_name, ie->ie_name);
-ok:
-#endif
+ break;
+ }
+ if (ih == NULL) {
+ panic("interrupt handler \"%s\" not found in "
+ "interrupt event \"%s\"", handler->ih_name, ie->ie_name);
+ }
+
/*
- * If there is no ithread, then just remove the handler and return.
- * XXX: Note that an INTR_FAST handler might be running on another
- * CPU!
+ * If there is no ithread, then directly remove the handler. Note that
+ * intr_event_handle() iterates ie_handlers in a lock-less fashion, so
+ * care needs to be taken to keep ie_handlers consistent and to free
+ * the removed handler only when ie_handlers is quiescent.
*/
if (ie->ie_thread == NULL) {
- TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
+ CK_SLIST_REMOVE_PREVPTR(prevptr, ih, ih_next);
+ intr_event_barrier(ie);
+ intr_event_update(ie);
mtx_unlock(&ie->ie_lock);
free(handler, M_ITHREAD);
return (0);
}
/*
- * If the interrupt thread is already running, then just mark this
- * handler as being dead and let the ithread do the actual removal.
- *
- * During a cold boot while cold is set, msleep() does not sleep,
- * so we have to remove the handler here rather than letting the
- * thread do it.
+ * Let the interrupt thread do the job.
+ * The interrupt source is disabled when the interrupt thread is
+ * running, so it does not have to worry about interaction with
+ * intr_event_handle().
*/
- thread_lock(ie->ie_thread->it_thread);
- if (!TD_AWAITING_INTR(ie->ie_thread->it_thread) && !cold) {
- handler->ih_flags |= IH_DEAD;
-
- /*
- * Ensure that the thread will process the handler list
- * again and remove this handler if it has already passed
- * it on the list.
- *
- * The release part of the following store ensures
- * that the update of ih_flags is ordered before the
- * it_need setting. See the comment before
- * atomic_cmpset_acq(&ithd->it_need, ...) operation in
- * the ithread_execute_handlers().
- */
- atomic_store_rel_int(&ie->ie_thread->it_need, 1);
- } else
- TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
- thread_unlock(ie->ie_thread->it_thread);
+ KASSERT((handler->ih_flags & IH_DEAD) == 0,
+ ("duplicate handle remove"));
+ handler->ih_flags |= IH_DEAD;
+ intr_event_schedule_thread(ie);
while (handler->ih_flags & IH_DEAD)
msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0);
intr_event_update(ie);
+
#ifdef notyet
/*
* XXX: This could be bad in the case of ppbus(8). Also, I think
@@ -838,8 +863,8 @@ ok:
* interrupt.
*/
dead = 1;
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (!(ih->ih_flags & IH_FAST)) {
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if (ih->ih_handler != NULL) {
dead = 0;
break;
}
@@ -866,7 +891,7 @@ intr_event_schedule_thread(struct intr_event *ie)
/*
* If no ithread or no handlers, then we have a stray interrupt.
*/
- if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers) ||
+ if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers) ||
ie->ie_thread == NULL)
return (EINVAL);
@@ -881,7 +906,7 @@ intr_event_schedule_thread(struct intr_event *ie)
if (ie->ie_flags & IE_ENTROPY) {
entropy.event = (uintptr_t)ie;
entropy.td = ctd;
- random_harvest_queue(&entropy, sizeof(entropy), 2, RANDOM_INTERRUPT);
+ random_harvest_queue(&entropy, sizeof(entropy), RANDOM_INTERRUPT);
}
#ifndef __rtems__
@@ -981,7 +1006,7 @@ swi_sched(void *cookie, int flags)
entropy.event = (uintptr_t)ih;
entropy.td = curthread;
- random_harvest_queue(&entropy, sizeof(entropy), 1, RANDOM_SWI);
+ random_harvest_queue(&entropy, sizeof(entropy), RANDOM_SWI);
/*
* Set ih_need for this handler so that if the ithread is already
@@ -1012,32 +1037,37 @@ swi_remove(void *cookie)
return (intr_event_remove_handler(cookie));
}
-
-
#endif /* __rtems__ */
-/*
- * This is a public function for use by drivers that mux interrupt
- * handlers for child devices from their interrupt handler.
- */
-void
+
+static void
intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
{
- struct intr_handler *ih, *ihn;
+ struct intr_handler *ih, *ihn, *ihp;
- TAILQ_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
+ ihp = NULL;
+ CK_SLIST_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
/*
* If this handler is marked for death, remove it from
* the list of handlers and wake up the sleeper.
*/
if (ih->ih_flags & IH_DEAD) {
mtx_lock(&ie->ie_lock);
- TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
+ if (ihp == NULL)
+ CK_SLIST_REMOVE_HEAD(&ie->ie_handlers, ih_next);
+ else
+ CK_SLIST_REMOVE_AFTER(ihp, ih_next);
ih->ih_flags &= ~IH_DEAD;
wakeup(ih);
mtx_unlock(&ie->ie_lock);
continue;
}
+ /*
+ * Now that we know that the current element won't be removed
+ * update the previous element.
+ */
+ ihp = ih;
+
/* Skip filter only handlers */
if (ih->ih_handler == NULL)
continue;
@@ -1226,6 +1256,7 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
struct trapframe *oldframe;
struct thread *td;
int ret, thread;
+ int phase;
td = curthread;
@@ -1234,7 +1265,7 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
#endif
/* An interrupt with no event or handlers is a stray interrupt. */
- if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
+ if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers))
return (EINVAL);
/*
@@ -1249,7 +1280,17 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
critical_enter();
oldframe = td->td_intr_frame;
td->td_intr_frame = frame;
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+
+ phase = ie->ie_phase;
+ atomic_add_int(&ie->ie_active[phase], 1);
+
+ /*
+ * This fence is required to ensure that no later loads are
+ * re-ordered before the ie_active store.
+ */
+ atomic_thread_fence_seq_cst();
+
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (ih->ih_filter == NULL) {
thread = 1;
continue;
@@ -1286,6 +1327,8 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
thread = 1;
}
}
+ atomic_add_rel_int(&ie->ie_active[phase], -1);
+
td->td_intr_frame = oldframe;
if (thread) {
@@ -1295,7 +1338,7 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
if (ie->ie_post_filter != NULL)
ie->ie_post_filter(ie->ie_source);
}
-
+
/* Schedule the ithread if needed. */
if (thread) {
int error __unused;
@@ -1441,7 +1484,7 @@ db_dump_intr_event(struct intr_event *ie, int handlers)
db_printf("\n");
if (handlers)
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next)
db_dump_intrhand(ih);
}
@@ -1456,7 +1499,7 @@ DB_SHOW_COMMAND(intr, db_show_intr)
verbose = strchr(modif, 'v') != NULL;
all = strchr(modif, 'a') != NULL;
TAILQ_FOREACH(ie, &event_list, ie_list) {
- if (!all && TAILQ_EMPTY(&ie->ie_handlers))
+ if (!all && CK_SLIST_EMPTY(&ie->ie_handlers))
continue;
db_dump_intr_event(ie, verbose);
if (db_pager_quit)
diff --git a/freebsd/sys/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c
index b4e9711f..3baea2e4 100644
--- a/freebsd/sys/kern/kern_sysctl.c
+++ b/freebsd/sys/kern/kern_sysctl.c
@@ -195,13 +195,8 @@ sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
char path[96];
ssize_t rem = sizeof(path);
ssize_t len;
- uint8_t val_8;
- uint16_t val_16;
- uint32_t val_32;
- int val_int;
- long val_long;
- int64_t val_64;
- quad_t val_quad;
+ uint8_t data[512] __aligned(sizeof(uint64_t));
+ int size;
int error;
path[--rem] = 0;
@@ -229,85 +224,88 @@ sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
switch (oidp->oid_kind & CTLTYPE) {
case CTLTYPE_INT:
- if (getenv_int(path + rem, &val_int) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(int), GETENV_SIGNED) == 0)
return;
- req.newlen = sizeof(val_int);
- req.newptr = &val_int;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_UINT:
- if (getenv_uint(path + rem, (unsigned int *)&val_int) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(int), GETENV_UNSIGNED) == 0)
return;
- req.newlen = sizeof(val_int);
- req.newptr = &val_int;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_LONG:
- if (getenv_long(path + rem, &val_long) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(long), GETENV_SIGNED) == 0)
return;
- req.newlen = sizeof(val_long);
- req.newptr = &val_long;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_ULONG:
- if (getenv_ulong(path + rem, (unsigned long *)&val_long) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(long), GETENV_UNSIGNED) == 0)
return;
- req.newlen = sizeof(val_long);
- req.newptr = &val_long;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_S8:
- if (getenv_int(path + rem, &val_int) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(int8_t), GETENV_SIGNED) == 0)
return;
- val_8 = val_int;
- req.newlen = sizeof(val_8);
- req.newptr = &val_8;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_S16:
- if (getenv_int(path + rem, &val_int) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(int16_t), GETENV_SIGNED) == 0)
return;
- val_16 = val_int;
- req.newlen = sizeof(val_16);
- req.newptr = &val_16;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_S32:
- if (getenv_long(path + rem, &val_long) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(int32_t), GETENV_SIGNED) == 0)
return;
- val_32 = val_long;
- req.newlen = sizeof(val_32);
- req.newptr = &val_32;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_S64:
- if (getenv_quad(path + rem, &val_quad) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(int64_t), GETENV_SIGNED) == 0)
return;
- val_64 = val_quad;
- req.newlen = sizeof(val_64);
- req.newptr = &val_64;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_U8:
- if (getenv_uint(path + rem, (unsigned int *)&val_int) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(uint8_t), GETENV_UNSIGNED) == 0)
return;
- val_8 = val_int;
- req.newlen = sizeof(val_8);
- req.newptr = &val_8;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_U16:
- if (getenv_uint(path + rem, (unsigned int *)&val_int) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(uint16_t), GETENV_UNSIGNED) == 0)
return;
- val_16 = val_int;
- req.newlen = sizeof(val_16);
- req.newptr = &val_16;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_U32:
- if (getenv_ulong(path + rem, (unsigned long *)&val_long) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(uint32_t), GETENV_UNSIGNED) == 0)
return;
- val_32 = val_long;
- req.newlen = sizeof(val_32);
- req.newptr = &val_32;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_U64:
- /* XXX there is no getenv_uquad() */
- if (getenv_quad(path + rem, &val_quad) == 0)
+ if (getenv_array(path + rem, data, sizeof(data), &size,
+ sizeof(uint64_t), GETENV_UNSIGNED) == 0)
return;
- val_64 = val_quad;
- req.newlen = sizeof(val_64);
- req.newptr = &val_64;
+ req.newlen = size;
+ req.newptr = data;
break;
case CTLTYPE_STRING:
penv = kern_getenv(path + rem);
diff --git a/freebsd/sys/kern/kern_time.c b/freebsd/sys/kern/kern_time.c
index a9c0547a..74b144cb 100644
--- a/freebsd/sys/kern/kern_time.c
+++ b/freebsd/sys/kern/kern_time.c
@@ -288,6 +288,8 @@ get_process_cputime(struct proc *targetp, struct timespec *ats)
PROC_STATLOCK(targetp);
rufetch(targetp, &ru);
runtime = targetp->p_rux.rux_runtime;
+ if (curthread->td_proc == targetp)
+ runtime += cpu_ticks() - PCPU_GET(switchtime);
PROC_STATUNLOCK(targetp);
cputick2timespec(runtime, ats);
}
@@ -1577,7 +1579,7 @@ realtimer_settime(struct itimer *it, int flags,
if ((flags & TIMER_ABSTIME) == 0) {
/* Convert to absolute time. */
timespecadd(&it->it_time.it_value, &cts,
- &it->it_time.it_value);
+ &it->it_time.it_value);
} else {
timespecsub(&ts, &cts, &ts);
/*
diff --git a/freebsd/sys/kern/subr_blist.c b/freebsd/sys/kern/subr_blist.c
index a7d78d86..e5b40e62 100644
--- a/freebsd/sys/kern/subr_blist.c
+++ b/freebsd/sys/kern/subr_blist.c
@@ -226,17 +226,19 @@ blist_create(daddr_t blocks, int flags)
u_daddr_t nodes, radix, skip;
int digit;
+ if (blocks == 0)
+ panic("invalid block count");
+
/*
- * Calculate the radix and node count used for scanning. Find the last
- * block that is followed by a terminator.
+ * Calculate the radix and node count used for scanning.
*/
last_block = blocks - 1;
radix = BLIST_BMAP_RADIX;
while (radix < blocks) {
if (((last_block / radix + 1) & BLIST_META_MASK) != 0)
/*
- * A terminator will be added. Update last_block to the
- * position just before that terminator.
+ * We must widen the blist to avoid partially
+ * filled nodes.
*/
last_block |= radix - 1;
radix *= BLIST_META_RADIX;
@@ -246,7 +248,9 @@ blist_create(daddr_t blocks, int flags)
* Count the meta-nodes in the expanded tree, including the final
* terminator, from the bottom level up to the root.
*/
- nodes = (last_block >= blocks) ? 2 : 1;
+ nodes = 1;
+ if (radix - blocks >= BLIST_BMAP_RADIX)
+ nodes++;
last_block /= BLIST_BMAP_RADIX;
while (last_block > 0) {
nodes += last_block + 1;
diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c
index 0626ec0a..391b2ed6 100644
--- a/freebsd/sys/kern/subr_bus.c
+++ b/freebsd/sys/kern/subr_bus.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <sys/random.h>
#include <sys/rman.h>
+#include <sys/sbuf.h>
#include <sys/selinfo.h>
#include <sys/signalvar.h>
#include <sys/smp.h>
@@ -60,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/bus.h>
-#include <sys/interrupt.h>
#include <sys/cpuset.h>
#include <net/vnet.h>
@@ -84,6 +84,8 @@ struct driverlink {
kobj_class_t driver;
TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */
int pass;
+ int flags;
+#define DL_DEFERRED_PROBE 1 /* Probe deferred on this */
TAILQ_ENTRY(driverlink) passlink;
};
@@ -155,6 +157,9 @@ EVENTHANDLER_LIST_DEFINE(device_detach);
EVENTHANDLER_LIST_DEFINE(dev_lookup);
static void devctl2_init(void);
+static bool device_frozen;
+#else /* __rtems__ */
+#define device_frozen false
#endif /* __rtems__ */
#define DRIVERNAME(d) ((d)? d->name : "no driver")
@@ -885,27 +890,18 @@ sysctl_devctl_queue(SYSCTL_HANDLER_ARGS)
* Strings are always terminated with a NUL, but may be truncated if longer
* than @p len bytes after quotes.
*
- * @param dst Buffer to hold the string. Must be at least @p len bytes long
+ * @param sb sbuf to place the characters into
* @param src Original buffer.
- * @param len Length of buffer pointed to by @dst, including trailing NUL
*/
void
-devctl_safe_quote(char *dst, const char *src, size_t len)
+devctl_safe_quote_sb(struct sbuf *sb, const char *src)
{
- char *walker = dst, *ep = dst + len - 1;
- if (len == 0)
- return;
- while (src != NULL && walker < ep)
- {
- if (*src == '"' || *src == '\\') {
- if (ep - walker < 2)
- break;
- *walker++ = '\\';
- }
- *walker++ = *src++;
+ while (*src != '\0') {
+ if (*src == '"' || *src == '\\')
+ sbuf_putc(sb, '\\');
+ sbuf_putc(sb, *src++);
}
- *walker = '\0';
}
/* End of /dev/devctl code */
@@ -1204,7 +1200,11 @@ devclass_add_driver(devclass_t dc, driver_t *driver, int pass, devclass_t *dcp)
dl->pass = pass;
driver_register_pass(dl);
- devclass_driver_added(dc, driver);
+ if (device_frozen) {
+ dl->flags |= DL_DEFERRED_PROBE;
+ } else {
+ devclass_driver_added(dc, driver);
+ }
bus_data_generation_update();
return (0);
}
@@ -1244,6 +1244,9 @@ devclass_driver_deleted(devclass_t busclass, devclass_t dc, driver_t *driver)
* Note that since a driver can be in multiple devclasses, we
* should not detach devices which are not children of devices in
* the affected devclass.
+ *
+ * If we're frozen, we don't generate NOMATCH events. Mark to
+ * generate later.
*/
for (i = 0; i < dc->maxunit; i++) {
if (dc->devices[i]) {
@@ -1252,9 +1255,14 @@ devclass_driver_deleted(devclass_t busclass, devclass_t dc, driver_t *driver)
dev->parent->devclass == busclass) {
if ((error = device_detach(dev)) != 0)
return (error);
- BUS_PROBE_NOMATCH(dev->parent, dev);
- devnomatch(dev);
- dev->flags |= DF_DONENOMATCH;
+ if (device_frozen) {
+ dev->flags &= ~DF_DONENOMATCH;
+ dev->flags |= DF_NEEDNOMATCH;
+ } else {
+ BUS_PROBE_NOMATCH(dev->parent, dev);
+ devnomatch(dev);
+ dev->flags |= DF_DONENOMATCH;
+ }
}
}
}
@@ -2958,6 +2966,7 @@ int
device_attach(device_t dev)
{
uint64_t attachtime;
+ uint16_t attachentropy;
int error;
#ifndef __rtems__
@@ -2985,19 +2994,12 @@ device_attach(device_t dev)
dev->state = DS_NOTPRESENT;
return (error);
}
- attachtime = get_cyclecount() - attachtime;
- /*
- * 4 bits per device is a reasonable value for desktop and server
- * hardware with good get_cyclecount() implementations, but WILL
- * need to be adjusted on other platforms.
+ dev->flags |= DF_ATTACHED_ONCE;
+ /* We only need the low bits of this time, but ranges from tens to thousands
+ * have been seen, so keep 2 bytes' worth.
*/
-#define RANDOM_PROBE_BIT_GUESS 4
- if (bootverbose)
- printf("random: harvesting attach, %zu bytes (%d bits) from %s%d\n",
- sizeof(attachtime), RANDOM_PROBE_BIT_GUESS,
- dev->driver->name, dev->unit);
- random_harvest_direct(&attachtime, sizeof(attachtime),
- RANDOM_PROBE_BIT_GUESS, RANDOM_ATTACH);
+ attachentropy = (uint16_t)(get_cyclecount() - attachtime);
+ random_harvest_direct(&attachentropy, sizeof(attachentropy), RANDOM_ATTACH);
device_sysctl_update(dev);
if (dev->busy)
dev->state = DS_BUSY;
@@ -5474,6 +5476,53 @@ driver_exists(device_t bus, const char *driver)
return (false);
}
+static void
+device_gen_nomatch(device_t dev)
+{
+ device_t child;
+
+ if (dev->flags & DF_NEEDNOMATCH &&
+ dev->state == DS_NOTPRESENT) {
+ BUS_PROBE_NOMATCH(dev->parent, dev);
+ devnomatch(dev);
+ dev->flags |= DF_DONENOMATCH;
+ }
+ dev->flags &= ~DF_NEEDNOMATCH;
+ TAILQ_FOREACH(child, &dev->children, link) {
+ device_gen_nomatch(child);
+ }
+}
+
+static void
+device_do_deferred_actions(void)
+{
+ devclass_t dc;
+ driverlink_t dl;
+
+ /*
+ * Walk through the devclasses to find all the drivers we've tagged as
+ * deferred during the freeze and call the driver added routines. They
+ * have already been added to the lists in the background, so the driver
+ * added routines that trigger a probe will have all the right bidders
+ * for the probe auction.
+ */
+ TAILQ_FOREACH(dc, &devclasses, link) {
+ TAILQ_FOREACH(dl, &dc->drivers, link) {
+ if (dl->flags & DL_DEFERRED_PROBE) {
+ devclass_driver_added(dc, dl->driver);
+ dl->flags &= ~DL_DEFERRED_PROBE;
+ }
+ }
+ }
+
+ /*
+ * We also defer no-match events during a freeze. Walk the tree and
+ * generate all the pent-up events that are still relevant.
+ */
+ device_gen_nomatch(root_bus);
+ bus_data_generation_update();
+}
+
static int
devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
@@ -5500,6 +5549,10 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
if (error == 0)
error = find_device(req, &dev);
break;
+ case DEV_FREEZE:
+ case DEV_THAW:
+ error = priv_check(td, PRIV_DRIVER);
+ break;
default:
error = ENOTTY;
break;
@@ -5703,7 +5756,23 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
error = device_delete_child(parent, dev);
break;
}
+#ifndef __rtems__
+ case DEV_FREEZE:
+ if (device_frozen)
+ error = EBUSY;
+ else
+ device_frozen = true;
+ break;
+ case DEV_THAW:
+ if (!device_frozen)
+ error = EBUSY;
+ else {
+ device_do_deferred_actions();
+ device_frozen = false;
+ }
+ break;
}
+#endif /* __rtems__ */
mtx_unlock(&Giant);
return (error);
}
diff --git a/freebsd/sys/kern/subr_counter.c b/freebsd/sys/kern/subr_counter.c
index e4c98fae..66cda02b 100644
--- a/freebsd/sys/kern/subr_counter.c
+++ b/freebsd/sys/kern/subr_counter.c
@@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
#define IN_SUBR_COUNTER_C
#include <sys/counter.h>
-
+
void
counter_u64_zero(counter_u64_t c)
{
@@ -62,20 +62,15 @@ counter_u64_fetch(counter_u64_t c)
counter_u64_t
counter_u64_alloc(int flags)
{
- counter_u64_t r;
-
- r = uma_zalloc(pcpu_zone_64, flags);
- if (r != NULL)
- counter_u64_zero(r);
- return (r);
+ return (uma_zalloc_pcpu(pcpu_zone_64, flags | M_ZERO));
}
void
counter_u64_free(counter_u64_t c)
{
- uma_zfree(pcpu_zone_64, c);
+ uma_zfree_pcpu(pcpu_zone_64, c);
}
int
@@ -142,7 +137,7 @@ counter_ratecheck(struct counter_rate *cr, int64_t limit)
val = cr->cr_over;
now = ticks;
- if (now - cr->cr_ticks >= hz) {
+ if ((u_int)(now - cr->cr_ticks) >= hz) {
/*
* Time to clear the structure, we are in the next second.
* First try unlocked read, and then proceed with atomic.
@@ -153,7 +148,7 @@ counter_ratecheck(struct counter_rate *cr, int64_t limit)
* Check if other thread has just went through the
* reset sequence before us.
*/
- if (now - cr->cr_ticks >= hz) {
+ if ((u_int)(now - cr->cr_ticks) >= hz) {
val = counter_u64_fetch(cr->cr_rate);
counter_u64_zero(cr->cr_rate);
cr->cr_over = 0;
diff --git a/freebsd/sys/kern/subr_gtaskqueue.c b/freebsd/sys/kern/subr_gtaskqueue.c
index aa5c922d..e56e90d7 100644
--- a/freebsd/sys/kern/subr_gtaskqueue.c
+++ b/freebsd/sys/kern/subr_gtaskqueue.c
@@ -921,6 +921,24 @@ taskqgroup_bind(struct taskqgroup *qgroup)
}
}
+static void
+taskqgroup_config_init(void *arg)
+{
+ struct taskqgroup *qgroup = qgroup_config;
+ LIST_HEAD(, grouptask) gtask_head = LIST_HEAD_INITIALIZER(NULL);
+
+ LIST_SWAP(&gtask_head, &qgroup->tqg_queue[0].tgc_tasks,
+ grouptask, gt_list);
+ qgroup->tqg_queue[0].tgc_cnt = 0;
+ taskqgroup_cpu_create(qgroup, 0, 0);
+
+ qgroup->tqg_cnt = 1;
+ qgroup->tqg_stride = 1;
+}
+
+SYSINIT(taskqgroup_config_init, SI_SUB_TASKQ, SI_ORDER_SECOND,
+ taskqgroup_config_init, NULL);
+
static int
_taskqgroup_adjust(struct taskqgroup *qgroup, int cnt, int stride)
{
diff --git a/freebsd/sys/kern/subr_hints.c b/freebsd/sys/kern/subr_hints.c
index 982059c3..78ab1b4e 100644
--- a/freebsd/sys/kern/subr_hints.c
+++ b/freebsd/sys/kern/subr_hints.c
@@ -33,228 +33,257 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/lock.h>
+#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/bus.h>
-/*
- * Access functions for device resources.
- */
-
#ifndef __rtems__
-static int checkmethod = 1;
-static int use_kenv;
-static char *hintp;
-#else /* __rtems__ */
-#define hintmode 1
-#define hintp static_hints
-#define use_kenv 0
-static char __used default_static_hints[] = "";
-__weak_reference(default_static_hints, static_hints);
-#endif /* __rtems__ */
+#define FBACK_MDENV 0 /* MD env (e.g. loader.conf) */
+#define FBACK_STENV 1 /* Static env */
+#define FBACK_STATIC 2 /* static_hints */
-#ifndef __rtems__
/*
- * Define kern.hintmode sysctl, which only accept value 2, that cause to
- * switch from Static KENV mode to Dynamic KENV. So systems that have hints
- * compiled into kernel will be able to see/modify KENV (and hints too).
+ * We'll use hintenv_merged to indicate that the dynamic environment has been
+ * properly prepared for hint usage. This implies that the dynamic environment
+ * has already been setup (dynamic_kenv) and that we have added any supplied
+ * static_hints to the dynamic environment.
+ */
+static bool hintenv_merged;
+/* Static environment and static hints cannot change, so we'll skip known bad */
+static bool stenv_skip;
+static bool sthints_skip;
+/*
+ * Access functions for device resources.
*/
-static int
-sysctl_hintmode(SYSCTL_HANDLER_ARGS)
+static void
+static_hints_to_env(void *data __unused)
{
const char *cp;
char *line, *eq;
- int eqidx, error, from_kenv, i, value;
-
- from_kenv = 0;
- cp = kern_envp;
- value = hintmode;
-
- /* Fetch candidate for new hintmode value */
- error = sysctl_handle_int(oidp, &value, 0, req);
- if (error || req->newptr == NULL)
- return (error);
-
- if (value != 2)
- /* Only accept swithing to hintmode 2 */
- return (EINVAL);
-
- /* Migrate from static to dynamic hints */
- switch (hintmode) {
- case 0:
- if (dynamic_kenv) {
- /*
- * Already here. But assign hintmode to 2, to not
- * check it in the future.
- */
- hintmode = 2;
- return (0);
- }
- from_kenv = 1;
- cp = kern_envp;
- break;
- case 1:
- cp = static_hints;
- break;
- case 2:
- /* Nothing to do, hintmode already 2 */
- return (0);
- }
+ int eqidx, i;
- while (cp) {
- i = strlen(cp);
- if (i == 0)
- break;
- if (from_kenv) {
- if (strncmp(cp, "hint.", 5) != 0)
- /* kenv can have not only hints */
- continue;
- }
+ cp = static_hints;
+ while (cp && *cp != '\0') {
eq = strchr(cp, '=');
if (eq == NULL)
/* Bad hint value */
continue;
eqidx = eq - cp;
- line = malloc(i+1, M_TEMP, M_WAITOK);
+ i = strlen(cp);
+ line = malloc(i + 1, M_TEMP, M_WAITOK);
strcpy(line, cp);
- line[eqidx] = '\0';
- kern_setenv(line, line + eqidx + 1);
+ line[eqidx] = line[i] = '\0';
+ /*
+ * Before adding a hint to the dynamic environment, check if
+ * another value for said hint has already been added. This is
+ * needed because static environment overrides static hints and
+ * dynamic environment overrides all.
+ */
+ if (testenv(line) == 0)
+ kern_setenv(line, line + eqidx + 1);
free(line, M_TEMP);
cp += i + 1;
}
-
- hintmode = value;
- use_kenv = 1;
- return (0);
+ hintenv_merged = true;
}
-SYSCTL_PROC(_kern, OID_AUTO, hintmode, CTLTYPE_INT|CTLFLAG_RW,
- &hintmode, 0, sysctl_hintmode, "I", "Get/set current hintmode");
+/* Any time after dynamic env is setup */
+SYSINIT(hintenv, SI_SUB_KMEM + 1, SI_ORDER_SECOND, static_hints_to_env, NULL);
+#else /* __rtems__ */
+#define sthints_skip false
+
+static char __used default_static_hints[] = "";
+__weak_reference(default_static_hints, static_hints);
#endif /* __rtems__ */
/*
+ * Checks the environment to see if we even have any hints. If it has no hints,
+ * then res_find can take the hint that there's no point in searching it and
+ * either move on to the next environment or fail early.
+ */
+static bool
+_res_checkenv(char *envp)
+{
+ char *cp;
+
+ cp = envp;
+ while (cp) {
+ if (strncmp(cp, "hint.", 5) == 0)
+ return (true);
+ while (*cp != '\0')
+ cp++;
+ cp++;
+ if (*cp == '\0')
+ break;
+ }
+ return (false);
+}
+
+/*
* Evil wildcarding resource string lookup.
* This walks the supplied env string table and returns a match.
* The start point can be remembered for incremental searches.
*/
static int
-res_find(int *line, int *startln,
+res_find(char **hintp_cookie, int *line, int *startln,
const char *name, int *unit, const char *resname, const char *value,
const char **ret_name, int *ret_namelen, int *ret_unit,
const char **ret_resname, int *ret_resnamelen, const char **ret_value)
{
- int n = 0, hit, i = 0;
+#ifndef __rtems__
+ int fbacklvl = FBACK_MDENV, i = 0, n = 0;
+#else /* __rtems__ */
+ int n = 0;
+#endif /* __rtems__ */
char r_name[32];
int r_unit;
char r_resname[32];
char r_value[128];
const char *s, *cp;
- char *p;
-
+ char *hintp, *p;
#ifndef __rtems__
- if (checkmethod) {
- hintp = NULL;
+ bool dyn_used = false;
- switch (hintmode) {
- case 0: /* loader hints in environment only */
- break;
- case 1: /* static hints only */
- hintp = static_hints;
- checkmethod = 0;
- break;
- case 2: /* fallback mode */
- if (dynamic_kenv) {
- mtx_lock(&kenv_lock);
- cp = kenvp[0];
- for (i = 0; cp != NULL; cp = kenvp[++i]) {
- if (!strncmp(cp, "hint.", 5)) {
- use_kenv = 1;
- checkmethod = 0;
- break;
- }
+
+ /*
+ * We are expecting that the caller will pass us a hintp_cookie that
+ * they are tracking. Upon entry, if *hintp_cookie is *not* set, this
+ * indicates to us that we should be figuring out based on the current
+ * environment where to search. This keeps us sane throughout the
+ * entirety of a single search.
+ */
+ if (*hintp_cookie == NULL) {
+ hintp = NULL;
+ if (hintenv_merged) {
+ /*
+ * static_hints, if it was previously used, has
+ * already been folded in to the environment
+ * by this point.
+ */
+ mtx_lock(&kenv_lock);
+ cp = kenvp[0];
+ for (i = 0; cp != NULL; cp = kenvp[++i]) {
+ if (!strncmp(cp, "hint.", 5)) {
+ hintp = kenvp[0];
+ break;
}
- mtx_unlock(&kenv_lock);
- } else {
- cp = kern_envp;
- while (cp) {
- if (strncmp(cp, "hint.", 5) == 0) {
- cp = NULL;
- hintp = kern_envp;
- break;
- }
- while (*cp != '\0')
- cp++;
- cp++;
- if (*cp == '\0') {
- cp = NULL;
- hintp = static_hints;
- break;
- }
+ }
+ mtx_unlock(&kenv_lock);
+ dyn_used = true;
+ } else {
+ /*
+ * We'll have a chance to keep coming back here until
+ * we've actually exhausted all of our possibilities.
+ * We might have chosen the MD/Static env because it
+ * had some kind of hints, but perhaps it didn't have
+ * the hint we are looking for. We don't provide any
+ * fallback when searching the dynamic environment.
+ */
+fallback:
+ if (dyn_used || fbacklvl >= FBACK_STATIC)
+ return (ENOENT);
+
+ switch (fbacklvl) {
+ case FBACK_MDENV:
+ fbacklvl++;
+ if (_res_checkenv(md_envp)) {
+ hintp = md_envp;
+ break;
}
+
+ /* FALLTHROUGH */
+ case FBACK_STENV:
+ fbacklvl++;
+ if (!stenv_skip && _res_checkenv(kern_envp)) {
+ hintp = kern_envp;
+ break;
+ } else
+ stenv_skip = true;
+
+ /* FALLTHROUGH */
+ case FBACK_STATIC:
+ fbacklvl++;
+#else /* __rtems__ */
+ hintp = NULL;
+#endif /* __rtems__ */
+ /* We'll fallback to static_hints if needed/can */
+ if (!sthints_skip &&
+ _res_checkenv(static_hints))
+ hintp = static_hints;
+#ifndef __rtems__
+ else
+ sthints_skip = true;
+
+ break;
+ default:
+ return (ENOENT);
}
- break;
- default:
- break;
- }
- if (hintp == NULL) {
- if (dynamic_kenv) {
- use_kenv = 1;
- checkmethod = 0;
- } else
- hintp = kern_envp;
}
+#endif /* __rtems__ */
+
+ if (hintp == NULL)
+ return (ENOENT);
+ *hintp_cookie = hintp;
+#ifndef __rtems__
+ } else {
+ hintp = *hintp_cookie;
+ if (hintenv_merged && hintp == kenvp[0])
+ dyn_used = true;
+ else
+ /*
+ * If we aren't using the dynamic environment, we need
+ * to run through the proper fallback procedure again.
+ * This is so that we do continuations right if we're
+ * working with *line and *startln.
+ */
+ goto fallback;
}
- if (use_kenv) {
+ if (dyn_used) {
mtx_lock(&kenv_lock);
i = 0;
- cp = kenvp[0];
- if (cp == NULL) {
- mtx_unlock(&kenv_lock);
- return (ENOENT);
- }
- } else
+ }
#endif /* __rtems__ */
- cp = hintp;
+
+ cp = hintp;
while (cp) {
- hit = 1;
(*line)++;
if (strncmp(cp, "hint.", 5) != 0)
- hit = 0;
- else
- n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%127s",
- r_name, &r_unit, r_resname, r_value);
- if (hit && n != 4) {
+ goto nexthint;
+ n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%127s", r_name, &r_unit,
+ r_resname, r_value);
+ if (n != 4) {
printf("CONFIG: invalid hint '%s'\n", cp);
p = strchr(cp, 'h');
*p = 'H';
- hit = 0;
+ goto nexthint;
}
- if (hit && startln && *startln >= 0 && *line < *startln)
- hit = 0;
- if (hit && name && strcmp(name, r_name) != 0)
- hit = 0;
- if (hit && unit && *unit != r_unit)
- hit = 0;
- if (hit && resname && strcmp(resname, r_resname) != 0)
- hit = 0;
- if (hit && value && strcmp(value, r_value) != 0)
- hit = 0;
- if (hit)
- break;
- if (use_kenv) {
+ if (startln && *startln >= 0 && *line < *startln)
+ goto nexthint;
+ if (name && strcmp(name, r_name) != 0)
+ goto nexthint;
+ if (unit && *unit != r_unit)
+ goto nexthint;
+ if (resname && strcmp(resname, r_resname) != 0)
+ goto nexthint;
+ if (value && strcmp(value, r_value) != 0)
+ goto nexthint;
+ /* Successfully found a hint matching all criteria */
+ break;
+nexthint:
#ifndef __rtems__
+ if (dyn_used) {
cp = kenvp[++i];
if (cp == NULL)
break;
-#else /* __rtems__ */
(void) i;
-#endif /* __rtems__ */
} else {
+#endif /* __rtems__ */
while (*cp != '\0')
cp++;
cp++;
@@ -262,14 +291,20 @@ res_find(int *line, int *startln,
cp = NULL;
break;
}
+#ifndef __rtems__
}
+#endif /* __rtems__ */
}
#ifndef __rtems__
- if (use_kenv)
+ if (dyn_used)
mtx_unlock(&kenv_lock);
#endif /* __rtems__ */
if (cp == NULL)
- return ENOENT;
+#ifndef __rtems__
+ goto fallback;
+#else /* __rtems__ */
+ return (ENOENT);
+#endif /* __rtems__ */
s = cp;
/* This is a bit of a hack, but at least is reentrant */
@@ -307,11 +342,13 @@ resource_find(int *line, int *startln,
{
int i;
int un;
+ char *hintp;
*line = 0;
+ hintp = NULL;
/* Search for exact unit matches first */
- i = res_find(line, startln, name, unit, resname, value,
+ i = res_find(&hintp, line, startln, name, unit, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
@@ -320,7 +357,7 @@ resource_find(int *line, int *startln,
return ENOENT;
/* If we are still here, search for wildcard matches */
un = -1;
- i = res_find(line, startln, name, &un, resname, value,
+ i = res_find(&hintp, line, startln, name, &un, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
diff --git a/freebsd/sys/kern/subr_module.c b/freebsd/sys/kern/subr_module.c
index d8d42653..21b2754c 100644
--- a/freebsd/sys/kern/subr_module.c
+++ b/freebsd/sys/kern/subr_module.c
@@ -35,6 +35,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/linker.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+
/*
* Preloaded module support
*/
@@ -206,29 +209,42 @@ preload_search_info(caddr_t mod, int inf)
void
preload_delete_name(const char *name)
{
- caddr_t curp;
- uint32_t *hdr;
+ caddr_t addr, curp;
+ uint32_t *hdr, sz;
int next;
int clearing;
+
+ addr = 0;
+ sz = 0;
if (preload_metadata != NULL) {
-
+
clearing = 0;
curp = preload_metadata;
for (;;) {
hdr = (uint32_t *)curp;
- if (hdr[0] == 0 && hdr[1] == 0)
- break;
-
- /* Search for a MODINFO_NAME field */
- if (hdr[0] == MODINFO_NAME) {
+ if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) {
+ /* Free memory used to store the file. */
+ if (addr != 0 && sz != 0)
+ kmem_bootstrap_free((vm_offset_t)addr, sz);
+ addr = 0;
+ sz = 0;
+
+ if (hdr[0] == 0)
+ break;
if (!strcmp(name, curp + sizeof(uint32_t) * 2))
clearing = 1; /* got it, start clearing */
- else if (clearing)
+ else if (clearing) {
clearing = 0; /* at next one now.. better stop */
+ }
}
- if (clearing)
+ if (clearing) {
+ if (hdr[0] == MODINFO_ADDR)
+ addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2);
+ else if (hdr[0] == MODINFO_SIZE)
+ sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2);
hdr[0] = MODINFO_EMPTY;
+ }
/* skip to next field */
next = sizeof(uint32_t) * 2 + hdr[1];
diff --git a/freebsd/sys/kern/subr_pcpu.c b/freebsd/sys/kern/subr_pcpu.c
index 1b866e3a..0ab77996 100644
--- a/freebsd/sys/kern/subr_pcpu.c
+++ b/freebsd/sys/kern/subr_pcpu.c
@@ -75,7 +75,7 @@ struct dpcpu_free {
TAILQ_ENTRY(dpcpu_free) df_link;
};
-static DPCPU_DEFINE(char, modspace[DPCPU_MODMIN]);
+DPCPU_DEFINE_STATIC(char, modspace[DPCPU_MODMIN] __aligned(__alignof(void *)));
static TAILQ_HEAD(, dpcpu_free) dpcpu_head = TAILQ_HEAD_INITIALIZER(dpcpu_head);
static struct sx dpcpu_lock;
uintptr_t dpcpu_off[MAXCPU];
diff --git a/freebsd/sys/kern/subr_prf.c b/freebsd/sys/kern/subr_prf.c
index 4c45bcfe..6e719897 100644
--- a/freebsd/sys/kern/subr_prf.c
+++ b/freebsd/sys/kern/subr_prf.c
@@ -135,10 +135,22 @@ static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
static void snprintf_func(int ch, void *arg);
#ifndef __rtems__
-static int msgbufmapped; /* Set when safe to use msgbuf */
+static bool msgbufmapped; /* Set when safe to use msgbuf */
int msgbuftrigger;
struct msgbuf *msgbufp;
+#ifndef BOOT_TAG_SZ
+#define BOOT_TAG_SZ 32
+#endif
+#ifndef BOOT_TAG
+/* Tag used to mark the start of a boot in dmesg */
+#define BOOT_TAG "---<<BOOT>>---"
+#endif
+
+static char current_boot_tag[BOOT_TAG_SZ + 1] = BOOT_TAG;
+SYSCTL_STRING(_kern, OID_AUTO, boot_tag, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
+ current_boot_tag, 0, "Tag added to dmesg at start of boot");
+
static int log_console_output = 1;
SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN,
&log_console_output, 0, "Duplicate console output to the syslog");
@@ -743,6 +755,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
padc = '0';
goto reswitch;
}
+ /* FALLTHROUGH */
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (n = 0;; ++fmt) {
@@ -1057,14 +1070,22 @@ msgbufinit(void *ptr, int size)
{
char *cp;
static struct msgbuf *oldp = NULL;
+ bool print_boot_tag;
size -= sizeof(*msgbufp);
cp = (char *)ptr;
+ print_boot_tag = !msgbufmapped;
+ /* Attempt to fetch kern.boot_tag tunable on first mapping */
+ if (!msgbufmapped)
+ TUNABLE_STR_FETCH("kern.boot_tag", current_boot_tag,
+ sizeof(current_boot_tag));
msgbufp = (struct msgbuf *)(cp + size);
msgbuf_reinit(msgbufp, cp, size);
if (msgbufmapped && oldp != msgbufp)
msgbuf_copy(oldp, msgbufp);
- msgbufmapped = 1;
+ msgbufmapped = true;
+ if (print_boot_tag && *current_boot_tag != '\0')
+ printf("%s\n", current_boot_tag);
oldp = msgbufp;
}
diff --git a/freebsd/sys/kern/sys_pipe.c b/freebsd/sys/kern/sys_pipe.c
index e527495a..8eb0aad9 100755
--- a/freebsd/sys/kern/sys_pipe.c
+++ b/freebsd/sys/kern/sys_pipe.c
@@ -572,9 +572,7 @@ pipe(int fildes[2])
* If it fails it will return ENOMEM.
*/
static int
-pipespace_new(cpipe, size)
- struct pipe *cpipe;
- int size;
+pipespace_new(struct pipe *cpipe, int size)
{
caddr_t buffer;
int error, cnt, firstseg;
@@ -646,9 +644,7 @@ retry:
* Wrapper for pipespace_new() that performs locking assertions.
*/
static int
-pipespace(cpipe, size)
- struct pipe *cpipe;
- int size;
+pipespace(struct pipe *cpipe, int size)
{
KASSERT(cpipe->pipe_state & PIPE_LOCKFL,
@@ -660,9 +656,7 @@ pipespace(cpipe, size)
* lock a pipe for I/O, blocking other access
*/
static __inline int
-pipelock(cpipe, catch)
- struct pipe *cpipe;
- int catch;
+pipelock(struct pipe *cpipe, int catch)
{
int error;
@@ -683,8 +677,7 @@ pipelock(cpipe, catch)
* unlock a pipe I/O lock
*/
static __inline void
-pipeunlock(cpipe)
- struct pipe *cpipe;
+pipeunlock(struct pipe *cpipe)
{
PIPE_LOCK_ASSERT(cpipe, MA_OWNED);
@@ -698,8 +691,7 @@ pipeunlock(cpipe)
}
void
-pipeselwakeup(cpipe)
- struct pipe *cpipe;
+pipeselwakeup(struct pipe *cpipe)
{
PIPE_LOCK_ASSERT(cpipe, MA_OWNED);
@@ -720,9 +712,7 @@ pipeselwakeup(cpipe)
* will start out zero'd from the ctor, so we just manage the kmem.
*/
static void
-pipe_create(pipe, backing)
- struct pipe *pipe;
- int backing;
+pipe_create(struct pipe *pipe, int backing)
{
if (backing) {
@@ -744,12 +734,8 @@ pipe_create(pipe, backing)
/* ARGSUSED */
static int
-pipe_read(fp, uio, active_cred, flags, td)
- struct file *fp;
- struct uio *uio;
- struct ucred *active_cred;
- struct thread *td;
- int flags;
+pipe_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
+ int flags, struct thread *td)
{
struct pipe *rpipe;
int error;
@@ -995,9 +981,7 @@ rtems_bsd_pipe_readv(rtems_libio_t *iop, const struct iovec *iov,
* This is similar to a physical write operation.
*/
static int
-pipe_build_write_buffer(wpipe, uio)
- struct pipe *wpipe;
- struct uio *uio;
+pipe_build_write_buffer(struct pipe *wpipe, struct uio *uio)
{
u_int size;
int i;
@@ -1041,8 +1025,7 @@ pipe_build_write_buffer(wpipe, uio)
* unmap and unwire the process buffer
*/
static void
-pipe_destroy_write_buffer(wpipe)
- struct pipe *wpipe;
+pipe_destroy_write_buffer(struct pipe *wpipe)
{
PIPE_LOCK_ASSERT(wpipe, MA_OWNED);
@@ -1056,8 +1039,7 @@ pipe_destroy_write_buffer(wpipe)
* pages can be freed without loss of data.
*/
static void
-pipe_clone_write_buffer(wpipe)
- struct pipe *wpipe;
+pipe_clone_write_buffer(struct pipe *wpipe)
{
struct uio uio;
struct iovec iov;
@@ -1096,9 +1078,7 @@ pipe_clone_write_buffer(wpipe)
* the pipe buffer. Then the direct mapping write is set-up.
*/
static int
-pipe_direct_write(wpipe, uio)
- struct pipe *wpipe;
- struct uio *uio;
+pipe_direct_write(struct pipe *wpipe, struct uio *uio)
{
int error;
@@ -1197,12 +1177,8 @@ error1:
#endif
static int
-pipe_write(fp, uio, active_cred, flags, td)
- struct file *fp;
- struct uio *uio;
- struct ucred *active_cred;
- struct thread *td;
- int flags;
+pipe_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
+ int flags, struct thread *td)
{
int error = 0;
int desiredsize;
@@ -1553,11 +1529,8 @@ rtems_bsd_pipe_writev(rtems_libio_t *iop, const struct iovec *iov,
/* ARGSUSED */
#ifndef __rtems__
static int
-pipe_truncate(fp, length, active_cred, td)
- struct file *fp;
- off_t length;
- struct ucred *active_cred;
- struct thread *td;
+pipe_truncate(struct file *fp, off_t length, struct ucred *active_cred,
+ struct thread *td)
{
struct pipe *cpipe;
int error;
@@ -1575,12 +1548,8 @@ pipe_truncate(fp, length, active_cred, td)
* we implement a very minimal set of ioctls for compatibility with sockets.
*/
static int
-pipe_ioctl(fp, cmd, data, active_cred, td)
- struct file *fp;
- u_long cmd;
- void *data;
- struct ucred *active_cred;
- struct thread *td;
+pipe_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
+ struct thread *td)
{
struct pipe *mpipe = fp->f_data;
int error;
@@ -1672,11 +1641,8 @@ rtems_bsd_pipe_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
#endif /* __rtems__ */
static int
-pipe_poll(fp, events, active_cred, td)
- struct file *fp;
- int events;
- struct ucred *active_cred;
- struct thread *td;
+pipe_poll(struct file *fp, int events, struct ucred *active_cred,
+ struct thread *td)
{
struct pipe *rpipe;
struct pipe *wpipe;
@@ -1786,11 +1752,8 @@ rtems_bsd_pipe_poll(rtems_libio_t *iop, int events)
*/
#ifndef __rtems__
static int
-pipe_stat(fp, ub, active_cred, td)
- struct file *fp;
- struct stat *ub;
- struct ucred *active_cred;
- struct thread *td;
+pipe_stat(struct file *fp, struct stat *ub, struct ucred *active_cred,
+ struct thread *td)
{
struct pipe *pipe;
#else /* __rtems__ */
@@ -1889,9 +1852,7 @@ rtems_bsd_pipe_stat(
/* ARGSUSED */
static int
-pipe_close(fp, td)
- struct file *fp;
- struct thread *td;
+pipe_close(struct file *fp, struct thread *td)
{
#ifndef __rtems__
@@ -1922,12 +1883,8 @@ pipe_chmod(struct file *fp, mode_t mode, struct ucred *active_cred, struct threa
}
static int
-pipe_chown(fp, uid, gid, active_cred, td)
- struct file *fp;
- uid_t uid;
- gid_t gid;
- struct ucred *active_cred;
- struct thread *td;
+pipe_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
{
struct pipe *cpipe;
int error;
@@ -1957,8 +1914,7 @@ pipe_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
#endif /* __rtems__ */
static void
-pipe_free_kmem(cpipe)
- struct pipe *cpipe;
+pipe_free_kmem(struct pipe *cpipe)
{
KASSERT(!mtx_owned(PIPE_MTX(cpipe)),
@@ -1988,8 +1944,7 @@ pipe_free_kmem(cpipe)
* shutdown the pipe
*/
static void
-pipeclose(cpipe)
- struct pipe *cpipe;
+pipeclose(struct pipe *cpipe)
{
struct pipepair *pp;
struct pipe *ppipe;
diff --git a/freebsd/sys/kern/uipc_sockbuf.c b/freebsd/sys/kern/uipc_sockbuf.c
index ec493c04..cf99c615 100644
--- a/freebsd/sys/kern/uipc_sockbuf.c
+++ b/freebsd/sys/kern/uipc_sockbuf.c
@@ -961,23 +961,14 @@ sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa,
return (retval);
}
-int
+void
sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control)
{
- struct mbuf *m, *n, *mlast;
- int space;
-
- SOCKBUF_LOCK_ASSERT(sb);
+ struct mbuf *m, *mlast;
- if (control == NULL)
- panic("sbappendcontrol_locked");
- space = m_length(control, &n) + m_length(m0, NULL);
-
- if (space > sbspace(sb))
- return (0);
m_clrprotoflags(m0);
- n->m_next = m0; /* concatenate data to control */
+ m_last(control)->m_next = m0;
SBLASTRECORDCHK(sb);
@@ -991,18 +982,15 @@ sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
SBLASTMBUFCHK(sb);
SBLASTRECORDCHK(sb);
- return (1);
}
-int
+void
sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
{
- int retval;
SOCKBUF_LOCK(sb);
- retval = sbappendcontrol_locked(sb, m0, control);
+ sbappendcontrol_locked(sb, m0, control);
SOCKBUF_UNLOCK(sb);
- return (retval);
}
/*
@@ -1289,6 +1277,63 @@ sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff)
return (ret);
}
+struct mbuf *
+#ifndef __rtems__
+sbsndptr_noadv(struct sockbuf *sb, uint32_t off, uint32_t *moff)
+#else /* __rtems__ */
+sbsndptr_noadv(struct sockbuf *sb, u_int off, u_int *moff)
+#endif /* __rtems__ */
+{
+ struct mbuf *m;
+
+ KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__));
+ if (sb->sb_sndptr == NULL || sb->sb_sndptroff > off) {
+ *moff = off;
+ if (sb->sb_sndptr == NULL) {
+ sb->sb_sndptr = sb->sb_mb;
+ sb->sb_sndptroff = 0;
+ }
+ return (sb->sb_mb);
+ } else {
+ m = sb->sb_sndptr;
+ off -= sb->sb_sndptroff;
+ }
+ *moff = off;
+ return (m);
+}
+
+void
+#ifndef __rtems__
+sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, uint32_t len)
+#else /* __rtems__ */
+sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, u_int len)
+#endif /* __rtems__ */
+{
+ /*
+ * A small copy was done, advance forward the sb_sbsndptr to cover
+ * it.
+ */
+ struct mbuf *m;
+
+ if (mb != sb->sb_sndptr) {
+ /* Did not copyout at the same mbuf */
+ return;
+ }
+ m = mb;
+ while (m && (len > 0)) {
+ if (len >= m->m_len) {
+ len -= m->m_len;
+ if (m->m_next) {
+ sb->sb_sndptroff += m->m_len;
+ sb->sb_sndptr = m->m_next;
+ }
+ m = m->m_next;
+ } else {
+ len = 0;
+ }
+ }
+}
+
/*
* Return the first mbuf and the mbuf data offset for the provided
* send offset without changing the "sb_sndptroff" field.
diff --git a/freebsd/sys/kern/uipc_socket.c b/freebsd/sys/kern/uipc_socket.c
index e82642e4..3143a392 100644
--- a/freebsd/sys/kern/uipc_socket.c
+++ b/freebsd/sys/kern/uipc_socket.c
@@ -1126,6 +1126,8 @@ soclose(struct socket *so)
drop:
if (so->so_proto->pr_usrreqs->pru_close != NULL)
(*so->so_proto->pr_usrreqs->pru_close)(so);
+ if (so->so_dtor != NULL)
+ so->so_dtor(so);
SOCK_LOCK(so);
if ((listening = (so->so_options & SO_ACCEPTCONN))) {
@@ -2191,7 +2193,6 @@ release:
/*
* Optimized version of soreceive() for stream (TCP) sockets.
- * XXXAO: (MSG_WAITALL | MSG_PEEK) isn't properly handled.
*/
int
soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *uio,
@@ -2206,12 +2207,12 @@ soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *uio,
return (EINVAL);
if (psa != NULL)
*psa = NULL;
- if (controlp != NULL)
- return (EINVAL);
if (flagsp != NULL)
flags = *flagsp &~ MSG_EOR;
else
flags = 0;
+ if (controlp != NULL)
+ *controlp = NULL;
if (flags & MSG_OOB)
return (soreceive_rcvoob(so, uio, flags));
if (mp0 != NULL)
@@ -2815,6 +2816,7 @@ sosetopt(struct socket *so, struct sockopt *sopt)
case SO_BROADCAST:
case SO_REUSEADDR:
case SO_REUSEPORT:
+ case SO_REUSEPORT_LB:
case SO_OOBINLINE:
case SO_TIMESTAMP:
case SO_BINTIME:
@@ -3035,6 +3037,7 @@ sogetopt(struct socket *so, struct sockopt *sopt)
case SO_KEEPALIVE:
case SO_REUSEADDR:
case SO_REUSEPORT:
+ case SO_REUSEPORT_LB:
case SO_BROADCAST:
case SO_OOBINLINE:
case SO_ACCEPTCONN:
@@ -3046,6 +3049,10 @@ integer:
error = sooptcopyout(sopt, &optval, sizeof optval);
break;
+ case SO_DOMAIN:
+ optval = so->so_proto->pr_domain->dom_family;
+ goto integer;
+
case SO_TYPE:
optval = so->so_type;
goto integer;
@@ -3867,6 +3874,17 @@ sodupsockaddr(const struct sockaddr *sa, int mflags)
}
/*
+ * Register per-socket destructor.
+ */
+void
+sodtor_set(struct socket *so, so_dtor_t *func)
+{
+
+ SOCK_LOCK_ASSERT(so);
+ so->so_dtor = func;
+}
+
+/*
* Register per-socket buffer upcalls.
*/
void
@@ -4027,12 +4045,12 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
{
xso->xso_len = sizeof *xso;
- xso->xso_so = so;
+ xso->xso_so = (uintptr_t)so;
xso->so_type = so->so_type;
xso->so_options = so->so_options;
xso->so_linger = so->so_linger;
xso->so_state = so->so_state;
- xso->so_pcb = so->so_pcb;
+ xso->so_pcb = (uintptr_t)so->so_pcb;
xso->xso_protocol = so->so_proto->pr_protocol;
xso->xso_family = so->so_proto->pr_domain->dom_family;
xso->so_timeo = so->so_timeo;
diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c
index 0872aa62..9c4c52e4 100644
--- a/freebsd/sys/kern/uipc_syscalls.c
+++ b/freebsd/sys/kern/uipc_syscalls.c
@@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socketvar.h>
#include <sys/syscallsubr.h>
#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -831,6 +833,15 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol,
error = soconnect2(so2, so1);
if (error != 0)
goto free4;
+ } else if (so1->so_proto->pr_flags & PR_CONNREQUIRED) {
+ struct unpcb *unp, *unp2;
+ unp = sotounpcb(so1);
+ unp2 = sotounpcb(so2);
+ /*
+ * No need to lock the unps, because the sockets are brand-new.
+ * No other threads can be using them yet
+ */
+ unp_copy_peercred(td, unp, unp2, unp);
}
finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
&socketops);
@@ -1260,7 +1271,7 @@ kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
{
struct uio auio;
struct iovec *iov;
- struct mbuf *m, *control = NULL;
+ struct mbuf *control, *m;
caddr_t ctlbuf;
struct file *fp;
struct socket *so;
@@ -1307,6 +1318,7 @@ kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
if (KTRPOINT(td, KTR_GENIO))
ktruio = cloneuio(&auio);
#endif
+ control = NULL;
len = auio.uio_resid;
error = soreceive(so, &fromsa, &auio, NULL,
(mp->msg_control || controlp) ? &control : NULL,
@@ -1370,30 +1382,22 @@ kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
control->m_data += sizeof (struct cmsghdr);
}
#endif
+ ctlbuf = mp->msg_control;
len = mp->msg_controllen;
- m = control;
mp->msg_controllen = 0;
- ctlbuf = mp->msg_control;
-
- while (m && len > 0) {
- unsigned int tocopy;
-
- if (len >= m->m_len)
- tocopy = m->m_len;
- else {
- mp->msg_flags |= MSG_CTRUNC;
- tocopy = len;
- }
-
- if ((error = copyout(mtod(m, caddr_t),
- ctlbuf, tocopy)) != 0)
+ for (m = control; m != NULL && len >= m->m_len; m = m->m_next) {
+ if ((error = copyout(mtod(m, caddr_t), ctlbuf,
+ m->m_len)) != 0)
goto out;
- ctlbuf += tocopy;
- len -= tocopy;
- m = m->m_next;
+ ctlbuf += m->m_len;
+ len -= m->m_len;
+ mp->msg_controllen += m->m_len;
+ }
+ if (m != NULL) {
+ mp->msg_flags |= MSG_CTRUNC;
+ m_dispose_extcontrolm(m);
}
- mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
}
out:
fdrop(fp, td);
@@ -1405,8 +1409,11 @@ out:
if (error == 0 && controlp != NULL)
*controlp = control;
- else if (control)
+ else if (control != NULL) {
+ if (error != 0)
+ m_dispose_extcontrolm(control);
m_freem(control);
+ }
return (error);
}
@@ -2134,3 +2141,51 @@ getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
return (0);
#endif /* __rtems__ */
}
+
+/*
+ * Dispose of externalized rights from an SCM_RIGHTS message. This function
+ * should be used in error or truncation cases to avoid leaking file descriptors
+ * into the recipient's (the current thread's) table.
+ */
+void
+m_dispose_extcontrolm(struct mbuf *m)
+{
+ struct cmsghdr *cm;
+ struct file *fp;
+ struct thread *td;
+ socklen_t clen, datalen;
+ int error, fd, *fds, nfd;
+
+ td = curthread;
+ for (; m != NULL; m = m->m_next) {
+ if (m->m_type != MT_EXTCONTROL)
+ continue;
+ cm = mtod(m, struct cmsghdr *);
+ clen = m->m_len;
+ while (clen > 0) {
+ if (clen < sizeof(*cm))
+ panic("%s: truncated mbuf %p", __func__, m);
+ datalen = CMSG_SPACE(cm->cmsg_len - CMSG_SPACE(0));
+ if (clen < datalen)
+ panic("%s: truncated mbuf %p", __func__, m);
+
+ if (cm->cmsg_level == SOL_SOCKET &&
+ cm->cmsg_type == SCM_RIGHTS) {
+ fds = (int *)CMSG_DATA(cm);
+ nfd = (cm->cmsg_len - CMSG_SPACE(0)) /
+ sizeof(int);
+
+ while (nfd-- > 0) {
+ fd = *fds++;
+ error = fget(td, fd, &cap_no_rights,
+ &fp);
+ if (error == 0)
+ fdclose(td, fp, fd);
+ }
+ }
+ clen -= datalen;
+ cm = (struct cmsghdr *)((uint8_t *)cm + datalen);
+ }
+ m_chtype(m, MT_CONTROL);
+ }
+}
diff --git a/freebsd/sys/kern/uipc_usrreq.c b/freebsd/sys/kern/uipc_usrreq.c
index 688682d4..c1885ed6 100644
--- a/freebsd/sys/kern/uipc_usrreq.c
+++ b/freebsd/sys/kern/uipc_usrreq.c
@@ -376,33 +376,32 @@ unp_pcb_lock2(struct unpcb *unp, struct unpcb *unp2)
}
static __noinline void
-unp_pcb_owned_lock2_slowpath(struct unpcb *unp, struct unpcb **unp2p, int *freed)
-
+unp_pcb_owned_lock2_slowpath(struct unpcb *unp, struct unpcb **unp2p,
+ int *freed)
{
struct unpcb *unp2;
unp2 = *unp2p;
- unp_pcb_hold((unp2));
- UNP_PCB_UNLOCK((unp));
- UNP_PCB_LOCK((unp2));
- UNP_PCB_LOCK((unp));
- *freed = unp_pcb_rele((unp2));
+ unp_pcb_hold(unp2);
+ UNP_PCB_UNLOCK(unp);
+ UNP_PCB_LOCK(unp2);
+ UNP_PCB_LOCK(unp);
+ *freed = unp_pcb_rele(unp2);
if (*freed)
*unp2p = NULL;
}
-#define unp_pcb_owned_lock2(unp, unp2, freed) do { \
- freed = 0; \
- UNP_PCB_LOCK_ASSERT((unp)); \
- UNP_PCB_UNLOCK_ASSERT((unp2)); \
- MPASS(unp != unp2); \
- if (__predict_true(UNP_PCB_TRYLOCK((unp2)))) \
- break; \
- else if ((uintptr_t)(unp2) > (uintptr_t)(unp)) \
- UNP_PCB_LOCK((unp2)); \
- else { \
- unp_pcb_owned_lock2_slowpath((unp), &(unp2), &freed); \
- } \
+#define unp_pcb_owned_lock2(unp, unp2, freed) do { \
+ freed = 0; \
+ UNP_PCB_LOCK_ASSERT(unp); \
+ UNP_PCB_UNLOCK_ASSERT(unp2); \
+ MPASS((unp) != (unp2)); \
+ if (__predict_true(UNP_PCB_TRYLOCK(unp2))) \
+ break; \
+ else if ((uintptr_t)(unp2) > (uintptr_t)(unp)) \
+ UNP_PCB_LOCK(unp2); \
+ else \
+ unp_pcb_owned_lock2_slowpath((unp), &(unp2), &freed); \
} while (0)
@@ -992,21 +991,19 @@ uipc_disconnect(struct socket *so)
UNP_PCB_UNLOCK(unp);
return (0);
}
- if (unp == unp2) {
- if (unp_pcb_rele(unp) == 0)
+ if (__predict_true(unp != unp2)) {
+ unp_pcb_owned_lock2(unp, unp2, freed);
+ if (__predict_false(freed)) {
UNP_PCB_UNLOCK(unp);
+ return (0);
+ }
+ unp_pcb_hold(unp2);
}
- unp_pcb_owned_lock2(unp, unp2, freed);
- if (__predict_false(freed)) {
- UNP_PCB_UNLOCK(unp);
- return (0);
- }
- unp_pcb_hold(unp2);
unp_pcb_hold(unp);
unp_disconnect(unp, unp2);
if (unp_pcb_rele(unp) == 0)
UNP_PCB_UNLOCK(unp);
- if (unp_pcb_rele(unp2) == 0)
+ if ((unp != unp2) && unp_pcb_rele(unp2) == 0)
UNP_PCB_UNLOCK(unp2);
return (0);
}
@@ -1305,16 +1302,22 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
control = unp_addsockcred(td, control);
#endif /* __rtems__ */
}
+
/*
- * Send to paired receive port, and then reduce send buffer
- * hiwater marks to maintain backpressure. Wake up readers.
+ * Send to paired receive port and wake up readers. Don't
+ * check for space available in the receive buffer if we're
+ * attaching ancillary data; Unix domain sockets only check
+ * for space in the sending sockbuf, and that check is
+ * performed one level up the stack. At that level we cannot
+ * precisely account for the amount of buffer space used
+ * (e.g., because control messages are not yet internalized).
*/
switch (so->so_type) {
case SOCK_STREAM:
if (control != NULL) {
- if (sbappendcontrol_locked(&so2->so_rcv, m,
- control))
- control = NULL;
+ sbappendcontrol_locked(&so2->so_rcv, m,
+ control);
+ control = NULL;
} else
sbappend_locked(&so2->so_rcv, m, flags);
break;
@@ -1323,14 +1326,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
const struct sockaddr *from;
from = &sun_noname;
- /*
- * Don't check for space available in so2->so_rcv.
- * Unix domain sockets only check for space in the
- * sending sockbuf, and that check is performed one
- * level up the stack.
- */
if (sbappendaddr_nospacecheck_locked(&so2->so_rcv,
- from, m, control))
+ from, m, control))
control = NULL;
break;
}
@@ -1396,14 +1393,21 @@ uipc_ready(struct socket *so, struct mbuf *m, int count)
unp = sotounpcb(so);
- UNP_LINK_RLOCK();
+ UNP_PCB_LOCK(unp);
if ((unp2 = unp->unp_conn) == NULL) {
- UNP_LINK_RUNLOCK();
- for (int i = 0; i < count; i++)
- m = m_free(m);
- return (ECONNRESET);
+ UNP_PCB_UNLOCK(unp);
+ goto error;
+ }
+ if (unp != unp2) {
+ if (UNP_PCB_TRYLOCK(unp2) == 0) {
+ unp_pcb_hold(unp2);
+ UNP_PCB_UNLOCK(unp);
+ UNP_PCB_LOCK(unp2);
+ if (unp_pcb_rele(unp2))
+ goto error;
+ } else
+ UNP_PCB_UNLOCK(unp);
}
- UNP_PCB_LOCK(unp2);
so2 = unp2->unp_socket;
SOCKBUF_LOCK(&so2->so_rcv);
@@ -1413,9 +1417,12 @@ uipc_ready(struct socket *so, struct mbuf *m, int count)
SOCKBUF_UNLOCK(&so2->so_rcv);
UNP_PCB_UNLOCK(unp2);
- UNP_LINK_RUNLOCK();
return (error);
+ error:
+ for (int i = 0; i < count; i++)
+ m = m_free(m);
+ return (ECONNRESET);
}
static int
@@ -1778,24 +1785,8 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
sa = NULL;
}
- /*
- * The connector's (client's) credentials are copied from its
- * process structure at the time of connect() (which is now).
- */
- cru2x(td->td_ucred, &unp3->unp_peercred);
- unp3->unp_flags |= UNP_HAVEPC;
+ unp_copy_peercred(td, unp3, unp, unp2);
- /*
- * The receiver's (server's) credentials are copied from the
- * unp_peercred member of socket on which the former called
- * listen(); uipc_listen() cached that process's credentials
- * at that time so we can use them now.
- */
- memcpy(&unp->unp_peercred, &unp2->unp_peercred,
- sizeof(unp->unp_peercred));
- unp->unp_flags |= UNP_HAVEPC;
- if (unp2->unp_flags & UNP_WANTCRED)
- unp3->unp_flags |= UNP_WANTCRED;
UNP_PCB_UNLOCK(unp2);
unp2 = unp3;
unp_pcb_owned_lock2(unp2, unp, freed);
@@ -1838,6 +1829,27 @@ bad:
return (error);
}
+/*
+ * Set socket peer credentials at connection time.
+ *
+ * The client's PCB credentials are copied from its process structure. The
+ * server's PCB credentials are copied from the socket on which it called
+ * listen(2). uipc_listen cached that process's credentials at the time.
+ */
+void
+unp_copy_peercred(struct thread *td, struct unpcb *client_unp,
+ struct unpcb *server_unp, struct unpcb *listen_unp)
+{
+ cru2x(td->td_ucred, &client_unp->unp_peercred);
+ client_unp->unp_flags |= UNP_HAVEPC;
+
+ memcpy(&server_unp->unp_peercred, &listen_unp->unp_peercred,
+ sizeof(server_unp->unp_peercred));
+ server_unp->unp_flags |= UNP_HAVEPC;
+ if (listen_unp->unp_flags & UNP_WANTCRED)
+ client_unp->unp_flags |= UNP_WANTCRED;
+}
+
static int
unp_connect2(struct socket *so, struct socket *so2, int req)
{
@@ -2026,7 +2038,7 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
if (freeunp == 0 && unp->unp_gencnt <= gencnt) {
xu->xu_len = sizeof *xu;
- xu->xu_unpp = unp;
+ xu->xu_unpp = (uintptr_t)unp;
/*
* XXX - need more locking here to protect against
* connect/disconnect races for SMP.
@@ -2043,10 +2055,10 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
unp->unp_conn->unp_addr->sun_len);
else
bzero(&xu->xu_caddr, sizeof(xu->xu_caddr));
- xu->unp_vnode = unp->unp_vnode;
- xu->unp_conn = unp->unp_conn;
- xu->xu_firstref = LIST_FIRST(&unp->unp_refs);
- xu->xu_nextref = LIST_NEXT(unp, unp_reflink);
+ xu->unp_vnode = (uintptr_t)unp->unp_vnode;
+ xu->unp_conn = (uintptr_t)unp->unp_conn;
+ xu->xu_firstref = (uintptr_t)LIST_FIRST(&unp->unp_refs);
+ xu->xu_nextref = (uintptr_t)LIST_NEXT(unp, unp_reflink);
xu->unp_gencnt = unp->unp_gencnt;
sotoxsocket(unp->unp_socket, &xu->xu_socket);
UNP_PCB_UNLOCK(unp);
@@ -2220,6 +2232,13 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
&fdep[i]->fde_caps);
unp_externalize_fp(fdep[i]->fde_file);
}
+
+ /*
+ * The new type indicates that the mbuf data refers to
+ * kernel resources that may need to be released before
+ * the mbuf is freed.
+ */
+ m_chtype(*controlp, MT_EXTCONTROL);
FILEDESC_XUNLOCK(fdesc);
free(fdep[0], M_FILECAPS);
} else {
diff --git a/freebsd/sys/mips/include/machine/cpuregs.h b/freebsd/sys/mips/include/machine/cpuregs.h
index b9978bd0..096f322d 100644
--- a/freebsd/sys/mips/include/machine/cpuregs.h
+++ b/freebsd/sys/mips/include/machine/cpuregs.h
@@ -60,6 +60,10 @@
#ifndef _MIPS_CPUREGS_H_
#define _MIPS_CPUREGS_H_
+#ifndef _KVM_MINIDUMP
+#include <machine/cca.h>
+#endif
+
/*
* Address space.
* 32-bit mips CPUS partition their 32-bit address space into four segments:
@@ -105,96 +109,6 @@
#define MIPS_IS_VALID_PTR(x) (MIPS_IS_KSEG0_ADDR(x) || \
MIPS_IS_KSEG1_ADDR(x))
-/*
- * Cache Coherency Attributes:
- * UC: Uncached.
- * UA: Uncached accelerated.
- * C: Cacheable, coherency unspecified.
- * CNC: Cacheable non-coherent.
- * CC: Cacheable coherent.
- * CCS: Cacheable coherent, shared read.
- * CCE: Cacheable coherent, exclusive read.
- * CCEW: Cacheable coherent, exclusive write.
- * CCUOW: Cacheable coherent, update on write.
- *
- * Note that some bits vary in meaning across implementations (and that the
- * listing here is no doubt incomplete) and that the optimal cached mode varies
- * between implementations. 0x02 is required to be UC and 0x03 is required to
- * be a least C.
- *
- * We define the following logical bits:
- * UNCACHED:
- * The optimal uncached mode for the target CPU type. This must
- * be suitable for use in accessing memory-mapped devices.
- * CACHED: The optional cached mode for the target CPU type.
- */
-
-#define MIPS_CCA_UC 0x02 /* Uncached. */
-#define MIPS_CCA_C 0x03 /* Cacheable, coherency unspecified. */
-
-#if defined(CPU_R4000) || defined(CPU_R10000)
-#define MIPS_CCA_CNC 0x03
-#define MIPS_CCA_CCE 0x04
-#define MIPS_CCA_CCEW 0x05
-
-#ifdef CPU_R4000
-#define MIPS_CCA_CCUOW 0x06
-#endif
-
-#ifdef CPU_R10000
-#define MIPS_CCA_UA 0x07
-#endif
-
-#define MIPS_CCA_CACHED MIPS_CCA_CCEW
-#endif /* defined(CPU_R4000) || defined(CPU_R10000) */
-
-#if defined(CPU_SB1)
-#define MIPS_CCA_CC 0x05 /* Cacheable Coherent. */
-#endif
-
-#if defined(CPU_MIPS74K)
-#define MIPS_CCA_UNCACHED 0x02
-#define MIPS_CCA_CACHED 0x03
-#endif
-
-/*
- * 1004K and 1074K cores, as well as interAptiv and proAptiv cores, support
- * Cacheable Coherent CCAs 0x04 and 0x05, as well as Cacheable non-Coherent
- * CCA 0x03 and Uncached Accelerated CCA 0x07
- */
-#if defined(CPU_MIPS1004K) || defined(CPU_MIPS1074K) || \
- defined(CPU_INTERAPTIV) || defined(CPU_PROAPTIV)
-#define MIPS_CCA_CNC 0x03
-#define MIPS_CCA_CCE 0x04
-#define MIPS_CCA_CCS 0x05
-#define MIPS_CCA_UA 0x07
-
-/* We use shared read CCA for CACHED CCA */
-#define MIPS_CCA_CACHED MIPS_CCA_CCS
-#endif
-
-#if defined(CPU_XBURST)
-#define MIPS_CCA_UA 0x01
-#define MIPS_CCA_WC MIPS_CCA_UA
-#endif
-
-#ifndef MIPS_CCA_UNCACHED
-#define MIPS_CCA_UNCACHED MIPS_CCA_UC
-#endif
-
-/*
- * If we don't know which cached mode to use and there is a cache coherent
- * mode, use it. If there is not a cache coherent mode, use the required
- * cacheable mode.
- */
-#ifndef MIPS_CCA_CACHED
-#ifdef MIPS_CCA_CC
-#define MIPS_CCA_CACHED MIPS_CCA_CC
-#else
-#define MIPS_CCA_CACHED MIPS_CCA_C
-#endif
-#endif
-
#define MIPS_PHYS_TO_XKPHYS(cca,x) \
((0x2ULL << 62) | ((unsigned long long)(cca) << 59) | (x))
#define MIPS_PHYS_TO_XKPHYS_CACHED(x) \
diff --git a/freebsd/sys/net/altq/altq.h b/freebsd/sys/net/altq/altq.h
index 9cb97bc2..35024461 100644
--- a/freebsd/sys/net/altq/altq.h
+++ b/freebsd/sys/net/altq/altq.h
@@ -76,8 +76,8 @@ struct altqreq {
/* simple token backet meter profile */
struct tb_profile {
- u_int rate; /* rate in bit-per-sec */
- u_int depth; /* depth in bytes */
+ u_int64_t rate; /* rate in bit-per-sec */
+ u_int32_t depth; /* depth in bytes */
};
#ifdef ALTQ3_COMPAT
@@ -203,4 +203,29 @@ struct pktcntr {
#include <net/altq/altq_var.h>
#endif
+/*
+ * Can't put these versions in the scheduler-specific headers and include
+ * them all here as that will cause build failure due to cross-including
+ * each other scheduler's private bits into each scheduler's
+ * implementation.
+ */
+#define CBQ_STATS_VERSION 0 /* Latest version of class_stats_t */
+#define CODEL_STATS_VERSION 0 /* Latest version of codel_ifstats */
+#define FAIRQ_STATS_VERSION 0 /* Latest version of fairq_classstats */
+#define HFSC_STATS_VERSION 1 /* Latest version of hfsc_classstats */
+#define PRIQ_STATS_VERSION 0 /* Latest version of priq_classstats */
+
+/* Return the latest stats version for the given scheduler. */
+static inline int altq_stats_version(int scheduler)
+{
+ switch (scheduler) {
+ case ALTQT_CBQ: return (CBQ_STATS_VERSION);
+ case ALTQT_CODEL: return (CODEL_STATS_VERSION);
+ case ALTQT_FAIRQ: return (FAIRQ_STATS_VERSION);
+ case ALTQT_HFSC: return (HFSC_STATS_VERSION);
+ case ALTQT_PRIQ: return (PRIQ_STATS_VERSION);
+ default: return (0);
+ }
+}
+
#endif /* _ALTQ_ALTQ_H_ */
diff --git a/freebsd/sys/net/altq/altq_cbq.c b/freebsd/sys/net/altq/altq_cbq.c
index 1631d145..ac108bd1 100644
--- a/freebsd/sys/net/altq/altq_cbq.c
+++ b/freebsd/sys/net/altq/altq_cbq.c
@@ -454,7 +454,7 @@ cbq_remove_queue(struct pf_altq *a)
}
int
-cbq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+cbq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
cbq_state_t *cbqp;
struct rm_class *cl;
diff --git a/freebsd/sys/net/altq/altq_cbq.h b/freebsd/sys/net/altq/altq_cbq.h
index 51e7cf9a..04bcab1a 100644
--- a/freebsd/sys/net/altq/altq_cbq.h
+++ b/freebsd/sys/net/altq/altq_cbq.h
@@ -99,6 +99,12 @@ typedef struct _cbq_class_stats_ {
struct codel_stats codel;
} class_stats_t;
+/*
+ * CBQ_STATS_VERSION is defined in altq.h to work around issues stemming
+ * from mixing of public-API and internal bits in each scheduler-specific
+ * header.
+ */
+
#ifdef ALTQ3_COMPAT
/*
* Define structures associated with IOCTLS for cbq.
diff --git a/freebsd/sys/net/altq/altq_codel.c b/freebsd/sys/net/altq/altq_codel.c
index 37a44216..4a55cdbe 100644
--- a/freebsd/sys/net/altq/altq_codel.c
+++ b/freebsd/sys/net/altq/altq_codel.c
@@ -158,7 +158,7 @@ codel_remove_altq(struct pf_altq *a)
}
int
-codel_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+codel_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
struct codel_if *cif;
struct codel_ifstats stats;
diff --git a/freebsd/sys/net/altq/altq_codel.h b/freebsd/sys/net/altq/altq_codel.h
index 8d7178b4..d7341a87 100644
--- a/freebsd/sys/net/altq/altq_codel.h
+++ b/freebsd/sys/net/altq/altq_codel.h
@@ -57,6 +57,12 @@ struct codel_ifstats {
struct pktcntr cl_dropcnt; /* dropped packet counter */
};
+/*
+ * CBQ_STATS_VERSION is defined in altq.h to work around issues stemming
+ * from mixing of public-API and internal bits in each scheduler-specific
+ * header.
+ */
+
#ifdef _KERNEL
#include <net/altq/altq_classq.h>
diff --git a/freebsd/sys/net/altq/altq_fairq.c b/freebsd/sys/net/altq/altq_fairq.c
index 9979a1fa..a1bc3fdb 100644
--- a/freebsd/sys/net/altq/altq_fairq.c
+++ b/freebsd/sys/net/altq/altq_fairq.c
@@ -231,7 +231,7 @@ fairq_remove_queue(struct pf_altq *a)
}
int
-fairq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+fairq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
struct fairq_if *pif;
struct fairq_class *cl;
diff --git a/freebsd/sys/net/altq/altq_fairq.h b/freebsd/sys/net/altq/altq_fairq.h
index 1a4b97dd..f1e3217c 100644
--- a/freebsd/sys/net/altq/altq_fairq.h
+++ b/freebsd/sys/net/altq/altq_fairq.h
@@ -82,6 +82,12 @@ struct fairq_classstats {
struct codel_stats codel;
};
+/*
+ * FAIRQ_STATS_VERSION is defined in altq.h to work around issues stemming
+ * from mixing of public-API and internal bits in each scheduler-specific
+ * header.
+ */
+
#ifdef _KERNEL
typedef struct fairq_bucket {
diff --git a/freebsd/sys/net/altq/altq_hfsc.c b/freebsd/sys/net/altq/altq_hfsc.c
index d31d55c3..8d8fdfdc 100644
--- a/freebsd/sys/net/altq/altq_hfsc.c
+++ b/freebsd/sys/net/altq/altq_hfsc.c
@@ -118,10 +118,10 @@ static struct hfsc_class *actlist_firstfit(struct hfsc_class *,
static __inline u_int64_t seg_x2y(u_int64_t, u_int64_t);
static __inline u_int64_t seg_y2x(u_int64_t, u_int64_t);
-static __inline u_int64_t m2sm(u_int);
-static __inline u_int64_t m2ism(u_int);
+static __inline u_int64_t m2sm(u_int64_t);
+static __inline u_int64_t m2ism(u_int64_t);
static __inline u_int64_t d2dx(u_int);
-static u_int sm2m(u_int64_t);
+static u_int64_t sm2m(u_int64_t);
static u_int dx2d(u_int64_t);
static void sc2isc(struct service_curve *, struct internal_sc *);
@@ -132,7 +132,9 @@ static u_int64_t rtsc_x2y(struct runtime_sc *, u_int64_t);
static void rtsc_min(struct runtime_sc *, struct internal_sc *,
u_int64_t, u_int64_t);
-static void get_class_stats(struct hfsc_classstats *,
+static void get_class_stats_v0(struct hfsc_classstats_v0 *,
+ struct hfsc_class *);
+static void get_class_stats_v1(struct hfsc_classstats_v1 *,
struct hfsc_class *);
static struct hfsc_class *clh_to_clp(struct hfsc_if *, u_int32_t);
@@ -160,7 +162,7 @@ altqdev_decl(hfsc);
*/
#define is_a_parent_class(cl) ((cl)->cl_children != NULL)
-#define HT_INFINITY 0xffffffffffffffffLL /* infinite time value */
+#define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */
#ifdef ALTQ3_COMPAT
/* hif_list keeps all hfsc_if's allocated. */
@@ -228,7 +230,7 @@ hfsc_add_queue(struct pf_altq *a)
{
struct hfsc_if *hif;
struct hfsc_class *cl, *parent;
- struct hfsc_opts *opts;
+ struct hfsc_opts_v1 *opts;
struct service_curve rtsc, lssc, ulsc;
if ((hif = a->altq_disc) == NULL)
@@ -282,11 +284,15 @@ hfsc_remove_queue(struct pf_altq *a)
}
int
-hfsc_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+hfsc_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
struct hfsc_if *hif;
struct hfsc_class *cl;
- struct hfsc_classstats stats;
+ union {
+ struct hfsc_classstats_v0 v0;
+ struct hfsc_classstats_v1 v1;
+ } stats;
+ size_t stats_size;
int error = 0;
if ((hif = altq_lookup(a->ifname, ALTQT_HFSC)) == NULL)
@@ -295,14 +301,27 @@ hfsc_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
if ((cl = clh_to_clp(hif, a->qid)) == NULL)
return (EINVAL);
- if (*nbytes < sizeof(stats))
+ if (version > HFSC_STATS_VERSION)
return (EINVAL);
- get_class_stats(&stats, cl);
+ memset(&stats, 0, sizeof(stats));
+ switch (version) {
+ case 0:
+ get_class_stats_v0(&stats.v0, cl);
+ stats_size = sizeof(struct hfsc_classstats_v0);
+ break;
+ case 1:
+ get_class_stats_v1(&stats.v1, cl);
+ stats_size = sizeof(struct hfsc_classstats_v1);
+ break;
+ }
+
+ if (*nbytes < stats_size)
+ return (EINVAL);
- if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
+ if ((error = copyout((caddr_t)&stats, ubuf, stats_size)) != 0)
return (error);
- *nbytes = sizeof(stats);
+ *nbytes = stats_size;
return (0);
}
@@ -1359,27 +1378,17 @@ actlist_firstfit(struct hfsc_class *cl, u_int64_t cur_time)
* m: bits/sec
* d: msec
* internal service curve parameters
- * sm: (bytes/tsc_interval) << SM_SHIFT
- * ism: (tsc_count/byte) << ISM_SHIFT
- * dx: tsc_count
- *
- * SM_SHIFT and ISM_SHIFT are scaled in order to keep effective digits.
- * we should be able to handle 100K-1Gbps linkspeed with 200Hz-1GHz CPU
- * speed. SM_SHIFT and ISM_SHIFT are selected to have at least 3 effective
- * digits in decimal using the following table.
+ * sm: (bytes/machclk tick) << SM_SHIFT
+ * ism: (machclk ticks/byte) << ISM_SHIFT
+ * dx: machclk ticks
*
- * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps
- * ----------+-------------------------------------------------------
- * bytes/nsec 12.5e-6 125e-6 1250e-6 12500e-6 125000e-6
- * sm(500MHz) 25.0e-6 250e-6 2500e-6 25000e-6 250000e-6
- * sm(200MHz) 62.5e-6 625e-6 6250e-6 62500e-6 625000e-6
+ * SM_SHIFT and ISM_SHIFT are scaled in order to keep effective digits. we
+ * should be able to handle 100K-100Gbps linkspeed with 256 MHz machclk
+ * frequency and at least 3 effective digits in decimal.
*
- * nsec/byte 80000 8000 800 80 8
- * ism(500MHz) 40000 4000 400 40 4
- * ism(200MHz) 16000 1600 160 16 1.6
*/
#define SM_SHIFT 24
-#define ISM_SHIFT 10
+#define ISM_SHIFT 14
#define SM_MASK ((1LL << SM_SHIFT) - 1)
#define ISM_MASK ((1LL << ISM_SHIFT) - 1)
@@ -1415,16 +1424,16 @@ seg_y2x(u_int64_t y, u_int64_t ism)
}
static __inline u_int64_t
-m2sm(u_int m)
+m2sm(u_int64_t m)
{
u_int64_t sm;
- sm = ((u_int64_t)m << SM_SHIFT) / 8 / machclk_freq;
+ sm = (m << SM_SHIFT) / 8 / machclk_freq;
return (sm);
}
static __inline u_int64_t
-m2ism(u_int m)
+m2ism(u_int64_t m)
{
u_int64_t ism;
@@ -1444,13 +1453,13 @@ d2dx(u_int d)
return (dx);
}
-static u_int
+static u_int64_t
sm2m(u_int64_t sm)
{
u_int64_t m;
m = (sm * 8 * machclk_freq) >> SM_SHIFT;
- return ((u_int)m);
+ return (m);
}
static u_int
@@ -1599,7 +1608,89 @@ rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u_int64_t x,
}
static void
-get_class_stats(struct hfsc_classstats *sp, struct hfsc_class *cl)
+get_class_stats_v0(struct hfsc_classstats_v0 *sp, struct hfsc_class *cl)
+{
+ sp->class_id = cl->cl_id;
+ sp->class_handle = cl->cl_handle;
+
+#define SATU32(x) (u_int32_t)uqmin((x), UINT_MAX)
+
+ if (cl->cl_rsc != NULL) {
+ sp->rsc.m1 = SATU32(sm2m(cl->cl_rsc->sm1));
+ sp->rsc.d = dx2d(cl->cl_rsc->dx);
+ sp->rsc.m2 = SATU32(sm2m(cl->cl_rsc->sm2));
+ } else {
+ sp->rsc.m1 = 0;
+ sp->rsc.d = 0;
+ sp->rsc.m2 = 0;
+ }
+ if (cl->cl_fsc != NULL) {
+ sp->fsc.m1 = SATU32(sm2m(cl->cl_fsc->sm1));
+ sp->fsc.d = dx2d(cl->cl_fsc->dx);
+ sp->fsc.m2 = SATU32(sm2m(cl->cl_fsc->sm2));
+ } else {
+ sp->fsc.m1 = 0;
+ sp->fsc.d = 0;
+ sp->fsc.m2 = 0;
+ }
+ if (cl->cl_usc != NULL) {
+ sp->usc.m1 = SATU32(sm2m(cl->cl_usc->sm1));
+ sp->usc.d = dx2d(cl->cl_usc->dx);
+ sp->usc.m2 = SATU32(sm2m(cl->cl_usc->sm2));
+ } else {
+ sp->usc.m1 = 0;
+ sp->usc.d = 0;
+ sp->usc.m2 = 0;
+ }
+
+#undef SATU32
+
+ sp->total = cl->cl_total;
+ sp->cumul = cl->cl_cumul;
+
+ sp->d = cl->cl_d;
+ sp->e = cl->cl_e;
+ sp->vt = cl->cl_vt;
+ sp->f = cl->cl_f;
+
+ sp->initvt = cl->cl_initvt;
+ sp->vtperiod = cl->cl_vtperiod;
+ sp->parentperiod = cl->cl_parentperiod;
+ sp->nactive = cl->cl_nactive;
+ sp->vtoff = cl->cl_vtoff;
+ sp->cvtmax = cl->cl_cvtmax;
+ sp->myf = cl->cl_myf;
+ sp->cfmin = cl->cl_cfmin;
+ sp->cvtmin = cl->cl_cvtmin;
+ sp->myfadj = cl->cl_myfadj;
+ sp->vtadj = cl->cl_vtadj;
+
+ sp->cur_time = read_machclk();
+ sp->machclk_freq = machclk_freq;
+
+ sp->qlength = qlen(cl->cl_q);
+ sp->qlimit = qlimit(cl->cl_q);
+ sp->xmit_cnt = cl->cl_stats.xmit_cnt;
+ sp->drop_cnt = cl->cl_stats.drop_cnt;
+ sp->period = cl->cl_stats.period;
+
+ sp->qtype = qtype(cl->cl_q);
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_getstats(cl->cl_red, &sp->red[0]);
+#endif
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_getstats((rio_t *)cl->cl_red, &sp->red[0]);
+#endif
+#ifdef ALTQ_CODEL
+ if (q_is_codel(cl->cl_q))
+ codel_getstats(cl->cl_codel, &sp->codel);
+#endif
+}
+
+static void
+get_class_stats_v1(struct hfsc_classstats_v1 *sp, struct hfsc_class *cl)
{
sp->class_id = cl->cl_id;
sp->class_handle = cl->cl_handle;
diff --git a/freebsd/sys/net/altq/altq_hfsc.h b/freebsd/sys/net/altq/altq_hfsc.h
index 0a9fcf95..67ec0036 100644
--- a/freebsd/sys/net/altq/altq_hfsc.h
+++ b/freebsd/sys/net/altq/altq_hfsc.h
@@ -43,12 +43,21 @@
extern "C" {
#endif
-struct service_curve {
+struct service_curve_v0 {
u_int m1; /* slope of the first segment in bits/sec */
u_int d; /* the x-projection of the first segment in msec */
u_int m2; /* slope of the second segment in bits/sec */
};
+struct service_curve_v1 {
+ u_int64_t m1; /* slope of the first segment in bits/sec */
+ u_int d; /* the x-projection of the first segment in msec */
+ u_int64_t m2; /* slope of the second segment in bits/sec */
+};
+
+/* Latest version of struct service_curve_vX */
+#define HFSC_SERVICE_CURVE_VERSION 1
+
/* special class handles */
#define HFSC_NULLCLASS_HANDLE 0
#define HFSC_MAX_CLASSES 64
@@ -67,12 +76,55 @@ struct service_curve {
#define HFSC_UPPERLIMITSC 4
#define HFSC_DEFAULTSC (HFSC_REALTIMESC|HFSC_LINKSHARINGSC)
-struct hfsc_classstats {
+struct hfsc_classstats_v0 {
+ u_int class_id;
+ u_int32_t class_handle;
+ struct service_curve_v0 rsc;
+ struct service_curve_v0 fsc;
+ struct service_curve_v0 usc; /* upper limit service curve */
+
+ u_int64_t total; /* total work in bytes */
+ u_int64_t cumul; /* cumulative work in bytes
+ done by real-time criteria */
+ u_int64_t d; /* deadline */
+ u_int64_t e; /* eligible time */
+ u_int64_t vt; /* virtual time */
+ u_int64_t f; /* fit time for upper-limit */
+
+ /* info helpful for debugging */
+ u_int64_t initvt; /* init virtual time */
+ u_int64_t vtoff; /* cl_vt_ipoff */
+ u_int64_t cvtmax; /* cl_maxvt */
+ u_int64_t myf; /* cl_myf */
+ u_int64_t cfmin; /* cl_mincf */
+ u_int64_t cvtmin; /* cl_mincvt */
+ u_int64_t myfadj; /* cl_myfadj */
+ u_int64_t vtadj; /* cl_vtadj */
+ u_int64_t cur_time;
+ u_int32_t machclk_freq;
+
+ u_int qlength;
+ u_int qlimit;
+ struct pktcntr xmit_cnt;
+ struct pktcntr drop_cnt;
+ u_int period;
+
+ u_int vtperiod; /* vt period sequence no */
+ u_int parentperiod; /* parent's vt period seqno */
+ int nactive; /* number of active children */
+
+ /* codel, red and rio related info */
+ int qtype;
+ struct redstats red[3];
+ struct codel_stats codel;
+};
+
+struct hfsc_classstats_v1 {
u_int class_id;
u_int32_t class_handle;
- struct service_curve rsc;
- struct service_curve fsc;
- struct service_curve usc; /* upper limit service curve */
+ struct service_curve_v1 rsc;
+ struct service_curve_v1 fsc;
+ struct service_curve_v1 usc; /* upper limit service curve */
u_int64_t total; /* total work in bytes */
u_int64_t cumul; /* cumulative work in bytes
@@ -110,6 +162,12 @@ struct hfsc_classstats {
struct codel_stats codel;
};
+/*
+ * HFSC_STATS_VERSION is defined in altq.h to work around issues stemming
+ * from mixing of public-API and internal bits in each scheduler-specific
+ * header.
+ */
+
#ifdef ALTQ3_COMPAT
struct hfsc_interface {
char hfsc_ifname[IFNAMSIZ]; /* interface name (e.g., fxp0) */
@@ -310,6 +368,35 @@ struct hfsc_if {
#endif
};
+/*
+ * Kernel code always wants the latest version - avoid a bunch of renames in
+ * the code to the current latest versioned name.
+ */
+#define service_curve __CONCAT(service_curve_v, HFSC_SERVICE_CURVE_VERSION)
+
+#else /* _KERNEL */
+
+#ifdef PFIOC_USE_LATEST
+/*
+ * Maintaining in-tree consumers of the ioctl interface is easier when that
+ * code can be written in terms old names that refer to the latest interface
+ * version as that reduces the required changes in the consumers to those
+ * that are functionally necessary to accommodate a new interface version.
+ */
+#define hfsc_classstats __CONCAT(hfsc_classstats_v, HFSC_STATS_VERSION)
+#define service_curve __CONCAT(service_curve_v, HFSC_SERVICE_CURVE_VERSION)
+
+#else
+/*
+ * When building out-of-tree code that is written for the old interface,
+ * such as may exist in ports for example, resolve the old struct tags to
+ * the v0 versions.
+ */
+#define hfsc_classstats __CONCAT(hfsc_classstats_v, 0)
+#define service_curve __CONCAT(service_curve_v, 0)
+
+#endif /* PFIOC_USE_LATEST */
+
#endif /* _KERNEL */
#ifdef __cplusplus
diff --git a/freebsd/sys/net/altq/altq_priq.c b/freebsd/sys/net/altq/altq_priq.c
index 46a014ad..ce0830eb 100644
--- a/freebsd/sys/net/altq/altq_priq.c
+++ b/freebsd/sys/net/altq/altq_priq.c
@@ -201,7 +201,7 @@ priq_remove_queue(struct pf_altq *a)
}
int
-priq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+priq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
struct priq_if *pif;
struct priq_class *cl;
diff --git a/freebsd/sys/net/altq/altq_priq.h b/freebsd/sys/net/altq/altq_priq.h
index fcbfee98..1a824d60 100644
--- a/freebsd/sys/net/altq/altq_priq.h
+++ b/freebsd/sys/net/altq/altq_priq.h
@@ -112,6 +112,12 @@ struct priq_classstats {
struct codel_stats codel;
};
+/*
+ * PRIQ_STATS_VERSION is defined in altq.h to work around issues stemming
+ * from mixing of public-API and internal bits in each scheduler-specific
+ * header.
+ */
+
#ifdef ALTQ3_COMPAT
struct priq_class_stats {
struct priq_interface iface;
diff --git a/freebsd/sys/net/altq/altq_subr.c b/freebsd/sys/net/altq/altq_subr.c
index 47a353fc..6da36129 100644
--- a/freebsd/sys/net/altq/altq_subr.c
+++ b/freebsd/sys/net/altq/altq_subr.c
@@ -294,12 +294,12 @@ altq_assert(file, line, failedexpr)
/*
* internal representation of token bucket parameters
- * rate: byte_per_unittime << 32
- * (((bits_per_sec) / 8) << 32) / machclk_freq
- * depth: byte << 32
+ * rate: (byte_per_unittime << TBR_SHIFT) / machclk_freq
+ * (((bits_per_sec) / 8) << TBR_SHIFT) / machclk_freq
+ * depth: byte << TBR_SHIFT
*
*/
-#define TBR_SHIFT 32
+#define TBR_SHIFT 29
#define TBR_SCALE(x) ((int64_t)(x) << TBR_SHIFT)
#define TBR_UNSCALE(x) ((x) >> TBR_SHIFT)
@@ -396,7 +396,20 @@ tbr_set(ifq, profile)
if (tbr->tbr_rate > 0)
tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate;
else
- tbr->tbr_filluptime = 0xffffffffffffffffLL;
+ tbr->tbr_filluptime = LLONG_MAX;
+ /*
+ * The longest time between tbr_dequeue() calls will be about 1
+ * system tick, as the callout that drives it is scheduled once per
+ * tick. The refill-time detection logic in tbr_dequeue() can only
+ * properly detect the passage of up to LLONG_MAX machclk ticks.
+ * Therefore, in order for this logic to function properly in the
+ * extreme case, the maximum value of tbr_filluptime should be
+ * LLONG_MAX less one system tick's worth of machclk ticks less
+ * some additional slop factor (here one more system tick's worth
+ * of machclk ticks).
+ */
+ if (tbr->tbr_filluptime > (LLONG_MAX - 2 * machclk_per_tick))
+ tbr->tbr_filluptime = LLONG_MAX - 2 * machclk_per_tick;
tbr->tbr_token = tbr->tbr_depth;
tbr->tbr_last = read_machclk();
tbr->tbr_lastop = ALTDQ_REMOVE;
@@ -458,29 +471,6 @@ tbr_timeout(arg)
}
/*
- * get token bucket regulator profile
- */
-int
-tbr_get(ifq, profile)
- struct ifaltq *ifq;
- struct tb_profile *profile;
-{
- struct tb_regulator *tbr;
-
- IFQ_LOCK(ifq);
- if ((tbr = ifq->altq_tbr) == NULL) {
- profile->rate = 0;
- profile->depth = 0;
- } else {
- profile->rate =
- (u_int)TBR_UNSCALE(tbr->tbr_rate * 8 * machclk_freq);
- profile->depth = (u_int)TBR_UNSCALE(tbr->tbr_depth);
- }
- IFQ_UNLOCK(ifq);
- return (0);
-}
-
-/*
* attach a discipline to the interface. if one already exists, it is
* overridden.
* Locking is done in the discipline specific attach functions. Basically
@@ -735,34 +725,34 @@ altq_remove_queue(struct pf_altq *a)
* copyout operations, also it is not yet clear which lock to use.
*/
int
-altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
int error = 0;
switch (a->scheduler) {
#ifdef ALTQ_CBQ
case ALTQT_CBQ:
- error = cbq_getqstats(a, ubuf, nbytes);
+ error = cbq_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_PRIQ
case ALTQT_PRIQ:
- error = priq_getqstats(a, ubuf, nbytes);
+ error = priq_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_HFSC
case ALTQT_HFSC:
- error = hfsc_getqstats(a, ubuf, nbytes);
+ error = hfsc_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_FAIRQ
case ALTQT_FAIRQ:
- error = fairq_getqstats(a, ubuf, nbytes);
+ error = fairq_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_CODEL
case ALTQT_CODEL:
- error = codel_getqstats(a, ubuf, nbytes);
+ error = codel_getqstats(a, ubuf, nbytes, version);
break;
#endif
default:
diff --git a/freebsd/sys/net/altq/altq_var.h b/freebsd/sys/net/altq/altq_var.h
index 1909599d..47326a03 100644
--- a/freebsd/sys/net/altq/altq_var.h
+++ b/freebsd/sys/net/altq/altq_var.h
@@ -196,7 +196,6 @@ u_int8_t read_dsfield(struct mbuf *, struct altq_pktattr *);
void write_dsfield(struct mbuf *, struct altq_pktattr *, u_int8_t);
void altq_assert(const char *, int, const char *);
int tbr_set(struct ifaltq *, struct tb_profile *);
-int tbr_get(struct ifaltq *, struct tb_profile *);
int altq_pfattach(struct pf_altq *);
int altq_pfdetach(struct pf_altq *);
@@ -204,40 +203,40 @@ int altq_add(struct pf_altq *);
int altq_remove(struct pf_altq *);
int altq_add_queue(struct pf_altq *);
int altq_remove_queue(struct pf_altq *);
-int altq_getqstats(struct pf_altq *, void *, int *);
+int altq_getqstats(struct pf_altq *, void *, int *, int);
int cbq_pfattach(struct pf_altq *);
int cbq_add_altq(struct pf_altq *);
int cbq_remove_altq(struct pf_altq *);
int cbq_add_queue(struct pf_altq *);
int cbq_remove_queue(struct pf_altq *);
-int cbq_getqstats(struct pf_altq *, void *, int *);
+int cbq_getqstats(struct pf_altq *, void *, int *, int);
int codel_pfattach(struct pf_altq *);
int codel_add_altq(struct pf_altq *);
int codel_remove_altq(struct pf_altq *);
-int codel_getqstats(struct pf_altq *, void *, int *);
+int codel_getqstats(struct pf_altq *, void *, int *, int);
int priq_pfattach(struct pf_altq *);
int priq_add_altq(struct pf_altq *);
int priq_remove_altq(struct pf_altq *);
int priq_add_queue(struct pf_altq *);
int priq_remove_queue(struct pf_altq *);
-int priq_getqstats(struct pf_altq *, void *, int *);
+int priq_getqstats(struct pf_altq *, void *, int *, int);
int hfsc_pfattach(struct pf_altq *);
int hfsc_add_altq(struct pf_altq *);
int hfsc_remove_altq(struct pf_altq *);
int hfsc_add_queue(struct pf_altq *);
int hfsc_remove_queue(struct pf_altq *);
-int hfsc_getqstats(struct pf_altq *, void *, int *);
+int hfsc_getqstats(struct pf_altq *, void *, int *, int);
int fairq_pfattach(struct pf_altq *);
int fairq_add_altq(struct pf_altq *);
int fairq_remove_altq(struct pf_altq *);
int fairq_add_queue(struct pf_altq *);
int fairq_remove_queue(struct pf_altq *);
-int fairq_getqstats(struct pf_altq *, void *, int *);
+int fairq_getqstats(struct pf_altq *, void *, int *, int);
#endif /* _KERNEL */
#endif /* _ALTQ_ALTQ_VAR_H_ */
diff --git a/freebsd/sys/net/altq/if_altq.h b/freebsd/sys/net/altq/if_altq.h
index 3dcc96c2..7a093500 100644
--- a/freebsd/sys/net/altq/if_altq.h
+++ b/freebsd/sys/net/altq/if_altq.h
@@ -143,7 +143,11 @@ struct tb_regulator {
#define ALTRQ_PURGE 1 /* purge all packets */
#define ALTQ_IS_READY(ifq) ((ifq)->altq_flags & ALTQF_READY)
+#ifdef ALTQ
#define ALTQ_IS_ENABLED(ifq) ((ifq)->altq_flags & ALTQF_ENABLED)
+#else
+#define ALTQ_IS_ENABLED(ifq) 0
+#endif
#define ALTQ_NEEDS_CLASSIFY(ifq) ((ifq)->altq_flags & ALTQF_CLASSIFY)
#define ALTQ_IS_CNDTNING(ifq) ((ifq)->altq_flags & ALTQF_CNDTNING)
diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c
index 57aff5b8..357fd1b1 100644
--- a/freebsd/sys/net/bpf.c
+++ b/freebsd/sys/net/bpf.c
@@ -124,6 +124,11 @@ struct bpf_if {
CTASSERT(offsetof(struct bpf_if, bif_ext) == 0);
+#define BPFIF_RLOCK(bif) rw_rlock(&(bif)->bif_lock)
+#define BPFIF_RUNLOCK(bif) rw_runlock(&(bif)->bif_lock)
+#define BPFIF_WLOCK(bif) rw_wlock(&(bif)->bif_lock)
+#define BPFIF_WUNLOCK(bif) rw_wunlock(&(bif)->bif_lock)
+
#if defined(DEV_BPF) || defined(NETGRAPH_BPF)
#define PRINET 26 /* interruptible */
@@ -217,7 +222,7 @@ SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_enable, CTLFLAG_RW,
static SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_MPSAFE | CTLFLAG_RW,
bpf_stats_sysctl, "bpf statistics portal");
-static VNET_DEFINE(int, bpf_optimize_writers) = 0;
+VNET_DEFINE_STATIC(int, bpf_optimize_writers) = 0;
#define V_bpf_optimize_writers VNET(bpf_optimize_writers)
SYSCTL_INT(_net_bpf, OID_AUTO, optimize_writers, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(bpf_optimize_writers), 0,
@@ -1974,8 +1979,13 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
return (EINVAL);
}
#ifdef BPF_JITTER
- /* Filter is copied inside fcode and is perfectly valid. */
- jfunc = bpf_jitter(fcode, flen);
+ if (cmd != BIOCSETWF) {
+ /*
+ * Filter is copied inside fcode and is
+ * perfectly valid.
+ */
+ jfunc = bpf_jitter(fcode, flen);
+ }
#endif
}
diff --git a/freebsd/sys/net/bpf_jitter.c b/freebsd/sys/net/bpf_jitter.c
index ac3a6ddd..85782597 100644
--- a/freebsd/sys/net/bpf_jitter.c
+++ b/freebsd/sys/net/bpf_jitter.c
@@ -103,11 +103,13 @@ void
bpf_destroy_jit_filter(bpf_jit_filter *filter)
{
- if (filter->func != bpf_jit_accept_all)
- bpf_jit_free(filter->func, filter->size);
#ifdef _KERNEL
+ if (filter->func != bpf_jit_accept_all)
+ free(filter->func, M_BPFJIT);
free(filter, M_BPFJIT);
#else
+ if (filter->func != bpf_jit_accept_all)
+ munmap(filter->func, filter->size);
free(filter);
#endif
}
diff --git a/freebsd/sys/net/bpf_jitter.h b/freebsd/sys/net/bpf_jitter.h
index a7c7cd9f..23049d14 100644
--- a/freebsd/sys/net/bpf_jitter.h
+++ b/freebsd/sys/net/bpf_jitter.h
@@ -88,6 +88,5 @@ void bpf_destroy_jit_filter(bpf_jit_filter *filter);
struct bpf_insn;
bpf_filter_func bpf_jit_compile(struct bpf_insn *, u_int, size_t *);
-void bpf_jit_free(void *, size_t);
#endif /* _NET_BPF_JITTER_H_ */
diff --git a/freebsd/sys/net/bpfdesc.h b/freebsd/sys/net/bpfdesc.h
index 95093cff..2ce9204b 100644
--- a/freebsd/sys/net/bpfdesc.h
+++ b/freebsd/sys/net/bpfdesc.h
@@ -161,11 +161,6 @@ struct xbpf_d {
u_int64_t bd_spare[4];
};
-#define BPFIF_RLOCK(bif) rw_rlock(&(bif)->bif_lock)
-#define BPFIF_RUNLOCK(bif) rw_runlock(&(bif)->bif_lock)
-#define BPFIF_WLOCK(bif) rw_wlock(&(bif)->bif_lock)
-#define BPFIF_WUNLOCK(bif) rw_wunlock(&(bif)->bif_lock)
-
#define BPFIF_FLAG_DYING 1 /* Reject new bpf consumers */
#endif
diff --git a/freebsd/sys/net/ieee8023ad_lacp.c b/freebsd/sys/net/ieee8023ad_lacp.c
index 2a30f4a3..9a70d6a1 100644
--- a/freebsd/sys/net/ieee8023ad_lacp.c
+++ b/freebsd/sys/net/ieee8023ad_lacp.c
@@ -196,13 +196,13 @@ static const char *lacp_format_portid(const struct lacp_portid *, char *,
static void lacp_dprintf(const struct lacp_port *, const char *, ...)
__attribute__((__format__(__printf__, 2, 3)));
-static VNET_DEFINE(int, lacp_debug);
+VNET_DEFINE_STATIC(int, lacp_debug);
#define V_lacp_debug VNET(lacp_debug)
SYSCTL_NODE(_net_link_lagg, OID_AUTO, lacp, CTLFLAG_RD, 0, "ieee802.3ad");
SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, debug, CTLFLAG_RWTUN | CTLFLAG_VNET,
&VNET_NAME(lacp_debug), 0, "Enable LACP debug logging (1=debug, 2=trace)");
-static VNET_DEFINE(int, lacp_default_strict_mode) = 1;
+VNET_DEFINE_STATIC(int, lacp_default_strict_mode) = 1;
SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, default_strict_mode,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(lacp_default_strict_mode), 0,
"LACP strict protocol compliance default");
@@ -713,6 +713,8 @@ lacp_disable_distributing(struct lacp_port *lp)
}
lp->lp_state &= ~LACP_STATE_DISTRIBUTING;
+ if_link_state_change(sc->sc_ifp,
+ sc->sc_active ? LINK_STATE_UP : LINK_STATE_DOWN);
}
static void
@@ -747,6 +749,9 @@ lacp_enable_distributing(struct lacp_port *lp)
} else
/* try to become the active aggregator */
lacp_select_active_aggregator(lsc);
+
+ if_link_state_change(sc->sc_ifp,
+ sc->sc_active ? LINK_STATE_UP : LINK_STATE_DOWN);
}
static void
@@ -1106,6 +1111,7 @@ lacp_compose_key(struct lacp_port *lp)
case IFM_100_VG:
case IFM_100_T2:
case IFM_100_T:
+ case IFM_100_SGMII:
key = IFM_100_TX;
break;
case IFM_1000_SX:
@@ -1137,14 +1143,31 @@ lacp_compose_key(struct lacp_port *lp)
break;
case IFM_2500_KX:
case IFM_2500_T:
+ case IFM_2500_X:
key = IFM_2500_KX;
break;
case IFM_5000_T:
+ case IFM_5000_KR:
+ case IFM_5000_KR_S:
+ case IFM_5000_KR1:
key = IFM_5000_T;
break;
case IFM_50G_PCIE:
case IFM_50G_CR2:
case IFM_50G_KR2:
+ case IFM_50G_SR2:
+ case IFM_50G_LR2:
+ case IFM_50G_LAUI2_AC:
+ case IFM_50G_LAUI2:
+ case IFM_50G_AUI2_AC:
+ case IFM_50G_AUI2:
+ case IFM_50G_CP:
+ case IFM_50G_SR:
+ case IFM_50G_LR:
+ case IFM_50G_FR:
+ case IFM_50G_KR_PAM4:
+ case IFM_50G_AUI1_AC:
+ case IFM_50G_AUI1:
key = IFM_50G_PCIE;
break;
case IFM_56G_R4:
@@ -1157,6 +1180,12 @@ lacp_compose_key(struct lacp_port *lp)
case IFM_25G_LR:
case IFM_25G_ACC:
case IFM_25G_AOC:
+ case IFM_25G_T:
+ case IFM_25G_CR_S:
+ case IFM_25G_CR1:
+ case IFM_25G_KR_S:
+ case IFM_25G_AUI:
+ case IFM_25G_KR1:
key = IFM_25G_PCIE;
break;
case IFM_40G_CR4:
@@ -1164,14 +1193,50 @@ lacp_compose_key(struct lacp_port *lp)
case IFM_40G_LR4:
case IFM_40G_XLPPI:
case IFM_40G_KR4:
+ case IFM_40G_XLAUI:
+ case IFM_40G_XLAUI_AC:
+ case IFM_40G_ER4:
key = IFM_40G_CR4;
break;
case IFM_100G_CR4:
case IFM_100G_SR4:
case IFM_100G_KR4:
case IFM_100G_LR4:
+ case IFM_100G_CAUI4_AC:
+ case IFM_100G_CAUI4:
+ case IFM_100G_AUI4_AC:
+ case IFM_100G_AUI4:
+ case IFM_100G_CR_PAM4:
+ case IFM_100G_KR_PAM4:
+ case IFM_100G_CP2:
+ case IFM_100G_SR2:
+ case IFM_100G_DR:
+ case IFM_100G_KR2_PAM4:
+ case IFM_100G_CAUI2_AC:
+ case IFM_100G_CAUI2:
+ case IFM_100G_AUI2_AC:
+ case IFM_100G_AUI2:
key = IFM_100G_CR4;
break;
+ case IFM_200G_CR4_PAM4:
+ case IFM_200G_SR4:
+ case IFM_200G_FR4:
+ case IFM_200G_LR4:
+ case IFM_200G_DR4:
+ case IFM_200G_KR4_PAM4:
+ case IFM_200G_AUI4_AC:
+ case IFM_200G_AUI4:
+ case IFM_200G_AUI8_AC:
+ case IFM_200G_AUI8:
+ key = IFM_200G_CR4_PAM4;
+ break;
+ case IFM_400G_FR8:
+ case IFM_400G_LR8:
+ case IFM_400G_DR4:
+ case IFM_400G_AUI8_AC:
+ case IFM_400G_AUI8:
+ key = IFM_400G_FR8;
+ break;
default:
key = subtype;
break;
diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c
index d4c18b46..4d3c303c 100644
--- a/freebsd/sys/net/if.c
+++ b/freebsd/sys/net/if.c
@@ -300,7 +300,7 @@ int ifqmaxlen = IFQ_MAXLEN;
VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */
VNET_DEFINE(struct ifgrouphead, ifg_head);
-static VNET_DEFINE(int, if_indexlim) = 8;
+VNET_DEFINE_STATIC(int, if_indexlim) = 8;
/* Table of ifnet by index. */
VNET_DEFINE(struct ifnet **, ifindex_table);
@@ -1769,29 +1769,35 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd)
void
if_addr_rlock(struct ifnet *ifp)
{
-
- IF_ADDR_RLOCK(ifp);
+ MPASS(*(uint64_t *)&ifp->if_addr_et == 0);
+ epoch_enter_preempt(net_epoch_preempt, &ifp->if_addr_et);
}
void
if_addr_runlock(struct ifnet *ifp)
{
-
- IF_ADDR_RUNLOCK(ifp);
+ epoch_exit_preempt(net_epoch_preempt, &ifp->if_addr_et);
+#ifdef INVARIANTS
+ bzero(&ifp->if_addr_et, sizeof(struct epoch_tracker));
+#endif
}
void
if_maddr_rlock(if_t ifp)
{
- IF_ADDR_RLOCK((struct ifnet *)ifp);
+ MPASS(*(uint64_t *)&ifp->if_maddr_et == 0);
+ epoch_enter_preempt(net_epoch_preempt, &ifp->if_maddr_et);
}
void
if_maddr_runlock(if_t ifp)
{
- IF_ADDR_RUNLOCK((struct ifnet *)ifp);
+ epoch_exit_preempt(net_epoch_preempt, &ifp->if_maddr_et);
+#ifdef INVARIANTS
+ bzero(&ifp->if_maddr_et, sizeof(struct epoch_tracker));
+#endif
}
/*
@@ -1935,7 +1941,7 @@ ifa_ifwithaddr(const struct sockaddr *addr)
struct ifnet *ifp;
struct ifaddr *ifa;
- MPASS(in_epoch());
+ MPASS(in_epoch(net_epoch_preempt));
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
@@ -1978,7 +1984,7 @@ ifa_ifwithbroadaddr(const struct sockaddr *addr, int fibnum)
struct ifnet *ifp;
struct ifaddr *ifa;
- MPASS(in_epoch());
+ MPASS(in_epoch(net_epoch_preempt));
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum))
continue;
@@ -2008,7 +2014,7 @@ ifa_ifwithdstaddr(const struct sockaddr *addr, int fibnum)
struct ifnet *ifp;
struct ifaddr *ifa;
- MPASS(in_epoch());
+ MPASS(in_epoch(net_epoch_preempt));
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
continue;
@@ -2041,7 +2047,7 @@ ifa_ifwithnet(const struct sockaddr *addr, int ignore_ptp, int fibnum)
u_int af = addr->sa_family;
const char *addr_data = addr->sa_data, *cplim;
- MPASS(in_epoch());
+ MPASS(in_epoch(net_epoch_preempt));
/*
* AF_LINK addresses can be looked up directly by their index number,
* so do that if we can.
@@ -2078,7 +2084,6 @@ next: continue;
*/
if (ifa->ifa_dstaddr != NULL &&
sa_equal(addr, ifa->ifa_dstaddr)) {
- IF_ADDR_RUNLOCK(ifp);
goto done;
}
} else {
@@ -2137,7 +2142,8 @@ ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
if (af >= AF_MAX)
return (NULL);
- MPASS(in_epoch());
+
+ MPASS(in_epoch(net_epoch_preempt));
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != af)
continue;
@@ -2301,6 +2307,7 @@ void (*vlan_trunk_cap_p)(struct ifnet *); /* XXX: private from if_vlan */
struct ifnet *(*vlan_trunkdev_p)(struct ifnet *);
struct ifnet *(*vlan_devat_p)(struct ifnet *, uint16_t);
int (*vlan_tag_p)(struct ifnet *, uint16_t *);
+int (*vlan_pcp_p)(struct ifnet *, uint16_t *);
int (*vlan_setcookie_p)(struct ifnet *, void *);
void *(*vlan_cookie_p)(struct ifnet *);
@@ -2988,8 +2995,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
#ifdef COMPAT_FREEBSD32
caddr_t saved_data = NULL;
struct ifmediareq ifmr;
-#endif
struct ifmediareq *ifmrp;
+#endif
struct ifnet *ifp;
struct ifreq *ifr;
int error;
@@ -3035,8 +3042,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
#endif
}
- ifmrp = NULL;
#ifdef COMPAT_FREEBSD32
+ ifmrp = NULL;
switch (cmd) {
case SIOCGIFMEDIA32:
case SIOCGIFXMEDIA32:
@@ -3564,6 +3571,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
error = ENOMEM;
goto free_llsa_out;
}
+ ll_ifma->ifma_flags |= IFMA_F_ENQUEUED;
CK_STAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma,
ifma_link);
} else
@@ -3576,6 +3584,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
* referenced link layer address. Add the primary address to the
* ifnet address list.
*/
+ ifma->ifma_flags |= IFMA_F_ENQUEUED;
CK_STAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
if (retifma != NULL)
@@ -3776,9 +3785,10 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
if (--ifma->ifma_refcount > 0)
return 0;
- if (ifp != NULL && detaching == 0)
+ if (ifp != NULL && detaching == 0 && (ifma->ifma_flags & IFMA_F_ENQUEUED)) {
CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
-
+ ifma->ifma_flags &= ~IFMA_F_ENQUEUED;
+ }
/*
* If this ifma is a network-layer ifma, a link-layer ifma may
* have been associated with it. Release it first if so.
@@ -3791,8 +3801,11 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
ll_ifma->ifma_ifp = NULL; /* XXX */
if (--ll_ifma->ifma_refcount == 0) {
if (ifp != NULL) {
- CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr,
- ifma_link);
+ if (ll_ifma->ifma_flags & IFMA_F_ENQUEUED) {
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr,
+ ifma_link);
+ ll_ifma->ifma_flags &= ~IFMA_F_ENQUEUED;
+ }
}
if_freemulti(ll_ifma);
}
@@ -3922,6 +3935,44 @@ if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req)
}
/*
+ * Tunnel interfaces can nest, also they may cause infinite recursion
+ * calls when misconfigured. We'll prevent this by detecting loops.
+ * High nesting level may cause stack exhaustion. We'll prevent this
+ * by introducing upper limit.
+ *
+ * Return 0, if tunnel nesting count is equal or less than limit.
+ */
+int
+if_tunnel_check_nesting(struct ifnet *ifp, struct mbuf *m, uint32_t cookie,
+ int limit)
+{
+ struct m_tag *mtag;
+ int count;
+
+ count = 1;
+ mtag = NULL;
+ while ((mtag = m_tag_locate(m, cookie, 0, mtag)) != NULL) {
+ if (*(struct ifnet **)(mtag + 1) == ifp) {
+ log(LOG_NOTICE, "%s: loop detected\n", if_name(ifp));
+ return (EIO);
+ }
+ count++;
+ }
+ if (count > limit) {
+ log(LOG_NOTICE,
+ "%s: if_output recursively called too many times(%d)\n",
+ if_name(ifp), count);
+ return (EIO);
+ }
+ mtag = m_tag_alloc(cookie, 0, sizeof(struct ifnet *), M_NOWAIT);
+ if (mtag == NULL)
+ return (ENOMEM);
+ *(struct ifnet **)(mtag + 1) = ifp;
+ m_tag_prepend(m, mtag);
+ return (0);
+}
+
+/*
* Get the link layer address that was read from the hardware at attach.
*
* This is only set by Ethernet NICs (IFT_ETHER), but laggX interfaces re-type
diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c
index 3e774934..aa56be48 100644
--- a/freebsd/sys/net/if_bridge.c
+++ b/freebsd/sys/net/if_bridge.c
@@ -231,7 +231,7 @@ struct bridge_softc {
u_char sc_defaddr[6]; /* Default MAC address */
};
-static VNET_DEFINE(struct mtx, bridge_list_mtx);
+VNET_DEFINE_STATIC(struct mtx, bridge_list_mtx);
#define V_bridge_list_mtx VNET(bridge_list_mtx)
static eventhandler_tag bridge_detach_cookie;
@@ -356,59 +356,59 @@ SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge");
/* only pass IP[46] packets when pfil is enabled */
-static VNET_DEFINE(int, pfil_onlyip) = 1;
+VNET_DEFINE_STATIC(int, pfil_onlyip) = 1;
#define V_pfil_onlyip VNET(pfil_onlyip)
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_onlyip), 0,
"Only pass IP packets when pfil is enabled");
/* run pfil hooks on the bridge interface */
-static VNET_DEFINE(int, pfil_bridge) = 1;
+VNET_DEFINE_STATIC(int, pfil_bridge) = 1;
#define V_pfil_bridge VNET(pfil_bridge)
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_bridge), 0,
"Packet filter on the bridge interface");
/* layer2 filter with ipfw */
-static VNET_DEFINE(int, pfil_ipfw);
+VNET_DEFINE_STATIC(int, pfil_ipfw);
#define V_pfil_ipfw VNET(pfil_ipfw)
/* layer2 ARP filter with ipfw */
-static VNET_DEFINE(int, pfil_ipfw_arp);
+VNET_DEFINE_STATIC(int, pfil_ipfw_arp);
#define V_pfil_ipfw_arp VNET(pfil_ipfw_arp)
SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_ipfw_arp), 0,
"Filter ARP packets through IPFW layer2");
/* run pfil hooks on the member interface */
-static VNET_DEFINE(int, pfil_member) = 1;
+VNET_DEFINE_STATIC(int, pfil_member) = 1;
#define V_pfil_member VNET(pfil_member)
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_member), 0,
"Packet filter on the member interface");
/* run pfil hooks on the physical interface for locally destined packets */
-static VNET_DEFINE(int, pfil_local_phys);
+VNET_DEFINE_STATIC(int, pfil_local_phys);
#define V_pfil_local_phys VNET(pfil_local_phys)
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_local_phys), 0,
"Packet filter on the physical interface for locally destined packets");
/* log STP state changes */
-static VNET_DEFINE(int, log_stp);
+VNET_DEFINE_STATIC(int, log_stp);
#define V_log_stp VNET(log_stp)
SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(log_stp), 0,
"Log STP state changes");
/* share MAC with first bridge member */
-static VNET_DEFINE(int, bridge_inherit_mac);
+VNET_DEFINE_STATIC(int, bridge_inherit_mac);
#define V_bridge_inherit_mac VNET(bridge_inherit_mac)
SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac,
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(bridge_inherit_mac), 0,
"Inherit MAC address from the first bridge member");
-static VNET_DEFINE(int, allow_llz_overlap) = 0;
+VNET_DEFINE_STATIC(int, allow_llz_overlap) = 0;
#define V_allow_llz_overlap VNET(allow_llz_overlap)
SYSCTL_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap,
CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(allow_llz_overlap), 0,
@@ -512,7 +512,7 @@ const struct bridge_control bridge_control_table[] = {
};
const int bridge_control_table_size = nitems(bridge_control_table);
-static VNET_DEFINE(LIST_HEAD(, bridge_softc), bridge_list);
+VNET_DEFINE_STATIC(LIST_HEAD(, bridge_softc), bridge_list);
#define V_bridge_list VNET(bridge_list)
#define BRIDGE_LIST_LOCK_INIT(x) mtx_init(&V_bridge_list_mtx, \
"if_bridge list", NULL, MTX_DEF)
@@ -520,7 +520,7 @@ static VNET_DEFINE(LIST_HEAD(, bridge_softc), bridge_list);
#define BRIDGE_LIST_LOCK(x) mtx_lock(&V_bridge_list_mtx)
#define BRIDGE_LIST_UNLOCK(x) mtx_unlock(&V_bridge_list_mtx)
-static VNET_DEFINE(struct if_clone *, bridge_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, bridge_cloner);
#define V_bridge_cloner VNET(bridge_cloner)
static const char bridge_name[] = "bridge";
diff --git a/freebsd/sys/net/if_clone.c b/freebsd/sys/net/if_clone.c
index 5a9c20c2..1fa79766 100644
--- a/freebsd/sys/net/if_clone.c
+++ b/freebsd/sys/net/if_clone.c
@@ -110,7 +110,7 @@ static int ifc_simple_destroy(struct if_clone *, struct ifnet *);
static struct mtx if_cloners_mtx;
MTX_SYSINIT(if_cloners_lock, &if_cloners_mtx, "if_cloners lock", MTX_DEF);
-static VNET_DEFINE(int, if_cloners_count);
+VNET_DEFINE_STATIC(int, if_cloners_count);
VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners);
#define V_if_cloners_count VNET(if_cloners_count)
diff --git a/freebsd/sys/net/if_disc.c b/freebsd/sys/net/if_disc.c
index b3ff7ff8..1c0bc166 100644
--- a/freebsd/sys/net/if_disc.c
+++ b/freebsd/sys/net/if_disc.c
@@ -78,7 +78,7 @@ static void disc_clone_destroy(struct ifnet *);
static const char discname[] = "disc";
static MALLOC_DEFINE(M_DISC, discname, "Discard interface");
-static VNET_DEFINE(struct if_clone *, disc_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, disc_cloner);
#define V_disc_cloner VNET(disc_cloner)
static int
diff --git a/freebsd/sys/net/if_edsc.c b/freebsd/sys/net/if_edsc.c
index 6b5671c1..b12e0bb8 100644
--- a/freebsd/sys/net/if_edsc.c
+++ b/freebsd/sys/net/if_edsc.c
@@ -74,7 +74,7 @@ struct edsc_softc {
/*
* Attach to the interface cloning framework.
*/
-static VNET_DEFINE(struct if_clone *, edsc_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, edsc_cloner);
#define V_edsc_cloner VNET(edsc_cloner)
static int edsc_clone_create(struct if_clone *, int, caddr_t);
static void edsc_clone_destroy(struct ifnet *);
diff --git a/freebsd/sys/net/if_enc.c b/freebsd/sys/net/if_enc.c
index 8ca8aa4d..ebfbf5cb 100644
--- a/freebsd/sys/net/if_enc.c
+++ b/freebsd/sys/net/if_enc.c
@@ -88,9 +88,9 @@ struct enchdr {
struct enc_softc {
struct ifnet *sc_ifp;
};
-static VNET_DEFINE(struct enc_softc *, enc_sc);
+VNET_DEFINE_STATIC(struct enc_softc *, enc_sc);
#define V_enc_sc VNET(enc_sc)
-static VNET_DEFINE(struct if_clone *, enc_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, enc_cloner);
#define V_enc_cloner VNET(enc_cloner)
static int enc_ioctl(struct ifnet *, u_long, caddr_t);
@@ -113,10 +113,10 @@ static const char encname[] = "enc";
* some changes to the packet, e.g. address translation. If PFIL hook
* consumes mbuf, nothing will be captured.
*/
-static VNET_DEFINE(int, filter_mask_in) = IPSEC_ENC_BEFORE;
-static VNET_DEFINE(int, bpf_mask_in) = IPSEC_ENC_BEFORE;
-static VNET_DEFINE(int, filter_mask_out) = IPSEC_ENC_BEFORE;
-static VNET_DEFINE(int, bpf_mask_out) = IPSEC_ENC_BEFORE | IPSEC_ENC_AFTER;
+VNET_DEFINE_STATIC(int, filter_mask_in) = IPSEC_ENC_BEFORE;
+VNET_DEFINE_STATIC(int, bpf_mask_in) = IPSEC_ENC_BEFORE;
+VNET_DEFINE_STATIC(int, filter_mask_out) = IPSEC_ENC_BEFORE;
+VNET_DEFINE_STATIC(int, bpf_mask_out) = IPSEC_ENC_BEFORE | IPSEC_ENC_AFTER;
#define V_filter_mask_in VNET(filter_mask_in)
#define V_bpf_mask_in VNET(bpf_mask_in)
#define V_filter_mask_out VNET(filter_mask_out)
diff --git a/freebsd/sys/net/if_epair.c b/freebsd/sys/net/if_epair.c
index d727bc2c..69ff3efc 100644
--- a/freebsd/sys/net/if_epair.c
+++ b/freebsd/sys/net/if_epair.c
@@ -109,6 +109,7 @@ static int epair_clone_create(struct if_clone *, char *, size_t, caddr_t);
static int epair_clone_destroy(struct if_clone *, struct ifnet *);
static const char epairname[] = "epair";
+static unsigned int next_index = 0;
/* Netisr related definitions and sysctl. */
static struct netisr_handler epair_nh = {
@@ -181,7 +182,7 @@ STAILQ_HEAD(eid_list, epair_ifp_drain);
static MALLOC_DEFINE(M_EPAIR, epairname,
"Pair of virtual cross-over connected Ethernet-like interfaces");
-static VNET_DEFINE(struct if_clone *, epair_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, epair_cloner);
#define V_epair_cloner VNET(epair_cloner)
/*
@@ -845,12 +846,22 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
/*
* Calculate the etheraddr hashing the hostid and the
- * interface index. The result would be hopefully unique
+ * interface index. The result would be hopefully unique.
+ * Note that the "a" component of an epair instance may get moved
+ * to a different VNET after creation. In that case its index
+ * will be freed and the index can get reused by new epair instance.
+ * Make sure we do not create same etheraddr again.
*/
getcredhostid(curthread->td_ucred, (unsigned long *)&hostid);
if (hostid == 0)
arc4rand(&hostid, sizeof(hostid), 0);
- key[0] = (uint32_t)ifp->if_index;
+
+ if (ifp->if_index > next_index)
+ next_index = ifp->if_index;
+ else
+ next_index++;
+
+ key[0] = (uint32_t)next_index;
key[1] = (uint32_t)(hostid & 0xffffffff);
key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff);
hash = jenkins_hash32(key, 3, 0);
diff --git a/freebsd/sys/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c
index 3893d331..01e757e5 100644
--- a/freebsd/sys/net/if_ethersubr.c
+++ b/freebsd/sys/net/if_ethersubr.c
@@ -463,7 +463,8 @@ ether_output_frame(struct ifnet *ifp, struct mbuf *m)
uint8_t pcp;
pcp = ifp->if_pcp;
- if (pcp != IFNET_PCP_NONE && !ether_set_pcp(&m, ifp, pcp))
+ if (pcp != IFNET_PCP_NONE && ifp->if_type != IFT_L2VLAN &&
+ !ether_set_pcp(&m, ifp, pcp))
return (0);
if (PFIL_HOOKED(&V_link_pfil_hook)) {
@@ -515,7 +516,7 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m)
}
eh = mtod(m, struct ether_header *);
etype = ntohs(eh->ether_type);
- random_harvest_queue_ether(m, sizeof(*m), 2);
+ random_harvest_queue_ether(m, sizeof(*m));
CURVNET_SET_QUIET(ifp->if_vnet);
@@ -1293,7 +1294,7 @@ static SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0,
static SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0,
"for consistency");
-static VNET_DEFINE(int, soft_pad);
+VNET_DEFINE_STATIC(int, soft_pad);
#define V_soft_pad VNET(soft_pad)
SYSCTL_INT(_net_link_vlan, OID_AUTO, soft_pad, CTLFLAG_RW | CTLFLAG_VNET,
&VNET_NAME(soft_pad), 0,
diff --git a/freebsd/sys/net/if_gif.c b/freebsd/sys/net/if_gif.c
index 6a90538a..5a67e7ff 100644
--- a/freebsd/sys/net/if_gif.c
+++ b/freebsd/sys/net/if_gif.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/protosw.h>
#include <sys/conf.h>
#include <machine/cpu.h>
@@ -87,8 +86,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip6.h>
#include <netinet6/ip6_ecn.h>
#include <netinet6/ip6_var.h>
-#include <netinet6/scope6_var.h>
-#include <netinet6/ip6protosw.h>
#endif /* INET6 */
#include <netinet/ip_encap.h>
@@ -100,42 +97,24 @@ __FBSDID("$FreeBSD$");
static const char gifname[] = "gif";
-/*
- * gif_mtx protects a per-vnet gif_softc_list.
- */
-static VNET_DEFINE(struct mtx, gif_mtx);
-#define V_gif_mtx VNET(gif_mtx)
-static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
-static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
-#define V_gif_softc_list VNET(gif_softc_list)
+MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
static struct sx gif_ioctl_sx;
SX_SYSINIT(gif_ioctl_sx, &gif_ioctl_sx, "gif_ioctl");
-#define GIF_LIST_LOCK_INIT(x) mtx_init(&V_gif_mtx, "gif_mtx", \
- NULL, MTX_DEF)
-#define GIF_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gif_mtx)
-#define GIF_LIST_LOCK(x) mtx_lock(&V_gif_mtx)
-#define GIF_LIST_UNLOCK(x) mtx_unlock(&V_gif_mtx)
-
void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
void (*ng_gif_attach_p)(struct ifnet *ifp);
void (*ng_gif_detach_p)(struct ifnet *ifp);
-static int gif_check_nesting(struct ifnet *, struct mbuf *);
-static int gif_set_tunnel(struct ifnet *, struct sockaddr *,
- struct sockaddr *);
-static void gif_delete_tunnel(struct ifnet *);
+static void gif_delete_tunnel(struct gif_softc *);
static int gif_ioctl(struct ifnet *, u_long, caddr_t);
static int gif_transmit(struct ifnet *, struct mbuf *);
static void gif_qflush(struct ifnet *);
static int gif_clone_create(struct if_clone *, int, caddr_t);
static void gif_clone_destroy(struct ifnet *);
-static VNET_DEFINE(struct if_clone *, gif_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, gif_cloner);
#define V_gif_cloner VNET(gif_cloner)
-static int gifmodevent(module_t, int, void *);
-
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
"Generic Tunnel Interface");
@@ -150,26 +129,11 @@ static SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
*/
#define MAX_GIF_NEST 1
#endif
-static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST;
+VNET_DEFINE_STATIC(int, max_gif_nesting) = MAX_GIF_NEST;
#define V_max_gif_nesting VNET(max_gif_nesting)
SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(max_gif_nesting), 0, "Max nested tunnels");
-/*
- * By default, we disallow creation of multiple tunnels between the same
- * pair of addresses. Some applications require this functionality so
- * we allow control over this check here.
- */
-#ifdef XBONEHACK
-static VNET_DEFINE(int, parallel_tunnels) = 1;
-#else
-static VNET_DEFINE(int, parallel_tunnels) = 0;
-#endif
-#define V_parallel_tunnels VNET(parallel_tunnels)
-SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(parallel_tunnels), 0,
- "Allow parallel tunnels?");
-
static int
gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
@@ -182,20 +146,15 @@ gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
sc->gif_fibnum = BSD_DEFAULT_FIB;
#endif /* __rtems__ */
GIF2IFP(sc) = if_alloc(IFT_GIF);
- GIF_LOCK_INIT(sc);
GIF2IFP(sc)->if_softc = sc;
if_initname(GIF2IFP(sc), gifname, unit);
GIF2IFP(sc)->if_addrlen = 0;
GIF2IFP(sc)->if_mtu = GIF_MTU;
GIF2IFP(sc)->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
-#if 0
- /* turn off ingress filter */
- GIF2IFP(sc)->if_flags |= IFF_LINK2;
-#endif
GIF2IFP(sc)->if_ioctl = gif_ioctl;
- GIF2IFP(sc)->if_transmit = gif_transmit;
- GIF2IFP(sc)->if_qflush = gif_qflush;
+ GIF2IFP(sc)->if_transmit = gif_transmit;
+ GIF2IFP(sc)->if_qflush = gif_qflush;
GIF2IFP(sc)->if_output = gif_output;
GIF2IFP(sc)->if_capabilities |= IFCAP_LINKSTATE;
GIF2IFP(sc)->if_capenable |= IFCAP_LINKSTATE;
@@ -204,9 +163,6 @@ gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
if (ng_gif_attach_p != NULL)
(*ng_gif_attach_p)(GIF2IFP(sc));
- GIF_LIST_LOCK();
- LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list);
- GIF_LIST_UNLOCK();
return (0);
}
@@ -217,10 +173,7 @@ gif_clone_destroy(struct ifnet *ifp)
sx_xlock(&gif_ioctl_sx);
sc = ifp->if_softc;
- gif_delete_tunnel(ifp);
- GIF_LIST_LOCK();
- LIST_REMOVE(sc, gif_list);
- GIF_LIST_UNLOCK();
+ gif_delete_tunnel(sc);
if (ng_gif_detach_p != NULL)
(*ng_gif_detach_p)(ifp);
bpfdetach(ifp);
@@ -228,8 +181,8 @@ gif_clone_destroy(struct ifnet *ifp)
ifp->if_softc = NULL;
sx_xunlock(&gif_ioctl_sx);
+ GIF_WAIT();
if_free(ifp);
- GIF_LOCK_DESTROY(sc);
free(sc, M_GIF);
}
@@ -237,10 +190,14 @@ static void
vnet_gif_init(const void *unused __unused)
{
- LIST_INIT(&V_gif_softc_list);
- GIF_LIST_LOCK_INIT();
V_gif_cloner = if_clone_simple(gifname, gif_clone_create,
gif_clone_destroy, 0);
+#ifdef INET
+ in_gif_init();
+#endif
+#ifdef INET6
+ in6_gif_init();
+#endif
}
VNET_SYSINIT(vnet_gif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_gif_init, NULL);
@@ -250,7 +207,12 @@ vnet_gif_uninit(const void *unused __unused)
{
if_clone_detach(V_gif_cloner);
- GIF_LIST_LOCK_DESTROY();
+#ifdef INET
+ in_gif_uninit();
+#endif
+#ifdef INET6
+ in6_gif_uninit();
+#endif
}
VNET_SYSUNINIT(vnet_gif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_gif_uninit, NULL);
@@ -278,67 +240,28 @@ static moduledata_t gif_mod = {
DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
MODULE_VERSION(if_gif, 1);
-int
-gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+struct gif_list *
+gif_hashinit(void)
{
- GIF_RLOCK_TRACKER;
- const struct ip *ip;
- struct gif_softc *sc;
- int ret;
-
- sc = (struct gif_softc *)arg;
- if (sc == NULL || (GIF2IFP(sc)->if_flags & IFF_UP) == 0)
- return (0);
+ struct gif_list *hash;
+ int i;
- ret = 0;
- GIF_RLOCK(sc);
+ hash = malloc(sizeof(struct gif_list) * GIF_HASH_SIZE,
+ M_GIF, M_WAITOK);
+ for (i = 0; i < GIF_HASH_SIZE; i++)
+ CK_LIST_INIT(&hash[i]);
- /* no physical address */
- if (sc->gif_family == 0)
- goto done;
-
- switch (proto) {
-#ifdef INET
- case IPPROTO_IPV4:
-#endif
-#ifdef INET6
- case IPPROTO_IPV6:
-#endif
- case IPPROTO_ETHERIP:
- break;
- default:
- goto done;
- }
+ return (hash);
+}
- /* Bail on short packets */
- M_ASSERTPKTHDR(m);
- if (m->m_pkthdr.len < sizeof(struct ip))
- goto done;
+void
+gif_hashdestroy(struct gif_list *hash)
+{
- ip = mtod(m, const struct ip *);
- switch (ip->ip_v) {
-#ifdef INET
- case 4:
- if (sc->gif_family != AF_INET)
- goto done;
- ret = in_gif_encapcheck(m, off, proto, arg);
- break;
-#endif
-#ifdef INET6
- case 6:
- if (m->m_pkthdr.len < sizeof(struct ip6_hdr))
- goto done;
- if (sc->gif_family != AF_INET6)
- goto done;
- ret = in6_gif_encapcheck(m, off, proto, arg);
- break;
-#endif
- }
-done:
- GIF_RUNLOCK(sc);
- return (ret);
+ free(hash, M_GIF);
}
+#define MTAG_GIF 1080679712
static int
gif_transmit(struct ifnet *ifp, struct mbuf *m)
{
@@ -363,11 +286,13 @@ gif_transmit(struct ifnet *ifp, struct mbuf *m)
}
#endif
error = ENETDOWN;
+ GIF_RLOCK();
sc = ifp->if_softc;
if ((ifp->if_flags & IFF_MONITOR) != 0 ||
(ifp->if_flags & IFF_UP) == 0 ||
sc->gif_family == 0 ||
- (error = gif_check_nesting(ifp, m)) != 0) {
+ (error = if_tunnel_check_nesting(ifp, m, MTAG_GIF,
+ V_max_gif_nesting)) != 0) {
m_freem(m);
goto err;
}
@@ -450,6 +375,7 @@ gif_transmit(struct ifnet *ifp, struct mbuf *m)
err:
if (error)
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ GIF_RUNLOCK();
return (error);
}
@@ -459,42 +385,6 @@ gif_qflush(struct ifnet *ifp __unused)
}
-#define MTAG_GIF 1080679712
-static int
-gif_check_nesting(struct ifnet *ifp, struct mbuf *m)
-{
- struct m_tag *mtag;
- int count;
-
- /*
- * gif may cause infinite recursion calls when misconfigured.
- * We'll prevent this by detecting loops.
- *
- * High nesting level may cause stack exhaustion.
- * We'll prevent this by introducing upper limit.
- */
- count = 1;
- mtag = NULL;
- while ((mtag = m_tag_locate(m, MTAG_GIF, 0, mtag)) != NULL) {
- if (*(struct ifnet **)(mtag + 1) == ifp) {
- log(LOG_NOTICE, "%s: loop detected\n", if_name(ifp));
- return (EIO);
- }
- count++;
- }
- if (count > V_max_gif_nesting) {
- log(LOG_NOTICE,
- "%s: if_output recursively called too many times(%d)\n",
- if_name(ifp), count);
- return (EIO);
- }
- mtag = m_tag_alloc(MTAG_GIF, 0, sizeof(struct ifnet *), M_NOWAIT);
- if (mtag == NULL)
- return (ENOMEM);
- *(struct ifnet **)(mtag + 1) = ifp;
- m_tag_prepend(m, mtag);
- return (0);
-}
int
gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
@@ -622,7 +512,8 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn)
break;
#endif
case AF_LINK:
- n = sizeof(struct etherip_header) + sizeof(struct ether_header);
+ n = sizeof(struct etherip_header) +
+ sizeof(struct ether_header);
if (n > m->m_len)
m = m_pullup(m, n);
if (m == NULL)
@@ -680,20 +571,11 @@ drop:
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
}
-/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
-int
+static int
gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- GIF_RLOCK_TRACKER;
struct ifreq *ifr = (struct ifreq*)data;
- struct sockaddr *dst, *src;
struct gif_softc *sc;
-#ifdef INET
- struct sockaddr_in *sin = NULL;
-#endif
-#ifdef INET6
- struct sockaddr_in6 *sin6 = NULL;
-#endif
u_int options;
int error;
@@ -721,176 +603,25 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
error = 0;
switch (cmd) {
- case SIOCSIFPHYADDR:
-#ifdef INET6
- case SIOCSIFPHYADDR_IN6:
-#endif
- error = EINVAL;
- switch (cmd) {
-#ifdef INET
- case SIOCSIFPHYADDR:
- src = (struct sockaddr *)
- &(((struct in_aliasreq *)data)->ifra_addr);
- dst = (struct sockaddr *)
- &(((struct in_aliasreq *)data)->ifra_dstaddr);
- break;
-#endif
-#ifdef INET6
- case SIOCSIFPHYADDR_IN6:
- src = (struct sockaddr *)
- &(((struct in6_aliasreq *)data)->ifra_addr);
- dst = (struct sockaddr *)
- &(((struct in6_aliasreq *)data)->ifra_dstaddr);
- break;
-#endif
- default:
- goto bad;
- }
- /* sa_family must be equal */
- if (src->sa_family != dst->sa_family ||
- src->sa_len != dst->sa_len)
- goto bad;
-
- /* validate sa_len */
- /* check sa_family looks sane for the cmd */
- switch (src->sa_family) {
-#ifdef INET
- case AF_INET:
- if (src->sa_len != sizeof(struct sockaddr_in))
- goto bad;
- if (cmd != SIOCSIFPHYADDR) {
- error = EAFNOSUPPORT;
- goto bad;
- }
- if (satosin(src)->sin_addr.s_addr == INADDR_ANY ||
- satosin(dst)->sin_addr.s_addr == INADDR_ANY) {
- error = EADDRNOTAVAIL;
- goto bad;
- }
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (src->sa_len != sizeof(struct sockaddr_in6))
- goto bad;
- if (cmd != SIOCSIFPHYADDR_IN6) {
- error = EAFNOSUPPORT;
- goto bad;
- }
- error = EADDRNOTAVAIL;
- if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)
- ||
- IN6_IS_ADDR_UNSPECIFIED(&satosin6(dst)->sin6_addr))
- goto bad;
- /*
- * Check validity of the scope zone ID of the
- * addresses, and convert it into the kernel
- * internal form if necessary.
- */
- error = sa6_embedscope(satosin6(src), 0);
- if (error != 0)
- goto bad;
- error = sa6_embedscope(satosin6(dst), 0);
- if (error != 0)
- goto bad;
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- goto bad;
- }
- error = gif_set_tunnel(ifp, src, dst);
- break;
case SIOCDIFPHYADDR:
- gif_delete_tunnel(ifp);
+ if (sc->gif_family == 0)
+ break;
+ gif_delete_tunnel(sc);
break;
+#ifdef INET
+ case SIOCSIFPHYADDR:
case SIOCGIFPSRCADDR:
case SIOCGIFPDSTADDR:
+ error = in_gif_ioctl(sc, cmd, data);
+ break;
+#endif
#ifdef INET6
+ case SIOCSIFPHYADDR_IN6:
case SIOCGIFPSRCADDR_IN6:
case SIOCGIFPDSTADDR_IN6:
-#endif
- if (sc->gif_family == 0) {
- error = EADDRNOTAVAIL;
- break;
- }
- GIF_RLOCK(sc);
- switch (cmd) {
-#ifdef INET
- case SIOCGIFPSRCADDR:
- case SIOCGIFPDSTADDR:
- if (sc->gif_family != AF_INET) {
- error = EADDRNOTAVAIL;
- break;
- }
- sin = (struct sockaddr_in *)&ifr->ifr_addr;
- memset(sin, 0, sizeof(*sin));
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- break;
-#endif
-#ifdef INET6
- case SIOCGIFPSRCADDR_IN6:
- case SIOCGIFPDSTADDR_IN6:
- if (sc->gif_family != AF_INET6) {
- error = EADDRNOTAVAIL;
- break;
- }
- sin6 = (struct sockaddr_in6 *)
- &(((struct in6_ifreq *)data)->ifr_addr);
- memset(sin6, 0, sizeof(*sin6));
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(*sin6);
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- }
- if (error == 0) {
- switch (cmd) {
-#ifdef INET
- case SIOCGIFPSRCADDR:
- sin->sin_addr = sc->gif_iphdr->ip_src;
- break;
- case SIOCGIFPDSTADDR:
- sin->sin_addr = sc->gif_iphdr->ip_dst;
- break;
-#endif
-#ifdef INET6
- case SIOCGIFPSRCADDR_IN6:
- sin6->sin6_addr = sc->gif_ip6hdr->ip6_src;
- break;
- case SIOCGIFPDSTADDR_IN6:
- sin6->sin6_addr = sc->gif_ip6hdr->ip6_dst;
- break;
-#endif
- }
- }
- GIF_RUNLOCK(sc);
- if (error != 0)
- break;
- switch (cmd) {
-#ifdef INET
- case SIOCGIFPSRCADDR:
- case SIOCGIFPDSTADDR:
- error = prison_if(curthread->td_ucred,
- (struct sockaddr *)sin);
- if (error != 0)
- memset(sin, 0, sizeof(*sin));
- break;
-#endif
-#ifdef INET6
- case SIOCGIFPSRCADDR_IN6:
- case SIOCGIFPDSTADDR_IN6:
- error = prison_if(curthread->td_ucred,
- (struct sockaddr *)sin6);
- if (error == 0)
- error = sa6_recoverscope(sin6);
- if (error != 0)
- memset(sin6, 0, sizeof(*sin6));
-#endif
- }
+ error = in6_gif_ioctl(sc, cmd, data);
break;
+#endif
case SIOCGTUNFIB:
ifr->ifr_fib = sc->gif_fibnum;
break;
@@ -914,159 +645,63 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
sizeof(options));
if (error)
break;
- if (options & ~GIF_OPTMASK)
+ if (options & ~GIF_OPTMASK) {
error = EINVAL;
- else
- sc->gif_options = options;
- break;
- default:
- error = EINVAL;
- break;
- }
-bad:
- sx_xunlock(&gif_ioctl_sx);
- return (error);
-}
-
-static void
-gif_detach(struct gif_softc *sc)
-{
-
- sx_assert(&gif_ioctl_sx, SA_XLOCKED);
- if (sc->gif_ecookie != NULL)
- encap_detach(sc->gif_ecookie);
- sc->gif_ecookie = NULL;
-}
-
-static int
-gif_attach(struct gif_softc *sc, int af)
-{
-
- sx_assert(&gif_ioctl_sx, SA_XLOCKED);
- switch (af) {
-#ifdef INET
- case AF_INET:
- return (in_gif_attach(sc));
-#endif
-#ifdef INET6
- case AF_INET6:
- return (in6_gif_attach(sc));
-#endif
- }
- return (EAFNOSUPPORT);
-}
-
-static int
-gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
-{
- struct gif_softc *sc = ifp->if_softc;
- struct gif_softc *tsc;
+ break;
+ }
+ if (sc->gif_options != options) {
+ switch (sc->gif_family) {
#ifdef INET
- struct ip *ip;
+ case AF_INET:
+ error = in_gif_setopts(sc, options);
+ break;
#endif
#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
- void *hdr;
- int error = 0;
-
- if (sc == NULL)
- return (ENXIO);
- /* Disallow parallel tunnels unless instructed otherwise. */
- if (V_parallel_tunnels == 0) {
- GIF_LIST_LOCK();
- LIST_FOREACH(tsc, &V_gif_softc_list, gif_list) {
- if (tsc == sc || tsc->gif_family != src->sa_family)
- continue;
-#ifdef INET
- if (tsc->gif_family == AF_INET &&
- tsc->gif_iphdr->ip_src.s_addr ==
- satosin(src)->sin_addr.s_addr &&
- tsc->gif_iphdr->ip_dst.s_addr ==
- satosin(dst)->sin_addr.s_addr) {
- error = EADDRNOTAVAIL;
- GIF_LIST_UNLOCK();
- goto bad;
- }
+ case AF_INET6:
+ error = in6_gif_setopts(sc, options);
+ break;
#endif
-#ifdef INET6
- if (tsc->gif_family == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(&tsc->gif_ip6hdr->ip6_src,
- &satosin6(src)->sin6_addr) &&
- IN6_ARE_ADDR_EQUAL(&tsc->gif_ip6hdr->ip6_dst,
- &satosin6(dst)->sin6_addr)) {
- error = EADDRNOTAVAIL;
- GIF_LIST_UNLOCK();
- goto bad;
+ default:
+ /* No need to invoke AF-handler */
+ sc->gif_options = options;
}
-#endif
}
- GIF_LIST_UNLOCK();
+ break;
+ default:
+ error = EINVAL;
+ break;
}
- switch (src->sa_family) {
+ if (error == 0 && sc->gif_family != 0) {
+ if (
#ifdef INET
- case AF_INET:
- hdr = ip = malloc(sizeof(struct ip), M_GIF,
- M_WAITOK | M_ZERO);
- ip->ip_src.s_addr = satosin(src)->sin_addr.s_addr;
- ip->ip_dst.s_addr = satosin(dst)->sin_addr.s_addr;
- break;
+ cmd == SIOCSIFPHYADDR ||
#endif
#ifdef INET6
- case AF_INET6:
- hdr = ip6 = malloc(sizeof(struct ip6_hdr), M_GIF,
- M_WAITOK | M_ZERO);
- ip6->ip6_src = satosin6(src)->sin6_addr;
- ip6->ip6_dst = satosin6(dst)->sin6_addr;
- ip6->ip6_vfc = IPV6_VERSION;
- break;
+ cmd == SIOCSIFPHYADDR_IN6 ||
#endif
- default:
- return (EAFNOSUPPORT);
+ 0) {
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
}
-
- if (sc->gif_family != src->sa_family)
- gif_detach(sc);
- if (sc->gif_family == 0 ||
- sc->gif_family != src->sa_family)
- error = gif_attach(sc, src->sa_family);
-
- GIF_WLOCK(sc);
- if (sc->gif_family != 0)
- free(sc->gif_hdr, M_GIF);
- sc->gif_family = src->sa_family;
- sc->gif_hdr = hdr;
- GIF_WUNLOCK(sc);
-#if defined(INET) || defined(INET6)
bad:
-#endif
- if (error == 0 && sc->gif_family != 0) {
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- if_link_state_change(ifp, LINK_STATE_UP);
- } else {
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- if_link_state_change(ifp, LINK_STATE_DOWN);
- }
+ sx_xunlock(&gif_ioctl_sx);
return (error);
}
static void
-gif_delete_tunnel(struct ifnet *ifp)
+gif_delete_tunnel(struct gif_softc *sc)
{
- struct gif_softc *sc = ifp->if_softc;
- int family;
- if (sc == NULL)
- return;
-
- GIF_WLOCK(sc);
- family = sc->gif_family;
- sc->gif_family = 0;
- GIF_WUNLOCK(sc);
- if (family != 0) {
- gif_detach(sc);
+ sx_assert(&gif_ioctl_sx, SA_XLOCKED);
+ if (sc->gif_family != 0) {
+ CK_LIST_REMOVE(sc, chain);
+ /* Wait until it become safe to free gif_hdr */
+ GIF_WAIT();
free(sc->gif_hdr, M_GIF);
}
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- if_link_state_change(ifp, LINK_STATE_DOWN);
+ sc->gif_family = 0;
+ GIF2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if_link_state_change(GIF2IFP(sc), LINK_STATE_DOWN);
}
+
diff --git a/freebsd/sys/net/if_gif.h b/freebsd/sys/net/if_gif.h
index 556c2acc..501a4e5d 100644
--- a/freebsd/sys/net/if_gif.h
+++ b/freebsd/sys/net/if_gif.h
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,14 +37,9 @@
#define _NET_IF_GIF_H_
#ifdef _KERNEL
-#include <rtems/bsd/local/opt_inet.h>
-#include <rtems/bsd/local/opt_inet6.h>
-
-#include <netinet/in.h>
struct ip;
struct ip6_hdr;
-struct encaptab;
extern void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp,
int af);
@@ -55,8 +51,6 @@ extern void (*ng_gif_detach_p)(struct ifnet *ifp);
struct gif_softc {
struct ifnet *gif_ifp;
- struct rmlock gif_lock;
- const struct encaptab *gif_ecookie;
int gif_family;
int gif_flags;
u_int gif_fibnum;
@@ -65,28 +59,22 @@ struct gif_softc {
union {
void *hdr;
struct ip *iphdr;
-#ifdef INET6
struct ip6_hdr *ip6hdr;
-#endif
} gif_uhdr;
- LIST_ENTRY(gif_softc) gif_list; /* all gif's are linked */
+
+ CK_LIST_ENTRY(gif_softc) chain;
};
-#define GIF2IFP(sc) ((sc)->gif_ifp)
-#define GIF_LOCK_INIT(sc) rm_init(&(sc)->gif_lock, "gif softc")
-#define GIF_LOCK_DESTROY(sc) rm_destroy(&(sc)->gif_lock)
-#define GIF_RLOCK_TRACKER struct rm_priotracker gif_tracker
-#define GIF_RLOCK(sc) rm_rlock(&(sc)->gif_lock, &gif_tracker)
-#define GIF_RUNLOCK(sc) rm_runlock(&(sc)->gif_lock, &gif_tracker)
-#define GIF_RLOCK_ASSERT(sc) rm_assert(&(sc)->gif_lock, RA_RLOCKED)
-#define GIF_WLOCK(sc) rm_wlock(&(sc)->gif_lock)
-#define GIF_WUNLOCK(sc) rm_wunlock(&(sc)->gif_lock)
-#define GIF_WLOCK_ASSERT(sc) rm_assert(&(sc)->gif_lock, RA_WLOCKED)
+CK_LIST_HEAD(gif_list, gif_softc);
+MALLOC_DECLARE(M_GIF);
+#ifndef GIF_HASH_SIZE
+#define GIF_HASH_SIZE (1 << 4)
+#endif
+
+#define GIF2IFP(sc) ((sc)->gif_ifp)
#define gif_iphdr gif_uhdr.iphdr
#define gif_hdr gif_uhdr.hdr
-#ifdef INET6
#define gif_ip6hdr gif_uhdr.ip6hdr
-#endif
#define GIF_MTU (1280) /* Default MTU */
#define GIF_MTU_MIN (1280) /* Minimum MTU */
@@ -108,21 +96,29 @@ struct etherip_header {
/* mbuf adjust factor to force 32-bit alignment of IP header */
#define ETHERIP_ALIGN 2
+#define GIF_RLOCK() struct epoch_tracker gif_et; epoch_enter_preempt(net_epoch_preempt, &gif_et)
+#define GIF_RUNLOCK() epoch_exit_preempt(net_epoch_preempt, &gif_et)
+#define GIF_WAIT() epoch_wait_preempt(net_epoch_preempt)
+
/* Prototypes */
+struct gif_list *gif_hashinit(void);
+void gif_hashdestroy(struct gif_list *);
+
void gif_input(struct mbuf *, struct ifnet *, int, uint8_t);
int gif_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
struct route *);
-int gif_encapcheck(const struct mbuf *, int, int, void *);
-#ifdef INET
+
+void in_gif_init(void);
+void in_gif_uninit(void);
int in_gif_output(struct ifnet *, struct mbuf *, int, uint8_t);
-int in_gif_encapcheck(const struct mbuf *, int, int, void *);
-int in_gif_attach(struct gif_softc *);
-#endif
-#ifdef INET6
+int in_gif_ioctl(struct gif_softc *, u_long, caddr_t);
+int in_gif_setopts(struct gif_softc *, u_int);
+
+void in6_gif_init(void);
+void in6_gif_uninit(void);
int in6_gif_output(struct ifnet *, struct mbuf *, int, uint8_t);
-int in6_gif_encapcheck(const struct mbuf *, int, int, void *);
-int in6_gif_attach(struct gif_softc *);
-#endif
+int in6_gif_ioctl(struct gif_softc *, u_long, caddr_t);
+int in6_gif_setopts(struct gif_softc *, u_int);
#endif /* _KERNEL */
#define GIFGOPTS _IOWR('i', 150, struct ifreq)
diff --git a/freebsd/sys/net/if_gre.c b/freebsd/sys/net/if_gre.c
index 0bff9bc9..5ff41259 100644
--- a/freebsd/sys/net/if_gre.c
+++ b/freebsd/sys/net/if_gre.c
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
- * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org>
+ * Copyright (c) 2014, 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -43,17 +43,13 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_inet6.h>
#include <sys/param.h>
-#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
-#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mbuf.h>
#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/protosw.h>
-#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sx.h>
@@ -72,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#ifdef INET
-#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
@@ -82,7 +77,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip6.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6_var.h>
-#include <netinet6/scope6_var.h>
#endif
#include <netinet/ip_encap.h>
@@ -93,24 +87,16 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
#define GREMTU 1476
+
static const char grename[] = "gre";
-static MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation");
-static VNET_DEFINE(struct mtx, gre_mtx);
-#define V_gre_mtx VNET(gre_mtx)
-#define GRE_LIST_LOCK_INIT(x) mtx_init(&V_gre_mtx, "gre_mtx", NULL, \
- MTX_DEF)
-#define GRE_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gre_mtx)
-#define GRE_LIST_LOCK(x) mtx_lock(&V_gre_mtx)
-#define GRE_LIST_UNLOCK(x) mtx_unlock(&V_gre_mtx)
-
-static VNET_DEFINE(LIST_HEAD(, gre_softc), gre_softc_list);
-#define V_gre_softc_list VNET(gre_softc_list)
+MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation");
+
static struct sx gre_ioctl_sx;
SX_SYSINIT(gre_ioctl_sx, &gre_ioctl_sx, "gre_ioctl");
static int gre_clone_create(struct if_clone *, int, caddr_t);
static void gre_clone_destroy(struct ifnet *);
-static VNET_DEFINE(struct if_clone *, gre_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, gre_cloner);
#define V_gre_cloner VNET(gre_cloner)
static void gre_qflush(struct ifnet *);
@@ -118,11 +104,7 @@ static int gre_transmit(struct ifnet *, struct mbuf *);
static int gre_ioctl(struct ifnet *, u_long, caddr_t);
static int gre_output(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
-
-static void gre_updatehdr(struct gre_softc *);
-static int gre_set_tunnel(struct ifnet *, struct sockaddr *,
- struct sockaddr *);
-static void gre_delete_tunnel(struct ifnet *);
+static void gre_delete_tunnel(struct gre_softc *);
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
@@ -139,7 +121,7 @@ static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
#define MAX_GRE_NEST 1
#endif
-static VNET_DEFINE(int, max_gre_nesting) = MAX_GRE_NEST;
+VNET_DEFINE_STATIC(int, max_gre_nesting) = MAX_GRE_NEST;
#define V_max_gre_nesting VNET(max_gre_nesting)
SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
&VNET_NAME(max_gre_nesting), 0, "Max nested tunnels");
@@ -147,10 +129,15 @@ SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
static void
vnet_gre_init(const void *unused __unused)
{
- LIST_INIT(&V_gre_softc_list);
- GRE_LIST_LOCK_INIT();
+
V_gre_cloner = if_clone_simple(grename, gre_clone_create,
gre_clone_destroy, 0);
+#ifdef INET
+ in_gre_init();
+#endif
+#ifdef INET6
+ in6_gre_init();
+#endif
}
VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_gre_init, NULL);
@@ -160,7 +147,12 @@ vnet_gre_uninit(const void *unused __unused)
{
if_clone_detach(V_gre_cloner);
- GRE_LIST_LOCK_DESTROY();
+#ifdef INET
+ in_gre_uninit();
+#endif
+#ifdef INET6
+ in6_gre_uninit();
+#endif
}
VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_gre_uninit, NULL);
@@ -177,7 +169,6 @@ gre_clone_create(struct if_clone *ifc, int unit, caddr_t params)
sc->gre_fibnum = BSD_DEFAULT_FIB;
#endif /* __rtems__ */
GRE2IFP(sc) = if_alloc(IFT_TUNNEL);
- GRE_LOCK_INIT(sc);
GRE2IFP(sc)->if_softc = sc;
if_initname(GRE2IFP(sc), grename, unit);
@@ -191,9 +182,6 @@ gre_clone_create(struct if_clone *ifc, int unit, caddr_t params)
GRE2IFP(sc)->if_capenable |= IFCAP_LINKSTATE;
if_attach(GRE2IFP(sc));
bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
- GRE_LIST_LOCK();
- LIST_INSERT_HEAD(&V_gre_softc_list, sc, gre_list);
- GRE_LIST_UNLOCK();
return (0);
}
@@ -204,33 +192,22 @@ gre_clone_destroy(struct ifnet *ifp)
sx_xlock(&gre_ioctl_sx);
sc = ifp->if_softc;
- gre_delete_tunnel(ifp);
- GRE_LIST_LOCK();
- LIST_REMOVE(sc, gre_list);
- GRE_LIST_UNLOCK();
+ gre_delete_tunnel(sc);
bpfdetach(ifp);
if_detach(ifp);
ifp->if_softc = NULL;
sx_xunlock(&gre_ioctl_sx);
+ GRE_WAIT();
if_free(ifp);
- GRE_LOCK_DESTROY(sc);
free(sc, M_GRE);
}
static int
gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- GRE_RLOCK_TRACKER;
struct ifreq *ifr = (struct ifreq *)data;
- struct sockaddr *src, *dst;
struct gre_softc *sc;
-#ifdef INET
- struct sockaddr_in *sin = NULL;
-#endif
-#ifdef INET6
- struct sockaddr_in6 *sin6 = NULL;
-#endif
uint32_t opt;
int error;
@@ -255,7 +232,6 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case GREGPROTO:
return (EOPNOTSUPP);
}
- src = dst = NULL;
sx_xlock(&gre_ioctl_sx);
sc = ifp->if_softc;
if (sc == NULL) {
@@ -264,189 +240,25 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
error = 0;
switch (cmd) {
- case SIOCSIFPHYADDR:
-#ifdef INET6
- case SIOCSIFPHYADDR_IN6:
-#endif
- error = EINVAL;
- switch (cmd) {
-#ifdef INET
- case SIOCSIFPHYADDR:
- src = (struct sockaddr *)
- &(((struct in_aliasreq *)data)->ifra_addr);
- dst = (struct sockaddr *)
- &(((struct in_aliasreq *)data)->ifra_dstaddr);
- break;
-#endif
-#ifdef INET6
- case SIOCSIFPHYADDR_IN6:
- src = (struct sockaddr *)
- &(((struct in6_aliasreq *)data)->ifra_addr);
- dst = (struct sockaddr *)
- &(((struct in6_aliasreq *)data)->ifra_dstaddr);
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- goto end;
- }
- /* sa_family must be equal */
- if (src->sa_family != dst->sa_family ||
- src->sa_len != dst->sa_len)
- goto end;
-
- /* validate sa_len */
- switch (src->sa_family) {
-#ifdef INET
- case AF_INET:
- if (src->sa_len != sizeof(struct sockaddr_in))
- goto end;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (src->sa_len != sizeof(struct sockaddr_in6))
- goto end;
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- goto end;
- }
- /* check sa_family looks sane for the cmd */
- error = EAFNOSUPPORT;
- switch (cmd) {
-#ifdef INET
- case SIOCSIFPHYADDR:
- if (src->sa_family == AF_INET)
- break;
- goto end;
-#endif
-#ifdef INET6
- case SIOCSIFPHYADDR_IN6:
- if (src->sa_family == AF_INET6)
- break;
- goto end;
-#endif
- }
- error = EADDRNOTAVAIL;
- switch (src->sa_family) {
-#ifdef INET
- case AF_INET:
- if (satosin(src)->sin_addr.s_addr == INADDR_ANY ||
- satosin(dst)->sin_addr.s_addr == INADDR_ANY)
- goto end;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)
- ||
- IN6_IS_ADDR_UNSPECIFIED(&satosin6(dst)->sin6_addr))
- goto end;
- /*
- * Check validity of the scope zone ID of the
- * addresses, and convert it into the kernel
- * internal form if necessary.
- */
- error = sa6_embedscope(satosin6(src), 0);
- if (error != 0)
- goto end;
- error = sa6_embedscope(satosin6(dst), 0);
- if (error != 0)
- goto end;
-#endif
- }
- error = gre_set_tunnel(ifp, src, dst);
- break;
case SIOCDIFPHYADDR:
- gre_delete_tunnel(ifp);
+ if (sc->gre_family == 0)
+ break;
+ gre_delete_tunnel(sc);
break;
+#ifdef INET
+ case SIOCSIFPHYADDR:
case SIOCGIFPSRCADDR:
case SIOCGIFPDSTADDR:
+ error = in_gre_ioctl(sc, cmd, data);
+ break;
+#endif
#ifdef INET6
+ case SIOCSIFPHYADDR_IN6:
case SIOCGIFPSRCADDR_IN6:
case SIOCGIFPDSTADDR_IN6:
-#endif
- if (sc->gre_family == 0) {
- error = EADDRNOTAVAIL;
- break;
- }
- GRE_RLOCK(sc);
- switch (cmd) {
-#ifdef INET
- case SIOCGIFPSRCADDR:
- case SIOCGIFPDSTADDR:
- if (sc->gre_family != AF_INET) {
- error = EADDRNOTAVAIL;
- break;
- }
- sin = (struct sockaddr_in *)&ifr->ifr_addr;
- memset(sin, 0, sizeof(*sin));
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- break;
-#endif
-#ifdef INET6
- case SIOCGIFPSRCADDR_IN6:
- case SIOCGIFPDSTADDR_IN6:
- if (sc->gre_family != AF_INET6) {
- error = EADDRNOTAVAIL;
- break;
- }
- sin6 = (struct sockaddr_in6 *)
- &(((struct in6_ifreq *)data)->ifr_addr);
- memset(sin6, 0, sizeof(*sin6));
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(*sin6);
- break;
-#endif
- }
- if (error == 0) {
- switch (cmd) {
-#ifdef INET
- case SIOCGIFPSRCADDR:
- sin->sin_addr = sc->gre_oip.ip_src;
- break;
- case SIOCGIFPDSTADDR:
- sin->sin_addr = sc->gre_oip.ip_dst;
- break;
-#endif
-#ifdef INET6
- case SIOCGIFPSRCADDR_IN6:
- sin6->sin6_addr = sc->gre_oip6.ip6_src;
- break;
- case SIOCGIFPDSTADDR_IN6:
- sin6->sin6_addr = sc->gre_oip6.ip6_dst;
- break;
-#endif
- }
- }
- GRE_RUNLOCK(sc);
- if (error != 0)
- break;
- switch (cmd) {
-#ifdef INET
- case SIOCGIFPSRCADDR:
- case SIOCGIFPDSTADDR:
- error = prison_if(curthread->td_ucred,
- (struct sockaddr *)sin);
- if (error != 0)
- memset(sin, 0, sizeof(*sin));
- break;
-#endif
-#ifdef INET6
- case SIOCGIFPSRCADDR_IN6:
- case SIOCGIFPDSTADDR_IN6:
- error = prison_if(curthread->td_ucred,
- (struct sockaddr *)sin6);
- if (error == 0)
- error = sa6_recoverscope(sin6);
- if (error != 0)
- memset(sin6, 0, sizeof(*sin6));
-#endif
- }
+ error = in6_gre_ioctl(sc, cmd, data);
break;
+#endif
case SIOCGTUNFIB:
ifr->ifr_fib = sc->gre_fibnum;
break;
@@ -459,40 +271,50 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
sc->gre_fibnum = ifr->ifr_fib;
break;
case GRESKEY:
+ case GRESOPTS:
if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
break;
if ((error = copyin(ifr_data_get_ptr(ifr), &opt,
sizeof(opt))) != 0)
break;
- if (sc->gre_key != opt) {
- GRE_WLOCK(sc);
- sc->gre_key = opt;
- gre_updatehdr(sc);
- GRE_WUNLOCK(sc);
+ if (cmd == GRESKEY) {
+ if (sc->gre_key == opt)
+ break;
+ } else if (cmd == GRESOPTS) {
+ if (opt & ~GRE_OPTMASK) {
+ error = EINVAL;
+ break;
+ }
+ if (sc->gre_options == opt)
+ break;
}
- break;
- case GREGKEY:
- error = copyout(&sc->gre_key, ifr_data_get_ptr(ifr),
- sizeof(sc->gre_key));
- break;
- case GRESOPTS:
- if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
+ switch (sc->gre_family) {
+#ifdef INET
+ case AF_INET:
+ in_gre_setopts(sc, cmd, opt);
break;
- if ((error = copyin(ifr_data_get_ptr(ifr), &opt,
- sizeof(opt))) != 0)
+#endif
+#ifdef INET6
+ case AF_INET6:
+ in6_gre_setopts(sc, cmd, opt);
break;
- if (opt & ~GRE_OPTMASK)
- error = EINVAL;
- else {
- if (sc->gre_options != opt) {
- GRE_WLOCK(sc);
+#endif
+ default:
+ if (cmd == GRESKEY)
+ sc->gre_key = opt;
+ else
sc->gre_options = opt;
- gre_updatehdr(sc);
- GRE_WUNLOCK(sc);
- }
+ break;
}
+ /*
+ * XXX: Do we need to initiate change of interface
+ * state here?
+ */
+ break;
+ case GREGKEY:
+ error = copyout(&sc->gre_key, ifr_data_get_ptr(ifr),
+ sizeof(sc->gre_key));
break;
-
case GREGOPTS:
error = copyout(&sc->gre_options, ifr_data_get_ptr(ifr),
sizeof(sc->gre_options));
@@ -501,40 +323,68 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = EINVAL;
break;
}
+ if (error == 0 && sc->gre_family != 0) {
+ if (
+#ifdef INET
+ cmd == SIOCSIFPHYADDR ||
+#endif
+#ifdef INET6
+ cmd == SIOCSIFPHYADDR_IN6 ||
+#endif
+ 0) {
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
+ }
end:
sx_xunlock(&gre_ioctl_sx);
return (error);
}
static void
-gre_updatehdr(struct gre_softc *sc)
+gre_delete_tunnel(struct gre_softc *sc)
+{
+
+ sx_assert(&gre_ioctl_sx, SA_XLOCKED);
+ if (sc->gre_family != 0) {
+ CK_LIST_REMOVE(sc, chain);
+ GRE_WAIT();
+ free(sc->gre_hdr, M_GRE);
+ sc->gre_family = 0;
+ }
+ GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if_link_state_change(GRE2IFP(sc), LINK_STATE_DOWN);
+}
+
+struct gre_list *
+gre_hashinit(void)
+{
+ struct gre_list *hash;
+ int i;
+
+ hash = malloc(sizeof(struct gre_list) * GRE_HASH_SIZE,
+ M_GRE, M_WAITOK);
+ for (i = 0; i < GRE_HASH_SIZE; i++)
+ CK_LIST_INIT(&hash[i]);
+
+ return (hash);
+}
+
+void
+gre_hashdestroy(struct gre_list *hash)
+{
+
+ free(hash, M_GRE);
+}
+
+void
+gre_updatehdr(struct gre_softc *sc, struct grehdr *gh)
{
- struct grehdr *gh = NULL;
uint32_t *opts;
uint16_t flags;
- GRE_WLOCK_ASSERT(sc);
- switch (sc->gre_family) {
-#ifdef INET
- case AF_INET:
- sc->gre_hlen = sizeof(struct greip);
- sc->gre_oip.ip_v = IPPROTO_IPV4;
- sc->gre_oip.ip_hl = sizeof(struct ip) >> 2;
- sc->gre_oip.ip_p = IPPROTO_GRE;
- gh = &sc->gre_gihdr->gi_gre;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- sc->gre_hlen = sizeof(struct greip6);
- sc->gre_oip6.ip6_vfc = IPV6_VERSION;
- sc->gre_oip6.ip6_nxt = IPPROTO_GRE;
- gh = &sc->gre_gi6hdr->gi6_gre;
- break;
-#endif
- default:
- return;
- }
+ sx_assert(&gre_ioctl_sx, SA_XLOCKED);
+
flags = 0;
opts = gh->gre_opts;
if (sc->gre_options & GRE_ENABLE_CSUM) {
@@ -556,136 +406,12 @@ gre_updatehdr(struct gre_softc *sc)
gh->gre_flags = htons(flags);
}
-static void
-gre_detach(struct gre_softc *sc)
-{
-
- sx_assert(&gre_ioctl_sx, SA_XLOCKED);
- if (sc->gre_ecookie != NULL)
- encap_detach(sc->gre_ecookie);
- sc->gre_ecookie = NULL;
-}
-
-static int
-gre_set_tunnel(struct ifnet *ifp, struct sockaddr *src,
- struct sockaddr *dst)
-{
- struct gre_softc *sc, *tsc;
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
-#ifdef INET
- struct ip *ip;
-#endif
- void *hdr;
- int error;
-
- sx_assert(&gre_ioctl_sx, SA_XLOCKED);
- GRE_LIST_LOCK();
- sc = ifp->if_softc;
- LIST_FOREACH(tsc, &V_gre_softc_list, gre_list) {
- if (tsc == sc || tsc->gre_family != src->sa_family)
- continue;
-#ifdef INET
- if (tsc->gre_family == AF_INET &&
- tsc->gre_oip.ip_src.s_addr ==
- satosin(src)->sin_addr.s_addr &&
- tsc->gre_oip.ip_dst.s_addr ==
- satosin(dst)->sin_addr.s_addr) {
- GRE_LIST_UNLOCK();
- return (EADDRNOTAVAIL);
- }
-#endif
-#ifdef INET6
- if (tsc->gre_family == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(&tsc->gre_oip6.ip6_src,
- &satosin6(src)->sin6_addr) &&
- IN6_ARE_ADDR_EQUAL(&tsc->gre_oip6.ip6_dst,
- &satosin6(dst)->sin6_addr)) {
- GRE_LIST_UNLOCK();
- return (EADDRNOTAVAIL);
- }
-#endif
- }
- GRE_LIST_UNLOCK();
-
- switch (src->sa_family) {
-#ifdef INET
- case AF_INET:
- hdr = ip = malloc(sizeof(struct greip) +
- 3 * sizeof(uint32_t), M_GRE, M_WAITOK | M_ZERO);
- ip->ip_src = satosin(src)->sin_addr;
- ip->ip_dst = satosin(dst)->sin_addr;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- hdr = ip6 = malloc(sizeof(struct greip6) +
- 3 * sizeof(uint32_t), M_GRE, M_WAITOK | M_ZERO);
- ip6->ip6_src = satosin6(src)->sin6_addr;
- ip6->ip6_dst = satosin6(dst)->sin6_addr;
- break;
-#endif
- default:
- return (EAFNOSUPPORT);
- }
- if (sc->gre_family != 0)
- gre_detach(sc);
- GRE_WLOCK(sc);
- if (sc->gre_family != 0)
- free(sc->gre_hdr, M_GRE);
- sc->gre_family = src->sa_family;
- sc->gre_hdr = hdr;
- sc->gre_oseq = 0;
- sc->gre_iseq = UINT32_MAX;
- gre_updatehdr(sc);
- GRE_WUNLOCK(sc);
-
- error = 0;
- switch (src->sa_family) {
-#ifdef INET
- case AF_INET:
- error = in_gre_attach(sc);
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- error = in6_gre_attach(sc);
- break;
-#endif
- }
- if (error == 0) {
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- if_link_state_change(ifp, LINK_STATE_UP);
- }
- return (error);
-}
-
-static void
-gre_delete_tunnel(struct ifnet *ifp)
-{
- struct gre_softc *sc = ifp->if_softc;
- int family;
-
- GRE_WLOCK(sc);
- family = sc->gre_family;
- sc->gre_family = 0;
- GRE_WUNLOCK(sc);
- if (family != 0) {
- gre_detach(sc);
- free(sc->gre_hdr, M_GRE);
- }
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- if_link_state_change(ifp, LINK_STATE_DOWN);
-}
-
int
-gre_input(struct mbuf **mp, int *offp, int proto)
+gre_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct gre_softc *sc;
+ struct gre_softc *sc = arg;
struct grehdr *gh;
struct ifnet *ifp;
- struct mbuf *m;
uint32_t *opts;
#ifdef notyet
uint32_t key;
@@ -693,12 +419,8 @@ gre_input(struct mbuf **mp, int *offp, int proto)
uint16_t flags;
int hlen, isr, af;
- m = *mp;
- sc = encap_getarg(m);
- KASSERT(sc != NULL, ("encap_getarg returned NULL"));
-
ifp = GRE2IFP(sc);
- hlen = *offp + sizeof(struct grehdr) + 4 * sizeof(uint32_t);
+ hlen = off + sizeof(struct grehdr) + 4 * sizeof(uint32_t);
if (m->m_pkthdr.len < hlen)
goto drop;
if (m->m_len < hlen) {
@@ -706,7 +428,7 @@ gre_input(struct mbuf **mp, int *offp, int proto)
if (m == NULL)
goto drop;
}
- gh = (struct grehdr *)mtodo(m, *offp);
+ gh = (struct grehdr *)mtodo(m, off);
flags = ntohs(gh->gre_flags);
if (flags & ~GRE_FLAGS_MASK)
goto drop;
@@ -716,7 +438,7 @@ gre_input(struct mbuf **mp, int *offp, int proto)
/* reserved1 field must be zero */
if (((uint16_t *)opts)[1] != 0)
goto drop;
- if (in_cksum_skip(m, m->m_pkthdr.len, *offp) != 0)
+ if (in_cksum_skip(m, m->m_pkthdr.len, off) != 0)
goto drop;
hlen += 2 * sizeof(uint16_t);
opts++;
@@ -766,7 +488,7 @@ gre_input(struct mbuf **mp, int *offp, int proto)
default:
goto drop;
}
- m_adj(m, *offp + hlen);
+ m_adj(m, off + hlen);
m_clrprotoflags(m);
m->m_pkthdr.rcvif = ifp;
M_SETFIB(m, ifp->if_fib);
@@ -787,70 +509,23 @@ drop:
return (IPPROTO_DONE);
}
-#define MTAG_GRE 1307983903
-static int
-gre_check_nesting(struct ifnet *ifp, struct mbuf *m)
-{
- struct m_tag *mtag;
- int count;
-
- count = 1;
- mtag = NULL;
- while ((mtag = m_tag_locate(m, MTAG_GRE, 0, mtag)) != NULL) {
- if (*(struct ifnet **)(mtag + 1) == ifp) {
- log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname);
- return (EIO);
- }
- count++;
- }
- if (count > V_max_gre_nesting) {
- log(LOG_NOTICE,
- "%s: if_output recursively called too many times(%d)\n",
- ifp->if_xname, count);
- return (EIO);
- }
- mtag = m_tag_alloc(MTAG_GRE, 0, sizeof(struct ifnet *), M_NOWAIT);
- if (mtag == NULL)
- return (ENOMEM);
- *(struct ifnet **)(mtag + 1) = ifp;
- m_tag_prepend(m, mtag);
- return (0);
-}
-
static int
gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
struct route *ro)
{
uint32_t af;
- int error;
-#ifdef MAC
- error = mac_ifnet_check_transmit(ifp, m);
- if (error != 0)
- goto drop;
-#endif
- if ((ifp->if_flags & IFF_MONITOR) != 0 ||
- (ifp->if_flags & IFF_UP) == 0) {
- error = ENETDOWN;
- goto drop;
- }
-
- error = gre_check_nesting(ifp, m);
- if (error != 0)
- goto drop;
-
- m->m_flags &= ~(M_BCAST|M_MCAST);
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
else
af = dst->sa_family;
- BPF_MTAP2(ifp, &af, sizeof(af), m);
- m->m_pkthdr.csum_data = af; /* save af for if_transmit */
+ /*
+ * Now save the af in the inbound pkt csum data, this is a cheat since
+ * we are using the inbound csum_data field to carry the af over to
+ * the gre_transmit() routine, avoiding using yet another mtag.
+ */
+ m->m_pkthdr.csum_data = af;
return (ifp->if_transmit(ifp, m));
-drop:
- m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return (error);
}
static void
@@ -870,95 +545,95 @@ gre_setseqn(struct grehdr *gh, uint32_t seq)
*opts = htonl(seq);
}
+#define MTAG_GRE 1307983903
static int
gre_transmit(struct ifnet *ifp, struct mbuf *m)
{
- GRE_RLOCK_TRACKER;
struct gre_softc *sc;
struct grehdr *gh;
- uint32_t iaf, oaf, oseq;
- int error, hlen, olen, plen;
- int want_seq, want_csum;
+ uint32_t af;
+ int error, len;
+ uint16_t proto;
- plen = 0;
- sc = ifp->if_softc;
- if (sc == NULL) {
- error = ENETDOWN;
+ len = 0;
+#ifdef MAC
+ error = mac_ifnet_check_transmit(ifp, m);
+ if (error) {
m_freem(m);
goto drop;
}
- GRE_RLOCK(sc);
- if (sc->gre_family == 0) {
- GRE_RUNLOCK(sc);
- error = ENETDOWN;
+#endif
+ error = ENETDOWN;
+ GRE_RLOCK();
+ sc = ifp->if_softc;
+ if ((ifp->if_flags & IFF_MONITOR) != 0 ||
+ (ifp->if_flags & IFF_UP) == 0 ||
+ sc->gre_family == 0 ||
+ (error = if_tunnel_check_nesting(ifp, m, MTAG_GRE,
+ V_max_gre_nesting)) != 0) {
m_freem(m);
goto drop;
}
- iaf = m->m_pkthdr.csum_data;
- oaf = sc->gre_family;
- hlen = sc->gre_hlen;
- want_seq = (sc->gre_options & GRE_ENABLE_SEQ) != 0;
- if (want_seq)
- oseq = sc->gre_oseq++; /* XXX */
- else
- oseq = 0; /* Make compiler happy. */
- want_csum = (sc->gre_options & GRE_ENABLE_CSUM) != 0;
+ af = m->m_pkthdr.csum_data;
M_SETFIB(m, sc->gre_fibnum);
- M_PREPEND(m, hlen, M_NOWAIT);
+ M_PREPEND(m, sc->gre_hlen, M_NOWAIT);
if (m == NULL) {
- GRE_RUNLOCK(sc);
error = ENOBUFS;
goto drop;
}
- bcopy(sc->gre_hdr, mtod(m, void *), hlen);
- GRE_RUNLOCK(sc);
- switch (oaf) {
+ bcopy(sc->gre_hdr, mtod(m, void *), sc->gre_hlen);
+ /* Determine GRE proto */
+ switch (af) {
#ifdef INET
case AF_INET:
- olen = sizeof(struct ip);
+ proto = htons(ETHERTYPE_IP);
break;
#endif
#ifdef INET6
case AF_INET6:
- olen = sizeof(struct ip6_hdr);
+ proto = htons(ETHERTYPE_IPV6);
break;
#endif
default:
+ m_freem(m);
error = ENETDOWN;
goto drop;
}
- gh = (struct grehdr *)mtodo(m, olen);
- switch (iaf) {
+ /* Determine offset of GRE header */
+ switch (sc->gre_family) {
#ifdef INET
case AF_INET:
- gh->gre_proto = htons(ETHERTYPE_IP);
+ len = sizeof(struct ip);
break;
#endif
#ifdef INET6
case AF_INET6:
- gh->gre_proto = htons(ETHERTYPE_IPV6);
+ len = sizeof(struct ip6_hdr);
break;
#endif
default:
+ m_freem(m);
error = ENETDOWN;
goto drop;
}
- if (want_seq)
- gre_setseqn(gh, oseq);
- if (want_csum) {
+ gh = (struct grehdr *)mtodo(m, len);
+ gh->gre_proto = proto;
+ if (sc->gre_options & GRE_ENABLE_SEQ)
+ gre_setseqn(gh, sc->gre_oseq++);
+ if (sc->gre_options & GRE_ENABLE_CSUM) {
*(uint16_t *)gh->gre_opts = in_cksum_skip(m,
- m->m_pkthdr.len, olen);
+ m->m_pkthdr.len, len);
}
- plen = m->m_pkthdr.len - hlen;
- switch (oaf) {
+ len = m->m_pkthdr.len - len;
+ switch (sc->gre_family) {
#ifdef INET
case AF_INET:
- error = in_gre_output(m, iaf, hlen);
+ error = in_gre_output(m, af, sc->gre_hlen);
break;
#endif
#ifdef INET6
case AF_INET6:
- error = in6_gre_output(m, iaf, hlen);
+ error = in6_gre_output(m, af, sc->gre_hlen);
break;
#endif
default:
@@ -970,8 +645,9 @@ drop:
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
else {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(ifp, IFCOUNTER_OBYTES, plen);
+ if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
}
+ GRE_RUNLOCK();
return (error);
}
diff --git a/freebsd/sys/net/if_gre.h b/freebsd/sys/net/if_gre.h
index 0eac9e9f..cc8b08f9 100644
--- a/freebsd/sys/net/if_gre.h
+++ b/freebsd/sys/net/if_gre.h
@@ -64,8 +64,6 @@ struct greip6 {
struct gre_softc {
struct ifnet *gre_ifp;
- LIST_ENTRY(gre_softc) gre_list;
- struct rmlock gre_lock;
int gre_family; /* AF of delivery header */
uint32_t gre_iseq;
uint32_t gre_oseq;
@@ -82,18 +80,20 @@ struct gre_softc {
struct greip6 *gi6hdr;
#endif
} gre_uhdr;
- const struct encaptab *gre_ecookie;
+
+ CK_LIST_ENTRY(gre_softc) chain;
};
+CK_LIST_HEAD(gre_list, gre_softc);
+MALLOC_DECLARE(M_GRE);
+
+#ifndef GRE_HASH_SIZE
+#define GRE_HASH_SIZE (1 << 4)
+#endif
+
#define GRE2IFP(sc) ((sc)->gre_ifp)
-#define GRE_LOCK_INIT(sc) rm_init(&(sc)->gre_lock, "gre softc")
-#define GRE_LOCK_DESTROY(sc) rm_destroy(&(sc)->gre_lock)
-#define GRE_RLOCK_TRACKER struct rm_priotracker gre_tracker
-#define GRE_RLOCK(sc) rm_rlock(&(sc)->gre_lock, &gre_tracker)
-#define GRE_RUNLOCK(sc) rm_runlock(&(sc)->gre_lock, &gre_tracker)
-#define GRE_RLOCK_ASSERT(sc) rm_assert(&(sc)->gre_lock, RA_RLOCKED)
-#define GRE_WLOCK(sc) rm_wlock(&(sc)->gre_lock)
-#define GRE_WUNLOCK(sc) rm_wunlock(&(sc)->gre_lock)
-#define GRE_WLOCK_ASSERT(sc) rm_assert(&(sc)->gre_lock, RA_WLOCKED)
+#define GRE_RLOCK() struct epoch_tracker gre_et; epoch_enter_preempt(net_epoch_preempt, &gre_et)
+#define GRE_RUNLOCK() epoch_exit_preempt(net_epoch_preempt, &gre_et)
+#define GRE_WAIT() epoch_wait_preempt(net_epoch_preempt)
#define gre_hdr gre_uhdr.hdr
#define gre_gihdr gre_uhdr.gihdr
@@ -101,15 +101,23 @@ struct gre_softc {
#define gre_oip gre_gihdr->gi_ip
#define gre_oip6 gre_gi6hdr->gi6_ip6
-int gre_input(struct mbuf **, int *, int);
-#ifdef INET
-int in_gre_attach(struct gre_softc *);
+struct gre_list *gre_hashinit(void);
+void gre_hashdestroy(struct gre_list *);
+
+int gre_input(struct mbuf *, int, int, void *);
+void gre_updatehdr(struct gre_softc *, struct grehdr *);
+
+void in_gre_init(void);
+void in_gre_uninit(void);
+void in_gre_setopts(struct gre_softc *, u_long, uint32_t);
+int in_gre_ioctl(struct gre_softc *, u_long, caddr_t);
int in_gre_output(struct mbuf *, int, int);
-#endif
-#ifdef INET6
-int in6_gre_attach(struct gre_softc *);
+
+void in6_gre_init(void);
+void in6_gre_uninit(void);
+void in6_gre_setopts(struct gre_softc *, u_long, uint32_t);
+int in6_gre_ioctl(struct gre_softc *, u_long, caddr_t);
int in6_gre_output(struct mbuf *, int, int);
-#endif
/*
* CISCO uses special type for GRE tunnel created as part of WCCP
* connection, while in fact those packets are just IPv4 encapsulated
diff --git a/freebsd/sys/net/if_ipsec.c b/freebsd/sys/net/if_ipsec.c
index eaeecd5a..5b1d5e82 100644
--- a/freebsd/sys/net/if_ipsec.c
+++ b/freebsd/sys/net/if_ipsec.c
@@ -122,9 +122,9 @@ RM_SYSINIT(ipsec_sc_lock, &ipsec_sc_lock, "if_ipsec softc list");
#define IPSEC_SC_WLOCK_ASSERT() rm_assert(&ipsec_sc_lock, RA_WLOCKED)
LIST_HEAD(ipsec_iflist, ipsec_softc);
-static VNET_DEFINE(struct ipsec_iflist, ipsec_sc_list);
-static VNET_DEFINE(struct ipsec_iflist *, ipsec_sc_htbl);
-static VNET_DEFINE(u_long, ipsec_sc_hmask);
+VNET_DEFINE_STATIC(struct ipsec_iflist, ipsec_sc_list);
+VNET_DEFINE_STATIC(struct ipsec_iflist *, ipsec_sc_htbl);
+VNET_DEFINE_STATIC(u_long, ipsec_sc_hmask);
#define V_ipsec_sc_list VNET(ipsec_sc_list)
#define V_ipsec_sc_htbl VNET(ipsec_sc_htbl)
#define V_ipsec_sc_hmask VNET(ipsec_sc_hmask)
@@ -164,7 +164,7 @@ static void ipsec_qflush(struct ifnet *);
static int ipsec_clone_create(struct if_clone *, int, caddr_t);
static void ipsec_clone_destroy(struct ifnet *);
-static VNET_DEFINE(struct if_clone *, ipsec_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, ipsec_cloner);
#define V_ipsec_cloner VNET(ipsec_cloner)
static int
diff --git a/freebsd/sys/net/if_lagg.c b/freebsd/sys/net/if_lagg.c
index 578078c2..4d5aaa29 100644
--- a/freebsd/sys/net/if_lagg.c
+++ b/freebsd/sys/net/if_lagg.c
@@ -75,10 +75,10 @@ __FBSDID("$FreeBSD$");
#include <net/if_lagg.h>
#include <net/ieee8023ad_lacp.h>
-#define LAGG_RLOCK() epoch_enter_preempt(net_epoch_preempt)
-#define LAGG_RUNLOCK() epoch_exit_preempt(net_epoch_preempt)
-#define LAGG_RLOCK_ASSERT() MPASS(in_epoch())
-#define LAGG_UNLOCK_ASSERT() MPASS(!in_epoch())
+#define LAGG_RLOCK() struct epoch_tracker lagg_et; epoch_enter_preempt(net_epoch_preempt, &lagg_et)
+#define LAGG_RUNLOCK() epoch_exit_preempt(net_epoch_preempt, &lagg_et)
+#define LAGG_RLOCK_ASSERT() MPASS(in_epoch(net_epoch_preempt))
+#define LAGG_UNLOCK_ASSERT() MPASS(!in_epoch(net_epoch_preempt))
#define LAGG_SX_INIT(_sc) sx_init(&(_sc)->sc_sx, "if_lagg sx")
#define LAGG_SX_DESTROY(_sc) sx_destroy(&(_sc)->sc_sx)
@@ -99,7 +99,7 @@ static struct {
VNET_DEFINE(SLIST_HEAD(__trhead, lagg_softc), lagg_list); /* list of laggs */
#define V_lagg_list VNET(lagg_list)
-static VNET_DEFINE(struct mtx, lagg_list_mtx);
+VNET_DEFINE_STATIC(struct mtx, lagg_list_mtx);
#define V_lagg_list_mtx VNET(lagg_list_mtx)
#define LAGG_LIST_LOCK_INIT(x) mtx_init(&V_lagg_list_mtx, \
"if_lagg list", NULL, MTX_DEF)
@@ -110,7 +110,7 @@ eventhandler_tag lagg_detach_cookie = NULL;
static int lagg_clone_create(struct if_clone *, int, caddr_t);
static void lagg_clone_destroy(struct ifnet *);
-static VNET_DEFINE(struct if_clone *, lagg_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, lagg_cloner);
#define V_lagg_cloner VNET(lagg_cloner)
static const char laggname[] = "lagg";
@@ -251,21 +251,21 @@ SYSCTL_NODE(_net_link, OID_AUTO, lagg, CTLFLAG_RW, 0,
"Link Aggregation");
/* Allow input on any failover links */
-static VNET_DEFINE(int, lagg_failover_rx_all);
+VNET_DEFINE_STATIC(int, lagg_failover_rx_all);
#define V_lagg_failover_rx_all VNET(lagg_failover_rx_all)
SYSCTL_INT(_net_link_lagg, OID_AUTO, failover_rx_all, CTLFLAG_RW | CTLFLAG_VNET,
&VNET_NAME(lagg_failover_rx_all), 0,
"Accept input from any interface in a failover lagg");
/* Default value for using flowid */
-static VNET_DEFINE(int, def_use_flowid) = 0;
+VNET_DEFINE_STATIC(int, def_use_flowid) = 0;
#define V_def_use_flowid VNET(def_use_flowid)
SYSCTL_INT(_net_link_lagg, OID_AUTO, default_use_flowid, CTLFLAG_RWTUN,
&VNET_NAME(def_use_flowid), 0,
"Default setting for using flow id for load sharing");
/* Default value for flowid shift */
-static VNET_DEFINE(int, def_flowid_shift) = 16;
+VNET_DEFINE_STATIC(int, def_flowid_shift) = 16;
#define V_def_flowid_shift VNET(def_flowid_shift)
SYSCTL_INT(_net_link_lagg, OID_AUTO, default_flowid_shift, CTLFLAG_RWTUN,
&VNET_NAME(def_flowid_shift), 0,
@@ -1739,6 +1739,10 @@ lagg_linkstate(struct lagg_softc *sc)
LAGG_XLOCK_ASSERT(sc);
+ /* LACP handles link state itself */
+ if (sc->sc_proto == LAGG_PROTO_LACP)
+ return;
+
/* Our link is considered up if at least one of our ports is active */
LAGG_RLOCK();
CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
@@ -1793,6 +1797,7 @@ struct lagg_port *
lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp)
{
struct lagg_port *lp_next, *rval = NULL;
+ struct epoch_tracker net_et;
/*
* Search a port which reports an active link state.
@@ -1811,15 +1816,14 @@ lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp)
}
search:
- LAGG_RLOCK();
+ epoch_enter_preempt(net_epoch_preempt, &net_et);
CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) {
if (LAGG_PORTACTIVE(lp_next)) {
- LAGG_RUNLOCK();
- rval = lp_next;
- goto found;
+ epoch_exit_preempt(net_epoch_preempt, &net_et);
+ return (lp_next);
}
}
- LAGG_RUNLOCK();
+ epoch_exit_preempt(net_epoch_preempt, &net_et);
found:
return (rval);
}
diff --git a/freebsd/sys/net/if_llatbl.c b/freebsd/sys/net/if_llatbl.c
index d6e9dbaf..b220d7aa 100644
--- a/freebsd/sys/net/if_llatbl.c
+++ b/freebsd/sys/net/if_llatbl.c
@@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
-static VNET_DEFINE(SLIST_HEAD(, lltable), lltables) =
+VNET_DEFINE_STATIC(SLIST_HEAD(, lltable), lltables) =
SLIST_HEAD_INITIALIZER(lltables);
#define V_lltables VNET(lltables)
@@ -438,6 +438,9 @@ llentry_free(struct llentry *lle)
pkts_dropped = lltable_drop_entry_queue(lle);
+ /* cancel timer */
+ if (callout_stop(&lle->lle_timer) > 0)
+ LLE_REMREF(lle);
LLE_FREE_LOCKED(lle);
return (pkts_dropped);
@@ -524,8 +527,6 @@ lltable_free(struct lltable *llt)
IF_AFDATA_WUNLOCK(llt->llt_ifp);
CK_LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
- if (callout_stop(&lle->lle_timer) > 0)
- LLE_REMREF(lle);
llentry_free(lle);
}
diff --git a/freebsd/sys/net/if_loop.c b/freebsd/sys/net/if_loop.c
index 988b9f9d..a96144b8 100644
--- a/freebsd/sys/net/if_loop.c
+++ b/freebsd/sys/net/if_loop.c
@@ -101,7 +101,7 @@ static void lo_clone_destroy(struct ifnet *);
VNET_DEFINE(struct ifnet *, loif); /* Used externally */
#ifdef VIMAGE
-static VNET_DEFINE(struct if_clone *, lo_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, lo_cloner);
#define V_lo_cloner VNET(lo_cloner)
#endif
@@ -382,6 +382,7 @@ loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_UP);
/*
* Everything else is done at a higher level.
*/
diff --git a/freebsd/sys/net/if_media.h b/freebsd/sys/net/if_media.h
index 97cd6552..8192a679 100644
--- a/freebsd/sys/net/if_media.h
+++ b/freebsd/sys/net/if_media.h
@@ -202,6 +202,62 @@ uint64_t ifmedia_baudrate(int);
#define IFM_10G_AOC IFM_X(59) /* 10G active optical cable */
#define IFM_25G_ACC IFM_X(60) /* 25G active copper cable */
#define IFM_25G_AOC IFM_X(61) /* 25G active optical cable */
+#define IFM_100_SGMII IFM_X(62) /* 100M media interface */
+#define IFM_2500_X IFM_X(63) /* 2500BaseX */
+#define IFM_5000_KR IFM_X(64) /* 5GBase-KR backplane */
+#define IFM_25G_T IFM_X(65) /* 25GBase-T - RJ45 */
+#define IFM_25G_CR_S IFM_X(66) /* 25GBase-CR (short) */
+#define IFM_25G_CR1 IFM_X(67) /* 25GBase-CR1 DA cable */
+#define IFM_25G_KR_S IFM_X(68) /* 25GBase-KR (short) */
+#define IFM_5000_KR_S IFM_X(69) /* 5GBase-KR backplane (short) */
+#define IFM_5000_KR1 IFM_X(70) /* 5GBase-KR backplane */
+#define IFM_25G_AUI IFM_X(71) /* 25G-AUI-C2C (chip to chip) */
+#define IFM_40G_XLAUI IFM_X(72) /* 40G-XLAUI */
+#define IFM_40G_XLAUI_AC IFM_X(73) /* 40G active copper/optical */
+#define IFM_40G_ER4 IFM_X(74) /* 40GBase-ER4 */
+#define IFM_50G_SR2 IFM_X(75) /* 50GBase-SR2 */
+#define IFM_50G_LR2 IFM_X(76) /* 50GBase-LR2 */
+#define IFM_50G_LAUI2_AC IFM_X(77) /* 50G active copper/optical */
+#define IFM_50G_LAUI2 IFM_X(78) /* 50G-LAUI2 */
+#define IFM_50G_AUI2_AC IFM_X(79) /* 50G active copper/optical */
+#define IFM_50G_AUI2 IFM_X(80) /* 50G-AUI2 */
+#define IFM_50G_CP IFM_X(81) /* 50GBase-CP */
+#define IFM_50G_SR IFM_X(82) /* 50GBase-SR */
+#define IFM_50G_LR IFM_X(83) /* 50GBase-LR */
+#define IFM_50G_FR IFM_X(84) /* 50GBase-FR */
+#define IFM_50G_KR_PAM4 IFM_X(85) /* 50GBase-KR PAM4 */
+#define IFM_25G_KR1 IFM_X(86) /* 25GBase-KR1 */
+#define IFM_50G_AUI1_AC IFM_X(87) /* 50G active copper/optical */
+#define IFM_50G_AUI1 IFM_X(88) /* 50G-AUI1 */
+#define IFM_100G_CAUI4_AC IFM_X(89) /* 100G-CAUI4 active copper/optical */
+#define IFM_100G_CAUI4 IFM_X(90) /* 100G-CAUI4 */
+#define IFM_100G_AUI4_AC IFM_X(91) /* 100G-AUI4 active copper/optical */
+#define IFM_100G_AUI4 IFM_X(92) /* 100G-AUI4 */
+#define IFM_100G_CR_PAM4 IFM_X(93) /* 100GBase-CR PAM4 */
+#define IFM_100G_KR_PAM4 IFM_X(94) /* 100GBase-CR PAM4 */
+#define IFM_100G_CP2 IFM_X(95) /* 100GBase-CP2 */
+#define IFM_100G_SR2 IFM_X(96) /* 100GBase-SR2 */
+#define IFM_100G_DR IFM_X(97) /* 100GBase-DR */
+#define IFM_100G_KR2_PAM4 IFM_X(98) /* 100GBase-KR2 PAM4 */
+#define IFM_100G_CAUI2_AC IFM_X(99) /* 100G-CAUI2 active copper/optical */
+#define IFM_100G_CAUI2 IFM_X(100) /* 100G-CAUI2 */
+#define IFM_100G_AUI2_AC IFM_X(101) /* 100G-AUI2 active copper/optical */
+#define IFM_100G_AUI2 IFM_X(102) /* 100G-AUI2 */
+#define IFM_200G_CR4_PAM4 IFM_X(103) /* 200GBase-CR4 PAM4 */
+#define IFM_200G_SR4 IFM_X(104) /* 200GBase-SR4 */
+#define IFM_200G_FR4 IFM_X(105) /* 200GBase-FR4 */
+#define IFM_200G_LR4 IFM_X(106) /* 200GBase-LR4 */
+#define IFM_200G_DR4 IFM_X(107) /* 200GBase-DR4 */
+#define IFM_200G_KR4_PAM4 IFM_X(108) /* 200GBase-KR4 PAM4 */
+#define IFM_200G_AUI4_AC IFM_X(109) /* 200G-AUI4 active copper/optical */
+#define IFM_200G_AUI4 IFM_X(110) /* 200G-AUI4 */
+#define IFM_200G_AUI8_AC IFM_X(111) /* 200G-AUI8 active copper/optical */
+#define IFM_200G_AUI8 IFM_X(112) /* 200G-AUI8 */
+#define IFM_400G_FR8 IFM_X(113) /* 400GBase-FR8 */
+#define IFM_400G_LR8 IFM_X(114) /* 400GBase-LR8 */
+#define IFM_400G_DR4 IFM_X(115) /* 400GBase-DR4 */
+#define IFM_400G_AUI8_AC IFM_X(116) /* 400G-AUI8 active copper/optical */
+#define IFM_400G_AUI8 IFM_X(117) /* 400G-AUI8 */
/*
* Please update ieee8023ad_lacp.c:lacp_compose_key()
@@ -432,6 +488,62 @@ struct ifmedia_description {
{ IFM_10G_AOC, "10GBase-AOC" }, \
{ IFM_25G_ACC, "25GBase-ACC" }, \
{ IFM_25G_AOC, "25GBase-AOC" }, \
+ { IFM_100_SGMII, "100M-SGMII" }, \
+ { IFM_2500_X, "2500Base-X" }, \
+ { IFM_5000_KR, "5000Base-KR" }, \
+ { IFM_25G_T, "25GBase-T" }, \
+ { IFM_25G_CR_S, "25GBase-CR-S" }, \
+ { IFM_25G_CR1, "25GBase-CR1" }, \
+ { IFM_25G_KR_S, "25GBase-KR-S" }, \
+ { IFM_5000_KR_S, "5000Base-KR-S" }, \
+ { IFM_5000_KR1, "5000Base-KR1" }, \
+ { IFM_25G_AUI, "25G-AUI" }, \
+ { IFM_40G_XLAUI, "40G-XLAUI" }, \
+ { IFM_40G_XLAUI_AC, "40G-XLAUI-AC" }, \
+ { IFM_40G_ER4, "40GBase-ER4" }, \
+ { IFM_50G_SR2, "50GBase-SR2" }, \
+ { IFM_50G_LR2, "50GBase-LR2" }, \
+ { IFM_50G_LAUI2_AC, "50G-LAUI2-AC" }, \
+ { IFM_50G_LAUI2, "50G-LAUI2" }, \
+ { IFM_50G_AUI2_AC, "50G-AUI2-AC" }, \
+ { IFM_50G_AUI2, "50G-AUI2" }, \
+ { IFM_50G_CP, "50GBase-CP" }, \
+ { IFM_50G_SR, "50GBase-SR" }, \
+ { IFM_50G_LR, "50GBase-LR" }, \
+ { IFM_50G_FR, "50GBase-FR" }, \
+ { IFM_50G_KR_PAM4, "50GBase-KR-PAM4" }, \
+ { IFM_25G_KR1, "25GBase-KR1" }, \
+ { IFM_50G_AUI1_AC, "50G-AUI1-AC" }, \
+ { IFM_50G_AUI1, "50G-AUI1" }, \
+ { IFM_100G_CAUI4_AC, "100G-CAUI4-AC" }, \
+ { IFM_100G_CAUI4, "100G-CAUI4" }, \
+ { IFM_100G_AUI4_AC, "100G-AUI4-AC" }, \
+ { IFM_100G_AUI4, "100G-AUI4" }, \
+ { IFM_100G_CR_PAM4, "100GBase-CR-PAM4" }, \
+ { IFM_100G_KR_PAM4, "100GBase-KR-PAM4" }, \
+ { IFM_100G_CP2, "100GBase-CP2" }, \
+ { IFM_100G_SR2, "100GBase-SR2" }, \
+ { IFM_100G_DR, "100GBase-DR" }, \
+ { IFM_100G_KR2_PAM4, "100GBase-KR2-PAM4" }, \
+ { IFM_100G_CAUI2_AC, "100G-CAUI2-AC" }, \
+ { IFM_100G_CAUI2, "100G-CAUI2" }, \
+ { IFM_100G_AUI2_AC, "100G-AUI2-AC" }, \
+ { IFM_100G_AUI2, "100G-AUI2" }, \
+ { IFM_200G_CR4_PAM4, "200GBase-CR4-PAM4" }, \
+ { IFM_200G_SR4, "200GBase-SR4" }, \
+ { IFM_200G_FR4, "200GBase-FR4" }, \
+ { IFM_200G_LR4, "200GBase-LR4" }, \
+ { IFM_200G_DR4, "200GBase-DR4" }, \
+ { IFM_200G_KR4_PAM4, "200GBase-KR4-PAM4" }, \
+ { IFM_200G_AUI4_AC, "200G-AUI4-AC" }, \
+ { IFM_200G_AUI4, "200G-AUI4" }, \
+ { IFM_200G_AUI8_AC, "200G-AUI8-AC" }, \
+ { IFM_200G_AUI8, "200G-AUI8" }, \
+ { IFM_400G_FR8, "400GBase-FR8" }, \
+ { IFM_400G_LR8, "400GBase-LR8" }, \
+ { IFM_400G_DR4, "400GBase-DR4" }, \
+ { IFM_400G_AUI8_AC, "400G-AUI8-AC" }, \
+ { IFM_400G_AUI8, "400G-AUI8" }, \
{ 0, NULL }, \
}
@@ -719,6 +831,62 @@ struct ifmedia_baudrate {
{ IFM_ETHER | IFM_10G_AOC, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_25G_ACC, IF_Gbps(25ULL) }, \
{ IFM_ETHER | IFM_25G_AOC, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_100_SGMII, IF_Mbps(100) }, \
+ { IFM_ETHER | IFM_2500_X, IF_Mbps(2500ULL) }, \
+ { IFM_ETHER | IFM_5000_KR, IF_Mbps(5000ULL) }, \
+ { IFM_ETHER | IFM_25G_T, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_25G_CR_S, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_25G_CR1, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_25G_KR_S, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_5000_KR_S, IF_Mbps(5000ULL) }, \
+ { IFM_ETHER | IFM_5000_KR1, IF_Mbps(5000ULL) }, \
+ { IFM_ETHER | IFM_25G_AUI, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_40G_XLAUI, IF_Gbps(40ULL) }, \
+ { IFM_ETHER | IFM_40G_XLAUI_AC, IF_Gbps(40ULL) }, \
+ { IFM_ETHER | IFM_40G_ER4, IF_Gbps(40ULL) }, \
+ { IFM_ETHER | IFM_50G_SR2, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_LR2, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_LAUI2_AC, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_LAUI2, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_AUI2_AC, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_AUI2, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_CP, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_SR, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_LR, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_FR, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_KR_PAM4, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_25G_KR1, IF_Gbps(25ULL) }, \
+ { IFM_ETHER | IFM_50G_AUI1_AC, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_50G_AUI1, IF_Gbps(50ULL) }, \
+ { IFM_ETHER | IFM_100G_CAUI4_AC, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_CAUI4, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_AUI4_AC, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_AUI4, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_CR_PAM4, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_KR_PAM4, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_CP2, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_SR2, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_DR, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_KR2_PAM4, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_CAUI2_AC, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_CAUI2, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_AUI2_AC, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_100G_AUI2, IF_Gbps(100ULL) }, \
+ { IFM_ETHER | IFM_200G_CR4_PAM4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_SR4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_FR4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_LR4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_DR4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_KR4_PAM4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_AUI4_AC, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_AUI4, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_AUI8_AC, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_200G_AUI8, IF_Gbps(200ULL) }, \
+ { IFM_ETHER | IFM_400G_FR8, IF_Gbps(400ULL) }, \
+ { IFM_ETHER | IFM_400G_LR8, IF_Gbps(400ULL) }, \
+ { IFM_ETHER | IFM_400G_DR4, IF_Gbps(400ULL) }, \
+ { IFM_ETHER | IFM_400G_AUI8_AC, IF_Gbps(400ULL) }, \
+ { IFM_ETHER | IFM_400G_AUI8, IF_Gbps(400ULL) }, \
\
{ IFM_IEEE80211 | IFM_IEEE80211_FH1, IF_Mbps(1) }, \
{ IFM_IEEE80211 | IFM_IEEE80211_FH2, IF_Mbps(2) }, \
diff --git a/freebsd/sys/net/if_stf.c b/freebsd/sys/net/if_stf.c
index 1d16b2d7..1102a62d 100644
--- a/freebsd/sys/net/if_stf.c
+++ b/freebsd/sys/net/if_stf.c
@@ -87,7 +87,6 @@
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
-#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/rmlock.h>
@@ -153,19 +152,7 @@ static const char stfname[] = "stf";
static MALLOC_DEFINE(M_STF, stfname, "6to4 Tunnel Interface");
static const int ip_stf_ttl = 40;
-extern struct domain inetdomain;
-static int in_stf_input(struct mbuf **, int *, int);
-static struct protosw in_stf_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_IPV6,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = in_stf_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
+static int in_stf_input(struct mbuf *, int, int, void *);
static char *stfnames[] = {"stf0", "stf", "6to4", NULL};
static int stfmodevent(module_t, int, void *);
@@ -185,6 +172,14 @@ static int stf_clone_create(struct if_clone *, char *, size_t, caddr_t);
static int stf_clone_destroy(struct if_clone *, struct ifnet *);
static struct if_clone *stf_cloner;
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_IPV6,
+ .min_length = sizeof(struct ip),
+ .exact_match = (sizeof(in_addr_t) << 3) + 8,
+ .check = stf_encapcheck,
+ .input = in_stf_input
+};
+
static int
stf_clone_match(struct if_clone *ifc, const char *name)
{
@@ -256,8 +251,7 @@ stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_dname = stfname;
ifp->if_dunit = IF_DUNIT_NONE;
- sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
- stf_encapcheck, &in_stf_protosw, sc);
+ sc->encap_cookie = ip_encap_attach(&ipv4_encap_cfg, sc, M_WAITOK);
if (sc->encap_cookie == NULL) {
if_printf(ifp, "attach failed\n");
free(sc, M_STF);
@@ -280,7 +274,7 @@ stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
struct stf_softc *sc = ifp->if_softc;
int err __unused;
- err = encap_detach(sc->encap_cookie);
+ err = ip_encap_detach(sc->encap_cookie);
KASSERT(err == 0, ("Unexpected error detaching encap_cookie"));
bpfdetach(ifp);
if_detach(ifp);
@@ -614,18 +608,13 @@ stf_checkaddr6(struct stf_softc *sc, struct in6_addr *in6, struct ifnet *inifp)
}
static int
-in_stf_input(struct mbuf **mp, int *offp, int proto)
+in_stf_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct stf_softc *sc;
+ struct stf_softc *sc = arg;
struct ip *ip;
struct ip6_hdr *ip6;
- struct mbuf *m;
u_int8_t otos, itos;
struct ifnet *ifp;
- int off;
-
- m = *mp;
- off = *offp;
if (proto != IPPROTO_IPV6) {
m_freem(m);
@@ -633,9 +622,6 @@ in_stf_input(struct mbuf **mp, int *offp, int proto)
}
ip = mtod(m, struct ip *);
-
- sc = (struct stf_softc *)encap_getarg(m);
-
if (sc == NULL || (STF2IFP(sc)->if_flags & IFF_UP) == 0) {
m_freem(m);
return (IPPROTO_DONE);
@@ -686,7 +672,7 @@ in_stf_input(struct mbuf **mp, int *offp, int proto)
ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
m->m_pkthdr.rcvif = ifp;
-
+
if (bpf_peers_present(ifp->if_bpf)) {
/*
* We need to prepend the address family as
diff --git a/freebsd/sys/net/if_tun.c b/freebsd/sys/net/if_tun.c
index e4a0b02f..14a75645 100644
--- a/freebsd/sys/net/if_tun.c
+++ b/freebsd/sys/net/if_tun.c
@@ -924,7 +924,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
m_freem(m);
return (EAFNOSUPPORT);
}
- random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_TUN);
+ random_harvest_queue(m, sizeof(*m), RANDOM_NET_TUN);
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
CURVNET_SET(ifp->if_vnet);
diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h
index f8e18f7e..00fcbebd 100644
--- a/freebsd/sys/net/if_var.h
+++ b/freebsd/sys/net/if_var.h
@@ -390,6 +390,8 @@ struct ifnet {
struct netdump_methods *if_netdump_methods;
#endif /* __rtems__ */
struct epoch_context if_epoch_ctx;
+ struct epoch_tracker if_addr_et;
+ struct epoch_tracker if_maddr_et;
#ifndef __rtems__
/*
@@ -421,15 +423,17 @@ struct rtems_ifinputreq {
*/
#define IF_ADDR_LOCK_INIT(if) mtx_init(&(if)->if_addr_lock, "if_addr_lock", NULL, MTX_DEF)
#define IF_ADDR_LOCK_DESTROY(if) mtx_destroy(&(if)->if_addr_lock)
-#define IF_ADDR_RLOCK(if) epoch_enter_preempt(net_epoch_preempt);
-#define IF_ADDR_RUNLOCK(if) epoch_exit_preempt(net_epoch_preempt);
+#define IF_ADDR_RLOCK(if) struct epoch_tracker if_addr_et; epoch_enter_preempt(net_epoch_preempt, &if_addr_et);
+#define IF_ADDR_RUNLOCK(if) epoch_exit_preempt(net_epoch_preempt, &if_addr_et);
#define IF_ADDR_WLOCK(if) mtx_lock(&(if)->if_addr_lock)
#define IF_ADDR_WUNLOCK(if) mtx_unlock(&(if)->if_addr_lock)
-#define IF_ADDR_LOCK_ASSERT(if) MPASS(in_epoch() || mtx_owned(&(if)->if_addr_lock))
+#define IF_ADDR_LOCK_ASSERT(if) MPASS(in_epoch(net_epoch_preempt) || mtx_owned(&(if)->if_addr_lock))
#define IF_ADDR_WLOCK_ASSERT(if) mtx_assert(&(if)->if_addr_lock, MA_OWNED)
-#define NET_EPOCH_ENTER() epoch_enter_preempt(net_epoch_preempt)
-#define NET_EPOCH_EXIT() epoch_exit_preempt(net_epoch_preempt)
+#define NET_EPOCH_ENTER() struct epoch_tracker nep_et; epoch_enter_preempt(net_epoch_preempt, &nep_et)
+#define NET_EPOCH_ENTER_ET(et) epoch_enter_preempt(net_epoch_preempt, &(et))
+#define NET_EPOCH_EXIT() epoch_exit_preempt(net_epoch_preempt, &nep_et)
+#define NET_EPOCH_EXIT_ET(et) epoch_exit_preempt(net_epoch_preempt, &(et))
/*
@@ -505,16 +509,16 @@ EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
mtx_init(&(ifp)->if_afdata_lock, "if_afdata", NULL, MTX_DEF)
#define IF_AFDATA_WLOCK(ifp) mtx_lock(&(ifp)->if_afdata_lock)
-#define IF_AFDATA_RLOCK(ifp) epoch_enter_preempt(net_epoch_preempt)
+#define IF_AFDATA_RLOCK(ifp) struct epoch_tracker if_afdata_et; epoch_enter_preempt(net_epoch_preempt, &if_afdata_et)
#define IF_AFDATA_WUNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_lock)
-#define IF_AFDATA_RUNLOCK(ifp) epoch_exit_preempt(net_epoch_preempt)
+#define IF_AFDATA_RUNLOCK(ifp) epoch_exit_preempt(net_epoch_preempt, &if_afdata_et)
#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp)
#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp)
#define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_lock)
#define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_lock)
-#define IF_AFDATA_LOCK_ASSERT(ifp) MPASS(in_epoch() || mtx_owned(&(ifp)->if_afdata_lock))
-#define IF_AFDATA_RLOCK_ASSERT(ifp) MPASS(in_epoch());
+#define IF_AFDATA_LOCK_ASSERT(ifp) MPASS(in_epoch(net_epoch_preempt) || mtx_owned(&(ifp)->if_afdata_lock))
+#define IF_AFDATA_RLOCK_ASSERT(ifp) MPASS(in_epoch(net_epoch_preempt));
#define IF_AFDATA_WLOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_lock, MA_OWNED)
#define IF_AFDATA_UNLOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_lock, MA_NOTOWNED)
@@ -567,12 +571,14 @@ void ifa_ref(struct ifaddr *ifa);
* Multicast address structure. This is analogous to the ifaddr
* structure except that it keeps track of multicast addresses.
*/
+#define IFMA_F_ENQUEUED 0x1
struct ifmultiaddr {
CK_STAILQ_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */
struct sockaddr *ifma_addr; /* address this membership is for */
struct sockaddr *ifma_lladdr; /* link-layer translation, if any */
struct ifnet *ifma_ifp; /* back-pointer to interface */
u_int ifma_refcount; /* reference count */
+ int ifma_flags;
void *ifma_protospec; /* protocol-specific state, if any */
struct ifmultiaddr *ifma_llifma; /* pointer to ifma for ifma_lladdr */
struct epoch_context ifma_epoch_ctx;
@@ -596,16 +602,16 @@ extern struct sx ifnet_sxlock;
* write, but also whether it was acquired with sleep support or not.
*/
#define IFNET_RLOCK_ASSERT() sx_assert(&ifnet_sxlock, SA_SLOCKED)
-#define IFNET_RLOCK_NOSLEEP_ASSERT() MPASS(in_epoch())
+#define IFNET_RLOCK_NOSLEEP_ASSERT() MPASS(in_epoch(net_epoch_preempt))
#define IFNET_WLOCK_ASSERT() do { \
sx_assert(&ifnet_sxlock, SA_XLOCKED); \
rw_assert(&ifnet_rwlock, RA_WLOCKED); \
} while (0)
#define IFNET_RLOCK() sx_slock(&ifnet_sxlock)
-#define IFNET_RLOCK_NOSLEEP() epoch_enter_preempt(net_epoch_preempt)
+#define IFNET_RLOCK_NOSLEEP() struct epoch_tracker ifnet_rlock_et; epoch_enter_preempt(net_epoch_preempt, &ifnet_rlock_et)
#define IFNET_RUNLOCK() sx_sunlock(&ifnet_sxlock)
-#define IFNET_RUNLOCK_NOSLEEP() epoch_exit_preempt(net_epoch_preempt)
+#define IFNET_RUNLOCK_NOSLEEP() epoch_exit_preempt(net_epoch_preempt, &ifnet_rlock_et)
/*
* Look up an ifnet given its index; the _ref variant also acquires a
@@ -663,6 +669,7 @@ int if_printf(struct ifnet *, const char *, ...) __printflike(2, 3);
void if_ref(struct ifnet *);
void if_rele(struct ifnet *);
int if_setlladdr(struct ifnet *, const u_char *, int);
+int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, uint32_t, int);
void if_up(struct ifnet *);
int ifioctl(struct socket *, u_long, caddr_t, struct thread *);
int ifpromisc(struct ifnet *, int);
diff --git a/freebsd/sys/net/if_vlan.c b/freebsd/sys/net/if_vlan.c
index 26f6bbde..22061dc4 100644
--- a/freebsd/sys/net/if_vlan.c
+++ b/freebsd/sys/net/if_vlan.c
@@ -337,7 +337,7 @@ static void vlan_lladdr_fn(void *arg, int pending);
static struct if_clone *vlan_cloner;
#ifdef VIMAGE
-static VNET_DEFINE(struct if_clone *, vlan_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, vlan_cloner);
#define V_vlan_cloner VNET(vlan_cloner)
#endif
@@ -760,6 +760,18 @@ vlan_tag(struct ifnet *ifp, uint16_t *vidp)
return (0);
}
+static int
+vlan_pcp(struct ifnet *ifp, uint16_t *pcpp)
+{
+ struct ifvlan *ifv;
+
+ if (ifp->if_type != IFT_L2VLAN)
+ return (EINVAL);
+ ifv = ifp->if_softc;
+ *pcpp = ifv->ifv_pcp;
+ return (0);
+}
+
/*
* Return a driver specific cookie for this interface. Synchronization
* with setcookie must be provided by the driver.
@@ -863,6 +875,7 @@ vlan_modevent(module_t mod, int type, void *data)
vlan_cookie_p = vlan_cookie;
vlan_setcookie_p = vlan_setcookie;
vlan_tag_p = vlan_tag;
+ vlan_pcp_p = vlan_pcp;
vlan_devat_p = vlan_devat;
#ifndef VIMAGE
vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
@@ -1424,6 +1437,7 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
ifp->if_resolvemulti = p->if_resolvemulti;
ifp->if_addrlen = p->if_addrlen;
ifp->if_broadcastaddr = p->if_broadcastaddr;
+ ifp->if_pcp = ifv->ifv_pcp;
/*
* Copy only a selected subset of flags from the parent.
@@ -1948,6 +1962,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
ifv->ifv_pcp = ifr->ifr_vlan_pcp;
+ ifp->if_pcp = ifv->ifv_pcp;
vlan_tag_recalculate(ifv);
/* broadcast event about PCP change */
EVENTHANDLER_INVOKE(ifnet_event, ifp, IFNET_EVENT_PCP);
diff --git a/freebsd/sys/net/if_vlan_var.h b/freebsd/sys/net/if_vlan_var.h
index b926df80..0b66ec0a 100644
--- a/freebsd/sys/net/if_vlan_var.h
+++ b/freebsd/sys/net/if_vlan_var.h
@@ -132,6 +132,8 @@ struct vlanreq {
((_ifp)->if_type == IFT_L2VLAN ? (*vlan_trunkdev_p)((_ifp)) : NULL)
#define VLAN_TAG(_ifp, _vid) \
((_ifp)->if_type == IFT_L2VLAN ? (*vlan_tag_p)((_ifp), (_vid)) : EINVAL)
+#define VLAN_PCP(_ifp, _pcp) \
+ ((_ifp)->if_type == IFT_L2VLAN ? (*vlan_pcp_p)((_ifp), (_pcp)) : EINVAL)
#define VLAN_COOKIE(_ifp) \
((_ifp)->if_type == IFT_L2VLAN ? (*vlan_cookie_p)((_ifp)) : NULL)
#define VLAN_SETCOOKIE(_ifp, _cookie) \
@@ -144,6 +146,7 @@ extern void (*vlan_trunk_cap_p)(struct ifnet *);
extern struct ifnet *(*vlan_trunkdev_p)(struct ifnet *);
extern struct ifnet *(*vlan_devat_p)(struct ifnet *, uint16_t);
extern int (*vlan_tag_p)(struct ifnet *, uint16_t *);
+extern int (*vlan_pcp_p)(struct ifnet *, uint16_t *);
extern int (*vlan_setcookie_p)(struct ifnet *, void *);
extern void *(*vlan_cookie_p)(struct ifnet *);
diff --git a/freebsd/sys/net/iflib.h b/freebsd/sys/net/iflib.h
index 140c488b..6e1eee63 100644
--- a/freebsd/sys/net/iflib.h
+++ b/freebsd/sys/net/iflib.h
@@ -45,13 +45,6 @@ struct if_clone;
*/
typedef uint16_t qidx_t;
#define QIDX_INVALID 0xFFFF
-/*
- * Most cards can handle much larger TSO requests
- * but the FreeBSD TCP stack will break on larger
- * values
- */
-#define FREEBSD_TSO_SIZE_MAX 65518
-
struct iflib_ctx;
typedef struct iflib_ctx *if_ctx_t;
@@ -216,6 +209,7 @@ typedef struct if_softc_ctx {
int isc_tx_tso_size_max;
int isc_tx_tso_segsize_max;
int isc_tx_csum_flags;
+ int isc_capabilities;
int isc_capenable;
int isc_rss_table_size;
int isc_rss_table_mask;
@@ -242,6 +236,8 @@ struct if_shared_ctx {
bus_size_t isc_q_align;
bus_size_t isc_tx_maxsize;
bus_size_t isc_tx_maxsegsize;
+ bus_size_t isc_tso_maxsize;
+ bus_size_t isc_tso_maxsegsize;
bus_size_t isc_rx_maxsize;
bus_size_t isc_rx_maxsegsize;
int isc_rx_nsegments;
diff --git a/freebsd/sys/net/netisr.c b/freebsd/sys/net/netisr.c
index 8f2430eb..a3da964b 100644
--- a/freebsd/sys/net/netisr.c
+++ b/freebsd/sys/net/netisr.c
@@ -227,7 +227,7 @@ static struct netisr_proto netisr_proto[NETISR_MAXPROT];
* mechanism to stop netisr processing for vnet teardown.
* Apart from that we expect a VNET to always be enabled.
*/
-static VNET_DEFINE(u_int, netisr_enable[NETISR_MAXPROT]);
+VNET_DEFINE_STATIC(u_int, netisr_enable[NETISR_MAXPROT]);
#define V_netisr_enable VNET(netisr_enable)
#endif
diff --git a/freebsd/sys/net/pfvar.h b/freebsd/sys/net/pfvar.h
index 824b8ec3..5e80b665 100644
--- a/freebsd/sys/net/pfvar.h
+++ b/freebsd/sys/net/pfvar.h
@@ -621,9 +621,9 @@ struct pf_rule {
#define PFRULE_IFBOUND 0x00010000 /* if-bound */
#define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */
-#define PFSTATE_HIWAT 10000 /* default state table size */
-#define PFSTATE_ADAPT_START 6000 /* default adaptive timeout start */
-#define PFSTATE_ADAPT_END 12000 /* default adaptive timeout end */
+#define PFSTATE_HIWAT 100000 /* default state table size */
+#define PFSTATE_ADAPT_START 60000 /* default adaptive timeout start */
+#define PFSTATE_ADAPT_END 120000 /* default adaptive timeout end */
struct pf_threshold {
@@ -1300,21 +1300,56 @@ struct pfioc_limit {
unsigned limit;
};
-struct pfioc_altq {
+struct pfioc_altq_v0 {
u_int32_t action;
u_int32_t ticket;
u_int32_t nr;
- struct pf_altq altq;
+ struct pf_altq_v0 altq;
};
-struct pfioc_qstats {
+struct pfioc_altq_v1 {
+ u_int32_t action;
+ u_int32_t ticket;
+ u_int32_t nr;
+ /*
+ * Placed here so code that only uses the above parameters can be
+ * written entirely in terms of the v0 or v1 type.
+ */
+ u_int32_t version;
+ struct pf_altq_v1 altq;
+};
+
+/*
+ * Latest version of struct pfioc_altq_vX. This must move in lock-step with
+ * the latest version of struct pf_altq_vX as it has that struct as a
+ * member.
+ */
+#define PFIOC_ALTQ_VERSION PF_ALTQ_VERSION
+
+struct pfioc_qstats_v0 {
+ u_int32_t ticket;
+ u_int32_t nr;
+ void *buf;
+ int nbytes;
+ u_int8_t scheduler;
+};
+
+struct pfioc_qstats_v1 {
u_int32_t ticket;
u_int32_t nr;
void *buf;
int nbytes;
u_int8_t scheduler;
+ /*
+ * Placed here so code that only uses the above parameters can be
+ * written entirely in terms of the v0 or v1 type.
+ */
+ u_int32_t version; /* Requested version of stats struct */
};
+/* Latest version of struct pfioc_qstats_vX */
+#define PFIOC_QSTATS_VERSION 1
+
struct pfioc_ruleset {
u_int32_t nr;
char path[MAXPATHLEN];
@@ -1403,11 +1438,16 @@ struct pfioc_iface {
#define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill)
#define DIOCSTARTALTQ _IO ('D', 42)
#define DIOCSTOPALTQ _IO ('D', 43)
-#define DIOCADDALTQ _IOWR('D', 45, struct pfioc_altq)
-#define DIOCGETALTQS _IOWR('D', 47, struct pfioc_altq)
-#define DIOCGETALTQ _IOWR('D', 48, struct pfioc_altq)
-#define DIOCCHANGEALTQ _IOWR('D', 49, struct pfioc_altq)
-#define DIOCGETQSTATS _IOWR('D', 50, struct pfioc_qstats)
+#define DIOCADDALTQV0 _IOWR('D', 45, struct pfioc_altq_v0)
+#define DIOCADDALTQV1 _IOWR('D', 45, struct pfioc_altq_v1)
+#define DIOCGETALTQSV0 _IOWR('D', 47, struct pfioc_altq_v0)
+#define DIOCGETALTQSV1 _IOWR('D', 47, struct pfioc_altq_v1)
+#define DIOCGETALTQV0 _IOWR('D', 48, struct pfioc_altq_v0)
+#define DIOCGETALTQV1 _IOWR('D', 48, struct pfioc_altq_v1)
+#define DIOCCHANGEALTQV0 _IOWR('D', 49, struct pfioc_altq_v0)
+#define DIOCCHANGEALTQV1 _IOWR('D', 49, struct pfioc_altq_v1)
+#define DIOCGETQSTATSV0 _IOWR('D', 50, struct pfioc_qstats_v0)
+#define DIOCGETQSTATSV1 _IOWR('D', 50, struct pfioc_qstats_v1)
#define DIOCBEGINADDRS _IOWR('D', 51, struct pfioc_pooladdr)
#define DIOCADDADDR _IOWR('D', 52, struct pfioc_pooladdr)
#define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr)
@@ -1445,11 +1485,63 @@ struct pfioc_iface {
#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill)
-struct pf_ifspeed {
+struct pf_ifspeed_v0 {
char ifname[IFNAMSIZ];
u_int32_t baudrate;
};
-#define DIOCGIFSPEED _IOWR('D', 92, struct pf_ifspeed)
+
+struct pf_ifspeed_v1 {
+ char ifname[IFNAMSIZ];
+ u_int32_t baudrate32;
+ /* layout identical to struct pf_ifspeed_v0 up to this point */
+ u_int64_t baudrate;
+};
+
+/* Latest version of struct pf_ifspeed_vX */
+#define PF_IFSPEED_VERSION 1
+
+#define DIOCGIFSPEEDV0 _IOWR('D', 92, struct pf_ifspeed_v0)
+#define DIOCGIFSPEEDV1 _IOWR('D', 92, struct pf_ifspeed_v1)
+
+/*
+ * Compatibility and convenience macros
+ */
+#ifndef _KERNEL
+#ifdef PFIOC_USE_LATEST
+/*
+ * Maintaining in-tree consumers of the ioctl interface is easier when that
+ * code can be written in terms old names that refer to the latest interface
+ * version as that reduces the required changes in the consumers to those
+ * that are functionally necessary to accommodate a new interface version.
+ */
+#define pfioc_altq __CONCAT(pfioc_altq_v, PFIOC_ALTQ_VERSION)
+#define pfioc_qstats __CONCAT(pfioc_qstats_v, PFIOC_QSTATS_VERSION)
+#define pf_ifspeed __CONCAT(pf_ifspeed_v, PF_IFSPEED_VERSION)
+
+#define DIOCADDALTQ __CONCAT(DIOCADDALTQV, PFIOC_ALTQ_VERSION)
+#define DIOCGETALTQS __CONCAT(DIOCGETALTQSV, PFIOC_ALTQ_VERSION)
+#define DIOCGETALTQ __CONCAT(DIOCGETALTQV, PFIOC_ALTQ_VERSION)
+#define DIOCCHANGEALTQ __CONCAT(DIOCCHANGEALTQV, PFIOC_ALTQ_VERSION)
+#define DIOCGETQSTATS __CONCAT(DIOCGETQSTATSV, PFIOC_QSTATS_VERSION)
+#define DIOCGIFSPEED __CONCAT(DIOCGIFSPEEDV, PF_IFSPEED_VERSION)
+#else
+/*
+ * When building out-of-tree code that is written for the old interface,
+ * such as may exist in ports for example, resolve the old struct tags and
+ * ioctl command names to the v0 versions.
+ */
+#define pfioc_altq __CONCAT(pfioc_altq_v, 0)
+#define pfioc_qstats __CONCAT(pfioc_qstats_v, 0)
+#define pf_ifspeed __CONCAT(pf_ifspeed_v, 0)
+
+#define DIOCADDALTQ __CONCAT(DIOCADDALTQV, 0)
+#define DIOCGETALTQS __CONCAT(DIOCGETALTQSV, 0)
+#define DIOCGETALTQ __CONCAT(DIOCGETALTQV, 0)
+#define DIOCCHANGEALTQ __CONCAT(DIOCCHANGEALTQV, 0)
+#define DIOCGETQSTATS __CONCAT(DIOCGETQSTATSV, 0)
+#define DIOCGIFSPEED __CONCAT(DIOCGIFSPEEDV, 0)
+#endif /* PFIOC_USE_LATEST */
+#endif /* _KERNEL */
#ifdef _KERNEL
LIST_HEAD(pf_src_node_list, pf_src_node);
@@ -1470,7 +1562,7 @@ struct pf_idhash {
extern u_long pf_hashmask;
extern u_long pf_srchashmask;
-#define PF_HASHSIZ (32768)
+#define PF_HASHSIZ (131072)
#define PF_SRCHASHSIZ (PF_HASHSIZ/4)
VNET_DECLARE(struct pf_keyhash *, pf_keyhash);
VNET_DECLARE(struct pf_idhash *, pf_idhash);
diff --git a/freebsd/sys/net/radix.c b/freebsd/sys/net/radix.c
index bbfd5f65..9fbfb298 100644
--- a/freebsd/sys/net/radix.c
+++ b/freebsd/sys/net/radix.c
@@ -41,7 +41,7 @@
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/mutex.h>
-#include <sys/rwlock.h>
+#include <sys/rmlock.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
diff --git a/freebsd/sys/net/radix.h b/freebsd/sys/net/radix.h
index 05f0f490..a0e5e5c5 100644
--- a/freebsd/sys/net/radix.h
+++ b/freebsd/sys/net/radix.h
@@ -38,7 +38,7 @@
#ifdef _KERNEL
#include <sys/_lock.h>
#include <sys/_mutex.h>
-#include <sys/_rwlock.h>
+#include <sys/_rmlock.h>
#endif
#ifdef MALLOC_DECLARE
@@ -138,7 +138,7 @@ struct radix_node_head {
rn_close_t *rnh_close; /*do something when the last ref drops*/
struct radix_node rnh_nodes[3]; /* empty tree for common case */
#ifdef _KERNEL
- struct rwlock rnh_lock; /* locks entire radix tree */
+ struct rmlock rnh_lock; /* locks entire radix tree */
#endif
};
@@ -159,18 +159,18 @@ void rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes,
#define R_Zalloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT | M_ZERO))
#define R_Free(p) free((caddr_t)p, M_RTABLE);
+#define RADIX_NODE_HEAD_RLOCK_TRACKER struct rm_priotracker _rnh_tracker
#define RADIX_NODE_HEAD_LOCK_INIT(rnh) \
- rw_init_flags(&(rnh)->rnh_lock, "radix node head", 0)
-#define RADIX_NODE_HEAD_LOCK(rnh) rw_wlock(&(rnh)->rnh_lock)
-#define RADIX_NODE_HEAD_UNLOCK(rnh) rw_wunlock(&(rnh)->rnh_lock)
-#define RADIX_NODE_HEAD_RLOCK(rnh) rw_rlock(&(rnh)->rnh_lock)
-#define RADIX_NODE_HEAD_RUNLOCK(rnh) rw_runlock(&(rnh)->rnh_lock)
-#define RADIX_NODE_HEAD_LOCK_TRY_UPGRADE(rnh) rw_try_upgrade(&(rnh)->rnh_lock)
-
-
-#define RADIX_NODE_HEAD_DESTROY(rnh) rw_destroy(&(rnh)->rnh_lock)
-#define RADIX_NODE_HEAD_LOCK_ASSERT(rnh) rw_assert(&(rnh)->rnh_lock, RA_LOCKED)
-#define RADIX_NODE_HEAD_WLOCK_ASSERT(rnh) rw_assert(&(rnh)->rnh_lock, RA_WLOCKED)
+ rm_init(&(rnh)->rnh_lock, "radix node head")
+#define RADIX_NODE_HEAD_LOCK(rnh) rm_wlock(&(rnh)->rnh_lock)
+#define RADIX_NODE_HEAD_UNLOCK(rnh) rm_wunlock(&(rnh)->rnh_lock)
+#define RADIX_NODE_HEAD_RLOCK(rnh) rm_rlock(&(rnh)->rnh_lock,\
+ &_rnh_tracker)
+#define RADIX_NODE_HEAD_RUNLOCK(rnh) rm_runlock(&(rnh)->rnh_lock,\
+ &_rnh_tracker)
+#define RADIX_NODE_HEAD_DESTROY(rnh) rm_destroy(&(rnh)->rnh_lock)
+#define RADIX_NODE_HEAD_LOCK_ASSERT(rnh) rm_assert(&(rnh)->rnh_lock, RA_LOCKED)
+#define RADIX_NODE_HEAD_WLOCK_ASSERT(rnh) rm_assert(&(rnh)->rnh_lock, RA_WLOCKED)
#endif /* _KERNEL */
int rn_inithead(void **, int);
diff --git a/freebsd/sys/net/radix_mpath.c b/freebsd/sys/net/radix_mpath.c
index 7eccd8f1..3f90a9da 100644
--- a/freebsd/sys/net/radix_mpath.c
+++ b/freebsd/sys/net/radix_mpath.c
@@ -45,12 +45,15 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/domain.h>
#include <sys/syslog.h>
#include <net/radix.h>
#include <net/radix_mpath.h>
+#include <sys/rmlock.h>
#include <net/route.h>
#include <net/route_var.h>
#include <net/if.h>
diff --git a/freebsd/sys/net/route.c b/freebsd/sys/net/route.c
index c2348e31..3cd909c1 100644
--- a/freebsd/sys/net/route.c
+++ b/freebsd/sys/net/route.c
@@ -56,6 +56,8 @@
#include <sys/proc.h>
#include <sys/domain.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -141,7 +143,7 @@ VNET_DEFINE(int, rttrash); /* routes not in table but not freed */
*/
#define RNTORT(p) ((struct rtentry *)(p))
-static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */
+VNET_DEFINE_STATIC(uma_zone_t, rtzone); /* Routing table UMA zone. */
#define V_rtzone VNET(rtzone)
static int rtrequest1_fib_change(struct rib_head *, struct rt_addrinfo *,
@@ -472,6 +474,7 @@ struct rtentry *
rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
u_int fibnum)
{
+ RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
struct rtentry *newrt;
@@ -762,7 +765,7 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway,
struct ifaddr *ifa;
int not_found = 0;
- MPASS(in_epoch());
+ MPASS(in_epoch(net_epoch_preempt));
if ((flags & RTF_GATEWAY) == 0) {
/*
* If we are adding a route to an interface,
@@ -955,6 +958,7 @@ int
rib_lookup_info(uint32_t fibnum, const struct sockaddr *dst, uint32_t flags,
uint32_t flowid, struct rt_addrinfo *info)
{
+ RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
struct rtentry *rt;
@@ -1976,6 +1980,7 @@ rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netma
static inline int
rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
{
+ RIB_RLOCK_TRACKER;
struct sockaddr *dst;
struct sockaddr *netmask;
struct rtentry *rt = NULL;
diff --git a/freebsd/sys/net/route.h b/freebsd/sys/net/route.h
index 28f1db01..15ec1b3e 100644
--- a/freebsd/sys/net/route.h
+++ b/freebsd/sys/net/route.h
@@ -410,10 +410,8 @@ struct rt_addrinfo {
} while (0)
#define RO_RTFREE(_ro) do { \
- if ((_ro)->ro_rt) { \
- RT_LOCK((_ro)->ro_rt); \
- RTFREE_LOCKED((_ro)->ro_rt); \
- } \
+ if ((_ro)->ro_rt) \
+ RTFREE((_ro)->ro_rt); \
} while (0)
#define RO_INVALIDATE_CACHE(ro) do { \
diff --git a/freebsd/sys/net/route_var.h b/freebsd/sys/net/route_var.h
index f32dbc21..9d0d1931 100644
--- a/freebsd/sys/net/route_var.h
+++ b/freebsd/sys/net/route_var.h
@@ -44,18 +44,19 @@ struct rib_head {
rt_gen_t rnh_gen; /* generation counter */
int rnh_multipath; /* multipath capable ? */
struct radix_node rnh_nodes[3]; /* empty tree for common case */
- struct rwlock rib_lock; /* config/data path lock */
+ struct rmlock rib_lock; /* config/data path lock */
struct radix_mask_head rmhead; /* masks radix head */
};
-#define RIB_LOCK_INIT(rh) rw_init(&(rh)->rib_lock, "rib head lock")
-#define RIB_LOCK_DESTROY(rh) rw_destroy(&(rh)->rib_lock)
-#define RIB_RLOCK(rh) rw_rlock(&(rh)->rib_lock)
-#define RIB_RUNLOCK(rh) rw_runlock(&(rh)->rib_lock)
-#define RIB_WLOCK(rh) rw_wlock(&(rh)->rib_lock)
-#define RIB_WUNLOCK(rh) rw_wunlock(&(rh)->rib_lock)
-#define RIB_LOCK_ASSERT(rh) rw_assert(&(rh)->rib_lock, RA_LOCKED)
-#define RIB_WLOCK_ASSERT(rh) rw_assert(&(rh)->rib_lock, RA_WLOCKED)
+#define RIB_RLOCK_TRACKER struct rm_priotracker _rib_tracker
+#define RIB_LOCK_INIT(rh) rm_init(&(rh)->rib_lock, "rib head lock")
+#define RIB_LOCK_DESTROY(rh) rm_destroy(&(rh)->rib_lock)
+#define RIB_RLOCK(rh) rm_rlock(&(rh)->rib_lock, &_rib_tracker)
+#define RIB_RUNLOCK(rh) rm_runlock(&(rh)->rib_lock, &_rib_tracker)
+#define RIB_WLOCK(rh) rm_wlock(&(rh)->rib_lock)
+#define RIB_WUNLOCK(rh) rm_wunlock(&(rh)->rib_lock)
+#define RIB_LOCK_ASSERT(rh) rm_assert(&(rh)->rib_lock, RA_LOCKED)
+#define RIB_WLOCK_ASSERT(rh) rm_assert(&(rh)->rib_lock, RA_WLOCKED)
struct rib_head *rt_tables_get_rnh(int fib, int family);
diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c
index c0c5c5c2..84afd627 100644
--- a/freebsd/sys/net/rtsock.c
+++ b/freebsd/sys/net/rtsock.c
@@ -47,6 +47,7 @@
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
+#include <sys/rmlock.h>
#include <sys/rwlock.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@@ -141,7 +142,7 @@ typedef struct {
int ip6_count; /* attached w/ AF_INET6 */
int any_count; /* total attached */
} route_cb_t;
-static VNET_DEFINE(route_cb_t, route_cb);
+VNET_DEFINE_STATIC(route_cb_t, route_cb);
#define V_route_cb VNET(route_cb)
struct mtx rtsock_mtx;
@@ -550,6 +551,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
static int
route_output(struct mbuf *m, struct socket *so, ...)
{
+ RIB_RLOCK_TRACKER;
struct rt_msghdr *rtm = NULL;
struct rtentry *rt = NULL;
struct rib_head *rnh;
@@ -1746,15 +1748,15 @@ sysctl_iflist(int af, struct walkarg *w)
struct rt_addrinfo info;
int len, error = 0;
struct sockaddr_storage ss;
+ struct epoch_tracker et;
bzero((caddr_t)&info, sizeof(info));
bzero(&ifd, sizeof(ifd));
- IFNET_RLOCK_NOSLEEP();
+ NET_EPOCH_ENTER_ET(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (w->w_arg && w->w_arg != ifp->if_index)
continue;
if_data_copy(ifp, &ifd);
- IF_ADDR_RLOCK(ifp);
ifa = ifp->if_addr;
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
error = rtsock_msg_buffer(RTM_IFINFO, &info, w, &len);
@@ -1795,15 +1797,12 @@ sysctl_iflist(int af, struct walkarg *w)
goto done;
}
}
- IF_ADDR_RUNLOCK(ifp);
info.rti_info[RTAX_IFA] = NULL;
info.rti_info[RTAX_NETMASK] = NULL;
info.rti_info[RTAX_BRD] = NULL;
}
done:
- if (ifp != NULL)
- IF_ADDR_RUNLOCK(ifp);
- IFNET_RUNLOCK_NOSLEEP();
+ NET_EPOCH_EXIT_ET(et);
return (error);
}
@@ -1862,6 +1861,7 @@ sysctl_ifmalist(int af, struct walkarg *w)
static int
sysctl_rtsock(SYSCTL_HANDLER_ARGS)
{
+ RIB_RLOCK_TRACKER;
int *name = (int *)arg1;
u_int namelen = arg2;
struct rib_head *rnh = NULL; /* silence compiler. */
diff --git a/freebsd/sys/net/vnet.h b/freebsd/sys/net/vnet.h
index 0ec00aad..b4168750 100644
--- a/freebsd/sys/net/vnet.h
+++ b/freebsd/sys/net/vnet.h
@@ -93,6 +93,8 @@ struct vnet {
#define VNET_PCPUSTAT_DEFINE(type, name) \
VNET_DEFINE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)])
+#define VNET_PCPUSTAT_DEFINE_STATIC(type, name) \
+ VNET_DEFINE_STATIC(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)])
#define VNET_PCPUSTAT_ALLOC(name, wait) \
COUNTER_ARRAY_ALLOC(VNET(name), \
@@ -268,7 +270,20 @@ extern struct sx vnet_sxlock;
*/
#define VNET_NAME(n) vnet_entry_##n
#define VNET_DECLARE(t, n) extern t VNET_NAME(n)
-#define VNET_DEFINE(t, n) t VNET_NAME(n) __section(VNET_SETNAME) __used
+/* struct _hack is to stop this from being used with static data */
+#define VNET_DEFINE(t, n) \
+ struct _hack; t VNET_NAME(n) __section(VNET_SETNAME) __used
+#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv))
+/*
+ * As with DPCPU_DEFINE_STATIC we are unable to mark this data as static
+ * in modules on some architectures.
+ */
+#define VNET_DEFINE_STATIC(t, n) \
+ t VNET_NAME(n) __section(VNET_SETNAME) __used
+#else
+#define VNET_DEFINE_STATIC(t, n) \
+ static t VNET_NAME(n) __section(VNET_SETNAME) __used
+#endif
#define _VNET_PTR(b, n) (__typeof(VNET_NAME(n))*) \
((b) + (uintptr_t)&VNET_NAME(n))
@@ -400,7 +415,8 @@ do { \
*/
#define VNET_NAME(n) n
#define VNET_DECLARE(t, n) extern t n
-#define VNET_DEFINE(t, n) t n
+#define VNET_DEFINE(t, n) struct _hack; t n
+#define VNET_DEFINE_STATIC(t, n) static t n
#define _VNET_PTR(b, n) &VNET_NAME(n)
/*
diff --git a/freebsd/sys/net80211/ieee80211.c b/freebsd/sys/net80211/ieee80211.c
index d914c2e4..a81b5343 100644
--- a/freebsd/sys/net80211/ieee80211.c
+++ b/freebsd/sys/net80211/ieee80211.c
@@ -278,14 +278,14 @@ null_update_chw(struct ieee80211com *ic)
int
ic_printf(struct ieee80211com *ic, const char * fmt, ...)
-{
+{
va_list ap;
int retval;
retval = printf("%s: ", ic->ic_name);
va_start(ap, fmt);
retval += vprintf(fmt, ap);
- va_end(ap);
+ va_end(ap);
return (retval);
}
@@ -388,6 +388,15 @@ ieee80211_ifdetach(struct ieee80211com *ic)
{
struct ieee80211vap *vap;
+ /*
+ * We use this as an indicator that ifattach never had a chance to be
+ * called, e.g. early driver attach failed and ifdetach was called
+ * during subsequent detach. Never fear, for we have nothing to do
+ * here.
+ */
+ if (ic->ic_tq == NULL)
+ return;
+
mtx_lock(&ic_list_mtx);
LIST_REMOVE(ic, ic_next);
mtx_unlock(&ic_list_mtx);
@@ -704,7 +713,7 @@ ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
return 1;
}
-/*
+/*
* Tear down vap state and reclaim the ifnet.
* The driver is assumed to have prepared for
* this; e.g. by turning off interrupts for the
@@ -1762,7 +1771,7 @@ addmedia(struct ifmedia *media, int caps, int addsta, int mode, int mword)
#define ADD(_ic, _s, _o) \
ifmedia_add(media, \
IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
- static const u_int mopts[IEEE80211_MODE_MAX] = {
+ static const u_int mopts[IEEE80211_MODE_MAX] = {
[IEEE80211_MODE_AUTO] = IFM_AUTO,
[IEEE80211_MODE_11A] = IFM_IEEE80211_11A,
[IEEE80211_MODE_11B] = IFM_IEEE80211_11B,
@@ -2388,13 +2397,13 @@ ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode m
case IEEE80211_MODE_11NA:
case IEEE80211_MODE_TURBO_A:
case IEEE80211_MODE_STURBO_A:
- return findmedia(rates, nitems(rates),
+ return findmedia(rates, nitems(rates),
rate | IFM_IEEE80211_11A);
case IEEE80211_MODE_11B:
- return findmedia(rates, nitems(rates),
+ return findmedia(rates, nitems(rates),
rate | IFM_IEEE80211_11B);
case IEEE80211_MODE_FH:
- return findmedia(rates, nitems(rates),
+ return findmedia(rates, nitems(rates),
rate | IFM_IEEE80211_FH);
case IEEE80211_MODE_AUTO:
/* NB: ic may be NULL for some drivers */
diff --git a/freebsd/sys/net80211/ieee80211_hwmp.c b/freebsd/sys/net80211/ieee80211_hwmp.c
index 37beae83..b8950c5e 100644
--- a/freebsd/sys/net80211/ieee80211_hwmp.c
+++ b/freebsd/sys/net80211/ieee80211_hwmp.c
@@ -922,7 +922,7 @@ hwmp_update_transmitter(struct ieee80211vap *vap, struct ieee80211_node *ni,
rttran->rt_metric > metric)
{
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
- "%s path to transmiter %6D of %s, metric %d:%d",
+ "%s path to transmitter %6D of %s, metric %d:%d",
rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
"prefer" : "update", ni->ni_macaddr, ":", hwmp_frame,
rttran->rt_metric, metric);
diff --git a/freebsd/sys/net80211/ieee80211_node.c b/freebsd/sys/net80211/ieee80211_node.c
index 45d6fa73..55e51299 100644
--- a/freebsd/sys/net80211/ieee80211_node.c
+++ b/freebsd/sys/net80211/ieee80211_node.c
@@ -34,13 +34,13 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_wlan.h>
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/socket.h>
-
+
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
@@ -139,6 +139,7 @@ ieee80211_node_detach(struct ieee80211com *ic)
callout_drain(&ic->ic_inact);
ieee80211_node_table_cleanup(&ic->ic_sta);
+ ieee80211_ageq_drain(&ic->ic_stageq);
ieee80211_ageq_cleanup(&ic->ic_stageq);
}
@@ -204,7 +205,7 @@ ieee80211_node_vdetach(struct ieee80211vap *vap)
}
}
-/*
+/*
* Port authorize/unauthorize interfaces for use by an authenticator.
*/
@@ -380,7 +381,7 @@ ieee80211_create_ibss(struct ieee80211vap* vap, struct ieee80211_channel *chan)
memcpy(ni->ni_meshid, vap->iv_mesh->ms_id, ni->ni_meshidlen);
#endif
}
- /*
+ /*
* Fix the channel and related attributes.
*/
/* clear DFS CAC state on previous channel */
@@ -572,7 +573,7 @@ check_bss_debug(struct ieee80211vap *vap, struct ieee80211_node *ni)
printf("%s\n", fail & 0x10 ? "!" : "");
}
#endif /* IEEE80211_DEBUG */
-
+
int
ieee80211_ibss_merge_check(struct ieee80211_node *ni)
@@ -881,7 +882,7 @@ ieee80211_sta_join1(struct ieee80211_node *selbs)
* Set the erp state (mostly the slot time) to deal with
* the auto-select case; this should be redundant if the
* mode is locked.
- */
+ */
ieee80211_reset_erp(ic);
ieee80211_wme_initparams(vap);
@@ -1679,7 +1680,7 @@ ieee80211_fakeup_adhoc_node(struct ieee80211vap *vap,
/*
* In adhoc demo mode there are no management
* frames to use to discover neighbor capabilities,
- * so blindly propagate the local configuration
+ * so blindly propagate the local configuration
* so we can do interesting things (e.g. use
* WME to disable ACK's).
*/
@@ -2353,7 +2354,7 @@ timeout_stations(void *arg __unused, struct ieee80211_node *ni)
/* XXX before inact decrement? */
if (ni == vap->iv_bss)
return;
- if (ni->ni_associd != 0 ||
+ if (ni->ni_associd != 0 ||
(vap->iv_opmode == IEEE80211_M_IBSS ||
vap->iv_opmode == IEEE80211_M_AHDEMO)) {
/*
diff --git a/freebsd/sys/netinet/cc/cc_newreno.c b/freebsd/sys/netinet/cc/cc_newreno.c
index 4d5f8644..2450f08e 100644
--- a/freebsd/sys/netinet/cc/cc_newreno.c
+++ b/freebsd/sys/netinet/cc/cc_newreno.c
@@ -90,8 +90,8 @@ static void newreno_cong_signal(struct cc_var *ccv, uint32_t type);
static void newreno_post_recovery(struct cc_var *ccv);
static int newreno_ctl_output(struct cc_var *ccv, struct sockopt *sopt, void *buf);
-static VNET_DEFINE(uint32_t, newreno_beta) = 50;
-static VNET_DEFINE(uint32_t, newreno_beta_ecn) = 80;
+VNET_DEFINE_STATIC(uint32_t, newreno_beta) = 50;
+VNET_DEFINE_STATIC(uint32_t, newreno_beta_ecn) = 80;
#define V_newreno_beta VNET(newreno_beta)
#define V_newreno_beta_ecn VNET(newreno_beta_ecn)
@@ -129,9 +129,7 @@ newreno_malloc(struct cc_var *ccv)
static void
newreno_cb_destroy(struct cc_var *ccv)
{
-
- if (ccv->cc_data != NULL)
- free(ccv->cc_data, M_NEWRENO);
+ free(ccv->cc_data, M_NEWRENO);
}
static void
diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c
index 0d608180..6ee6b71c 100644
--- a/freebsd/sys/netinet/if_ether.c
+++ b/freebsd/sys/netinet/if_ether.c
@@ -96,13 +96,13 @@ static SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
static SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, "");
/* timer values */
-static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20
+VNET_DEFINE_STATIC(int, arpt_keep) = (20*60); /* once resolved, good for 20
* minutes */
-static VNET_DEFINE(int, arp_maxtries) = 5;
-static VNET_DEFINE(int, arp_proxyall) = 0;
-static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for
+VNET_DEFINE_STATIC(int, arp_maxtries) = 5;
+VNET_DEFINE_STATIC(int, arp_proxyall) = 0;
+VNET_DEFINE_STATIC(int, arpt_down) = 20; /* keep incomplete entries for
* 20 seconds */
-static VNET_DEFINE(int, arpt_rexmit) = 1; /* retransmit arp entries, sec*/
+VNET_DEFINE_STATIC(int, arpt_rexmit) = 1; /* retransmit arp entries, sec*/
VNET_PCPUSTAT_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
VNET_PCPUSTAT_SYSINIT(arpstat);
@@ -110,7 +110,7 @@ VNET_PCPUSTAT_SYSINIT(arpstat);
VNET_PCPUSTAT_SYSUNINIT(arpstat);
#endif /* VIMAGE */
-static VNET_DEFINE(int, arp_maxhold) = 1;
+VNET_DEFINE_STATIC(int, arp_maxhold) = 1;
#define V_arpt_keep VNET(arpt_keep)
#define V_arpt_down VNET(arpt_down)
diff --git a/freebsd/sys/netinet/igmp.c b/freebsd/sys/netinet/igmp.c
index a4b99f62..970a01a0 100644
--- a/freebsd/sys/netinet/igmp.c
+++ b/freebsd/sys/netinet/igmp.c
@@ -219,11 +219,11 @@ static MALLOC_DEFINE(M_IGMP, "igmp", "igmp state");
* FUTURE: Stop using IFP_TO_IA/INADDR_ANY, and use source address selection
* policy to control the address used by IGMP on the link.
*/
-static VNET_DEFINE(int, interface_timers_running); /* IGMPv3 general
+VNET_DEFINE_STATIC(int, interface_timers_running); /* IGMPv3 general
* query response */
-static VNET_DEFINE(int, state_change_timers_running); /* IGMPv3 state-change
+VNET_DEFINE_STATIC(int, state_change_timers_running); /* IGMPv3 state-change
* retransmit */
-static VNET_DEFINE(int, current_state_timers_running); /* IGMPv1/v2 host
+VNET_DEFINE_STATIC(int, current_state_timers_running); /* IGMPv1/v2 host
* report; IGMPv3 g/sg
* query response */
@@ -231,25 +231,25 @@ static VNET_DEFINE(int, current_state_timers_running); /* IGMPv1/v2 host
#define V_state_change_timers_running VNET(state_change_timers_running)
#define V_current_state_timers_running VNET(current_state_timers_running)
-static VNET_DEFINE(LIST_HEAD(, igmp_ifsoftc), igi_head) =
+VNET_DEFINE_STATIC(LIST_HEAD(, igmp_ifsoftc), igi_head) =
LIST_HEAD_INITIALIZER(igi_head);
-static VNET_DEFINE(struct igmpstat, igmpstat) = {
+VNET_DEFINE_STATIC(struct igmpstat, igmpstat) = {
.igps_version = IGPS_VERSION_3,
.igps_len = sizeof(struct igmpstat),
};
-static VNET_DEFINE(struct timeval, igmp_gsrdelay) = {10, 0};
+VNET_DEFINE_STATIC(struct timeval, igmp_gsrdelay) = {10, 0};
#define V_igi_head VNET(igi_head)
#define V_igmpstat VNET(igmpstat)
#define V_igmp_gsrdelay VNET(igmp_gsrdelay)
-static VNET_DEFINE(int, igmp_recvifkludge) = 1;
-static VNET_DEFINE(int, igmp_sendra) = 1;
-static VNET_DEFINE(int, igmp_sendlocal) = 1;
-static VNET_DEFINE(int, igmp_v1enable) = 1;
-static VNET_DEFINE(int, igmp_v2enable) = 1;
-static VNET_DEFINE(int, igmp_legacysupp);
-static VNET_DEFINE(int, igmp_default_version) = IGMP_VERSION_3;
+VNET_DEFINE_STATIC(int, igmp_recvifkludge) = 1;
+VNET_DEFINE_STATIC(int, igmp_sendra) = 1;
+VNET_DEFINE_STATIC(int, igmp_sendlocal) = 1;
+VNET_DEFINE_STATIC(int, igmp_v1enable) = 1;
+VNET_DEFINE_STATIC(int, igmp_v2enable) = 1;
+VNET_DEFINE_STATIC(int, igmp_legacysupp);
+VNET_DEFINE_STATIC(int, igmp_default_version) = IGMP_VERSION_3;
#define V_igmp_recvifkludge VNET(igmp_recvifkludge)
#define V_igmp_sendra VNET(igmp_sendra)
diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c
index 7233f9a2..78fd00c0 100644
--- a/freebsd/sys/netinet/in.c
+++ b/freebsd/sys/netinet/in.c
@@ -80,7 +80,7 @@ static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *);
static void in_socktrim(struct sockaddr_in *);
static void in_purgemaddrs(struct ifnet *);
-static VNET_DEFINE(int, nosameprefix);
+VNET_DEFINE_STATIC(int, nosameprefix);
#define V_nosameprefix VNET(nosameprefix)
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(nosameprefix), 0,
@@ -624,8 +624,7 @@ in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td)
in_ifadown(&ia->ia_ifa, 1);
if (ia->ia_ifa.ifa_carp)
- (*carp_detach_p)(&ia->ia_ifa,
- (cmd == SIOCDIFADDR) ? false : true);
+ (*carp_detach_p)(&ia->ia_ifa, cmd == SIOCAIFADDR);
/*
* If this is the last IPv4 address configured on this
@@ -1169,10 +1168,6 @@ in_lltable_free_entry(struct lltable *llt, struct llentry *lle)
lltable_unlink_entry(llt, lle);
}
- /* cancel timer */
- if (callout_stop(&lle->lle_timer) > 0)
- LLE_REMREF(lle);
-
/* Drop hold queue */
pkts_dropped = llentry_free(lle);
ARPSTAT_ADD(dropped, pkts_dropped);
diff --git a/freebsd/sys/netinet/in_fib.c b/freebsd/sys/netinet/in_fib.c
index f62bc4a1..f61909ea 100644
--- a/freebsd/sys/netinet/in_fib.c
+++ b/freebsd/sys/netinet/in_fib.c
@@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
-#include <sys/rwlock.h>
+#include <sys/rmlock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
@@ -136,6 +136,7 @@ int
fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flags,
uint32_t flowid, struct nhop4_basic *pnh4)
{
+ RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
struct sockaddr_in sin;
@@ -184,6 +185,7 @@ int
fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flags,
uint32_t flowid, struct nhop4_extended *pnh4)
{
+ RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
struct sockaddr_in sin;
diff --git a/freebsd/sys/netinet/in_gif.c b/freebsd/sys/netinet/in_gif.c
index d072161f..03aaaf08 100644
--- a/freebsd/sys/netinet/in_gif.c
+++ b/freebsd/sys/netinet/in_gif.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,18 +41,18 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_inet6.h>
#include <sys/param.h>
-#include <sys/lock.h>
-#include <sys/rmlock.h>
#include <sys/systm.h>
+#include <sys/jail.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
-#include <sys/protosw.h>
#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
@@ -72,35 +73,161 @@ __FBSDID("$FreeBSD$");
#include <net/if_gif.h>
-static int in_gif_input(struct mbuf **, int *, int);
-
-extern struct domain inetdomain;
-static struct protosw in_gif_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = 0/* IPPROTO_IPV[46] */,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = in_gif_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
#define GIF_TTL 30
-static VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
+VNET_DEFINE_STATIC(int, ip_gif_ttl) = GIF_TTL;
#define V_ip_gif_ttl VNET(ip_gif_ttl)
SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip_gif_ttl), 0, "");
+ &VNET_NAME(ip_gif_ttl), 0, "Default TTL value for encapsulated packets");
+
+/*
+ * We keep interfaces in a hash table using src+dst as key.
+ * Interfaces with GIF_IGNORE_SOURCE flag are linked into plain list.
+ */
+VNET_DEFINE_STATIC(struct gif_list *, ipv4_hashtbl) = NULL;
+VNET_DEFINE_STATIC(struct gif_list, ipv4_list) = CK_LIST_HEAD_INITIALIZER();
+#define V_ipv4_hashtbl VNET(ipv4_hashtbl)
+#define V_ipv4_list VNET(ipv4_list)
+
+#define GIF_HASH(src, dst) (V_ipv4_hashtbl[\
+ in_gif_hashval((src), (dst)) & (GIF_HASH_SIZE - 1)])
+#define GIF_HASH_SC(sc) GIF_HASH((sc)->gif_iphdr->ip_src.s_addr,\
+ (sc)->gif_iphdr->ip_dst.s_addr)
+static uint32_t
+in_gif_hashval(in_addr_t src, in_addr_t dst)
+{
+ uint32_t ret;
+
+ ret = fnv_32_buf(&src, sizeof(src), FNV1_32_INIT);
+ return (fnv_32_buf(&dst, sizeof(dst), ret));
+}
+
+static int
+in_gif_checkdup(const struct gif_softc *sc, in_addr_t src, in_addr_t dst)
+{
+ struct gif_softc *tmp;
+
+ if (sc->gif_family == AF_INET &&
+ sc->gif_iphdr->ip_src.s_addr == src &&
+ sc->gif_iphdr->ip_dst.s_addr == dst)
+ return (EEXIST);
+
+ CK_LIST_FOREACH(tmp, &GIF_HASH(src, dst), chain) {
+ if (tmp == sc)
+ continue;
+ if (tmp->gif_iphdr->ip_src.s_addr == src &&
+ tmp->gif_iphdr->ip_dst.s_addr == dst)
+ return (EADDRNOTAVAIL);
+ }
+ return (0);
+}
+
+static void
+in_gif_attach(struct gif_softc *sc)
+{
+
+ if (sc->gif_options & GIF_IGNORE_SOURCE)
+ CK_LIST_INSERT_HEAD(&V_ipv4_list, sc, chain);
+ else
+ CK_LIST_INSERT_HEAD(&GIF_HASH_SC(sc), sc, chain);
+}
+
+int
+in_gif_setopts(struct gif_softc *sc, u_int options)
+{
+
+ /* NOTE: we are protected with gif_ioctl_sx lock */
+ MPASS(sc->gif_family == AF_INET);
+ MPASS(sc->gif_options != options);
+
+ if ((options & GIF_IGNORE_SOURCE) !=
+ (sc->gif_options & GIF_IGNORE_SOURCE)) {
+ CK_LIST_REMOVE(sc, chain);
+ sc->gif_options = options;
+ in_gif_attach(sc);
+ }
+ return (0);
+}
+
+int
+in_gif_ioctl(struct gif_softc *sc, u_long cmd, caddr_t data)
+{
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct sockaddr_in *dst, *src;
+ struct ip *ip;
+ int error;
+
+ /* NOTE: we are protected with gif_ioctl_sx lock */
+ error = EINVAL;
+ switch (cmd) {
+ case SIOCSIFPHYADDR:
+ src = &((struct in_aliasreq *)data)->ifra_addr;
+ dst = &((struct in_aliasreq *)data)->ifra_dstaddr;
+
+ /* sanity checks */
+ if (src->sin_family != dst->sin_family ||
+ src->sin_family != AF_INET ||
+ src->sin_len != dst->sin_len ||
+ src->sin_len != sizeof(*src))
+ break;
+ if (src->sin_addr.s_addr == INADDR_ANY ||
+ dst->sin_addr.s_addr == INADDR_ANY) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ if (V_ipv4_hashtbl == NULL)
+ V_ipv4_hashtbl = gif_hashinit();
+ error = in_gif_checkdup(sc, src->sin_addr.s_addr,
+ dst->sin_addr.s_addr);
+ if (error == EADDRNOTAVAIL)
+ break;
+ if (error == EEXIST) {
+ /* Addresses are the same. Just return. */
+ error = 0;
+ break;
+ }
+ ip = malloc(sizeof(*ip), M_GIF, M_WAITOK | M_ZERO);
+ ip->ip_src.s_addr = src->sin_addr.s_addr;
+ ip->ip_dst.s_addr = dst->sin_addr.s_addr;
+ if (sc->gif_family != 0) {
+ /* Detach existing tunnel first */
+ CK_LIST_REMOVE(sc, chain);
+ GIF_WAIT();
+ free(sc->gif_hdr, M_GIF);
+ /* XXX: should we notify about link state change? */
+ }
+ sc->gif_family = AF_INET;
+ sc->gif_iphdr = ip;
+ in_gif_attach(sc);
+ break;
+ case SIOCGIFPSRCADDR:
+ case SIOCGIFPDSTADDR:
+ if (sc->gif_family != AF_INET) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ src = (struct sockaddr_in *)&ifr->ifr_addr;
+ memset(src, 0, sizeof(*src));
+ src->sin_family = AF_INET;
+ src->sin_len = sizeof(*src);
+ src->sin_addr = (cmd == SIOCGIFPSRCADDR) ?
+ sc->gif_iphdr->ip_src: sc->gif_iphdr->ip_dst;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)src);
+ if (error != 0)
+ memset(src, 0, sizeof(*src));
+ break;
+ }
+ return (error);
+}
int
in_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
{
- GIF_RLOCK_TRACKER;
struct gif_softc *sc = ifp->if_softc;
struct ip *ip;
int len;
/* prepend new IP header */
+ MPASS(in_epoch(net_epoch_preempt));
len = sizeof(struct ip);
#ifndef __NO_STRICT_ALIGNMENT
if (proto == IPPROTO_ETHERIP)
@@ -119,15 +246,9 @@ in_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
}
#endif
ip = mtod(m, struct ip *);
- GIF_RLOCK(sc);
- if (sc->gif_family != AF_INET) {
- m_freem(m);
- GIF_RUNLOCK(sc);
- return (ENETDOWN);
- }
- bcopy(sc->gif_iphdr, ip, sizeof(struct ip));
- GIF_RUNLOCK(sc);
+ MPASS(sc->gif_family == AF_INET);
+ bcopy(sc->gif_iphdr, ip, sizeof(struct ip));
ip->ip_p = proto;
/* version will be set in ip_output() */
ip->ip_ttl = V_ip_gif_ttl;
@@ -138,15 +259,14 @@ in_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
}
static int
-in_gif_input(struct mbuf **mp, int *offp, int proto)
+in_gif_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct mbuf *m = *mp;
- struct gif_softc *sc;
+ struct gif_softc *sc = arg;
struct ifnet *gifp;
struct ip *ip;
uint8_t ecn;
- sc = encap_getarg(m);
+ MPASS(in_epoch(net_epoch_preempt));
if (sc == NULL) {
m_freem(m);
KMOD_IPSTAT_INC(ips_nogif);
@@ -156,7 +276,7 @@ in_gif_input(struct mbuf **mp, int *offp, int proto)
if ((gifp->if_flags & IFF_UP) != 0) {
ip = mtod(m, struct ip *);
ecn = ip->ip_tos;
- m_adj(m, *offp);
+ m_adj(m, off);
gif_input(m, gifp, proto, ecn);
} else {
m_freem(m);
@@ -165,56 +285,125 @@ in_gif_input(struct mbuf **mp, int *offp, int proto)
return (IPPROTO_DONE);
}
-/*
- * we know that we are in IFF_UP, outer address available, and outer family
- * matched the physical addr family. see gif_encapcheck().
- */
-int
-in_gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+static int
+in_gif_lookup(const struct mbuf *m, int off, int proto, void **arg)
{
const struct ip *ip;
struct gif_softc *sc;
int ret;
- /* sanity check done in caller */
- sc = (struct gif_softc *)arg;
- GIF_RLOCK_ASSERT(sc);
+ if (V_ipv4_hashtbl == NULL)
+ return (0);
- /* check for address match */
+ MPASS(in_epoch(net_epoch_preempt));
ip = mtod(m, const struct ip *);
- if (sc->gif_iphdr->ip_src.s_addr != ip->ip_dst.s_addr)
+ /*
+ * NOTE: it is safe to iterate without any locking here, because softc
+ * can be reclaimed only when we are not within net_epoch_preempt
+ * section, but ip_encap lookup+input are executed in epoch section.
+ */
+ ret = 0;
+ CK_LIST_FOREACH(sc, &GIF_HASH(ip->ip_dst.s_addr,
+ ip->ip_src.s_addr), chain) {
+ /*
+ * This is an inbound packet, its ip_dst is source address
+ * in softc.
+ */
+ if (sc->gif_iphdr->ip_src.s_addr == ip->ip_dst.s_addr &&
+ sc->gif_iphdr->ip_dst.s_addr == ip->ip_src.s_addr) {
+ ret = ENCAP_DRV_LOOKUP;
+ goto done;
+ }
+ }
+ /*
+ * No exact match.
+ * Check the list of interfaces with GIF_IGNORE_SOURCE flag.
+ */
+ CK_LIST_FOREACH(sc, &V_ipv4_list, chain) {
+ if (sc->gif_iphdr->ip_src.s_addr == ip->ip_dst.s_addr) {
+ ret = 32 + 8; /* src + proto */
+ goto done;
+ }
+ }
+ return (0);
+done:
+ if ((GIF2IFP(sc)->if_flags & IFF_UP) == 0)
return (0);
- ret = 32;
- if (sc->gif_iphdr->ip_dst.s_addr != ip->ip_src.s_addr) {
- if ((sc->gif_options & GIF_IGNORE_SOURCE) == 0)
- return (0);
- } else
- ret += 32;
-
/* ingress filters on outer source */
if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0) {
struct nhop4_basic nh4;
struct in_addr dst;
dst = ip->ip_src;
-
if (fib4_lookup_nh_basic(sc->gif_fibnum, dst, 0, 0, &nh4) != 0)
return (0);
-
if (nh4.nh_ifp != m->m_pkthdr.rcvif)
return (0);
}
+ *arg = sc;
return (ret);
}
-int
-in_gif_attach(struct gif_softc *sc)
+static struct {
+ const struct encap_config encap;
+ const struct encaptab *cookie;
+} ipv4_encap_cfg[] = {
+ {
+ .encap = {
+ .proto = IPPROTO_IPV4,
+ .min_length = 2 * sizeof(struct ip),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in_gif_lookup,
+ .input = in_gif_input
+ },
+ },
+#ifdef INET6
+ {
+ .encap = {
+ .proto = IPPROTO_IPV6,
+ .min_length = sizeof(struct ip) +
+ sizeof(struct ip6_hdr),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in_gif_lookup,
+ .input = in_gif_input
+ },
+ },
+#endif
+ {
+ .encap = {
+ .proto = IPPROTO_ETHERIP,
+ .min_length = sizeof(struct ip) +
+ sizeof(struct etherip_header) +
+ sizeof(struct ether_header),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in_gif_lookup,
+ .input = in_gif_input
+ },
+ }
+};
+
+void
+in_gif_init(void)
{
+ int i;
- KASSERT(sc->gif_ecookie == NULL, ("gif_ecookie isn't NULL"));
- sc->gif_ecookie = encap_attach_func(AF_INET, -1, gif_encapcheck,
- &in_gif_protosw, sc);
- if (sc->gif_ecookie == NULL)
- return (EEXIST);
- return (0);
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+ for (i = 0; i < nitems(ipv4_encap_cfg); i++)
+ ipv4_encap_cfg[i].cookie = ip_encap_attach(
+ &ipv4_encap_cfg[i].encap, NULL, M_WAITOK);
+}
+
+void
+in_gif_uninit(void)
+{
+ int i;
+
+ if (IS_DEFAULT_VNET(curvnet)) {
+ for (i = 0; i < nitems(ipv4_encap_cfg); i++)
+ ip_encap_detach(ipv4_encap_cfg[i].cookie);
+ }
+ if (V_ipv4_hashtbl != NULL)
+ gif_hashdestroy(V_ipv4_hashtbl);
}
+
diff --git a/freebsd/sys/netinet/in_gif.h b/freebsd/sys/netinet/in_gif.h
deleted file mode 100644
index e1f4ae48..00000000
--- a/freebsd/sys/netinet/in_gif.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: in_gif.h,v 1.5 2000/04/14 08:36:02 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _NETINET_IN_GIF_H_
-#define _NETINET_IN_GIF_H_
-
-#define GIF_TTL 30
-
-struct gif_softc;
-void in_gif_input(struct mbuf *, int);
-int in_gif_output(struct ifnet *, int, struct mbuf *);
-int gif_encapcheck4(const struct mbuf *, int, int, void *);
-int in_gif_attach(struct gif_softc *);
-int in_gif_detach(struct gif_softc *);
-
-#endif /*_NETINET_IN_GIF_H_*/
diff --git a/freebsd/sys/netinet/in_kdtrace.h b/freebsd/sys/netinet/in_kdtrace.h
index ba63a9a9..ccf53833 100644
--- a/freebsd/sys/netinet/in_kdtrace.h
+++ b/freebsd/sys/netinet/in_kdtrace.h
@@ -34,6 +34,8 @@
SDT_PROBE6(ip, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
#define UDP_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \
SDT_PROBE5(udp, , , probe, arg0, arg1, arg2, arg3, arg4)
+#define UDPLITE_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \
+ SDT_PROBE5(udplite, , , probe, arg0, arg1, arg2, arg3, arg4)
#define TCP_PROBE1(probe, arg0) \
SDT_PROBE1(tcp, , , probe, arg0)
#define TCP_PROBE2(probe, arg0, arg1) \
@@ -46,14 +48,32 @@
SDT_PROBE5(tcp, , , probe, arg0, arg1, arg2, arg3, arg4)
#define TCP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \
SDT_PROBE6(tcp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
+#define SCTP_PROBE1(probe, arg0) \
+ SDT_PROBE1(sctp, , , probe, arg0)
+#define SCTP_PROBE2(probe, arg0, arg1) \
+ SDT_PROBE2(sctp, , , probe, arg0, arg1)
+#define SCTP_PROBE3(probe, arg0, arg1, arg2) \
+ SDT_PROBE3(sctp, , , probe, arg0, arg1, arg2)
+#define SCTP_PROBE4(probe, arg0, arg1, arg2, arg3) \
+ SDT_PROBE4(sctp, , , probe, arg0, arg1, arg2, arg3)
+#define SCTP_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \
+ SDT_PROBE5(sctp, , , probe, arg0, arg1, arg2, arg3, arg4)
+#define SCTP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \
+ SDT_PROBE6(sctp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
SDT_PROVIDER_DECLARE(ip);
+SDT_PROVIDER_DECLARE(sctp);
SDT_PROVIDER_DECLARE(tcp);
SDT_PROVIDER_DECLARE(udp);
+SDT_PROVIDER_DECLARE(udplite);
SDT_PROBE_DECLARE(ip, , , receive);
SDT_PROBE_DECLARE(ip, , , send);
+SDT_PROBE_DECLARE(sctp, , , receive);
+SDT_PROBE_DECLARE(sctp, , , send);
+SDT_PROBE_DECLARE(sctp, , , state__change);
+
SDT_PROBE_DECLARE(tcp, , , accept__established);
SDT_PROBE_DECLARE(tcp, , , accept__refused);
SDT_PROBE_DECLARE(tcp, , , connect__established);
@@ -72,4 +92,7 @@ SDT_PROBE_DECLARE(tcp, , , receive__autoresize);
SDT_PROBE_DECLARE(udp, , , receive);
SDT_PROBE_DECLARE(udp, , , send);
+SDT_PROBE_DECLARE(udplite, , , receive);
+SDT_PROBE_DECLARE(udplite, , , send);
+
#endif
diff --git a/freebsd/sys/netinet/in_mcast.c b/freebsd/sys/netinet/in_mcast.c
index ea4779fc..e0fd4c37 100644
--- a/freebsd/sys/netinet/in_mcast.c
+++ b/freebsd/sys/netinet/in_mcast.c
@@ -233,8 +233,13 @@ static void inm_init(void)
taskqgroup_config_gtask_init(NULL, &free_gtask, inm_release_task, "inm release task");
}
+#ifdef EARLY_AP_STARTUP
SYSINIT(inm_init, SI_SUB_SMP + 1, SI_ORDER_FIRST,
inm_init, NULL);
+#else
+SYSINIT(inm_init, SI_SUB_ROOT_CONF - 1, SI_ORDER_FIRST,
+ inm_init, NULL);
+#endif
void
@@ -260,7 +265,10 @@ inm_disconnect(struct in_multi *inm)
ifma = inm->inm_ifma;
if_ref(ifp);
- CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
+ if (ifma->ifma_flags & IFMA_F_ENQUEUED) {
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
+ ifma->ifma_flags &= ~IFMA_F_ENQUEUED;
+ }
MCDPRINTF("removed ifma: %p from %s\n", ifma, ifp->if_xname);
if ((ll_ifma = ifma->ifma_llifma) != NULL) {
MPASS(ifma != ll_ifma);
@@ -268,7 +276,10 @@ inm_disconnect(struct in_multi *inm)
MPASS(ll_ifma->ifma_llifma == NULL);
MPASS(ll_ifma->ifma_ifp == ifp);
if (--ll_ifma->ifma_refcount == 0) {
- CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr, ifma_link);
+ if (ll_ifma->ifma_flags & IFMA_F_ENQUEUED) {
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr, ifma_link);
+ ll_ifma->ifma_flags &= ~IFMA_F_ENQUEUED;
+ }
MCDPRINTF("removed ll_ifma: %p from %s\n", ll_ifma, ifp->if_xname);
if_freemulti(ll_ifma);
ifma_restart = true;
@@ -1581,23 +1592,24 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Begin state merge transaction at IGMP layer.
*/
IN_MULTI_LOCK();
- IN_MULTI_LIST_LOCK();
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
+ IN_MULTI_LIST_LOCK();
error = inm_merge(inm, imf);
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
+ IN_MULTI_LIST_UNLOCK();
goto out_in_multi_locked;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
error = igmp_change_state(inm);
+ IN_MULTI_LIST_UNLOCK();
if (error)
CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__);
out_in_multi_locked:
IN_MULTI_UNLOCK();
- IN_MULTI_UNLOCK();
out_imf_rollback:
if (error)
imf_rollback(imf);
@@ -1664,16 +1676,13 @@ inp_findmoptions(struct inpcb *inp)
}
static void
-inp_gcmoptions(epoch_context_t ctx)
+inp_gcmoptions(struct ip_moptions *imo)
{
- struct ip_moptions *imo;
struct in_mfilter *imf;
struct in_multi *inm;
struct ifnet *ifp;
size_t idx, nmships;
- imo = __containerof(ctx, struct ip_moptions, imo_epoch_ctx);
-
nmships = imo->imo_num_memberships;
for (idx = 0; idx < nmships; ++idx) {
imf = imo->imo_mfilters ? &imo->imo_mfilters[idx] : NULL;
@@ -1709,7 +1718,7 @@ inp_freemoptions(struct ip_moptions *imo)
{
if (imo == NULL)
return;
- epoch_call(net_epoch_preempt, &imo->imo_epoch_ctx, inp_gcmoptions);
+ inp_gcmoptions(imo);
}
/*
@@ -2261,7 +2270,8 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
__func__);
IN_MULTI_LIST_UNLOCK();
goto out_imo_free;
- }
+ }
+ inm_acquire(inm);
imo->imo_membership[idx] = inm;
} else {
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
@@ -2301,6 +2311,12 @@ out_in_multi_locked:
out_imo_free:
if (error && is_new) {
+ inm = imo->imo_membership[idx];
+ if (inm != NULL) {
+ IN_MULTI_LIST_LOCK();
+ inm_release_deferred(inm);
+ IN_MULTI_LIST_UNLOCK();
+ }
imo->imo_membership[idx] = NULL;
--imo->imo_num_memberships;
}
@@ -2494,6 +2510,7 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state",
__func__);
+ IN_MULTI_LIST_UNLOCK();
goto out_in_multi_locked;
}
@@ -2738,12 +2755,12 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
INP_WLOCK_ASSERT(inp);
IN_MULTI_LOCK();
- IN_MULTI_LIST_LOCK();
/*
* Begin state merge transaction at IGMP layer.
*/
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
+ IN_MULTI_LIST_LOCK();
error = inm_merge(inm, imf);
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c
index f89487b6..5ba918fa 100644
--- a/freebsd/sys/netinet/in_pcb.c
+++ b/freebsd/sys/netinet/in_pcb.c
@@ -114,6 +114,9 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
+#define INPCBLBGROUP_SIZMIN 8
+#define INPCBLBGROUP_SIZMAX 256
+
static struct callout ipport_tick_callout;
/*
@@ -141,7 +144,7 @@ VNET_DEFINE(int, ipport_randomcps) = 10; /* user controlled via sysctl */
VNET_DEFINE(int, ipport_randomtime) = 45; /* user controlled via sysctl */
VNET_DEFINE(int, ipport_stoprandom); /* toggled by ipport_tick */
VNET_DEFINE(int, ipport_tcpallocs);
-static VNET_DEFINE(int, ipport_tcplastcount);
+VNET_DEFINE_STATIC(int, ipport_tcplastcount);
#define V_ipport_tcplastcount VNET(ipport_tcplastcount)
@@ -223,6 +226,222 @@ SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime,
* functions often modify hash chains or addresses in pcbs.
*/
+static struct inpcblbgroup *
+in_pcblbgroup_alloc(struct inpcblbgrouphead *hdr, u_char vflag,
+ uint16_t port, const union in_dependaddr *addr, int size)
+{
+ struct inpcblbgroup *grp;
+ size_t bytes;
+
+ bytes = __offsetof(struct inpcblbgroup, il_inp[size]);
+ grp = malloc(bytes, M_PCB, M_ZERO | M_NOWAIT);
+ if (!grp)
+ return (NULL);
+ grp->il_vflag = vflag;
+ grp->il_lport = port;
+ grp->il_dependladdr = *addr;
+ grp->il_inpsiz = size;
+ CK_LIST_INSERT_HEAD(hdr, grp, il_list);
+ return (grp);
+}
+
+static void
+in_pcblbgroup_free_deferred(epoch_context_t ctx)
+{
+ struct inpcblbgroup *grp;
+
+ grp = __containerof(ctx, struct inpcblbgroup, il_epoch_ctx);
+ free(grp, M_PCB);
+}
+
+static void
+in_pcblbgroup_free(struct inpcblbgroup *grp)
+{
+
+ CK_LIST_REMOVE(grp, il_list);
+ epoch_call(net_epoch_preempt, &grp->il_epoch_ctx,
+ in_pcblbgroup_free_deferred);
+}
+
+static struct inpcblbgroup *
+in_pcblbgroup_resize(struct inpcblbgrouphead *hdr,
+ struct inpcblbgroup *old_grp, int size)
+{
+ struct inpcblbgroup *grp;
+ int i;
+
+ grp = in_pcblbgroup_alloc(hdr, old_grp->il_vflag,
+ old_grp->il_lport, &old_grp->il_dependladdr, size);
+ if (!grp)
+ return (NULL);
+
+ KASSERT(old_grp->il_inpcnt < grp->il_inpsiz,
+ ("invalid new local group size %d and old local group count %d",
+ grp->il_inpsiz, old_grp->il_inpcnt));
+
+ for (i = 0; i < old_grp->il_inpcnt; ++i)
+ grp->il_inp[i] = old_grp->il_inp[i];
+ grp->il_inpcnt = old_grp->il_inpcnt;
+ in_pcblbgroup_free(old_grp);
+ return (grp);
+}
+
+/*
+ * PCB at index 'i' is removed from the group. Pull up the ones below il_inp[i]
+ * and shrink group if possible.
+ */
+static void
+in_pcblbgroup_reorder(struct inpcblbgrouphead *hdr, struct inpcblbgroup **grpp,
+ int i)
+{
+ struct inpcblbgroup *grp = *grpp;
+
+ for (; i + 1 < grp->il_inpcnt; ++i)
+ grp->il_inp[i] = grp->il_inp[i + 1];
+ grp->il_inpcnt--;
+
+ if (grp->il_inpsiz > INPCBLBGROUP_SIZMIN &&
+ grp->il_inpcnt <= (grp->il_inpsiz / 4)) {
+ /* Shrink this group. */
+ struct inpcblbgroup *new_grp =
+ in_pcblbgroup_resize(hdr, grp, grp->il_inpsiz / 2);
+ if (new_grp)
+ *grpp = new_grp;
+ }
+ return;
+}
+
+/*
+ * Add PCB to load balance group for SO_REUSEPORT_LB option.
+ */
+static int
+in_pcbinslbgrouphash(struct inpcb *inp)
+{
+ const static struct timeval interval = { 60, 0 };
+ static struct timeval lastprint;
+ struct inpcbinfo *pcbinfo;
+ struct inpcblbgrouphead *hdr;
+ struct inpcblbgroup *grp;
+ uint16_t hashmask, lport;
+ uint32_t group_index;
+ struct ucred *cred;
+
+ pcbinfo = inp->inp_pcbinfo;
+
+ INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
+
+ if (pcbinfo->ipi_lbgrouphashbase == NULL)
+ return (0);
+
+ hashmask = pcbinfo->ipi_lbgrouphashmask;
+ lport = inp->inp_lport;
+ group_index = INP_PCBLBGROUP_PORTHASH(lport, hashmask);
+ hdr = &pcbinfo->ipi_lbgrouphashbase[group_index];
+
+ /*
+ * Don't allow jailed socket to join local group.
+ */
+ if (inp->inp_socket != NULL)
+ cred = inp->inp_socket->so_cred;
+ else
+ cred = NULL;
+ if (cred != NULL && jailed(cred))
+ return (0);
+
+#ifdef INET6
+ /*
+ * Don't allow IPv4 mapped INET6 wild socket.
+ */
+ if ((inp->inp_vflag & INP_IPV4) &&
+ inp->inp_laddr.s_addr == INADDR_ANY &&
+ INP_CHECK_SOCKAF(inp->inp_socket, AF_INET6)) {
+ return (0);
+ }
+#endif
+
+ hdr = &pcbinfo->ipi_lbgrouphashbase[
+ INP_PCBLBGROUP_PORTHASH(inp->inp_lport,
+ pcbinfo->ipi_lbgrouphashmask)];
+ CK_LIST_FOREACH(grp, hdr, il_list) {
+ if (grp->il_vflag == inp->inp_vflag &&
+ grp->il_lport == inp->inp_lport &&
+ memcmp(&grp->il_dependladdr,
+ &inp->inp_inc.inc_ie.ie_dependladdr,
+ sizeof(grp->il_dependladdr)) == 0) {
+ break;
+ }
+ }
+ if (grp == NULL) {
+ /* Create new load balance group. */
+ grp = in_pcblbgroup_alloc(hdr, inp->inp_vflag,
+ inp->inp_lport, &inp->inp_inc.inc_ie.ie_dependladdr,
+ INPCBLBGROUP_SIZMIN);
+ if (!grp)
+ return (ENOBUFS);
+ } else if (grp->il_inpcnt == grp->il_inpsiz) {
+ if (grp->il_inpsiz >= INPCBLBGROUP_SIZMAX) {
+ if (ratecheck(&lastprint, &interval))
+ printf("lb group port %d, limit reached\n",
+ ntohs(grp->il_lport));
+ return (0);
+ }
+
+ /* Expand this local group. */
+ grp = in_pcblbgroup_resize(hdr, grp, grp->il_inpsiz * 2);
+ if (!grp)
+ return (ENOBUFS);
+ }
+
+ KASSERT(grp->il_inpcnt < grp->il_inpsiz,
+ ("invalid local group size %d and count %d",
+ grp->il_inpsiz, grp->il_inpcnt));
+
+ grp->il_inp[grp->il_inpcnt] = inp;
+ grp->il_inpcnt++;
+ return (0);
+}
+
+/*
+ * Remove PCB from load balance group.
+ */
+static void
+in_pcbremlbgrouphash(struct inpcb *inp)
+{
+ struct inpcbinfo *pcbinfo;
+ struct inpcblbgrouphead *hdr;
+ struct inpcblbgroup *grp;
+ int i;
+
+ pcbinfo = inp->inp_pcbinfo;
+
+ INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
+
+ if (pcbinfo->ipi_lbgrouphashbase == NULL)
+ return;
+
+ hdr = &pcbinfo->ipi_lbgrouphashbase[
+ INP_PCBLBGROUP_PORTHASH(inp->inp_lport,
+ pcbinfo->ipi_lbgrouphashmask)];
+
+ CK_LIST_FOREACH(grp, hdr, il_list) {
+ for (i = 0; i < grp->il_inpcnt; ++i) {
+ if (grp->il_inp[i] != inp)
+ continue;
+
+ if (grp->il_inpcnt == 1) {
+ /* We are the last, free this local group. */
+ in_pcblbgroup_free(grp);
+ } else {
+ /* Pull up inpcbs, shrink group if possible. */
+ in_pcblbgroup_reorder(hdr, &grp, i);
+ }
+ return;
+ }
+ }
+}
+
/*
* Different protocols initialize their inpcbs differently - giving
* different name to the lock. But they all are disposed the same.
@@ -252,12 +471,14 @@ in_pcbinfo_init(struct inpcbinfo *pcbinfo, const char *name,
pcbinfo->ipi_vnet = curvnet;
#endif
pcbinfo->ipi_listhead = listhead;
- LIST_INIT(pcbinfo->ipi_listhead);
+ CK_LIST_INIT(pcbinfo->ipi_listhead);
pcbinfo->ipi_count = 0;
pcbinfo->ipi_hashbase = hashinit(hash_nelements, M_PCB,
&pcbinfo->ipi_hashmask);
pcbinfo->ipi_porthashbase = hashinit(porthash_nelements, M_PCB,
&pcbinfo->ipi_porthashmask);
+ pcbinfo->ipi_lbgrouphashbase = hashinit(hash_nelements, M_PCB,
+ &pcbinfo->ipi_lbgrouphashmask);
#ifdef PCBGROUP
in_pcbgroup_init(pcbinfo, hashfields, hash_nelements);
#endif
@@ -281,6 +502,8 @@ in_pcbinfo_destroy(struct inpcbinfo *pcbinfo)
hashdestroy(pcbinfo->ipi_hashbase, M_PCB, pcbinfo->ipi_hashmask);
hashdestroy(pcbinfo->ipi_porthashbase, M_PCB,
pcbinfo->ipi_porthashmask);
+ hashdestroy(pcbinfo->ipi_lbgrouphashbase, M_PCB,
+ pcbinfo->ipi_lbgrouphashmask);
#ifdef PCBGROUP
in_pcbgroup_destroy(pcbinfo);
#endif
@@ -341,7 +564,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
#endif
INP_WLOCK(inp);
INP_LIST_WLOCK(pcbinfo);
- LIST_INSERT_HEAD(pcbinfo->ipi_listhead, inp, inp_list);
+ CK_LIST_INSERT_HEAD(pcbinfo->ipi_listhead, inp, inp_list);
pcbinfo->ipi_count++;
so->so_pcb = (caddr_t)inp;
#ifdef INET6
@@ -519,18 +742,20 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
/*
* Return cached socket options.
*/
-short
+int
inp_so_options(const struct inpcb *inp)
{
- short so_options;
+ int so_options;
- so_options = 0;
+ so_options = 0;
- if ((inp->inp_flags2 & INP_REUSEPORT) != 0)
- so_options |= SO_REUSEPORT;
- if ((inp->inp_flags2 & INP_REUSEADDR) != 0)
- so_options |= SO_REUSEADDR;
- return (so_options);
+ if ((inp->inp_flags2 & INP_REUSEPORT_LB) != 0)
+ so_options |= SO_REUSEPORT_LB;
+ if ((inp->inp_flags2 & INP_REUSEPORT) != 0)
+ so_options |= SO_REUSEPORT;
+ if ((inp->inp_flags2 & INP_REUSEADDR) != 0)
+ so_options |= SO_REUSEADDR;
+ return (so_options);
}
#endif /* INET || INET6 */
@@ -589,6 +814,12 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
int error;
/*
+ * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here
+ * so that we don't have to add to the (already messy) code below.
+ */
+ int reuseport_lb = (so->so_options & SO_REUSEPORT_LB);
+
+ /*
* No state changes, so read locks are sufficient here.
*/
INP_LOCK_ASSERT(inp);
@@ -599,7 +830,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
laddr.s_addr = *laddrp;
if (nam != NULL && laddr.s_addr != INADDR_ANY)
return (EINVAL);
- if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
+ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0)
lookupflags = INPLOOKUP_WILDCARD;
if (nam == NULL) {
if ((error = prison_local_ip4(cred, &laddr)) != 0)
@@ -636,16 +867,23 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
*/
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0)
reuseport = SO_REUSEADDR|SO_REUSEPORT;
+ /*
+ * XXX: How to deal with SO_REUSEPORT_LB here?
+ * Treat same as SO_REUSEPORT for now.
+ */
+ if ((so->so_options &
+ (SO_REUSEADDR|SO_REUSEPORT_LB)) != 0)
+ reuseport_lb = SO_REUSEADDR|SO_REUSEPORT_LB;
} else if (sin->sin_addr.s_addr != INADDR_ANY) {
sin->sin_port = 0; /* yech... */
bzero(&sin->sin_zero, sizeof(sin->sin_zero));
/*
- * Is the address a local IP address?
+ * Is the address a local IP address?
* If INP_BINDANY is set, then the socket may be bound
* to any endpoint address, local or not.
*/
if ((inp->inp_flags & INP_BINDANY) == 0 &&
- ifa_ifwithaddr_check((struct sockaddr *)sin) == 0)
+ ifa_ifwithaddr_check((struct sockaddr *)sin) == 0)
return (EADDRNOTAVAIL);
}
laddr = sin->sin_addr;
@@ -675,7 +913,8 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
ntohl(t->inp_faddr.s_addr) == INADDR_ANY) &&
(ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
- (t->inp_flags2 & INP_REUSEPORT) == 0) &&
+ (t->inp_flags2 & INP_REUSEPORT) ||
+ (t->inp_flags2 & INP_REUSEPORT_LB) == 0) &&
#ifndef __rtems__
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
@@ -704,11 +943,15 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
*/
tw = intotw(t);
if (tw == NULL ||
- (reuseport & tw->tw_so_options) == 0)
+ ((reuseport & tw->tw_so_options) == 0 &&
+ (reuseport_lb &
+ tw->tw_so_options) == 0)) {
return (EADDRINUSE);
+ }
} else if (t &&
- ((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
- (reuseport & inp_so_options(t)) == 0) {
+ ((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
+ (reuseport & inp_so_options(t)) == 0 &&
+ (reuseport_lb & inp_so_options(t)) == 0) {
#ifdef INET6
if (ntohl(sin->sin_addr.s_addr) !=
INADDR_ANY ||
@@ -717,7 +960,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
(inp->inp_vflag & INP_IPV6PROTO) == 0 ||
(t->inp_vflag & INP_IPV6PROTO) == 0)
#endif
- return (EADDRINUSE);
+ return (EADDRINUSE);
if (t && (! in_pcbbind_check_bindmulti(inp, t)))
return (EADDRINUSE);
}
@@ -862,7 +1105,6 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
ifp = ia->ia_ifp;
ia = NULL;
- IF_ADDR_RLOCK(ifp);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
@@ -876,10 +1118,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
if (ia != NULL) {
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
- IF_ADDR_RUNLOCK(ifp);
goto done;
}
- IF_ADDR_RUNLOCK(ifp);
/* 3. As a last resort return the 'default' jail address. */
error = prison_get_ip4(cred, laddr);
@@ -921,7 +1161,6 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
*/
ia = NULL;
ifp = sro.ro_rt->rt_ifp;
- IF_ADDR_RLOCK(ifp);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET)
@@ -934,10 +1173,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
if (ia != NULL) {
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
- IF_ADDR_RUNLOCK(ifp);
goto done;
}
- IF_ADDR_RUNLOCK(ifp);
/* 3. As a last resort return the 'default' jail address. */
error = prison_get_ip4(cred, laddr);
@@ -985,9 +1222,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
ifp = ia->ia_ifp;
ia = NULL;
- IF_ADDR_RLOCK(ifp);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
-
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET)
continue;
@@ -1000,10 +1235,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
if (ia != NULL) {
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
- IF_ADDR_RUNLOCK(ifp);
goto done;
}
- IF_ADDR_RUNLOCK(ifp);
}
/* 3. As a last resort return the 'default' jail address. */
@@ -1347,6 +1580,58 @@ in_pcblist_rele_rlocked(epoch_context_t ctx)
free(il, M_TEMP);
}
+static void
+inpcbport_free(epoch_context_t ctx)
+{
+ struct inpcbport *phd;
+
+ phd = __containerof(ctx, struct inpcbport, phd_epoch_ctx);
+ free(phd, M_PCB);
+}
+
+static void
+in_pcbfree_deferred(epoch_context_t ctx)
+{
+ struct inpcb *inp;
+ int released __unused;
+
+ inp = __containerof(ctx, struct inpcb, inp_epoch_ctx);
+
+ INP_WLOCK(inp);
+#ifdef INET
+ struct ip_moptions *imo = inp->inp_moptions;
+ inp->inp_moptions = NULL;
+#endif
+ /* XXXRW: Do as much as possible here. */
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ if (inp->inp_sp != NULL)
+ ipsec_delete_pcbpolicy(inp);
+#endif
+#ifdef INET6
+ struct ip6_moptions *im6o = NULL;
+ if (inp->inp_vflag & INP_IPV6PROTO) {
+ ip6_freepcbopts(inp->in6p_outputopts);
+ im6o = inp->in6p_moptions;
+ inp->in6p_moptions = NULL;
+ }
+#endif
+ if (inp->inp_options)
+ (void)m_free(inp->inp_options);
+ inp->inp_vflag = 0;
+ crfree(inp->inp_cred);
+#ifdef MAC
+ mac_inpcb_destroy(inp);
+#endif
+ released = in_pcbrele_wlocked(inp);
+ MPASS(released);
+#ifdef INET6
+ ip6_freemoptions(im6o);
+#endif
+#ifdef INET
+ inp_freemoptions(imo);
+#endif
+}
+
/*
* Unconditionally schedule an inpcb to be freed by decrementing its
* reference count, which should occur only after the inpcb has been detached
@@ -1361,14 +1646,7 @@ in_pcbfree(struct inpcb *inp)
{
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
-#ifdef INET6
- struct ip6_moptions *im6o = NULL;
-#endif
-#ifdef INET
- struct ip_moptions *imo = NULL;
-#endif
KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
-
KASSERT((inp->inp_flags2 & INP_FREED) == 0,
("%s: called twice for pcb %p", __func__, inp));
if (inp->inp_flags2 & INP_FREED) {
@@ -1384,45 +1662,14 @@ in_pcbfree(struct inpcb *inp)
}
#endif
INP_WLOCK_ASSERT(inp);
-
-#ifdef INET
- imo = inp->inp_moptions;
- inp->inp_moptions = NULL;
-#endif
- /* XXXRW: Do as much as possible here. */
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
- if (inp->inp_sp != NULL)
- ipsec_delete_pcbpolicy(inp);
-#endif
INP_LIST_WLOCK(pcbinfo);
- inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
in_pcbremlists(inp);
INP_LIST_WUNLOCK(pcbinfo);
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO) {
- ip6_freepcbopts(inp->in6p_outputopts);
- im6o = inp->in6p_moptions;
- inp->in6p_moptions = NULL;
- }
-#endif
- if (inp->inp_options)
- (void)m_free(inp->inp_options);
RO_INVALIDATE_CACHE(&inp->inp_route);
-
- inp->inp_vflag = 0;
+ /* mark as destruction in progress */
inp->inp_flags2 |= INP_FREED;
- crfree(inp->inp_cred);
-#ifdef MAC
- mac_inpcb_destroy(inp);
-#endif
-#ifdef INET6
- ip6_freemoptions(im6o);
-#endif
-#ifdef INET
- inp_freemoptions(imo);
-#endif
- if (!in_pcbrele_wlocked(inp))
- INP_WUNLOCK(inp);
+ INP_WUNLOCK(inp);
+ epoch_call(net_epoch_preempt, &inp->inp_epoch_ctx, in_pcbfree_deferred);
}
/*
@@ -1444,6 +1691,10 @@ in_pcbdrop(struct inpcb *inp)
{
INP_WLOCK_ASSERT(inp);
+#ifdef INVARIANTS
+ if (inp->inp_socket != NULL && inp->inp_ppcb != NULL)
+ MPASS(inp->inp_refcount > 1);
+#endif
/*
* XXXRW: Possibly we should protect the setting of INP_DROPPED with
@@ -1454,11 +1705,12 @@ in_pcbdrop(struct inpcb *inp)
struct inpcbport *phd = inp->inp_phd;
INP_HASH_WLOCK(inp->inp_pcbinfo);
- LIST_REMOVE(inp, inp_hash);
- LIST_REMOVE(inp, inp_portlist);
- if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
- LIST_REMOVE(phd, phd_hash);
- free(phd, M_PCB);
+ in_pcbremlbgrouphash(inp);
+ CK_LIST_REMOVE(inp, inp_hash);
+ CK_LIST_REMOVE(inp, inp_portlist);
+ if (CK_LIST_FIRST(&phd->phd_pcblist) == NULL) {
+ CK_LIST_REMOVE(phd, phd_hash);
+ epoch_call(net_epoch_preempt, &phd->phd_epoch_ctx, inpcbport_free);
}
INP_HASH_WUNLOCK(inp->inp_pcbinfo);
inp->inp_flags &= ~INP_INHASHLIST;
@@ -1532,7 +1784,7 @@ in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr faddr, int errno,
struct inpcb *inp, *inp_temp;
INP_INFO_WLOCK(pcbinfo);
- LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
+ CK_LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
INP_WLOCK(inp);
#ifdef INET6
if ((inp->inp_vflag & INP_IPV4) == 0) {
@@ -1559,7 +1811,7 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
int i, gap;
INP_INFO_WLOCK(pcbinfo);
- LIST_FOREACH(inp, pcbinfo->ipi_listhead, inp_list) {
+ CK_LIST_FOREACH(inp, pcbinfo->ipi_listhead, inp_list) {
INP_WLOCK(inp);
imo = inp->inp_moptions;
if ((inp->inp_vflag & INP_IPV4) &&
@@ -1624,7 +1876,7 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
*/
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
0, pcbinfo->ipi_hashmask)];
- LIST_FOREACH(inp, head, inp_hash) {
+ CK_LIST_FOREACH(inp, head, inp_hash) {
#ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0)
@@ -1658,7 +1910,7 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
*/
porthash = &pcbinfo->ipi_porthashbase[INP_PCBPORTHASH(lport,
pcbinfo->ipi_porthashmask)];
- LIST_FOREACH(phd, porthash, phd_hash) {
+ CK_LIST_FOREACH(phd, porthash, phd_hash) {
if (phd->phd_port == lport)
break;
}
@@ -1667,7 +1919,7 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
* Port is in use by one or more PCBs. Look for best
* fit.
*/
- LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
+ CK_LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
wildcard = 0;
if (cred != NULL &&
!prison_equal_ip4(inp->inp_cred->cr_prison,
@@ -1717,6 +1969,50 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
}
#undef INP_LOOKUP_MAPPED_PCB_COST
+static struct inpcb *
+in_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo,
+ const struct in_addr *laddr, uint16_t lport, const struct in_addr *faddr,
+ uint16_t fport, int lookupflags)
+{
+ struct inpcb *local_wild;
+ const struct inpcblbgrouphead *hdr;
+ struct inpcblbgroup *grp;
+ uint32_t idx;
+
+ INP_HASH_LOCK_ASSERT(pcbinfo);
+
+ hdr = &pcbinfo->ipi_lbgrouphashbase[INP_PCBLBGROUP_PORTHASH(lport,
+ pcbinfo->ipi_lbgrouphashmask)];
+
+ /*
+ * Order of socket selection:
+ * 1. non-wild.
+ * 2. wild (if lookupflags contains INPLOOKUP_WILDCARD).
+ *
+ * NOTE:
+ * - Load balanced group does not contain jailed sockets
+ * - Load balanced group does not contain IPv4 mapped INET6 wild sockets
+ */
+ local_wild = NULL;
+ CK_LIST_FOREACH(grp, hdr, il_list) {
+#ifdef INET6
+ if (!(grp->il_vflag & INP_IPV4))
+ continue;
+#endif
+ if (grp->il_lport != lport)
+ continue;
+
+ idx = INP_PCBLBGROUP_PKTHASH(faddr->s_addr, lport, fport) %
+ grp->il_inpcnt;
+ if (grp->il_laddr.s_addr == laddr->s_addr)
+ return (grp->il_inp[idx]);
+ if (grp->il_laddr.s_addr == INADDR_ANY &&
+ (lookupflags & INPLOOKUP_WILDCARD) != 0)
+ local_wild = grp->il_inp[idx];
+ }
+ return (local_wild);
+}
+
#ifdef PCBGROUP
/*
* Lookup PCB in hash list, using pcbgroup tables.
@@ -1738,7 +2034,7 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
INP_GROUP_LOCK(pcbgroup);
head = &pcbgroup->ipg_hashbase[INP_PCBHASH(faddr.s_addr, lport, fport,
pcbgroup->ipg_hashmask)];
- LIST_FOREACH(inp, head, inp_pcbgrouphash) {
+ CK_LIST_FOREACH(inp, head, inp_pcbgrouphash) {
#ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0)
@@ -1788,7 +2084,7 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
head = &pcbgroup->ipg_hashbase[INP_PCBHASH(INADDR_ANY,
lport, 0, pcbgroup->ipg_hashmask)];
- LIST_FOREACH(inp, head, inp_pcbgrouphash) {
+ CK_LIST_FOREACH(inp, head, inp_pcbgrouphash) {
#ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0)
@@ -1862,7 +2158,7 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
*/
head = &pcbinfo->ipi_wildbase[INP_PCBHASH(INADDR_ANY, lport,
0, pcbinfo->ipi_wildmask)];
- LIST_FOREACH(inp, head, inp_pcbgroup_wild) {
+ CK_LIST_FOREACH(inp, head, inp_pcbgroup_wild) {
#ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0)
@@ -1922,7 +2218,13 @@ found:
locked = INP_TRY_RLOCK(inp);
else
panic("%s: locking bug", __func__);
- if (!locked)
+ if (__predict_false(locked && (inp->inp_flags2 & INP_FREED))) {
+ if (lookupflags & INPLOOKUP_WLOCKPCB)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
+ return (NULL);
+ } else if (!locked)
in_pcbref(inp);
INP_GROUP_UNLOCK(pcbgroup);
if (!locked) {
@@ -1960,18 +2262,19 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr,
struct inpcb *inp, *tmpinp;
u_short fport = fport_arg, lport = lport_arg;
+#ifdef INVARIANTS
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
-
- INP_HASH_LOCK_ASSERT(pcbinfo);
-
+ if (!mtx_owned(&pcbinfo->ipi_hash_lock))
+ MPASS(in_epoch_verbose(net_epoch_preempt, 1));
+#endif
/*
* First look for an exact match.
*/
tmpinp = NULL;
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(faddr.s_addr, lport, fport,
pcbinfo->ipi_hashmask)];
- LIST_FOREACH(inp, head, inp_hash) {
+ CK_LIST_FOREACH(inp, head, inp_hash) {
#ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0)
@@ -1996,6 +2299,18 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr,
return (tmpinp);
/*
+ * Then look in lb group (for wildcard match).
+ */
+ if (pcbinfo->ipi_lbgrouphashbase != NULL &&
+ (lookupflags & INPLOOKUP_WILDCARD)) {
+ inp = in_pcblookup_lbgroup(pcbinfo, &laddr, lport, &faddr,
+ fport, lookupflags);
+ if (inp != NULL) {
+ return (inp);
+ }
+ }
+
+ /*
* Then look for a wildcard match, if requested.
*/
if ((lookupflags & INPLOOKUP_WILDCARD) != 0) {
@@ -2016,7 +2331,7 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr,
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
0, pcbinfo->ipi_hashmask)];
- LIST_FOREACH(inp, head, inp_hash) {
+ CK_LIST_FOREACH(inp, head, inp_hash) {
#ifdef INET6
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV4) == 0)
@@ -2080,40 +2395,35 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
struct ifnet *ifp)
{
struct inpcb *inp;
- bool locked;
INP_HASH_RLOCK(pcbinfo);
inp = in_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
(lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
if (inp != NULL) {
- if (lookupflags & INPLOOKUP_WLOCKPCB)
- locked = INP_TRY_WLOCK(inp);
- else if (lookupflags & INPLOOKUP_RLOCKPCB)
- locked = INP_TRY_RLOCK(inp);
- else
- panic("%s: locking bug", __func__);
- if (!locked)
- in_pcbref(inp);
- INP_HASH_RUNLOCK(pcbinfo);
- if (!locked) {
- if (lookupflags & INPLOOKUP_WLOCKPCB) {
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (NULL);
- } else {
- INP_RLOCK(inp);
- if (in_pcbrele_rlocked(inp))
- return (NULL);
+ if (lookupflags & INPLOOKUP_WLOCKPCB) {
+ INP_WLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_WUNLOCK(inp);
+ inp = NULL;
}
- }
+ } else if (lookupflags & INPLOOKUP_RLOCKPCB) {
+ INP_RLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_RUNLOCK(inp);
+ inp = NULL;
+ }
+ } else
+ panic("%s: locking bug", __func__);
#ifdef INVARIANTS
- if (lookupflags & INPLOOKUP_WLOCKPCB)
- INP_WLOCK_ASSERT(inp);
- else
- INP_RLOCK_ASSERT(inp);
+ if (inp != NULL) {
+ if (lookupflags & INPLOOKUP_WLOCKPCB)
+ INP_WLOCK_ASSERT(inp);
+ else
+ INP_RLOCK_ASSERT(inp);
+ }
#endif
- } else
- INP_HASH_RUNLOCK(pcbinfo);
+ }
+ INP_HASH_RUNLOCK(pcbinfo);
return (inp);
}
@@ -2212,6 +2522,7 @@ in_pcbinshash_internal(struct inpcb *inp, int do_pcbgroup_update)
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
struct inpcbport *phd;
u_int32_t hashkey_faddr;
+ int so_options;
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(pcbinfo);
@@ -2233,9 +2544,22 @@ in_pcbinshash_internal(struct inpcb *inp, int do_pcbgroup_update)
INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_porthashmask)];
/*
+ * Add entry to load balance group.
+ * Only do this if SO_REUSEPORT_LB is set.
+ */
+ so_options = inp_so_options(inp);
+ if (so_options & SO_REUSEPORT_LB) {
+ int ret = in_pcbinslbgrouphash(inp);
+ if (ret) {
+ /* pcb lb group malloc fail (ret=ENOBUFS). */
+ return (ret);
+ }
+ }
+
+ /*
* Go through port list and look for a head for this lport.
*/
- LIST_FOREACH(phd, pcbporthash, phd_hash) {
+ CK_LIST_FOREACH(phd, pcbporthash, phd_hash) {
if (phd->phd_port == inp->inp_lport)
break;
}
@@ -2247,13 +2571,14 @@ in_pcbinshash_internal(struct inpcb *inp, int do_pcbgroup_update)
if (phd == NULL) {
return (ENOBUFS); /* XXX */
}
+ bzero(&phd->phd_epoch_ctx, sizeof(struct epoch_context));
phd->phd_port = inp->inp_lport;
- LIST_INIT(&phd->phd_pcblist);
- LIST_INSERT_HEAD(pcbporthash, phd, phd_hash);
+ CK_LIST_INIT(&phd->phd_pcblist);
+ CK_LIST_INSERT_HEAD(pcbporthash, phd, phd_hash);
}
inp->inp_phd = phd;
- LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist);
- LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
+ CK_LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist);
+ CK_LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
inp->inp_flags |= INP_INHASHLIST;
#ifdef PCBGROUP
if (do_pcbgroup_update)
@@ -2316,8 +2641,8 @@ in_pcbrehash_mbuf(struct inpcb *inp, struct mbuf *m)
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(hashkey_faddr,
inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)];
- LIST_REMOVE(inp, inp_hash);
- LIST_INSERT_HEAD(head, inp, inp_hash);
+ CK_LIST_REMOVE(inp, inp_hash);
+ CK_LIST_INSERT_HEAD(head, inp, inp_hash);
#ifdef PCBGROUP
if (m != NULL)
@@ -2358,16 +2683,20 @@ in_pcbremlists(struct inpcb *inp)
struct inpcbport *phd = inp->inp_phd;
INP_HASH_WLOCK(pcbinfo);
- LIST_REMOVE(inp, inp_hash);
- LIST_REMOVE(inp, inp_portlist);
- if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
- LIST_REMOVE(phd, phd_hash);
- free(phd, M_PCB);
+
+ /* XXX: Only do if SO_REUSEPORT_LB set? */
+ in_pcbremlbgrouphash(inp);
+
+ CK_LIST_REMOVE(inp, inp_hash);
+ CK_LIST_REMOVE(inp, inp_portlist);
+ if (CK_LIST_FIRST(&phd->phd_pcblist) == NULL) {
+ CK_LIST_REMOVE(phd, phd_hash);
+ epoch_call(net_epoch_preempt, &phd->phd_epoch_ctx, inpcbport_free);
}
INP_HASH_WUNLOCK(pcbinfo);
inp->inp_flags &= ~INP_INHASHLIST;
}
- LIST_REMOVE(inp, inp_list);
+ CK_LIST_REMOVE(inp, inp_list);
pcbinfo->ipi_count--;
#ifdef PCBGROUP
in_pcbgroup_remove(inp);
@@ -2511,7 +2840,7 @@ inp_apply_all(void (*func)(struct inpcb *, void *), void *arg)
struct inpcb *inp;
INP_INFO_WLOCK(&V_tcbinfo);
- LIST_FOREACH(inp, V_tcbinfo.ipi_listhead, inp_list) {
+ CK_LIST_FOREACH(inp, V_tcbinfo.ipi_listhead, inp_list) {
INP_WLOCK(inp);
func(inp, arg);
INP_WUNLOCK(inp);
@@ -2594,7 +2923,7 @@ in_pcbtoxinpcb(const struct inpcb *inp, struct xinpcb *xi)
bzero(&xi->xi_socket, sizeof(struct xsocket));
bcopy(&inp->inp_inc, &xi->inp_inc, sizeof(struct in_conninfo));
xi->inp_gencnt = inp->inp_gencnt;
- xi->inp_ppcb = inp->inp_ppcb;
+ xi->inp_ppcb = (uintptr_t)inp->inp_ppcb;
xi->inp_flow = inp->inp_flow;
xi->inp_flowid = inp->inp_flowid;
xi->inp_flowtype = inp->inp_flowtype;
diff --git a/freebsd/sys/netinet/in_pcb.h b/freebsd/sys/netinet/in_pcb.h
index d00dd456..86c9705c 100644
--- a/freebsd/sys/netinet/in_pcb.h
+++ b/freebsd/sys/netinet/in_pcb.h
@@ -51,8 +51,11 @@
#include <sys/lock.h>
#include <sys/rwlock.h>
#include <net/vnet.h>
+#include <net/if.h>
+#include <net/if_var.h>
#include <vm/uma.h>
#endif
+#include <sys/ck.h>
#define in6pcb inpcb /* for KAME src sync over BSD*'s */
#define in6p_sp inp_sp /* for KAME src sync over BSD*'s */
@@ -65,8 +68,9 @@
* numbers, and pointers up (to a socket structure) and down (to a
* protocol-specific control block) are stored here.
*/
-LIST_HEAD(inpcbhead, inpcb);
-LIST_HEAD(inpcbporthead, inpcbport);
+CK_LIST_HEAD(inpcbhead, inpcb);
+CK_LIST_HEAD(inpcbporthead, inpcbport);
+CK_LIST_HEAD(inpcblbgrouphead, inpcblbgroup);
typedef uint64_t inp_gen_t;
/*
@@ -79,6 +83,11 @@ struct in_addr_4in6 {
struct in_addr ia46_addr4;
};
+union in_dependaddr {
+ struct in_addr_4in6 id46_addr;
+ struct in6_addr id6_addr;
+};
+
/*
* NOTE: ipv6 addrs should be 64-bit aligned, per RFC 2553. in_conninfo has
* some extra padding to accomplish this.
@@ -89,22 +98,14 @@ struct in_endpoints {
u_int16_t ie_fport; /* foreign port */
u_int16_t ie_lport; /* local port */
/* protocol dependent part, local and foreign addr */
- union {
- /* foreign host table entry */
- struct in_addr_4in6 ie46_foreign;
- struct in6_addr ie6_foreign;
- } ie_dependfaddr;
- union {
- /* local host table entry */
- struct in_addr_4in6 ie46_local;
- struct in6_addr ie6_local;
- } ie_dependladdr;
+ union in_dependaddr ie_dependfaddr; /* foreign host table entry */
+ union in_dependaddr ie_dependladdr; /* local host table entry */
+#define ie_faddr ie_dependfaddr.id46_addr.ia46_addr4
+#define ie_laddr ie_dependladdr.id46_addr.ia46_addr4
+#define ie6_faddr ie_dependfaddr.id6_addr
+#define ie6_laddr ie_dependladdr.id6_addr
u_int32_t ie6_zoneid; /* scope zone id */
};
-#define ie_faddr ie_dependfaddr.ie46_foreign.ia46_addr4
-#define ie_laddr ie_dependladdr.ie46_local.ia46_addr4
-#define ie6_faddr ie_dependfaddr.ie6_foreign
-#define ie6_laddr ie_dependladdr.ie6_local
/*
* XXX The defines for inc_* are hacks and should be changed to direct
@@ -122,8 +123,8 @@ struct in_conninfo {
* Flags for inc_flags.
*/
#define INC_ISIPV6 0x01
+#define INC_IPV6MINMTU 0x02
-#define inc_isipv6 inc_flags /* temp compatibility */
#define inc_fport inc_ie.ie_fport
#define inc_lport inc_ie.ie_lport
#define inc_faddr inc_ie.ie_faddr
@@ -159,6 +160,7 @@ struct in_conninfo {
* Key:
* (b) - Protected by the hpts lock.
* (c) - Constant after initialization
+ * (e) - Protected by the net_epoch_prempt epoch
* (g) - Protected by the pcbgroup lock
* (i) - Protected by the inpcb lock
* (p) - Protected by the pcbinfo lock for the inpcb
@@ -233,8 +235,8 @@ struct inpcbpolicy;
struct m_snd_tag;
struct inpcb {
/* Cache line #1 (amd64) */
- LIST_ENTRY(inpcb) inp_hash; /* (h/i) hash list */
- LIST_ENTRY(inpcb) inp_pcbgrouphash; /* (g/i) hash list */
+ CK_LIST_ENTRY(inpcb) inp_hash; /* [w](h/i) [r](e/i) hash list */
+ CK_LIST_ENTRY(inpcb) inp_pcbgrouphash; /* (g/i) hash list */
struct rwlock inp_lock;
/* Cache line #2 (amd64) */
#define inp_start_zero inp_hpts
@@ -278,7 +280,7 @@ struct inpcb {
TAILQ_ENTRY(inpcb) inp_input; /* pacing in queue next lock(b) */
struct inpcbinfo *inp_pcbinfo; /* (c) PCB list info */
struct inpcbgroup *inp_pcbgroup; /* (g/i) PCB group list */
- LIST_ENTRY(inpcb) inp_pcbgroup_wild; /* (g/i/h) group wildcard entry */
+ CK_LIST_ENTRY(inpcb) inp_pcbgroup_wild; /* (g/i/h) group wildcard entry */
struct ucred *inp_cred; /* (c) cache of socket cred */
u_int32_t inp_flow; /* (i) IPv6 flow information */
u_char inp_vflag; /* (i) IP version flag (v4/v6) */
@@ -316,18 +318,19 @@ struct inpcb {
int in6p_cksum;
short in6p_hops;
};
- LIST_ENTRY(inpcb) inp_portlist; /* (i/h) */
+ CK_LIST_ENTRY(inpcb) inp_portlist; /* (i/h) */
struct inpcbport *inp_phd; /* (i/h) head of this list */
inp_gen_t inp_gencnt; /* (c) generation count */
- struct llentry *inp_lle; /* cached L2 information */
+ void *spare_ptr; /* Spare pointer. */
rt_gen_t inp_rt_cookie; /* generation for route entry */
union { /* cached L3 information */
struct route inp_route;
struct route_in6 inp_route6;
};
- LIST_ENTRY(inpcb) inp_list; /* (p/l) list for all PCBs for proto */
- /* (p[w]) for list iteration */
- /* (p[r]/l) for addition/removal */
+ CK_LIST_ENTRY(inpcb) inp_list; /* (p/l) list for all PCBs for proto */
+ /* (e[r]) for list iteration */
+ /* (p[w]/l) for addition/removal */
+ struct epoch_context inp_epoch_ctx;
};
#endif /* _KERNEL */
@@ -364,14 +367,11 @@ struct inpcb {
*/
#ifdef _SYS_SOCKETVAR_H_
struct xinpcb {
- size_t xi_len; /* length of this structure */
+ ksize_t xi_len; /* length of this structure */
struct xsocket xi_socket; /* (s,p) */
struct in_conninfo inp_inc; /* (s,p) */
uint64_t inp_gencnt; /* (s,p) */
- union {
- void *inp_ppcb; /* (s) netstat(1) */
- int64_t ph_ppcb;
- };
+ kvaddr_t inp_ppcb; /* (s) netstat(1) */
int64_t inp_spare64[4];
uint32_t inp_flow; /* (s) */
uint32_t inp_flowid; /* (s) */
@@ -392,10 +392,12 @@ struct xinpcb {
} __aligned(8);
struct xinpgen {
- size_t xig_len; /* length of this structure */
+ ksize_t xig_len; /* length of this structure */
u_int xig_count; /* number of PCBs at this time */
+ uint32_t _xig_spare32;
inp_gen_t xig_gen; /* generation count at this time */
so_gen_t xig_sogen; /* socket generation count this time */
+ uint64_t _xig_spare64[4];
} __aligned(8);
#ifdef _KERNEL
void in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *);
@@ -403,7 +405,8 @@ void in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *);
#endif /* _SYS_SOCKETVAR_H_ */
struct inpcbport {
- LIST_ENTRY(inpcbport) phd_hash;
+ struct epoch_context phd_epoch_ctx;
+ CK_LIST_ENTRY(inpcbport) phd_hash;
struct inpcbhead phd_pcblist;
u_short phd_port;
};
@@ -436,22 +439,23 @@ struct in_pcblist {
* Locking key:
*
* (c) Constant or nearly constant after initialisation
+ * (e) - Protected by the net_epoch_prempt epoch
* (g) Locked by ipi_lock
* (l) Locked by ipi_list_lock
- * (h) Read using either ipi_hash_lock or inpcb lock; write requires both
+ * (h) Read using either net_epoch_preempt or inpcb lock; write requires both ipi_hash_lock and inpcb lock
* (p) Protected by one or more pcbgroup locks
* (x) Synchronisation properties poorly defined
*/
struct inpcbinfo {
/*
- * Global lock protecting full inpcb list traversal
+ * Global lock protecting inpcb list modification
*/
- struct rwlock ipi_lock;
+ struct mtx ipi_lock;
/*
* Global list of inpcbs on the protocol.
*/
- struct inpcbhead *ipi_listhead; /* (g/l) */
+ struct inpcbhead *ipi_listhead; /* [r](e) [w](g/l) */
u_int ipi_count; /* (l) */
/*
@@ -482,9 +486,9 @@ struct inpcbinfo {
u_int ipi_hashfields; /* (c) */
/*
- * Global lock protecting non-pcbgroup hash lookup tables.
+ * Global lock protecting modification non-pcbgroup hash lookup tables.
*/
- struct rwlock ipi_hash_lock;
+ struct mtx ipi_hash_lock;
/*
* Global hash of inpcbs, hashed by local and foreign addresses and
@@ -508,6 +512,13 @@ struct inpcbinfo {
u_long ipi_wildmask; /* (p) */
/*
+ * Load balance groups used for the SO_REUSEPORT_LB option,
+ * hashed by local port.
+ */
+ struct inpcblbgrouphead *ipi_lbgrouphashbase; /* (h) */
+ u_long ipi_lbgrouphashmask; /* (h) */
+
+ /*
* Pointer to network stack instance
*/
struct vnet *ipi_vnet; /* (c) */
@@ -549,6 +560,27 @@ struct inpcbgroup {
struct mtx ipg_lock;
} __aligned(CACHE_LINE_SIZE);
+/*
+ * Load balance groups used for the SO_REUSEPORT_LB socket option. Each group
+ * (or unique address:port combination) can be re-used at most
+ * INPCBLBGROUP_SIZMAX (256) times. The inpcbs are stored in il_inp which
+ * is dynamically resized as processes bind/unbind to that specific group.
+ */
+struct inpcblbgroup {
+ CK_LIST_ENTRY(inpcblbgroup) il_list;
+ struct epoch_context il_epoch_ctx;
+ uint16_t il_lport; /* (c) */
+ u_char il_vflag; /* (c) */
+ u_char il_pad;
+ uint32_t il_pad2;
+ union in_dependaddr il_dependladdr; /* (c) */
+#define il_laddr il_dependladdr.id46_addr.ia46_addr4
+#define il6_laddr il_dependladdr.id6_addr
+ uint32_t il_inpsiz; /* max count in il_inp[] (h) */
+ uint32_t il_inpcnt; /* cur count in il_inp[] (h) */
+ struct inpcb *il_inp[]; /* (h) */
+};
+
#define INP_LOCK_INIT(inp, d, t) \
rw_init_flags(&(inp)->inp_lock, (t), RW_RECURSE | RW_DUPOK)
#define INP_LOCK_DESTROY(inp) rw_destroy(&(inp)->inp_lock)
@@ -593,25 +625,24 @@ struct tcpcb *
inp_inpcbtotcpcb(struct inpcb *inp);
void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
uint32_t *faddr, uint16_t *fp);
-short inp_so_options(const struct inpcb *inp);
+int inp_so_options(const struct inpcb *inp);
#endif /* _KERNEL */
#define INP_INFO_LOCK_INIT(ipi, d) \
- rw_init_flags(&(ipi)->ipi_lock, (d), RW_RECURSE)
-#define INP_INFO_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_lock)
-#define INP_INFO_RLOCK(ipi) rw_rlock(&(ipi)->ipi_lock)
-#define INP_INFO_WLOCK(ipi) rw_wlock(&(ipi)->ipi_lock)
-#define INP_INFO_TRY_RLOCK(ipi) rw_try_rlock(&(ipi)->ipi_lock)
-#define INP_INFO_TRY_WLOCK(ipi) rw_try_wlock(&(ipi)->ipi_lock)
-#define INP_INFO_TRY_UPGRADE(ipi) rw_try_upgrade(&(ipi)->ipi_lock)
-#define INP_INFO_WLOCKED(ipi) rw_wowned(&(ipi)->ipi_lock)
-#define INP_INFO_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_lock)
-#define INP_INFO_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_lock)
-#define INP_INFO_LOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_LOCKED)
-#define INP_INFO_RLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_RLOCKED)
-#define INP_INFO_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_WLOCKED)
-#define INP_INFO_UNLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_UNLOCKED)
+ mtx_init(&(ipi)->ipi_lock, (d), NULL, MTX_DEF| MTX_RECURSE)
+#define INP_INFO_LOCK_DESTROY(ipi) mtx_destroy(&(ipi)->ipi_lock)
+#define INP_INFO_RLOCK_ET(ipi, et) NET_EPOCH_ENTER_ET((et))
+#define INP_INFO_WLOCK(ipi) mtx_lock(&(ipi)->ipi_lock)
+#define INP_INFO_TRY_WLOCK(ipi) mtx_trylock(&(ipi)->ipi_lock)
+#define INP_INFO_WLOCKED(ipi) mtx_owned(&(ipi)->ipi_lock)
+#define INP_INFO_RUNLOCK_ET(ipi, et) NET_EPOCH_EXIT_ET((et))
+#define INP_INFO_RUNLOCK_TP(ipi, tp) NET_EPOCH_EXIT_ET(*(tp)->t_inpcb->inp_et)
+#define INP_INFO_WUNLOCK(ipi) mtx_unlock(&(ipi)->ipi_lock)
+#define INP_INFO_LOCK_ASSERT(ipi) MPASS(in_epoch(net_epoch_preempt) || mtx_owned(&(ipi)->ipi_lock))
+#define INP_INFO_RLOCK_ASSERT(ipi) MPASS(in_epoch(net_epoch_preempt))
+#define INP_INFO_WLOCK_ASSERT(ipi) mtx_assert(&(ipi)->ipi_lock, MA_OWNED)
+#define INP_INFO_UNLOCK_ASSERT(ipi) MPASS(!in_epoch(net_epoch_preempt) && !mtx_owned(&(ipi)->ipi_lock))
#define INP_LIST_LOCK_INIT(ipi, d) \
rw_init_flags(&(ipi)->ipi_list_lock, (d), 0)
@@ -632,17 +663,16 @@ short inp_so_options(const struct inpcb *inp);
#define INP_LIST_UNLOCK_ASSERT(ipi) \
rw_assert(&(ipi)->ipi_list_lock, RA_UNLOCKED)
-#define INP_HASH_LOCK_INIT(ipi, d) \
- rw_init_flags(&(ipi)->ipi_hash_lock, (d), 0)
-#define INP_HASH_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_hash_lock)
-#define INP_HASH_RLOCK(ipi) rw_rlock(&(ipi)->ipi_hash_lock)
-#define INP_HASH_WLOCK(ipi) rw_wlock(&(ipi)->ipi_hash_lock)
-#define INP_HASH_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_hash_lock)
-#define INP_HASH_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_hash_lock)
-#define INP_HASH_LOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_hash_lock, \
- RA_LOCKED)
-#define INP_HASH_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_hash_lock, \
- RA_WLOCKED)
+#define INP_HASH_LOCK_INIT(ipi, d) mtx_init(&(ipi)->ipi_hash_lock, (d), NULL, MTX_DEF)
+#define INP_HASH_LOCK_DESTROY(ipi) mtx_destroy(&(ipi)->ipi_hash_lock)
+#define INP_HASH_RLOCK(ipi) struct epoch_tracker inp_hash_et; epoch_enter_preempt(net_epoch_preempt, &inp_hash_et)
+#define INP_HASH_RLOCK_ET(ipi, et) epoch_enter_preempt(net_epoch_preempt, &(et))
+#define INP_HASH_WLOCK(ipi) mtx_lock(&(ipi)->ipi_hash_lock)
+#define INP_HASH_RUNLOCK(ipi) NET_EPOCH_EXIT_ET(inp_hash_et)
+#define INP_HASH_RUNLOCK_ET(ipi, et) NET_EPOCH_EXIT_ET((et))
+#define INP_HASH_WUNLOCK(ipi) mtx_unlock(&(ipi)->ipi_hash_lock)
+#define INP_HASH_LOCK_ASSERT(ipi) MPASS(in_epoch(net_epoch_preempt) || mtx_owned(&(ipi)->ipi_hash_lock))
+#define INP_HASH_WLOCK_ASSERT(ipi) mtx_assert(&(ipi)->ipi_hash_lock, MA_OWNED);
#define INP_GROUP_LOCK_INIT(ipg, d) mtx_init(&(ipg)->ipg_lock, (d), NULL, \
MTX_DEF | MTX_DUPOK)
@@ -656,6 +686,10 @@ short inp_so_options(const struct inpcb *inp);
(((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport))) & (mask))
#define INP_PCBPORTHASH(lport, mask) \
(ntohs((lport)) & (mask))
+#define INP_PCBLBGROUP_PORTHASH(lport, mask) \
+ (ntohs((lport)) & (mask))
+#define INP_PCBLBGROUP_PKTHASH(faddr, lport, fport) \
+ ((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport)))
#define INP6_PCBHASHKEY(faddr) ((faddr)->s6_addr32[3])
/*
@@ -711,8 +745,8 @@ short inp_so_options(const struct inpcb *inp);
/*
* Flags for inp_flags2.
*/
-#define INP_LLE_VALID 0x00000001 /* cached lle is valid */
-#define INP_RT_VALID 0x00000002 /* cached rtentry is valid */
+#define INP_2UNUSED1 0x00000001
+#define INP_2UNUSED2 0x00000002
#define INP_PCBGROUPWILD 0x00000004 /* in pcbgroup wildcard list */
#define INP_REUSEPORT 0x00000008 /* SO_REUSEPORT option is set */
#define INP_FREED 0x00000010 /* inp itself is not valid */
@@ -724,6 +758,7 @@ short inp_so_options(const struct inpcb *inp);
#define INP_RATE_LIMIT_CHANGED 0x00000400 /* rate limit needs attention */
#define INP_ORIGDSTADDR 0x00000800 /* receive IP dst address/port */
#define INP_CANNOT_DO_ECN 0x00001000 /* The stack does not do ECN */
+#define INP_REUSEPORT_LB 0x00002000 /* SO_REUSEPORT_LB option is set */
/*
* Flags passed to in_pcblookup*() functions.
diff --git a/freebsd/sys/netinet/ip.h b/freebsd/sys/netinet/ip.h
index 6d902fe4..934bd812 100644
--- a/freebsd/sys/netinet/ip.h
+++ b/freebsd/sys/netinet/ip.h
@@ -94,6 +94,11 @@ struct ip {
#define IPTOS_PREC_ROUTINE IPTOS_DSCP_CS0
/*
+ * Offset of Diffserv decimal value to convert it to tos value .
+ */
+#define IPTOS_DSCP_OFFSET 2
+
+/*
* Definitions for DiffServ Codepoints as per RFC2474 and RFC5865.
*/
#define IPTOS_DSCP_CS0 0x00
diff --git a/freebsd/sys/netinet/ip6.h b/freebsd/sys/netinet/ip6.h
index a0dfcb0f..1f4be3fd 100644
--- a/freebsd/sys/netinet/ip6.h
+++ b/freebsd/sys/netinet/ip6.h
@@ -104,6 +104,7 @@ struct ip6_hdr {
#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */
#endif /* LITTLE_ENDIAN */
#endif
+#define IPV6_FLOWLABEL_LEN 20
#if 1
/* ECN bits proposed by Sally Floyd */
#define IP6TOS_CE 0x01 /* congestion experienced */
diff --git a/freebsd/sys/netinet/ip_carp.c b/freebsd/sys/netinet/ip_carp.c
index 6f5160e0..8f7f6edf 100644
--- a/freebsd/sys/netinet/ip_carp.c
+++ b/freebsd/sys/netinet/ip_carp.c
@@ -189,36 +189,44 @@ static int proto_reg[] = {-1, -1};
*/
/* Accept incoming CARP packets. */
-static VNET_DEFINE(int, carp_allow) = 1;
+VNET_DEFINE_STATIC(int, carp_allow) = 1;
#define V_carp_allow VNET(carp_allow)
+/* Set DSCP in outgoing CARP packets. */
+VNET_DEFINE_STATIC(int, carp_dscp) = 56;
+#define V_carp_dscp VNET(carp_dscp)
+
/* Preempt slower nodes. */
-static VNET_DEFINE(int, carp_preempt) = 0;
+VNET_DEFINE_STATIC(int, carp_preempt) = 0;
#define V_carp_preempt VNET(carp_preempt)
/* Log level. */
-static VNET_DEFINE(int, carp_log) = 1;
+VNET_DEFINE_STATIC(int, carp_log) = 1;
#define V_carp_log VNET(carp_log)
/* Global advskew demotion. */
-static VNET_DEFINE(int, carp_demotion) = 0;
+VNET_DEFINE_STATIC(int, carp_demotion) = 0;
#define V_carp_demotion VNET(carp_demotion)
/* Send error demotion factor. */
-static VNET_DEFINE(int, carp_senderr_adj) = CARP_MAXSKEW;
+VNET_DEFINE_STATIC(int, carp_senderr_adj) = CARP_MAXSKEW;
#define V_carp_senderr_adj VNET(carp_senderr_adj)
/* Iface down demotion factor. */
-static VNET_DEFINE(int, carp_ifdown_adj) = CARP_MAXSKEW;
+VNET_DEFINE_STATIC(int, carp_ifdown_adj) = CARP_MAXSKEW;
#define V_carp_ifdown_adj VNET(carp_ifdown_adj)
static int carp_allow_sysctl(SYSCTL_HANDLER_ARGS);
+static int carp_dscp_sysctl(SYSCTL_HANDLER_ARGS);
static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS);
SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP");
SYSCTL_PROC(_net_inet_carp, OID_AUTO, allow,
CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, 0, 0, carp_allow_sysctl, "I",
"Accept incoming CARP packets");
+SYSCTL_PROC(_net_inet_carp, OID_AUTO, dscp,
+ CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, 0, 0, carp_dscp_sysctl, "I",
+ "DSCP value for carp packets");
SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(carp_preempt), 0, "High-priority backup preemption mode");
SYSCTL_INT(_net_inet_carp, OID_AUTO, log, CTLFLAG_VNET | CTLFLAG_RW,
@@ -935,7 +943,7 @@ carp_send_ad_locked(struct carp_softc *sc)
ip = mtod(m, struct ip *);
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(*ip) >> 2;
- ip->ip_tos = IPTOS_LOWDELAY;
+ ip->ip_tos = V_carp_dscp << IPTOS_DSCP_OFFSET;
ip->ip_len = htons(len);
ip->ip_off = htons(IP_DF);
ip->ip_ttl = CARP_DFLTTL;
@@ -985,6 +993,10 @@ carp_send_ad_locked(struct carp_softc *sc)
ip6 = mtod(m, struct ip6_hdr *);
bzero(ip6, sizeof(*ip6));
ip6->ip6_vfc |= IPV6_VERSION;
+ /* Traffic class isn't defined in ip6 struct instead
+ * it gets offset into flowid field */
+ ip6->ip6_flow |= htonl(V_carp_dscp << (IPV6_FLOWLABEL_LEN +
+ IPTOS_DSCP_OFFSET));
ip6->ip6_hlim = CARP_DFLTTL;
ip6->ip6_nxt = IPPROTO_CARP;
@@ -1413,6 +1425,7 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
free(im6o->im6o_membership, M_CARP);
break;
}
+ in6m_acquire(in6m);
im6o->im6o_membership[0] = in6m;
im6o->im6o_num_memberships++;
@@ -1434,6 +1447,7 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
free(im6o->im6o_membership, M_CARP);
break;
}
+ in6m_acquire(in6m);
im6o->im6o_membership[1] = in6m;
im6o->im6o_num_memberships++;
break;
@@ -2104,6 +2118,24 @@ carp_allow_sysctl(SYSCTL_HANDLER_ARGS)
}
static int
+carp_dscp_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ int new, error;
+
+ new = V_carp_dscp;
+ error = sysctl_handle_int(oidp, &new, 0, req);
+ if (error || !req->newptr)
+ return (error);
+
+ if (new < 0 || new > 63)
+ return (EINVAL);
+
+ V_carp_dscp = new;
+
+ return (0);
+}
+
+static int
carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS)
{
int new, error;
diff --git a/freebsd/sys/netinet/ip_divert.c b/freebsd/sys/netinet/ip_divert.c
index 84f39023..fbf74ca1 100644
--- a/freebsd/sys/netinet/ip_divert.c
+++ b/freebsd/sys/netinet/ip_divert.c
@@ -113,8 +113,8 @@ __FBSDID("$FreeBSD$");
*/
/* Internal variables. */
-static VNET_DEFINE(struct inpcbhead, divcb);
-static VNET_DEFINE(struct inpcbinfo, divcbinfo);
+VNET_DEFINE_STATIC(struct inpcbhead, divcb);
+VNET_DEFINE_STATIC(struct inpcbinfo, divcbinfo);
#define V_divcb VNET(divcb)
#define V_divcbinfo VNET(divcbinfo)
@@ -194,6 +194,7 @@ divert_packet(struct mbuf *m, int incoming)
u_int16_t nport;
struct sockaddr_in divsrc;
struct m_tag *mtag;
+ struct epoch_tracker et;
mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
if (mtag == NULL) {
@@ -274,8 +275,8 @@ divert_packet(struct mbuf *m, int incoming)
/* Put packet on socket queue, if any */
sa = NULL;
nport = htons((u_int16_t)(((struct ipfw_rule_ref *)(mtag+1))->info));
- INP_INFO_RLOCK(&V_divcbinfo);
- LIST_FOREACH(inp, &V_divcb, inp_list) {
+ INP_INFO_RLOCK_ET(&V_divcbinfo, et);
+ CK_LIST_FOREACH(inp, &V_divcb, inp_list) {
/* XXX why does only one socket match? */
if (inp->inp_lport == nport) {
INP_RLOCK(inp);
@@ -292,7 +293,7 @@ divert_packet(struct mbuf *m, int incoming)
break;
}
}
- INP_INFO_RUNLOCK(&V_divcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_divcbinfo, et);
if (sa == NULL) {
m_freem(m);
KMOD_IPSTAT_INC(ips_noproto);
@@ -554,7 +555,6 @@ div_detach(struct socket *so)
KASSERT(inp != NULL, ("div_detach: inp == NULL"));
INP_INFO_WLOCK(&V_divcbinfo);
INP_WLOCK(inp);
- /* XXX defer destruction to epoch_call */
in_pcbdetach(inp);
in_pcbfree(inp);
INP_INFO_WUNLOCK(&V_divcbinfo);
@@ -634,10 +634,10 @@ static int
div_pcblist(SYSCTL_HANDLER_ARGS)
{
int error, i, n;
- struct in_pcblist *il;
struct inpcb *inp, **inp_list;
inp_gen_t gencnt;
struct xinpgen xig;
+ struct epoch_tracker et;
/*
* The process of preparing the TCB list is too time-consuming and
@@ -656,10 +656,10 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
/*
* OK, now we're committed to doing something.
*/
- INP_INFO_RLOCK(&V_divcbinfo);
+ INP_INFO_WLOCK(&V_divcbinfo);
gencnt = V_divcbinfo.ipi_gencnt;
n = V_divcbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_divcbinfo);
+ INP_INFO_WUNLOCK(&V_divcbinfo);
error = sysctl_wire_old_buffer(req,
2 * sizeof(xig) + n*sizeof(struct xinpcb));
@@ -674,12 +674,13 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
if (error)
return error;
- il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
- inp_list = il->il_inp_list;
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
+ if (inp_list == NULL)
+ return ENOMEM;
- INP_INFO_RLOCK(&V_divcbinfo);
- for (inp = LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; inp && i < n;
- inp = LIST_NEXT(inp, inp_list)) {
+ INP_INFO_RLOCK_ET(&V_divcbinfo, et);
+ for (inp = CK_LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; inp && i < n;
+ inp = CK_LIST_NEXT(inp, inp_list)) {
INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt &&
cr_canseeinpcb(req->td->td_ucred, inp) == 0) {
@@ -688,7 +689,7 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
}
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_divcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_divcbinfo, et);
n = i;
error = 0;
@@ -704,11 +705,17 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
} else
INP_RUNLOCK(inp);
}
- il->il_count = n;
- il->il_pcbinfo = &V_divcbinfo;
- epoch_call(net_epoch_preempt, &il->il_epoch_ctx, in_pcblist_rele_rlocked);
+ INP_INFO_WLOCK(&V_divcbinfo);
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
+ }
+ INP_INFO_WUNLOCK(&V_divcbinfo);
if (!error) {
+ struct epoch_tracker et;
/*
* Give the user an updated idea of our state.
* If the generation differs from what we told
@@ -716,13 +723,14 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
* while we were processing this request, and it
* might be necessary to retry.
*/
- INP_INFO_RLOCK(&V_divcbinfo);
+ INP_INFO_RLOCK_ET(&V_divcbinfo, et);
xig.xig_gen = V_divcbinfo.ipi_gencnt;
xig.xig_sogen = so_gencnt;
xig.xig_count = V_divcbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_divcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_divcbinfo, et);
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
+ free(inp_list, M_TEMP);
return error;
}
@@ -802,7 +810,6 @@ div_modevent(module_t mod, int type, void *unused)
break;
}
ip_divert_ptr = NULL;
- /* XXX defer to epoch_call ? */
err = pf_proto_unregister(PF_INET, IPPROTO_DIVERT, SOCK_RAW);
INP_INFO_WUNLOCK(&V_divcbinfo);
#ifndef VIMAGE
diff --git a/freebsd/sys/netinet/ip_encap.c b/freebsd/sys/netinet/ip_encap.c
index 52cd0b40..1e794f73 100644
--- a/freebsd/sys/netinet/ip_encap.c
+++ b/freebsd/sys/netinet/ip_encap.c
@@ -6,6 +6,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -58,417 +59,214 @@
* So, clearly good old protosw does not work for protocol #4 and #41.
* The code will let you match protocol via src/dst address pair.
*/
-/* XXX is M_NETADDR correct? */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <rtems/bsd/local/opt_mrouting.h>
#include <rtems/bsd/local/opt_inet.h>
#include <rtems/bsd/local/opt_inet6.h>
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
-#include <sys/protosw.h>
-#include <sys/queue.h>
+#include <sys/socket.h>
#include <net/if.h>
-#include <net/route.h>
+#include <net/if_var.h>
#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_encap.h>
#ifdef INET6
-#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#endif
-#include <machine/stdarg.h>
+static MALLOC_DEFINE(M_NETADDR, "encap_export_host",
+ "Export host address structure");
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-static MALLOC_DEFINE(M_NETADDR, "encap_export_host", "Export host address structure");
+struct encaptab {
+ CK_LIST_ENTRY(encaptab) chain;
+ int proto;
+ int min_length;
+ int exact_match;
+ void *arg;
-static void encap_add(struct encaptab *);
-static int mask_match(const struct encaptab *, const struct sockaddr *,
- const struct sockaddr *);
-static void encap_fillarg(struct mbuf *, void *);
+ encap_lookup_t lookup;
+ encap_check_t check;
+ encap_input_t input;
+};
+
+CK_LIST_HEAD(encaptab_head, encaptab);
+#ifdef INET
+static struct encaptab_head ipv4_encaptab = CK_LIST_HEAD_INITIALIZER();
+#endif
+#ifdef INET6
+static struct encaptab_head ipv6_encaptab = CK_LIST_HEAD_INITIALIZER();
+#endif
-/*
- * All global variables in ip_encap.c are locked using encapmtx.
- */
static struct mtx encapmtx;
MTX_SYSINIT(encapmtx, &encapmtx, "encapmtx", MTX_DEF);
-static LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(encaptab);
-
-#ifdef INET
-int
-encap4_input(struct mbuf **mp, int *offp, int proto)
+#define ENCAP_WLOCK() mtx_lock(&encapmtx)
+#define ENCAP_WUNLOCK() mtx_unlock(&encapmtx)
+#define ENCAP_RLOCK() struct epoch_tracker encap_et; epoch_enter_preempt(net_epoch_preempt, &encap_et)
+#define ENCAP_RUNLOCK() epoch_exit_preempt(net_epoch_preempt, &encap_et)
+#define ENCAP_WAIT() epoch_wait_preempt(net_epoch_preempt)
+
+static struct encaptab *
+encap_attach(struct encaptab_head *head, const struct encap_config *cfg,
+ void *arg, int mflags)
{
- struct ip *ip;
- struct mbuf *m;
- struct sockaddr_in s, d;
- const struct protosw *psw;
- struct encaptab *ep, *match;
- void *arg;
- int matchprio, off, prio;
-
- m = *mp;
- off = *offp;
- ip = mtod(m, struct ip *);
-
- bzero(&s, sizeof(s));
- s.sin_family = AF_INET;
- s.sin_len = sizeof(struct sockaddr_in);
- s.sin_addr = ip->ip_src;
- bzero(&d, sizeof(d));
- d.sin_family = AF_INET;
- d.sin_len = sizeof(struct sockaddr_in);
- d.sin_addr = ip->ip_dst;
-
- arg = NULL;
- psw = NULL;
- match = NULL;
- matchprio = 0;
- mtx_lock(&encapmtx);
- LIST_FOREACH(ep, &encaptab, chain) {
- if (ep->af != AF_INET)
- continue;
- if (ep->proto >= 0 && ep->proto != proto)
- continue;
- if (ep->func)
- prio = (*ep->func)(m, off, proto, ep->arg);
- else {
- /*
- * it's inbound traffic, we need to match in reverse
- * order
- */
- prio = mask_match(ep, (struct sockaddr *)&d,
- (struct sockaddr *)&s);
- }
+ struct encaptab *ep, *tmp;
- /*
- * We prioritize the matches by using bit length of the
- * matches. mask_match() and user-supplied matching function
- * should return the bit length of the matches (for example,
- * if both src/dst are matched for IPv4, 64 should be returned).
- * 0 or negative return value means "it did not match".
- *
- * The question is, since we have two "mask" portion, we
- * cannot really define total order between entries.
- * For example, which of these should be preferred?
- * mask_match() returns 48 (32 + 16) for both of them.
- * src=3ffe::/16, dst=3ffe:501::/32
- * src=3ffe:501::/32, dst=3ffe::/16
- *
- * We need to loop through all the possible candidates
- * to get the best match - the search takes O(n) for
- * n attachments (i.e. interfaces).
- */
- if (prio <= 0)
- continue;
- if (prio > matchprio) {
- matchprio = prio;
- match = ep;
- }
- }
- if (match != NULL) {
- psw = match->psw;
- arg = match->arg;
- }
- mtx_unlock(&encapmtx);
+ if (cfg == NULL || cfg->input == NULL ||
+ (cfg->check == NULL && cfg->lookup == NULL) ||
+ (cfg->lookup != NULL && cfg->exact_match != ENCAP_DRV_LOOKUP) ||
+ (cfg->exact_match == ENCAP_DRV_LOOKUP && cfg->lookup == NULL))
+ return (NULL);
- if (match != NULL) {
- /* found a match, "match" has the best one */
- if (psw != NULL && psw->pr_input != NULL) {
- encap_fillarg(m, arg);
- (*psw->pr_input)(mp, offp, proto);
- } else
- m_freem(m);
- return (IPPROTO_DONE);
+ ep = malloc(sizeof(*ep), M_NETADDR, mflags);
+ if (ep == NULL)
+ return (NULL);
+
+ ep->proto = cfg->proto;
+ ep->min_length = cfg->min_length;
+ ep->exact_match = cfg->exact_match;
+ ep->arg = arg;
+ ep->lookup = cfg->exact_match == ENCAP_DRV_LOOKUP ? cfg->lookup: NULL;
+ ep->check = cfg->exact_match != ENCAP_DRV_LOOKUP ? cfg->check: NULL;
+ ep->input = cfg->input;
+
+ ENCAP_WLOCK();
+ CK_LIST_FOREACH(tmp, head, chain) {
+ if (tmp->exact_match <= ep->exact_match)
+ break;
}
+ if (tmp == NULL)
+ CK_LIST_INSERT_HEAD(head, ep, chain);
+ else
+ CK_LIST_INSERT_BEFORE(tmp, ep, chain);
+ ENCAP_WUNLOCK();
+ return (ep);
+}
+
+static int
+encap_detach(struct encaptab_head *head, const struct encaptab *cookie)
+{
+ struct encaptab *ep;
- /* last resort: inject to raw socket */
- return (rip_input(mp, offp, proto));
+ ENCAP_WLOCK();
+ CK_LIST_FOREACH(ep, head, chain) {
+ if (ep == cookie) {
+ CK_LIST_REMOVE(ep, chain);
+ ENCAP_WUNLOCK();
+ ENCAP_WAIT();
+ free(ep, M_NETADDR);
+ return (0);
+ }
+ }
+ ENCAP_WUNLOCK();
+ return (EINVAL);
}
-#endif
-#ifdef INET6
-int
-encap6_input(struct mbuf **mp, int *offp, int proto)
+static int
+encap_input(struct encaptab_head *head, struct mbuf *m, int off, int proto)
{
- struct mbuf *m = *mp;
- struct ip6_hdr *ip6;
- struct sockaddr_in6 s, d;
- const struct protosw *psw;
struct encaptab *ep, *match;
void *arg;
- int prio, matchprio;
-
- ip6 = mtod(m, struct ip6_hdr *);
+ int matchprio, ret;
- bzero(&s, sizeof(s));
- s.sin6_family = AF_INET6;
- s.sin6_len = sizeof(struct sockaddr_in6);
- s.sin6_addr = ip6->ip6_src;
- bzero(&d, sizeof(d));
- d.sin6_family = AF_INET6;
- d.sin6_len = sizeof(struct sockaddr_in6);
- d.sin6_addr = ip6->ip6_dst;
-
- arg = NULL;
- psw = NULL;
match = NULL;
matchprio = 0;
- mtx_lock(&encapmtx);
- LIST_FOREACH(ep, &encaptab, chain) {
- if (ep->af != AF_INET6)
- continue;
+
+ ENCAP_RLOCK();
+ CK_LIST_FOREACH(ep, head, chain) {
if (ep->proto >= 0 && ep->proto != proto)
continue;
- if (ep->func)
- prio = (*ep->func)(m, *offp, proto, ep->arg);
- else {
- /*
- * it's inbound traffic, we need to match in reverse
- * order
- */
- prio = mask_match(ep, (struct sockaddr *)&d,
- (struct sockaddr *)&s);
- }
-
- /* see encap4_input() for issues here */
- if (prio <= 0)
+ if (ep->min_length > m->m_pkthdr.len)
continue;
- if (prio > matchprio) {
- matchprio = prio;
+ if (ep->exact_match == ENCAP_DRV_LOOKUP)
+ ret = (*ep->lookup)(m, off, proto, &arg);
+ else
+ ret = (*ep->check)(m, off, proto, ep->arg);
+ if (ret <= 0)
+ continue;
+ if (ret > matchprio) {
match = ep;
+ if (ep->exact_match != ENCAP_DRV_LOOKUP)
+ arg = ep->arg;
+ /*
+ * No need to continue the search, we got the
+ * exact match.
+ */
+ if (ret >= ep->exact_match)
+ break;
+ matchprio = ret;
}
}
- if (match != NULL) {
- psw = match->psw;
- arg = match->arg;
- }
- mtx_unlock(&encapmtx);
if (match != NULL) {
- /* found a match */
- if (psw != NULL && psw->pr_input != NULL) {
- encap_fillarg(m, arg);
- return (*psw->pr_input)(mp, offp, proto);
- } else {
- m_freem(m);
- return (IPPROTO_DONE);
- }
+ /* found a match, "match" has the best one */
+ ret = (*match->input)(m, off, proto, arg);
+ ENCAP_RUNLOCK();
+ MPASS(ret == IPPROTO_DONE);
+ return (IPPROTO_DONE);
}
-
- /* last resort: inject to raw socket */
- return rip6_input(mp, offp, proto);
-}
-#endif
-
-/*lint -sem(encap_add, custodial(1)) */
-static void
-encap_add(struct encaptab *ep)
-{
-
- mtx_assert(&encapmtx, MA_OWNED);
- LIST_INSERT_HEAD(&encaptab, ep, chain);
+ ENCAP_RUNLOCK();
+ return (0);
}
-/*
- * sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
- * length of mask (sm and dm) is assumed to be same as sp/dp.
- * Return value will be necessary as input (cookie) for encap_detach().
- */
+#ifdef INET
const struct encaptab *
-encap_attach(int af, int proto, const struct sockaddr *sp,
- const struct sockaddr *sm, const struct sockaddr *dp,
- const struct sockaddr *dm, const struct protosw *psw, void *arg)
+ip_encap_attach(const struct encap_config *cfg, void *arg, int mflags)
{
- struct encaptab *ep;
-
- /* sanity check on args */
- if (sp->sa_len > sizeof(ep->src) || dp->sa_len > sizeof(ep->dst))
- return (NULL);
- if (sp->sa_len != dp->sa_len)
- return (NULL);
- if (af != sp->sa_family || af != dp->sa_family)
- return (NULL);
- /* check if anyone have already attached with exactly same config */
- mtx_lock(&encapmtx);
- LIST_FOREACH(ep, &encaptab, chain) {
- if (ep->af != af)
- continue;
- if (ep->proto != proto)
- continue;
- if (ep->src.ss_len != sp->sa_len ||
- bcmp(&ep->src, sp, sp->sa_len) != 0 ||
- bcmp(&ep->srcmask, sm, sp->sa_len) != 0)
- continue;
- if (ep->dst.ss_len != dp->sa_len ||
- bcmp(&ep->dst, dp, dp->sa_len) != 0 ||
- bcmp(&ep->dstmask, dm, dp->sa_len) != 0)
- continue;
-
- mtx_unlock(&encapmtx);
- return (NULL);
- }
-
- ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/
- if (ep == NULL) {
- mtx_unlock(&encapmtx);
- return (NULL);
- }
- bzero(ep, sizeof(*ep));
-
- ep->af = af;
- ep->proto = proto;
- bcopy(sp, &ep->src, sp->sa_len);
- bcopy(sm, &ep->srcmask, sp->sa_len);
- bcopy(dp, &ep->dst, dp->sa_len);
- bcopy(dm, &ep->dstmask, dp->sa_len);
- ep->psw = psw;
- ep->arg = arg;
-
- encap_add(ep);
- mtx_unlock(&encapmtx);
- return (ep);
+ return (encap_attach(&ipv4_encaptab, cfg, arg, mflags));
}
-const struct encaptab *
-encap_attach_func(int af, int proto,
- int (*func)(const struct mbuf *, int, int, void *),
- const struct protosw *psw, void *arg)
+int
+ip_encap_detach(const struct encaptab *cookie)
{
- struct encaptab *ep;
- /* sanity check on args */
- if (!func)
- return (NULL);
-
- ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/
- if (ep == NULL)
- return (NULL);
- bzero(ep, sizeof(*ep));
-
- ep->af = af;
- ep->proto = proto;
- ep->func = func;
- ep->psw = psw;
- ep->arg = arg;
-
- mtx_lock(&encapmtx);
- encap_add(ep);
- mtx_unlock(&encapmtx);
- return (ep);
+ return (encap_detach(&ipv4_encaptab, cookie));
}
int
-encap_detach(const struct encaptab *cookie)
+encap4_input(struct mbuf **mp, int *offp, int proto)
{
- const struct encaptab *ep = cookie;
- struct encaptab *p;
-
- mtx_lock(&encapmtx);
- LIST_FOREACH(p, &encaptab, chain) {
- if (p == ep) {
- LIST_REMOVE(p, chain);
- mtx_unlock(&encapmtx);
- free(p, M_NETADDR); /*XXX*/
- return 0;
- }
- }
- mtx_unlock(&encapmtx);
- return EINVAL;
+ if (encap_input(&ipv4_encaptab, *mp, *offp, proto) != IPPROTO_DONE)
+ return (rip_input(mp, offp, proto));
+ return (IPPROTO_DONE);
}
+#endif /* INET */
-static int
-mask_match(const struct encaptab *ep, const struct sockaddr *sp,
- const struct sockaddr *dp)
+#ifdef INET6
+const struct encaptab *
+ip6_encap_attach(const struct encap_config *cfg, void *arg, int mflags)
{
- struct sockaddr_storage s;
- struct sockaddr_storage d;
- int i;
- const u_int8_t *p, *q;
- u_int8_t *r;
- int matchlen;
-
- if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d))
- return 0;
- if (sp->sa_family != ep->af || dp->sa_family != ep->af)
- return 0;
- if (sp->sa_len != ep->src.ss_len || dp->sa_len != ep->dst.ss_len)
- return 0;
-
- matchlen = 0;
-
- p = (const u_int8_t *)sp;
- q = (const u_int8_t *)&ep->srcmask;
- r = (u_int8_t *)&s;
- for (i = 0 ; i < sp->sa_len; i++) {
- r[i] = p[i] & q[i];
- /* XXX estimate */
- matchlen += (q[i] ? 8 : 0);
- }
- p = (const u_int8_t *)dp;
- q = (const u_int8_t *)&ep->dstmask;
- r = (u_int8_t *)&d;
- for (i = 0 ; i < dp->sa_len; i++) {
- r[i] = p[i] & q[i];
- /* XXX rough estimate */
- matchlen += (q[i] ? 8 : 0);
- }
-
- /* need to overwrite len/family portion as we don't compare them */
- s.ss_len = sp->sa_len;
- s.ss_family = sp->sa_family;
- d.ss_len = dp->sa_len;
- d.ss_family = dp->sa_family;
-
- if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 &&
- bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) {
- return matchlen;
- } else
- return 0;
+ return (encap_attach(&ipv6_encaptab, cfg, arg, mflags));
}
-static void
-encap_fillarg(struct mbuf *m, void *arg)
+int
+ip6_encap_detach(const struct encaptab *cookie)
{
- struct m_tag *tag;
- if (arg != NULL) {
- tag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT);
- if (tag != NULL) {
- *(void**)(tag+1) = arg;
- m_tag_prepend(m, tag);
- }
- }
+ return (encap_detach(&ipv6_encaptab, cookie));
}
-void *
-encap_getarg(struct mbuf *m)
+int
+encap6_input(struct mbuf **mp, int *offp, int proto)
{
- void *p = NULL;
- struct m_tag *tag;
- tag = m_tag_find(m, PACKET_TAG_ENCAP, NULL);
- if (tag) {
- p = *(void**)(tag+1);
- m_tag_delete(m, tag);
- }
- return p;
+ if (encap_input(&ipv6_encaptab, *mp, *offp, proto) != IPPROTO_DONE)
+ return (rip6_input(mp, offp, proto));
+ return (IPPROTO_DONE);
}
+#endif /* INET6 */
diff --git a/freebsd/sys/netinet/ip_encap.h b/freebsd/sys/netinet/ip_encap.h
index ef232189..f3d1d3af 100644
--- a/freebsd/sys/netinet/ip_encap.h
+++ b/freebsd/sys/netinet/ip_encap.h
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,29 +38,33 @@
#ifdef _KERNEL
-struct encaptab {
- LIST_ENTRY(encaptab) chain;
- int af;
- int proto; /* -1: don't care, I'll check myself */
- struct sockaddr_storage src; /* my addr */
- struct sockaddr_storage srcmask;
- struct sockaddr_storage dst; /* remote addr */
- struct sockaddr_storage dstmask;
- int (*func)(const struct mbuf *, int, int, void *);
- const struct protosw *psw; /* only pr_input will be used */
- void *arg; /* passed via m->m_pkthdr.aux */
-};
-
int encap4_input(struct mbuf **, int *, int);
int encap6_input(struct mbuf **, int *, int);
-const struct encaptab *encap_attach(int, int, const struct sockaddr *,
- const struct sockaddr *, const struct sockaddr *,
- const struct sockaddr *, const struct protosw *, void *);
-const struct encaptab *encap_attach_func(int, int,
- int (*)(const struct mbuf *, int, int, void *),
- const struct protosw *, void *);
-int encap_detach(const struct encaptab *);
-void *encap_getarg(struct mbuf *);
+
+typedef int (*encap_lookup_t)(const struct mbuf *, int, int, void **);
+typedef int (*encap_check_t)(const struct mbuf *, int, int, void *);
+typedef int (*encap_input_t)(struct mbuf *, int , int, void *);
+
+struct encap_config {
+ int proto; /* protocol */
+ int min_length; /* minimum packet length */
+ int exact_match; /* a packet is exactly matched */
+#define ENCAP_DRV_LOOKUP 0x7fffffff
+
+ encap_lookup_t lookup;
+ encap_check_t check;
+ encap_input_t input;
+};
+
+struct encaptab;
+
+const struct encaptab *ip_encap_attach(const struct encap_config *,
+ void *arg, int mflags);
+const struct encaptab *ip6_encap_attach(const struct encap_config *,
+ void *arg, int mflags);
+
+int ip_encap_detach(const struct encaptab *);
+int ip6_encap_detach(const struct encaptab *);
#endif
#endif /*_NETINET_IP_ENCAP_H_*/
diff --git a/freebsd/sys/netinet/ip_fastfwd.c b/freebsd/sys/netinet/ip_fastfwd.c
index b084fdc6..05deb4d8 100644
--- a/freebsd/sys/netinet/ip_fastfwd.c
+++ b/freebsd/sys/netinet/ip_fastfwd.c
@@ -155,7 +155,7 @@ ip_tryforward(struct mbuf *m)
struct mbuf *m0 = NULL;
struct nhop4_basic nh;
struct sockaddr_in dst;
- struct in_addr odest, dest;
+ struct in_addr dest, odest, rtdest;
uint16_t ip_len, ip_off;
int error = 0;
struct m_tag *fwd_tag = NULL;
@@ -296,12 +296,31 @@ passin:
#endif
/*
+ * Next hop forced by pfil(9) hook?
+ */
+ if ((m->m_flags & M_IP_NEXTHOP) &&
+ ((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) {
+ /*
+ * Now we will find route to forced destination.
+ */
+ dest.s_addr = ((struct sockaddr_in *)
+ (fwd_tag + 1))->sin_addr.s_addr;
+ m_tag_delete(m, fwd_tag);
+ m->m_flags &= ~M_IP_NEXTHOP;
+ }
+
+ /*
* Find route to destination.
*/
if (ip_findroute(&nh, dest, m) != 0)
return (NULL); /* icmp unreach already sent */
/*
+ * Avoid second route lookup by caching destination.
+ */
+ rtdest.s_addr = dest.s_addr;
+
+ /*
* Step 5: outgoing firewall packet processing
*/
if (!PFIL_HOOKED(&V_inet_pfil_hook))
@@ -323,6 +342,8 @@ passin:
*/
if (m->m_flags & M_IP_NEXTHOP)
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ else
+ fwd_tag = NULL;
if (odest.s_addr != dest.s_addr || fwd_tag != NULL) {
/*
* Is it now for a local address on this host?
@@ -344,7 +365,8 @@ forwardlocal:
m_tag_delete(m, fwd_tag);
m->m_flags &= ~M_IP_NEXTHOP;
}
- if (ip_findroute(&nh, dest, m) != 0)
+ if (dest.s_addr != rtdest.s_addr &&
+ ip_findroute(&nh, dest, m) != 0)
return (NULL); /* icmp unreach already sent */
}
diff --git a/freebsd/sys/netinet/ip_fw.h b/freebsd/sys/netinet/ip_fw.h
index 286eb03f..a7bf5b4d 100644
--- a/freebsd/sys/netinet/ip_fw.h
+++ b/freebsd/sys/netinet/ip_fw.h
@@ -285,6 +285,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_EXTERNAL_INSTANCE, /* arg1=id of eaction handler instance */
O_EXTERNAL_DATA, /* variable length data */
+ O_SKIP_ACTION, /* none */
+
O_LAST_OPCODE /* not an opcode! */
};
diff --git a/freebsd/sys/netinet/ip_gre.c b/freebsd/sys/netinet/ip_gre.c
index 673e23d5..65ab0ab9 100644
--- a/freebsd/sys/netinet/ip_gre.c
+++ b/freebsd/sys/netinet/ip_gre.c
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause-NetBSD
*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
- * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org>
+ * Copyright (c) 2014, 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -43,18 +43,17 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_inet6.h>
#include <sys/param.h>
+#include <sys/jail.h>
#include <sys/systm.h>
-#include <sys/mbuf.h>
#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/protosw.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
#include <sys/errno.h>
-#include <sys/time.h>
#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/rmlock.h>
#include <sys/sysctl.h>
-#include <net/ethernet.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+
#include <net/if.h>
#include <net/if_var.h>
#include <net/vnet.h>
@@ -71,61 +70,177 @@ __FBSDID("$FreeBSD$");
#include <net/if_gre.h>
-extern struct domain inetdomain;
-static const struct protosw in_gre_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_GRE,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = gre_input,
- .pr_output = rip_output,
- .pr_ctlinput = rip_ctlinput,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
#define GRE_TTL 30
VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL;
#define V_ip_gre_ttl VNET(ip_gre_ttl)
SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip_gre_ttl), 0, "");
+ &VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets");
+
+VNET_DEFINE_STATIC(struct gre_list *, ipv4_hashtbl) = NULL;
+#define V_ipv4_hashtbl VNET(ipv4_hashtbl)
+#define GRE_HASH(src, dst) (V_ipv4_hashtbl[\
+ in_gre_hashval((src), (dst)) & (GRE_HASH_SIZE - 1)])
+#define GRE_HASH_SC(sc) GRE_HASH((sc)->gre_oip.ip_src.s_addr,\
+ (sc)->gre_oip.ip_dst.s_addr)
+
+static uint32_t
+in_gre_hashval(in_addr_t src, in_addr_t dst)
+{
+ uint32_t ret;
+
+ ret = fnv_32_buf(&src, sizeof(src), FNV1_32_INIT);
+ return (fnv_32_buf(&dst, sizeof(dst), ret));
+}
+
+static int
+in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst)
+{
+ struct gre_softc *tmp;
+
+ if (sc->gre_family == AF_INET &&
+ sc->gre_oip.ip_src.s_addr == src &&
+ sc->gre_oip.ip_dst.s_addr == dst)
+ return (EEXIST);
+
+ CK_LIST_FOREACH(tmp, &GRE_HASH(src, dst), chain) {
+ if (tmp == sc)
+ continue;
+ if (tmp->gre_oip.ip_src.s_addr == src &&
+ tmp->gre_oip.ip_dst.s_addr == dst)
+ return (EADDRNOTAVAIL);
+ }
+ return (0);
+}
static int
-in_gre_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+in_gre_lookup(const struct mbuf *m, int off, int proto, void **arg)
{
- GRE_RLOCK_TRACKER;
+ const struct ip *ip;
struct gre_softc *sc;
- struct ip *ip;
- sc = (struct gre_softc *)arg;
- if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0)
+ if (V_ipv4_hashtbl == NULL)
return (0);
- M_ASSERTPKTHDR(m);
- /*
- * We expect that payload contains at least IPv4
- * or IPv6 packet.
- */
- if (m->m_pkthdr.len < sizeof(struct greip) + sizeof(struct ip))
- return (0);
+ MPASS(in_epoch(net_epoch_preempt));
+ ip = mtod(m, const struct ip *);
+ CK_LIST_FOREACH(sc, &GRE_HASH(ip->ip_dst.s_addr,
+ ip->ip_src.s_addr), chain) {
+ /*
+ * This is an inbound packet, its ip_dst is source address
+ * in softc.
+ */
+ if (sc->gre_oip.ip_src.s_addr == ip->ip_dst.s_addr &&
+ sc->gre_oip.ip_dst.s_addr == ip->ip_src.s_addr) {
+ if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0)
+ return (0);
+ *arg = sc;
+ return (ENCAP_DRV_LOOKUP);
+ }
+ }
+ return (0);
+}
- GRE_RLOCK(sc);
- if (sc->gre_family == 0)
- goto bad;
+static void
+in_gre_attach(struct gre_softc *sc)
+{
- KASSERT(sc->gre_family == AF_INET,
- ("wrong gre_family: %d", sc->gre_family));
+ sc->gre_hlen = sizeof(struct greip);
+ sc->gre_oip.ip_v = IPVERSION;
+ sc->gre_oip.ip_hl = sizeof(struct ip) >> 2;
+ sc->gre_oip.ip_p = IPPROTO_GRE;
+ gre_updatehdr(sc, &sc->gre_gihdr->gi_gre);
+ CK_LIST_INSERT_HEAD(&GRE_HASH_SC(sc), sc, chain);
+}
- ip = mtod(m, struct ip *);
- if (sc->gre_oip.ip_src.s_addr != ip->ip_dst.s_addr ||
- sc->gre_oip.ip_dst.s_addr != ip->ip_src.s_addr)
- goto bad;
+void
+in_gre_setopts(struct gre_softc *sc, u_long cmd, uint32_t value)
+{
- GRE_RUNLOCK(sc);
- return (32 * 2);
-bad:
- GRE_RUNLOCK(sc);
- return (0);
+ MPASS(cmd == GRESKEY || cmd == GRESOPTS);
+
+ /* NOTE: we are protected with gre_ioctl_sx lock */
+ MPASS(sc->gre_family == AF_INET);
+ CK_LIST_REMOVE(sc, chain);
+ GRE_WAIT();
+ if (cmd == GRESKEY)
+ sc->gre_key = value;
+ else
+ sc->gre_options = value;
+ in_gre_attach(sc);
+}
+
+int
+in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data)
+{
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct sockaddr_in *dst, *src;
+ struct ip *ip;
+ int error;
+
+ /* NOTE: we are protected with gre_ioctl_sx lock */
+ error = EINVAL;
+ switch (cmd) {
+ case SIOCSIFPHYADDR:
+ src = &((struct in_aliasreq *)data)->ifra_addr;
+ dst = &((struct in_aliasreq *)data)->ifra_dstaddr;
+
+ /* sanity checks */
+ if (src->sin_family != dst->sin_family ||
+ src->sin_family != AF_INET ||
+ src->sin_len != dst->sin_len ||
+ src->sin_len != sizeof(*src))
+ break;
+ if (src->sin_addr.s_addr == INADDR_ANY ||
+ dst->sin_addr.s_addr == INADDR_ANY) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ if (V_ipv4_hashtbl == NULL)
+ V_ipv4_hashtbl = gre_hashinit();
+ error = in_gre_checkdup(sc, src->sin_addr.s_addr,
+ dst->sin_addr.s_addr);
+ if (error == EADDRNOTAVAIL)
+ break;
+ if (error == EEXIST) {
+ /* Addresses are the same. Just return. */
+ error = 0;
+ break;
+ }
+ ip = malloc(sizeof(struct greip) + 3 * sizeof(uint32_t),
+ M_GRE, M_WAITOK | M_ZERO);
+ ip->ip_src.s_addr = src->sin_addr.s_addr;
+ ip->ip_dst.s_addr = dst->sin_addr.s_addr;
+ if (sc->gre_family != 0) {
+ /* Detach existing tunnel first */
+ CK_LIST_REMOVE(sc, chain);
+ GRE_WAIT();
+ free(sc->gre_hdr, M_GRE);
+ /* XXX: should we notify about link state change? */
+ }
+ sc->gre_family = AF_INET;
+ sc->gre_hdr = ip;
+ sc->gre_oseq = 0;
+ sc->gre_iseq = UINT32_MAX;
+ in_gre_attach(sc);
+ break;
+ case SIOCGIFPSRCADDR:
+ case SIOCGIFPDSTADDR:
+ if (sc->gre_family != AF_INET) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ src = (struct sockaddr_in *)&ifr->ifr_addr;
+ memset(src, 0, sizeof(*src));
+ src->sin_family = AF_INET;
+ src->sin_len = sizeof(*src);
+ src->sin_addr = (cmd == SIOCGIFPSRCADDR) ?
+ sc->gre_oip.ip_src: sc->gre_oip.ip_dst;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)src);
+ if (error != 0)
+ memset(src, 0, sizeof(*src));
+ break;
+ }
+ return (error);
}
int
@@ -158,14 +273,30 @@ in_gre_output(struct mbuf *m, int af, int hlen)
return (ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL));
}
-int
-in_gre_attach(struct gre_softc *sc)
+static const struct encaptab *ecookie = NULL;
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_GRE,
+ .min_length = sizeof(struct greip) + sizeof(struct ip),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in_gre_lookup,
+ .input = gre_input
+};
+
+void
+in_gre_init(void)
{
- KASSERT(sc->gre_ecookie == NULL, ("gre_ecookie isn't NULL"));
- sc->gre_ecookie = encap_attach_func(AF_INET, IPPROTO_GRE,
- in_gre_encapcheck, &in_gre_protosw, sc);
- if (sc->gre_ecookie == NULL)
- return (EEXIST);
- return (0);
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+ ecookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
+}
+
+void
+in_gre_uninit(void)
+{
+
+ if (IS_DEFAULT_VNET(curvnet))
+ ip_encap_detach(ecookie);
+ if (V_ipv4_hashtbl != NULL)
+ gre_hashdestroy(V_ipv4_hashtbl);
}
diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c
index 3fc59a14..414e3812 100644
--- a/freebsd/sys/netinet/ip_icmp.c
+++ b/freebsd/sys/netinet/ip_icmp.c
@@ -84,13 +84,13 @@ __FBSDID("$FreeBSD$");
* routines to turnaround packets back to the originator, and
* host table maintenance routines.
*/
-static VNET_DEFINE(int, icmplim) = 200;
+VNET_DEFINE_STATIC(int, icmplim) = 200;
#define V_icmplim VNET(icmplim)
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmplim), 0,
"Maximum number of ICMP responses per second");
-static VNET_DEFINE(int, icmplim_output) = 1;
+VNET_DEFINE_STATIC(int, icmplim_output) = 1;
#define V_icmplim_output VNET(icmplim_output)
SYSCTL_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmplim_output), 0,
@@ -106,13 +106,13 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_icmp, ICMPCTL_STATS, stats, struct icmpstat,
VNET_PCPUSTAT_SYSUNINIT(icmpstat);
#endif /* VIMAGE */
-static VNET_DEFINE(int, icmpmaskrepl) = 0;
+VNET_DEFINE_STATIC(int, icmpmaskrepl) = 0;
#define V_icmpmaskrepl VNET(icmpmaskrepl)
SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmpmaskrepl), 0,
"Reply to ICMP Address Mask Request packets");
-static VNET_DEFINE(u_int, icmpmaskfake) = 0;
+VNET_DEFINE_STATIC(u_int, icmpmaskfake) = 0;
#define V_icmpmaskfake VNET(icmpmaskfake)
SYSCTL_UINT(_net_inet_icmp, OID_AUTO, maskfake, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmpmaskfake), 0,
@@ -124,37 +124,37 @@ SYSCTL_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(drop_redirect), 0,
"Ignore ICMP redirects");
-static VNET_DEFINE(int, log_redirect) = 0;
+VNET_DEFINE_STATIC(int, log_redirect) = 0;
#define V_log_redirect VNET(log_redirect)
SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(log_redirect), 0,
"Log ICMP redirects to the console");
-static VNET_DEFINE(char, reply_src[IFNAMSIZ]);
+VNET_DEFINE_STATIC(char, reply_src[IFNAMSIZ]);
#define V_reply_src VNET(reply_src)
SYSCTL_STRING(_net_inet_icmp, OID_AUTO, reply_src, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(reply_src), IFNAMSIZ,
"ICMP reply source for non-local packets");
-static VNET_DEFINE(int, icmp_rfi) = 0;
+VNET_DEFINE_STATIC(int, icmp_rfi) = 0;
#define V_icmp_rfi VNET(icmp_rfi)
SYSCTL_INT(_net_inet_icmp, OID_AUTO, reply_from_interface, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmp_rfi), 0,
"ICMP reply from incoming interface for non-local packets");
-
-static VNET_DEFINE(int, icmp_quotelen) = 8;
+/* Router requirements RFC 1812 section 4.3.2.3 requires 576 - 28. */
+VNET_DEFINE_STATIC(int, icmp_quotelen) = 548;
#define V_icmp_quotelen VNET(icmp_quotelen)
SYSCTL_INT(_net_inet_icmp, OID_AUTO, quotelen, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmp_quotelen), 0,
"Number of bytes from original packet to quote in ICMP reply");
-static VNET_DEFINE(int, icmpbmcastecho) = 0;
+VNET_DEFINE_STATIC(int, icmpbmcastecho) = 0;
#define V_icmpbmcastecho VNET(icmpbmcastecho)
SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmpbmcastecho), 0,
"Reply to multicast ICMP Echo Request and Timestamp packets");
-static VNET_DEFINE(int, icmptstamprepl) = 1;
+VNET_DEFINE_STATIC(int, icmptstamprepl) = 1;
#define V_icmptstamprepl VNET(icmptstamprepl)
SYSCTL_INT(_net_inet_icmp, OID_AUTO, tstamprepl, CTLFLAG_RW,
&VNET_NAME(icmptstamprepl), 0,
@@ -1003,7 +1003,7 @@ struct icmp_rate {
const char *descr;
struct counter_rate cr;
};
-static VNET_DEFINE(struct icmp_rate, icmp_rates[BANDLIM_MAX]) = {
+VNET_DEFINE_STATIC(struct icmp_rate, icmp_rates[BANDLIM_MAX]) = {
{ "icmp unreach response" },
{ "icmp ping response" },
{ "icmp tstamp response" },
diff --git a/freebsd/sys/netinet/ip_id.c b/freebsd/sys/netinet/ip_id.c
index 02bf2c5b..85a67612 100644
--- a/freebsd/sys/netinet/ip_id.c
+++ b/freebsd/sys/netinet/ip_id.c
@@ -100,8 +100,8 @@ __FBSDID("$FreeBSD$");
* suggested by RFC6864. We use per-CPU counter for that, or if
* user wants to, we can turn on random ID generation.
*/
-static VNET_DEFINE(int, ip_rfc6864) = 1;
-static VNET_DEFINE(int, ip_do_randomid) = 0;
+VNET_DEFINE_STATIC(int, ip_rfc6864) = 1;
+VNET_DEFINE_STATIC(int, ip_do_randomid) = 0;
#define V_ip_rfc6864 VNET(ip_rfc6864)
#define V_ip_do_randomid VNET(ip_do_randomid)
@@ -109,13 +109,13 @@ static VNET_DEFINE(int, ip_do_randomid) = 0;
* Random ID state engine.
*/
static MALLOC_DEFINE(M_IPID, "ipid", "randomized ip id state");
-static VNET_DEFINE(uint16_t *, id_array);
-static VNET_DEFINE(bitstr_t *, id_bits);
-static VNET_DEFINE(int, array_ptr);
-static VNET_DEFINE(int, array_size);
-static VNET_DEFINE(int, random_id_collisions);
-static VNET_DEFINE(int, random_id_total);
-static VNET_DEFINE(struct mtx, ip_id_mtx);
+VNET_DEFINE_STATIC(uint16_t *, id_array);
+VNET_DEFINE_STATIC(bitstr_t *, id_bits);
+VNET_DEFINE_STATIC(int, array_ptr);
+VNET_DEFINE_STATIC(int, array_size);
+VNET_DEFINE_STATIC(int, random_id_collisions);
+VNET_DEFINE_STATIC(int, random_id_total);
+VNET_DEFINE_STATIC(struct mtx, ip_id_mtx);
#define V_id_array VNET(id_array)
#define V_id_bits VNET(id_bits)
#define V_array_ptr VNET(array_ptr)
@@ -127,7 +127,7 @@ static VNET_DEFINE(struct mtx, ip_id_mtx);
/*
* Non-random ID state engine is simply a per-cpu counter.
*/
-static VNET_DEFINE(counter_u64_t, ip_id);
+VNET_DEFINE_STATIC(counter_u64_t, ip_id);
#define V_ip_id VNET(ip_id)
static int sysctl_ip_randomid(SYSCTL_HANDLER_ARGS);
diff --git a/freebsd/sys/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c
index 343eec5e..2852b52e 100644
--- a/freebsd/sys/netinet/ip_input.c
+++ b/freebsd/sys/netinet/ip_input.c
@@ -111,7 +111,7 @@ SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_VNET | CTLFLAG_RW
&VNET_NAME(ipforwarding), 0,
"Enable IP forwarding between interfaces");
-static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */
+VNET_DEFINE_STATIC(int, ipsendredirects) = 1; /* XXX */
#define V_ipsendredirects VNET(ipsendredirects)
SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(ipsendredirects), 0,
@@ -130,7 +130,7 @@ SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_VNET | CTLFLAG_R
* to the loopback interface instead of the interface where the
* packets for those addresses are received.
*/
-static VNET_DEFINE(int, ip_checkinterface);
+VNET_DEFINE_STATIC(int, ip_checkinterface);
#define V_ip_checkinterface VNET(ip_checkinterface)
SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(ip_checkinterface), 0,
@@ -559,13 +559,15 @@ tooshort:
/*
* Try to forward the packet, but if we fail continue.
+ * ip_tryforward() does not generate redirects, so fall
+ * through to normal processing if redirects are required.
* ip_tryforward() does inbound and outbound packet firewall
* processing. If firewall has decided that destination becomes
* our local address, it sets M_FASTFWD_OURS flag. In this
* case skip another inbound firewall processing and update
* ip pointer.
*/
- if (V_ipforwarding != 0
+ if (V_ipforwarding != 0 && V_ipsendredirects == 0
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
&& (!IPSEC_ENABLED(ipv4) ||
IPSEC_CAPS(ipv4, m, IPSEC_CAP_OPERABLE) == 0)
@@ -1349,7 +1351,7 @@ makedummy:
* locking. This code remains in ip_input.c as ip_mroute.c is optionally
* compiled.
*/
-static VNET_DEFINE(int, ip_rsvp_on);
+VNET_DEFINE_STATIC(int, ip_rsvp_on);
VNET_DEFINE(struct socket *, ip_rsvpd);
#define V_ip_rsvp_on VNET(ip_rsvp_on)
diff --git a/freebsd/sys/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c
index ac901601..987549c6 100644
--- a/freebsd/sys/netinet/ip_mroute.c
+++ b/freebsd/sys/netinet/ip_mroute.c
@@ -127,7 +127,7 @@ __FBSDID("$FreeBSD$");
#define VIFI_INVALID ((vifi_t) -1)
-static VNET_DEFINE(uint32_t, last_tv_sec); /* last time we processed this */
+VNET_DEFINE_STATIC(uint32_t, last_tv_sec); /* last time we processed this */
#define V_last_tv_sec VNET(last_tv_sec)
static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache");
@@ -151,14 +151,14 @@ static struct mtx mrouter_mtx;
static int ip_mrouter_cnt; /* # of vnets with active mrouters */
static int ip_mrouter_unloading; /* Allow no more V_ip_mrouter sockets */
-static VNET_PCPUSTAT_DEFINE(struct mrtstat, mrtstat);
+VNET_PCPUSTAT_DEFINE_STATIC(struct mrtstat, mrtstat);
VNET_PCPUSTAT_SYSINIT(mrtstat);
VNET_PCPUSTAT_SYSUNINIT(mrtstat);
SYSCTL_VNET_PCPUSTAT(_net_inet_ip, OID_AUTO, mrtstat, struct mrtstat,
mrtstat, "IPv4 Multicast Forwarding Statistics (struct mrtstat, "
"netinet/ip_mroute.h)");
-static VNET_DEFINE(u_long, mfchash);
+VNET_DEFINE_STATIC(u_long, mfchash);
#define V_mfchash VNET(mfchash)
#define MFCHASH(a, g) \
((((a).s_addr >> 20) ^ ((a).s_addr >> 10) ^ (a).s_addr ^ \
@@ -166,9 +166,9 @@ static VNET_DEFINE(u_long, mfchash);
#define MFCHASHSIZE 256
static u_long mfchashsize; /* Hash size */
-static VNET_DEFINE(u_char *, nexpire); /* 0..mfchashsize-1 */
+VNET_DEFINE_STATIC(u_char *, nexpire); /* 0..mfchashsize-1 */
#define V_nexpire VNET(nexpire)
-static VNET_DEFINE(LIST_HEAD(mfchashhdr, mfc)*, mfchashtbl);
+VNET_DEFINE_STATIC(LIST_HEAD(mfchashhdr, mfc)*, mfchashtbl);
#define V_mfchashtbl VNET(mfchashtbl)
static struct mtx mfc_mtx;
@@ -179,9 +179,9 @@ static struct mtx mfc_mtx;
mtx_init(&mfc_mtx, "IPv4 multicast forwarding cache", NULL, MTX_DEF)
#define MFC_LOCK_DESTROY() mtx_destroy(&mfc_mtx)
-static VNET_DEFINE(vifi_t, numvifs);
+VNET_DEFINE_STATIC(vifi_t, numvifs);
#define V_numvifs VNET(numvifs)
-static VNET_DEFINE(struct vif, viftable[MAXVIFS]);
+VNET_DEFINE_STATIC(struct vif, viftable[MAXVIFS]);
#define V_viftable VNET(viftable)
SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_VNET | CTLFLAG_RD,
&VNET_NAME(viftable), sizeof(V_viftable), "S,vif[MAXVIFS]",
@@ -197,7 +197,7 @@ static struct mtx vif_mtx;
static eventhandler_tag if_detach_event_tag = NULL;
-static VNET_DEFINE(struct callout, expire_upcalls_ch);
+VNET_DEFINE_STATIC(struct callout, expire_upcalls_ch);
#define V_expire_upcalls_ch VNET(expire_upcalls_ch)
#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
@@ -212,9 +212,9 @@ static MALLOC_DEFINE(M_BWMETER, "bwmeter", "multicast upcall bw meters");
* expiration time. Periodically, the entries are analysed and processed.
*/
#define BW_METER_BUCKETS 1024
-static VNET_DEFINE(struct bw_meter*, bw_meter_timers[BW_METER_BUCKETS]);
+VNET_DEFINE_STATIC(struct bw_meter*, bw_meter_timers[BW_METER_BUCKETS]);
#define V_bw_meter_timers VNET(bw_meter_timers)
-static VNET_DEFINE(struct callout, bw_meter_ch);
+VNET_DEFINE_STATIC(struct callout, bw_meter_ch);
#define V_bw_meter_ch VNET(bw_meter_ch)
#define BW_METER_PERIOD (hz) /* periodical handling of bw meters */
@@ -222,16 +222,16 @@ static VNET_DEFINE(struct callout, bw_meter_ch);
* Pending upcalls are stored in a vector which is flushed when
* full, or periodically
*/
-static VNET_DEFINE(struct bw_upcall, bw_upcalls[BW_UPCALLS_MAX]);
+VNET_DEFINE_STATIC(struct bw_upcall, bw_upcalls[BW_UPCALLS_MAX]);
#define V_bw_upcalls VNET(bw_upcalls)
-static VNET_DEFINE(u_int, bw_upcalls_n); /* # of pending upcalls */
+VNET_DEFINE_STATIC(u_int, bw_upcalls_n); /* # of pending upcalls */
#define V_bw_upcalls_n VNET(bw_upcalls_n)
-static VNET_DEFINE(struct callout, bw_upcalls_ch);
+VNET_DEFINE_STATIC(struct callout, bw_upcalls_ch);
#define V_bw_upcalls_ch VNET(bw_upcalls_ch)
#define BW_UPCALLS_PERIOD (hz) /* periodical flush of bw upcalls */
-static VNET_PCPUSTAT_DEFINE(struct pimstat, pimstat);
+VNET_PCPUSTAT_DEFINE_STATIC(struct pimstat, pimstat);
VNET_PCPUSTAT_SYSINIT(pimstat);
VNET_PCPUSTAT_SYSUNINIT(pimstat);
@@ -244,20 +244,17 @@ SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW,
&pim_squelch_wholepkt, 0,
"Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified");
-extern struct domain inetdomain;
-static const struct protosw in_pim_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_PIM,
- .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
- .pr_input = pim_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
static const struct encaptab *pim_encap_cookie;
-
static int pim_encapcheck(const struct mbuf *, int, int, void *);
+static int pim_input(struct mbuf *, int, int, void *);
+
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_PIM,
+ .min_length = sizeof(struct ip) + PIM_MINLEN,
+ .exact_match = 8,
+ .check = pim_encapcheck,
+ .input = pim_input
+};
/*
* Note: the PIM Register encapsulation adds the following in front of a
@@ -302,9 +299,9 @@ static struct pim_encap_pimhdr pim_encap_pimhdr = {
0 /* flags */
};
-static VNET_DEFINE(vifi_t, reg_vif_num) = VIFI_INVALID;
+VNET_DEFINE_STATIC(vifi_t, reg_vif_num) = VIFI_INVALID;
#define V_reg_vif_num VNET(reg_vif_num)
-static VNET_DEFINE(struct ifnet, multicast_register_if);
+VNET_DEFINE_STATIC(struct ifnet, multicast_register_if);
#define V_multicast_register_if VNET(multicast_register_if)
/*
@@ -373,9 +370,9 @@ static const uint32_t mrt_api_support = (MRT_MFC_FLAGS_DISABLE_WRONGVIF |
MRT_MFC_FLAGS_BORDER_VIF |
MRT_MFC_RP |
MRT_MFC_BW_UPCALL);
-static VNET_DEFINE(uint32_t, mrt_api_config);
+VNET_DEFINE_STATIC(uint32_t, mrt_api_config);
#define V_mrt_api_config VNET(mrt_api_config)
-static VNET_DEFINE(int, pim_assert_enabled);
+VNET_DEFINE_STATIC(int, pim_assert_enabled);
#define V_pim_assert_enabled VNET(pim_assert_enabled)
static struct timeval pim_assert_interval = { 3, 0 }; /* Rate limit */
@@ -2546,16 +2543,12 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy,
* into the kernel.
*/
static int
-pim_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+pim_encapcheck(const struct mbuf *m __unused, int off __unused,
+ int proto __unused, void *arg __unused)
{
-#ifdef DIAGNOSTIC
KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
-#endif
- if (proto != IPPROTO_PIM)
- return 0; /* not for us; reject the datagram. */
-
- return 64; /* claim the datagram. */
+ return (8); /* claim the datagram. */
}
/*
@@ -2566,18 +2559,15 @@ pim_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
* (used by PIM-SM): the PIM header is stripped off, and the inner packet
* is passed to if_simloop().
*/
-int
-pim_input(struct mbuf **mp, int *offp, int proto)
+static int
+pim_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
- struct mbuf *m = *mp;
struct ip *ip = mtod(m, struct ip *);
struct pim *pim;
- int iphlen = *offp;
+ int iphlen = off;
int minlen;
int datalen = ntohs(ip->ip_len) - iphlen;
int ip_tos;
-
- *mp = NULL;
/* Keep statistics */
PIMSTAT_INC(pims_rcv_total_msgs);
@@ -2781,10 +2771,7 @@ pim_input_to_daemon:
* XXX: the outer IP header pkt size of a Register is not adjust to
* reflect the fact that the inner multicast data is truncated.
*/
- *mp = m;
- rip_input(mp, offp, proto);
-
- return (IPPROTO_DONE);
+ return (rip_input(&m, &off, proto));
}
static int
@@ -2877,8 +2864,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt",
&pim_squelch_wholepkt);
- pim_encap_cookie = encap_attach_func(AF_INET, IPPROTO_PIM,
- pim_encapcheck, &in_pim_protosw, NULL);
+ pim_encap_cookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
if (pim_encap_cookie == NULL) {
printf("ip_mroute: unable to attach pim encap\n");
VIF_LOCK_DESTROY();
@@ -2921,7 +2907,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag);
if (pim_encap_cookie) {
- encap_detach(pim_encap_cookie);
+ ip_encap_detach(pim_encap_cookie);
pim_encap_cookie = NULL;
}
diff --git a/freebsd/sys/netinet/ip_options.c b/freebsd/sys/netinet/ip_options.c
index cc2f3eed..7c189bdb 100644
--- a/freebsd/sys/netinet/ip_options.c
+++ b/freebsd/sys/netinet/ip_options.c
@@ -70,13 +70,13 @@ __FBSDID("$FreeBSD$");
#include <sys/socketvar.h>
-static VNET_DEFINE(int, ip_dosourceroute);
+VNET_DEFINE_STATIC(int, ip_dosourceroute);
SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_dosourceroute), 0,
"Enable forwarding source routed IP packets");
#define V_ip_dosourceroute VNET(ip_dosourceroute)
-static VNET_DEFINE(int, ip_acceptsourceroute);
+VNET_DEFINE_STATIC(int, ip_acceptsourceroute);
SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_acceptsourceroute), 0,
"Enable accepting source routed IP packets");
diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c
index 792f2311..5f643746 100644
--- a/freebsd/sys/netinet/ip_output.c
+++ b/freebsd/sys/netinet/ip_output.c
@@ -82,6 +82,10 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
#include <netinet/ip_options.h>
+
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
#ifdef SCTP
#include <netinet/sctp.h>
#include <netinet/sctp_crc32.h>
@@ -922,24 +926,34 @@ void
in_delayed_cksum(struct mbuf *m)
{
struct ip *ip;
- uint16_t csum, offset, ip_len;
+ struct udphdr *uh;
+ uint16_t cklen, csum, offset;
ip = mtod(m, struct ip *);
offset = ip->ip_hl << 2 ;
- ip_len = ntohs(ip->ip_len);
- csum = in_cksum_skip(m, ip_len, offset);
- if (m->m_pkthdr.csum_flags & CSUM_UDP && csum == 0)
- csum = 0xffff;
- offset += m->m_pkthdr.csum_data; /* checksum offset */
- /* find the mbuf in the chain where the checksum starts*/
- while ((m != NULL) && (offset >= m->m_len)) {
- offset -= m->m_len;
- m = m->m_next;
+ if (m->m_pkthdr.csum_flags & CSUM_UDP) {
+ /* if udp header is not in the first mbuf copy udplen */
+ if (offset + sizeof(struct udphdr) > m->m_len)
+ m_copydata(m, offset + offsetof(struct udphdr,
+ uh_ulen), sizeof(cklen), (caddr_t)&cklen);
+ else {
+ uh = (struct udphdr *)mtodo(m, offset);
+ cklen = ntohs(uh->uh_ulen);
+ }
+ csum = in_cksum_skip(m, cklen + offset, offset);
+ if (csum == 0)
+ csum = 0xffff;
+ } else {
+ cklen = ntohs(ip->ip_len);
+ csum = in_cksum_skip(m, cklen, offset);
}
- KASSERT(m != NULL, ("in_delayed_cksum: checksum outside mbuf chain."));
- KASSERT(offset + sizeof(u_short) <= m->m_len, ("in_delayed_cksum: checksum split between mbufs."));
- *(u_short *)(m->m_data + offset) = csum;
+ offset += m->m_pkthdr.csum_data; /* checksum offset */
+
+ if (offset + sizeof(csum) > m->m_len)
+ m_copyback(m, offset, sizeof(csum), (caddr_t)&csum);
+ else
+ *(u_short *)mtodo(m, offset) = csum;
}
/*
@@ -980,6 +994,15 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
INP_WUNLOCK(inp);
error = 0;
break;
+ case SO_REUSEPORT_LB:
+ INP_WLOCK(inp);
+ if ((so->so_options & SO_REUSEPORT_LB) != 0)
+ inp->inp_flags2 |= INP_REUSEPORT_LB;
+ else
+ inp->inp_flags2 &= ~INP_REUSEPORT_LB;
+ INP_WUNLOCK(inp);
+ error = 0;
+ break;
case SO_SETFIB:
INP_WLOCK(inp);
inp->inp_inc.inc_fibnum = so->so_fibnum;
@@ -1235,13 +1258,23 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
switch (sopt->sopt_name) {
case IP_OPTIONS:
case IP_RETOPTS:
- if (inp->inp_options)
- error = sooptcopyout(sopt,
- mtod(inp->inp_options,
- char *),
- inp->inp_options->m_len);
- else
+ INP_RLOCK(inp);
+ if (inp->inp_options) {
+ struct mbuf *options;
+
+ options = m_dup(inp->inp_options, M_NOWAIT);
+ INP_RUNLOCK(inp);
+ if (options != NULL) {
+ error = sooptcopyout(sopt,
+ mtod(options, char *),
+ options->m_len);
+ m_freem(options);
+ } else
+ error = ENOMEM;
+ } else {
+ INP_RUNLOCK(inp);
sopt->sopt_valsize = 0;
+ }
break;
case IP_TOS:
diff --git a/freebsd/sys/netinet/ip_reass.c b/freebsd/sys/netinet/ip_reass.c
index 64660228..95603390 100644
--- a/freebsd/sys/netinet/ip_reass.c
+++ b/freebsd/sys/netinet/ip_reass.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/hash.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
@@ -65,18 +66,19 @@ SYSCTL_DECL(_net_inet_ip);
/*
* Reassembly headers are stored in hash buckets.
*/
-#define IPREASS_NHASH_LOG2 6
+#define IPREASS_NHASH_LOG2 10
#define IPREASS_NHASH (1 << IPREASS_NHASH_LOG2)
#define IPREASS_HMASK (IPREASS_NHASH - 1)
struct ipqbucket {
TAILQ_HEAD(ipqhead, ipq) head;
struct mtx lock;
+ int count;
};
-static VNET_DEFINE(struct ipqbucket, ipq[IPREASS_NHASH]);
+VNET_DEFINE_STATIC(struct ipqbucket, ipq[IPREASS_NHASH]);
#define V_ipq VNET(ipq)
-static VNET_DEFINE(uint32_t, ipq_hashseed);
+VNET_DEFINE_STATIC(uint32_t, ipq_hashseed);
#define V_ipq_hashseed VNET(ipq_hashseed)
#define IPQ_LOCK(i) mtx_lock(&V_ipq[i].lock)
@@ -84,6 +86,9 @@ static VNET_DEFINE(uint32_t, ipq_hashseed);
#define IPQ_UNLOCK(i) mtx_unlock(&V_ipq[i].lock)
#define IPQ_LOCK_ASSERT(i) mtx_assert(&V_ipq[i].lock, MA_OWNED)
+VNET_DEFINE_STATIC(int, ipreass_maxbucketsize);
+#define V_ipreass_maxbucketsize VNET(ipreass_maxbucketsize)
+
void ipreass_init(void);
void ipreass_drain(void);
void ipreass_slowtimo(void);
@@ -91,28 +96,54 @@ void ipreass_slowtimo(void);
void ipreass_destroy(void);
#endif
static int sysctl_maxfragpackets(SYSCTL_HANDLER_ARGS);
+static int sysctl_maxfragbucketsize(SYSCTL_HANDLER_ARGS);
static void ipreass_zone_change(void *);
static void ipreass_drain_tomax(void);
-static void ipq_free(struct ipqhead *, struct ipq *);
+static void ipq_free(struct ipqbucket *, struct ipq *);
static struct ipq * ipq_reuse(int);
static inline void
-ipq_timeout(struct ipqhead *head, struct ipq *fp)
+ipq_timeout(struct ipqbucket *bucket, struct ipq *fp)
{
IPSTAT_ADD(ips_fragtimeout, fp->ipq_nfrags);
- ipq_free(head, fp);
+ ipq_free(bucket, fp);
}
static inline void
-ipq_drop(struct ipqhead *head, struct ipq *fp)
+ipq_drop(struct ipqbucket *bucket, struct ipq *fp)
{
IPSTAT_ADD(ips_fragdropped, fp->ipq_nfrags);
- ipq_free(head, fp);
+ ipq_free(bucket, fp);
}
-static VNET_DEFINE(uma_zone_t, ipq_zone);
+/*
+ * By default, limit the number of IP fragments across all reassembly
+ * queues to 1/32 of the total number of mbuf clusters.
+ *
+ * Limit the total number of reassembly queues per VNET to the
+ * IP fragment limit, but ensure the limit will not allow any bucket
+ * to grow above 100 items. (The bucket limit is
+ * IP_MAXFRAGPACKETS / (IPREASS_NHASH / 2), so the 50 is the correct
+ * multiplier to reach a 100-item limit.)
+ * The 100-item limit was chosen as brief testing seems to show that
+ * this produces "reasonable" performance on some subset of systems
+ * under DoS attack.
+ */
+#define IP_MAXFRAGS (nmbclusters / 32)
+#define IP_MAXFRAGPACKETS (imin(IP_MAXFRAGS, IPREASS_NHASH * 50))
+
+static int maxfrags;
+static volatile u_int nfrags;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfrags, CTLFLAG_RW,
+ &maxfrags, 0,
+ "Maximum number of IPv4 fragments allowed across all reassembly queues");
+SYSCTL_UINT(_net_inet_ip, OID_AUTO, curfrags, CTLFLAG_RD,
+ __DEVOLATILE(u_int *, &nfrags), 0,
+ "Current number of IPv4 fragments across all reassembly queues");
+
+VNET_DEFINE_STATIC(uma_zone_t, ipq_zone);
#define V_ipq_zone VNET(ipq_zone)
SYSCTL_PROC(_net_inet_ip, OID_AUTO, maxfragpackets, CTLFLAG_VNET |
CTLTYPE_INT | CTLFLAG_RW, NULL, 0, sysctl_maxfragpackets, "I",
@@ -121,14 +152,18 @@ SYSCTL_UMA_CUR(_net_inet_ip, OID_AUTO, fragpackets, CTLFLAG_VNET,
&VNET_NAME(ipq_zone),
"Current number of IPv4 fragment reassembly queue entries");
-static VNET_DEFINE(int, noreass);
+VNET_DEFINE_STATIC(int, noreass);
#define V_noreass VNET(noreass)
-static VNET_DEFINE(int, maxfragsperpacket);
+VNET_DEFINE_STATIC(int, maxfragsperpacket);
#define V_maxfragsperpacket VNET(maxfragsperpacket)
SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfragsperpacket, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(maxfragsperpacket), 0,
"Maximum number of IPv4 fragments allowed per packet");
+SYSCTL_PROC(_net_inet_ip, OID_AUTO, maxfragbucketsize,
+ CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RW, NULL, 0,
+ sysctl_maxfragbucketsize, "I",
+ "Maximum number of IPv4 fragment reassembly queue entries per bucket");
/*
* Take incoming datagram fragment and try to reassemble it into
@@ -148,9 +183,9 @@ ip_reass(struct mbuf *m)
struct mbuf *p, *q, *nq, *t;
struct ipq *fp;
struct ipqhead *head;
- int i, hlen, next;
+ int i, hlen, next, tmpmax;
u_int8_t ecn, ecn0;
- uint32_t hash;
+ uint32_t hash, hashkey[3];
#ifdef RSS
uint32_t rss_hash, rss_type;
#endif
@@ -158,8 +193,12 @@ ip_reass(struct mbuf *m)
/*
* If no reassembling or maxfragsperpacket are 0,
* never accept fragments.
+ * Also, drop packet if it would exceed the maximum
+ * number of fragments.
*/
- if (V_noreass == 1 || V_maxfragsperpacket == 0) {
+ tmpmax = maxfrags;
+ if (V_noreass == 1 || V_maxfragsperpacket == 0 ||
+ (tmpmax >= 0 && atomic_load_int(&nfrags) >= (u_int)tmpmax)) {
IPSTAT_INC(ips_fragments);
IPSTAT_INC(ips_fragdropped);
m_freem(m);
@@ -204,8 +243,12 @@ ip_reass(struct mbuf *m)
m->m_data += hlen;
m->m_len -= hlen;
- hash = ip->ip_src.s_addr ^ ip->ip_id;
- hash = jenkins_hash32(&hash, 1, V_ipq_hashseed) & IPREASS_HMASK;
+ hashkey[0] = ip->ip_src.s_addr;
+ hashkey[1] = ip->ip_dst.s_addr;
+ hashkey[2] = (uint32_t)ip->ip_p << 16;
+ hashkey[2] += ip->ip_id;
+ hash = jenkins_hash32(hashkey, nitems(hashkey), V_ipq_hashseed);
+ hash &= IPREASS_HMASK;
head = &V_ipq[hash].head;
IPQ_LOCK(hash);
@@ -226,9 +269,12 @@ ip_reass(struct mbuf *m)
* If first fragment to arrive, create a reassembly queue.
*/
if (fp == NULL) {
- fp = uma_zalloc(V_ipq_zone, M_NOWAIT);
+ if (V_ipq[hash].count < V_ipreass_maxbucketsize)
+ fp = uma_zalloc(V_ipq_zone, M_NOWAIT);
if (fp == NULL)
fp = ipq_reuse(hash);
+ if (fp == NULL)
+ goto dropfrag;
#ifdef MAC
if (mac_ipq_init(fp, M_NOWAIT) != 0) {
uma_zfree(V_ipq_zone, fp);
@@ -238,7 +284,9 @@ ip_reass(struct mbuf *m)
mac_ipq_create(m, fp);
#endif
TAILQ_INSERT_HEAD(head, fp, ipq_list);
+ V_ipq[hash].count++;
fp->ipq_nfrags = 1;
+ atomic_add_int(&nfrags, 1);
fp->ipq_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id;
@@ -249,6 +297,7 @@ ip_reass(struct mbuf *m)
goto done;
} else {
fp->ipq_nfrags++;
+ atomic_add_int(&nfrags, 1);
#ifdef MAC
mac_ipq_update(m, fp);
#endif
@@ -325,6 +374,7 @@ ip_reass(struct mbuf *m)
m->m_nextpkt = nq;
IPSTAT_INC(ips_fragdropped);
fp->ipq_nfrags--;
+ atomic_subtract_int(&nfrags, 1);
m_freem(q);
}
@@ -342,7 +392,7 @@ ip_reass(struct mbuf *m)
for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) {
if (ntohs(GETIP(q)->ip_off) != next) {
if (fp->ipq_nfrags > V_maxfragsperpacket)
- ipq_drop(head, fp);
+ ipq_drop(&V_ipq[hash], fp);
goto done;
}
next += ntohs(GETIP(q)->ip_len);
@@ -350,7 +400,7 @@ ip_reass(struct mbuf *m)
/* Make sure the last packet didn't have the IP_MF flag */
if (p->m_flags & M_IP_FRAG) {
if (fp->ipq_nfrags > V_maxfragsperpacket)
- ipq_drop(head, fp);
+ ipq_drop(&V_ipq[hash], fp);
goto done;
}
@@ -361,7 +411,7 @@ ip_reass(struct mbuf *m)
ip = GETIP(q);
if (next + (ip->ip_hl << 2) > IP_MAXPACKET) {
IPSTAT_INC(ips_toolong);
- ipq_drop(head, fp);
+ ipq_drop(&V_ipq[hash], fp);
goto done;
}
@@ -390,6 +440,7 @@ ip_reass(struct mbuf *m)
while (m->m_pkthdr.csum_data & 0xffff0000)
m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) +
(m->m_pkthdr.csum_data >> 16);
+ atomic_subtract_int(&nfrags, fp->ipq_nfrags);
#ifdef MAC
mac_ipq_reassemble(fp, m);
mac_ipq_destroy(fp);
@@ -404,6 +455,7 @@ ip_reass(struct mbuf *m)
ip->ip_src = fp->ipq_src;
ip->ip_dst = fp->ipq_dst;
TAILQ_REMOVE(head, fp, ipq_list);
+ V_ipq[hash].count--;
uma_zfree(V_ipq_zone, fp);
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
@@ -449,8 +501,10 @@ ip_reass(struct mbuf *m)
dropfrag:
IPSTAT_INC(ips_fragdropped);
- if (fp != NULL)
+ if (fp != NULL) {
fp->ipq_nfrags--;
+ atomic_subtract_int(&nfrags, 1);
+ }
m_freem(m);
done:
IPQ_UNLOCK(hash);
@@ -465,21 +519,27 @@ done:
void
ipreass_init(void)
{
+ int max;
for (int i = 0; i < IPREASS_NHASH; i++) {
TAILQ_INIT(&V_ipq[i].head);
mtx_init(&V_ipq[i].lock, "IP reassembly", NULL,
MTX_DEF | MTX_DUPOK);
+ V_ipq[i].count = 0;
}
V_ipq_hashseed = arc4random();
V_maxfragsperpacket = 16;
V_ipq_zone = uma_zcreate("ipq", sizeof(struct ipq), NULL, NULL, NULL,
NULL, UMA_ALIGN_PTR, 0);
- uma_zone_set_max(V_ipq_zone, nmbclusters / 32);
+ max = IP_MAXFRAGPACKETS;
+ max = uma_zone_set_max(V_ipq_zone, max);
+ V_ipreass_maxbucketsize = imax(max / (IPREASS_NHASH / 2), 1);
- if (IS_DEFAULT_VNET(curvnet))
+ if (IS_DEFAULT_VNET(curvnet)) {
+ maxfrags = IP_MAXFRAGS;
EVENTHANDLER_REGISTER(nmbclusters_change, ipreass_zone_change,
NULL, EVENTHANDLER_PRI_ANY);
+ }
}
/*
@@ -494,7 +554,7 @@ ipreass_slowtimo(void)
IPQ_LOCK(i);
TAILQ_FOREACH_SAFE(fp, &V_ipq[i].head, ipq_list, tmp)
if (--fp->ipq_ttl == 0)
- ipq_timeout(&V_ipq[i].head, fp);
+ ipq_timeout(&V_ipq[i], fp);
IPQ_UNLOCK(i);
}
}
@@ -509,7 +569,10 @@ ipreass_drain(void)
for (int i = 0; i < IPREASS_NHASH; i++) {
IPQ_LOCK(i);
while(!TAILQ_EMPTY(&V_ipq[i].head))
- ipq_drop(&V_ipq[i].head, TAILQ_FIRST(&V_ipq[i].head));
+ ipq_drop(&V_ipq[i], TAILQ_FIRST(&V_ipq[i].head));
+ KASSERT(V_ipq[i].count == 0,
+ ("%s: V_ipq[%d] count %d (V_ipq=%p)", __func__, i,
+ V_ipq[i].count, V_ipq));
IPQ_UNLOCK(i);
}
}
@@ -537,9 +600,23 @@ ipreass_destroy(void)
static void
ipreass_drain_tomax(void)
{
+ struct ipq *fp;
int target;
/*
+ * Make sure each bucket is under the new limit. If
+ * necessary, drop enough of the oldest elements from
+ * each bucket to get under the new limit.
+ */
+ for (int i = 0; i < IPREASS_NHASH; i++) {
+ IPQ_LOCK(i);
+ while (V_ipq[i].count > V_ipreass_maxbucketsize &&
+ (fp = TAILQ_LAST(&V_ipq[i].head, ipqhead)) != NULL)
+ ipq_timeout(&V_ipq[i], fp);
+ IPQ_UNLOCK(i);
+ }
+
+ /*
* If we are over the maximum number of fragments,
* drain off enough to get down to the new limit,
* stripping off last elements on queues. Every
@@ -547,13 +624,11 @@ ipreass_drain_tomax(void)
*/
target = uma_zone_get_max(V_ipq_zone);
while (uma_zone_get_cur(V_ipq_zone) > target) {
- struct ipq *fp;
-
for (int i = 0; i < IPREASS_NHASH; i++) {
IPQ_LOCK(i);
fp = TAILQ_LAST(&V_ipq[i].head, ipqhead);
if (fp != NULL)
- ipq_timeout(&V_ipq[i].head, fp);
+ ipq_timeout(&V_ipq[i], fp);
IPQ_UNLOCK(i);
}
}
@@ -562,9 +637,20 @@ ipreass_drain_tomax(void)
static void
ipreass_zone_change(void *tag)
{
-
- uma_zone_set_max(V_ipq_zone, nmbclusters / 32);
- ipreass_drain_tomax();
+ VNET_ITERATOR_DECL(vnet_iter);
+ int max;
+
+ maxfrags = IP_MAXFRAGS;
+ max = IP_MAXFRAGPACKETS;
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ max = uma_zone_set_max(V_ipq_zone, max);
+ V_ipreass_maxbucketsize = imax(max / (IPREASS_NHASH / 2), 1);
+ ipreass_drain_tomax();
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
@@ -592,6 +678,7 @@ sysctl_maxfragpackets(SYSCTL_HANDLER_ARGS)
* and place an extreme upper bound.
*/
max = uma_zone_set_max(V_ipq_zone, max);
+ V_ipreass_maxbucketsize = imax(max / (IPREASS_NHASH / 2), 1);
ipreass_drain_tomax();
V_noreass = 0;
} else if (max == 0) {
@@ -600,6 +687,7 @@ sysctl_maxfragpackets(SYSCTL_HANDLER_ARGS)
} else if (max == -1) {
V_noreass = 0;
uma_zone_set_max(V_ipq_zone, 0);
+ V_ipreass_maxbucketsize = INT_MAX;
} else
return (EINVAL);
return (0);
@@ -613,49 +701,72 @@ static struct ipq *
ipq_reuse(int start)
{
struct ipq *fp;
- int i;
+ int bucket, i;
IPQ_LOCK_ASSERT(start);
- for (i = start;; i++) {
- if (i == IPREASS_NHASH)
- i = 0;
- if (i != start && IPQ_TRYLOCK(i) == 0)
+ for (i = 0; i < IPREASS_NHASH; i++) {
+ bucket = (start + i) % IPREASS_NHASH;
+ if (bucket != start && IPQ_TRYLOCK(bucket) == 0)
continue;
- fp = TAILQ_LAST(&V_ipq[i].head, ipqhead);
+ fp = TAILQ_LAST(&V_ipq[bucket].head, ipqhead);
if (fp) {
struct mbuf *m;
IPSTAT_ADD(ips_fragtimeout, fp->ipq_nfrags);
+ atomic_subtract_int(&nfrags, fp->ipq_nfrags);
while (fp->ipq_frags) {
m = fp->ipq_frags;
fp->ipq_frags = m->m_nextpkt;
m_freem(m);
}
- TAILQ_REMOVE(&V_ipq[i].head, fp, ipq_list);
- if (i != start)
- IPQ_UNLOCK(i);
- IPQ_LOCK_ASSERT(start);
- return (fp);
+ TAILQ_REMOVE(&V_ipq[bucket].head, fp, ipq_list);
+ V_ipq[bucket].count--;
+ if (bucket != start)
+ IPQ_UNLOCK(bucket);
+ break;
}
- if (i != start)
- IPQ_UNLOCK(i);
+ if (bucket != start)
+ IPQ_UNLOCK(bucket);
}
+ IPQ_LOCK_ASSERT(start);
+ return (fp);
}
/*
* Free a fragment reassembly header and all associated datagrams.
*/
static void
-ipq_free(struct ipqhead *fhp, struct ipq *fp)
+ipq_free(struct ipqbucket *bucket, struct ipq *fp)
{
struct mbuf *q;
+ atomic_subtract_int(&nfrags, fp->ipq_nfrags);
while (fp->ipq_frags) {
q = fp->ipq_frags;
fp->ipq_frags = q->m_nextpkt;
m_freem(q);
}
- TAILQ_REMOVE(fhp, fp, ipq_list);
+ TAILQ_REMOVE(&bucket->head, fp, ipq_list);
+ bucket->count--;
uma_zfree(V_ipq_zone, fp);
}
+
+/*
+ * Get or set the maximum number of reassembly queues per bucket.
+ */
+static int
+sysctl_maxfragbucketsize(SYSCTL_HANDLER_ARGS)
+{
+ int error, max;
+
+ max = V_ipreass_maxbucketsize;
+ error = sysctl_handle_int(oidp, &max, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (max <= 0)
+ return (EINVAL);
+ V_ipreass_maxbucketsize = max;
+ ipreass_drain_tomax();
+ return (0);
+}
diff --git a/freebsd/sys/netinet/libalias/alias.c b/freebsd/sys/netinet/libalias/alias.c
index 2dd5b999..d4eeb040 100644
--- a/freebsd/sys/netinet/libalias/alias.c
+++ b/freebsd/sys/netinet/libalias/alias.c
@@ -1753,7 +1753,8 @@ LibAliasUnLoadAllModule(void)
* the input packet, on failure NULL. The input packet is always consumed.
*/
struct mbuf *
-m_megapullup(struct mbuf *m, int len) {
+m_megapullup(struct mbuf *m, int len)
+{
struct mbuf *mcl;
if (len > m->m_pkthdr.len)
@@ -1762,7 +1763,14 @@ m_megapullup(struct mbuf *m, int len) {
if (m->m_next == NULL && M_WRITABLE(m))
return (m);
- mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (len <= MJUMPAGESIZE)
+ mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
+ else if (len <= MJUM9BYTES)
+ mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
+ else if (len <= MJUM16BYTES)
+ mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
+ else
+ goto bad;
if (mcl == NULL)
goto bad;
m_align(mcl, len);
diff --git a/freebsd/sys/netinet/libalias/alias_irc.c b/freebsd/sys/netinet/libalias/alias_irc.c
index 1dbb9ddf..19337121 100644
--- a/freebsd/sys/netinet/libalias/alias_irc.c
+++ b/freebsd/sys/netinet/libalias/alias_irc.c
@@ -100,8 +100,7 @@ static int
fingerprint(struct libalias *la, struct alias_data *ah)
{
- if (ah->dport == NULL || ah->dport == NULL || ah->lnk == NULL ||
- ah->maxpktsize == 0)
+ if (ah->dport == NULL || ah->lnk == NULL || ah->maxpktsize == 0)
return (-1);
if (ntohs(*ah->dport) == IRC_CONTROL_PORT_NUMBER_1
|| ntohs(*ah->dport) == IRC_CONTROL_PORT_NUMBER_2)
diff --git a/freebsd/sys/netinet/libalias/alias_mod.h b/freebsd/sys/netinet/libalias/alias_mod.h
index c646f794..a894b6de 100644
--- a/freebsd/sys/netinet/libalias/alias_mod.h
+++ b/freebsd/sys/netinet/libalias/alias_mod.h
@@ -41,17 +41,17 @@ MALLOC_DECLARE(M_ALIAS);
/* Use kernel allocator. */
#if defined(_SYS_MALLOC_H_)
+#undef malloc
#ifndef __rtems__
#define malloc(x) malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
#define calloc(n, x) mallocarray((n), (x), M_ALIAS, M_NOWAIT|M_ZERO)
#define free(x) free(x, M_ALIAS)
#else /* __rtems__ */
-#undef malloc
#undef calloc
#undef free
-#define malloc(x) _bsd_malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
-#define calloc(x, n) malloc(x*n)
-#define free(x) _bsd_free(x, M_ALIAS)
+#define malloc(x) _bsd_malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
+#define calloc(n, x) mallocarray((n), (x), M_ALIAS, M_NOWAIT|M_ZERO)
+#define free(x) _bsd_free(x, M_ALIAS)
#endif /* __rtems__ */
#endif
#endif
diff --git a/freebsd/sys/netinet/pim_var.h b/freebsd/sys/netinet/pim_var.h
index e6398a4d..dfb06928 100644
--- a/freebsd/sys/netinet/pim_var.h
+++ b/freebsd/sys/netinet/pim_var.h
@@ -73,8 +73,6 @@ struct pimstat {
#define PIMCTL_STATS 1 /* statistics (read-only) */
#ifdef _KERNEL
-
-int pim_input(struct mbuf **, int *, int);
SYSCTL_DECL(_net_inet_pim);
#endif
diff --git a/freebsd/sys/netinet/raw_ip.c b/freebsd/sys/netinet/raw_ip.c
index 7dea3ec1..a97eadae 100644
--- a/freebsd/sys/netinet/raw_ip.c
+++ b/freebsd/sys/netinet/raw_ip.c
@@ -172,7 +172,7 @@ rip_inshash(struct inpcb *inp)
} else
hash = 0;
pcbhash = &pcbinfo->ipi_hashbase[hash];
- LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
+ CK_LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
}
static void
@@ -182,7 +182,7 @@ rip_delhash(struct inpcb *inp)
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
- LIST_REMOVE(inp, inp_hash);
+ CK_LIST_REMOVE(inp, inp_hash);
}
#endif /* INET */
@@ -287,6 +287,7 @@ rip_input(struct mbuf **mp, int *offp, int proto)
struct ip *ip = mtod(m, struct ip *);
struct inpcb *inp, *last;
struct sockaddr_in ripsrc;
+ struct epoch_tracker et;
int hash;
*mp = NULL;
@@ -301,8 +302,8 @@ rip_input(struct mbuf **mp, int *offp, int proto)
hash = INP_PCBHASH_RAW(proto, ip->ip_src.s_addr,
ip->ip_dst.s_addr, V_ripcbinfo.ipi_hashmask);
- INP_INFO_RLOCK(&V_ripcbinfo);
- LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[hash], inp_hash) {
+ INP_INFO_RLOCK_ET(&V_ripcbinfo, et);
+ CK_LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[hash], inp_hash) {
if (inp->inp_ip_p != proto)
continue;
#ifdef INET6
@@ -314,27 +315,33 @@ rip_input(struct mbuf **mp, int *offp, int proto)
continue;
if (inp->inp_faddr.s_addr != ip->ip_src.s_addr)
continue;
- if (jailed_without_vnet(inp->inp_cred)) {
- /*
- * XXX: If faddr was bound to multicast group,
- * jailed raw socket will drop datagram.
- */
- if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
- continue;
- }
if (last != NULL) {
struct mbuf *n;
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
if (n != NULL)
- (void) rip_append(last, ip, n, &ripsrc);
+ (void) rip_append(last, ip, n, &ripsrc);
/* XXX count dropped packet */
INP_RUNLOCK(last);
+ last = NULL;
}
INP_RLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED))
+ goto skip_1;
+ if (jailed_without_vnet(inp->inp_cred)) {
+ /*
+ * XXX: If faddr was bound to multicast group,
+ * jailed raw socket will drop datagram.
+ */
+ if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
+ goto skip_1;
+ }
last = inp;
+ continue;
+ skip_1:
+ INP_RUNLOCK(inp);
}
- LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[0], inp_hash) {
+ CK_LIST_FOREACH(inp, &V_ripcbinfo.ipi_hashbase[0], inp_hash) {
if (inp->inp_ip_p && inp->inp_ip_p != proto)
continue;
#ifdef INET6
@@ -348,6 +355,19 @@ rip_input(struct mbuf **mp, int *offp, int proto)
if (!in_nullhost(inp->inp_faddr) &&
!in_hosteq(inp->inp_faddr, ip->ip_src))
continue;
+ if (last != NULL) {
+ struct mbuf *n;
+
+ n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+ if (n != NULL)
+ (void) rip_append(last, ip, n, &ripsrc);
+ /* XXX count dropped packet */
+ INP_RUNLOCK(last);
+ last = NULL;
+ }
+ INP_RLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED))
+ goto skip_2;
if (jailed_without_vnet(inp->inp_cred)) {
/*
* Allow raw socket in jail to receive multicast;
@@ -356,7 +376,7 @@ rip_input(struct mbuf **mp, int *offp, int proto)
*/
if (!IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
- continue;
+ goto skip_2;
}
/*
* If this raw socket has multicast state, and we
@@ -397,22 +417,15 @@ rip_input(struct mbuf **mp, int *offp, int proto)
if (blocked != MCAST_PASS) {
IPSTAT_INC(ips_notmember);
- continue;
+ goto skip_2;
}
}
- if (last != NULL) {
- struct mbuf *n;
-
- n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
- if (n != NULL)
- (void) rip_append(last, ip, n, &ripsrc);
- /* XXX count dropped packet */
- INP_RUNLOCK(last);
- }
- INP_RLOCK(inp);
last = inp;
+ continue;
+ skip_2:
+ INP_RUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_ripcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
if (last != NULL) {
if (rip_append(last, ip, m, &ripsrc) != 0)
IPSTAT_INC(ips_delivered);
@@ -853,7 +866,6 @@ rip_detach(struct socket *so)
ip_rsvp_force_done(so);
if (so == V_ip_rsvpd)
ip_rsvp_done();
- /* XXX defer to epoch_call */
in_pcbdetach(inp);
in_pcbfree(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
@@ -1023,10 +1035,10 @@ static int
rip_pcblist(SYSCTL_HANDLER_ARGS)
{
int error, i, n;
- struct in_pcblist *il;
struct inpcb *inp, **inp_list;
inp_gen_t gencnt;
struct xinpgen xig;
+ struct epoch_tracker et;
/*
* The process of preparing the TCB list is too time-consuming and
@@ -1045,10 +1057,10 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
/*
* OK, now we're committed to doing something.
*/
- INP_INFO_RLOCK(&V_ripcbinfo);
+ INP_INFO_WLOCK(&V_ripcbinfo);
gencnt = V_ripcbinfo.ipi_gencnt;
n = V_ripcbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_ripcbinfo);
+ INP_INFO_WUNLOCK(&V_ripcbinfo);
xig.xig_len = sizeof xig;
xig.xig_count = n;
@@ -1058,12 +1070,11 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
- il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
- inp_list = il->il_inp_list;
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
- INP_INFO_RLOCK(&V_ripcbinfo);
- for (inp = LIST_FIRST(V_ripcbinfo.ipi_listhead), i = 0; inp && i < n;
- inp = LIST_NEXT(inp, inp_list)) {
+ INP_INFO_RLOCK_ET(&V_ripcbinfo, et);
+ for (inp = CK_LIST_FIRST(V_ripcbinfo.ipi_listhead), i = 0; inp && i < n;
+ inp = CK_LIST_NEXT(inp, inp_list)) {
INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt &&
cr_canseeinpcb(req->td->td_ucred, inp) == 0) {
@@ -1072,7 +1083,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
}
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_ripcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
n = i;
error = 0;
@@ -1088,24 +1099,31 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
} else
INP_RUNLOCK(inp);
}
- il->il_count = n;
- il->il_pcbinfo = &V_ripcbinfo;
- epoch_call(net_epoch_preempt, &il->il_epoch_ctx, in_pcblist_rele_rlocked);
+ INP_INFO_WLOCK(&V_ripcbinfo);
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
+ }
+ INP_INFO_WUNLOCK(&V_ripcbinfo);
if (!error) {
+ struct epoch_tracker et;
/*
* Give the user an updated idea of our state. If the
* generation differs from what we told her before, she knows
* that something happened while we were processing this
* request, and it might be necessary to retry.
*/
- INP_INFO_RLOCK(&V_ripcbinfo);
+ INP_INFO_RLOCK_ET(&V_ripcbinfo, et);
xig.xig_gen = V_ripcbinfo.ipi_gencnt;
xig.xig_sogen = so_gencnt;
xig.xig_count = V_ripcbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_ripcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
+ free(inp_list, M_TEMP);
return (error);
}
diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h
index 5a86f108..64fd5442 100644
--- a/freebsd/sys/netinet/sctp.h
+++ b/freebsd/sys/netinet/sctp.h
@@ -419,7 +419,7 @@ struct sctp_error_unresolv_addr {
struct sctp_error_unrecognized_chunk {
struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRECOG_CHUNK */
- struct sctp_chunkhdr ch;/* header from chunk in error */
+ struct sctp_chunkhdr ch; /* header from chunk in error */
} SCTP_PACKED;
struct sctp_error_no_user_data {
diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index d2d990e1..c21e3251 100644
--- a/freebsd/sys/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
@@ -279,6 +279,7 @@ sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
/* not found */
return (-1);
}
+
/* delete all destination addresses except the source */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if (net != src_net) {
@@ -385,6 +386,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
aparam_length);
return (m_reply);
}
+
/* if deleting 0.0.0.0/::0, delete all addresses except src addr */
if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
result = sctp_asconf_del_remote_addrs_except(stcb, src);
@@ -403,6 +405,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
}
return (m_reply);
}
+
/* delete the address */
result = sctp_del_remote_addr(stcb, sa);
/*
@@ -618,6 +621,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
serial_num, asoc->asconf_seq_in + 1);
return;
}
+
/* it's the expected "next" sequence number, so process it */
asoc->asconf_seq_in = serial_num; /* update sequence */
/* get length of all the param's in the ASCONF */
@@ -642,6 +646,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
}
}
+
m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
M_NOWAIT, 1, MT_DATA);
if (m_ack == NULL) {
@@ -976,6 +981,7 @@ sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
if (stcb->asoc.deleted_primary == NULL) {
return;
}
+
if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
@@ -1079,6 +1085,7 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
}
return;
}
+
/* Multiple local addresses exsist in the association. */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
/* clear any cached route and source address */
@@ -1325,6 +1332,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
if (stcb->asoc.asconf_supported == 0) {
return (-1);
}
+
/*
* if this is deleting the last address from the assoc, mark it as
* pending.
@@ -1345,6 +1353,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
return (-1);
}
}
+
/* queue an asconf parameter */
status = sctp_asconf_queue_mgmt(stcb, ifa, type);
@@ -1366,6 +1375,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
stcb->asoc.asconf_addr_del_pending = NULL;
}
}
+
if (pending_delete_queued) {
struct sctp_nets *net;
@@ -1390,6 +1400,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
SCTP_FROM_SCTP_ASCONF,
__LINE__);
}
+
/* queue in an advisory set primary too */
(void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
/* let caller know we should send this out immediately */
@@ -1687,11 +1698,13 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
serial_num, asoc->asconf_seq_out_acked + 1);
return;
}
+
if (serial_num == asoc->asconf_seq_out - 1) {
/* stop our timer */
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_ASCONF + SCTP_LOC_5);
}
+
/* process the ASCONF-ACK contents */
ack_length = ntohs(cp->ch.chunk_length) -
sizeof(struct sctp_asconf_ack_chunk);
@@ -1780,7 +1793,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
* at any given time
*/
if (last_error_id == 0)
- last_error_id--;/* set to "max" value */
+ last_error_id--; /* set to "max" value */
TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
if (aa->sent == 1) {
/*
@@ -1980,8 +1993,8 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* sent when the state goes open.
*/
if (status == 0 &&
- ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED))) {
+ ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED))) {
#ifdef SCTP_TIMER_BASED_ASCONF
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
stcb, stcb->asoc.primary_destination);
@@ -2060,6 +2073,7 @@ sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP
laddr->action = 0;
break;
}
+
}
} else if (l->action == SCTP_DEL_IP_ADDRESS) {
LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
@@ -2093,6 +2107,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (ifa->vrf_id != stcb->asoc.vrf_id) {
continue;
}
+
/* Same checks again for assoc */
switch (ifa->address.sa.sa_family) {
#ifdef INET6
@@ -2229,8 +2244,8 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* count of queued params. If in the non-open
* state, these get sent when the assoc goes open.
*/
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
if (status >= 0) {
num_queued++;
}
@@ -2283,6 +2298,7 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
/* Invalid address */
return (-1);
}
+
/* queue an ASCONF:SET_PRIM_ADDR to be sent */
if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
/* set primary queuing succeeded */
@@ -2290,8 +2306,8 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
"set_primary_ip_address_sa: queued on tcb=%p, ",
(void *)stcb);
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
#ifdef SCTP_TIMER_BASED_ASCONF
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
stcb->sctp_ep, stcb,
@@ -2361,11 +2377,13 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
break;
}
+
aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
if (aph == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
break;
}
+
ph = (struct sctp_paramhdr *)(aph + 1);
if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
switch (param_type) {
@@ -2380,6 +2398,7 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
}
last_param_type = param_type;
}
+
offset += SCTP_SIZE32(param_length);
if (offset >= asconf_limit) {
/* no more data in the mbuf chain */
@@ -2463,6 +2482,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
continue;
}
+
sin6 = &sctp_ifa->address.sin6;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
/*
@@ -2826,8 +2846,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
* out the ASCONF.
*/
if (status == 0 &&
- SCTP_GET_STATE(&stcb->asoc) ==
- SCTP_STATE_OPEN) {
+ SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
#ifdef SCTP_TIMER_BASED_ASCONF
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
stcb->sctp_ep, stcb,
@@ -2838,6 +2857,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
}
}
}
+
next_addr:
/*
* Sanity check: Make sure the length isn't 0, otherwise
@@ -3372,6 +3392,7 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
if (vrf == NULL) {
goto skip_rest;
}
+
SCTP_IPI_ADDR_RLOCK();
LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
diff --git a/freebsd/sys/netinet/sctp_asconf.h b/freebsd/sys/netinet/sctp_asconf.h
index 2a372205..581d504c 100644
--- a/freebsd/sys/netinet/sctp_asconf.h
+++ b/freebsd/sys/netinet/sctp_asconf.h
@@ -60,10 +60,10 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *, struct sockaddr *,
uint32_t, uint32_t, struct sctp_ifa *);
-extern int
+extern int
sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr,
uint32_t val);
-extern void
+extern void
sctp_asconf_iterator_stcb(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
void *ptr, uint32_t type);
diff --git a/freebsd/sys/netinet/sctp_auth.c b/freebsd/sys/netinet/sctp_auth.c
index d8fbcf6e..0fc076e1 100644
--- a/freebsd/sys/netinet/sctp_auth.c
+++ b/freebsd/sys/netinet/sctp_auth.c
@@ -1311,6 +1311,7 @@ sctp_auth_setactivekey(struct sctp_tcb *stcb, uint16_t keyid)
/* can't reactivate a deactivated key with other refcounts */
return (-1);
}
+
/* set the (new) active key */
stcb->asoc.authinfo.active_keyid = keyid;
/* reset the deactivated flag */
@@ -1365,6 +1366,7 @@ sctp_deact_sharedkey(struct sctp_tcb *stcb, uint16_t keyid)
sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb, keyid, 0,
SCTP_SO_LOCKED);
}
+
/* mark the key as deactivated */
skey->deactivated = 1;
@@ -1506,6 +1508,8 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
if (p_random != NULL) {
keylen = sizeof(*p_random) + random_len;
memcpy(new_key->key, p_random, keylen);
+ } else {
+ keylen = 0;
}
/* append in the AUTH chunks */
if (chunks != NULL) {
@@ -1582,6 +1586,7 @@ sctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset,
"Assoc Key");
#endif
}
+
/* set in the active key id */
auth->shared_key_id = htons(keyid);
@@ -1769,6 +1774,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
/* If the socket is gone we are out of here */
return;
}
+
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_AUTHEVNT))
/* event not enabled */
return;
@@ -1929,6 +1935,7 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
if (num_chunks)
got_chklist = 1;
}
+
offset += SCTP_SIZE32(plen);
if (offset >= limit) {
break;
@@ -2023,6 +2030,7 @@ sctp_initialize_auth_params(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
new_key->key[keylen++] = i;
}
}
+
/* append in the HMACs */
ph = (struct sctp_paramhdr *)(new_key->key + keylen);
ph->param_type = htons(SCTP_HMAC_LIST);
diff --git a/freebsd/sys/netinet/sctp_auth.h b/freebsd/sys/netinet/sctp_auth.h
index 66990c30..44126e3e 100644
--- a/freebsd/sys/netinet/sctp_auth.h
+++ b/freebsd/sys/netinet/sctp_auth.h
@@ -87,7 +87,7 @@ typedef struct sctp_hmaclist {
typedef struct sctp_authinformation {
sctp_key_t *random; /* local random key (concatenated) */
uint32_t random_len; /* local random number length for param */
- sctp_key_t *peer_random;/* peer's random key (concatenated) */
+ sctp_key_t *peer_random; /* peer's random key (concatenated) */
sctp_key_t *assoc_key; /* cached concatenated send key */
sctp_key_t *recv_key; /* cached concatenated recv key */
uint16_t active_keyid; /* active send keyid */
@@ -114,13 +114,13 @@ extern sctp_auth_chklist_t *sctp_copy_chunklist(sctp_auth_chklist_t *chklist);
extern int sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t *list);
extern int sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list);
extern size_t sctp_auth_get_chklist_size(const sctp_auth_chklist_t *list);
-extern int
+extern int
sctp_serialize_auth_chunks(const sctp_auth_chklist_t *list,
uint8_t *ptr);
-extern int
+extern int
sctp_pack_auth_chunks(const sctp_auth_chklist_t *list,
uint8_t *ptr);
-extern int
+extern int
sctp_unpack_auth_chunks(const uint8_t *ptr, uint8_t num_chunks,
sctp_auth_chklist_t *list);
@@ -141,16 +141,16 @@ extern void sctp_free_sharedkey(sctp_sharedkey_t *skey);
extern sctp_sharedkey_t *
sctp_find_sharedkey(struct sctp_keyhead *shared_keys,
uint16_t key_id);
-extern int
+extern int
sctp_insert_sharedkey(struct sctp_keyhead *shared_keys,
sctp_sharedkey_t *new_skey);
-extern int
+extern int
sctp_copy_skeylist(const struct sctp_keyhead *src,
struct sctp_keyhead *dest);
/* ref counts on shared keys, by key id */
extern void sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t keyid);
-extern void
+extern void
sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t keyid,
int so_locked);
@@ -161,11 +161,11 @@ extern void sctp_free_hmaclist(sctp_hmaclist_t *list);
extern int sctp_auth_add_hmacid(sctp_hmaclist_t *list, uint16_t hmac_id);
extern sctp_hmaclist_t *sctp_copy_hmaclist(sctp_hmaclist_t *list);
extern sctp_hmaclist_t *sctp_default_supported_hmaclist(void);
-extern uint16_t
+extern uint16_t
sctp_negotiate_hmacid(sctp_hmaclist_t *peer,
sctp_hmaclist_t *local);
extern int sctp_serialize_hmaclist(sctp_hmaclist_t *list, uint8_t *ptr);
-extern int
+extern int
sctp_verify_hmac_param(struct sctp_auth_hmac_algo *hmacs,
uint32_t num_hmacs);
@@ -175,22 +175,22 @@ extern void sctp_free_authinfo(sctp_authinfo_t *authinfo);
/* keyed-HMAC functions */
extern uint32_t sctp_get_auth_chunk_len(uint16_t hmac_algo);
extern uint32_t sctp_get_hmac_digest_len(uint16_t hmac_algo);
-extern uint32_t
+extern uint32_t
sctp_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
uint8_t *text, uint32_t textlen, uint8_t *digest);
-extern int
+extern int
sctp_verify_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
uint8_t *text, uint32_t textlen, uint8_t *digest, uint32_t digestlen);
-extern uint32_t
+extern uint32_t
sctp_compute_hmac(uint16_t hmac_algo, sctp_key_t *key,
uint8_t *text, uint32_t textlen, uint8_t *digest);
extern int sctp_auth_is_supported_hmac(sctp_hmaclist_t *list, uint16_t id);
/* mbuf versions */
-extern uint32_t
+extern uint32_t
sctp_hmac_m(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
struct mbuf *m, uint32_t m_offset, uint8_t *digest, uint32_t trailer);
-extern uint32_t
+extern uint32_t
sctp_compute_hmac_m(uint16_t hmac_algo, sctp_key_t *key,
struct mbuf *m, uint32_t m_offset, uint8_t *digest);
@@ -206,26 +206,26 @@ extern int sctp_auth_setactivekey_ep(struct sctp_inpcb *inp, uint16_t keyid);
extern int sctp_deact_sharedkey(struct sctp_tcb *stcb, uint16_t keyid);
extern int sctp_deact_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid);
-extern void
+extern void
sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
uint32_t offset, uint32_t length);
-extern void
+extern void
sctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset,
struct sctp_auth_chunk *auth, struct sctp_tcb *stcb, uint16_t key_id);
extern struct mbuf *
sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end,
struct sctp_auth_chunk **auth_ret, uint32_t *offset,
struct sctp_tcb *stcb, uint8_t chunk);
-extern int
+extern int
sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *ch,
struct mbuf *m, uint32_t offset);
-extern void
+extern void
sctp_notify_authentication(struct sctp_tcb *stcb,
uint32_t indication, uint16_t keyid, uint16_t alt_keyid, int so_locked);
-extern int
+extern int
sctp_validate_init_auth_params(struct mbuf *m, int offset,
int limit);
-extern void
+extern void
sctp_initialize_auth_params(struct sctp_inpcb *inp,
struct sctp_tcb *stcb);
diff --git a/freebsd/sys/netinet/sctp_bsd_addr.c b/freebsd/sys/netinet/sctp_bsd_addr.c
index 94c23bff..0f0ddd89 100644
--- a/freebsd/sys/netinet/sctp_bsd_addr.c
+++ b/freebsd/sys/netinet/sctp_bsd_addr.c
@@ -307,10 +307,12 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
SCTP_BASE_VAR(first_time) = 1;
sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID);
}
+
if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) {
/* don't know what to do with this */
return;
}
+
if (ifa->ifa_addr == NULL) {
return;
}
diff --git a/freebsd/sys/netinet/sctp_cc_functions.c b/freebsd/sys/netinet/sctp_cc_functions.c
index e8d6a354..1163cb91 100644
--- a/freebsd/sys/netinet/sctp_cc_functions.c
+++ b/freebsd/sys/netinet/sctp_cc_functions.c
@@ -133,6 +133,7 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
t_ucwnd_sbw = 1;
}
}
+
/*-
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
@@ -1121,6 +1122,7 @@ sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
}
+
}
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
} else {
@@ -1320,7 +1322,7 @@ sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *ne
static
-void
+void
sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
struct sctp_tmit_chunk *tp1)
{
@@ -1937,6 +1939,7 @@ measure_achieved_throughput(struct sctp_nets *net)
net->cc_mod.htcp_ca.lasttime = now;
return;
}
+
net->cc_mod.htcp_ca.bytecount += net->net_ack;
if ((net->cc_mod.htcp_ca.bytecount >= net->cwnd - (((net->cc_mod.htcp_ca.alpha >> 7) ? (net->cc_mod.htcp_ca.alpha >> 7) : 1) * net->mtu)) &&
(now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
@@ -1973,6 +1976,7 @@ htcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
return;
}
}
+
if (ca->modeswitch && minRTT > (uint32_t)MSEC_TO_TICKS(10) && maxRTT) {
ca->beta = (minRTT << 7) / maxRTT;
if (ca->beta < BETA_MIN)
@@ -1996,6 +2000,7 @@ htcp_alpha_update(struct htcp *ca)
diff -= hz;
factor = 1 + (10 * diff + ((diff / 2) * (diff / 2) / hz)) / hz;
}
+
if (use_rtt_scaling && minRTT) {
uint32_t scale = (hz << 3) / (10 * minRTT);
@@ -2005,6 +2010,7 @@ htcp_alpha_update(struct htcp *ca)
if (!factor)
factor = 1;
}
+
ca->alpha = 2 * factor * ((1 << 7) - ca->beta);
if (!ca->alpha)
ca->alpha = ALPHA_BASE;
@@ -2059,12 +2065,14 @@ htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
sctp_log_cwnd(stcb, net, net->mtu,
SCTP_CWND_LOG_FROM_SS);
}
+
} else {
net->cwnd += net->net_ack;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, net->net_ack,
SCTP_CWND_LOG_FROM_SS);
}
+
}
sctp_enforce_cwnd_limit(&stcb->asoc, net);
} else {
diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h
index 018cd282..d07381d5 100644
--- a/freebsd/sys/netinet/sctp_constants.h
+++ b/freebsd/sys/netinet/sctp_constants.h
@@ -470,10 +470,14 @@ __FBSDID("$FreeBSD$");
#define SCTP_STATE_IN_ACCEPT_QUEUE 0x1000
#define SCTP_STATE_MASK 0x007f
-#define SCTP_GET_STATE(asoc) ((asoc)->state & SCTP_STATE_MASK)
-#define SCTP_SET_STATE(asoc, newstate) ((asoc)->state = ((asoc)->state & ~SCTP_STATE_MASK) | newstate)
-#define SCTP_CLEAR_SUBSTATE(asoc, substate) ((asoc)->state &= ~substate)
-#define SCTP_ADD_SUBSTATE(asoc, substate) ((asoc)->state |= substate)
+#define SCTP_GET_STATE(_stcb) \
+ ((_stcb)->asoc.state & SCTP_STATE_MASK)
+#define SCTP_SET_STATE(_stcb, _state) \
+ sctp_set_state(_stcb, _state)
+#define SCTP_CLEAR_SUBSTATE(_stcb, _substate) \
+ (_stcb)->asoc.state &= ~(_substate)
+#define SCTP_ADD_SUBSTATE(_stcb, _substate) \
+ sctp_add_substate(_stcb, _substate)
/* SCTP reachability state for each address */
#define SCTP_ADDR_REACHABLE 0x001
diff --git a/freebsd/sys/netinet/sctp_dtrace_define.h b/freebsd/sys/netinet/sctp_dtrace_define.h
index 53451d20..ad7c8526 100644
--- a/freebsd/sys/netinet/sctp_dtrace_define.h
+++ b/freebsd/sys/netinet/sctp_dtrace_define.h
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/sdt.h>
-SDT_PROVIDER_DEFINE(sctp);
+SDT_PROVIDER_DECLARE(sctp);
/********************************************************/
/* Cwnd probe - tracks changes in the congestion window on a netp */
diff --git a/freebsd/sys/netinet/sctp_header.h b/freebsd/sys/netinet/sctp_header.h
index 685ed78a..8c4137a5 100644
--- a/freebsd/sys/netinet/sctp_header.h
+++ b/freebsd/sys/netinet/sctp_header.h
@@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$");
* Parameter structures
*/
struct sctp_ipv4addr_param {
- struct sctp_paramhdr ph;/* type=SCTP_IPV4_PARAM_TYPE, len=8 */
+ struct sctp_paramhdr ph; /* type=SCTP_IPV4_PARAM_TYPE, len=8 */
uint32_t addr; /* IPV4 address */
} SCTP_PACKED;
@@ -56,20 +56,20 @@ struct sctp_ipv4addr_param {
struct sctp_ipv6addr_param {
- struct sctp_paramhdr ph;/* type=SCTP_IPV6_PARAM_TYPE, len=20 */
+ struct sctp_paramhdr ph; /* type=SCTP_IPV6_PARAM_TYPE, len=20 */
uint8_t addr[SCTP_V6_ADDR_BYTES]; /* IPV6 address */
} SCTP_PACKED;
/* Cookie Preservative */
struct sctp_cookie_perserve_param {
- struct sctp_paramhdr ph;/* type=SCTP_COOKIE_PRESERVE, len=8 */
+ struct sctp_paramhdr ph; /* type=SCTP_COOKIE_PRESERVE, len=8 */
uint32_t time; /* time in ms to extend cookie */
} SCTP_PACKED;
#define SCTP_ARRAY_MIN_LEN 1
/* Host Name Address */
struct sctp_host_name_param {
- struct sctp_paramhdr ph;/* type=SCTP_HOSTNAME_ADDRESS */
+ struct sctp_paramhdr ph; /* type=SCTP_HOSTNAME_ADDRESS */
char name[SCTP_ARRAY_MIN_LEN]; /* host name */
} SCTP_PACKED;
@@ -80,7 +80,7 @@ struct sctp_host_name_param {
#define SCTP_MAX_ADDR_PARAMS_SIZE 12
/* supported address type */
struct sctp_supported_addr_param {
- struct sctp_paramhdr ph;/* type=SCTP_SUPPORTED_ADDRTYPE */
+ struct sctp_paramhdr ph; /* type=SCTP_SUPPORTED_ADDRTYPE */
uint16_t addr_type[2]; /* array of supported address types */
} SCTP_PACKED;
@@ -108,8 +108,8 @@ struct sctp_prsctp_supported_param {
/* draft-ietf-tsvwg-addip-sctp */
struct sctp_asconf_paramhdr { /* an ASCONF "parameter" */
- struct sctp_paramhdr ph;/* a SCTP parameter header */
- uint32_t correlation_id;/* correlation id for this param */
+ struct sctp_paramhdr ph; /* a SCTP parameter header */
+ uint32_t correlation_id; /* correlation id for this param */
} SCTP_PACKED;
struct sctp_asconf_addr_param { /* an ASCONF address parameter */
@@ -133,7 +133,7 @@ struct sctp_asconf_addrv4_param { /* an ASCONF address (v4) parameter */
#define SCTP_MAX_SUPPORTED_EXT 256
struct sctp_supported_chunk_types_param {
- struct sctp_paramhdr ph;/* type = 0x8008 len = x */
+ struct sctp_paramhdr ph; /* type = 0x8008 len = x */
uint8_t chunk_types[];
} SCTP_PACKED;
@@ -206,8 +206,8 @@ struct sctp_state_cookie { /* this is our definition... */
uint16_t peerport; /* port address of the peer in the INIT */
uint16_t myport; /* my port address used in the INIT */
- uint8_t ipv4_addr_legal;/* Are V4 addr legal? */
- uint8_t ipv6_addr_legal;/* Are V6 addr legal? */
+ uint8_t ipv4_addr_legal; /* Are V4 addr legal? */
+ uint8_t ipv6_addr_legal; /* Are V6 addr legal? */
uint8_t local_scope; /* IPv6 local scope flag */
uint8_t site_scope; /* IPv6 site scope flag */
@@ -512,17 +512,17 @@ struct sctp_stream_reset_resp_tsn {
/* Should we make the max be 32? */
#define SCTP_RANDOM_MAX_SIZE 256
struct sctp_auth_random {
- struct sctp_paramhdr ph;/* type = 0x8002 */
+ struct sctp_paramhdr ph; /* type = 0x8002 */
uint8_t random_data[];
} SCTP_PACKED;
struct sctp_auth_chunk_list {
- struct sctp_paramhdr ph;/* type = 0x8003 */
+ struct sctp_paramhdr ph; /* type = 0x8003 */
uint8_t chunk_types[];
} SCTP_PACKED;
struct sctp_auth_hmac_algo {
- struct sctp_paramhdr ph;/* type = 0x8004 */
+ struct sctp_paramhdr ph; /* type = 0x8004 */
uint16_t hmac_ids[];
} SCTP_PACKED;
diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 98b397a2..28e3f5b2 100644
--- a/freebsd/sys/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
@@ -92,6 +92,7 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
if (stcb->sctp_socket == NULL) {
return (calc);
}
+
KASSERT(asoc->cnt_on_reasm_queue > 0 || asoc->size_on_reasm_queue == 0,
("size_on_reasm_queue is %u", asoc->size_on_reasm_queue));
KASSERT(asoc->cnt_on_all_streams > 0 || asoc->size_on_all_streams == 0,
@@ -117,6 +118,7 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
/* out of space */
return (calc);
}
+
/* what is the overhead of all these rwnd's */
calc = sctp_sbspace_sub(calc, stcb->asoc.my_rwnd_control_len);
/*
@@ -187,6 +189,7 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
/* user does not want any ancillary data */
return (NULL);
}
+
len = 0;
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
@@ -1046,6 +1049,7 @@ place_chunk:
SCTP_FROM_SCTP_INDATA + SCTP_LOC_5);
return;
}
+
}
if (inserted == 0) {
/* Its at the end */
@@ -2140,6 +2144,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
control = NULL;
goto finish_express_del;
}
+
/* Now will we need a chunk too? */
if ((chk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) {
sctp_alloc_a_chunk(stcb, chk);
@@ -2570,7 +2575,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap)
* Now we need to see if we need to queue a sack or just start the
* timer (if allowed).
*/
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) {
/*
* Ok special case, in SHUTDOWN-SENT case. here we maker
* sure SACK timer is off and instead send a SHUTDOWN and a
@@ -2927,7 +2932,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_last_rcvd);
}
/* now service all of the reassm queue if needed */
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) {
/* Assure that we ack right away */
stcb->asoc.send_sack = 1;
}
@@ -3075,7 +3080,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
tp1->whoTo->net_ack += tp1->send_size;
if (tp1->snd_count < 2) {
/*-
- * True non-retransmited chunk
+ * True non-retransmitted chunk
*/
tp1->whoTo->net_ack2 += tp1->send_size;
@@ -3098,6 +3103,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
tp1->do_rtt = 0;
}
}
+
}
if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
if (SCTP_TSN_GT(tp1->rec.data.tsn,
@@ -3363,6 +3369,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
continue;
}
}
+
}
if (SCTP_TSN_GT(tp1->rec.data.tsn, asoc->this_sack_highest_gap) &&
!(accum_moved && asoc->fast_retran_loss_recovery)) {
@@ -3598,6 +3605,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1);
}
}
+
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) {
sctp_log_rwnd(SCTP_INCREASE_PEER_RWND,
asoc->peers_rwnd, tp1->send_size, SCTP_BASE_SYSCTL(sctp_peer_chunk_oh));
@@ -3679,6 +3687,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->whoTo->find_pseudo_cumack = 1;
tp1->whoTo->find_rtx_pseudo_cumack = 1;
}
+
} else { /* CMT is OFF */
#ifdef SCTP_FR_TO_ALTERNATE
@@ -3967,6 +3976,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
return;
}
+
/* First setup for CC stuff */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (SCTP_TSN_GT(cumack, net->cwr_window_tsn)) {
@@ -4048,7 +4058,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
tp1->whoTo->net_ack += tp1->send_size;
if (tp1->snd_count < 2) {
/*
- * True non-retransmited
+ * True non-retransmitted
* chunk
*/
tp1->whoTo->net_ack2 +=
@@ -4232,6 +4242,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
asoc->total_flight = 0;
asoc->total_flight_count = 0;
}
+
/* RWND update */
asoc->peers_rwnd = sctp_sbspace_sub(rwnd,
(uint32_t)(asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh))));
@@ -4320,12 +4331,12 @@ again:
/* clean up */
if ((asoc->stream_queue_cnt == 1) &&
((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
- (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc))) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
(asoc->stream_queue_cnt == 1) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
struct mbuf *op_err;
@@ -4341,12 +4352,11 @@ again:
(asoc->stream_queue_cnt == 0)) {
struct sctp_nets *netp;
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (asoc->alternate) {
netp = asoc->alternate;
@@ -4358,13 +4368,12 @@ again:
stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, netp);
- } else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ } else if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
struct sctp_nets *netp;
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_ACK_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (asoc->alternate) {
netp = asoc->alternate;
@@ -4484,6 +4493,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_misc_ints(SCTP_SACK_LOG_NORMAL, cum_ack,
rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd);
}
+
old_rwnd = stcb->asoc.peers_rwnd;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
@@ -4555,6 +4565,7 @@ hopeless_peer:
/* acking something behind */
return;
}
+
/* update the Rwnd of the peer */
if (TAILQ_EMPTY(&asoc->sent_queue) &&
TAILQ_EMPTY(&asoc->send_queue) &&
@@ -4608,6 +4619,7 @@ hopeless_peer:
if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) {
(*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) (stcb, net);
}
+
/*
* CMT: SFR algo (and HTNA) - this_sack_highest_newack has
* to be greater than the cumack. Also reset saw_newack to 0
@@ -4664,7 +4676,7 @@ hopeless_peer:
if (tp1->snd_count < 2) {
/*
- * True non-retransmited
+ * True non-retransmitted
* chunk
*/
tp1->whoTo->net_ack2 +=
@@ -4843,6 +4855,7 @@ hopeless_peer:
#endif
asoc->total_flight = 0;
}
+
/* sa_ignore NO_NULL_CHK */
if ((wake_him) && (stcb->sctp_socket)) {
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -4947,6 +4960,7 @@ hopeless_peer:
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
0, (void *)net, SCTP_SO_NOT_LOCKED);
}
+
if (net == stcb->asoc.primary_destination) {
if (stcb->asoc.alternate) {
/*
@@ -4957,6 +4971,7 @@ hopeless_peer:
stcb->asoc.alternate = NULL;
}
}
+
if (net->dest_state & SCTP_ADDR_PF) {
net->dest_state &= ~SCTP_ADDR_PF;
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
@@ -4979,6 +4994,7 @@ hopeless_peer:
}
asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
}
+
if (TAILQ_EMPTY(&asoc->sent_queue)) {
/* nothing left in-flight */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
@@ -4992,6 +5008,7 @@ hopeless_peer:
asoc->total_flight = 0;
asoc->total_flight_count = 0;
}
+
/**********************************/
/* Now what about shutdown issues */
/**********************************/
@@ -5009,12 +5026,12 @@ hopeless_peer:
/* clean up */
if ((asoc->stream_queue_cnt == 1) &&
((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
- (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc))) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
(asoc->stream_queue_cnt == 1) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
struct mbuf *op_err;
@@ -5030,12 +5047,11 @@ hopeless_peer:
(asoc->stream_queue_cnt == 0)) {
struct sctp_nets *netp;
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (asoc->alternate) {
netp = asoc->alternate;
@@ -5048,13 +5064,12 @@ hopeless_peer:
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, netp);
return;
- } else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ } else if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
struct sctp_nets *netp;
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_ACK_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (asoc->alternate) {
netp = asoc->alternate;
@@ -5126,6 +5141,7 @@ hopeless_peer:
if (asoc->peers_rwnd > old_rwnd) {
win_probe_recovery = 1;
}
+
/*
* Now we must setup so we have a timer up for anyone with
* outstanding data.
diff --git a/freebsd/sys/netinet/sctp_indata.h b/freebsd/sys/netinet/sctp_indata.h
index 10b18d0b..59ceac3a 100644
--- a/freebsd/sys/netinet/sctp_indata.h
+++ b/freebsd/sys/netinet/sctp_indata.h
@@ -99,8 +99,7 @@ void
sctp_handle_forward_tsn(struct sctp_tcb *,
struct sctp_forward_tsn_chunk *, int *, struct mbuf *, int);
-struct sctp_tmit_chunk *
- sctp_try_advance_peer_ack_point(struct sctp_tcb *, struct sctp_association *);
+struct sctp_tmit_chunk *sctp_try_advance_peer_ack_point(struct sctp_tcb *, struct sctp_association *);
void sctp_service_queues(struct sctp_tcb *, struct sctp_association *);
diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c
index ee206551..c7e86e78 100644
--- a/freebsd/sys/netinet/sctp_input.c
+++ b/freebsd/sys/netinet/sctp_input.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#if defined(INET) || defined(INET6)
#include <netinet/udp.h>
#endif
+#include <netinet/in_kdtrace.h>
#include <sys/smp.h>
@@ -192,7 +193,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
goto outnow;
}
if ((stcb != NULL) &&
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n");
sctp_send_shutdown_ack(stcb, NULL);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
@@ -307,6 +308,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION);
}
+
}
}
SCTP_TCB_SEND_LOCK(stcb);
@@ -493,6 +495,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
SCTP_FREE(param, SCTP_M_ASC_ADDR);
}
}
+
stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
stcb->asoc.local_hmacs);
if (op_err) {
@@ -555,6 +558,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
}
return (retval);
}
+
return (0);
}
@@ -572,6 +576,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
/* Invalid length */
return;
}
+
memset(&store, 0, sizeof(store));
switch (cp->heartbeat.hb_info.addr_family) {
#ifdef INET
@@ -711,15 +716,15 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
struct sctpasochead *head;
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_INFO_WLOCK();
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
}
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) {
/* generate a new vtag and send init */
LIST_REMOVE(stcb, sctp_asocs);
stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
@@ -733,15 +738,14 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
SCTP_INP_INFO_WUNLOCK();
return (1);
}
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
/*
* treat like a case where the cookie expired i.e.: - dump
* current cookie. - generate a new vtag. - resend init.
*/
/* generate a new vtag and send init */
LIST_REMOVE(stcb, sctp_asocs);
- stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED;
- stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
sctp_stop_all_cookie_timers(stcb);
sctp_toss_old_cookies(stcb, &stcb->asoc);
stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
@@ -823,8 +827,8 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED);
/* free the tcb */
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
#ifdef SCTP_ASOCLOG_OF_TSNS
@@ -838,7 +842,7 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
- stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -893,15 +897,15 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
if (stcb == NULL)
return;
asoc = &stcb->asoc;
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
return;
}
if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
/* Shutdown NOT the expected size */
return;
}
- old_state = SCTP_GET_STATE(asoc);
+ old_state = SCTP_GET_STATE(stcb);
sctp_update_acked(stcb, cp, abort_flag);
if (*abort_flag) {
return;
@@ -957,11 +961,10 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
}
/* goto SHUTDOWN_RECEIVED state to block new requests */
if (stcb->sctp_socket) {
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT)) {
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_RECEIVED);
/*
* notify upper layer that peer has initiated a
* shutdown
@@ -972,7 +975,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
}
}
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) {
/*
* stop the shutdown timer, since we WILL move to
* SHUTDOWN-ACK-SENT.
@@ -992,13 +995,12 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
/* no outstanding data to send, so move on... */
/* send SHUTDOWN-ACK */
/* move to SHUTDOWN-ACK-SENT state */
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_ACK_SENT);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown_ack(stcb, net);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
@@ -1027,15 +1029,15 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
asoc = &stcb->asoc;
/* process according to association state */
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
/* unexpected SHUTDOWN-ACK... do OOTB handling... */
sctp_send_shutdown_complete(stcb, net, 1);
SCTP_TCB_UNLOCK(stcb);
return;
}
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* unexpected SHUTDOWN-ACK... so ignore... */
SCTP_TCB_UNLOCK(stcb);
return;
@@ -1231,7 +1233,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
* waiting.
*/
if ((cause_length >= sizeof(struct sctp_error_stale_cookie)) &&
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
struct sctp_error_stale_cookie *stale_cookie;
stale_cookie = (struct sctp_error_stale_cookie *)cause;
@@ -1264,8 +1266,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
}
/* blast back to INIT state */
sctp_toss_old_cookies(stcb, &stcb->asoc);
- asoc->state &= ~SCTP_STATE_COOKIE_ECHOED;
- asoc->state |= SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
sctp_stop_all_cookie_timers(stcb);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
}
@@ -1416,7 +1417,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
return (-1);
}
/* process according to association state... */
- switch (stcb->asoc.state & SCTP_STATE_MASK) {
+ switch (SCTP_GET_STATE(stcb)) {
case SCTP_STATE_COOKIE_WAIT:
/* this is the expected state for this chunk */
/* process the INIT-ACK parameters */
@@ -1442,7 +1443,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
}
/* update our state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n");
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_ECHOED);
/* reset the RTO calc */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
@@ -1536,7 +1537,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
if (how_indx < sizeof(asoc->cookie_how)) {
asoc->cookie_how[how_indx] = 1;
}
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
/* SHUTDOWN came in after sending INIT-ACK */
sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, "");
@@ -1605,7 +1606,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
return (NULL);
}
- switch (SCTP_GET_STATE(asoc)) {
+ switch (SCTP_GET_STATE(stcb)) {
case SCTP_STATE_COOKIE_WAIT:
case SCTP_STATE_COOKIE_ECHOED:
/*
@@ -1629,12 +1630,12 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
stcb, net,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_14);
/* update current state */
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
else
SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
@@ -1718,6 +1719,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->cookie_how[how_indx] = 5;
return (stcb);
}
+
if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag &&
cookie->tie_tag_my_vtag == 0 &&
@@ -1733,7 +1735,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* If nat support, and the below and stcb is established, send back
* a ABORT(colliding state) if we are established.
*/
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) &&
(asoc->peer_supports_nat) &&
((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) ||
@@ -1838,8 +1840,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->cookie_how[how_indx] = 10;
return (NULL);
}
- if ((asoc->state & SCTP_STATE_COOKIE_WAIT) ||
- (asoc->state & SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
*notification = SCTP_NOTIFY_ASSOC_UP;
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
@@ -1867,17 +1869,17 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
else
SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
- } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ } else if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
SCTP_STAT_INCR_COUNTER32(sctps_restartestab);
} else {
SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
@@ -1937,24 +1939,24 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_RESTART;
atomic_add_int(&stcb->asoc.refcnt, 1);
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT)) {
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
}
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
SCTP_STAT_INCR_GAUGE32(sctps_restartestab);
- } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
+ } else if (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) {
SCTP_STAT_INCR_GAUGE32(sctps_collisionestab);
}
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
- } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) {
+ } else if (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) {
/* move to OPEN state, if not in SHUTDOWN_SENT */
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
}
asoc->pre_open_streams =
ntohs(initack_cp->init.num_outbound_streams);
@@ -2293,6 +2295,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
stcb->asoc.authenticated = 1;
}
}
+
/*
* if we're doing ASCONFs, check to see if we have any new local
* addresses that need to get added to the peer (eg. addresses
@@ -2342,7 +2345,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
/* update current state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
@@ -2590,6 +2593,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
(uint32_t)offset, cookie_offset, sig_offset);
return (NULL);
}
+
/*
* check the cookie timestamps to be sure it's not stale
*/
@@ -2710,6 +2714,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
}
}
}
+
cookie_len -= SCTP_SIGNATURE_SIZE;
if (*stcb == NULL) {
/* this is the "normal" case... get a new TCB */
@@ -2877,7 +2882,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
* the accept state waiting for the accept!
*/
if (*stcb) {
- (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_ADD_SUBSTATE(*stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
}
sctp_move_pcb_and_assoc(*inp_p, inp, *stcb);
@@ -2912,6 +2917,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
(*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
}
+
/*
* Pull it from the incomplete queue and wake the
* guy
@@ -2952,6 +2958,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
if ((stcb == NULL) || (net == NULL)) {
return;
}
+
asoc = &stcb->asoc;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
@@ -2963,10 +2970,10 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
asoc->overall_error_count = 0;
sctp_stop_all_cookie_timers(stcb);
/* process according to association state */
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
/* state change only needed when I am in right state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
sctp_start_net_timers(stcb);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
@@ -3018,6 +3025,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
*/
goto closed_socket;
}
+
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
stcb, net);
@@ -3224,7 +3232,6 @@ static void
sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
- struct sctp_association *asoc;
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -3234,9 +3241,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE
if (stcb == NULL)
return;
- asoc = &stcb->asoc;
/* process according to association state */
- if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
/* unexpected SHUTDOWN-COMPLETE... so ignore... */
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n");
@@ -3248,8 +3254,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
}
#ifdef INVARIANTS
- if (!TAILQ_EMPTY(&asoc->send_queue) ||
- !TAILQ_EMPTY(&asoc->sent_queue) ||
+ if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
+ !TAILQ_EMPTY(&stcb->asoc.sent_queue) ||
sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED)) {
panic("Queues are not empty when handling SHUTDOWN-COMPLETE");
}
@@ -3796,6 +3802,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
}
+
stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map;
stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn);
memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
@@ -4395,6 +4402,7 @@ sctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp,
if (trunc_len > limit) {
trunc_len = limit;
}
+
/* now the chunks themselves */
while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) {
desc.chunk_type = ch->chunk_type;
@@ -4654,6 +4662,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
*/
SCTP_INP_DECR_REF(inp);
}
+
/* now go back and verify any auth chunk to be sure */
if (auth_skipped && (stcb != NULL)) {
struct sctp_auth_chunk *auth;
@@ -4748,11 +4757,12 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
if (((ch->chunk_type == SCTP_SELECTIVE_ACK) ||
(ch->chunk_type == SCTP_NR_SELECTIVE_ACK) ||
(ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
/* implied cookie-ack.. we must have lost the ack */
sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb,
*netp);
}
+
process_control_chunks:
while (IS_SCTP_CONTROL(ch)) {
/* validate chunk length */
@@ -4792,6 +4802,7 @@ process_control_chunks:
}
return (NULL);
}
+
num_chunks++;
/* Save off the last place we got a control from */
if (stcb != NULL) {
@@ -4811,7 +4822,6 @@ process_control_chunks:
/* check to see if this chunk required auth, but isn't */
if ((stcb != NULL) &&
- (stcb->asoc.auth_supported == 1) &&
sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) &&
!stcb->asoc.authenticated) {
/* "silently" ignore */
@@ -4941,7 +4951,7 @@ process_control_chunks:
break;
}
}
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
/*-
* If we have sent a shutdown-ack, we will pay no
* attention to a sack sent in to us since
@@ -5159,6 +5169,7 @@ process_control_chunks:
goto abend;
}
}
+
if (netp != NULL) {
struct sctp_tcb *locked_stcb;
@@ -5331,6 +5342,7 @@ process_control_chunks:
*offset = length;
return (stcb);
}
+
if (stcb != NULL) {
int abort_flag = 0;
@@ -5393,6 +5405,7 @@ process_control_chunks:
*offset = length;
return (stcb);
}
+
if ((ch != NULL) && (stcb != NULL) && (netp != NULL) && (*netp != NULL)) {
if (stcb->asoc.pktdrop_supported == 0) {
goto unknown_chunk;
@@ -5559,6 +5572,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
net->flowtype = mflowtype;
net->flowid = mflowid;
}
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
if ((inp != NULL) && (stcb != NULL)) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
@@ -5599,6 +5613,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
net->flowid = mflowid;
}
if (inp == NULL) {
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
SCTP_STAT_INCR(sctps_noport);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
goto out;
@@ -5647,6 +5662,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
SCTP_TCB_UNLOCK(stcb);
stcb = NULL;
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
@@ -5655,6 +5671,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
vrf_id, port);
goto out;
}
+
}
if (IS_SCTP_CONTROL(ch)) {
/* process the control portion of the SCTP packet */
@@ -5700,14 +5717,15 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
* chunks
*/
if ((stcb != NULL) &&
- (stcb->asoc.auth_supported == 1) &&
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
/* "silently" ignore */
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
SCTP_STAT_INCR(sctps_recvauthmissing);
goto out;
}
if (stcb == NULL) {
/* out of the blue DATA chunk */
+ SCTP_PROBE5(receive, NULL, NULL, m, NULL, sh);
snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
@@ -5718,11 +5736,13 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
/* v_tag mismatch! */
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
SCTP_STAT_INCR(sctps_badvtag);
goto out;
}
}
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
if (stcb == NULL) {
/*
* no valid TCB for this packet, or we found it's a bad
@@ -5731,6 +5751,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
goto out;
}
+
/*
* DATA chunk processing
*/
@@ -5742,7 +5763,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
if ((length > offset) &&
(stcb != NULL) &&
- (stcb->asoc.auth_supported == 1) &&
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) &&
!stcb->asoc.authenticated) {
/* "silently" ignore */
@@ -5759,7 +5779,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
* not get here unless we really did have a tag, so we don't
* abort if this happens, just dump the chunk silently.
*/
- switch (SCTP_GET_STATE(&stcb->asoc)) {
+ switch (SCTP_GET_STATE(stcb)) {
case SCTP_STATE_COOKIE_ECHOED:
/*
* we consider data with valid tags in this state
@@ -5810,6 +5830,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
* process_data
*/
}
+
/* take care of ecn */
if ((data_processed == 1) &&
(stcb->asoc.ecn_supported == 1) &&
@@ -5817,6 +5838,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
/* Yep, we need to add a ECNE */
sctp_send_ecn_echo(stcb, net, high_tsn);
}
+
if ((data_processed == 0) && (fwd_tsn_seen)) {
int was_a_gap;
uint32_t highest_tsn;
diff --git a/freebsd/sys/netinet/sctp_input.h b/freebsd/sys/netinet/sctp_input.h
index f393ad89..72908e11 100644
--- a/freebsd/sys/netinet/sctp_input.h
+++ b/freebsd/sys/netinet/sctp_input.h
@@ -52,7 +52,7 @@ struct sctp_stream_reset_request *
sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq,
struct sctp_tmit_chunk **bchk);
-void
+void
sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries,
uint16_t *list);
diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h
index d8d9e6e8..abe8e2c9 100644
--- a/freebsd/sys/netinet/sctp_os_bsd.h
+++ b/freebsd/sys/netinet/sctp_os_bsd.h
@@ -445,7 +445,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed,
/*
* SCTP AUTH
*/
-#define SCTP_READ_RANDOM(buf, len) read_random(buf, len)
+#define SCTP_READ_RANDOM(buf, len) arc4rand(buf, len, 0)
/* map standard crypto API names */
#define SCTP_SHA1_CTX SHA1_CTX
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index bdef958c..8f0c8aa4 100644
--- a/freebsd/sys/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/udp_var.h>
#include <machine/in_cksum.h>
+#include <netinet/in_kdtrace.h>
@@ -2547,6 +2548,7 @@ once_again:
inp->next_addr_touse = NULL;
goto once_again;
}
+
inp->next_addr_touse = starting_point;
resettotop = 0;
once_again_too:
@@ -2554,6 +2556,7 @@ once_again_too:
inp->next_addr_touse = LIST_FIRST(&inp->sctp_addr_list);
resettotop = 1;
}
+
/* ok, what about an acceptable address in the inp */
for (laddr = inp->next_addr_touse; laddr;
laddr = LIST_NEXT(laddr, sctp_nxt_addr)) {
@@ -2576,6 +2579,7 @@ once_again_too:
inp->next_addr_touse = NULL;
goto once_again_too;
}
+
/*
* no address bound can be a source for the destination we are in
* trouble
@@ -3990,8 +3994,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
int so_locked
#endif
)
-/* nofragment_flag to tell if IP_DF should be set (IPv4 only) */
{
+/* nofragment_flag to tell if IP_DF should be set (IPv4 only) */
/**
* Given a mbuf chain (via SCTP_BUF_NEXT()) that holds a packet header
* WITH an SCTPHDR but no IP header, endpoint inp and sa structure:
@@ -4038,6 +4042,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if ((auth != NULL) && (stcb != NULL)) {
sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid);
}
+
if (net) {
tos_value = net->dscp;
} else if (stcb) {
@@ -4249,6 +4254,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
SCTP_SOCKET_UNLOCK(so, 0);
}
#endif
+ SCTP_PROBE5(send, NULL, stcb, ip, stcb, sctphdr);
SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
@@ -4394,7 +4400,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
} else {
ip6h->ip6_nxt = IPPROTO_SCTP;
}
- ip6h->ip6_plen = (uint16_t)(packet_length - sizeof(struct ip6_hdr));
+ ip6h->ip6_plen = htons((uint16_t)(packet_length - sizeof(struct ip6_hdr)));
ip6h->ip6_dst = sin6->sin6_addr;
/*
@@ -4552,6 +4558,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
prev_scope = sin6->sin6_scope_id;
prev_port = sin6->sin6_port;
}
+
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
/* failed to prepend data, give up */
sctp_m_freem(m);
@@ -4581,6 +4588,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
sctp_packet_log(o_pak);
#endif
+ SCTP_PROBE5(send, NULL, stcb, ip6h, stcb, sctphdr);
SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
@@ -4740,6 +4748,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
chunk_len += parameter_len;
}
+
/* ECN parameter */
if (stcb->asoc.ecn_supported == 1) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
@@ -4748,6 +4757,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
+
/* PR-SCTP supported parameter */
if (stcb->asoc.prsctp_supported == 1) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
@@ -4756,6 +4766,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
+
/* Add NAT friendly parameter. */
if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
@@ -4764,6 +4775,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
+
/* And now tell the peer which extensions we support */
num_ext = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
@@ -4854,6 +4866,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
chunk_len += parameter_len;
}
}
+
/* now any cookie time extensions */
if (stcb->asoc.cookie_preserve_req) {
struct sctp_cookie_perserve_param *cookie_preserve;
@@ -4871,6 +4884,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
stcb->asoc.cookie_preserve_req = 0;
chunk_len += parameter_len;
}
+
if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) {
uint8_t i;
@@ -4899,6 +4913,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
padding_len = 4 - 2 * i;
chunk_len += parameter_len;
}
+
SCTP_BUF_LEN(m) = chunk_len;
/* now the addresses */
/*
@@ -5519,7 +5534,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc = NULL;
}
if ((asoc != NULL) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT)) {
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT)) {
if (sctp_are_there_new_addresses(asoc, init_pkt, offset, src)) {
/*
* new addresses, out of here in non-cookie-wait
@@ -5822,9 +5837,9 @@ do_a_abort:
initack->ch.chunk_length = 0;
/* place in my tag */
if ((asoc != NULL) &&
- ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_INUSE) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED))) {
+ ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_INUSE) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED))) {
/* re-use the v-tags and init-seq here */
initack->init.initiate_tag = htonl(asoc->my_vtag);
initack->init.initial_tsn = htonl(asoc->init_seq_number);
@@ -5904,6 +5919,7 @@ do_a_abort:
ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
chunk_len += parameter_len;
}
+
/* ECN parameter */
if (((asoc != NULL) && (asoc->ecn_supported == 1)) ||
((asoc == NULL) && (inp->ecn_supported == 1))) {
@@ -5913,6 +5929,7 @@ do_a_abort:
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
+
/* PR-SCTP supported parameter */
if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
((asoc == NULL) && (inp->prsctp_supported == 1))) {
@@ -5922,6 +5939,7 @@ do_a_abort:
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
+
/* Add NAT friendly parameter */
if (nat_friendly) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
@@ -5930,6 +5948,7 @@ do_a_abort:
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
+
/* And now tell the peer which extensions we support */
num_ext = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
@@ -5973,6 +5992,7 @@ do_a_abort:
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
chunk_len += parameter_len;
}
+
/* add authentication parameters */
if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
((asoc == NULL) && (inp->auth_supported == 1))) {
@@ -6050,6 +6070,7 @@ do_a_abort:
SCTP_BUF_LEN(m) += padding_len;
padding_len = 0;
}
+
/* tack on the operational error if present */
if (op_err) {
parameter_len = 0;
@@ -6347,9 +6368,9 @@ sctp_msg_append(struct sctp_tcb *stcb,
}
strm = &stcb->asoc.strmout[srcv->sinfo_stream];
/* Now can we send this? */
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_SENT) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
(stcb->asoc.state & SCTP_STATE_SHUTDOWN_PENDING)) {
/* got data while shutting down */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
@@ -6682,18 +6703,17 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
* there is nothing queued to send, so I'm
* done...
*/
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/*
* only send SHUTDOWN the first time
* through
*/
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb, net);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
@@ -6714,13 +6734,13 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
* we will allow user data to be sent first
* and move to SHUTDOWN-PENDING
*/
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
- asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
@@ -7433,6 +7453,7 @@ dont_do_it:
chk->last_mbuf = SCTP_BUF_NEXT(chk->last_mbuf);
}
}
+
if (to_move > length) {
/*- This should not happen either
* since we always lower to_move to the size
@@ -7839,7 +7860,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
*reason_code = 0;
auth_keyid = stcb->asoc.authinfo.active_keyid;
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
- (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
eeor_mode = 1;
} else {
@@ -7970,6 +7991,7 @@ nothing_to_send:
*reason_code = 8;
return (0);
}
+
if (asoc->sctp_cmt_on_off > 0) {
/* get the last start point */
start_at = asoc->last_net_cmt_send_started;
@@ -8596,8 +8618,8 @@ again_one_more_time:
omtu = 0;
break;
}
- if ((((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ if ((((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
(skip_data_for_this_net == 0)) ||
(cookie)) {
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
@@ -8616,6 +8638,7 @@ again_one_more_time:
/* Don't send the chunk on this net */
continue;
}
+
if (asoc->sctp_cmt_on_off == 0) {
if ((asoc->alternate) &&
(asoc->alternate != net) &&
@@ -8645,7 +8668,7 @@ again_one_more_time:
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
}
if (SCTP_BASE_SYSCTL(sctp_enable_sack_immediately) &&
- ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) == SCTP_STATE_SHUTDOWN_PENDING)) {
+ (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) {
struct sctp_data_chunk *dchkh;
dchkh = mtod(chk->data, struct sctp_data_chunk *);
@@ -8879,6 +8902,7 @@ no_data_fill:
if (old_start_at)
goto again_one_more_time;
}
+
/*
* At the end there should be no NON timed chunks hanging on this
* queue.
@@ -9272,17 +9296,20 @@ sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net, int addr_locked)
/* can't send a new one if there is one in flight already */
return;
}
+
/* compose an ASCONF chunk, maximum length is PMTU */
m_asconf = sctp_compose_asconf(stcb, &len, addr_locked);
if (m_asconf == NULL) {
return;
}
+
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
/* no memory */
sctp_m_freem(m_asconf);
return;
}
+
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_ASCONF;
chk->rec.chunk_id.can_take_data = 0;
@@ -9353,6 +9380,7 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
if (ack->data == NULL) {
continue;
}
+
/* copy the asconf_ack */
m_ack = SCTP_M_COPYM(ack->data, 0, M_COPYALL, M_NOWAIT);
if (m_ack == NULL) {
@@ -9541,8 +9569,8 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
if (TAILQ_EMPTY(&asoc->sent_queue)) {
return (SCTP_RETRAN_DONE);
}
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT)) {
/* not yet open, resend the cookie and that is it */
return (1);
}
@@ -10241,6 +10269,7 @@ sctp_output(
SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
+
if (inp->sctp_socket == NULL) {
SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
@@ -11228,12 +11257,13 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
sctp_packet_log(o_pak);
}
#endif
+ SCTP_PROBE5(send, NULL, NULL, ip, NULL, shout);
SCTP_IP_OUTPUT(ret, o_pak, NULL, NULL, vrf_id);
break;
#endif
#ifdef INET6
case AF_INET6:
- ip6->ip6_plen = (uint16_t)(len - sizeof(struct ip6_hdr));
+ ip6->ip6_plen = htons((uint16_t)(len - sizeof(struct ip6_hdr)));
if (port) {
shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
@@ -11250,6 +11280,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
sctp_packet_log(o_pak);
}
#endif
+ SCTP_PROBE5(send, NULL, NULL, ip6, NULL, shout);
SCTP_IP6_OUTPUT(ret, o_pak, NULL, NULL, NULL, vrf_id);
break;
#endif
@@ -11314,6 +11345,7 @@ sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net, int so_locked
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak, can't get a chunk for hb\n");
return;
}
+
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_HEARTBEAT_REQUEST;
chk->rec.chunk_id.can_take_data = 1;
@@ -12332,6 +12364,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp,
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
return (ENOBUFS);
}
+
sp->tail_mbuf = m_last(sp->data);
return (0);
}
@@ -12348,6 +12381,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
int user_marks_eor,
int *error)
{
+
/*-
* This routine must be very careful in its work. Protocol
* processing is up and running so care must be taken to spl...()
@@ -12360,9 +12394,9 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
*error = 0;
/* Now can we send this? */
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
(asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) {
/* got data while shutting down */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
@@ -12748,7 +12782,7 @@ sctp_lower_sosend(struct socket *so,
*/
queue_only = 1;
asoc = &stcb->asoc;
- SCTP_SET_STATE(asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
/* initialize authentication params for the assoc */
@@ -12870,8 +12904,8 @@ sctp_lower_sosend(struct socket *so,
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, error);
goto out_unlocked;
}
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
queue_only = 1;
}
/* we are now done with all control */
@@ -12879,9 +12913,9 @@ sctp_lower_sosend(struct socket *so,
sctp_m_freem(control);
control = NULL;
}
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
(asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) {
if (srcv->sinfo_flags & SCTP_ABORT) {
;
@@ -12903,8 +12937,8 @@ sctp_lower_sosend(struct socket *so,
int tot_demand, tot_out = 0, max_out;
SCTP_STAT_INCR(sctps_sends_with_abort);
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
/* It has to be up before we abort */
/* how big is the user initiated abort? */
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -13014,6 +13048,7 @@ sctp_lower_sosend(struct socket *so,
error = EFAULT;
goto out_unlocked;
}
+
/* Unless E_EOR mode is on, we must make a send FIT in one call. */
if ((user_marks_eor == 0) &&
(sndlen > SCTP_SB_LIMIT_SND(stcb->sctp_socket))) {
@@ -13031,6 +13066,7 @@ sctp_lower_sosend(struct socket *so,
error = EINVAL;
goto out_unlocked;
}
+
if (user_marks_eor) {
local_add_more = min(SCTP_SB_LIMIT_SND(so), SCTP_BASE_SYSCTL(sctp_add_more_threshold));
} else {
@@ -13095,6 +13131,7 @@ sctp_lower_sosend(struct socket *so,
}
SOCKBUF_UNLOCK(&so->so_snd);
}
+
skip_preblock:
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
goto out_unlocked;
@@ -13231,6 +13268,7 @@ skip_preblock:
if (srcv->sinfo_flags & SCTP_SACK_IMMEDIATELY) {
sp->sinfo_flags |= SCTP_SACK_IMMEDIATELY;
}
+
/* Did we reach EOR? */
if ((uio->uio_resid == 0) &&
((user_marks_eor == 0) ||
@@ -13279,12 +13317,12 @@ skip_preblock:
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
/* a collision took us forward? */
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
- SCTP_SET_STATE(asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
queue_only = 1;
}
}
@@ -13396,6 +13434,7 @@ skip_preblock:
SOCKBUF_UNLOCK(&so->so_snd);
goto out_unlocked;
}
+
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_OUTOF_BLK,
asoc, stcb->asoc.total_output_queue_size);
@@ -13466,17 +13505,16 @@ dataless_eof:
goto abort_anyway;
}
/* there is nothing queued to send, so I'm done... */
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
struct sctp_nets *netp;
/* only send SHUTDOWN the first time through */
- if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (stcb->asoc.alternate) {
netp = stcb->asoc.alternate;
@@ -13500,17 +13538,17 @@ dataless_eof:
* data to be sent first and move to
* SHUTDOWN-PENDING
*/
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
if (hold_tcblock == 0) {
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
- asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
@@ -13551,12 +13589,12 @@ skip_out_eof:
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
/* a collision took us forward? */
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
queue_only = 1;
}
}
@@ -13761,6 +13799,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t *ro)
SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)src6);
return (0);
}
+
SCTPDBG(SCTP_DEBUG_OUTPUT2, "v6src_match_nexthop(), Prefix entry is ");
SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)src6);
diff --git a/freebsd/sys/netinet/sctp_output.h b/freebsd/sys/netinet/sctp_output.h
index e6222e3f..1b3d22d9 100644
--- a/freebsd/sys/netinet/sctp_output.h
+++ b/freebsd/sys/netinet/sctp_output.h
@@ -74,7 +74,7 @@ int
int
sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t *ro);
-void
+void
sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -117,7 +117,7 @@ void sctp_send_shutdown_ack(struct sctp_tcb *, struct sctp_nets *);
void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *, int);
-void
+void
sctp_send_shutdown_complete2(struct sockaddr *, struct sockaddr *,
struct sctphdr *,
uint8_t, uint32_t, uint16_t,
@@ -146,13 +146,13 @@ int
sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct thread *, int);
-void
+void
sctp_chunk_output(struct sctp_inpcb *, struct sctp_tcb *, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
-void
+void
sctp_send_abort_tcb(struct sctp_tcb *, struct mbuf *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -201,7 +201,7 @@ sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
-void
+void
sctp_send_operr_to(struct sockaddr *, struct sockaddr *,
struct sctphdr *, uint32_t, struct mbuf *,
uint8_t, uint32_t, uint16_t,
diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index cf993d64..782e5f1d 100644
--- a/freebsd/sys/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
@@ -187,6 +187,7 @@ sctp_allocate_vrf(int vrf_id)
SCTP_FREE(vrf, SCTP_M_VRF);
return (NULL);
}
+
/* Add it to the hash table */
bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(vrf_id & SCTP_BASE_INFO(hashvrfmark))];
LIST_INSERT_HEAD(bucket, vrf, next_vrf);
@@ -738,6 +739,7 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id);
goto out_now;
}
+
#ifdef SCTP_DEBUG
SCTPDBG(SCTP_DEBUG_PCB4, "vrf_id 0x%x: deleting address:", vrf_id);
SCTPDBG_ADDR(SCTP_DEBUG_PCB4, addr);
@@ -866,6 +868,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
SCTP_IPI_ADDR_RUNLOCK();
return (0);
}
+
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
if ((loopback_scope == 0) &&
@@ -1027,6 +1030,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
if ((to == NULL) || (from == NULL)) {
return (NULL);
}
+
switch (to->sa_family) {
#ifdef INET
case AF_INET:
@@ -1389,6 +1393,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
if (locked_tcb) {
atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
}
+
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (stcb);
@@ -2254,6 +2259,7 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
return (stcb);
}
}
+
if (inp_p) {
stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp,
1, vrf_id);
@@ -2849,6 +2855,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
}
+
sin = (struct sockaddr_in *)addr;
lport = sin->sin_port;
/*
@@ -3368,14 +3375,14 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* was not closed. So go ahead and
* start it now.
*/
- asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_IN_ACCEPT_QUEUE);
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL);
}
SCTP_TCB_UNLOCK(asoc);
continue;
}
- if (((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) &&
+ if (((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) &&
(asoc->asoc.total_output_queue_size == 0)) {
/*
* If we have data in queue, we don't want
@@ -3392,7 +3399,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
/* Disconnect the socket please */
asoc->sctp_socket = NULL;
- asoc->asoc.state |= SCTP_STATE_CLOSED_SOCKET;
+ SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_CLOSED_SOCKET);
if ((asoc->asoc.size_on_reasm_queue > 0) ||
(asoc->asoc.control_pdapi) ||
(asoc->asoc.size_on_all_streams > 0) ||
@@ -3404,8 +3411,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3;
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
if (sctp_free_assoc(inp, asoc,
@@ -3419,20 +3426,19 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
if ((*asoc->asoc.ss_functions.sctp_ss_is_user_msgs_incomplete) (asoc, &asoc->asoc)) {
goto abort_anyway;
}
- if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
struct sctp_nets *netp;
/*
* there is nothing queued to send,
* so I send shutdown
*/
- if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(asoc);
if (asoc->asoc.alternate) {
netp = asoc->asoc.alternate;
@@ -3448,11 +3454,11 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
} else {
/* mark into shutdown pending */
- asoc->asoc.state |= SCTP_STATE_SHUTDOWN_PENDING;
+ SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc,
asoc->asoc.primary_destination);
if ((*asoc->asoc.ss_functions.sctp_ss_is_user_msgs_incomplete) (asoc, &asoc->asoc)) {
- asoc->asoc.state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (TAILQ_EMPTY(&asoc->asoc.send_queue) &&
TAILQ_EMPTY(&asoc->asoc.sent_queue) &&
@@ -3464,8 +3470,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5;
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
if (sctp_free_assoc(inp, asoc,
@@ -3503,6 +3509,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
LIST_REMOVE(inp, sctp_hash);
inp->sctp_flags |= SCTP_PCB_FLAGS_UNBOUND;
}
+
/*
* If there is a timer running to kill us, forget it, since it may
* have a contest on the INP lock.. which would cause us to die ...
@@ -3512,7 +3519,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_TCB_LOCK(asoc);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) {
- asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_IN_ACCEPT_QUEUE);
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL);
}
cnt++;
@@ -3520,7 +3527,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
continue;
}
/* Free associations that are NOT killing us */
- if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_COOKIE_WAIT) &&
+ if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) {
struct mbuf *op_err;
@@ -3533,8 +3540,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_TCB_UNLOCK(asoc);
continue;
}
- if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE,
@@ -3637,6 +3644,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
(void)sctp_m_free(ip_pcb->inp_options);
ip_pcb->inp_options = 0;
}
+
+
#ifdef INET6
if (ip_pcb->inp_vflag & INP_IPV6) {
struct in6pcb *in6p;
@@ -4797,7 +4806,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* Now the read queue needs to be cleaned up (only once) */
if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) {
- stcb->asoc.state |= SCTP_STATE_ABOUT_TO_BE_FREED;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_ABOUT_TO_BE_FREED);
SCTP_INP_READ_LOCK(inp);
TAILQ_FOREACH(sq, &inp->read_queue, next) {
if (sq->stcb == stcb) {
@@ -4851,7 +4860,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
if ((stcb->asoc.refcnt) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
- stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
}
SCTP_TCB_UNLOCK(stcb);
@@ -4864,6 +4873,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_sorwakeup(inp, so);
sctp_sowwakeup(inp, so);
}
+
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 9);
#endif
@@ -4922,6 +4932,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
}
+
/*
* Make it invalid too, that way if its about to run it will abort
* and return.
@@ -4931,7 +4942,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
atomic_add_int(&stcb->asoc.refcnt, -1);
}
if (stcb->asoc.refcnt) {
- stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
if (from_inpcbfree == SCTP_NORMAL_PROC) {
SCTP_INP_INFO_WUNLOCK();
@@ -5339,6 +5350,7 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp)
__func__);
continue;
}
+
if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
continue;
}
@@ -5752,6 +5764,7 @@ sctp_startup_mcore_threads(void)
i++;
}
}
+
/* Now start them all */
CPU_FOREACH(cpu) {
(void)kproc_create(sctp_mcore_thread,
@@ -6267,7 +6280,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* assoc? straighten out locks.
*/
if (stcb_tmp) {
- if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb_tmp) == SCTP_STATE_COOKIE_WAIT) {
struct mbuf *op_err;
char msg[SCTP_DIAG_INFO_LEN];
@@ -6286,6 +6299,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
SCTP_TCB_UNLOCK(stcb_tmp);
}
+
if (stcb->asoc.state == 0) {
/* the assoc was freed? */
return (-12);
@@ -6366,7 +6380,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* assoc? straighten out locks.
*/
if (stcb_tmp) {
- if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb_tmp) == SCTP_STATE_COOKIE_WAIT) {
struct mbuf *op_err;
char msg[SCTP_DIAG_INFO_LEN];
@@ -6708,6 +6722,8 @@ next_param:
if (p_random != NULL) {
keylen = sizeof(*p_random) + random_len;
memcpy(new_key->key, p_random, keylen);
+ } else {
+ keylen = 0;
}
/* append in the AUTH chunks */
if (chunks != NULL) {
@@ -7003,6 +7019,7 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
if (!fnd) {
asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1;
}
+
/*
* Question, should we go through the delivery queue? The
* only reason things are on here is the app not reading OR
diff --git a/freebsd/sys/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h
index 3fc03399..5b41ae8a 100644
--- a/freebsd/sys/netinet/sctp_pcb.h
+++ b/freebsd/sys/netinet/sctp_pcb.h
@@ -363,7 +363,7 @@ struct sctp_inpcb {
union {
struct inpcb inp;
char align[(sizeof(struct in6pcb) + SCTP_ALIGNM1) &
- ~SCTP_ALIGNM1];
+ ~SCTP_ALIGNM1];
} ip_inp;
@@ -389,7 +389,7 @@ struct sctp_inpcb {
uint64_t sctp_features; /* Feature flags */
uint32_t sctp_flags; /* INP state flag set */
uint32_t sctp_mobility_features; /* Mobility Feature flags */
- struct sctp_pcb sctp_ep;/* SCTP ep data */
+ struct sctp_pcb sctp_ep; /* SCTP ep data */
/* head of the hash of all associations */
struct sctpasochead *sctp_tcbhash;
u_long sctp_hashmark;
@@ -492,8 +492,7 @@ int SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b);
void sctp_fill_pcbinfo(struct sctp_pcbinfo *);
-struct sctp_ifn *
- sctp_find_ifn(void *ifn, uint32_t ifn_index);
+struct sctp_ifn *sctp_find_ifn(void *ifn, uint32_t ifn_index);
struct sctp_vrf *sctp_allocate_vrf(int vrfid);
struct sctp_vrf *sctp_find_vrf(uint32_t vrfid);
@@ -524,7 +523,7 @@ void sctp_free_ifn(struct sctp_ifn *sctp_ifnp);
void sctp_free_ifa(struct sctp_ifa *sctp_ifap);
-void
+void
sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr,
uint32_t ifn_index, const char *if_name);
@@ -534,7 +533,7 @@ struct sctp_nets *sctp_findnet(struct sctp_tcb *, struct sockaddr *);
struct sctp_inpcb *sctp_pcb_findep(struct sockaddr *, int, int, uint32_t);
-int
+int
sctp_inpcb_bind(struct socket *, struct sockaddr *,
struct sctp_ifa *, struct thread *);
@@ -563,8 +562,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **,
struct sockaddr *, struct sctp_nets **, struct sockaddr *,
struct sctp_tcb *);
-struct sctp_tcb *
- sctp_findasoc_ep_asocid_locked(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock);
+struct sctp_tcb *sctp_findasoc_ep_asocid_locked(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock);
struct sctp_tcb *
sctp_findassociation_ep_asocid(struct sctp_inpcb *,
diff --git a/freebsd/sys/netinet/sctp_peeloff.c b/freebsd/sys/netinet/sctp_peeloff.c
index ad96b88c..14a7c381 100644
--- a/freebsd/sys/netinet/sctp_peeloff.c
+++ b/freebsd/sys/netinet/sctp_peeloff.c
@@ -76,7 +76,7 @@ sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOENT);
return (ENOENT);
}
- state = SCTP_GET_STATE((&stcb->asoc));
+ state = SCTP_GET_STATE(stcb);
if ((state == SCTP_STATE_EMPTY) ||
(state == SCTP_STATE_INUSE)) {
SCTP_TCB_UNLOCK(stcb);
@@ -105,13 +105,15 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
}
- state = SCTP_GET_STATE((&stcb->asoc));
+
+ state = SCTP_GET_STATE(stcb);
if ((state == SCTP_STATE_EMPTY) ||
(state == SCTP_STATE_INUSE)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
}
+
n_inp = (struct sctp_inpcb *)so->so_pcb;
n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
SCTP_PCB_FLAGS_CONNECTED |
diff --git a/freebsd/sys/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h
index d60705b4..c4eafc26 100644
--- a/freebsd/sys/netinet/sctp_structs.h
+++ b/freebsd/sys/netinet/sctp_structs.h
@@ -105,7 +105,7 @@ TAILQ_HEAD(sctp_resethead, sctp_stream_reset_list);
#define SCTP_ASOC_ANY_STATE 0x00000000
typedef void (*asoc_func) (struct sctp_inpcb *, struct sctp_tcb *, void *ptr,
- uint32_t val);
+ uint32_t val);
typedef int (*inp_func) (struct sctp_inpcb *, void *ptr, uint32_t val);
typedef void (*end_func) (void *ptr, uint32_t val);
@@ -144,7 +144,7 @@ struct sctp_iterator {
asoc_func function_assoc; /* per assoc function */
inp_func function_inp; /* per endpoint function */
inp_func function_inp_end; /* end INP function */
- end_func function_atend;/* iterator completion function */
+ end_func function_atend; /* iterator completion function */
void *pointer; /* pointer for apply func to use */
uint32_t val; /* value for apply func to use */
uint32_t pcb_flags; /* endpoint flags being checked */
@@ -231,7 +231,7 @@ struct rtcc_cc {
uint64_t bw_tot_time; /* The total time since sending began */
uint64_t new_tot_time; /* temp holding the new value */
uint64_t bw_bytes_at_last_rttc; /* What bw_bytes was at last rtt calc */
- uint32_t cwnd_at_bw_set;/* Cwnd at last bw saved - lbw */
+ uint32_t cwnd_at_bw_set; /* Cwnd at last bw saved - lbw */
uint32_t vol_reduce; /* cnt of voluntary reductions */
uint16_t steady_step; /* The number required to be in steady state */
uint16_t step_cnt; /* The current number */
@@ -240,7 +240,8 @@ struct rtcc_cc {
uint8_t use_dccc_ecn; /* Flag to enable DCCC ECN */
uint8_t tls_needs_set; /* Flag to indicate we need to set tls 0 or 1
* means set at send 2 not */
- uint8_t last_step_state;/* Last state if steady state stepdown is on */
+ uint8_t last_step_state; /* Last state if steady state stepdown
+ * is on */
uint8_t rtt_set_this_sack; /* Flag saying this sack had RTT calc
* on it */
uint8_t last_inst_ind; /* Last saved inst indication */
@@ -331,8 +332,8 @@ struct sctp_nets {
uint8_t dscp;
struct timeval start_time; /* time when this net was created */
- uint32_t marked_retrans;/* number or DATA chunks marked for timer
- * based retransmissions */
+ uint32_t marked_retrans; /* number or DATA chunks marked for
+ * timer based retransmissions */
uint32_t marked_fastretrans;
uint32_t heart_beat_delay; /* Heart Beat delay in ms */
@@ -706,28 +707,28 @@ struct sctp_nonpad_sndrcvinfo {
struct sctp_cc_functions {
void (*sctp_set_initial_cc_param) (struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_after_sack) (struct sctp_tcb *stcb,
- struct sctp_association *asoc,
- int accum_moved, int reneged_all, int will_exit);
+ struct sctp_association *asoc,
+ int accum_moved, int reneged_all, int will_exit);
void (*sctp_cwnd_update_exit_pf) (struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_after_fr) (struct sctp_tcb *stcb,
- struct sctp_association *asoc);
+ struct sctp_association *asoc);
void (*sctp_cwnd_update_after_timeout) (struct sctp_tcb *stcb,
- struct sctp_nets *net);
+ struct sctp_nets *net);
void (*sctp_cwnd_update_after_ecn_echo) (struct sctp_tcb *stcb,
- struct sctp_nets *net, int in_window, int num_pkt_lost);
+ struct sctp_nets *net, int in_window, int num_pkt_lost);
void (*sctp_cwnd_update_after_packet_dropped) (struct sctp_tcb *stcb,
- struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
- uint32_t *bottle_bw, uint32_t *on_queue);
+ struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
+ uint32_t *bottle_bw, uint32_t *on_queue);
void (*sctp_cwnd_update_after_output) (struct sctp_tcb *stcb,
- struct sctp_nets *net, int burst_limit);
+ struct sctp_nets *net, int burst_limit);
void (*sctp_cwnd_update_packet_transmitted) (struct sctp_tcb *stcb,
- struct sctp_nets *net);
+ struct sctp_nets *net);
void (*sctp_cwnd_update_tsn_acknowledged) (struct sctp_nets *net,
- struct sctp_tmit_chunk *);
+ struct sctp_tmit_chunk *);
void (*sctp_cwnd_new_transmission_begins) (struct sctp_tcb *stcb,
- struct sctp_nets *net);
+ struct sctp_nets *net);
void (*sctp_cwnd_prepare_net_for_sack) (struct sctp_tcb *stcb,
- struct sctp_nets *net);
+ struct sctp_nets *net);
int (*sctp_cwnd_socket_option) (struct sctp_tcb *stcb, int set, struct sctp_cc_option *);
void (*sctp_rtt_calculated) (struct sctp_tcb *, struct sctp_nets *, struct timeval *);
};
@@ -738,25 +739,25 @@ struct sctp_cc_functions {
*/
struct sctp_ss_functions {
void (*sctp_ss_init) (struct sctp_tcb *stcb, struct sctp_association *asoc,
- int holds_lock);
+ int holds_lock);
void (*sctp_ss_clear) (struct sctp_tcb *stcb, struct sctp_association *asoc,
- int clear_values, int holds_lock);
+ int clear_values, int holds_lock);
void (*sctp_ss_init_stream) (struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq);
void (*sctp_ss_add_to_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc,
- struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock);
+ struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock);
int (*sctp_ss_is_empty) (struct sctp_tcb *stcb, struct sctp_association *asoc);
void (*sctp_ss_remove_from_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc,
- struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock);
- struct sctp_stream_out *(*sctp_ss_select_stream) (struct sctp_tcb *stcb,
- struct sctp_nets *net, struct sctp_association *asoc);
+ struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock);
+struct sctp_stream_out *(*sctp_ss_select_stream) (struct sctp_tcb *stcb,
+ struct sctp_nets *net, struct sctp_association *asoc);
void (*sctp_ss_scheduled) (struct sctp_tcb *stcb, struct sctp_nets *net,
- struct sctp_association *asoc, struct sctp_stream_out *strq, int moved_how_much);
+ struct sctp_association *asoc, struct sctp_stream_out *strq, int moved_how_much);
void (*sctp_ss_packet_done) (struct sctp_tcb *stcb, struct sctp_nets *net,
- struct sctp_association *asoc);
+ struct sctp_association *asoc);
int (*sctp_ss_get_value) (struct sctp_tcb *stcb, struct sctp_association *asoc,
- struct sctp_stream_out *strq, uint16_t *value);
+ struct sctp_stream_out *strq, uint16_t *value);
int (*sctp_ss_set_value) (struct sctp_tcb *stcb, struct sctp_association *asoc,
- struct sctp_stream_out *strq, uint16_t value);
+ struct sctp_stream_out *strq, uint16_t value);
int (*sctp_ss_is_user_msgs_incomplete) (struct sctp_tcb *stcb, struct sctp_association *asoc);
};
diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c
index f1a8d1d5..a4343cbe 100644
--- a/freebsd/sys/netinet/sctp_sysctl.c
+++ b/freebsd/sys/netinet/sctp_sysctl.c
@@ -411,7 +411,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xinpcb.total_recvs = inp->total_recvs;
xinpcb.total_nospaces = inp->total_nospaces;
xinpcb.fragmentation_point = inp->sctp_frag_point;
- xinpcb.socket = inp->sctp_socket;
+ xinpcb.socket = (uintptr_t)inp->sctp_socket;
so = inp->sctp_socket;
if ((so == NULL) ||
(!SCTP_IS_LISTENING(inp)) ||
diff --git a/freebsd/sys/netinet/sctp_timer.c b/freebsd/sys/netinet/sctp_timer.c
index c0253840..86ed4d0d 100644
--- a/freebsd/sys/netinet/sctp_timer.c
+++ b/freebsd/sys/netinet/sctp_timer.c
@@ -651,6 +651,7 @@ start_again:
sctp_log_fr(chk->rec.data.tsn, chk->snd_count,
0, SCTP_FR_T3_MARKED);
}
+
if (chk->rec.data.chunk_was_revoked) {
/* deflate the cwnd */
chk->whoTo->cwnd -= chk->book_size;
@@ -717,6 +718,7 @@ start_again:
/* we did not subtract the same things? */
audit_tf = 1;
}
+
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
}
@@ -791,6 +793,7 @@ start_again:
(uint32_t)(uintptr_t)chk->whoTo,
chk->rec.data.tsn);
}
+
sctp_flight_size_increase(chk);
sctp_total_flight_increase(stcb, chk);
}
@@ -911,6 +914,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
(net->flight_size == 0)) {
(*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net);
}
+
/*
* setup the sat loss recovery that prevents satellite cwnd advance.
*/
@@ -939,6 +943,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
RTFREE(net->ro.ro_rt);
net->ro.ro_rt = NULL;
}
+
/* Was it our primary? */
if ((stcb->asoc.primary_destination == net) && (alt != net)) {
/*
@@ -959,7 +964,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
* Special case for cookie-echo'ed case, we don't do output but must
* await the COOKIE-ACK before retransmission
*/
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
/*
* Here we just reset the timer and start again since we
* have not established the asoc
@@ -1001,7 +1006,7 @@ sctp_t1init_timer(struct sctp_inpcb *inp,
sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED);
return (0);
}
- if (SCTP_GET_STATE((&stcb->asoc)) != SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
return (0);
}
if (sctp_threshold_management(inp, stcb, net,
@@ -1049,7 +1054,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
}
}
if (cookie == NULL) {
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
/* FOOBAR! */
struct mbuf *op_err;
@@ -1061,7 +1066,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
#ifdef INVARIANTS
panic("Cookie timer expires in wrong state?");
#else
- SCTP_PRINTF("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(&stcb->asoc));
+ SCTP_PRINTF("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(stcb));
return (0);
#endif
}
@@ -1212,6 +1217,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asconf->whoTo = alt;
atomic_add_int(&alt->ref_count, 1);
}
+
/* See if an ECN Echo is also stranded */
TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
if ((chk->whoTo == net) &&
@@ -1554,16 +1560,15 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
* there is nothing queued to send, so I'm
* done...
*/
- if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) {
/* only send SHUTDOWN 1st time thru */
struct sctp_nets *netp;
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (stcb->asoc.alternate) {
netp = stcb->asoc.alternate;
diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h
index 8732219c..c91e0414 100644
--- a/freebsd/sys/netinet/sctp_uio.h
+++ b/freebsd/sys/netinet/sctp_uio.h
@@ -258,13 +258,14 @@ struct sctp_snd_all_completes {
/* for the endpoint */
/* The lower four bits is an enumeration of PR-SCTP policies */
-#define SCTP_PR_SCTP_NONE 0x0000/* Reliable transfer */
-#define SCTP_PR_SCTP_TTL 0x0001/* Time based PR-SCTP */
-#define SCTP_PR_SCTP_PRIO 0x0002/* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_NONE 0x0000 /* Reliable transfer */
+#define SCTP_PR_SCTP_TTL 0x0001 /* Time based PR-SCTP */
+#define SCTP_PR_SCTP_PRIO 0x0002 /* Buffer based PR-SCTP */
#define SCTP_PR_SCTP_BUF SCTP_PR_SCTP_PRIO /* For backwards compatibility */
-#define SCTP_PR_SCTP_RTX 0x0003/* Number of retransmissions based PR-SCTP */
+#define SCTP_PR_SCTP_RTX 0x0003 /* Number of retransmissions based
+ * PR-SCTP */
#define SCTP_PR_SCTP_MAX SCTP_PR_SCTP_RTX
-#define SCTP_PR_SCTP_ALL 0x000f/* Used for aggregated stats */
+#define SCTP_PR_SCTP_ALL 0x000f /* Used for aggregated stats */
#define PR_SCTP_POLICY(x) ((x) & 0x0f)
#define PR_SCTP_ENABLED(x) ((PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE) && \
@@ -744,7 +745,7 @@ struct sctp_prstatus {
struct sctp_cwnd_args {
struct sctp_nets *net; /* network to *//* FIXME: LP64 issue */
- uint32_t cwnd_new_value;/* cwnd in k */
+ uint32_t cwnd_new_value; /* cwnd in k */
uint32_t pseudo_cumack;
uint16_t inflight; /* flightsize in k */
uint16_t cwnd_augment; /* increment to it */
@@ -758,9 +759,9 @@ struct sctp_blk_args {
uint32_t onsb; /* in 1k bytes */
uint32_t sndlen; /* len of send being attempted */
uint32_t peer_rwnd; /* rwnd of peer */
- uint16_t send_sent_qcnt;/* chnk cnt */
+ uint16_t send_sent_qcnt; /* chnk cnt */
uint16_t stream_qcnt; /* chnk cnt */
- uint16_t chunks_on_oque;/* chunks out */
+ uint16_t chunks_on_oque; /* chunks out */
uint16_t flight_size; /* flight size in k */
};
@@ -952,7 +953,7 @@ struct sctpstat {
uint32_t sctps_collisionestab;
uint32_t sctps_passiveestab; /* sctpStats 3 (Counter32) */
uint32_t sctps_aborted; /* sctpStats 4 (Counter32) */
- uint32_t sctps_shutdown;/* sctpStats 5 (Counter32) */
+ uint32_t sctps_shutdown; /* sctpStats 5 (Counter32) */
uint32_t sctps_outoftheblue; /* sctpStats 6 (Counter32) */
uint32_t sctps_checksumerrors; /* sctpStats 7 (Counter32) */
uint32_t sctps_outcontrolchunks; /* sctpStats 8 (Counter64) */
@@ -971,12 +972,12 @@ struct sctpstat {
uint32_t sctps_recvdatagrams; /* total input datagrams */
uint32_t sctps_recvpktwithdata; /* total packets that had data */
uint32_t sctps_recvsacks; /* total input SACK chunks */
- uint32_t sctps_recvdata;/* total input DATA chunks */
+ uint32_t sctps_recvdata; /* total input DATA chunks */
uint32_t sctps_recvdupdata; /* total input duplicate DATA chunks */
uint32_t sctps_recvheartbeat; /* total input HB chunks */
uint32_t sctps_recvheartbeatack; /* total input HB-ACK chunks */
- uint32_t sctps_recvecne;/* total input ECNE chunks */
- uint32_t sctps_recvauth;/* total input AUTH chunks */
+ uint32_t sctps_recvecne; /* total input ECNE chunks */
+ uint32_t sctps_recvauth; /* total input AUTH chunks */
uint32_t sctps_recvauthmissing; /* total input chunks missing AUTH */
uint32_t sctps_recvivalhmacid; /* total number of invalid HMAC ids
* received */
@@ -993,7 +994,7 @@ struct sctpstat {
/* output statistics: */
uint32_t sctps_sendpackets; /* total output packets */
uint32_t sctps_sendsacks; /* total output SACKs */
- uint32_t sctps_senddata;/* total output DATA chunks */
+ uint32_t sctps_senddata; /* total output DATA chunks */
uint32_t sctps_sendretransdata; /* total output retransmitted DATA
* chunks */
uint32_t sctps_sendfastretrans; /* total output fast retransmitted
@@ -1003,8 +1004,8 @@ struct sctpstat {
* chunk (u-del multi-fr
* algo). */
uint32_t sctps_sendheartbeat; /* total output HB chunks */
- uint32_t sctps_sendecne;/* total output ECNE chunks */
- uint32_t sctps_sendauth;/* total output AUTH chunks FIXME */
+ uint32_t sctps_sendecne; /* total output ECNE chunks */
+ uint32_t sctps_sendauth; /* total output AUTH chunks FIXME */
uint32_t sctps_senderrors; /* ip_output error counter */
uint32_t sctps_send_spare; /* formerly sctps_sendnocrc */
uint32_t sctps_sendswcrc;
@@ -1012,8 +1013,8 @@ struct sctpstat {
/* PCKDROPREP statistics: */
uint32_t sctps_pdrpfmbox; /* Packet drop from middle box */
uint32_t sctps_pdrpfehos; /* P-drop from end host */
- uint32_t sctps_pdrpmbda;/* P-drops with data */
- uint32_t sctps_pdrpmbct;/* P-drops, non-data, non-endhost */
+ uint32_t sctps_pdrpmbda; /* P-drops with data */
+ uint32_t sctps_pdrpmbct; /* P-drops, non-data, non-endhost */
uint32_t sctps_pdrpbwrpt; /* P-drop, non-endhost, bandwidth rep
* only */
uint32_t sctps_pdrpcrupt; /* P-drop, not enough for chunk header */
@@ -1024,16 +1025,17 @@ struct sctpstat {
uint32_t sctps_pdrpdnfnd; /* P-drop, attempt reverse TSN lookup */
uint32_t sctps_pdrpdiwnp; /* P-drop, e-host confirms zero-rwnd */
uint32_t sctps_pdrpdizrw; /* P-drop, midbox confirms no space */
- uint32_t sctps_pdrpbadd;/* P-drop, data did not match TSN */
- uint32_t sctps_pdrpmark;/* P-drop, TSN's marked for Fast Retran */
+ uint32_t sctps_pdrpbadd; /* P-drop, data did not match TSN */
+ uint32_t sctps_pdrpmark; /* P-drop, TSN's marked for Fast
+ * Retran */
/* timeouts */
uint32_t sctps_timoiterator; /* Number of iterator timers that
* fired */
- uint32_t sctps_timodata;/* Number of T3 data time outs */
+ uint32_t sctps_timodata; /* Number of T3 data time outs */
uint32_t sctps_timowindowprobe; /* Number of window probe (T3) timers
* that fired */
- uint32_t sctps_timoinit;/* Number of INIT timers that fired */
- uint32_t sctps_timosack;/* Number of sack timers that fired */
+ uint32_t sctps_timoinit; /* Number of INIT timers that fired */
+ uint32_t sctps_timosack; /* Number of sack timers that fired */
uint32_t sctps_timoshutdown; /* Number of shutdown timers that
* fired */
uint32_t sctps_timoheartbeat; /* Number of heartbeat timers that
@@ -1175,14 +1177,11 @@ struct xsctp_inpcb {
uint16_t local_port;
uint16_t qlen_old;
uint16_t maxqlen_old;
- void *socket;
+ uint16_t __spare16;
+ kvaddr_t socket;
uint32_t qlen;
uint32_t maxqlen;
-#if defined(__LP64__)
- uint32_t extra_padding[27]; /* future */
-#else
- uint32_t extra_padding[28]; /* future */
-#endif
+ uint32_t extra_padding[26]; /* future */
};
struct xsctp_tcb {
@@ -1192,7 +1191,7 @@ struct xsctp_tcb {
uint32_t state; /* sctpAssocEntry 8 */
uint32_t in_streams; /* sctpAssocEntry 9 */
uint32_t out_streams; /* sctpAssocEntry 10 */
- uint32_t max_nr_retrans;/* sctpAssocEntry 11 */
+ uint32_t max_nr_retrans; /* sctpAssocEntry 11 */
uint32_t primary_process; /* sctpAssocEntry 12 */
uint32_t T1_expireries; /* sctpAssocEntry 13 */
uint32_t T2_expireries; /* sctpAssocEntry 14 */
@@ -1305,37 +1304,37 @@ void sctp_freeladdrs(struct sockaddr *);
int sctp_opt_info(int, sctp_assoc_t, int, void *, socklen_t *);
/* deprecated */
-ssize_t
+ssize_t
sctp_sendmsg(int, const void *, size_t, const struct sockaddr *,
socklen_t, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t);
/* deprecated */
-ssize_t
+ssize_t
sctp_send(int, const void *, size_t,
const struct sctp_sndrcvinfo *, int);
/* deprecated */
-ssize_t
+ssize_t
sctp_sendx(int, const void *, size_t, struct sockaddr *,
int, struct sctp_sndrcvinfo *, int);
/* deprecated */
-ssize_t
+ssize_t
sctp_sendmsgx(int sd, const void *, size_t, struct sockaddr *,
int, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t);
sctp_assoc_t sctp_getassocid(int, struct sockaddr *);
/* deprecated */
-ssize_t
+ssize_t
sctp_recvmsg(int, void *, size_t, struct sockaddr *, socklen_t *,
struct sctp_sndrcvinfo *, int *);
-ssize_t
+ssize_t
sctp_sendv(int, const struct iovec *, int, struct sockaddr *,
int, void *, socklen_t, unsigned int, int);
-ssize_t
+ssize_t
sctp_recvv(int, const struct iovec *, int, struct sockaddr *,
socklen_t *, void *, socklen_t *, unsigned int *, int *);
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index 071d44c2..b519971c 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -391,6 +391,7 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
SCTP_INP_DECR_REF(inp);
goto cred_can_cont;
}
+
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
goto out;
@@ -431,6 +432,7 @@ sctp_abort(struct socket *so)
if (inp == NULL) {
return;
}
+
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@@ -704,8 +706,7 @@ sctp_disconnect(struct socket *so)
if (((so->so_options & SO_LINGER) &&
(so->so_linger == 0)) ||
(so->so_rcv.sb_cc > 0)) {
- if (SCTP_GET_STATE(asoc) !=
- SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
/* Left with Data unread */
struct mbuf *op_err;
@@ -714,8 +715,8 @@ sctp_disconnect(struct socket *so)
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
}
SCTP_INP_RUNLOCK(inp);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
@@ -730,17 +731,16 @@ sctp_disconnect(struct socket *so)
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
goto abort_anyway;
}
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* only send SHUTDOWN 1st time thru */
struct sctp_nets *netp;
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (stcb->asoc.alternate) {
netp = stcb->asoc.alternate;
@@ -773,11 +773,11 @@ sctp_disconnect(struct socket *so)
netp = stcb->asoc.primary_destination;
}
- asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
netp);
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
@@ -789,8 +789,8 @@ sctp_disconnect(struct socket *so)
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_INP_RUNLOCK(inp);
@@ -921,9 +921,9 @@ sctp_shutdown(struct socket *so)
SCTP_INP_RUNLOCK(inp);
return (0);
}
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_ECHOED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_ECHOED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN)) {
/*
* If we are not in or before ESTABLISHED, there is
* no protocol action required.
@@ -937,7 +937,7 @@ sctp_shutdown(struct socket *so)
} else {
netp = stcb->asoc.primary_destination;
}
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) &&
TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->stream_queue_cnt == 0)) {
@@ -946,8 +946,7 @@ sctp_shutdown(struct socket *so)
}
/* there is nothing queued to send, so I'm done... */
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
@@ -957,9 +956,9 @@ sctp_shutdown(struct socket *so)
* We still got (or just got) data to send, so set
* SHUTDOWN_PENDING.
*/
- SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT);
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
@@ -1369,11 +1368,13 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
+
if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
(sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -1438,6 +1439,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
goto out_now;
}
}
+
/* FIX ME: do we want to pass in a vrf on the connect call? */
vrf_id = inp->def_vrf_id;
@@ -1457,7 +1459,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
switch (sa->sa_family) {
#ifdef INET
@@ -1549,6 +1551,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -2393,6 +2396,7 @@ flags_out:
break;
}
}
+
if (stcb != NULL) {
/* Applies to the specific association */
paddrp->spp_flags = 0;
@@ -3262,6 +3266,7 @@ flags_out:
break;
}
}
+
if (stcb != NULL) {
if (net != NULL) {
thlds->spt_pathmaxrxt = net->failure_threshold;
@@ -3374,6 +3379,7 @@ flags_out:
break;
}
}
+
if (stcb != NULL) {
if (net) {
encaps->sue_port = net->port;
@@ -4252,6 +4258,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ } else {
+ inp->auth_supported = 1;
}
SCTP_INP_WUNLOCK(inp);
break;
@@ -4397,6 +4405,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
+
hmaclist = sctp_alloc_hmaclist((uint16_t)shmac->shmac_number_of_idents);
if (hmaclist == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
@@ -4589,6 +4598,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_INP_RUNLOCK(inp);
}
+
}
break;
}
@@ -5272,12 +5282,14 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
if (stcb != NULL) {
/************************TCB SPECIFIC SET ******************/
if (net != NULL) {
@@ -5413,6 +5425,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
net->failure_threshold = paddrp->spp_pathmaxrxt;
}
}
+
if (paddrp->spp_flags & SPP_HB_ENABLE) {
if (paddrp->spp_hbinterval != 0) {
stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
@@ -5523,6 +5536,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (paddrp->spp_pathmaxrxt != 0) {
inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
}
+
if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
else if (paddrp->spp_hbinterval != 0) {
@@ -5530,6 +5544,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
}
+
if (paddrp->spp_flags & SPP_HB_ENABLE) {
if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
@@ -6482,6 +6497,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
break;
}
}
+
if (stcb != NULL) {
if (net != NULL) {
net->port = encaps->sue_port;
@@ -6865,6 +6881,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
+
switch (addr->sa_family) {
#ifdef INET6
case AF_INET6:
@@ -6970,6 +6987,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
error = EALREADY;
goto out_now;
}
+
vrf_id = inp->def_vrf_id;
/* We are GOOD to go */
stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
@@ -6984,7 +7002,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
/* initialize authentication parameters for the assoc */
@@ -6996,6 +7014,7 @@ out_now:
if (create_lock_on) {
SCTP_ASOC_CREATE_UNLOCK(inp);
}
+
SCTP_INP_DECR_REF(inp);
return (error);
}
@@ -7134,6 +7153,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
return (EADDRINUSE);
}
}
+
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
/* We are already connected AND the TCP model */
@@ -7201,7 +7221,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
SCTP_TCB_LOCK(stcb);
SCTP_INP_RUNLOCK(inp);
store = stcb->asoc.primary_destination->ro._l_addr;
- stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
SCTP_TCB_UNLOCK(stcb);
switch (store.sa.sa_family) {
#ifdef INET
@@ -7336,6 +7356,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
SCTP_TCB_UNLOCK(stcb);
goto notConn;
}
+
vrf_id = inp->def_vrf_id;
sctp_ifa = sctp_source_address_selection(inp,
stcb,
diff --git a/freebsd/sys/netinet/sctp_var.h b/freebsd/sys/netinet/sctp_var.h
index 84cbfc88..175888c3 100644
--- a/freebsd/sys/netinet/sctp_var.h
+++ b/freebsd/sys/netinet/sctp_var.h
@@ -341,12 +341,12 @@ int sctp_input(struct mbuf **, int *, int);
void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t);
void sctp_drain(void);
void sctp_init(void);
-void
+void
sctp_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *,
uint8_t, uint8_t, uint16_t, uint32_t);
int sctp_flush(struct socket *, int);
int sctp_shutdown(struct socket *);
-int
+int
sctp_bindx(struct socket *, int, struct sockaddr_storage *,
int, int, struct proc *);
diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index aad1e19d..c3cb115e 100644
--- a/freebsd/sys/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#include <netinet/in_kdtrace.h>
#include <sys/proc.h>
#ifdef INET6
#include <netinet/icmp6.h>
@@ -1016,7 +1017,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc = &stcb->asoc;
/* init all variables to a known value. */
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
+ SCTP_SET_STATE(stcb, SCTP_STATE_INUSE);
asoc->max_burst = inp->sctp_ep.max_burst;
asoc->fr_max_burst = inp->sctp_ep.fr_max_burst;
asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
@@ -1435,6 +1436,7 @@ select_a_new_ep:
atomic_add_int(&it->stcb->asoc.refcnt, -1);
iteration_count = 0;
}
+
/* run function on this one */
(*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
@@ -1788,6 +1790,7 @@ sctp_timeout_handler(void *t)
if ((stcb == NULL) || (inp == NULL)) {
break;
}
+
if (sctp_cookie_timer(inp, stcb, net)) {
/* no need to unlock on tcb its gone */
goto out_decr;
@@ -1983,6 +1986,7 @@ out_decr:
if (inp) {
SCTP_INP_DECR_REF(inp);
}
+
out_no_decr:
SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type = %d)\n", type);
CURVNET_RESTORE();
@@ -2498,9 +2502,8 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
}
timevalsub(&now, old);
/* store the current RTT in us */
- net->rtt = (uint64_t)1000000 *(uint64_t)now.tv_sec +
- (uint64_t)now.tv_usec;
-
+ net->rtt = (uint64_t)1000000 * (uint64_t)now.tv_sec +
+ (uint64_t)now.tv_usec;
/* compute rtt in ms */
rtt = (int32_t)(net->rtt / 1000);
if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
@@ -2522,6 +2525,7 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
net->lan_type = SCTP_LAN_LOCAL;
}
}
+
/***************************/
/* 2. update RTTVAR & SRTT */
/***************************/
@@ -2798,7 +2802,7 @@ set_error:
((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
SOCK_LOCK(stcb->sctp_socket);
if (from_peer) {
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) {
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
stcb->sctp_socket->so_error = ECONNREFUSED;
} else {
@@ -2806,8 +2810,8 @@ set_error:
stcb->sctp_socket->so_error = ECONNRESET;
}
} else {
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT);
stcb->sctp_socket->so_error = ETIMEDOUT;
} else {
@@ -2960,6 +2964,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
/* event not enabled */
return;
}
+
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
notifhdr_len = sizeof(struct sctp_send_failed_event);
} else {
@@ -3188,6 +3193,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb)
/* event not enabled */
return;
}
+
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
@@ -3244,6 +3250,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
return;
}
+
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
@@ -3352,6 +3359,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
/* event not enabled */
return;
}
+
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
@@ -3401,6 +3409,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
/* event not enabled */
return;
}
+
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
/* no space left */
@@ -3557,6 +3566,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
/* event not enabled */
return;
}
+
m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
@@ -3691,8 +3701,8 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
return;
}
- if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
- (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
(notification == SCTP_NOTIFY_INTERFACE_UP) ||
(notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) {
@@ -3766,16 +3776,16 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
break;
}
case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
- if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
- ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked);
} else {
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked);
}
break;
case SCTP_NOTIFY_ASSOC_REM_ABORTED:
- if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
- ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked);
} else {
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked);
@@ -4019,7 +4029,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (stcb != NULL) {
/* We have a TCB to abort, send notification too */
sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
- stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
/* Ok, now lets free it */
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
@@ -4030,8 +4040,8 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
@@ -4130,13 +4140,13 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
return;
} else {
- stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
}
/* notify the peer */
sctp_send_abort_tcb(stcb, op_err, so_locked);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
/* notify the ulp */
@@ -4971,6 +4981,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
if (holds_lock == 0) {
SCTP_INP_RLOCK(inp);
}
+
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == NULL)
continue;
@@ -5060,6 +5071,7 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
SCTP_IPI_ADDR_RUNLOCK();
return (NULL);
}
+
hash_of_addr = sctp_get_ifa_hash_val(addr);
hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)];
@@ -5121,9 +5133,8 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
atomic_add_int(&stcb->asoc.refcnt, 1);
- if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED |
- SCTP_STATE_SHUTDOWN_RECEIVED |
- SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) ||
+ (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED | SCTP_STATE_SHUTDOWN_RECEIVED))) {
/* Pre-check If we are freeing no update */
goto no_lock;
}
@@ -5184,6 +5195,7 @@ out:
if (so && r_unlocked && hold_rlock) {
SCTP_INP_READ_LOCK(stcb->sctp_ep);
}
+
SCTP_INP_DECR_REF(stcb->sctp_ep);
no_lock:
atomic_add_int(&stcb->asoc.refcnt, -1);
@@ -5233,6 +5245,7 @@ sctp_sorecvmsg(struct socket *so,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (EINVAL);
}
+
if (msg_flags) {
in_flags = *msg_flags;
if (in_flags & MSG_PEEK)
@@ -5276,6 +5289,8 @@ sctp_sorecvmsg(struct socket *so,
sctp_misc_ints(SCTP_SORECV_ENTERPL,
rwnd_req, block_allowed, so->so_rcv.sb_cc, (uint32_t)uio->uio_resid);
}
+
+
error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
if (error) {
goto release_unlocked;
@@ -5385,6 +5400,7 @@ restart_nosblocks:
hold_rlock = 0;
goto restart;
}
+
if ((control->length == 0) &&
(control->do_not_ref_stcb)) {
/*
@@ -5568,6 +5584,7 @@ found_one:
control->do_not_ref_stcb == 0) {
stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1;
}
+
/* First lets get off the sinfo and sockaddr info */
if ((sinfo != NULL) && (filling_sinfo != 0)) {
sinfo->sinfo_stream = control->sinfo_stream;
@@ -5729,6 +5746,7 @@ get_more_data:
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
goto release;
}
+
if ((control->do_not_ref_stcb == 0) && stcb &&
stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
no_rcv_needed = 1;
@@ -5941,6 +5959,7 @@ wait_some_more:
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
goto release;
}
+
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)
goto release;
@@ -6069,6 +6088,7 @@ release:
SOCKBUF_UNLOCK(&so->so_rcv);
hold_sblock = 0;
}
+
sbunlock(&so->so_rcv);
sockbuf_lock = 0;
@@ -6106,6 +6126,7 @@ out:
if (sockbuf_lock) {
sbunlock(&so->so_rcv);
}
+
if (freecnt_applied) {
/*
* The lock on the socket buffer protects us so the free
@@ -6703,6 +6724,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
SCTP_IPI_ADDR_RUNLOCK();
return (0);
}
+
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
/*
* bound all case: go through all ifns on the vrf
@@ -7362,3 +7384,49 @@ sctp_hc_get_mtu(union sctp_sockstore *addr, uint16_t fibnum)
}
return ((uint32_t)tcp_hc_getmtu(&inc));
}
+
+void
+sctp_set_state(struct sctp_tcb *stcb, int new_state)
+{
+#if defined(KDTRACE_HOOKS)
+ int old_state = stcb->asoc.state;
+#endif
+
+ KASSERT((new_state & ~SCTP_STATE_MASK) == 0,
+ ("sctp_set_state: Can't set substate (new_state = %x)",
+ new_state));
+ stcb->asoc.state = (stcb->asoc.state & ~SCTP_STATE_MASK) | new_state;
+ if ((new_state == SCTP_STATE_SHUTDOWN_RECEIVED) ||
+ (new_state == SCTP_STATE_SHUTDOWN_SENT) ||
+ (new_state == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
+ }
+#if defined(KDTRACE_HOOKS)
+ if (((old_state & SCTP_STATE_MASK) != new_state) &&
+ !(((old_state & SCTP_STATE_MASK) == SCTP_STATE_EMPTY) &&
+ (new_state == SCTP_STATE_INUSE))) {
+ SCTP_PROBE6(state__change, NULL, stcb, NULL, stcb, NULL, old_state);
+ }
+#endif
+}
+
+void
+sctp_add_substate(struct sctp_tcb *stcb, int substate)
+{
+#if defined(KDTRACE_HOOKS)
+ int old_state = stcb->asoc.state;
+#endif
+
+ KASSERT((substate & SCTP_STATE_MASK) == 0,
+ ("sctp_add_substate: Can't set state (substate = %x)",
+ substate));
+ stcb->asoc.state |= substate;
+#if defined(KDTRACE_HOOKS)
+ if (((substate & SCTP_STATE_ABOUT_TO_BE_FREED) &&
+ ((old_state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) ||
+ ((substate & SCTP_STATE_SHUTDOWN_PENDING) &&
+ ((old_state & SCTP_STATE_SHUTDOWN_PENDING) == 0))) {
+ SCTP_PROBE6(state__change, NULL, stcb, NULL, stcb, NULL, old_state);
+ }
+#endif
+}
diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h
index 61d34591..c12fb210 100644
--- a/freebsd/sys/netinet/sctputil.h
+++ b/freebsd/sys/netinet/sctputil.h
@@ -72,11 +72,9 @@ int32_t
uint32_t
sctp_get_ifa_hash_val(struct sockaddr *addr);
-struct sctp_ifa *
- sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int hold_lock);
+struct sctp_ifa *sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int hold_lock);
-struct sctp_ifa *
- sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock);
+struct sctp_ifa *sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock);
uint32_t sctp_select_initial_TSN(struct sctp_pcb *);
@@ -147,13 +145,11 @@ struct sctp_paramhdr *
sctp_get_next_param(struct mbuf *, int,
struct sctp_paramhdr *, int);
-struct mbuf *
- sctp_add_pad_tombuf(struct mbuf *, int);
+struct mbuf *sctp_add_pad_tombuf(struct mbuf *, int);
-struct mbuf *
- sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
+struct mbuf *sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
-void
+void
sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -168,7 +164,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
-void
+void
sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -177,7 +173,7 @@ sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
int sctp_expand_mapping_array(struct sctp_association *, uint32_t);
-void
+void
sctp_abort_notification(struct sctp_tcb *, uint8_t, uint16_t,
struct sctp_abort_chunk *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
@@ -203,7 +199,7 @@ sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *,
#endif
);
-void
+void
sctp_handle_ootb(struct mbuf *, int, int,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_inpcb *,
@@ -211,7 +207,7 @@ sctp_handle_ootb(struct mbuf *, int, int,
uint8_t, uint32_t, uint16_t,
uint32_t, uint16_t);
-int
+int
sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
int totaddr, int *error);
@@ -224,8 +220,7 @@ int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *);
#ifdef INET6
uint32_t sctp_is_same_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
-struct sockaddr_in6 *
- sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
+struct sockaddr_in6 *sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
#define sctp_recover_scope_mac(addr, store) do { \
if ((addr->sin6_family == AF_INET6) && \
@@ -258,11 +253,11 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
struct mbuf *sctp_generate_cause(uint16_t, char *);
struct mbuf *sctp_generate_no_user_data_cause(uint32_t);
-void
+void
sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
struct sockaddr *sa, sctp_assoc_t assoc_id,
uint32_t vrf_id, int *error, void *p);
-void
+void
sctp_bindx_delete_address(struct sctp_inpcb *inp,
struct sockaddr *sa, sctp_assoc_t assoc_id,
uint32_t vrf_id, int *error);
@@ -393,5 +388,7 @@ void sctp_audit_log(uint8_t, uint8_t);
uint32_t sctp_min_mtu(uint32_t, uint32_t, uint32_t);
void sctp_hc_set_mtu(union sctp_sockstore *, uint16_t, uint32_t);
uint32_t sctp_hc_get_mtu(union sctp_sockstore *, uint16_t);
+void sctp_set_state(struct sctp_tcb *, int);
+void sctp_add_substate(struct sctp_tcb *, int);
#endif /* _KERNEL */
#endif
diff --git a/freebsd/sys/netinet/tcp_hostcache.c b/freebsd/sys/netinet/tcp_hostcache.c
index d1de3f33..f2e3d875 100644
--- a/freebsd/sys/netinet/tcp_hostcache.c
+++ b/freebsd/sys/netinet/tcp_hostcache.c
@@ -114,10 +114,10 @@ __FBSDID("$FreeBSD$");
#define TCP_HOSTCACHE_EXPIRE 60*60 /* one hour */
#define TCP_HOSTCACHE_PRUNE 5*60 /* every 5 minutes */
-static VNET_DEFINE(struct tcp_hostcache, tcp_hostcache);
+VNET_DEFINE_STATIC(struct tcp_hostcache, tcp_hostcache);
#define V_tcp_hostcache VNET(tcp_hostcache)
-static VNET_DEFINE(struct callout, tcp_hc_callout);
+VNET_DEFINE_STATIC(struct callout, tcp_hc_callout);
#define V_tcp_hc_callout VNET(tcp_hc_callout)
static struct hc_metrics *tcp_hc_lookup(struct in_conninfo *);
diff --git a/freebsd/sys/netinet/tcp_hpts.h b/freebsd/sys/netinet/tcp_hpts.h
index c52a1d78..04c86769 100644
--- a/freebsd/sys/netinet/tcp_hpts.h
+++ b/freebsd/sys/netinet/tcp_hpts.h
@@ -238,10 +238,10 @@ int
#define tcp_queue_to_input_locked(a, b) __tcp_queue_to_input_locked(a, b, __LINE__);
void
tcp_queue_pkt_to_input(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
- int32_t tlen, int32_t drop_hdrlen, uint8_t iptos, uint8_t ti_locked);
+ int32_t tlen, int32_t drop_hdrlen, uint8_t iptos);
int
__tcp_queue_to_input(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
- int32_t tlen, int32_t drop_hdrlen, uint8_t iptos, uint8_t ti_locked, int32_t line);
+ int32_t tlen, int32_t drop_hdrlen, uint8_t iptos, int32_t line);
#define tcp_queue_to_input(a, b, c, d, e, f, g) __tcp_queue_to_input(a, b, c, d, e, f, g, __LINE__)
uint16_t tcp_hpts_delayedby(struct inpcb *inp);
diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index 20bea2de..2c6c3048 100644
--- a/freebsd/sys/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
@@ -585,6 +585,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
int rstreason = 0; /* For badport_bandlim accounting purposes */
uint8_t iptos;
struct m_tag *fwd_tag = NULL;
+ struct epoch_tracker et;
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
int isipv6;
@@ -775,7 +776,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
* connection in TIMEWAIT and SYNs not targeting a listening socket.
*/
if ((thflags & (TH_FIN | TH_RST)) != 0) {
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
ti_locked = TI_RLOCKED;
} else
ti_locked = TI_UNLOCKED;
@@ -962,25 +963,10 @@ findpcb:
*
* XXXRW: It may be time to rethink timewait locking.
*/
-relocked:
if (inp->inp_flags & INP_TIMEWAIT) {
if (ti_locked == TI_UNLOCKED) {
- if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) {
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- INP_INFO_RLOCK(&V_tcbinfo);
- ti_locked = TI_RLOCKED;
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp)) {
- inp = NULL;
- goto findpcb;
- } else if (inp->inp_flags & INP_DROPPED) {
- INP_WUNLOCK(inp);
- inp = NULL;
- goto findpcb;
- }
- } else
- ti_locked = TI_RLOCKED;
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
+ ti_locked = TI_RLOCKED;
}
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
@@ -991,7 +977,7 @@ relocked:
*/
if (tcp_twcheck(inp, &to, th, m, tlen))
goto findpcb;
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (IPPROTO_DONE);
}
/*
@@ -1028,23 +1014,8 @@ relocked:
(tp->t_state == TCPS_LISTEN && (thflags & TH_SYN) &&
!IS_FASTOPEN(tp->t_flags)))) {
if (ti_locked == TI_UNLOCKED) {
- if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) {
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- INP_INFO_RLOCK(&V_tcbinfo);
- ti_locked = TI_RLOCKED;
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp)) {
- inp = NULL;
- goto findpcb;
- } else if (inp->inp_flags & INP_DROPPED) {
- INP_WUNLOCK(inp);
- inp = NULL;
- goto findpcb;
- }
- goto relocked;
- } else
- ti_locked = TI_RLOCKED;
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
+ ti_locked = TI_RLOCKED;
}
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
}
@@ -1082,6 +1053,8 @@ relocked:
#ifdef INET6
if (isipv6) {
inc.inc_flags |= INC_ISIPV6;
+ if (inp->inp_inc.inc_flags & INC_IPV6MINMTU)
+ inc.inc_flags |= INC_IPV6MINMTU;
inc.inc6_faddr = ip6->ip6_src;
inc.inc6_laddr = ip6->ip6_dst;
} else
@@ -1176,9 +1149,11 @@ tfo_socket_result:
* contains. tcp_do_segment() consumes
* the mbuf chain and unlocks the inpcb.
*/
+ TCP_PROBE5(receive, NULL, tp, m, tp, th);
tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen,
- iptos, ti_locked);
- INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ iptos);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (IPPROTO_DONE);
}
/*
@@ -1382,7 +1357,7 @@ tfo_socket_result:
* Only the listen socket is unlocked by syncache_add().
*/
if (ti_locked == TI_RLOCKED) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
ti_locked = TI_UNLOCKED;
}
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
@@ -1416,15 +1391,16 @@ tfo_socket_result:
* state. tcp_do_segment() always consumes the mbuf chain, unlocks
* the inpcb, and unlocks pcbinfo.
*/
- tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked);
- INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (IPPROTO_DONE);
dropwithreset:
TCP_PROBE5(receive, NULL, tp, m, tp, th);
if (ti_locked == TI_RLOCKED) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
ti_locked = TI_UNLOCKED;
}
#ifdef INVARIANTS
@@ -1448,7 +1424,7 @@ dropunlock:
TCP_PROBE5(receive, NULL, tp, m, tp, th);
if (ti_locked == TI_RLOCKED) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
ti_locked = TI_UNLOCKED;
}
#ifdef INVARIANTS
@@ -1535,8 +1511,7 @@ tcp_autorcvbuf(struct mbuf *m, struct tcphdr *th, struct socket *so,
void
tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
- struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
- int ti_locked)
+ struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos)
{
int thflags, acked, ourfinisacked, needoutput = 0, sack_changed;
int rstreason, todrop, win;
@@ -1562,7 +1537,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->sackhint.last_sack_ack = 0;
sack_changed = 0;
nsegs = max(1, m->m_pkthdr.lro_nsegs);
-
/*
* If this is either a state-changing packet or current state isn't
* established, we require a write lock on tcbinfo. Otherwise, we
@@ -1571,19 +1545,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
tp->t_state != TCPS_ESTABLISHED) {
- KASSERT(ti_locked == TI_RLOCKED, ("%s ti_locked %d for "
- "SYN/FIN/RST/!EST", __func__, ti_locked));
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
- } else {
-#ifdef INVARIANTS
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
- else {
- KASSERT(ti_locked == TI_UNLOCKED, ("%s: EST "
- "ti_locked: %d", __func__, ti_locked));
- INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
- }
-#endif
}
INP_WLOCK_ASSERT(tp->t_inpcb);
KASSERT(tp->t_state > TCPS_LISTEN, ("%s: TCPS_LISTEN",
@@ -1717,10 +1679,19 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
(to.to_flags & TOF_SACKPERM) == 0)
tp->t_flags &= ~TF_SACK_PERMIT;
if (IS_FASTOPEN(tp->t_flags)) {
- if (to.to_flags & TOF_FASTOPEN)
- tcp_fastopen_update_cache(tp, to.to_mss,
+ if (to.to_flags & TOF_FASTOPEN) {
+ uint16_t mss;
+
+ if (to.to_flags & TOF_MSS)
+ mss = to.to_mss;
+ else
+ if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
+ mss = TCP6_MSS;
+ else
+ mss = TCP_MSS;
+ tcp_fastopen_update_cache(tp, mss,
to.to_tfo_len, to.to_tfo_cookie);
- else
+ } else
tcp_fastopen_disable_path(tp);
}
}
@@ -1767,7 +1738,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->snd_nxt == tp->snd_max &&
tiwin && tiwin == tp->snd_wnd &&
((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
- LIST_EMPTY(&tp->t_segq) &&
+ SEGQ_EMPTY(tp) &&
((to.to_flags & TOF_TS) == 0 ||
TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) {
@@ -1792,10 +1763,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
/*
* This is a pure ack for outstanding data.
*/
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- ti_locked = TI_UNLOCKED;
-
TCPSTAT_INC(tcps_predack);
/*
@@ -1899,10 +1866,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* nothing on the reassembly queue and we have enough
* buffer space to take it.
*/
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- ti_locked = TI_UNLOCKED;
-
/* Clean receiver SACK report if present */
if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks)
tcp_clean_sackreport(tp);
@@ -2104,8 +2067,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcp_state_change(tp, TCPS_SYN_RECEIVED);
}
- KASSERT(ti_locked == TI_RLOCKED, ("%s: trimthenstep6: "
- "ti_locked %d", __func__, ti_locked));
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -2180,9 +2141,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
(tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_RLOCKED,
- ("%s: TH_RST ti_locked %d, th %p tp %p",
- __func__, ti_locked, th, tp));
KASSERT(tp->t_state != TCPS_SYN_SENT,
("%s: TH_RST for TCPS_SYN_SENT th %p tp %p",
__func__, th, tp));
@@ -2225,8 +2183,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((thflags & TH_SYN) && tp->t_state != TCPS_SYN_SENT &&
tp->t_state != TCPS_SYN_RECEIVED) {
- KASSERT(ti_locked == TI_RLOCKED,
- ("tcp_do_segment: TH_SYN ti_locked %d", ti_locked));
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
TCPSTAT_INC(tcps_badsyn);
@@ -2340,8 +2296,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((so->so_state & SS_NOFDREF) &&
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
- KASSERT(ti_locked == TI_RLOCKED, ("%s: SS_NOFDEREF && "
- "CLOSE_WAIT && tlen ti_locked %d", __func__, ti_locked));
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
@@ -2457,6 +2411,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* SYN-RECEIVED* -> FIN-WAIT-1
*/
tp->t_starttime = ticks;
+ if (IS_FASTOPEN(tp->t_flags) && tp->t_tfo_pending) {
+ tcp_fastopen_decrement_counter(tp->t_tfo_pending);
+ tp->t_tfo_pending = NULL;
+
+ /*
+ * Account for the ACK of our SYN prior to
+ * regular ACK processing below.
+ */
+ tp->snd_una++;
+ }
if (tp->t_flags & TF_NEEDFIN) {
tcp_state_change(tp, TCPS_FIN_WAIT_1);
tp->t_flags &= ~TF_NEEDFIN;
@@ -2464,16 +2428,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcp_state_change(tp, TCPS_ESTABLISHED);
TCP_PROBE5(accept__established, NULL, tp,
m, tp, th);
- if (IS_FASTOPEN(tp->t_flags) && tp->t_tfo_pending) {
- tcp_fastopen_decrement_counter(tp->t_tfo_pending);
- tp->t_tfo_pending = NULL;
-
- /*
- * Account for the ACK of our SYN prior to
- * regular ACK processing below.
- */
- tp->snd_una++;
- }
/*
* TFO connections call cc_conn_init() during SYN
* processing. Calling it again here for such
@@ -2490,7 +2444,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* later; if not, do so now to pass queued data to user.
*/
if (tlen == 0 && (thflags & TH_FIN) == 0)
- (void) tcp_reass(tp, (struct tcphdr *)0, 0,
+ (void) tcp_reass(tp, (struct tcphdr *)0, NULL, 0,
(struct mbuf *)0);
tp->snd_wl1 = th->th_seq - 1;
/* FALLTHROUGH */
@@ -2931,7 +2885,6 @@ process_ACK:
if (ourfinisacked) {
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
tcp_twstart(tp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return;
}
@@ -3068,7 +3021,7 @@ dodata: /* XXX */
* fast retransmit can work).
*/
if (th->th_seq == tp->rcv_nxt &&
- LIST_EMPTY(&tp->t_segq) &&
+ SEGQ_EMPTY(tp) &&
(TCPS_HAVEESTABLISHED(tp->t_state) ||
tfo_syn)) {
if (DELAY_ACK(tp, tlen) || tfo_syn)
@@ -3093,7 +3046,7 @@ dodata: /* XXX */
* m_adj() doesn't actually frees any mbufs
* when trimming from the head.
*/
- thflags = tcp_reass(tp, th, &tlen, m);
+ thflags = tcp_reass(tp, th, &save_start, &tlen, m);
tp->t_flags |= TF_ACKNOW;
}
if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT))
@@ -3163,19 +3116,11 @@ dodata: /* XXX */
*/
case TCPS_FIN_WAIT_2:
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_RLOCKED, ("%s: dodata "
- "TCP_FIN_WAIT_2 ti_locked: %d", __func__,
- ti_locked));
tcp_twstart(tp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
return;
}
}
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- ti_locked = TI_UNLOCKED;
-
#ifdef TCPDEBUG
if (so->so_options & SO_DEBUG)
tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen,
@@ -3190,9 +3135,6 @@ dodata: /* XXX */
(void) tp->t_fb->tfb_tcp_output(tp);
check_delack:
- KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d",
- __func__, ti_locked));
- INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tp->t_inpcb);
if (tp->t_flags & TF_DELACK) {
@@ -3230,10 +3172,6 @@ dropafterack:
&tcp_savetcp, 0);
#endif
TCP_PROBE3(debug__input, tp, th, m);
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- ti_locked = TI_UNLOCKED;
-
tp->t_flags |= TF_ACKNOW;
(void) tp->t_fb->tfb_tcp_output(tp);
INP_WUNLOCK(tp->t_inpcb);
@@ -3241,10 +3179,6 @@ dropafterack:
return;
dropwithreset:
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- ti_locked = TI_UNLOCKED;
-
if (tp != NULL) {
tcp_dropwithreset(m, th, tp, tlen, rstreason);
INP_WUNLOCK(tp->t_inpcb);
@@ -3253,15 +3187,6 @@ dropwithreset:
return;
drop:
- if (ti_locked == TI_RLOCKED) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
- ti_locked = TI_UNLOCKED;
- }
-#ifdef INVARIANTS
- else
- INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
-#endif
-
/*
* Drop space held by incoming segment and return.
*/
diff --git a/freebsd/sys/netinet/tcp_log_buf.h b/freebsd/sys/netinet/tcp_log_buf.h
index 58713fe5..e569395a 100644
--- a/freebsd/sys/netinet/tcp_log_buf.h
+++ b/freebsd/sys/netinet/tcp_log_buf.h
@@ -94,7 +94,7 @@ struct tcp_log_bbr {
uint16_t flex7;
uint8_t bbr_state;
uint8_t bbr_substate;
- uint8_t inpacer;
+ uint8_t inhpts;
uint8_t ininput;
uint8_t use_lt_bw;
uint8_t flex8;
@@ -217,7 +217,9 @@ enum tcp_log_events {
BBR_LOG_REDUCE, /* old bbr log reduce for 4.1 and earlier 46*/
TCP_LOG_RTT, /* A rtt (in useconds) is being sampled and applied to the srtt algo 47 */
BBR_LOG_SETTINGS_CHG, /* Settings changed for loss response 48 */
- TCP_LOG_END /* End (keep at end) 49 */
+ BBR_LOG_SRTT_GAIN_EVENT, /* SRTT gaining 49 */
+ TCP_LOG_REASS, /* Reassembly buffer logging 50 */
+ TCP_LOG_END /* End (keep at end) 51 */
};
enum tcp_log_states {
diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c
index bdbfe984..8f83440d 100644
--- a/freebsd/sys/netinet/tcp_output.c
+++ b/freebsd/sys/netinet/tcp_output.c
@@ -145,18 +145,13 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_auto_lowat, CTLFLAG_VNET | CTLFLAG_R
tcp_timer_active((tp), TT_PERSIST), \
("neither rexmt nor persist timer is set"))
-#ifdef TCP_HHOOK
-static void inline hhook_run_tcp_est_out(struct tcpcb *tp,
- struct tcphdr *th, struct tcpopt *to,
- uint32_t len, int tso);
-#endif
static void inline cc_after_idle(struct tcpcb *tp);
#ifdef TCP_HHOOK
/*
* Wrapper for the TCP established output helper hook.
*/
-static void inline
+void
hhook_run_tcp_est_out(struct tcpcb *tp, struct tcphdr *th,
struct tcpopt *to, uint32_t len, int tso)
{
@@ -197,6 +192,8 @@ tcp_output(struct tcpcb *tp)
int32_t len;
uint32_t recwin, sendwin;
int off, flags, error = 0; /* Keep compiler happy */
+ u_int if_hw_tsomaxsegcount = 0;
+ u_int if_hw_tsomaxsegsize;
struct mbuf *m;
struct ip *ip = NULL;
#ifdef TCPDEBUG
@@ -233,13 +230,15 @@ tcp_output(struct tcpcb *tp)
#endif
/*
- * For TFO connections in SYN_RECEIVED, only allow the initial
- * SYN|ACK and those sent by the retransmit timer.
+ * For TFO connections in SYN_SENT or SYN_RECEIVED,
+ * only allow the initial SYN or SYN|ACK and those sent
+ * by the retransmit timer.
*/
if (IS_FASTOPEN(tp->t_flags) &&
- (tp->t_state == TCPS_SYN_RECEIVED) &&
- SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN|ACK sent */
- (tp->snd_nxt != tp->snd_una)) /* not a retransmit */
+ ((tp->t_state == TCPS_SYN_SENT) ||
+ (tp->t_state == TCPS_SYN_RECEIVED)) &&
+ SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN or SYN|ACK sent */
+ (tp->snd_nxt != tp->snd_una)) /* not a retransmit */
return (0);
/*
@@ -867,9 +866,6 @@ send:
if (tso) {
u_int if_hw_tsomax;
- u_int if_hw_tsomaxsegcount;
- u_int if_hw_tsomaxsegsize;
- struct mbuf *mb;
u_int moff;
int max_len;
@@ -901,65 +897,6 @@ send:
len = max_len;
}
}
-
- /*
- * Check if we should limit by maximum segment
- * size and count:
- */
- if (if_hw_tsomaxsegcount != 0 &&
- if_hw_tsomaxsegsize != 0) {
- /*
- * Subtract one segment for the LINK
- * and TCP/IP headers mbuf that will
- * be prepended to this mbuf chain
- * after the code in this section
- * limits the number of mbufs in the
- * chain to if_hw_tsomaxsegcount.
- */
- if_hw_tsomaxsegcount -= 1;
- max_len = 0;
- mb = sbsndmbuf(&so->so_snd, off, &moff);
-
- while (mb != NULL && max_len < len) {
- u_int mlen;
- u_int frags;
-
- /*
- * Get length of mbuf fragment
- * and how many hardware frags,
- * rounded up, it would use:
- */
- mlen = (mb->m_len - moff);
- frags = howmany(mlen,
- if_hw_tsomaxsegsize);
-
- /* Handle special case: Zero Length Mbuf */
- if (frags == 0)
- frags = 1;
-
- /*
- * Check if the fragment limit
- * will be reached or exceeded:
- */
- if (frags >= if_hw_tsomaxsegcount) {
- max_len += min(mlen,
- if_hw_tsomaxsegcount *
- if_hw_tsomaxsegsize);
- break;
- }
- max_len += mlen;
- if_hw_tsomaxsegcount -= frags;
- moff = 0;
- mb = mb->m_next;
- }
- if (max_len <= 0) {
- len = 0;
- } else if (len > max_len) {
- sendalot = 1;
- len = max_len;
- }
- }
-
/*
* Prevent the last segment from being
* fractional unless the send sockbuf can be
@@ -994,7 +931,6 @@ send:
*/
if (tp->t_flags & TF_NEEDFIN)
sendalot = 1;
-
} else {
len = tp->t_maxseg - optlen - ipoptlen;
sendalot = 1;
@@ -1029,6 +965,7 @@ send:
*/
if (len) {
struct mbuf *mb;
+ struct sockbuf *msb;
u_int moff;
if ((tp->t_flags & TF_FORCEDATA) && len == 1)
@@ -1062,14 +999,30 @@ send:
* Start the m_copy functions from the closest mbuf
* to the offset in the socket buffer chain.
*/
- mb = sbsndptr(&so->so_snd, off, len, &moff);
-
+ mb = sbsndptr_noadv(&so->so_snd, off, &moff);
if (len <= MHLEN - hdrlen - max_linkhdr) {
m_copydata(mb, moff, len,
mtod(m, caddr_t) + hdrlen);
+ if (SEQ_LT(tp->snd_nxt, tp->snd_max))
+ sbsndptr_adv(&so->so_snd, mb, len);
m->m_len += len;
} else {
- m->m_next = m_copym(mb, moff, len, M_NOWAIT);
+ if (SEQ_LT(tp->snd_nxt, tp->snd_max))
+ msb = NULL;
+ else
+ msb = &so->so_snd;
+ m->m_next = tcp_m_copym(mb, moff,
+ &len, if_hw_tsomaxsegcount,
+ if_hw_tsomaxsegsize, msb);
+ if (len <= (tp->t_maxseg - optlen)) {
+ /*
+ * Must have ran out of mbufs for the copy
+ * shorten it to no longer need tso. Lets
+ * not put on sendalot since we are low on
+ * mbufs.
+ */
+ tso = 0;
+ }
if (m->m_next == NULL) {
SOCKBUF_UNLOCK(&so->so_snd);
(void) m_free(m);
@@ -1853,6 +1806,144 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
return (optlen);
}
+/*
+ * This is a copy of m_copym(), taking the TSO segment size/limit
+ * constraints into account, and advancing the sndptr as it goes.
+ */
+struct mbuf *
+tcp_m_copym(struct mbuf *m, int32_t off0, int32_t *plen,
+ int32_t seglimit, int32_t segsize, struct sockbuf *sb)
+{
+ struct mbuf *n, **np;
+ struct mbuf *top;
+ int32_t off = off0;
+ int32_t len = *plen;
+ int32_t fragsize;
+ int32_t len_cp = 0;
+ int32_t *pkthdrlen;
+ uint32_t mlen, frags;
+ bool copyhdr;
+
+
+ KASSERT(off >= 0, ("tcp_m_copym, negative off %d", off));
+ KASSERT(len >= 0, ("tcp_m_copym, negative len %d", len));
+ if (off == 0 && m->m_flags & M_PKTHDR)
+ copyhdr = true;
+ else
+ copyhdr = false;
+ while (off > 0) {
+ KASSERT(m != NULL, ("tcp_m_copym, offset > size of mbuf chain"));
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ if ((sb) && (m == sb->sb_sndptr)) {
+ sb->sb_sndptroff += m->m_len;
+ sb->sb_sndptr = m->m_next;
+ }
+ m = m->m_next;
+ }
+ np = &top;
+ top = NULL;
+ pkthdrlen = NULL;
+ while (len > 0) {
+ if (m == NULL) {
+ KASSERT(len == M_COPYALL,
+ ("tcp_m_copym, length > size of mbuf chain"));
+ *plen = len_cp;
+ if (pkthdrlen != NULL)
+ *pkthdrlen = len_cp;
+ break;
+ }
+ mlen = min(len, m->m_len - off);
+ if (seglimit) {
+ /*
+ * For M_NOMAP mbufs, add 3 segments
+ * + 1 in case we are crossing page boundaries
+ * + 2 in case the TLS hdr/trailer are used
+ * It is cheaper to just add the segments
+ * than it is to take the cache miss to look
+ * at the mbuf ext_pgs state in detail.
+ */
+ if (m->m_flags & M_NOMAP) {
+ fragsize = min(segsize, PAGE_SIZE);
+ frags = 3;
+ } else {
+ fragsize = segsize;
+ frags = 0;
+ }
+
+ /* Break if we really can't fit anymore. */
+ if ((frags + 1) >= seglimit) {
+ *plen = len_cp;
+ if (pkthdrlen != NULL)
+ *pkthdrlen = len_cp;
+ break;
+ }
+
+ /*
+ * Reduce size if you can't copy the whole
+ * mbuf. If we can't copy the whole mbuf, also
+ * adjust len so the loop will end after this
+ * mbuf.
+ */
+ if ((frags + howmany(mlen, fragsize)) >= seglimit) {
+ mlen = (seglimit - frags - 1) * fragsize;
+ len = mlen;
+ *plen = len_cp + len;
+ if (pkthdrlen != NULL)
+ *pkthdrlen = *plen;
+ }
+ frags += howmany(mlen, fragsize);
+ if (frags == 0)
+ frags++;
+ seglimit -= frags;
+ KASSERT(seglimit > 0,
+ ("%s: seglimit went too low", __func__));
+ }
+ if (copyhdr)
+ n = m_gethdr(M_NOWAIT, m->m_type);
+ else
+ n = m_get(M_NOWAIT, m->m_type);
+ *np = n;
+ if (n == NULL)
+ goto nospace;
+ if (copyhdr) {
+ if (!m_dup_pkthdr(n, m, M_NOWAIT))
+ goto nospace;
+ if (len == M_COPYALL)
+ n->m_pkthdr.len -= off0;
+ else
+ n->m_pkthdr.len = len;
+ pkthdrlen = &n->m_pkthdr.len;
+ copyhdr = false;
+ }
+ n->m_len = mlen;
+ len_cp += n->m_len;
+ if (m->m_flags & M_EXT) {
+ n->m_data = m->m_data + off;
+ mb_dupcl(n, m);
+ } else
+ bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
+ (u_int)n->m_len);
+
+ if (sb && (sb->sb_sndptr == m) &&
+ ((n->m_len + off) >= m->m_len) && m->m_next) {
+ sb->sb_sndptroff += m->m_len;
+ sb->sb_sndptr = m->m_next;
+ }
+ off = 0;
+ if (len != M_COPYALL) {
+ len -= n->m_len;
+ }
+ m = m->m_next;
+ np = &n->m_next;
+ }
+ return (top);
+nospace:
+ m_freem(top);
+ return (NULL);
+}
+
void
tcp_sndbuf_autoscale(struct tcpcb *tp, struct socket *so, uint32_t sendwin)
{
diff --git a/freebsd/sys/netinet/tcp_reass.c b/freebsd/sys/netinet/tcp_reass.c
index dbb61299..4776a808 100644
--- a/freebsd/sys/netinet/tcp_reass.c
+++ b/freebsd/sys/netinet/tcp_reass.c
@@ -74,15 +74,37 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
+#include <netinet/tcp_log_buf.h>
+#include <netinet/tcp_hpts.h>
#include <netinet6/tcp6_var.h>
#include <netinet/tcpip.h>
#ifdef TCPDEBUG
#include <netinet/tcp_debug.h>
#endif /* TCPDEBUG */
+#define TCP_R_LOG_ADD 1
+#define TCP_R_LOG_LIMIT_REACHED 2
+#define TCP_R_LOG_APPEND 3
+#define TCP_R_LOG_PREPEND 4
+#define TCP_R_LOG_REPLACE 5
+#define TCP_R_LOG_MERGE_INTO 6
+#define TCP_R_LOG_NEW_ENTRY 7
+#define TCP_R_LOG_READ 8
+#define TCP_R_LOG_ZERO 9
+#define TCP_R_LOG_DUMP 10
+#define TCP_R_LOG_TRIM 11
+
+/* For debugging we want counters and BB logging */
+/* #define TCP_REASS_COUNTERS 1 */
+/* #define TCP_REASS_LOGGING 1 */
+
static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0,
"TCP Segment Reassembly Queue");
+static SYSCTL_NODE(_net_inet_tcp_reass, OID_AUTO, stats, CTLFLAG_RW, 0,
+ "TCP Segment Reassembly stats");
+
+
static int tcp_reass_maxseg = 0;
SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN,
&tcp_reass_maxseg, 0,
@@ -93,6 +115,77 @@ SYSCTL_UMA_CUR(_net_inet_tcp_reass, OID_AUTO, cursegments, 0,
&tcp_reass_zone,
"Global number of TCP Segments currently in Reassembly Queue");
+static u_int tcp_reass_maxqueuelen = 100;
+SYSCTL_UINT(_net_inet_tcp_reass, OID_AUTO, maxqueuelen, CTLFLAG_RWTUN,
+ &tcp_reass_maxqueuelen, 0,
+ "Maximum number of TCP Segments per Reassembly Queue");
+
+static int tcp_new_limits = 0;
+SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, new_limit, CTLFLAG_RWTUN,
+ &tcp_new_limits, 0,
+ "Do we use the new limit method we are discussing?");
+
+static u_int tcp_reass_queue_guard = 16;
+SYSCTL_UINT(_net_inet_tcp_reass, OID_AUTO, queueguard, CTLFLAG_RWTUN,
+ &tcp_reass_queue_guard, 16,
+ "Number of TCP Segments in Reassembly Queue where we flip over to guard mode");
+
+#ifdef TCP_REASS_COUNTERS
+
+counter_u64_t reass_entry;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, entry, CTLFLAG_RD,
+ &reass_entry, "A segment entered reassembly ");
+
+counter_u64_t reass_path1;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path1, CTLFLAG_RD,
+ &reass_path1, "Took path 1");
+
+counter_u64_t reass_path2;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path2, CTLFLAG_RD,
+ &reass_path2, "Took path 2");
+
+counter_u64_t reass_path3;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path3, CTLFLAG_RD,
+ &reass_path3, "Took path 3");
+
+counter_u64_t reass_path4;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path4, CTLFLAG_RD,
+ &reass_path4, "Took path 4");
+
+counter_u64_t reass_path5;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path5, CTLFLAG_RD,
+ &reass_path5, "Took path 5");
+
+counter_u64_t reass_path6;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path6, CTLFLAG_RD,
+ &reass_path6, "Took path 6");
+
+counter_u64_t reass_path7;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, path7, CTLFLAG_RD,
+ &reass_path7, "Took path 7");
+
+counter_u64_t reass_fullwalk;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, fullwalk, CTLFLAG_RD,
+ &reass_fullwalk, "Took a full walk ");
+
+counter_u64_t reass_nospace;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, nospace, CTLFLAG_RD,
+ &reass_nospace, "Had no mbuf capacity ");
+
+counter_u64_t merge_fwd;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, merge_fwd, CTLFLAG_RD,
+ &merge_fwd, "Ran merge fwd");
+
+counter_u64_t merge_into;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, merge_into, CTLFLAG_RD,
+ &merge_into, "Ran merge into");
+
+counter_u64_t tcp_zero_input;
+SYSCTL_COUNTER_U64(_net_inet_tcp_reass_stats, OID_AUTO, zero_input, CTLFLAG_RD,
+ &tcp_zero_input, "The reassembly buffer saw a zero len segment etc");
+
+#endif
+
/* Initialize TCP reassembly queue */
static void
tcp_reass_zone_change(void *tag)
@@ -104,6 +197,77 @@ tcp_reass_zone_change(void *tag)
tcp_reass_maxseg);
}
+#ifdef TCP_REASS_LOGGING
+
+static void
+tcp_log_reassm(struct tcpcb *tp, struct tseg_qent *q, struct tseg_qent *p,
+ tcp_seq seq, int len, uint8_t action, int instance)
+{
+ uint32_t cts;
+ struct timeval tv;
+
+ if (tp->t_logstate != TCP_LOG_STATE_OFF) {
+ union tcp_log_stackspecific log;
+
+ memset(&log, 0, sizeof(log));
+ cts = tcp_get_usecs(&tv);
+ log.u_bbr.flex1 = seq;
+ log.u_bbr.cur_del_rate = (uint64_t)q;
+ log.u_bbr.delRate = (uint64_t)p;
+ if (q != NULL) {
+ log.u_bbr.flex2 = q->tqe_start;
+ log.u_bbr.flex3 = q->tqe_len;
+ log.u_bbr.flex4 = q->tqe_mbuf_cnt;
+ log.u_bbr.hptsi_gain = q->tqe_flags;
+ }
+ if (p != NULL) {
+ log.u_bbr.flex5 = p->tqe_start;
+ log.u_bbr.pkts_out = p->tqe_len;
+ log.u_bbr.epoch = p->tqe_mbuf_cnt;
+ log.u_bbr.cwnd_gain = p->tqe_flags;
+ }
+ log.u_bbr.flex6 = tp->t_segqmbuflen;
+ log.u_bbr.flex7 = instance;
+ log.u_bbr.flex8 = action;
+ log.u_bbr.timeStamp = cts;
+ TCP_LOG_EVENTP(tp, NULL,
+ &tp->t_inpcb->inp_socket->so_rcv,
+ &tp->t_inpcb->inp_socket->so_snd,
+ TCP_LOG_REASS, 0,
+ len, &log, false, &tv);
+ }
+}
+
+static void
+tcp_reass_log_dump(struct tcpcb *tp)
+{
+ struct tseg_qent *q;
+
+ if (tp->t_logstate != TCP_LOG_STATE_OFF) {
+ TAILQ_FOREACH(q, &tp->t_segq, tqe_q) {
+ tcp_log_reassm(tp, q, NULL, q->tqe_start, q->tqe_len, TCP_R_LOG_DUMP, 0);
+ }
+ };
+}
+
+static void
+tcp_reass_log_new_in(struct tcpcb *tp, tcp_seq seq, int len, struct mbuf *m,
+ int logval, struct tseg_qent *q)
+{
+ int cnt;
+ struct mbuf *t;
+
+ cnt = 0;
+ t = m;
+ while (t) {
+ cnt += t->m_len;
+ t = t->m_next;
+ }
+ tcp_log_reassm(tp, q, NULL, seq, len, logval, cnt);
+}
+
+#endif
+
void
tcp_reass_global_init(void)
{
@@ -116,8 +280,24 @@ tcp_reass_global_init(void)
/* Set the zone limit and read back the effective value. */
tcp_reass_maxseg = uma_zone_set_max(tcp_reass_zone,
tcp_reass_maxseg);
+#ifdef TCP_REASS_COUNTERS
+ reass_path1 = counter_u64_alloc(M_WAITOK);
+ reass_path2 = counter_u64_alloc(M_WAITOK);
+ reass_path3 = counter_u64_alloc(M_WAITOK);
+ reass_path4 = counter_u64_alloc(M_WAITOK);
+ reass_path5 = counter_u64_alloc(M_WAITOK);
+ reass_path6 = counter_u64_alloc(M_WAITOK);
+ reass_path7 = counter_u64_alloc(M_WAITOK);
+ reass_fullwalk = counter_u64_alloc(M_WAITOK);
+ reass_nospace = counter_u64_alloc(M_WAITOK);
+ reass_entry = counter_u64_alloc(M_WAITOK);
+ merge_fwd = counter_u64_alloc(M_WAITOK);
+ merge_into = counter_u64_alloc(M_WAITOK);
+ tcp_zero_input = counter_u64_alloc(M_WAITOK);
+#endif
EVENTHANDLER_REGISTER(nmbclusters_change,
tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY);
+
}
void
@@ -127,32 +307,237 @@ tcp_reass_flush(struct tcpcb *tp)
INP_WLOCK_ASSERT(tp->t_inpcb);
- while ((qe = LIST_FIRST(&tp->t_segq)) != NULL) {
- LIST_REMOVE(qe, tqe_q);
+ while ((qe = TAILQ_FIRST(&tp->t_segq)) != NULL) {
+ TAILQ_REMOVE(&tp->t_segq, qe, tqe_q);
m_freem(qe->tqe_m);
uma_zfree(tcp_reass_zone, qe);
tp->t_segqlen--;
}
-
+ tp->t_segqmbuflen = 0;
KASSERT((tp->t_segqlen == 0),
("TCP reass queue %p segment count is %d instead of 0 after flush.",
tp, tp->t_segqlen));
}
+static void
+tcp_reass_append(struct tcpcb *tp, struct tseg_qent *last,
+ struct mbuf *m, struct tcphdr *th, int tlen,
+ struct mbuf *mlast, int lenofoh)
+{
+
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, last, NULL, th->th_seq, tlen, TCP_R_LOG_APPEND, 0);
+#endif
+ last->tqe_len += tlen;
+ last->tqe_m->m_pkthdr.len += tlen;
+ /* Preserve the FIN bit if its there */
+ last->tqe_flags |= (th->th_flags & TH_FIN);
+ last->tqe_last->m_next = m;
+ last->tqe_last = mlast;
+ last->tqe_mbuf_cnt += lenofoh;
+ tp->t_rcvoopack++;
+ TCPSTAT_INC(tcps_rcvoopack);
+ TCPSTAT_ADD(tcps_rcvoobyte, tlen);
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_new_in(tp, last->tqe_start, lenofoh, last->tqe_m,
+ TCP_R_LOG_APPEND,
+ last);
+#endif
+}
+
+static void
+tcp_reass_prepend(struct tcpcb *tp, struct tseg_qent *first, struct mbuf *m, struct tcphdr *th,
+ int tlen, struct mbuf *mlast, int lenofoh)
+{
+ int i;
+
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, first, NULL, th->th_seq, tlen, TCP_R_LOG_PREPEND, 0);
+#endif
+ if (SEQ_GT((th->th_seq + tlen), first->tqe_start)) {
+ /* The new data overlaps into the old */
+ i = (th->th_seq + tlen) - first->tqe_start;
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, first, NULL, 0, i, TCP_R_LOG_TRIM, 1);
+#endif
+ m_adj(first->tqe_m, i);
+ first->tqe_len -= i;
+ first->tqe_start += i;
+ }
+ /* Ok now setup our chain to point to the old first */
+ mlast->m_next = first->tqe_m;
+ first->tqe_m = m;
+ first->tqe_len += tlen;
+ first->tqe_start = th->th_seq;
+ first->tqe_m->m_pkthdr.len = first->tqe_len;
+ first->tqe_mbuf_cnt += lenofoh;
+ tp->t_rcvoopack++;
+ TCPSTAT_INC(tcps_rcvoopack);
+ TCPSTAT_ADD(tcps_rcvoobyte, tlen);
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_new_in(tp, first->tqe_start, lenofoh, first->tqe_m,
+ TCP_R_LOG_PREPEND,
+ first);
+#endif
+}
+
+static void
+tcp_reass_replace(struct tcpcb *tp, struct tseg_qent *q, struct mbuf *m,
+ tcp_seq seq, int len, struct mbuf *mlast, int mbufoh, uint8_t flags)
+{
+ /*
+ * Free the data in q, and replace
+ * it with the new segment.
+ */
+ int len_dif;
+
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, q, NULL, seq, len, TCP_R_LOG_REPLACE, 0);
+#endif
+ m_freem(q->tqe_m);
+ KASSERT(tp->t_segqmbuflen >= q->tqe_mbuf_cnt,
+ ("Tp:%p seg queue goes negative", tp));
+ tp->t_segqmbuflen -= q->tqe_mbuf_cnt;
+ q->tqe_mbuf_cnt = mbufoh;
+ q->tqe_m = m;
+ q->tqe_last = mlast;
+ q->tqe_start = seq;
+ if (len > q->tqe_len)
+ len_dif = len - q->tqe_len;
+ else
+ len_dif = 0;
+ tp->t_rcvoopack++;
+ TCPSTAT_INC(tcps_rcvoopack);
+ TCPSTAT_ADD(tcps_rcvoobyte, len_dif);
+ q->tqe_len = len;
+ q->tqe_flags = (flags & TH_FIN);
+ q->tqe_m->m_pkthdr.len = q->tqe_len;
+ tp->t_segqmbuflen += mbufoh;
+
+}
+
+static void
+tcp_reass_merge_into(struct tcpcb *tp, struct tseg_qent *ent,
+ struct tseg_qent *q)
+{
+ /*
+ * Merge q into ent and free q from the list.
+ */
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, q, ent, 0, 0, TCP_R_LOG_MERGE_INTO, 0);
+#endif
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(merge_into, 1);
+#endif
+ ent->tqe_last->m_next = q->tqe_m;
+ ent->tqe_last = q->tqe_last;
+ ent->tqe_len += q->tqe_len;
+ ent->tqe_mbuf_cnt += q->tqe_mbuf_cnt;
+ ent->tqe_m->m_pkthdr.len += q->tqe_len;
+ ent->tqe_flags |= (q->tqe_flags & TH_FIN);
+ TAILQ_REMOVE(&tp->t_segq, q, tqe_q);
+ uma_zfree(tcp_reass_zone, q);
+ tp->t_segqlen--;
+
+}
+
+static void
+tcp_reass_merge_forward(struct tcpcb *tp, struct tseg_qent *ent)
+{
+ struct tseg_qent *q, *qtmp;
+ int i;
+ tcp_seq max;
+ /*
+ * Given an entry merge forward anyplace
+ * that ent overlaps forward.
+ */
+
+ max = ent->tqe_start + ent->tqe_len;
+ q = TAILQ_NEXT(ent, tqe_q);
+ if (q == NULL) {
+ /* Nothing left */
+ return;
+ }
+ TAILQ_FOREACH_FROM_SAFE(q, &tp->t_segq, tqe_q, qtmp) {
+ if (SEQ_GT(q->tqe_start, max)) {
+ /* Beyond q */
+ break;
+ }
+ /* We have some or all that are overlapping */
+ if (SEQ_GEQ(max, (q->tqe_start + q->tqe_len))) {
+ /* It consumes it all */
+ tp->t_segqmbuflen -= q->tqe_mbuf_cnt;
+ m_freem(q->tqe_m);
+ TAILQ_REMOVE(&tp->t_segq, q, tqe_q);
+ uma_zfree(tcp_reass_zone, q);
+ tp->t_segqlen--;
+ continue;
+ }
+ /*
+ * Trim the q entry to dovetail to this one
+ * and then merge q into ent updating max
+ * in the process.
+ */
+ i = max - q->tqe_start;
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, q, NULL, 0, i, TCP_R_LOG_TRIM, 2);
+#endif
+ m_adj(q->tqe_m, i);
+ q->tqe_len -= i;
+ q->tqe_start += i;
+ tcp_reass_merge_into(tp, ent, q);
+ max = ent->tqe_start + ent->tqe_len;
+ }
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(merge_fwd, 1);
+#endif
+}
+
+static int
+tcp_reass_overhead_of_chain(struct mbuf *m, struct mbuf **mlast)
+{
+ int len = MSIZE;
+
+ if (m->m_flags & M_EXT)
+ len += m->m_ext.ext_size;
+ while (m->m_next != NULL) {
+ m = m->m_next;
+ len += MSIZE;
+ if (m->m_flags & M_EXT)
+ len += m->m_ext.ext_size;
+ }
+ *mlast = m;
+ return (len);
+}
+
+
+/*
+ * NOTE!!! the new tcp-reassembly code *must not* use
+ * m_adj() with a negative index. That alters the chain
+ * of mbufs (by possibly chopping trailing mbufs). At
+ * the front of tcp_reass we count the mbuf overhead
+ * and setup the tail pointer. If we use m_adj(m, -5)
+ * we could corrupt the tail pointer. Currently the
+ * code only uses m_adj(m, postive-num). If this
+ * changes appropriate changes to update mlast would
+ * be needed.
+ */
int
-tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
+tcp_reass(struct tcpcb *tp, struct tcphdr *th, tcp_seq *seq_start,
+ int *tlenp, struct mbuf *m)
{
- struct tseg_qent *q;
+ struct tseg_qent *q, *last, *first;
struct tseg_qent *p = NULL;
- struct tseg_qent *nq;
+ struct tseg_qent *nq = NULL;
struct tseg_qent *te = NULL;
+ struct tseg_qent tqs;
+ struct mbuf *mlast = NULL;
+ struct sockbuf *sb;
struct socket *so = tp->t_inpcb->inp_socket;
char *s = NULL;
- int flags;
- struct tseg_qent tqs;
+ int flags, i, lenofoh;
INP_WLOCK_ASSERT(tp->t_inpcb);
-
/*
* XXX: tcp_reass() is rather inefficient with its data structures
* and should be rewritten (see NetBSD for optimizations).
@@ -164,149 +549,475 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
*/
if (th == NULL)
goto present;
-
+ KASSERT(SEQ_GEQ(th->th_seq, tp->rcv_nxt),
+ ("Attempt to add old entry to reassembly queue (th=%p, tp=%p)",
+ th, tp));
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_new_in(tp, th->th_seq, *tlenp, m, TCP_R_LOG_ADD, NULL);
+#endif
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_entry, 1);
+#endif
/*
- * Limit the number of segments that can be queued to reduce the
- * potential for mbuf exhaustion. For best performance, we want to be
- * able to queue a full window's worth of segments. The size of the
- * socket receive buffer determines our advertised window and grows
- * automatically when socket buffer autotuning is enabled. Use it as the
- * basis for our queue limit.
- * Always let the missing segment through which caused this queue.
- * NB: Access to the socket buffer is left intentionally unlocked as we
- * can tolerate stale information here.
- *
- * XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat
- * should work but causes packets to be dropped when they shouldn't.
- * Investigate why and re-evaluate the below limit after the behaviour
- * is understood.
+ * Check for zero length data.
+ */
+ if ((*tlenp == 0) && ((th->th_flags & TH_FIN) == 0)) {
+ /*
+ * A zero length segment does no
+ * one any good. We could check
+ * the rcv_nxt <-> rcv_wnd but thats
+ * already done for us by the caller.
+ */
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(tcp_zero_input, 1);
+#endif
+ m_freem(m);
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_dump(tp);
+#endif
+ return (0);
+ }
+ /*
+ * Will it fit?
*/
- if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
- tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) {
+ lenofoh = tcp_reass_overhead_of_chain(m, &mlast);
+ sb = &tp->t_inpcb->inp_socket->so_rcv;
+ if ((sb->sb_mbcnt + tp->t_segqmbuflen + lenofoh) > sb->sb_mbmax) {
+ /* No room */
TCPSTAT_INC(tcps_rcvreassfull);
- *tlenp = 0;
- if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
- log(LOG_DEBUG, "%s; %s: queue limit reached, "
- "segment dropped\n", s, __func__);
- free(s, M_TCPLOG);
- }
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_nospace, 1);
+#endif
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, NULL, NULL, th->th_seq, lenofoh, TCP_R_LOG_LIMIT_REACHED, 0);
+#endif
m_freem(m);
+ *tlenp = 0;
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_dump(tp);
+#endif
return (0);
}
-
/*
- * Allocate a new queue entry. If we can't, or hit the zone limit
- * just drop the pkt.
- *
- * Use a temporary structure on the stack for the missing segment
- * when the zone is exhausted. Otherwise we may get stuck.
+ * First lets deal with two common cases, the
+ * segment appends to the back of our collected
+ * segments. Or the segment is the next in line.
*/
- te = uma_zalloc(tcp_reass_zone, M_NOWAIT);
- if (te == NULL) {
- if (th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) {
- TCPSTAT_INC(tcps_rcvmemdrop);
- m_freem(m);
+ last = TAILQ_LAST_FAST(&tp->t_segq, tseg_qent, tqe_q);
+ if (last != NULL) {
+ if ((th->th_flags & TH_FIN) &&
+ SEQ_LT((th->th_seq + *tlenp), (last->tqe_start + last->tqe_len))) {
+ /*
+ * Someone is trying to game us, dump
+ * the segment.
+ */
*tlenp = 0;
- if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
- NULL))) {
- log(LOG_DEBUG, "%s; %s: global zone limit "
- "reached, segment dropped\n", s, __func__);
- free(s, M_TCPLOG);
+ m_freem(m);
+ return (0);
+ }
+ if ((SEQ_GEQ(th->th_seq, last->tqe_start)) &&
+ (SEQ_GEQ((last->tqe_start + last->tqe_len), th->th_seq))) {
+ /* Common case, trailing segment is added */
+ /**
+ * +--last
+ * v
+ * reassembly buffer |---| |---| |---|
+ * new segment |---|
+ */
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path1, 1);
+#endif
+ if (SEQ_GT((last->tqe_start + last->tqe_len), th->th_seq)) {
+ i = (last->tqe_start + last->tqe_len) - th->th_seq;
+ if (i < *tlenp) {
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, last, NULL, 0, i, TCP_R_LOG_TRIM, 3);
+ th->th_seq += i;
+#endif
+ m_adj(m, i);
+ *tlenp -= i;
+ } else {
+ /* Complete overlap */
+ TCPSTAT_INC(tcps_rcvduppack);
+ TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp);
+ m_freem(m);
+ *tlenp = last->tqe_len;
+ *seq_start = last->tqe_start;
+ return (0);
+ }
+ }
+ if (last->tqe_flags & TH_FIN) {
+ /*
+ * We have data after the FIN on the last?
+ */
+ *tlenp = 0;
+ m_freem(m);
+ return(0);
}
+ tcp_reass_append(tp, last, m, th, *tlenp, mlast, lenofoh);
+ tp->t_segqmbuflen += lenofoh;
+ *seq_start = last->tqe_start;
+ *tlenp = last->tqe_len;
return (0);
- } else {
- bzero(&tqs, sizeof(struct tseg_qent));
- te = &tqs;
- if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
- NULL))) {
- log(LOG_DEBUG,
- "%s; %s: global zone limit reached, using "
- "stack for missing segment\n", s, __func__);
- free(s, M_TCPLOG);
+ } else if (SEQ_GT(th->th_seq, (last->tqe_start + last->tqe_len))) {
+ /*
+ * Second common case, we missed
+ * another one and have something more
+ * for the end.
+ */
+ /**
+ * +--last
+ * v
+ * reassembly buffer |---| |---| |---|
+ * new segment |---|
+ */
+ if (last->tqe_flags & TH_FIN) {
+ /*
+ * We have data after the FIN on the last?
+ */
+ *tlenp = 0;
+ m_freem(m);
+ return(0);
}
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path2, 1);
+#endif
+ p = last;
+ goto new_entry;
}
+ } else {
+ /* First segment (it's NULL). */
+ goto new_entry;
}
- tp->t_segqlen++;
+ first = TAILQ_FIRST(&tp->t_segq);
+ if (SEQ_LT(th->th_seq, first->tqe_start) &&
+ SEQ_GEQ((th->th_seq + *tlenp),first->tqe_start) &&
+ SEQ_LT((th->th_seq + *tlenp), (first->tqe_start + first->tqe_len))) {
+ /*
+ * The head of the queue is prepended by this and
+ * it may be the one I want most.
+ */
+ /**
+ * first-------+
+ * v
+ * rea: |---| |---| |---|
+ * new: |---|
+ * Note the case we do not deal with here is:
+ * rea= |---| |---| |---|
+ * new= |----|
+ * Due to the fact that it could be
+ * new |--------------------|
+ * And we might need to merge forward.
+ */
+#ifdef INVARIANTS
+ struct mbuf *firstmbuf;
+#endif
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path3, 1);
+#endif
+ if (SEQ_LT(th->th_seq, tp->rcv_nxt)) {
+ /*
+ * The resend was even before
+ * what we have. We need to trim it.
+ * Note TSNH (it should be trimmed
+ * before the call to tcp_reass()).
+ */
+#ifdef INVARIANTS
+ panic("th->th_seq:%u rcv_nxt:%u tp:%p not pre-trimmed",
+ th->th_seq, tp->rcv_nxt, tp);
+#else
+ i = tp->rcv_nxt - th->th_seq;
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, first, NULL, 0, i, TCP_R_LOG_TRIM, 4);
+#endif
+ m_adj(m, i);
+ th->th_seq += i;
+ *tlenp -= i;
+#endif
+ }
+#ifdef INVARIANTS
+ firstmbuf = first->tqe_m;
+#endif
+ tcp_reass_prepend(tp, first, m, th, *tlenp, mlast, lenofoh);
+#ifdef INVARIANTS
+ if (firstmbuf == first->tqe_m) {
+ panic("First stayed same m:%p foobar:%p first->tqe_m:%p tp:%p first:%p",
+ m, firstmbuf, first->tqe_m, tp, first);
+ } else if (first->tqe_m != m) {
+ panic("First did not change to m:%p foobar:%p first->tqe_m:%p tp:%p first:%p",
+ m, firstmbuf, first->tqe_m, tp, first);
+ }
+#endif
+ tp->t_segqmbuflen += lenofoh;
+ *seq_start = first->tqe_start;
+ *tlenp = first->tqe_len;
+ goto present;
+ } else if (SEQ_LT((th->th_seq + *tlenp), first->tqe_start)) {
+ /* New segment is before our earliest segment. */
+ /**
+ * first---->+
+ * v
+ * rea= |---| ....
+ * new" |---|
+ *
+ */
+ goto new_entry;
+ }
/*
* Find a segment which begins after this one does.
*/
- LIST_FOREACH(q, &tp->t_segq, tqe_q) {
- if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_fullwalk, 1);
+#endif
+ TAILQ_FOREACH(q, &tp->t_segq, tqe_q) {
+ if (SEQ_GT(q->tqe_start, th->th_seq))
break;
- p = q;
}
-
- /*
- * If there is a preceding segment, it may provide some of
- * our data already. If so, drop the data from the incoming
- * segment. If it provides all of our data, drop us.
+ p = TAILQ_PREV(q, tsegqe_head, tqe_q);
+ /**
+ * Now is this fit just in-between only?
+ * i.e.:
+ * p---+ +----q
+ * v v
+ * res= |--| |--| |--|
+ * nee |-|
+ */
+ if (SEQ_LT((th->th_seq + *tlenp), q->tqe_start) &&
+ ((p == NULL) || (SEQ_GT(th->th_seq, (p->tqe_start + p->tqe_len))))) {
+ /* Yep no overlap */
+ goto new_entry;
+ }
+ /**
+ * If we reach here we have some (possibly all) overlap
+ * such as:
+ * res= |--| |--| |--|
+ * new= |----|
+ * or new= |-----------------|
+ * or new= |--------|
+ * or new= |---|
+ * or new= |-----------|
*/
- if (p != NULL) {
- int i;
+ if ((p != NULL) &&
+ (SEQ_LEQ(th->th_seq, (p->tqe_start + p->tqe_len)))) {
/* conversion to int (in i) handles seq wraparound */
- i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
- if (i > 0) {
+
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path4, 1);
+#endif
+ i = p->tqe_start + p->tqe_len - th->th_seq;
+ if (i >= 0) {
if (i >= *tlenp) {
+ /**
+ * prev seg---->+
+ * v
+ * reassembly buffer |---|
+ * new segment |-|
+ */
TCPSTAT_INC(tcps_rcvduppack);
TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp);
+ *tlenp = p->tqe_len;
+ *seq_start = p->tqe_start;
m_freem(m);
- if (te != &tqs)
- uma_zfree(tcp_reass_zone, te);
- tp->t_segqlen--;
/*
* Try to present any queued data
* at the left window edge to the user.
* This is needed after the 3-WHS
- * completes.
+ * completes. Note this probably
+ * will not work and we will return.
*/
- goto present; /* ??? */
+ return (0);
}
- m_adj(m, i);
- *tlenp -= i;
- th->th_seq += i;
+ if (i > 0) {
+ /**
+ * prev seg---->+
+ * v
+ * reassembly buffer |---|
+ * new segment |-----|
+ */
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path5, 1);
+#endif
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, p, NULL, 0, i, TCP_R_LOG_TRIM, 5);
+#endif
+ m_adj(m, i);
+ *tlenp -= i;
+ th->th_seq += i;
+ }
+ }
+ if (th->th_seq == (p->tqe_start + p->tqe_len)) {
+ /*
+ * If dovetails in with this one
+ * append it.
+ */
+ /**
+ * prev seg---->+
+ * v
+ * reassembly buffer |--| |---|
+ * new segment |--|
+ * (note: it was trimmed above if it overlapped)
+ */
+ tcp_reass_append(tp, p, m, th, *tlenp, mlast, lenofoh);
+ tp->t_segqmbuflen += lenofoh;
+ } else {
+#ifdef INVARIANTS
+ panic("Impossible cut th_seq:%u p->seq:%u(%d) p:%p tp:%p",
+ th->th_seq, p->tqe_start, p->tqe_len,
+ p, tp);
+#endif
+ *tlenp = 0;
+ m_freem(m);
+ return (0);
+ }
+ q = p;
+ } else {
+ /*
+ * The new data runs over the
+ * top of previously sack'd data (in q).
+ * It may be partially overlapping, or
+ * it may overlap the entire segment.
+ */
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path6, 1);
+#endif
+ if (SEQ_GEQ((th->th_seq + *tlenp), (q->tqe_start + q->tqe_len))) {
+ /* It consumes it all */
+ /**
+ * next seg---->+
+ * v
+ * reassembly buffer |--| |---|
+ * new segment |----------|
+ */
+#ifdef TCP_REASS_COUNTERS
+ counter_u64_add(reass_path7, 1);
+#endif
+ tcp_reass_replace(tp, q, m, th->th_seq, *tlenp, mlast, lenofoh, th->th_flags);
+ } else {
+ /*
+ * We just need to prepend the data
+ * to this. It does not overrun
+ * the end.
+ */
+ /**
+ * next seg---->+
+ * v
+ * reassembly buffer |--| |---|
+ * new segment |----------|
+ */
+ tcp_reass_prepend(tp, q, m, th, *tlenp, mlast, lenofoh);
+ tp->t_segqmbuflen += lenofoh;
}
}
- tp->t_rcvoopack++;
- TCPSTAT_INC(tcps_rcvoopack);
- TCPSTAT_ADD(tcps_rcvoobyte, *tlenp);
+ /* Now does it go further than that? */
+ tcp_reass_merge_forward(tp, q);
+ *seq_start = q->tqe_start;
+ *tlenp = q->tqe_len;
+ goto present;
- /*
- * While we overlap succeeding segments trim them or,
- * if they are completely covered, dequeue them.
+ /*
+ * When we reach here we can't combine it
+ * with any existing segment.
+ *
+ * Limit the number of segments that can be queued to reduce the
+ * potential for mbuf exhaustion. For best performance, we want to be
+ * able to queue a full window's worth of segments. The size of the
+ * socket receive buffer determines our advertised window and grows
+ * automatically when socket buffer autotuning is enabled. Use it as the
+ * basis for our queue limit.
+ *
+ * However, allow the user to specify a ceiling for the number of
+ * segments in each queue.
+ *
+ * Always let the missing segment through which caused this queue.
+ * NB: Access to the socket buffer is left intentionally unlocked as we
+ * can tolerate stale information here.
+ *
+ * XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat
+ * should work but causes packets to be dropped when they shouldn't.
+ * Investigate why and re-evaluate the below limit after the behaviour
+ * is understood.
*/
- while (q) {
- int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
- if (i <= 0)
- break;
- if (i < q->tqe_len) {
- q->tqe_th->th_seq += i;
- q->tqe_len -= i;
- m_adj(q->tqe_m, i);
- break;
+new_entry:
+ if (tcp_new_limits) {
+ if ((tp->t_segqlen > tcp_reass_queue_guard) &&
+ (*tlenp < MSIZE)) {
+ /*
+ * This is really a lie, we are not full but
+ * are getting a segment that is above
+ * guard threshold. If it is and its below
+ * a mbuf size (256) we drop it if it
+ * can't fill in some place.
+ */
+ TCPSTAT_INC(tcps_rcvreassfull);
+ *tlenp = 0;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: queue limit reached, "
+ "segment dropped\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ m_freem(m);
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_dump(tp);
+#endif
+ return (0);
}
+ } else {
- nq = LIST_NEXT(q, tqe_q);
- LIST_REMOVE(q, tqe_q);
- m_freem(q->tqe_m);
- uma_zfree(tcp_reass_zone, q);
- tp->t_segqlen--;
- q = nq;
+ if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
+ tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1,
+ tcp_reass_maxqueuelen)) {
+ TCPSTAT_INC(tcps_rcvreassfull);
+ *tlenp = 0;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: queue limit reached, "
+ "segment dropped\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ m_freem(m);
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_dump(tp);
+#endif
+ return (0);
+ }
}
-
+ /*
+ * Allocate a new queue entry. If we can't, or hit the zone limit
+ * just drop the pkt.
+ */
+ te = uma_zalloc(tcp_reass_zone, M_NOWAIT);
+ if (te == NULL) {
+ TCPSTAT_INC(tcps_rcvmemdrop);
+ m_freem(m);
+ *tlenp = 0;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+ NULL))) {
+ log(LOG_DEBUG, "%s; %s: global zone limit "
+ "reached, segment dropped\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ return (0);
+ }
+ tp->t_segqlen++;
+ tp->t_rcvoopack++;
+ TCPSTAT_INC(tcps_rcvoopack);
+ TCPSTAT_ADD(tcps_rcvoobyte, *tlenp);
/* Insert the new segment queue entry into place. */
te->tqe_m = m;
- te->tqe_th = th;
+ te->tqe_flags = th->th_flags;
te->tqe_len = *tlenp;
-
+ te->tqe_start = th->th_seq;
+ te->tqe_last = mlast;
+ te->tqe_mbuf_cnt = lenofoh;
+ tp->t_segqmbuflen += te->tqe_mbuf_cnt;
if (p == NULL) {
- LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
+ TAILQ_INSERT_HEAD(&tp->t_segq, te, tqe_q);
} else {
- KASSERT(te != &tqs, ("%s: temporary stack based entry not "
- "first element in queue", __func__));
- LIST_INSERT_AFTER(p, te, tqe_q);
+ TAILQ_INSERT_AFTER(&tp->t_segq, p, te, tqe_q);
}
-
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_new_in(tp, th->th_seq, *tlenp, m, TCP_R_LOG_NEW_ENTRY, te);
+#endif
present:
/*
* Present data to user, advancing rcv_nxt through
@@ -314,24 +1025,56 @@ present:
*/
if (!TCPS_HAVEESTABLISHED(tp->t_state))
return (0);
- q = LIST_FIRST(&tp->t_segq);
- if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
+ q = TAILQ_FIRST(&tp->t_segq);
+ KASSERT(q == NULL || SEQ_GEQ(q->tqe_start, tp->rcv_nxt),
+ ("Reassembly queue for %p has stale entry at head", tp));
+ if (!q || q->tqe_start != tp->rcv_nxt) {
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_dump(tp);
+#endif
return (0);
+ }
SOCKBUF_LOCK(&so->so_rcv);
do {
tp->rcv_nxt += q->tqe_len;
- flags = q->tqe_th->th_flags & TH_FIN;
- nq = LIST_NEXT(q, tqe_q);
- LIST_REMOVE(q, tqe_q);
- if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
+ flags = q->tqe_flags & TH_FIN;
+ nq = TAILQ_NEXT(q, tqe_q);
+ TAILQ_REMOVE(&tp->t_segq, q, tqe_q);
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
m_freem(q->tqe_m);
- else
+ } else {
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_new_in(tp, q->tqe_start, q->tqe_len, q->tqe_m, TCP_R_LOG_READ, q);
+ tcp_log_reassm(tp, q, NULL, th->th_seq, *tlenp, TCP_R_LOG_READ, 1);
+#endif
sbappendstream_locked(&so->so_rcv, q->tqe_m, 0);
- if (q != &tqs)
+ }
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, q, NULL, th->th_seq, *tlenp, TCP_R_LOG_READ, 2);
+#endif
+ KASSERT(tp->t_segqmbuflen >= q->tqe_mbuf_cnt,
+ ("tp:%p seg queue goes negative", tp));
+ tp->t_segqmbuflen -= q->tqe_mbuf_cnt;
+ if (q != &tqs)
uma_zfree(tcp_reass_zone, q);
tp->t_segqlen--;
q = nq;
- } while (q && q->tqe_th->th_seq == tp->rcv_nxt);
+ } while (q && q->tqe_start == tp->rcv_nxt);
+ if (TAILQ_EMPTY(&tp->t_segq) &&
+ (tp->t_segqmbuflen != 0)) {
+#ifdef INVARIANTS
+ panic("tp:%p segq:%p len:%d queue empty",
+ tp, &tp->t_segq, tp->t_segqmbuflen);
+#else
+#ifdef TCP_REASS_LOGGING
+ tcp_log_reassm(tp, NULL, NULL, th->th_seq, *tlenp, TCP_R_LOG_ZERO, 0);
+#endif
+ tp->t_segqmbuflen = 0;
+#endif
+ }
+#ifdef TCP_REASS_LOGGING
+ tcp_reass_log_dump(tp);
+#endif
sorwakeup_locked(so);
return (flags);
}
diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c
index 787213b0..4852ffaf 100644
--- a/freebsd/sys/netinet/tcp_subr.c
+++ b/freebsd/sys/netinet/tcp_subr.c
@@ -216,13 +216,13 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0,
SYSCTL_UINT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_VNET | CTLFLAG_RD,
&VNET_NAME(tcbinfo.ipi_count), 0, "Number of active PCBs");
-static VNET_DEFINE(int, icmp_may_rst) = 1;
+VNET_DEFINE_STATIC(int, icmp_may_rst) = 1;
#define V_icmp_may_rst VNET(icmp_may_rst)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmp_may_rst), 0,
"Certain ICMP unreachable messages may abort connections in SYN_SENT");
-static VNET_DEFINE(int, tcp_isn_reseed_interval) = 0;
+VNET_DEFINE_STATIC(int, tcp_isn_reseed_interval) = 0;
#define V_tcp_isn_reseed_interval VNET(tcp_isn_reseed_interval)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_isn_reseed_interval), 0,
@@ -239,6 +239,10 @@ VNET_DEFINE(uma_zone_t, sack_hole_zone);
VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]);
#endif
+#define TS_OFFSET_SECRET_LENGTH 32
+VNET_DEFINE_STATIC(u_char, ts_offset_secret[TS_OFFSET_SECRET_LENGTH]);
+#define V_ts_offset_secret VNET(ts_offset_secret)
+
static int tcp_default_fb_init(struct tcpcb *tp);
static void tcp_default_fb_fini(struct tcpcb *tp, int tcb_is_purged);
static int tcp_default_handoff_ok(struct tcpcb *tp);
@@ -701,7 +705,7 @@ struct tcpcb_mem {
#endif
};
-static VNET_DEFINE(uma_zone_t, tcpcb_zone);
+VNET_DEFINE_STATIC(uma_zone_t, tcpcb_zone);
#define V_tcpcb_zone VNET(tcpcb_zone)
MALLOC_DEFINE(M_TCPLOG, "tcplog", "TCP address and flags print buffers");
@@ -949,11 +953,10 @@ deregister_tcp_functions(struct tcp_function_block *blk, bool quiesce,
rw_wunlock(&tcp_function_lock);
VNET_LIST_RLOCK();
- /* XXX handle */
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
INP_INFO_WLOCK(&V_tcbinfo);
- LIST_FOREACH(inp, V_tcbinfo.ipi_listhead, inp_list) {
+ CK_LIST_FOREACH(inp, V_tcbinfo.ipi_listhead, inp_list) {
INP_WLOCK(inp);
if (inp->inp_flags & INP_TIMEWAIT) {
INP_WUNLOCK(inp);
@@ -1099,6 +1102,7 @@ tcp_init(void)
/* Initialize the TCP logging data. */
tcp_log_init();
#endif
+ arc4rand(&V_ts_offset_secret, sizeof(V_ts_offset_secret), 0);
if (tcp_soreceive_stream) {
#ifdef INET
@@ -1629,7 +1633,7 @@ tcp_newtcpcb(struct inpcb *inp)
tp->t_vnet = inp->inp_vnet;
#endif
tp->t_timers = &tm->tt;
- /* LIST_INIT(&tp->t_segq); */ /* XXX covered by M_ZERO */
+ TAILQ_INIT(&tp->t_segq);
tp->t_maxseg =
#ifdef INET6
isipv6 ? V_tcp_v6mssdflt :
@@ -1723,7 +1727,7 @@ tcp_ccalgounload(struct cc_algo *unload_algo)
* therefore don't enter the loop below until the connection
* list has stabilised.
*/
- LIST_FOREACH(inp, &V_tcb, inp_list) {
+ CK_LIST_FOREACH(inp, &V_tcb, inp_list) {
INP_WLOCK(inp);
/* Important to skip tcptw structs. */
if (!(inp->inp_flags & INP_TIMEWAIT) &&
@@ -1737,11 +1741,18 @@ tcp_ccalgounload(struct cc_algo *unload_algo)
*/
if (CC_ALGO(tp) == unload_algo) {
tmpalgo = CC_ALGO(tp);
- /* NewReno does not require any init. */
- CC_ALGO(tp) = &newreno_cc_algo;
- /* XXX defer to epoch_call */
if (tmpalgo->cb_destroy != NULL)
tmpalgo->cb_destroy(tp->ccv);
+ CC_DATA(tp) = NULL;
+ /*
+ * NewReno may allocate memory on
+ * demand for certain stateful
+ * configuration as needed, but is
+ * coded to never fail on memory
+ * allocation failure so it is a safe
+ * fallback.
+ */
+ CC_ALGO(tp) = &newreno_cc_algo;
}
}
INP_WUNLOCK(inp);
@@ -1893,6 +1904,7 @@ tcp_discardcb(struct tcpcb *tp)
/* Allow the CC algorithm to clean up after itself. */
if (CC_ALGO(tp)->cb_destroy != NULL)
CC_ALGO(tp)->cb_destroy(tp->ccv);
+ CC_DATA(tp) = NULL;
#ifdef TCP_HHOOK
khelp_destroy_osd(tp->osd);
@@ -1922,10 +1934,11 @@ tcp_timer_discard(void *ptp)
{
struct inpcb *inp;
struct tcpcb *tp;
+ struct epoch_tracker et;
tp = (struct tcpcb *)ptp;
CURVNET_SET(tp->t_vnet);
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
inp = tp->t_inpcb;
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL",
__func__, tp));
@@ -1945,13 +1958,13 @@ tcp_timer_discard(void *ptp)
tp->t_inpcb = NULL;
uma_zfree(V_tcpcb_zone, tp);
if (in_pcbrele_wlocked(inp)) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
CURVNET_RESTORE();
return;
}
}
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
CURVNET_RESTORE();
}
@@ -2024,10 +2037,12 @@ tcp_drain(void)
* useful.
*/
INP_INFO_WLOCK(&V_tcbinfo);
- LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
- if (inpb->inp_flags & INP_TIMEWAIT)
- continue;
+ CK_LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
INP_WLOCK(inpb);
+ if (inpb->inp_flags & INP_TIMEWAIT) {
+ INP_WUNLOCK(inpb);
+ continue;
+ }
if ((tcpb = intotcpcb(inpb)) != NULL) {
tcp_reass_flush(tcpb);
tcp_clean_sackreport(tcpb);
@@ -2110,10 +2125,10 @@ static int
tcp_pcblist(SYSCTL_HANDLER_ARGS)
{
int error, i, m, n, pcb_count;
- struct in_pcblist *il;
struct inpcb *inp, **inp_list;
inp_gen_t gencnt;
struct xinpgen xig;
+ struct epoch_tracker et;
/*
* The process of preparing the TCB list is too time-consuming and
@@ -2157,12 +2172,11 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
- il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
- inp_list = il->il_inp_list;
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
INP_INFO_WLOCK(&V_tcbinfo);
- for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0;
- inp != NULL && i < n; inp = LIST_NEXT(inp, inp_list)) {
+ for (inp = CK_LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0;
+ inp != NULL && i < n; inp = CK_LIST_NEXT(inp, inp_list)) {
INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt) {
/*
@@ -2201,10 +2215,14 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
} else
INP_RUNLOCK(inp);
}
-
- il->il_count = n;
- il->il_pcbinfo = &V_tcbinfo;
- epoch_call(net_epoch_preempt, &il->il_epoch_ctx, in_pcblist_rele_rlocked);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
+ }
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
if (!error) {
/*
@@ -2221,6 +2239,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
INP_LIST_RUNLOCK(&V_tcbinfo);
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
+ free(inp_list, M_TEMP);
return (error);
}
@@ -2342,6 +2361,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
struct icmp *icp;
struct in_conninfo inc;
+ struct epoch_tracker et;
tcp_seq icmp_tcp_seq;
int mtu;
@@ -2373,7 +2393,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip));
th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
inp = in_pcblookup(&V_tcbinfo, faddr, th->th_dport, ip->ip_src,
th->th_sport, INPLOOKUP_WLOCKPCB, NULL);
if (inp != NULL && PRC_IS_REDIRECT(cmd)) {
@@ -2438,7 +2458,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
out:
if (inp != NULL)
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
}
#endif /* INET */
@@ -2456,6 +2476,7 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
struct in_conninfo inc;
+ struct epoch_tracker et;
struct tcp_ports {
uint16_t th_sport;
uint16_t th_dport;
@@ -2517,7 +2538,7 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
}
bzero(&t_ports, sizeof(struct tcp_ports));
m_copydata(m, off, sizeof(struct tcp_ports), (caddr_t)&t_ports);
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_dst, t_ports.th_dport,
&ip6->ip6_src, t_ports.th_sport, INPLOOKUP_WLOCKPCB, NULL);
if (inp != NULL && PRC_IS_REDIRECT(cmd)) {
@@ -2589,10 +2610,45 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
out:
if (inp != NULL)
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
}
#endif /* INET6 */
+static uint32_t
+tcp_keyed_hash(struct in_conninfo *inc, u_char *key, u_int len)
+{
+ MD5_CTX ctx;
+ uint32_t hash[4];
+
+ MD5Init(&ctx);
+ MD5Update(&ctx, &inc->inc_fport, sizeof(uint16_t));
+ MD5Update(&ctx, &inc->inc_lport, sizeof(uint16_t));
+ switch (inc->inc_flags & INC_ISIPV6) {
+#ifdef INET
+ case 0:
+ MD5Update(&ctx, &inc->inc_faddr, sizeof(struct in_addr));
+ MD5Update(&ctx, &inc->inc_laddr, sizeof(struct in_addr));
+ break;
+#endif
+#ifdef INET6
+ case INC_ISIPV6:
+ MD5Update(&ctx, &inc->inc6_faddr, sizeof(struct in6_addr));
+ MD5Update(&ctx, &inc->inc6_laddr, sizeof(struct in6_addr));
+ break;
+#endif
+ }
+ MD5Update(&ctx, key, len);
+ MD5Final((unsigned char *)hash, &ctx);
+
+ return (hash[0]);
+}
+
+uint32_t
+tcp_new_ts_offset(struct in_conninfo *inc)
+{
+ return (tcp_keyed_hash(inc, V_ts_offset_secret,
+ sizeof(V_ts_offset_secret)));
+}
/*
* Following is where TCP initial sequence number generation occurs.
@@ -2634,19 +2690,20 @@ out:
* as reseeding should not be necessary.
*
* Locking of the global variables isn_secret, isn_last_reseed, isn_offset,
- * isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock. In
+ * isn_offset_old, and isn_ctx is performed using the ISN lock. In
* general, this means holding an exclusive (write) lock.
*/
#define ISN_BYTES_PER_SECOND 1048576
#define ISN_STATIC_INCREMENT 4096
#define ISN_RANDOM_INCREMENT (4096 - 1)
+#define ISN_SECRET_LENGTH 32
-static VNET_DEFINE(u_char, isn_secret[32]);
-static VNET_DEFINE(int, isn_last);
-static VNET_DEFINE(int, isn_last_reseed);
-static VNET_DEFINE(u_int32_t, isn_offset);
-static VNET_DEFINE(u_int32_t, isn_offset_old);
+VNET_DEFINE_STATIC(u_char, isn_secret[ISN_SECRET_LENGTH]);
+VNET_DEFINE_STATIC(int, isn_last);
+VNET_DEFINE_STATIC(int, isn_last_reseed);
+VNET_DEFINE_STATIC(u_int32_t, isn_offset);
+VNET_DEFINE_STATIC(u_int32_t, isn_offset_old);
#define V_isn_secret VNET(isn_secret)
#define V_isn_last VNET(isn_last)
@@ -2655,45 +2712,23 @@ static VNET_DEFINE(u_int32_t, isn_offset_old);
#define V_isn_offset_old VNET(isn_offset_old)
tcp_seq
-tcp_new_isn(struct tcpcb *tp)
+tcp_new_isn(struct in_conninfo *inc)
{
- MD5_CTX isn_ctx;
- u_int32_t md5_buffer[4];
tcp_seq new_isn;
u_int32_t projected_offset;
- INP_WLOCK_ASSERT(tp->t_inpcb);
-
ISN_LOCK();
/* Seed if this is the first use, reseed if requested. */
if ((V_isn_last_reseed == 0) || ((V_tcp_isn_reseed_interval > 0) &&
(((u_int)V_isn_last_reseed + (u_int)V_tcp_isn_reseed_interval*hz)
< (u_int)ticks))) {
- read_random(&V_isn_secret, sizeof(V_isn_secret));
+ arc4rand(&V_isn_secret, sizeof(V_isn_secret), 0);
V_isn_last_reseed = ticks;
}
/* Compute the md5 hash and return the ISN. */
- MD5Init(&isn_ctx);
- MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
- MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
-#ifdef INET6
- if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) {
- MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
- sizeof(struct in6_addr));
- MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
- sizeof(struct in6_addr));
- } else
-#endif
- {
- MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
- sizeof(struct in_addr));
- MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
- sizeof(struct in_addr));
- }
- MD5Update(&isn_ctx, (u_char *) &V_isn_secret, sizeof(V_isn_secret));
- MD5Final((u_char *) &md5_buffer, &isn_ctx);
- new_isn = (tcp_seq) md5_buffer[0];
+ new_isn = (tcp_seq)tcp_keyed_hash(inc, V_isn_secret,
+ sizeof(V_isn_secret));
V_isn_offset += ISN_STATIC_INCREMENT +
(arc4random() & ISN_RANDOM_INCREMENT);
if (ticks != V_isn_last) {
@@ -2840,6 +2875,9 @@ tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap)
KASSERT(inc != NULL, ("tcp_maxmtu6 with NULL in_conninfo pointer"));
+ if (inc->inc_flags & INC_IPV6MINMTU)
+ return (IPV6_MMTU);
+
if (!IN6_IS_ADDR_UNSPECIFIED(&inc->inc6_faddr)) {
in6_splitscope(&inc->inc6_faddr, &dst6, &scopeid);
if (fib6_lookup_nh_ext(inc->inc_fibnum, &dst6, scopeid, 0,
@@ -2928,6 +2966,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
struct tcpcb *tp;
struct tcptw *tw;
struct sockaddr_in *fin, *lin;
+ struct epoch_tracker et;
#ifdef INET6
struct sockaddr_in6 *fin6, *lin6;
#endif
@@ -2987,7 +3026,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
default:
return (EINVAL);
}
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
switch (addrs[0].ss_family) {
#ifdef INET6
case AF_INET6:
@@ -3026,7 +3065,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
INP_WUNLOCK(inp);
} else
error = ESRCH;
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (error);
}
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index e163aa54..6fdd859d 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <netinet/in_kdtrace.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_var.h>
@@ -104,19 +105,19 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static VNET_DEFINE(int, tcp_syncookies) = 1;
+VNET_DEFINE_STATIC(int, tcp_syncookies) = 1;
#define V_tcp_syncookies VNET(tcp_syncookies)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_syncookies), 0,
"Use TCP SYN cookies if the syncache overflows");
-static VNET_DEFINE(int, tcp_syncookiesonly) = 0;
+VNET_DEFINE_STATIC(int, tcp_syncookiesonly) = 0;
#define V_tcp_syncookiesonly VNET(tcp_syncookiesonly)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_syncookiesonly), 0,
"Use only TCP SYN cookies");
-static VNET_DEFINE(int, functions_inherit_listen_socket_stack) = 1;
+VNET_DEFINE_STATIC(int, functions_inherit_listen_socket_stack) = 1;
#define V_functions_inherit_listen_socket_stack \
VNET(functions_inherit_listen_socket_stack)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, functions_inherit_listen_socket_stack,
@@ -164,7 +165,7 @@ static int syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch,
#define TCP_SYNCACHE_HASHSIZE 512
#define TCP_SYNCACHE_BUCKETLIMIT 30
-static VNET_DEFINE(struct tcp_syncache, tcp_syncache);
+VNET_DEFINE_STATIC(struct tcp_syncache, tcp_syncache);
#define V_tcp_syncache VNET(tcp_syncache)
static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, syncache, CTLFLAG_RW, 0,
@@ -185,8 +186,27 @@ SYSCTL_UINT(_net_inet_tcp_syncache, OID_AUTO, hashsize, CTLFLAG_VNET | CTLFLAG_R
&VNET_NAME(tcp_syncache.hashsize), 0,
"Size of TCP syncache hashtable");
-SYSCTL_UINT(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit, CTLFLAG_VNET | CTLFLAG_RW,
+static int
+sysctl_net_inet_tcp_syncache_rexmtlimit_check(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ u_int new;
+
+ new = V_tcp_syncache.rexmt_limit;
+ error = sysctl_handle_int(oidp, &new, 0, req);
+ if ((error == 0) && (req->newptr != NULL)) {
+ if (new > TCP_MAXRXTSHIFT)
+ error = EINVAL;
+ else
+ V_tcp_syncache.rexmt_limit = new;
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit,
+ CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
&VNET_NAME(tcp_syncache.rexmt_limit), 0,
+ sysctl_net_inet_tcp_syncache_rexmtlimit_check, "UI",
"Limit on SYN/ACK retransmissions");
VNET_DEFINE(int, tcp_sc_rst_sock_fail) = 1;
@@ -398,8 +418,14 @@ syncache_drop(struct syncache *sc, struct syncache_head *sch)
static void
syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout)
{
- sc->sc_rxttime = ticks +
- TCPTV_RTOBASE * (tcp_syn_backoff[sc->sc_rxmits]);
+ int rexmt;
+
+ if (sc->sc_rxmits == 0)
+ rexmt = TCPTV_RTOBASE;
+ else
+ TCPT_RANGESET(rexmt, TCPTV_RTOBASE * tcp_syn_backoff[sc->sc_rxmits],
+ tcp_rexmit_min, TCPTV_REXMTMAX);
+ sc->sc_rxttime = ticks + rexmt;
sc->sc_rxmits++;
if (TSTMP_LT(sc->sc_rxttime, sch->sch_nextc)) {
sch->sch_nextc = sc->sc_rxttime;
@@ -746,10 +772,9 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
goto abort;
}
#ifdef INET6
- if (sc->sc_inc.inc_flags & INC_ISIPV6) {
+ if (inp->inp_vflag & INP_IPV6PROTO) {
struct inpcb *oinp = sotoinpcb(lso);
- struct in6_addr laddr6;
- struct sockaddr_in6 sin6;
+
/*
* Inherit socket options from the listening socket.
* Note that in6p_inputopts are not (and should not be)
@@ -763,6 +788,11 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
if (oinp->in6p_outputopts)
inp->in6p_outputopts =
ip6_copypktopts(oinp->in6p_outputopts, M_NOWAIT);
+ }
+
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
+ struct in6_addr laddr6;
+ struct sockaddr_in6 sin6;
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
@@ -1153,25 +1183,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
}
- /*
- * If timestamps were negotiated, the reflected timestamp
- * must be equal to what we actually sent in the SYN|ACK
- * except in the case of 0. Some boxes are known for sending
- * broken timestamp replies during the 3whs (and potentially
- * during the connection also).
- *
- * Accept the final ACK of 3whs with reflected timestamp of 0
- * instead of sending a RST and deleting the syncache entry.
- */
- if ((to->to_flags & TOF_TS) && to->to_tsecr &&
- to->to_tsecr != sc->sc_ts) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
- log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u, "
- "segment rejected\n",
- s, __func__, to->to_tsecr, sc->sc_ts);
- goto failed;
- }
-
*lsop = syncache_socket(sc, *lsop, m);
if (*lsop == NULL)
@@ -1404,6 +1415,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
mac_syncache_destroy(&maclabel);
#endif
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
/* Retransmit SYN|ACK and reset retransmit count. */
if ((s = tcp_log_addrs(&sc->sc_inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Received duplicate SYN, "
@@ -1418,7 +1430,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
TCPSTAT_INC(tcps_sndtotal);
}
SCH_UNLOCK(sch);
- goto done;
+ goto donenoprobe;
}
if (tfo_cookie_valid) {
@@ -1498,8 +1510,8 @@ skip_alloc:
*/
if (to->to_flags & TOF_TS) {
sc->sc_tsreflect = to->to_tsval;
- sc->sc_ts = tcp_ts_getticks();
sc->sc_flags |= SCF_TIMESTAMP;
+ sc->sc_tsoff = tcp_new_ts_offset(inc);
}
if (to->to_flags & TOF_SCALE) {
int wscale = 0;
@@ -1571,6 +1583,7 @@ skip_alloc:
goto tfo_expanded;
}
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
/*
* Do a standard 3-way handshake.
*/
@@ -1586,8 +1599,11 @@ skip_alloc:
syncache_free(sc);
TCPSTAT_INC(tcps_sc_dropped);
}
+ goto donenoprobe;
done:
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
+donenoprobe:
if (m) {
*lsop = NULL;
m_freem(m);
@@ -1727,8 +1743,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
to.to_flags |= TOF_SCALE;
}
if (sc->sc_flags & SCF_TIMESTAMP) {
- /* Virgin timestamp or TCP cookie enhanced one. */
- to.to_tsval = sc->sc_ts;
+ to.to_tsval = sc->sc_tsoff + tcp_ts_getticks();
to.to_tsecr = sc->sc_tsreflect;
to.to_flags |= TOF_TS;
}
@@ -1799,6 +1814,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
return (error);
}
#endif
+ TCP_PROBE5(send, NULL, NULL, ip6, NULL, th);
error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
}
#endif
@@ -1819,6 +1835,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
return (error);
}
#endif
+ TCP_PROBE5(send, NULL, NULL, ip, NULL, th);
error = ip_output(m, sc->sc_ipopts, NULL, 0, NULL, NULL);
}
#endif
@@ -2033,12 +2050,6 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc)
iss = hash & ~0xff;
iss |= cookie.cookie ^ (hash >> 24);
- /* Randomize the timestamp. */
- if (sc->sc_flags & SCF_TIMESTAMP) {
- sc->sc_ts = arc4random();
- sc->sc_tsoff = sc->sc_ts - tcp_ts_getticks();
- }
-
TCPSTAT_INC(tcps_sc_sendcookie);
return (iss);
}
@@ -2125,8 +2136,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
if (to->to_flags & TOF_TS) {
sc->sc_flags |= SCF_TIMESTAMP;
sc->sc_tsreflect = to->to_tsval;
- sc->sc_ts = to->to_tsecr;
- sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks();
+ sc->sc_tsoff = tcp_new_ts_offset(inc);
}
if (to->to_flags & TOF_SIGNATURE)
diff --git a/freebsd/sys/netinet/tcp_syncache.h b/freebsd/sys/netinet/tcp_syncache.h
index 92a7c7c9..0104e528 100644
--- a/freebsd/sys/netinet/tcp_syncache.h
+++ b/freebsd/sys/netinet/tcp_syncache.h
@@ -56,7 +56,6 @@ struct syncache {
int sc_rxttime; /* retransmit time */
u_int16_t sc_rxmits; /* retransmit counter */
u_int32_t sc_tsreflect; /* timestamp to reflect */
- u_int32_t sc_ts; /* our timestamp to send */
u_int32_t sc_tsoff; /* ts offset w/ syncookies */
u_int32_t sc_flowlabel; /* IPv6 flowlabel */
tcp_seq sc_irs; /* seq from peer */
diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c
index 422e5122..c50af2bb 100644
--- a/freebsd/sys/netinet/tcp_timer.c
+++ b/freebsd/sys/netinet/tcp_timer.c
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_log_buf.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
+#include <netinet/tcp_seq.h>
#include <netinet/cc/cc.h>
#ifdef INET6
#include <netinet6/tcp6_var.h>
@@ -141,7 +142,7 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
/* max idle probes */
int tcp_maxpersistidle;
-static int tcp_rexmit_drop_options = 0;
+int tcp_rexmit_drop_options = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
&tcp_rexmit_drop_options, 0,
"Drop TCP options from 3rd and later retransmitted SYN");
@@ -176,18 +177,13 @@ static int per_cpu_timers = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW,
&per_cpu_timers , 0, "run tcp timers on all cpus");
-#if 0
-#define INP_CPU(inp) (per_cpu_timers ? (!CPU_ABSENT(((inp)->inp_flowid % (mp_maxid+1))) ? \
- ((inp)->inp_flowid % (mp_maxid+1)) : curcpu) : 0)
-#endif
-
/*
* Map the given inp to a CPU id.
*
* This queries RSS if it's compiled in, else it defaults to the current
* CPU ID.
*/
-static inline int
+inline int
inp_to_cpuid(struct inpcb *inp)
{
u_int cpuid;
@@ -245,7 +241,7 @@ int tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
{ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 };
-static int tcp_totbackoff = 2559; /* sum of tcp_backoff[] */
+int tcp_totbackoff = 2559; /* sum of tcp_backoff[] */
/*
* TCP timer processing.
@@ -280,55 +276,10 @@ tcp_timer_delack(void *xtp)
CURVNET_RESTORE();
}
-/*
- * When a timer wants to remove a TCB it must
- * hold the INP_INFO_RLOCK(). The timer function
- * should only have grabbed the INP_WLOCK() when
- * it entered. To safely switch to holding both the
- * INP_INFO_RLOCK() and the INP_WLOCK() we must first
- * grab a reference on the inp, which will hold the inp
- * so that it can't be removed. We then unlock the INP_WLOCK(),
- * and grab the INP_INFO_RLOCK() lock. Once we have the INP_INFO_RLOCK()
- * we proceed again to get the INP_WLOCK() (this preserves proper
- * lock order). After acquiring the INP_WLOCK we must check if someone
- * else deleted the pcb i.e. the inp_flags check.
- * If so we return 1 otherwise we return 0.
- *
- * No matter what the tcp_inpinfo_lock_add() function
- * returns the caller must afterwards call tcp_inpinfo_lock_del()
- * to drop the locks and reference properly.
- */
-
-int
-tcp_inpinfo_lock_add(struct inpcb *inp)
-{
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- INP_INFO_RLOCK(&V_tcbinfo);
- INP_WLOCK(inp);
- if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
- return(1);
- }
- return(0);
-
-}
-
void
tcp_inpinfo_lock_del(struct inpcb *inp, struct tcpcb *tp)
{
- INP_INFO_RUNLOCK(&V_tcbinfo);
- if (inp && (tp == NULL)) {
- /*
- * If tcp_close/drop() gets called and tp
- * returns NULL, then the function dropped
- * the inp lock, we hold a reference keeping
- * this around, so we must re-aquire the
- * INP_WLOCK() in order to proceed with
- * our dropping the inp reference.
- */
- INP_WLOCK(inp);
- }
- if (inp && in_pcbrele_wlocked(inp) == 0)
+ if (inp && tp != NULL)
INP_WUNLOCK(inp);
}
@@ -337,6 +288,7 @@ tcp_timer_2msl(void *xtp)
{
struct tcpcb *tp = xtp;
struct inpcb *inp;
+ struct epoch_tracker et;
CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
int ostate;
@@ -383,11 +335,13 @@ tcp_timer_2msl(void *xtp)
tp->t_inpcb && tp->t_inpcb->inp_socket &&
(tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
TCPSTAT_INC(tcps_finwait2_drops);
- if (tcp_inpinfo_lock_add(inp)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
tp = tcp_close(tp);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
tcp_inpinfo_lock_del(inp, tp);
goto out;
} else {
@@ -395,15 +349,17 @@ tcp_timer_2msl(void *xtp)
callout_reset(&tp->t_timers->tt_2msl,
TP_KEEPINTVL(tp), tcp_timer_2msl, tp);
} else {
- if (tcp_inpinfo_lock_add(inp)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
tp = tcp_close(tp);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
- }
+ }
#ifdef TCPDEBUG
if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
@@ -424,6 +380,7 @@ tcp_timer_keep(void *xtp)
struct tcpcb *tp = xtp;
struct tcptemp *t_template;
struct inpcb *inp;
+ struct epoch_tracker et;
CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
int ostate;
@@ -517,11 +474,11 @@ tcp_timer_keep(void *xtp)
dropit:
TCPSTAT_INC(tcps_keepdrops);
-
- if (tcp_inpinfo_lock_add(inp)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
tp = tcp_drop(tp, ETIMEDOUT);
#ifdef TCPDEBUG
@@ -530,8 +487,9 @@ dropit:
PRU_SLOWTIMO);
#endif
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
tcp_inpinfo_lock_del(inp, tp);
-out:
+ out:
CURVNET_RESTORE();
}
@@ -540,6 +498,7 @@ tcp_timer_persist(void *xtp)
{
struct tcpcb *tp = xtp;
struct inpcb *inp;
+ struct epoch_tracker et;
CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
int ostate;
@@ -579,11 +538,13 @@ tcp_timer_persist(void *xtp)
(ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
TCPSTAT_INC(tcps_persistdrop);
- if (tcp_inpinfo_lock_add(inp)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
tp = tcp_drop(tp, ETIMEDOUT);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
@@ -594,11 +555,13 @@ tcp_timer_persist(void *xtp)
if (tp->t_state > TCPS_CLOSE_WAIT &&
(ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) {
TCPSTAT_INC(tcps_persistdrop);
- if (tcp_inpinfo_lock_add(inp)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
tp = tcp_drop(tp, ETIMEDOUT);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
@@ -624,6 +587,7 @@ tcp_timer_rexmt(void * xtp)
CURVNET_SET(tp->t_vnet);
int rexmt;
struct inpcb *inp;
+ struct epoch_tracker et;
#ifdef TCPDEBUG
int ostate;
@@ -660,11 +624,13 @@ tcp_timer_rexmt(void * xtp)
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
tp->t_rxtshift = TCP_MAXRXTSHIFT;
TCPSTAT_INC(tcps_timeoutdrop);
- if (tcp_inpinfo_lock_add(inp)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
tp = tcp_drop(tp, ETIMEDOUT);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
tcp_inpinfo_lock_del(inp, tp);
goto out;
}
@@ -950,6 +916,111 @@ tcp_timer_active(struct tcpcb *tp, uint32_t timer_type)
return callout_active(t_callout);
}
+/*
+ * Stop the timer from running, and apply a flag
+ * against the timer_flags that will force the
+ * timer never to run. The flag is needed to assure
+ * a race does not leave it running and cause
+ * the timer to possibly restart itself (keep and persist
+ * especially do this).
+ */
+int
+tcp_timer_suspend(struct tcpcb *tp, uint32_t timer_type)
+{
+ struct callout *t_callout;
+ uint32_t t_flags;
+
+ switch (timer_type) {
+ case TT_DELACK:
+ t_flags = TT_DELACK_SUS;
+ t_callout = &tp->t_timers->tt_delack;
+ break;
+ case TT_REXMT:
+ t_flags = TT_REXMT_SUS;
+ t_callout = &tp->t_timers->tt_rexmt;
+ break;
+ case TT_PERSIST:
+ t_flags = TT_PERSIST_SUS;
+ t_callout = &tp->t_timers->tt_persist;
+ break;
+ case TT_KEEP:
+ t_flags = TT_KEEP_SUS;
+ t_callout = &tp->t_timers->tt_keep;
+ break;
+ case TT_2MSL:
+ t_flags = TT_2MSL_SUS;
+ t_callout = &tp->t_timers->tt_2msl;
+ break;
+ default:
+ panic("tp:%p bad timer_type 0x%x", tp, timer_type);
+ }
+ tp->t_timers->tt_flags |= t_flags;
+ return (callout_stop(t_callout));
+}
+
+void
+tcp_timers_unsuspend(struct tcpcb *tp, uint32_t timer_type)
+{
+ switch (timer_type) {
+ case TT_DELACK:
+ if (tp->t_timers->tt_flags & TT_DELACK_SUS) {
+ tp->t_timers->tt_flags &= ~TT_DELACK_SUS;
+ if (tp->t_flags & TF_DELACK) {
+ /* Delayed ack timer should be up activate a timer */
+ tp->t_flags &= ~TF_DELACK;
+ tcp_timer_activate(tp, TT_DELACK,
+ tcp_delacktime);
+ }
+ }
+ break;
+ case TT_REXMT:
+ if (tp->t_timers->tt_flags & TT_REXMT_SUS) {
+ tp->t_timers->tt_flags &= ~TT_REXMT_SUS;
+ if (SEQ_GT(tp->snd_max, tp->snd_una) &&
+ (tcp_timer_active((tp), TT_PERSIST) == 0) &&
+ tp->snd_wnd) {
+ /* We have outstanding data activate a timer */
+ tcp_timer_activate(tp, TT_REXMT,
+ tp->t_rxtcur);
+ }
+ }
+ break;
+ case TT_PERSIST:
+ if (tp->t_timers->tt_flags & TT_PERSIST_SUS) {
+ tp->t_timers->tt_flags &= ~TT_PERSIST_SUS;
+ if (tp->snd_wnd == 0) {
+ /* Activate the persists timer */
+ tp->t_rxtshift = 0;
+ tcp_setpersist(tp);
+ }
+ }
+ break;
+ case TT_KEEP:
+ if (tp->t_timers->tt_flags & TT_KEEP_SUS) {
+ tp->t_timers->tt_flags &= ~TT_KEEP_SUS;
+ tcp_timer_activate(tp, TT_KEEP,
+ TCPS_HAVEESTABLISHED(tp->t_state) ?
+ TP_KEEPIDLE(tp) : TP_KEEPINIT(tp));
+ }
+ break;
+ case TT_2MSL:
+ if (tp->t_timers->tt_flags &= TT_2MSL_SUS) {
+ tp->t_timers->tt_flags &= ~TT_2MSL_SUS;
+ if ((tp->t_state == TCPS_FIN_WAIT_2) &&
+ ((tp->t_inpcb->inp_socket == NULL) ||
+ (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE))) {
+ /* Star the 2MSL timer */
+ tcp_timer_activate(tp, TT_2MSL,
+ (tcp_fast_finwait2_recycle) ?
+ tcp_finwait2_timeout : TP_MAXIDLE(tp));
+ }
+ }
+ break;
+ default:
+ panic("tp:%p bad timer_type 0x%x", tp, timer_type);
+ }
+}
+
void
tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type)
{
diff --git a/freebsd/sys/netinet/tcp_timer.h b/freebsd/sys/netinet/tcp_timer.h
index b0ff3809..a2ab6ca5 100644
--- a/freebsd/sys/netinet/tcp_timer.h
+++ b/freebsd/sys/netinet/tcp_timer.h
@@ -168,11 +168,15 @@ struct tcp_timer {
#define TT_2MSL 0x0010
#define TT_MASK (TT_DELACK|TT_REXMT|TT_PERSIST|TT_KEEP|TT_2MSL)
-#define TT_DELACK_RST 0x0100
-#define TT_REXMT_RST 0x0200
-#define TT_PERSIST_RST 0x0400
-#define TT_KEEP_RST 0x0800
-#define TT_2MSL_RST 0x1000
+/*
+ * Suspend flags - used when suspending a timer
+ * from ever running again.
+ */
+#define TT_DELACK_SUS 0x0100
+#define TT_REXMT_SUS 0x0200
+#define TT_PERSIST_SUS 0x0400
+#define TT_KEEP_SUS 0x0800
+#define TT_2MSL_SUS 0x1000
#define TT_STOPPED 0x00010000
@@ -196,6 +200,8 @@ extern int tcp_msl;
extern int tcp_ttl; /* time to live for TCP segs */
extern int tcp_backoff[];
extern int tcp_syn_backoff[];
+extern int tcp_totbackoff;
+extern int tcp_rexmit_drop_options;
extern int tcp_always_keepalive;
extern int tcp_finwait2_timeout;
@@ -208,7 +214,6 @@ VNET_DECLARE(int, tcp_pmtud_blackhole_mss);
VNET_DECLARE(int, tcp_v6pmtud_blackhole_mss);
#define V_tcp_v6pmtud_blackhole_mss VNET(tcp_v6pmtud_blackhole_mss)
-int tcp_inpinfo_lock_add(struct inpcb *inp);
void tcp_inpinfo_lock_del(struct inpcb *inp, struct tcpcb *tp);
void tcp_timer_init(void);
diff --git a/freebsd/sys/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c
index afadf7cd..8a28283f 100644
--- a/freebsd/sys/netinet/tcp_timewait.c
+++ b/freebsd/sys/netinet/tcp_timewait.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
@@ -98,7 +99,7 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static VNET_DEFINE(uma_zone_t, tcptw_zone);
+VNET_DEFINE_STATIC(uma_zone_t, tcptw_zone);
#define V_tcptw_zone VNET(tcptw_zone)
static int maxtcptw;
@@ -113,11 +114,11 @@ static int maxtcptw;
* - a tcptw relies on its inpcb reference counting for memory stability
* - a tcptw is dereferenceable only while its inpcb is locked
*/
-static VNET_DEFINE(TAILQ_HEAD(, tcptw), twq_2msl);
+VNET_DEFINE_STATIC(TAILQ_HEAD(, tcptw), twq_2msl);
#define V_twq_2msl VNET(twq_2msl)
/* Global timewait lock */
-static VNET_DEFINE(struct rwlock, tw_lock);
+VNET_DEFINE_STATIC(struct rwlock, tw_lock);
#define V_tw_lock VNET(tw_lock)
#define TW_LOCK_INIT(tw, d) rw_init_flags(&(tw), (d), 0)
@@ -174,7 +175,7 @@ SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW,
&maxtcptw, 0, sysctl_maxtcptw, "IU",
"Maximum number of compressed TCP TIME_WAIT entries");
-static VNET_DEFINE(int, nolocaltimewait) = 0;
+VNET_DEFINE_STATIC(int, nolocaltimewait) = 0;
#define V_nolocaltimewait VNET(nolocaltimewait)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(nolocaltimewait), 0,
@@ -208,11 +209,12 @@ void
tcp_tw_destroy(void)
{
struct tcptw *tw;
+ struct epoch_tracker et;
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
while ((tw = TAILQ_FIRST(&V_twq_2msl)) != NULL)
tcp_twclose(tw, 0);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
TW_LOCK_DESTROY(V_tw_lock);
uma_zdestroy(V_tcptw_zone);
@@ -230,6 +232,7 @@ tcp_twstart(struct tcpcb *tp)
struct tcptw twlocal, *tw;
struct inpcb *inp = tp->t_inpcb;
struct socket *so;
+ uint32_t recwin;
bool acknow, local;
#ifdef INET6
bool isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6;
@@ -292,10 +295,16 @@ tcp_twstart(struct tcpcb *tp)
/*
* Recover last window size sent.
*/
- if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
- tw->last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale;
- else
- tw->last_win = 0;
+ so = inp->inp_socket;
+ recwin = lmin(lmax(sbspace(&so->so_rcv), 0),
+ (long)TCP_MAXWIN << tp->rcv_scale);
+ if (recwin < (so->so_rcv.sb_hiwat / 4) &&
+ recwin < tp->t_maxseg)
+ recwin = 0;
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) &&
+ recwin < (tp->rcv_adv - tp->rcv_nxt))
+ recwin = (tp->rcv_adv - tp->rcv_nxt);
+ tw->last_win = htons((u_short)(recwin >> tp->rcv_scale));
/*
* Set t_recent if timestamps are used on the connection.
@@ -332,7 +341,6 @@ tcp_twstart(struct tcpcb *tp)
* and might not be needed here any longer.
*/
tcp_discardcb(tp);
- so = inp->inp_socket;
soisdisconnected(so);
tw->tw_so_options = so->so_options;
inp->inp_flags |= INP_TIMEWAIT;
@@ -451,9 +459,14 @@ tcp_twcheck(struct inpcb *inp, struct tcpopt *to __unused, struct tcphdr *th,
* Acknowledge the segment if it has data or is not a duplicate ACK.
*/
if (thflags != TH_ACK || tlen != 0 ||
- th->th_seq != tw->rcv_nxt || th->th_ack != tw->snd_nxt)
+ th->th_seq != tw->rcv_nxt || th->th_ack != tw->snd_nxt) {
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
tcp_twrespond(tw, TH_ACK);
+ goto dropnoprobe;
+ }
drop:
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
+dropnoprobe:
INP_WUNLOCK(inp);
m_freem(m);
return (0);
@@ -599,6 +612,7 @@ tcp_twrespond(struct tcptw *tw, int flags)
th->th_sum = in6_cksum_pseudo(ip6,
sizeof(struct tcphdr) + optlen, IPPROTO_TCP, 0);
ip6->ip6_hlim = in6_selecthlim(inp, NULL);
+ TCP_PROBE5(send, NULL, NULL, ip6, NULL, th);
error = ip6_output(m, inp->in6p_outputopts, NULL,
(tw->tw_so_options & SO_DONTROUTE), NULL, NULL, inp);
}
@@ -614,6 +628,7 @@ tcp_twrespond(struct tcptw *tw, int flags)
ip->ip_len = htons(m->m_pkthdr.len);
if (V_path_mtu_discovery)
ip->ip_off |= htons(IP_DF);
+ TCP_PROBE5(send, NULL, NULL, ip, NULL, th);
error = ip_output(m, inp->inp_options, NULL,
((tw->tw_so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0),
NULL, inp);
@@ -676,6 +691,7 @@ tcp_tw_2msl_scan(int reuse)
{
struct tcptw *tw;
struct inpcb *inp;
+ struct epoch_tracker et;
#ifdef INVARIANTS
if (reuse) {
@@ -709,54 +725,46 @@ tcp_tw_2msl_scan(int reuse)
in_pcbref(inp);
TW_RUNLOCK(V_tw_lock);
- if (INP_INFO_TRY_RLOCK(&V_tcbinfo)) {
-
- INP_WLOCK(inp);
- tw = intotw(inp);
- if (in_pcbrele_wlocked(inp)) {
- if (__predict_true(tw == NULL)) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
- continue;
- } else {
- /* This should not happen as in TIMEWAIT
- * state the inp should not be destroyed
- * before its tcptw. If INVARIANTS is
- * defined panic.
- */
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
+ INP_WLOCK(inp);
+ tw = intotw(inp);
+ if (in_pcbrele_wlocked(inp)) {
+ if (__predict_true(tw == NULL)) {
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
+ continue;
+ } else {
+ /* This should not happen as in TIMEWAIT
+ * state the inp should not be destroyed
+ * before its tcptw. If INVARIANTS is
+ * defined panic.
+ */
#ifdef INVARIANTS
- panic("%s: Panic before an infinite "
- "loop: INP_TIMEWAIT && (INP_FREED "
- "|| inp last reference) && tw != "
- "NULL", __func__);
+ panic("%s: Panic before an infinite "
+ "loop: INP_TIMEWAIT && (INP_FREED "
+ "|| inp last reference) && tw != "
+ "NULL", __func__);
#else
- log(LOG_ERR, "%s: Avoid an infinite "
- "loop: INP_TIMEWAIT && (INP_FREED "
- "|| inp last reference) && tw != "
- "NULL", __func__);
+ log(LOG_ERR, "%s: Avoid an infinite "
+ "loop: INP_TIMEWAIT && (INP_FREED "
+ "|| inp last reference) && tw != "
+ "NULL", __func__);
#endif
- INP_INFO_RUNLOCK(&V_tcbinfo);
- break;
- }
- }
-
- if (tw == NULL) {
- /* tcp_twclose() has already been called */
- INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
- continue;
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
+ break;
}
+ }
- tcp_twclose(tw, reuse);
- INP_INFO_RUNLOCK(&V_tcbinfo);
- if (reuse)
- return tw;
- } else {
- /* INP_INFO lock is busy, continue later. */
- INP_WLOCK(inp);
- if (!in_pcbrele_wlocked(inp))
- INP_WUNLOCK(inp);
- break;
+ if (tw == NULL) {
+ /* tcp_twclose() has already been called */
+ INP_WUNLOCK(inp);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
+ continue;
}
+
+ tcp_twclose(tw, reuse);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
+ if (reuse)
+ return tw;
}
return NULL;
diff --git a/freebsd/sys/netinet/tcp_usrreq.c b/freebsd/sys/netinet/tcp_usrreq.c
index bf2cff4c..617f60d0 100644
--- a/freebsd/sys/netinet/tcp_usrreq.c
+++ b/freebsd/sys/netinet/tcp_usrreq.c
@@ -278,11 +278,12 @@ tcp_usr_detach(struct socket *so)
{
struct inpcb *inp;
int rlock = 0;
+ struct epoch_tracker et;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_detach: inp == NULL"));
if (!INP_INFO_WLOCKED(&V_tcbinfo)) {
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
rlock = 1;
}
INP_WLOCK(inp);
@@ -290,7 +291,7 @@ tcp_usr_detach(struct socket *so)
("tcp_usr_detach: inp_socket == NULL"));
tcp_detach(so, inp);
if (rlock)
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
}
#ifdef INET
@@ -379,6 +380,11 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
struct sockaddr_in sin;
in6_sin6_2_sin(&sin, sin6p);
+ if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
+ error = EAFNOSUPPORT;
+ INP_HASH_WUNLOCK(&V_tcbinfo);
+ goto out;
+ }
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
error = in_pcbbind(inp, (struct sockaddr *)&sin,
@@ -608,6 +614,10 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
}
in6_sin6_2_sin(&sin, sin6p);
+ if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
+ error = EAFNOSUPPORT;
+ goto out;
+ }
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
if ((error = prison_remote_ip4(td->td_ucred,
@@ -670,10 +680,11 @@ tcp_usr_disconnect(struct socket *so)
{
struct inpcb *inp;
struct tcpcb *tp = NULL;
+ struct epoch_tracker et;
int error = 0;
TCPDEBUG0;
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL"));
INP_WLOCK(inp);
@@ -690,7 +701,7 @@ out:
TCPDEBUG2(PRU_DISCONNECT);
TCP_PROBE2(debug__user, tp, PRU_DISCONNECT);
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (error);
}
@@ -749,6 +760,7 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
struct tcpcb *tp = NULL;
struct in_addr addr;
struct in6_addr addr6;
+ struct epoch_tracker et;
in_port_t port = 0;
int v4 = 0;
TCPDEBUG0;
@@ -758,7 +770,7 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL"));
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
INP_WLOCK(inp);
if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNABORTED;
@@ -785,7 +797,7 @@ out:
TCPDEBUG2(PRU_ACCEPT);
TCP_PROBE2(debug__user, tp, PRU_ACCEPT);
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
if (error == 0) {
if (v4)
*nam = in6_v4mapsin6_sockaddr(port, &addr);
@@ -805,9 +817,10 @@ tcp_usr_shutdown(struct socket *so)
int error = 0;
struct inpcb *inp;
struct tcpcb *tp = NULL;
+ struct epoch_tracker et;
TCPDEBUG0;
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("inp == NULL"));
INP_WLOCK(inp);
@@ -826,7 +839,7 @@ out:
TCPDEBUG2(PRU_SHUTDOWN);
TCP_PROBE2(debug__user, tp, PRU_SHUTDOWN);
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (error);
}
@@ -889,6 +902,13 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
int error = 0;
struct inpcb *inp;
struct tcpcb *tp = NULL;
+ struct epoch_tracker net_et;
+#ifdef INET
+#ifdef INET6
+ struct sockaddr_in sin;
+#endif
+ struct sockaddr_in *sinp;
+#endif
#ifdef INET6
int isipv6;
#endif
@@ -899,7 +919,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
* this call.
*/
if (flags & PRUS_EOF)
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, net_et);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
INP_WLOCK(inp);
@@ -915,11 +935,124 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
error = ECONNRESET;
goto out;
}
-#ifdef INET6
- isipv6 = nam && nam->sa_family == AF_INET6;
-#endif /* INET6 */
tp = intotcpcb(inp);
TCPDEBUG1();
+ if (nam != NULL && tp->t_state < TCPS_SYN_SENT) {
+ switch (nam->sa_family) {
+#ifdef INET
+ case AF_INET:
+ sinp = (struct sockaddr_in *)nam;
+ if (sinp->sin_len != sizeof(struct sockaddr_in)) {
+ if (m)
+ m_freem(m);
+ error = EINVAL;
+ goto out;
+ }
+ if ((inp->inp_vflag & INP_IPV6) != 0) {
+ if (m)
+ m_freem(m);
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+ if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
+ if (m)
+ m_freem(m);
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+ if ((error = prison_remote_ip4(td->td_ucred,
+ &sinp->sin_addr))) {
+ if (m)
+ m_freem(m);
+ goto out;
+ }
+#ifdef INET6
+ isipv6 = 0;
+#endif
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6p;
+
+ sin6p = (struct sockaddr_in6 *)nam;
+ if (sin6p->sin6_len != sizeof(struct sockaddr_in6)) {
+ if (m)
+ m_freem(m);
+ error = EINVAL;
+ goto out;
+ }
+ if (IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) {
+ if (m)
+ m_freem(m);
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+ if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
+#ifdef INET
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) {
+ error = EINVAL;
+ if (m)
+ m_freem(m);
+ goto out;
+ }
+ if ((inp->inp_vflag & INP_IPV4) == 0) {
+ error = EAFNOSUPPORT;
+ if (m)
+ m_freem(m);
+ goto out;
+ }
+ inp->inp_vflag &= ~INP_IPV6;
+ sinp = &sin;
+ in6_sin6_2_sin(sinp, sin6p);
+ if (IN_MULTICAST(
+ ntohl(sinp->sin_addr.s_addr))) {
+ error = EAFNOSUPPORT;
+ if (m)
+ m_freem(m);
+ goto out;
+ }
+ if ((error = prison_remote_ip4(td->td_ucred,
+ &sinp->sin_addr))) {
+ if (m)
+ m_freem(m);
+ goto out;
+ }
+ isipv6 = 0;
+#else /* !INET */
+ error = EAFNOSUPPORT;
+ if (m)
+ m_freem(m);
+ goto out;
+#endif /* INET */
+ } else {
+ if ((inp->inp_vflag & INP_IPV6) == 0) {
+ if (m)
+ m_freem(m);
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+ inp->inp_vflag &= ~INP_IPV4;
+ inp->inp_inc.inc_flags |= INC_ISIPV6;
+ if ((error = prison_remote_ip6(td->td_ucred,
+ &sin6p->sin6_addr))) {
+ if (m)
+ m_freem(m);
+ goto out;
+ }
+ isipv6 = 1;
+ }
+ break;
+ }
+#endif /* INET6 */
+ default:
+ if (m)
+ m_freem(m);
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+ }
if (control) {
/* TCP doesn't do control messages (rights, creds, etc) */
if (control->m_len) {
@@ -947,7 +1080,8 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
else
#endif
#ifdef INET
- error = tcp_connect(tp, nam, td);
+ error = tcp_connect(tp,
+ (struct sockaddr *)sinp, td);
#endif
if (error)
goto out;
@@ -1016,7 +1150,8 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
else
#endif
#ifdef INET
- error = tcp_connect(tp, nam, td);
+ error = tcp_connect(tp,
+ (struct sockaddr *)sinp, td);
#endif
if (error)
goto out;
@@ -1042,7 +1177,7 @@ out:
((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
INP_WUNLOCK(inp);
if (flags & PRUS_EOF)
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, net_et);
return (error);
}
@@ -1081,12 +1216,13 @@ tcp_usr_abort(struct socket *so)
{
struct inpcb *inp;
struct tcpcb *tp = NULL;
+ struct epoch_tracker et;
TCPDEBUG0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_abort: inp == NULL"));
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
INP_WLOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_abort: inp_socket == NULL"));
@@ -1112,7 +1248,7 @@ tcp_usr_abort(struct socket *so)
}
INP_WUNLOCK(inp);
dropped:
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
}
/*
@@ -1123,12 +1259,13 @@ tcp_usr_close(struct socket *so)
{
struct inpcb *inp;
struct tcpcb *tp = NULL;
+ struct epoch_tracker et;
TCPDEBUG0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_close: inp == NULL"));
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
INP_WLOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_close: inp_socket == NULL"));
@@ -1152,7 +1289,7 @@ tcp_usr_close(struct socket *so)
inp->inp_flags |= INP_SOCKREF;
}
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
}
/*
@@ -1304,7 +1441,9 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
soisconnecting(so);
TCPSTAT_INC(tcps_connattempt);
tcp_state_change(tp, TCPS_SYN_SENT);
- tp->iss = tcp_new_isn(tp);
+ tp->iss = tcp_new_isn(&inp->inp_inc);
+ if (tp->t_flags & TF_REQ_TSTMP)
+ tp->ts_offset = tcp_new_ts_offset(&inp->inp_inc);
tcp_sendseqinit(tp);
return 0;
@@ -1343,7 +1482,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
soisconnecting(inp->inp_socket);
TCPSTAT_INC(tcps_connattempt);
tcp_state_change(tp, TCPS_SYN_SENT);
- tp->iss = tcp_new_isn(tp);
+ tp->iss = tcp_new_isn(&inp->inp_inc);
+ if (tp->t_flags & TF_REQ_TSTMP)
+ tp->ts_offset = tcp_new_ts_offset(&inp->inp_inc);
tcp_sendseqinit(tp);
return 0;
@@ -1445,6 +1586,42 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
if (inp->inp_vflag & INP_IPV6PROTO) {
INP_WUNLOCK(inp);
error = ip6_ctloutput(so, sopt);
+ /*
+ * In case of the IPV6_USE_MIN_MTU socket option,
+ * the INC_IPV6MINMTU flag to announce a corresponding
+ * MSS during the initial handshake.
+ * If the TCP connection is not in the front states,
+ * just reduce the MSS being used.
+ * This avoids the sending of TCP segments which will
+ * be fragmented at the IPv6 layer.
+ */
+ if ((error == 0) &&
+ (sopt->sopt_dir == SOPT_SET) &&
+ (sopt->sopt_level == IPPROTO_IPV6) &&
+ (sopt->sopt_name == IPV6_USE_MIN_MTU)) {
+ INP_WLOCK(inp);
+ if ((inp->inp_flags &
+ (INP_TIMEWAIT | INP_DROPPED))) {
+ INP_WUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ inp->inp_inc.inc_flags |= INC_IPV6MINMTU;
+ tp = intotcpcb(inp);
+ if ((tp->t_state >= TCPS_SYN_SENT) &&
+ (inp->inp_inc.inc_flags & INC_ISIPV6)) {
+ struct ip6_pktopts *opt;
+
+ opt = inp->in6p_outputopts;
+ if ((opt != NULL) &&
+ (opt->ip6po_minmtu ==
+ IP6PO_MINMTU_ALL)) {
+ if (tp->t_maxseg > TCP6_MSS) {
+ tp->t_maxseg = TCP6_MSS;
+ }
+ }
+ }
+ INP_WUNLOCK(inp);
+ }
}
#endif /* INET6 */
#if defined(INET6) && defined(INET)
@@ -1487,7 +1664,6 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
return (0);
}
if (tp->t_state != TCPS_CLOSED) {
- int error=EINVAL;
/*
* The user has advanced the state
* past the initial point, we may not
@@ -1500,7 +1676,8 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
* still be possible?
*/
error = (*blk->tfb_tcp_handoff_ok)(tp);
- }
+ } else
+ error = EINVAL;
if (error) {
refcount_release(&blk->tfb_refcnt);
INP_WUNLOCK(inp);
@@ -1724,6 +1901,7 @@ unlock_and_done:
*/
if (CC_ALGO(tp)->cb_destroy != NULL)
CC_ALGO(tp)->cb_destroy(tp->ccv);
+ CC_DATA(tp) = NULL;
CC_ALGO(tp) = algo;
/*
* If something goes pear shaped initialising the new
@@ -2045,6 +2223,7 @@ tcp_attach(struct socket *so)
{
struct tcpcb *tp;
struct inpcb *inp;
+ struct epoch_tracker et;
int error;
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
@@ -2054,10 +2233,10 @@ tcp_attach(struct socket *so)
}
so->so_rcv.sb_flags |= SB_AUTOSIZE;
so->so_snd.sb_flags |= SB_AUTOSIZE;
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK_ET(&V_tcbinfo, et);
error = in_pcballoc(so, &V_tcbinfo);
if (error) {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (error);
}
inp = sotoinpcb(so);
@@ -2075,12 +2254,12 @@ tcp_attach(struct socket *so)
if (tp == NULL) {
in_pcbdetach(inp);
in_pcbfree(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
return (ENOBUFS);
}
tp->t_state = TCPS_CLOSED;
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
TCPSTATES_INC(TCPS_CLOSED);
return (0);
}
@@ -2106,7 +2285,8 @@ tcp_disconnect(struct tcpcb *tp)
* Neither tcp_close() nor tcp_drop() should return NULL, as the
* socket is still open.
*/
- if (tp->t_state < TCPS_ESTABLISHED) {
+ if (tp->t_state < TCPS_ESTABLISHED &&
+ !(tp->t_state > TCPS_LISTEN && IS_FASTOPEN(tp->t_flags))) {
tp = tcp_close(tp);
KASSERT(tp != NULL,
("tcp_disconnect: tcp_close() returned NULL"));
@@ -2383,7 +2563,7 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent)
db_print_indent(indent);
db_printf("t_segq first: %p t_segqlen: %d t_dupacks: %d\n",
- LIST_FIRST(&tp->t_segq), tp->t_segqlen, tp->t_dupacks);
+ TAILQ_FIRST(&tp->t_segq), tp->t_segqlen, tp->t_dupacks);
db_print_indent(indent);
db_printf("tt_rexmt: %p tt_persist: %p tt_keep: %p\n",
diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h
index adaaff61..2fbe07ad 100644
--- a/freebsd/sys/netinet/tcp_var.h
+++ b/freebsd/sys/netinet/tcp_var.h
@@ -46,12 +46,15 @@
#if defined(_KERNEL) || defined(_WANT_TCPCB)
/* TCP segment queue entry */
struct tseg_qent {
- LIST_ENTRY(tseg_qent) tqe_q;
+ TAILQ_ENTRY(tseg_qent) tqe_q;
+ struct mbuf *tqe_m; /* mbuf contains packet */
+ struct mbuf *tqe_last; /* last mbuf in chain */
+ tcp_seq tqe_start; /* TCP Sequence number start */
int tqe_len; /* TCP segment data length */
- struct tcphdr *tqe_th; /* a pointer to tcp header */
- struct mbuf *tqe_m; /* mbuf contains packet */
+ uint32_t tqe_flags; /* The flags from the th->th_flags */
+ uint32_t tqe_mbuf_cnt; /* Count of mbuf overhead */
};
-LIST_HEAD(tsegqe_head, tseg_qent);
+TAILQ_HEAD(tsegqe_head, tseg_qent);
struct sackblk {
tcp_seq start; /* start seq no. of sack block */
@@ -79,6 +82,8 @@ struct sackhint {
uint64_t _pad[1]; /* TBD */
};
+#define SEGQ_EMPTY(tp) TAILQ_EMPTY(&(tp)->t_segq)
+
STAILQ_HEAD(tcp_log_stailq, tcp_log_mem);
/*
@@ -93,8 +98,11 @@ struct tcpcb {
void *t_fb_ptr; /* Pointer to t_fb specific data */
uint32_t t_maxseg:24, /* maximum segment size */
t_logstate:8; /* State of "black box" logging */
- uint32_t t_state:4, /* state of this connection */
- bits_spare : 24;
+ uint32_t t_port:16, /* Tunneling (over udp) port */
+ t_state:4, /* state of this connection */
+ t_idle_reduce : 1,
+ t_delayed_ack: 7, /* Delayed ack variable */
+ bits_spare : 4;
u_int t_flags;
tcp_seq snd_una; /* sent but unacknowledged */
tcp_seq snd_max; /* highest sequence number sent;
@@ -104,7 +112,7 @@ struct tcpcb {
tcp_seq snd_up; /* send urgent pointer */
uint32_t snd_wnd; /* send window */
uint32_t snd_cwnd; /* congestion-controlled window */
- uint32_t cl1_spare; /* Spare to round out CL 1 */
+ uint32_t t_peakrate_thr; /* pre-calculated peak rate threshold */
/* Cache line 2 */
u_int32_t ts_offset; /* our timestamp offset */
u_int32_t rfbuf_ts; /* recv buffer autoscaling timestamp */
@@ -128,6 +136,7 @@ struct tcpcb {
/* Cache line 3 */
tcp_seq rcv_up; /* receive urgent pointer */
int t_segqlen; /* segment reassembly queue length */
+ uint32_t t_segqmbuflen; /* Count of bytes mbufs on all entries */
struct tsegqe_head t_segq; /* segment reassembly queue */
struct mbuf *t_in_pkt;
struct mbuf *t_tail_pkt;
@@ -189,6 +198,7 @@ struct tcpcb {
struct cc_var *ccv; /* congestion control specific vars */
struct osd *osd; /* storage for Khelp module data */
int t_bytes_acked; /* # bytes acked during current RTT */
+ u_int t_maxunacktime;
u_int t_keepinit; /* time to establish connection */
u_int t_keepidle; /* time before keepalive probes begin */
u_int t_keepintvl; /* interval between keepalives */
@@ -260,12 +270,11 @@ struct tcp_function_block {
int (*tfb_tcp_output_wtime)(struct tcpcb *, const struct timeval *);
void (*tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *,
struct socket *, struct tcpcb *,
- int, int, uint8_t,
- int);
+ int, int, uint8_t);
void (*tfb_tcp_hpts_do_segment)(struct mbuf *, struct tcphdr *,
struct socket *, struct tcpcb *,
int, int, uint8_t,
- int, int, struct timeval *);
+ int, struct timeval *);
int (*tfb_tcp_ctloutput)(struct socket *so, struct sockopt *sopt,
struct inpcb *inp, struct tcpcb *tp);
/* Optional memory allocation/free routine */
@@ -361,6 +370,7 @@ TAILQ_HEAD(tcp_funchead, tcp_function);
#define TF2_PLPMTU_PMTUD 0x00000002 /* Allowed to attempt PLPMTUD. */
#define TF2_PLPMTU_MAXSEGSNT 0x00000004 /* Last seg sent was full seg. */
#define TF2_LOG_AUTO 0x00000008 /* Session is auto-logging. */
+#define TF2_DROP_AF_DATA 0x00000010 /* Drop after all data ack'd */
/*
* Structure to hold TCP options that are only used during segment
@@ -649,6 +659,11 @@ struct tcp_hhook_data {
int tso;
tcp_seq curack;
};
+#ifdef TCP_HHOOK
+void hhook_run_tcp_est_out(struct tcpcb *tp,
+ struct tcphdr *th, struct tcpopt *to,
+ uint32_t len, int tso);
+#endif
#endif
/*
@@ -668,7 +683,7 @@ struct tcp_hhook_data {
*/
#if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_)
struct xtcpcb {
- size_t xt_len; /* length of this structure */
+ ksize_t xt_len; /* length of this structure */
struct xinpcb xt_inp;
char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (s) */
char xt_logid[TCP_LOG_ID_LEN]; /* (s) */
@@ -801,6 +816,9 @@ VNET_DECLARE(struct inpcbinfo, tcbinfo);
#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes)
#define V_tcp_sc_rst_sock_fail VNET(tcp_sc_rst_sock_fail)
#define V_tcp_sendspace VNET(tcp_sendspace)
+#define V_tcp_udp_tunneling_overhead VNET(tcp_udp_tunneling_overhead)
+#define V_tcp_udp_tunneling_port VNET(tcp_udp_tunneling_port)
+
#ifdef TCP_HHOOK
VNET_DECLARE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST + 1]);
@@ -825,7 +843,7 @@ char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
const void *);
char *tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *,
const void *);
-int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *);
+int tcp_reass(struct tcpcb *, struct tcphdr *, tcp_seq *, int *, struct mbuf *);
void tcp_reass_global_init(void);
void tcp_reass_flush(struct tcpcb *);
void tcp_dooptions(struct tcpopt *, u_char *, int, int);
@@ -849,8 +867,7 @@ int tcp_input(struct mbuf **, int *, int);
int tcp_autorcvbuf(struct mbuf *, struct tcphdr *, struct socket *,
struct tcpcb *, int);
void tcp_do_segment(struct mbuf *, struct tcphdr *,
- struct socket *, struct tcpcb *, int, int, uint8_t,
- int);
+ struct socket *, struct tcpcb *, int, int, uint8_t);
int register_tcp_functions(struct tcp_function_block *blk, int wait);
int register_tcp_functions_as_names(struct tcp_function_block *blk,
@@ -893,9 +910,12 @@ struct tcptemp *
tcpip_maketemplate(struct inpcb *);
void tcpip_fillheaders(struct inpcb *, void *, void *);
void tcp_timer_activate(struct tcpcb *, uint32_t, u_int);
+int tcp_timer_suspend(struct tcpcb *, uint32_t);
+void tcp_timers_unsuspend(struct tcpcb *, uint32_t);
int tcp_timer_active(struct tcpcb *, uint32_t);
void tcp_timer_stop(struct tcpcb *, uint32_t);
void tcp_trace(short, short, struct tcpcb *, void *, struct tcphdr *, int);
+int inp_to_cpuid(struct inpcb *inp);
/*
* All tcp_hc_* functions are IPv4 and IPv6 (via in_conninfo)
*/
@@ -909,7 +929,9 @@ void tcp_hc_updatemtu(struct in_conninfo *, uint32_t);
void tcp_hc_update(struct in_conninfo *, struct hc_metrics_lite *);
extern struct pr_usrreqs tcp_usrreqs;
-tcp_seq tcp_new_isn(struct tcpcb *);
+
+uint32_t tcp_new_ts_offset(struct in_conninfo *);
+tcp_seq tcp_new_isn(struct in_conninfo *);
int tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq);
void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend);
@@ -921,6 +943,10 @@ void tcp_free_sackholes(struct tcpcb *tp);
int tcp_newreno(struct tcpcb *, struct tcphdr *);
int tcp_compute_pipe(struct tcpcb *);
void tcp_sndbuf_autoscale(struct tcpcb *, struct socket *, uint32_t);
+struct mbuf *
+ tcp_m_copym(struct mbuf *m, int32_t off0, int32_t *plen,
+ int32_t seglimit, int32_t segsize, struct sockbuf *sb);
+
static inline void
tcp_fields_to_host(struct tcphdr *th)
diff --git a/freebsd/sys/netinet/udp_usrreq.c b/freebsd/sys/netinet/udp_usrreq.c
index 178a8d5e..9557c154 100644
--- a/freebsd/sys/netinet/udp_usrreq.c
+++ b/freebsd/sys/netinet/udp_usrreq.c
@@ -150,7 +150,7 @@ VNET_DEFINE(struct inpcbhead, udb); /* from udp_var.h */
VNET_DEFINE(struct inpcbinfo, udbinfo);
VNET_DEFINE(struct inpcbhead, ulitecb);
VNET_DEFINE(struct inpcbinfo, ulitecbinfo);
-static VNET_DEFINE(uma_zone_t, udpcb_zone);
+VNET_DEFINE_STATIC(uma_zone_t, udpcb_zone);
#define V_udpcb_zone VNET(udpcb_zone)
#ifndef UDBHASHSIZE
@@ -405,6 +405,7 @@ udp_input(struct mbuf **mp, int *offp, int proto)
struct sockaddr_in udp_in[2];
struct mbuf *m;
struct m_tag *fwd_tag;
+ struct epoch_tracker et;
int cscov_partial, iphlen;
m = *mp;
@@ -535,10 +536,10 @@ udp_input(struct mbuf **mp, int *offp, int proto)
struct inpcbhead *pcblist;
struct ip_moptions *imo;
- INP_INFO_RLOCK(pcbinfo);
+ INP_INFO_RLOCK_ET(pcbinfo, et);
pcblist = udp_get_pcblist(proto);
last = NULL;
- LIST_FOREACH(inp, pcblist, inp_list) {
+ CK_LIST_FOREACH(inp, pcblist, inp_list) {
if (inp->inp_lport != uh->uh_dport)
continue;
#ifdef INET6
@@ -599,8 +600,12 @@ udp_input(struct mbuf **mp, int *offp, int proto)
if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) !=
NULL) {
- UDP_PROBE(receive, NULL, last, ip,
- last, uh);
+ if (proto == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, last, ip,
+ last, uh);
+ else
+ UDP_PROBE(receive, NULL, last, ip, last,
+ uh);
if (udp_append(last, ip, n, iphlen,
udp_in)) {
goto inp_lost;
@@ -618,7 +623,7 @@ udp_input(struct mbuf **mp, int *offp, int proto)
* will never clear these options after setting them.
*/
if ((last->inp_socket->so_options &
- (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+ (SO_REUSEPORT|SO_REUSEPORT_LB|SO_REUSEADDR)) == 0)
break;
}
@@ -631,14 +636,17 @@ udp_input(struct mbuf **mp, int *offp, int proto)
UDPSTAT_INC(udps_noportbcast);
if (inp)
INP_RUNLOCK(inp);
- INP_INFO_RUNLOCK(pcbinfo);
+ INP_INFO_RUNLOCK_ET(pcbinfo, et);
goto badunlocked;
}
- UDP_PROBE(receive, NULL, last, ip, last, uh);
+ if (proto == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, last, ip, last, uh);
+ else
+ UDP_PROBE(receive, NULL, last, ip, last, uh);
if (udp_append(last, ip, m, iphlen, udp_in) == 0)
INP_RUNLOCK(last);
inp_lost:
- INP_INFO_RUNLOCK(pcbinfo);
+ INP_INFO_RUNLOCK_ET(pcbinfo, et);
return (IPPROTO_DONE);
}
@@ -690,6 +698,10 @@ udp_input(struct mbuf **mp, int *offp, int proto)
inet_ntoa_r(ip->ip_dst, dst), ntohs(uh->uh_dport),
inet_ntoa_r(ip->ip_src, src), ntohs(uh->uh_sport));
}
+ if (proto == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, NULL, ip, NULL, uh);
+ else
+ UDP_PROBE(receive, NULL, NULL, ip, NULL, uh);
UDPSTAT_INC(udps_noport);
if (m->m_flags & (M_BCAST | M_MCAST)) {
UDPSTAT_INC(udps_noportbcast);
@@ -709,6 +721,10 @@ udp_input(struct mbuf **mp, int *offp, int proto)
*/
INP_RLOCK_ASSERT(inp);
if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
+ if (proto == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh);
+ else
+ UDP_PROBE(receive, NULL, inp, ip, inp, uh);
INP_RUNLOCK(inp);
m_freem(m);
return (IPPROTO_DONE);
@@ -724,7 +740,10 @@ udp_input(struct mbuf **mp, int *offp, int proto)
}
}
- UDP_PROBE(receive, NULL, inp, ip, inp, uh);
+ if (proto == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh);
+ else
+ UDP_PROBE(receive, NULL, inp, ip, inp, uh);
if (udp_append(inp, ip, m, iphlen, udp_in) == 0)
INP_RUNLOCK(inp);
return (IPPROTO_DONE);
@@ -808,14 +827,15 @@ udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip,
INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
if (inp != NULL) {
struct udpcb *up;
+ void *ctx;
+ udp_tun_icmp_t func;
up = intoudpcb(inp);
- if (up->u_icmp_func != NULL) {
- INP_RUNLOCK(inp);
- (*up->u_icmp_func)(cmd, sa, vip, up->u_tun_ctx);
- } else {
- INP_RUNLOCK(inp);
- }
+ ctx = up->u_tun_ctx;
+ func = up->u_icmp_func;
+ INP_RUNLOCK(inp);
+ if (func != NULL)
+ (*func)(cmd, sa, vip, ctx);
}
}
} else
@@ -842,9 +862,9 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
{
int error, i, n;
struct inpcb *inp, **inp_list;
- struct in_pcblist *il;
inp_gen_t gencnt;
struct xinpgen xig;
+ struct epoch_tracker et;
/*
* The process of preparing the PCB list is too time-consuming and
@@ -863,10 +883,10 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
/*
* OK, now we're committed to doing something.
*/
- INP_INFO_RLOCK(&V_udbinfo);
+ INP_INFO_RLOCK_ET(&V_udbinfo, et);
gencnt = V_udbinfo.ipi_gencnt;
n = V_udbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_INFO_RUNLOCK_ET(&V_udbinfo, et);
error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
+ n * sizeof(struct xinpcb));
@@ -880,12 +900,14 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, &xig, sizeof xig);
if (error)
return (error);
- il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
- inp_list = il->il_inp_list;
- INP_INFO_RLOCK(&V_udbinfo);
- for (inp = LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; inp && i < n;
- inp = LIST_NEXT(inp, inp_list)) {
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
+ if (inp_list == NULL)
+ return (ENOMEM);
+
+ INP_INFO_RLOCK_ET(&V_udbinfo, et);
+ for (inp = CK_LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; inp && i < n;
+ inp = CK_LIST_NEXT(inp, inp_list)) {
INP_WLOCK(inp);
if (inp->inp_gencnt <= gencnt &&
cr_canseeinpcb(req->td->td_ucred, inp) == 0) {
@@ -894,7 +916,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
}
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_INFO_RUNLOCK_ET(&V_udbinfo, et);
n = i;
error = 0;
@@ -910,9 +932,14 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
} else
INP_RUNLOCK(inp);
}
- il->il_count = n;
- il->il_pcbinfo = &V_udbinfo;
- epoch_call(net_epoch_preempt, &il->il_epoch_ctx, in_pcblist_rele_rlocked);
+ INP_INFO_WLOCK(&V_udbinfo);
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
+ }
+ INP_INFO_WUNLOCK(&V_udbinfo);
if (!error) {
/*
@@ -921,13 +948,14 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
* that something happened while we were processing this
* request, and it might be necessary to retry.
*/
- INP_INFO_RLOCK(&V_udbinfo);
+ INP_INFO_RLOCK_ET(&V_udbinfo, et);
xig.xig_gen = V_udbinfo.ipi_gencnt;
xig.xig_sogen = so_gencnt;
xig.xig_count = V_udbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_INFO_RUNLOCK_ET(&V_udbinfo, et);
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
+ free(inp_list, M_TEMP);
return (error);
}
@@ -1106,6 +1134,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
struct cmsghdr *cm;
struct inpcbinfo *pcbinfo;
struct sockaddr_in *sin, src;
+ struct epoch_tracker et;
int cscov_partial = 0;
int error = 0;
int ipflags;
@@ -1262,7 +1291,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
(inp->inp_laddr.s_addr == INADDR_ANY) ||
(inp->inp_lport == 0))) ||
(src.sin_family == AF_INET)) {
- INP_HASH_RLOCK(pcbinfo);
+ INP_HASH_RLOCK_ET(pcbinfo, et);
unlock_udbinfo = UH_RLOCKED;
} else
unlock_udbinfo = UH_UNLOCKED;
@@ -1390,6 +1419,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
*/
ui = mtod(m, struct udpiphdr *);
bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */
+ ui->ui_v = IPVERSION << 4;
ui->ui_pr = pr;
ui->ui_src = laddr;
ui->ui_dst = faddr;
@@ -1412,8 +1442,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
* the entire UDPLite packet is covered by the checksum.
*/
cscov_partial = (cscov == 0) ? 0 : 1;
- } else
- ui->ui_v = IPVERSION << 4;
+ }
/*
* Set the Don't Fragment bit in the IP header.
@@ -1518,8 +1547,11 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
if (unlock_udbinfo == UH_WLOCKED)
INP_HASH_WUNLOCK(pcbinfo);
else if (unlock_udbinfo == UH_RLOCKED)
- INP_HASH_RUNLOCK(pcbinfo);
- UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u);
+ INP_HASH_RUNLOCK_ET(pcbinfo, et);
+ if (pr == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u);
+ else
+ UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u);
error = ip_output(m, inp->inp_options,
(unlock_inp == UH_WLOCKED ? &inp->inp_route : NULL), ipflags,
inp->inp_moptions, inp);
@@ -1538,7 +1570,7 @@ release:
} else if (unlock_udbinfo == UH_RLOCKED) {
KASSERT(unlock_inp == UH_RLOCKED,
("%s: shared udbinfo lock, excl inp lock", __func__));
- INP_HASH_RUNLOCK(pcbinfo);
+ INP_HASH_RUNLOCK_ET(pcbinfo, et);
INP_RUNLOCK(inp);
} else if (unlock_inp == UH_WLOCKED)
INP_WUNLOCK(inp);
@@ -1719,7 +1751,6 @@ udp_detach(struct socket *so)
INP_WLOCK(inp);
up = intoudpcb(inp);
KASSERT(up != NULL, ("%s: up == NULL", __func__));
- /* XXX defer to epoch_call */
inp->inp_ppcb = NULL;
in_pcbdetach(inp);
in_pcbfree(inp);
diff --git a/freebsd/sys/netinet/udplite.h b/freebsd/sys/netinet/udplite.h
index 0e23cd70..57a1422a 100644
--- a/freebsd/sys/netinet/udplite.h
+++ b/freebsd/sys/netinet/udplite.h
@@ -29,6 +29,17 @@
#ifndef _NETINET_UDPLITE_H_
#define _NETINET_UDPLITE_H_
+/*
+ * UDP-Lite protocol header.
+ * Per RFC 3828, July, 2004.
+ */
+struct udplitehdr {
+ u_short udplite_sport; /* UDO-Lite source port */
+ u_short udplite_dport; /* UDP-Lite destination port */
+ u_short udplite_coverage; /* UDP-Lite checksum coverage */
+ u_short udplite_checksum; /* UDP-Lite checksum */
+};
+
/*
* User-settable options (used with setsockopt).
*/
diff --git a/freebsd/sys/netinet6/frag6.c b/freebsd/sys/netinet6/frag6.c
index 70103fe3..0b0c7b91 100644
--- a/freebsd/sys/netinet6/frag6.c
+++ b/freebsd/sys/netinet6/frag6.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/hash.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
@@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/syslog.h>
+#include <machine/atomic.h>
+
#include <net/if.h>
#include <net/if_var.h>
#include <net/netisr.h>
@@ -67,58 +70,110 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static void frag6_enq(struct ip6asfrag *, struct ip6asfrag *);
-static void frag6_deq(struct ip6asfrag *);
-static void frag6_insque(struct ip6q *, struct ip6q *);
-static void frag6_remque(struct ip6q *);
-static void frag6_freef(struct ip6q *);
-
-static struct mtx ip6qlock;
/*
- * These fields all protected by ip6qlock.
+ * Reassembly headers are stored in hash buckets.
*/
-static VNET_DEFINE(u_int, frag6_nfragpackets);
-static VNET_DEFINE(u_int, frag6_nfrags);
-static VNET_DEFINE(struct ip6q, ip6q); /* ip6 reassemble queue */
+#define IP6REASS_NHASH_LOG2 10
+#define IP6REASS_NHASH (1 << IP6REASS_NHASH_LOG2)
+#define IP6REASS_HMASK (IP6REASS_NHASH - 1)
+
+static void frag6_enq(struct ip6asfrag *, struct ip6asfrag *,
+ uint32_t bucket __unused);
+static void frag6_deq(struct ip6asfrag *, uint32_t bucket __unused);
+static void frag6_insque_head(struct ip6q *, struct ip6q *,
+ uint32_t bucket);
+static void frag6_remque(struct ip6q *, uint32_t bucket);
+static void frag6_freef(struct ip6q *, uint32_t bucket);
+
+struct ip6qbucket {
+ struct ip6q ip6q;
+ struct mtx lock;
+ int count;
+};
+
+VNET_DEFINE_STATIC(volatile u_int, frag6_nfragpackets);
+volatile u_int frag6_nfrags = 0;
+VNET_DEFINE_STATIC(struct ip6qbucket, ip6q[IP6REASS_NHASH]);
+VNET_DEFINE_STATIC(uint32_t, ip6q_hashseed);
#define V_frag6_nfragpackets VNET(frag6_nfragpackets)
-#define V_frag6_nfrags VNET(frag6_nfrags)
#define V_ip6q VNET(ip6q)
+#define V_ip6q_hashseed VNET(ip6q_hashseed)
-#define IP6Q_LOCK_INIT() mtx_init(&ip6qlock, "ip6qlock", NULL, MTX_DEF);
-#define IP6Q_LOCK() mtx_lock(&ip6qlock)
-#define IP6Q_TRYLOCK() mtx_trylock(&ip6qlock)
-#define IP6Q_LOCK_ASSERT() mtx_assert(&ip6qlock, MA_OWNED)
-#define IP6Q_UNLOCK() mtx_unlock(&ip6qlock)
+#define IP6Q_LOCK(i) mtx_lock(&V_ip6q[(i)].lock)
+#define IP6Q_TRYLOCK(i) mtx_trylock(&V_ip6q[(i)].lock)
+#define IP6Q_LOCK_ASSERT(i) mtx_assert(&V_ip6q[(i)].lock, MA_OWNED)
+#define IP6Q_UNLOCK(i) mtx_unlock(&V_ip6q[(i)].lock)
+#define IP6Q_HEAD(i) (&V_ip6q[(i)].ip6q)
static MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header");
/*
+ * By default, limit the number of IP6 fragments across all reassembly
+ * queues to 1/32 of the total number of mbuf clusters.
+ *
+ * Limit the total number of reassembly queues per VNET to the
+ * IP6 fragment limit, but ensure the limit will not allow any bucket
+ * to grow above 100 items. (The bucket limit is
+ * IP_MAXFRAGPACKETS / (IPREASS_NHASH / 2), so the 50 is the correct
+ * multiplier to reach a 100-item limit.)
+ * The 100-item limit was chosen as brief testing seems to show that
+ * this produces "reasonable" performance on some subset of systems
+ * under DoS attack.
+ */
+#define IP6_MAXFRAGS (nmbclusters / 32)
+#define IP6_MAXFRAGPACKETS (imin(IP6_MAXFRAGS, IP6REASS_NHASH * 50))
+
+/*
* Initialise reassembly queue and fragment identifier.
*/
+void
+frag6_set_bucketsize()
+{
+ int i;
+
+ if ((i = V_ip6_maxfragpackets) > 0)
+ V_ip6_maxfragbucketsize = imax(i / (IP6REASS_NHASH / 2), 1);
+}
+
static void
frag6_change(void *tag)
{
+ VNET_ITERATOR_DECL(vnet_iter);
- V_ip6_maxfragpackets = nmbclusters / 4;
- V_ip6_maxfrags = nmbclusters / 4;
+ ip6_maxfrags = IP6_MAXFRAGS;
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ V_ip6_maxfragpackets = IP6_MAXFRAGPACKETS;
+ frag6_set_bucketsize();
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
void
frag6_init(void)
{
-
- V_ip6_maxfragpackets = nmbclusters / 4;
- V_ip6_maxfrags = nmbclusters / 4;
- V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
-
+ struct ip6q *q6;
+ int i;
+
+ V_ip6_maxfragpackets = IP6_MAXFRAGPACKETS;
+ frag6_set_bucketsize();
+ for (i = 0; i < IP6REASS_NHASH; i++) {
+ q6 = IP6Q_HEAD(i);
+ q6->ip6q_next = q6->ip6q_prev = q6;
+ mtx_init(&V_ip6q[i].lock, "ip6qlock", NULL, MTX_DEF);
+ V_ip6q[i].count = 0;
+ }
+ V_ip6q_hashseed = arc4random();
+ V_ip6_maxfragsperpacket = 64;
if (!IS_DEFAULT_VNET(curvnet))
return;
+ ip6_maxfrags = IP6_MAXFRAGS;
EVENTHANDLER_REGISTER(nmbclusters_change,
frag6_change, NULL, EVENTHANDLER_PRI_ANY);
-
- IP6Q_LOCK_INIT();
}
/*
@@ -159,12 +214,15 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
struct mbuf *m = *mp, *t;
struct ip6_hdr *ip6;
struct ip6_frag *ip6f;
- struct ip6q *q6;
+ struct ip6q *head, *q6;
struct ip6asfrag *af6, *ip6af, *af6dwn;
struct in6_ifaddr *ia;
int offset = *offp, nxt, i, next;
int first_frag = 0;
int fragoff, frgpartlen; /* must be larger than u_int16_t */
+ uint32_t hashkey[(sizeof(struct in6_addr) * 2 +
+ sizeof(ip6f->ip6f_ident)) / sizeof(uint32_t)];
+ uint32_t hash, *hashkeyp;
struct ifnet *dstifp;
u_int8_t ecn, ecn0;
#ifdef RSS
@@ -233,19 +291,38 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
return (ip6f->ip6f_nxt);
}
- IP6Q_LOCK();
+ /* Get fragment length and discard 0-byte fragments. */
+ frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
+ if (frgpartlen == 0) {
+ icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
+ offsetof(struct ip6_hdr, ip6_plen));
+ in6_ifstat_inc(dstifp, ifs6_reass_fail);
+ IP6STAT_INC(ip6s_fragdropped);
+ return IPPROTO_DONE;
+ }
+
+ hashkeyp = hashkey;
+ memcpy(hashkeyp, &ip6->ip6_src, sizeof(struct in6_addr));
+ hashkeyp += sizeof(struct in6_addr) / sizeof(*hashkeyp);
+ memcpy(hashkeyp, &ip6->ip6_dst, sizeof(struct in6_addr));
+ hashkeyp += sizeof(struct in6_addr) / sizeof(*hashkeyp);
+ *hashkeyp = ip6f->ip6f_ident;
+ hash = jenkins_hash32(hashkey, nitems(hashkey), V_ip6q_hashseed);
+ hash &= IP6REASS_HMASK;
+ head = IP6Q_HEAD(hash);
+ IP6Q_LOCK(hash);
/*
* Enforce upper bound on number of fragments.
* If maxfrag is 0, never accept fragments.
* If maxfrag is -1, accept all fragments without limitation.
*/
- if (V_ip6_maxfrags < 0)
+ if (ip6_maxfrags < 0)
;
- else if (V_frag6_nfrags >= (u_int)V_ip6_maxfrags)
+ else if (atomic_load_int(&frag6_nfrags) >= (u_int)ip6_maxfrags)
goto dropfrag;
- for (q6 = V_ip6q.ip6q_next; q6 != &V_ip6q; q6 = q6->ip6q_next)
+ for (q6 = head->ip6q_next; q6 != head; q6 = q6->ip6q_next)
if (ip6f->ip6f_ident == q6->ip6q_ident &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)
@@ -255,7 +332,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
)
break;
- if (q6 == &V_ip6q) {
+ if (q6 == head) {
/*
* the first fragment to arrive, create a reassembly queue.
*/
@@ -270,9 +347,11 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
*/
if (V_ip6_maxfragpackets < 0)
;
- else if (V_frag6_nfragpackets >= (u_int)V_ip6_maxfragpackets)
+ else if (V_ip6q[hash].count >= V_ip6_maxfragbucketsize ||
+ atomic_load_int(&V_frag6_nfragpackets) >=
+ (u_int)V_ip6_maxfragpackets)
goto dropfrag;
- V_frag6_nfragpackets++;
+ atomic_add_int(&V_frag6_nfragpackets, 1);
q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE,
M_NOWAIT);
if (q6 == NULL)
@@ -285,7 +364,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
}
mac_ip6q_create(m, q6);
#endif
- frag6_insque(q6, &V_ip6q);
+ frag6_insque_head(q6, head, hash);
/* ip6q_nxt will be filled afterwards, from 1st fragment */
q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6;
@@ -319,21 +398,20 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
* in size.
* If it would exceed, discard the fragment and return an ICMP error.
*/
- frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
if (q6->ip6q_unfrglen >= 0) {
/* The 1st fragment has already arrived. */
if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) +
offsetof(struct ip6_frag, ip6f_offlg));
- IP6Q_UNLOCK();
+ IP6Q_UNLOCK(hash);
return (IPPROTO_DONE);
}
} else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) +
offsetof(struct ip6_frag, ip6f_offlg));
- IP6Q_UNLOCK();
+ IP6Q_UNLOCK(hash);
return (IPPROTO_DONE);
}
/*
@@ -352,7 +430,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
int erroff = af6->ip6af_offset;
/* dequeue the fragment. */
- frag6_deq(af6);
+ frag6_deq(af6, hash);
free(af6, M_FTABLE);
/* adjust pointer. */
@@ -450,7 +528,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
}
af6 = af6->ip6af_down;
m_freem(IP6_REASS_MBUF(af6->ip6af_up));
- frag6_deq(af6->ip6af_up);
+ frag6_deq(af6->ip6af_up, hash);
}
#else
/*
@@ -499,29 +577,38 @@ insert:
/*
* Stick new segment in its place;
* check for complete reassembly.
+ * If not complete, check fragment limit.
* Move to front of packet queue, as we are
* the most recently active fragmented packet.
*/
- frag6_enq(ip6af, af6->ip6af_up);
- V_frag6_nfrags++;
+ frag6_enq(ip6af, af6->ip6af_up, hash);
+ atomic_add_int(&frag6_nfrags, 1);
q6->ip6q_nfrag++;
#if 0 /* xxx */
- if (q6 != V_ip6q.ip6q_next) {
- frag6_remque(q6);
- frag6_insque(q6, &V_ip6q);
+ if (q6 != head->ip6q_next) {
+ frag6_remque(q6, hash);
+ frag6_insque_head(q6, head, hash);
}
#endif
next = 0;
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = af6->ip6af_down) {
if (af6->ip6af_off != next) {
- IP6Q_UNLOCK();
+ if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) {
+ IP6STAT_INC(ip6s_fragdropped);
+ frag6_freef(q6, hash);
+ }
+ IP6Q_UNLOCK(hash);
return IPPROTO_DONE;
}
next += af6->ip6af_frglen;
}
if (af6->ip6af_up->ip6af_mff) {
- IP6Q_UNLOCK();
+ if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) {
+ IP6STAT_INC(ip6s_fragdropped);
+ frag6_freef(q6, hash);
+ }
+ IP6Q_UNLOCK(hash);
return IPPROTO_DONE;
}
@@ -531,7 +618,7 @@ insert:
ip6af = q6->ip6q_down;
t = m = IP6_REASS_MBUF(ip6af);
af6 = ip6af->ip6af_down;
- frag6_deq(ip6af);
+ frag6_deq(ip6af, hash);
while (af6 != (struct ip6asfrag *)q6) {
m->m_pkthdr.csum_flags &=
IP6_REASS_MBUF(af6)->m_pkthdr.csum_flags;
@@ -539,7 +626,7 @@ insert:
IP6_REASS_MBUF(af6)->m_pkthdr.csum_data;
af6dwn = af6->ip6af_down;
- frag6_deq(af6);
+ frag6_deq(af6, hash);
while (t->m_next)
t = t->m_next;
m_adj(IP6_REASS_MBUF(af6), af6->ip6af_offset);
@@ -566,13 +653,13 @@ insert:
#endif
if (ip6_deletefraghdr(m, offset, M_NOWAIT) != 0) {
- frag6_remque(q6);
- V_frag6_nfrags -= q6->ip6q_nfrag;
+ frag6_remque(q6, hash);
+ atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag);
#ifdef MAC
mac_ip6q_destroy(q6);
#endif
free(q6, M_FTABLE);
- V_frag6_nfragpackets--;
+ atomic_subtract_int(&V_frag6_nfragpackets, 1);
goto dropfrag;
}
@@ -583,14 +670,14 @@ insert:
m_copyback(m, ip6_get_prevhdr(m, offset), sizeof(uint8_t),
(caddr_t)&nxt);
- frag6_remque(q6);
- V_frag6_nfrags -= q6->ip6q_nfrag;
+ frag6_remque(q6, hash);
+ atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag);
#ifdef MAC
mac_ip6q_reassemble(q6, m);
mac_ip6q_destroy(q6);
#endif
free(q6, M_FTABLE);
- V_frag6_nfragpackets--;
+ atomic_subtract_int(&V_frag6_nfragpackets, 1);
if (m->m_flags & M_PKTHDR) { /* Isn't it always true? */
int plen = 0;
@@ -612,7 +699,7 @@ insert:
m_tag_prepend(m, mtag);
#endif
- IP6Q_UNLOCK();
+ IP6Q_UNLOCK(hash);
IP6STAT_INC(ip6s_reassembled);
in6_ifstat_inc(dstifp, ifs6_reass_ok);
@@ -634,7 +721,7 @@ insert:
return nxt;
dropfrag:
- IP6Q_UNLOCK();
+ IP6Q_UNLOCK(hash);
in6_ifstat_inc(dstifp, ifs6_reass_fail);
IP6STAT_INC(ip6s_fragdropped);
m_freem(m);
@@ -645,19 +732,19 @@ insert:
* Free a fragment reassembly header and all
* associated datagrams.
*/
-void
-frag6_freef(struct ip6q *q6)
+static void
+frag6_freef(struct ip6q *q6, uint32_t bucket)
{
struct ip6asfrag *af6, *down6;
- IP6Q_LOCK_ASSERT();
+ IP6Q_LOCK_ASSERT(bucket);
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = down6) {
struct mbuf *m = IP6_REASS_MBUF(af6);
down6 = af6->ip6af_down;
- frag6_deq(af6);
+ frag6_deq(af6, bucket);
/*
* Return ICMP time exceeded error for the 1st fragment.
@@ -679,24 +766,25 @@ frag6_freef(struct ip6q *q6)
m_freem(m);
free(af6, M_FTABLE);
}
- frag6_remque(q6);
- V_frag6_nfrags -= q6->ip6q_nfrag;
+ frag6_remque(q6, bucket);
+ atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag);
#ifdef MAC
mac_ip6q_destroy(q6);
#endif
free(q6, M_FTABLE);
- V_frag6_nfragpackets--;
+ atomic_subtract_int(&V_frag6_nfragpackets, 1);
}
/*
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
-void
-frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6)
+static void
+frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6,
+ uint32_t bucket __unused)
{
- IP6Q_LOCK_ASSERT();
+ IP6Q_LOCK_ASSERT(bucket);
af6->ip6af_up = up6;
af6->ip6af_down = up6->ip6af_down;
@@ -707,36 +795,41 @@ frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6)
/*
* To frag6_enq as remque is to insque.
*/
-void
-frag6_deq(struct ip6asfrag *af6)
+static void
+frag6_deq(struct ip6asfrag *af6, uint32_t bucket __unused)
{
- IP6Q_LOCK_ASSERT();
+ IP6Q_LOCK_ASSERT(bucket);
af6->ip6af_up->ip6af_down = af6->ip6af_down;
af6->ip6af_down->ip6af_up = af6->ip6af_up;
}
-void
-frag6_insque(struct ip6q *new, struct ip6q *old)
+static void
+frag6_insque_head(struct ip6q *new, struct ip6q *old, uint32_t bucket)
{
- IP6Q_LOCK_ASSERT();
+ IP6Q_LOCK_ASSERT(bucket);
+ KASSERT(IP6Q_HEAD(bucket) == old,
+ ("%s: attempt to insert at head of wrong bucket"
+ " (bucket=%u, old=%p)", __func__, bucket, old));
new->ip6q_prev = old;
new->ip6q_next = old->ip6q_next;
old->ip6q_next->ip6q_prev= new;
old->ip6q_next = new;
+ V_ip6q[bucket].count++;
}
-void
-frag6_remque(struct ip6q *p6)
+static void
+frag6_remque(struct ip6q *p6, uint32_t bucket)
{
- IP6Q_LOCK_ASSERT();
+ IP6Q_LOCK_ASSERT(bucket);
p6->ip6q_prev->ip6q_next = p6->ip6q_next;
p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
+ V_ip6q[bucket].count--;
}
/*
@@ -748,37 +841,72 @@ void
frag6_slowtimo(void)
{
VNET_ITERATOR_DECL(vnet_iter);
- struct ip6q *q6;
+ struct ip6q *head, *q6;
+ int i;
VNET_LIST_RLOCK_NOSLEEP();
- IP6Q_LOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
- q6 = V_ip6q.ip6q_next;
- if (q6)
- while (q6 != &V_ip6q) {
+ for (i = 0; i < IP6REASS_NHASH; i++) {
+ IP6Q_LOCK(i);
+ head = IP6Q_HEAD(i);
+ q6 = head->ip6q_next;
+ if (q6 == NULL) {
+ /*
+ * XXXJTL: This should never happen. This
+ * should turn into an assertion.
+ */
+ IP6Q_UNLOCK(i);
+ continue;
+ }
+ while (q6 != head) {
--q6->ip6q_ttl;
q6 = q6->ip6q_next;
if (q6->ip6q_prev->ip6q_ttl == 0) {
IP6STAT_INC(ip6s_fragtimeout);
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(q6->ip6q_prev);
+ frag6_freef(q6->ip6q_prev, i);
}
}
+ /*
+ * If we are over the maximum number of fragments
+ * (due to the limit being lowered), drain off
+ * enough to get down to the new limit.
+ * Note that we drain all reassembly queues if
+ * maxfragpackets is 0 (fragmentation is disabled),
+ * and don't enforce a limit when maxfragpackets
+ * is negative.
+ */
+ while ((V_ip6_maxfragpackets == 0 ||
+ (V_ip6_maxfragpackets > 0 &&
+ V_ip6q[i].count > V_ip6_maxfragbucketsize)) &&
+ head->ip6q_prev != head) {
+ IP6STAT_INC(ip6s_fragoverflow);
+ /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
+ frag6_freef(head->ip6q_prev, i);
+ }
+ IP6Q_UNLOCK(i);
+ }
/*
- * If we are over the maximum number of fragments
- * (due to the limit being lowered), drain off
- * enough to get down to the new limit.
+ * If we are still over the maximum number of fragmented
+ * packets, drain off enough to get down to the new limit.
*/
- while (V_frag6_nfragpackets > (u_int)V_ip6_maxfragpackets &&
- V_ip6q.ip6q_prev) {
- IP6STAT_INC(ip6s_fragoverflow);
- /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(V_ip6q.ip6q_prev);
+ i = 0;
+ while (V_ip6_maxfragpackets >= 0 &&
+ atomic_load_int(&V_frag6_nfragpackets) >
+ (u_int)V_ip6_maxfragpackets) {
+ IP6Q_LOCK(i);
+ head = IP6Q_HEAD(i);
+ if (head->ip6q_prev != head) {
+ IP6STAT_INC(ip6s_fragoverflow);
+ /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
+ frag6_freef(head->ip6q_prev, i);
+ }
+ IP6Q_UNLOCK(i);
+ i = (i + 1) % IP6REASS_NHASH;
}
CURVNET_RESTORE();
}
- IP6Q_UNLOCK();
VNET_LIST_RUNLOCK_NOSLEEP();
}
@@ -789,22 +917,25 @@ void
frag6_drain(void)
{
VNET_ITERATOR_DECL(vnet_iter);
+ struct ip6q *head;
+ int i;
VNET_LIST_RLOCK_NOSLEEP();
- if (IP6Q_TRYLOCK() == 0) {
- VNET_LIST_RUNLOCK_NOSLEEP();
- return;
- }
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
- while (V_ip6q.ip6q_next != &V_ip6q) {
- IP6STAT_INC(ip6s_fragdropped);
- /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(V_ip6q.ip6q_next);
+ for (i = 0; i < IP6REASS_NHASH; i++) {
+ if (IP6Q_TRYLOCK(i) == 0)
+ continue;
+ head = IP6Q_HEAD(i);
+ while (head->ip6q_next != head) {
+ IP6STAT_INC(ip6s_fragdropped);
+ /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
+ frag6_freef(head->ip6q_next, i);
+ }
+ IP6Q_UNLOCK(i);
}
CURVNET_RESTORE();
}
- IP6Q_UNLOCK();
VNET_LIST_RUNLOCK_NOSLEEP();
}
diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c
index 4d06ca16..2b080169 100644
--- a/freebsd/sys/netinet6/icmp6.c
+++ b/freebsd/sys/netinet6/icmp6.c
@@ -126,8 +126,8 @@ VNET_PCPUSTAT_SYSUNINIT(icmp6stat);
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
VNET_DECLARE(struct inpcbhead, ripcb);
VNET_DECLARE(int, icmp6errppslim);
-static VNET_DEFINE(int, icmp6errpps_count) = 0;
-static VNET_DEFINE(struct timeval, icmp6errppslim_last);
+VNET_DEFINE_STATIC(int, icmp6errpps_count) = 0;
+VNET_DEFINE_STATIC(struct timeval, icmp6errppslim_last);
VNET_DECLARE(int, icmp6_nodeinfo);
#define V_ripcbinfo VNET(ripcbinfo)
@@ -1910,6 +1910,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
struct inpcb *last = NULL;
struct sockaddr_in6 fromsa;
struct icmp6_hdr *icmp6;
+ struct epoch_tracker et;
struct mbuf *opts = NULL;
#ifndef PULLDOWN_TEST
@@ -1936,8 +1937,8 @@ icmp6_rip6_input(struct mbuf **mp, int off)
return (IPPROTO_DONE);
}
- INP_INFO_RLOCK(&V_ripcbinfo);
- LIST_FOREACH(in6p, &V_ripcb, inp_list) {
+ INP_INFO_RLOCK_ET(&V_ripcbinfo, et);
+ CK_LIST_FOREACH(in6p, &V_ripcb, inp_list) {
if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
if (in6p->inp_ip_p != IPPROTO_ICMPV6)
@@ -2014,7 +2015,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
}
last = in6p;
}
- INP_INFO_RUNLOCK(&V_ripcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
if (last != NULL) {
if (last->inp_flags & INP_CONTROLOPTS)
ip6_savecontrol(last, m, &opts);
diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c
index 3ed80c9c..c415cf78 100644
--- a/freebsd/sys/netinet6/in6.c
+++ b/freebsd/sys/netinet6/in6.c
@@ -2139,9 +2139,6 @@ in6_lltable_free_entry(struct lltable *llt, struct llentry *lle)
lltable_unlink_entry(llt, lle);
}
- if (callout_stop(&lle->lle_timer) > 0)
- LLE_REMREF(lle);
-
llentry_free(lle);
}
diff --git a/freebsd/sys/netinet6/in6_fib.c b/freebsd/sys/netinet6/in6_fib.c
index cf79797d..e5e8a161 100644
--- a/freebsd/sys/netinet6/in6_fib.c
+++ b/freebsd/sys/netinet6/in6_fib.c
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
-#include <sys/rwlock.h>
+#include <sys/rmlock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
@@ -173,6 +173,7 @@ int
fib6_lookup_nh_basic(uint32_t fibnum, const struct in6_addr *dst, uint32_t scopeid,
uint32_t flags, uint32_t flowid, struct nhop6_basic *pnh6)
{
+ RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
struct sockaddr_in6 sin6;
@@ -222,6 +223,7 @@ int
fib6_lookup_nh_ext(uint32_t fibnum, const struct in6_addr *dst,uint32_t scopeid,
uint32_t flags, uint32_t flowid, struct nhop6_extended *pnh6)
{
+ RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
struct sockaddr_in6 sin6;
diff --git a/freebsd/sys/netinet6/in6_gif.c b/freebsd/sys/netinet6/in6_gif.c
index 160a0929..66b4c63a 100644
--- a/freebsd/sys/netinet6/in6_gif.c
+++ b/freebsd/sys/netinet6/in6_gif.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,20 +41,19 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_inet6.h>
#include <sys/param.h>
-#include <sys/lock.h>
-#include <sys/rmlock.h>
#include <sys/systm.h>
+#include <sys/jail.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/kernel.h>
-#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
-#include <sys/protosw.h>
#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
@@ -63,52 +63,189 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_systm.h>
#ifdef INET
#include <netinet/ip.h>
+#include <netinet/ip_ecn.h>
#endif
#include <netinet/ip_encap.h>
-#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_var.h>
-#endif
-#include <netinet/ip_ecn.h>
-#ifdef INET6
+#include <netinet6/scope6_var.h>
#include <netinet6/ip6_ecn.h>
#include <netinet6/in6_fib.h>
-#endif
#include <net/if_gif.h>
#define GIF_HLIM 30
-static VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
+VNET_DEFINE_STATIC(int, ip6_gif_hlim) = GIF_HLIM;
#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
SYSCTL_DECL(_net_inet6_ip6);
-SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip6_gif_hlim), 0, "");
-
-static int in6_gif_input(struct mbuf **, int *, int);
-
-extern struct domain inet6domain;
-static struct protosw in6_gif_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = 0, /* IPPROTO_IPV[46] */
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = in6_gif_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
+SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_gif_hlim), 0,
+ "Default hop limit for encapsulated packets");
+
+/*
+ * We keep interfaces in a hash table using src+dst as key.
+ * Interfaces with GIF_IGNORE_SOURCE flag are linked into plain list.
+ */
+VNET_DEFINE_STATIC(struct gif_list *, ipv6_hashtbl) = NULL;
+VNET_DEFINE_STATIC(struct gif_list, ipv6_list) = CK_LIST_HEAD_INITIALIZER();
+#define V_ipv6_hashtbl VNET(ipv6_hashtbl)
+#define V_ipv6_list VNET(ipv6_list)
+
+#define GIF_HASH(src, dst) (V_ipv6_hashtbl[\
+ in6_gif_hashval((src), (dst)) & (GIF_HASH_SIZE - 1)])
+#define GIF_HASH_SC(sc) GIF_HASH(&(sc)->gif_ip6hdr->ip6_src,\
+ &(sc)->gif_ip6hdr->ip6_dst)
+static uint32_t
+in6_gif_hashval(const struct in6_addr *src, const struct in6_addr *dst)
+{
+ uint32_t ret;
+
+ ret = fnv_32_buf(src, sizeof(*src), FNV1_32_INIT);
+ return (fnv_32_buf(dst, sizeof(*dst), ret));
+}
+
+static int
+in6_gif_checkdup(const struct gif_softc *sc, const struct in6_addr *src,
+ const struct in6_addr *dst)
+{
+ struct gif_softc *tmp;
+
+ if (sc->gif_family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_src, src) &&
+ IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_dst, dst))
+ return (EEXIST);
+
+ CK_LIST_FOREACH(tmp, &GIF_HASH(src, dst), chain) {
+ if (tmp == sc)
+ continue;
+ if (IN6_ARE_ADDR_EQUAL(&tmp->gif_ip6hdr->ip6_src, src) &&
+ IN6_ARE_ADDR_EQUAL(&tmp->gif_ip6hdr->ip6_dst, dst))
+ return (EADDRNOTAVAIL);
+ }
+ return (0);
+}
+
+static void
+in6_gif_attach(struct gif_softc *sc)
+{
+
+ if (sc->gif_options & GIF_IGNORE_SOURCE)
+ CK_LIST_INSERT_HEAD(&V_ipv6_list, sc, chain);
+ else
+ CK_LIST_INSERT_HEAD(&GIF_HASH_SC(sc), sc, chain);
+}
+
+int
+in6_gif_setopts(struct gif_softc *sc, u_int options)
+{
+
+ /* NOTE: we are protected with gif_ioctl_sx lock */
+ MPASS(sc->gif_family == AF_INET6);
+ MPASS(sc->gif_options != options);
+
+ if ((options & GIF_IGNORE_SOURCE) !=
+ (sc->gif_options & GIF_IGNORE_SOURCE)) {
+ CK_LIST_REMOVE(sc, chain);
+ sc->gif_options = options;
+ in6_gif_attach(sc);
+ }
+ return (0);
+}
+
+int
+in6_gif_ioctl(struct gif_softc *sc, u_long cmd, caddr_t data)
+{
+ struct in6_ifreq *ifr = (struct in6_ifreq *)data;
+ struct sockaddr_in6 *dst, *src;
+ struct ip6_hdr *ip6;
+ int error;
+
+ /* NOTE: we are protected with gif_ioctl_sx lock */
+ error = EINVAL;
+ switch (cmd) {
+ case SIOCSIFPHYADDR_IN6:
+ src = &((struct in6_aliasreq *)data)->ifra_addr;
+ dst = &((struct in6_aliasreq *)data)->ifra_dstaddr;
+
+ /* sanity checks */
+ if (src->sin6_family != dst->sin6_family ||
+ src->sin6_family != AF_INET6 ||
+ src->sin6_len != dst->sin6_len ||
+ src->sin6_len != sizeof(*src))
+ break;
+ if (IN6_IS_ADDR_UNSPECIFIED(&src->sin6_addr) ||
+ IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ /*
+ * Check validity of the scope zone ID of the
+ * addresses, and convert it into the kernel
+ * internal form if necessary.
+ */
+ if ((error = sa6_embedscope(src, 0)) != 0 ||
+ (error = sa6_embedscope(dst, 0)) != 0)
+ break;
+
+ if (V_ipv6_hashtbl == NULL)
+ V_ipv6_hashtbl = gif_hashinit();
+ error = in6_gif_checkdup(sc, &src->sin6_addr,
+ &dst->sin6_addr);
+ if (error == EADDRNOTAVAIL)
+ break;
+ if (error == EEXIST) {
+ /* Addresses are the same. Just return. */
+ error = 0;
+ break;
+ }
+ ip6 = malloc(sizeof(*ip6), M_GIF, M_WAITOK | M_ZERO);
+ ip6->ip6_src = src->sin6_addr;
+ ip6->ip6_dst = dst->sin6_addr;
+ ip6->ip6_vfc = IPV6_VERSION;
+ if (sc->gif_family != 0) {
+ /* Detach existing tunnel first */
+ CK_LIST_REMOVE(sc, chain);
+ GIF_WAIT();
+ free(sc->gif_hdr, M_GIF);
+ /* XXX: should we notify about link state change? */
+ }
+ sc->gif_family = AF_INET6;
+ sc->gif_ip6hdr = ip6;
+ in6_gif_attach(sc);
+ break;
+ case SIOCGIFPSRCADDR_IN6:
+ case SIOCGIFPDSTADDR_IN6:
+ if (sc->gif_family != AF_INET6) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ src = (struct sockaddr_in6 *)&ifr->ifr_addr;
+ memset(src, 0, sizeof(*src));
+ src->sin6_family = AF_INET6;
+ src->sin6_len = sizeof(*src);
+ src->sin6_addr = (cmd == SIOCGIFPSRCADDR_IN6) ?
+ sc->gif_ip6hdr->ip6_src: sc->gif_ip6hdr->ip6_dst;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)src);
+ if (error == 0)
+ error = sa6_recoverscope(src);
+ if (error != 0)
+ memset(src, 0, sizeof(*src));
+ break;
+ }
+ return (error);
+}
int
in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
{
- GIF_RLOCK_TRACKER;
struct gif_softc *sc = ifp->if_softc;
struct ip6_hdr *ip6;
int len;
/* prepend new IP header */
+ MPASS(in_epoch(net_epoch_preempt));
len = sizeof(struct ip6_hdr);
#ifndef __NO_STRICT_ALIGNMENT
if (proto == IPPROTO_ETHERIP)
@@ -128,14 +265,8 @@ in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
#endif
ip6 = mtod(m, struct ip6_hdr *);
- GIF_RLOCK(sc);
- if (sc->gif_family != AF_INET6) {
- m_freem(m);
- GIF_RUNLOCK(sc);
- return (ENETDOWN);
- }
+ MPASS(sc->gif_family == AF_INET6);
bcopy(sc->gif_ip6hdr, ip6, sizeof(struct ip6_hdr));
- GIF_RUNLOCK(sc);
ip6->ip6_flow |= htonl((uint32_t)ecn << 20);
ip6->ip6_nxt = proto;
@@ -149,15 +280,14 @@ in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
}
static int
-in6_gif_input(struct mbuf **mp, int *offp, int proto)
+in6_gif_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct mbuf *m = *mp;
+ struct gif_softc *sc = arg;
struct ifnet *gifp;
- struct gif_softc *sc;
struct ip6_hdr *ip6;
uint8_t ecn;
- sc = encap_getarg(m);
+ MPASS(in_epoch(net_epoch_preempt));
if (sc == NULL) {
m_freem(m);
IP6STAT_INC(ip6s_nogif);
@@ -167,7 +297,7 @@ in6_gif_input(struct mbuf **mp, int *offp, int proto)
if ((gifp->if_flags & IFF_UP) != 0) {
ip6 = mtod(m, struct ip6_hdr *);
ecn = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
- m_adj(m, *offp);
+ m_adj(m, off);
gif_input(m, gifp, proto, ecn);
} else {
m_freem(m);
@@ -176,59 +306,126 @@ in6_gif_input(struct mbuf **mp, int *offp, int proto)
return (IPPROTO_DONE);
}
-/*
- * we know that we are in IFF_UP, outer address available, and outer family
- * matched the physical addr family. see gif_encapcheck().
- */
-int
-in6_gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+static int
+in6_gif_lookup(const struct mbuf *m, int off, int proto, void **arg)
{
const struct ip6_hdr *ip6;
struct gif_softc *sc;
int ret;
- /* sanity check done in caller */
- sc = (struct gif_softc *)arg;
- GIF_RLOCK_ASSERT(sc);
+ if (V_ipv6_hashtbl == NULL)
+ return (0);
+ MPASS(in_epoch(net_epoch_preempt));
/*
- * Check for address match. Note that the check is for an incoming
- * packet. We should compare the *source* address in our configuration
- * and the *destination* address of the packet, and vice versa.
+ * NOTE: it is safe to iterate without any locking here, because softc
+ * can be reclaimed only when we are not within net_epoch_preempt
+ * section, but ip_encap lookup+input are executed in epoch section.
*/
ip6 = mtod(m, const struct ip6_hdr *);
- if (!IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_src, &ip6->ip6_dst))
+ ret = 0;
+ CK_LIST_FOREACH(sc, &GIF_HASH(&ip6->ip6_dst, &ip6->ip6_src), chain) {
+ /*
+ * This is an inbound packet, its ip6_dst is source address
+ * in softc.
+ */
+ if (IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_src,
+ &ip6->ip6_dst) &&
+ IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_dst,
+ &ip6->ip6_src)) {
+ ret = ENCAP_DRV_LOOKUP;
+ goto done;
+ }
+ }
+ /*
+ * No exact match.
+ * Check the list of interfaces with GIF_IGNORE_SOURCE flag.
+ */
+ CK_LIST_FOREACH(sc, &V_ipv6_list, chain) {
+ if (IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_src,
+ &ip6->ip6_dst)) {
+ ret = 128 + 8; /* src + proto */
+ goto done;
+ }
+ }
+ return (0);
+done:
+ if ((GIF2IFP(sc)->if_flags & IFF_UP) == 0)
return (0);
- ret = 128;
- if (!IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_dst, &ip6->ip6_src)) {
- if ((sc->gif_options & GIF_IGNORE_SOURCE) == 0)
- return (0);
- } else
- ret += 128;
-
/* ingress filters on outer source */
if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0) {
struct nhop6_basic nh6;
- /* XXX empty scope id */
- if (fib6_lookup_nh_basic(sc->gif_fibnum, &ip6->ip6_src, 0, 0, 0,
- &nh6) != 0)
+ if (fib6_lookup_nh_basic(sc->gif_fibnum, &ip6->ip6_src,
+ ntohs(in6_getscope(&ip6->ip6_src)), 0, 0, &nh6) != 0)
return (0);
if (nh6.nh_ifp != m->m_pkthdr.rcvif)
return (0);
}
+ *arg = sc;
return (ret);
}
-int
-in6_gif_attach(struct gif_softc *sc)
+static struct {
+ const struct encap_config encap;
+ const struct encaptab *cookie;
+} ipv6_encap_cfg[] = {
+#ifdef INET
+ {
+ .encap = {
+ .proto = IPPROTO_IPV4,
+ .min_length = sizeof(struct ip6_hdr) +
+ sizeof(struct ip),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in6_gif_lookup,
+ .input = in6_gif_input
+ },
+ },
+#endif
+ {
+ .encap = {
+ .proto = IPPROTO_IPV6,
+ .min_length = 2 * sizeof(struct ip6_hdr),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in6_gif_lookup,
+ .input = in6_gif_input
+ },
+ },
+ {
+ .encap = {
+ .proto = IPPROTO_ETHERIP,
+ .min_length = sizeof(struct ip6_hdr) +
+ sizeof(struct etherip_header) +
+ sizeof(struct ether_header),
+ .exact_match = ENCAP_DRV_LOOKUP,
+ .lookup = in6_gif_lookup,
+ .input = in6_gif_input
+ },
+ }
+};
+
+void
+in6_gif_init(void)
{
+ int i;
- KASSERT(sc->gif_ecookie == NULL, ("gif_ecookie isn't NULL"));
- sc->gif_ecookie = encap_attach_func(AF_INET6, -1, gif_encapcheck,
- (void *)&in6_gif_protosw, sc);
- if (sc->gif_ecookie == NULL)
- return (EEXIST);
- return (0);
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+ for (i = 0; i < nitems(ipv6_encap_cfg); i++)
+ ipv6_encap_cfg[i].cookie = ip6_encap_attach(
+ &ipv6_encap_cfg[i].encap, NULL, M_WAITOK);
+}
+
+void
+in6_gif_uninit(void)
+{
+ int i;
+
+ if (IS_DEFAULT_VNET(curvnet)) {
+ for (i = 0; i < nitems(ipv6_encap_cfg); i++)
+ ip6_encap_detach(ipv6_encap_cfg[i].cookie);
+ }
+ if (V_ipv6_hashtbl != NULL)
+ gif_hashdestroy(V_ipv6_hashtbl);
}
diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c
index 81182b4e..1cab31d1 100644
--- a/freebsd/sys/netinet6/in6_ifattach.c
+++ b/freebsd/sys/netinet6/in6_ifattach.c
@@ -759,7 +759,6 @@ _in6_ifdetach(struct ifnet *ifp, int purgeulp)
/*
* nuke any of IPv6 addresses we have
- * XXX: all addresses should be already removed
*/
CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
if (ifa->ifa_addr->sa_family != AF_INET6)
@@ -874,6 +873,7 @@ in6_purgemaddrs(struct ifnet *ifp)
ifma->ifma_protospec == NULL)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
+ in6m_disconnect(inm);
in6m_rele_locked(&purgeinms, inm);
if (__predict_false(ifma6_restart)) {
ifma6_restart = false;
diff --git a/freebsd/sys/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c
index 32660c89..3824645d 100644
--- a/freebsd/sys/netinet6/in6_mcast.c
+++ b/freebsd/sys/netinet6/in6_mcast.c
@@ -540,6 +540,8 @@ in6m_release(struct in6_multi *inm)
CTR2(KTR_MLD, "%s: purging ifma %p", __func__, ifma);
KASSERT(ifma->ifma_protospec == NULL,
("%s: ifma_protospec != NULL", __func__));
+ if (ifp == NULL)
+ ifp = ifma->ifma_ifp;
if (ifp != NULL) {
CURVNET_SET(ifp->if_vnet);
@@ -564,8 +566,13 @@ static void in6m_init(void)
taskqgroup_config_gtask_init(NULL, &free_gtask, in6m_release_task, "in6m release task");
}
+#ifdef EARLY_AP_STARTUP
SYSINIT(in6m_init, SI_SUB_SMP + 1, SI_ORDER_FIRST,
in6m_init, NULL);
+#else
+SYSINIT(in6m_init, SI_SUB_ROOT_CONF - 1, SI_ORDER_SECOND,
+ in6m_init, NULL);
+#endif
void
@@ -589,11 +596,20 @@ in6m_disconnect(struct in6_multi *inm)
struct ifmultiaddr *ifma, *ll_ifma;
ifp = inm->in6m_ifp;
+
+ if (ifp == NULL)
+ return;
+ inm->in6m_ifp = NULL;
IF_ADDR_WLOCK_ASSERT(ifp);
ifma = inm->in6m_ifma;
+ if (ifma == NULL)
+ return;
if_ref(ifp);
- CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
+ if (ifma->ifma_flags & IFMA_F_ENQUEUED) {
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
+ ifma->ifma_flags &= ~IFMA_F_ENQUEUED;
+ }
MCDPRINTF("removed ifma: %p from %s\n", ifma, ifp->if_xname);
if ((ll_ifma = ifma->ifma_llifma) != NULL) {
MPASS(ifma != ll_ifma);
@@ -602,7 +618,10 @@ in6m_disconnect(struct in6_multi *inm)
MPASS(ll_ifma->ifma_ifp == ifp);
if (--ll_ifma->ifma_refcount == 0) {
ifma6_restart = true;
- CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr, ifma_link);
+ if (ll_ifma->ifma_flags & IFMA_F_ENQUEUED) {
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr, ifma_link);
+ ll_ifma->ifma_flags &= ~IFMA_F_ENQUEUED;
+ }
MCDPRINTF("removed ll_ifma: %p from %s\n", ll_ifma, ifp->if_xname);
if_freemulti(ll_ifma);
}
@@ -629,7 +648,7 @@ in6m_release_deferred(struct in6_multi *inm)
IN6_MULTI_LIST_LOCK_ASSERT();
KASSERT(inm->in6m_refcount > 0, ("refcount == %d inm: %p", inm->in6m_refcount, inm));
if (--inm->in6m_refcount == 0) {
- in6m_disconnect(inm);
+ MPASS(inm->in6m_ifp == NULL);
SLIST_INIT(&tmp);
inm->in6m_ifma->ifma_protospec = NULL;
MPASS(inm->in6m_ifma->ifma_llifma == NULL);
@@ -1307,6 +1326,7 @@ out_in6m_release:
break;
}
}
+ in6m_disconnect(inm);
in6m_release_deferred(inm);
IF_ADDR_RUNLOCK(ifp);
} else {
@@ -1386,13 +1406,17 @@ in6_leavegroup_locked(struct in6_multi *inm, /*const*/ struct in6_mfilter *imf)
KASSERT(error == 0, ("%s: failed to merge inm state", __func__));
CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
- error = mld_change_state(inm, 0);
+ error = 0;
+ if (ifp)
+ error = mld_change_state(inm, 0);
if (error)
CTR1(KTR_MLD, "%s: failed mld downcall", __func__);
CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm);
if (ifp)
IF_ADDR_WLOCK(ifp);
+ if (inm->in6m_refcount == 1 && inm->in6m_ifp != NULL)
+ in6m_disconnect(inm);
in6m_release_deferred(inm);
if (ifp)
IF_ADDR_WUNLOCK(ifp);
@@ -1626,16 +1650,13 @@ in6p_findmoptions(struct inpcb *inp)
*/
static void
-inp_gcmoptions(epoch_context_t ctx)
+inp_gcmoptions(struct ip6_moptions *imo)
{
- struct ip6_moptions *imo;
struct in6_mfilter *imf;
struct in6_multi *inm;
struct ifnet *ifp;
size_t idx, nmships;
- imo = __containerof(ctx, struct ip6_moptions, imo6_epoch_ctx);
-
nmships = imo->im6o_num_memberships;
for (idx = 0; idx < nmships; ++idx) {
imf = imo->im6o_mfilters ? &imo->im6o_mfilters[idx] : NULL;
@@ -1665,7 +1686,7 @@ ip6_freemoptions(struct ip6_moptions *imo)
{
if (imo == NULL)
return;
- epoch_call(net_epoch_preempt, &imo->imo6_epoch_ctx, inp_gcmoptions);
+ inp_gcmoptions(imo);
}
/*
@@ -2159,6 +2180,7 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
IN6_MULTI_UNLOCK();
goto out_im6o_free;
}
+ in6m_acquire(inm);
imo->im6o_membership[idx] = inm;
} else {
CTR1(KTR_MLD, "%s: merge inm state", __func__);
@@ -2193,6 +2215,12 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
out_im6o_free:
if (error && is_new) {
+ inm = imo->im6o_membership[idx];
+ if (inm != NULL) {
+ IN6_MULTI_LIST_LOCK();
+ in6m_release_deferred(inm);
+ IN6_MULTI_LIST_UNLOCK();
+ }
imo->im6o_membership[idx] = NULL;
--imo->im6o_num_memberships;
}
diff --git a/freebsd/sys/netinet6/in6_pcb.c b/freebsd/sys/netinet6/in6_pcb.c
index 488cca86..a30cb98b 100644
--- a/freebsd/sys/netinet6/in6_pcb.c
+++ b/freebsd/sys/netinet6/in6_pcb.c
@@ -131,6 +131,12 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam,
int error, lookupflags = 0;
int reuseport = (so->so_options & SO_REUSEPORT);
+ /*
+ * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here
+ * so that we don't have to add to the (already messy) code below.
+ */
+ int reuseport_lb = (so->so_options & SO_REUSEPORT_LB);
+
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(pcbinfo);
@@ -138,7 +144,7 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam,
return (EADDRNOTAVAIL);
if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
return (EINVAL);
- if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
+ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0)
lookupflags = INPLOOKUP_WILDCARD;
if (nam == NULL) {
if ((error = prison_local_ip6(cred, &inp->in6p_laddr,
@@ -172,6 +178,13 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam,
*/
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0)
reuseport = SO_REUSEADDR|SO_REUSEPORT;
+ /*
+ * XXX: How to deal with SO_REUSEPORT_LB here?
+ * Treat same as SO_REUSEPORT for now.
+ */
+ if ((so->so_options &
+ (SO_REUSEADDR|SO_REUSEPORT_LB)) != 0)
+ reuseport_lb = SO_REUSEADDR|SO_REUSEPORT_LB;
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
struct ifaddr *ifa;
@@ -221,7 +234,8 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam,
IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
- (t->inp_flags2 & INP_REUSEPORT) == 0) &&
+ (t->inp_flags2 & INP_REUSEPORT) ||
+ (t->inp_flags2 & INP_REUSEPORT_LB) == 0) &&
#ifndef __rtems__
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
@@ -279,9 +293,11 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam,
*/
tw = intotw(t);
if (tw == NULL ||
- (reuseport & tw->tw_so_options) == 0)
+ ((reuseport & tw->tw_so_options) == 0 &&
+ (reuseport_lb & tw->tw_so_options) == 0))
return (EADDRINUSE);
- } else if (t && (reuseport & inp_so_options(t)) == 0) {
+ } else if (t && (reuseport & inp_so_options(t)) == 0 &&
+ (reuseport_lb & inp_so_options(t)) == 0) {
return (EADDRINUSE);
}
#ifdef INET
@@ -291,22 +307,25 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam,
in6_sin6_2_sin(&sin, sin6);
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
- lport, lookupflags, cred);
+ lport, lookupflags, cred);
if (t && t->inp_flags & INP_TIMEWAIT) {
tw = intotw(t);
if (tw == NULL)
return (EADDRINUSE);
if ((reuseport & tw->tw_so_options) == 0
+ && (reuseport_lb & tw->tw_so_options) == 0
&& (ntohl(t->inp_laddr.s_addr) !=
- INADDR_ANY || ((inp->inp_vflag &
- INP_IPV6PROTO) ==
- (t->inp_vflag & INP_IPV6PROTO))))
+ INADDR_ANY || ((inp->inp_vflag &
+ INP_IPV6PROTO) ==
+ (t->inp_vflag & INP_IPV6PROTO))))
return (EADDRINUSE);
} else if (t &&
(reuseport & inp_so_options(t)) == 0 &&
+ (reuseport_lb & inp_so_options(t)) == 0 &&
(ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
- (t->inp_vflag & INP_IPV6PROTO) != 0))
+ (t->inp_vflag & INP_IPV6PROTO) != 0)) {
return (EADDRINUSE);
+ }
}
#endif
}
@@ -644,7 +663,7 @@ in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
}
errno = inet6ctlerrmap[cmd];
INP_INFO_WLOCK(pcbinfo);
- LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
+ CK_LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
INP_WLOCK(inp);
if ((inp->inp_vflag & INP_IPV6) == 0) {
INP_WUNLOCK(inp);
@@ -721,7 +740,7 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(
INP6_PCBHASHKEY(&in6addr_any), lport, 0,
pcbinfo->ipi_hashmask)];
- LIST_FOREACH(inp, head, inp_hash) {
+ CK_LIST_FOREACH(inp, head, inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -751,7 +770,7 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
*/
porthash = &pcbinfo->ipi_porthashbase[INP_PCBPORTHASH(lport,
pcbinfo->ipi_porthashmask)];
- LIST_FOREACH(phd, porthash, phd_hash) {
+ CK_LIST_FOREACH(phd, porthash, phd_hash) {
if (phd->phd_port == lport)
break;
}
@@ -760,7 +779,7 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
* Port is in use by one or more PCBs. Look for best
* fit.
*/
- LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
+ CK_LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
wildcard = 0;
if (cred != NULL &&
!prison_equal_ip6(cred->cr_prison,
@@ -802,7 +821,7 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
int i, gap;
INP_INFO_WLOCK(pcbinfo);
- LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
+ CK_LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
INP_WLOCK(in6p);
im6o = in6p->in6p_moptions;
if ((in6p->inp_vflag & INP_IPV6) && im6o != NULL) {
@@ -841,16 +860,10 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
* (by a redirect), time to try a default gateway again.
*/
void
-in6_losing(struct inpcb *in6p)
+in6_losing(struct inpcb *inp)
{
- if (in6p->inp_route6.ro_rt) {
- RTFREE(in6p->inp_route6.ro_rt);
- in6p->inp_route6.ro_rt = (struct rtentry *)NULL;
- }
- if (in6p->inp_route.ro_lle)
- LLE_FREE(in6p->inp_route.ro_lle); /* zeros ro_lle */
- return;
+ RO_INVALIDATE_CACHE(&inp->inp_route6);
}
/*
@@ -858,18 +871,67 @@ in6_losing(struct inpcb *in6p)
* and allocate a (hopefully) better one.
*/
struct inpcb *
-in6_rtchange(struct inpcb *inp, int errno)
+in6_rtchange(struct inpcb *inp, int errno __unused)
{
- if (inp->inp_route6.ro_rt) {
- RTFREE(inp->inp_route6.ro_rt);
- inp->inp_route6.ro_rt = (struct rtentry *)NULL;
- }
- if (inp->inp_route.ro_lle)
- LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */
+ RO_INVALIDATE_CACHE(&inp->inp_route6);
return inp;
}
+static struct inpcb *
+in6_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo,
+ const struct in6_addr *laddr, uint16_t lport, const struct in6_addr *faddr,
+ uint16_t fport, int lookupflags)
+{
+ struct inpcb *local_wild = NULL;
+ const struct inpcblbgrouphead *hdr;
+ struct inpcblbgroup *grp;
+ struct inpcblbgroup *grp_local_wild;
+ uint32_t idx;
+
+ INP_HASH_LOCK_ASSERT(pcbinfo);
+
+ hdr = &pcbinfo->ipi_lbgrouphashbase[INP_PCBLBGROUP_PORTHASH(
+ lport, pcbinfo->ipi_lbgrouphashmask)];
+
+ /*
+ * Order of socket selection:
+ * 1. non-wild.
+ * 2. wild (if lookupflags contains INPLOOKUP_WILDCARD).
+ *
+ * NOTE:
+ * - Load balanced group does not contain jailed sockets.
+ * - Load balanced does not contain IPv4 mapped INET6 wild sockets.
+ */
+ CK_LIST_FOREACH(grp, hdr, il_list) {
+#ifdef INET
+ if (!(grp->il_vflag & INP_IPV6))
+ continue;
+#endif
+ if (grp->il_lport == lport) {
+ idx = 0;
+ int pkt_hash = INP_PCBLBGROUP_PKTHASH(
+ INP6_PCBHASHKEY(faddr), lport, fport);
+
+ idx = pkt_hash % grp->il_inpcnt;
+
+ if (IN6_ARE_ADDR_EQUAL(&grp->il6_laddr, laddr)) {
+ return (grp->il_inp[idx]);
+ } else {
+ if (IN6_IS_ADDR_UNSPECIFIED(&grp->il6_laddr) &&
+ (lookupflags & INPLOOKUP_WILDCARD)) {
+ local_wild = grp->il_inp[idx];
+ grp_local_wild = grp;
+ }
+ }
+ }
+ }
+ if (local_wild != NULL) {
+ return (local_wild);
+ }
+ return (NULL);
+}
+
#ifdef PCBGROUP
/*
* Lookup PCB in hash list, using pcbgroup tables.
@@ -891,7 +953,7 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
INP_GROUP_LOCK(pcbgroup);
head = &pcbgroup->ipg_hashbase[INP_PCBHASH(
INP6_PCBHASHKEY(faddr), lport, fport, pcbgroup->ipg_hashmask)];
- LIST_FOREACH(inp, head, inp_pcbgrouphash) {
+ CK_LIST_FOREACH(inp, head, inp_pcbgrouphash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -932,7 +994,7 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
*/
head = &pcbgroup->ipg_hashbase[
INP_PCBHASH(INADDR_ANY, lport, 0, pcbgroup->ipg_hashmask)];
- LIST_FOREACH(inp, head, inp_pcbgrouphash) {
+ CK_LIST_FOREACH(inp, head, inp_pcbgrouphash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -994,7 +1056,7 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
head = &pcbinfo->ipi_wildbase[INP_PCBHASH(
INP6_PCBHASHKEY(&in6addr_any), lport, 0,
pcbinfo->ipi_wildmask)];
- LIST_FOREACH(inp, head, inp_pcbgroup_wild) {
+ CK_LIST_FOREACH(inp, head, inp_pcbgroup_wild) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -1094,7 +1156,7 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
tmpinp = NULL;
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(
INP6_PCBHASHKEY(faddr), lport, fport, pcbinfo->ipi_hashmask)];
- LIST_FOREACH(inp, head, inp_hash) {
+ CK_LIST_FOREACH(inp, head, inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -1117,6 +1179,18 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
return (tmpinp);
/*
+ * Then look in lb group (for wildcard match).
+ */
+ if (pcbinfo->ipi_lbgrouphashbase != NULL &&
+ (lookupflags & INPLOOKUP_WILDCARD)) {
+ inp = in6_pcblookup_lbgroup(pcbinfo, laddr, lport, faddr,
+ fport, lookupflags);
+ if (inp != NULL) {
+ return (inp);
+ }
+ }
+
+ /*
* Then look for a wildcard match, if requested.
*/
if ((lookupflags & INPLOOKUP_WILDCARD) != 0) {
@@ -1134,7 +1208,7 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(
INP6_PCBHASHKEY(&in6addr_any), lport, 0,
pcbinfo->ipi_hashmask)];
- LIST_FOREACH(inp, head, inp_hash) {
+ CK_LIST_FOREACH(inp, head, inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
@@ -1192,40 +1266,35 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
struct ifnet *ifp)
{
struct inpcb *inp;
- bool locked;
INP_HASH_RLOCK(pcbinfo);
inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
(lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
if (inp != NULL) {
- if (lookupflags & INPLOOKUP_WLOCKPCB)
- locked = INP_TRY_WLOCK(inp);
- else if (lookupflags & INPLOOKUP_RLOCKPCB)
- locked = INP_TRY_RLOCK(inp);
- else
- panic("%s: locking bug", __func__);
- if (!locked)
- in_pcbref(inp);
- INP_HASH_RUNLOCK(pcbinfo);
- if (!locked) {
- if (lookupflags & INPLOOKUP_WLOCKPCB) {
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (NULL);
- } else {
- INP_RLOCK(inp);
- if (in_pcbrele_rlocked(inp))
- return (NULL);
+ if (lookupflags & INPLOOKUP_WLOCKPCB) {
+ INP_WLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_WUNLOCK(inp);
+ inp = NULL;
}
- }
+ } else if (lookupflags & INPLOOKUP_RLOCKPCB) {
+ INP_RLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_RUNLOCK(inp);
+ inp = NULL;
+ }
+ } else
+ panic("%s: locking bug", __func__);
#ifdef INVARIANTS
- if (lookupflags & INPLOOKUP_WLOCKPCB)
- INP_WLOCK_ASSERT(inp);
- else
- INP_RLOCK_ASSERT(inp);
+ if (inp != NULL) {
+ if (lookupflags & INPLOOKUP_WLOCKPCB)
+ INP_WLOCK_ASSERT(inp);
+ else
+ INP_RLOCK_ASSERT(inp);
+ }
#endif
- } else
- INP_HASH_RUNLOCK(pcbinfo);
+ }
+ INP_HASH_RUNLOCK(pcbinfo);
return (inp);
}
diff --git a/freebsd/sys/netinet6/in6_proto.c b/freebsd/sys/netinet6/in6_proto.c
index 756ea48b..cf62e60c 100644
--- a/freebsd/sys/netinet6/in6_proto.c
+++ b/freebsd/sys/netinet6/in6_proto.c
@@ -173,7 +173,7 @@ struct protosw inet6sw[] = {
.pr_type = SOCK_STREAM,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_TCP,
- .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN,
+ .pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|PR_LISTEN,
.pr_input = tcp6_input,
.pr_ctlinput = tcp6_ctlinput,
.pr_ctloutput = tcp_ctloutput,
@@ -387,7 +387,9 @@ VNET_DEFINE(int, ip6_no_radr) = 0;
VNET_DEFINE(int, ip6_norbit_raif) = 0;
VNET_DEFINE(int, ip6_rfc6204w3) = 0;
VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */
-VNET_DEFINE(int, ip6_maxfrags); /* initialized in frag6.c:frag6_init() */
+int ip6_maxfrags; /* initialized in frag6.c:frag6_init() */
+VNET_DEFINE(int, ip6_maxfragbucketsize);/* initialized in frag6.c:frag6_init() */
+VNET_DEFINE(int, ip6_maxfragsperpacket); /* initialized in frag6.c:frag6_init() */
VNET_DEFINE(int, ip6_log_interval) = 5;
VNET_DEFINE(int, ip6_hdrnestlimit) = 15;/* How many header options will we
* process? */
@@ -474,6 +476,20 @@ sysctl_ip6_tempvltime(SYSCTL_HANDLER_ARGS)
return (0);
}
+static int
+sysctl_ip6_maxfragpackets(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+
+ val = V_ip6_maxfragpackets;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || !req->newptr)
+ return (error);
+ V_ip6_maxfragpackets = val;
+ frag6_set_bucketsize();
+ return (0);
+}
+
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_FORWARDING, forwarding,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_forwarding), 0,
"Enable forwarding of IPv6 packets between interfaces");
@@ -486,8 +502,9 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFHLIM, hlim,
SYSCTL_VNET_PCPUSTAT(_net_inet6_ip6, IPV6CTL_STATS, stats, struct ip6stat,
ip6stat,
"IP6 statistics (struct ip6stat, netinet6/ip6_var.h)");
-SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragpackets), 0,
+SYSCTL_PROC(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets,
+ CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
+ sysctl_ip6_maxfragpackets, "I",
"Default maximum number of outstanding fragmented IPv6 packets. "
"A value of 0 means no fragmented packets will be accepted, while a "
"a value of -1 means no limit");
@@ -561,8 +578,16 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USE_DEFAULTZONE, use_defaultzone,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_use_defzone), 0,
"Use the default scope zone when none is specified");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGS, maxfrags,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfrags), 0,
- "Maximum allowed number of outstanding IPv6 packet fragments");
+ CTLFLAG_RW, &ip6_maxfrags, 0,
+ "Maximum allowed number of outstanding IPv6 packet fragments. "
+ "A value of 0 means no fragmented packets will be accepted, while a "
+ "a value of -1 means no limit");
+SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGBUCKETSIZE, maxfragbucketsize,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragbucketsize), 0,
+ "Maximum number of reassembly queues per hash bucket");
+SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGSPERPACKET, maxfragsperpacket,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragsperpacket), 0,
+ "Maximum allowed number of fragments per packet");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MCAST_PMTU, mcast_pmtu,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_mcast_pmtu), 0,
"Enable path MTU discovery for multicast packets");
diff --git a/freebsd/sys/netinet6/in6_rmx.c b/freebsd/sys/netinet6/in6_rmx.c
index 402d9e87..38c89b9b 100644
--- a/freebsd/sys/netinet6/in6_rmx.c
+++ b/freebsd/sys/netinet6/in6_rmx.c
@@ -161,7 +161,7 @@ struct mtuex_arg {
struct rib_head *rnh;
time_t nextstop;
};
-static VNET_DEFINE(struct callout, rtq_mtutimer);
+VNET_DEFINE_STATIC(struct callout, rtq_mtutimer);
#define V_rtq_mtutimer VNET(rtq_mtutimer)
static int
@@ -211,7 +211,7 @@ in6_mtutimo(void *rock)
/*
* Initialize our routing tree.
*/
-static VNET_DEFINE(int, _in6_rt_was_here);
+VNET_DEFINE_STATIC(int, _in6_rt_was_here);
#define V__in6_rt_was_here VNET(_in6_rt_was_here)
int
diff --git a/freebsd/sys/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c
index 92f7df4e..1cb71b88 100644
--- a/freebsd/sys/netinet6/in6_src.c
+++ b/freebsd/sys/netinet6/in6_src.c
@@ -129,7 +129,7 @@ static struct sx addrsel_sxlock;
#define ADDRSEL_XUNLOCK() sx_xunlock(&addrsel_sxlock)
#define ADDR_LABEL_NOTAPP (-1)
-static VNET_DEFINE(struct in6_addrpolicy, defaultaddrpolicy);
+VNET_DEFINE_STATIC(struct in6_addrpolicy, defaultaddrpolicy);
#define V_defaultaddrpolicy VNET(defaultaddrpolicy)
VNET_DEFINE(int, ip6_prefer_tempaddr) = 0;
@@ -975,7 +975,7 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
return(error);
/* XXX: this is redundant when called from in6_pcbbind */
- if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
+ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0)
lookupflags = INPLOOKUP_WILDCARD;
inp->inp_flags |= INP_ANONPORT;
@@ -1096,7 +1096,7 @@ struct addrsel_policyent {
TAILQ_HEAD(addrsel_policyhead, addrsel_policyent);
-static VNET_DEFINE(struct addrsel_policyhead, addrsel_policytab);
+VNET_DEFINE_STATIC(struct addrsel_policyhead, addrsel_policytab);
#define V_addrsel_policytab VNET(addrsel_policytab)
static void
diff --git a/freebsd/sys/netinet6/in6_var.h b/freebsd/sys/netinet6/in6_var.h
index 6b4fe1ab..5ed0ae90 100644
--- a/freebsd/sys/netinet6/in6_var.h
+++ b/freebsd/sys/netinet6/in6_var.h
@@ -784,7 +784,7 @@ in6m_rele_locked(struct in6_multi_head *inmh, struct in6_multi *inm)
IN6_MULTI_LIST_LOCK_ASSERT();
if (--inm->in6m_refcount == 0) {
- in6m_disconnect(inm);
+ MPASS(inm->in6m_ifp == NULL);
inm->in6m_ifma->ifma_protospec = NULL;
MPASS(inm->in6m_ifma->ifma_llifma == NULL);
SLIST_INSERT_HEAD(inmh, inm, in6m_nrele);
diff --git a/freebsd/sys/netinet6/ip6_input.c b/freebsd/sys/netinet6/ip6_input.c
index 77e32da8..25ab624c 100644
--- a/freebsd/sys/netinet6/ip6_input.c
+++ b/freebsd/sys/netinet6/ip6_input.c
@@ -722,13 +722,15 @@ ip6_input(struct mbuf *m)
#endif
/*
* Try to forward the packet, but if we fail continue.
+ * ip6_tryforward() does not generate redirects, so fall
+ * through to normal processing if redirects are required.
* ip6_tryforward() does inbound and outbound packet firewall
* processing. If firewall has decided that destination becomes
* our local address, it sets M_FASTFWD_OURS flag. In this
* case skip another inbound firewall processing and update
* ip6 pointer.
*/
- if (V_ip6_forwarding != 0
+ if (V_ip6_forwarding != 0 && V_ip6_sendredirects == 0
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
&& (!IPSEC_ENABLED(ipv6) ||
IPSEC_CAPS(ipv6, m, IPSEC_CAP_OPERABLE) == 0)
diff --git a/freebsd/sys/netinet6/ip6_mroute.c b/freebsd/sys/netinet6/ip6_mroute.c
index a4a8cdf9..c1f66028 100644
--- a/freebsd/sys/netinet6/ip6_mroute.c
+++ b/freebsd/sys/netinet6/ip6_mroute.c
@@ -111,7 +111,6 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
-#include <net/raw_cb.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -141,19 +140,19 @@ extern int in6_mcast_loop;
extern struct domain inet6domain;
static const struct encaptab *pim6_encap_cookie;
-static const struct protosw in6_pim_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = IPPROTO_PIM,
- .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
- .pr_input = pim6_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
static int pim6_encapcheck(const struct mbuf *, int, int, void *);
+static int pim6_input(struct mbuf *, int, int, void *);
+
+static const struct encap_config ipv6_encap_cfg = {
+ .proto = IPPROTO_PIM,
+ .min_length = sizeof(struct ip6_hdr) + PIM_MINLEN,
+ .exact_match = 8,
+ .check = pim6_encapcheck,
+ .input = pim6_input
+};
-static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
+
+VNET_DEFINE_STATIC(int, ip6_mrouter_ver) = 0;
#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver)
SYSCTL_DECL(_net_inet6);
@@ -238,7 +237,7 @@ static struct mtx mif6_mtx;
#define MIF6_LOCK_DESTROY() mtx_destroy(&mif6_mtx)
#ifdef MRT6DEBUG
-static VNET_DEFINE(u_int, mrt6debug) = 0; /* debug level */
+VNET_DEFINE_STATIC(u_int, mrt6debug) = 0; /* debug level */
#define V_mrt6debug VNET(mrt6debug)
#define DEBUG_MFC 0x02
#define DEBUG_FORWARD 0x04
@@ -291,7 +290,7 @@ SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RW,
"PIM Statistics (struct pim6stat, netinet6/pim6_var.h)");
#define PIM6STAT_INC(name) pim6stat.name += 1
-static VNET_DEFINE(int, pim6);
+VNET_DEFINE_STATIC(int, pim6);
#define V_pim6 VNET(pim6)
/*
@@ -1697,16 +1696,12 @@ register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m)
* into the kernel.
*/
static int
-pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+pim6_encapcheck(const struct mbuf *m __unused, int off __unused,
+ int proto __unused, void *arg __unused)
{
-#ifdef DIAGNOSTIC
KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
-#endif
- if (proto != IPPROTO_PIM)
- return 0; /* not for us; reject the datagram. */
-
- return 64; /* claim the datagram. */
+ return (8); /* claim the datagram. */
}
/*
@@ -1716,20 +1711,18 @@ pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
* The only message processed is the REGISTER pim message; the pim header
* is stripped off, and the inner packet is passed to register_mforward.
*/
-int
-pim6_input(struct mbuf **mp, int *offp, int proto)
+static int
+pim6_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
struct pim *pim; /* pointer to a pim struct */
struct ip6_hdr *ip6;
int pimlen;
- struct mbuf *m = *mp;
int minlen;
- int off = *offp;
PIM6STAT_INC(pim6s_rcv_total);
ip6 = mtod(m, struct ip6_hdr *);
- pimlen = m->m_pkthdr.len - *offp;
+ pimlen = m->m_pkthdr.len - off;
/*
* Validate lengths
@@ -1906,8 +1899,7 @@ pim6_input(struct mbuf **mp, int *offp, int proto)
* encapsulated ip6 header.
*/
pim6_input_to_daemon:
- rip6_input(&m, offp, proto);
- return (IPPROTO_DONE);
+ return (rip6_input(&m, &off, proto));
}
static int
@@ -1920,9 +1912,8 @@ ip6_mroute_modevent(module_t mod, int type, void *unused)
MFC6_LOCK_INIT();
MIF6_LOCK_INIT();
- pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
- pim6_encapcheck,
- (const struct protosw *)&in6_pim_protosw, NULL);
+ pim6_encap_cookie = ip6_encap_attach(&ipv6_encap_cfg,
+ NULL, M_WAITOK);
if (pim6_encap_cookie == NULL) {
printf("ip6_mroute: unable to attach pim6 encap\n");
MIF6_LOCK_DESTROY();
@@ -1943,7 +1934,7 @@ ip6_mroute_modevent(module_t mod, int type, void *unused)
return EINVAL;
if (pim6_encap_cookie) {
- encap_detach(pim6_encap_cookie);
+ ip6_encap_detach(pim6_encap_cookie);
pim6_encap_cookie = NULL;
}
X_ip6_mrouter_done();
diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index 1841829a..d3e530a6 100644
--- a/freebsd/sys/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
@@ -201,18 +201,10 @@ in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
csum = 0xffff;
offset += m->m_pkthdr.csum_data; /* checksum offset */
- if (offset + sizeof(u_short) > m->m_len) {
- printf("%s: delayed m_pullup, m->len: %d plen %u off %u "
- "csum_flags=%b\n", __func__, m->m_len, plen, offset,
- (int)m->m_pkthdr.csum_flags, CSUM_BITS);
- /*
- * XXX this should not happen, but if it does, the correct
- * behavior may be to insert the checksum in the appropriate
- * next mbuf in the chain.
- */
- return;
- }
- *(u_short *)(m->m_data + offset) = csum;
+ if (offset + sizeof(csum) > m->m_len)
+ m_copyback(m, offset, sizeof(csum), (caddr_t)&csum);
+ else
+ *(u_short *)mtodo(m, offset) = csum;
}
int
@@ -814,22 +806,16 @@ again:
error = netisr_queue(NETISR_IPV6, m);
goto done;
} else {
- RO_RTFREE(ro);
+ RO_INVALIDATE_CACHE(ro);
needfiblookup = 1; /* Redo the routing table lookup. */
- if (ro->ro_lle)
- LLE_FREE(ro->ro_lle); /* zeros ro_lle */
- ro->ro_lle = NULL;
}
}
/* See if fib was changed by packet filter. */
if (fibnum != M_GETFIB(m)) {
m->m_flags |= M_SKIP_FIREWALL;
fibnum = M_GETFIB(m);
- RO_RTFREE(ro);
+ RO_INVALIDATE_CACHE(ro);
needfiblookup = 1;
- if (ro->ro_lle)
- LLE_FREE(ro->ro_lle); /* zeros ro_lle */
- ro->ro_lle = NULL;
}
if (needfiblookup)
goto again;
@@ -1456,6 +1442,15 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
INP_WUNLOCK(in6p);
error = 0;
break;
+ case SO_REUSEPORT_LB:
+ INP_WLOCK(in6p);
+ if ((so->so_options & SO_REUSEPORT_LB) != 0)
+ in6p->inp_flags2 |= INP_REUSEPORT_LB;
+ else
+ in6p->inp_flags2 &= ~INP_REUSEPORT_LB;
+ INP_WUNLOCK(in6p);
+ error = 0;
+ break;
case SO_SETFIB:
INP_WLOCK(in6p);
in6p->inp_inc.inc_fibnum = so->so_fibnum;
@@ -1637,11 +1632,17 @@ do { \
error = EINVAL;
break;
}
+ INP_WLOCK(in6p);
+ if (in6p->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_WUNLOCK(in6p);
+ return (ECONNRESET);
+ }
optp = &in6p->in6p_outputopts;
error = ip6_pcbopt(IPV6_HOPLIMIT,
(u_char *)&optval, sizeof(optval),
optp, (td != NULL) ? td->td_ucred :
NULL, uproto);
+ INP_WUNLOCK(in6p);
break;
}
@@ -1751,11 +1752,17 @@ do { \
break;
{
struct ip6_pktopts **optp;
+ INP_WLOCK(in6p);
+ if (in6p->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_WUNLOCK(in6p);
+ return (ECONNRESET);
+ }
optp = &in6p->in6p_outputopts;
error = ip6_pcbopt(optname,
(u_char *)&optval, sizeof(optval),
optp, (td != NULL) ? td->td_ucred :
NULL, uproto);
+ INP_WUNLOCK(in6p);
break;
}
@@ -1837,10 +1844,16 @@ do { \
break;
optlen = sopt->sopt_valsize;
optbuf = optbuf_storage;
+ INP_WLOCK(in6p);
+ if (in6p->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_WUNLOCK(in6p);
+ return (ECONNRESET);
+ }
optp = &in6p->in6p_outputopts;
error = ip6_pcbopt(optname, optbuf, optlen,
optp, (td != NULL) ? td->td_ucred : NULL,
uproto);
+ INP_WUNLOCK(in6p);
break;
}
#undef OPTSET
@@ -2287,7 +2300,9 @@ ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt,
if (*pktopt == NULL) {
*pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT,
- M_WAITOK);
+ M_NOWAIT);
+ if (*pktopt == NULL)
+ return (ENOBUFS);
ip6_initpktopts(*pktopt);
}
opt = *pktopt;
diff --git a/freebsd/sys/netinet6/ip6_var.h b/freebsd/sys/netinet6/ip6_var.h
index 74b5f89c..f235572d 100644
--- a/freebsd/sys/netinet6/ip6_var.h
+++ b/freebsd/sys/netinet6/ip6_var.h
@@ -301,8 +301,10 @@ VNET_DECLARE(struct socket *, ip6_mrouter); /* multicast routing daemon */
VNET_DECLARE(int, ip6_sendredirects); /* send IP redirects when forwarding? */
VNET_DECLARE(int, ip6_maxfragpackets); /* Maximum packets in reassembly
* queue */
-VNET_DECLARE(int, ip6_maxfrags); /* Maximum fragments in reassembly
+extern int ip6_maxfrags; /* Maximum fragments in reassembly
* queue */
+VNET_DECLARE(int, ip6_maxfragbucketsize); /* Maximum reassembly queues per bucket */
+VNET_DECLARE(int, ip6_maxfragsperpacket); /* Maximum fragments per packet */
VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */
VNET_DECLARE(int, ip6_no_radr); /* No defroute from RA */
VNET_DECLARE(int, ip6_norbit_raif); /* Disable R-bit in NA on RA
@@ -317,7 +319,8 @@ VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */
#define V_ip6_mrouter VNET(ip6_mrouter)
#define V_ip6_sendredirects VNET(ip6_sendredirects)
#define V_ip6_maxfragpackets VNET(ip6_maxfragpackets)
-#define V_ip6_maxfrags VNET(ip6_maxfrags)
+#define V_ip6_maxfragbucketsize VNET(ip6_maxfragbucketsize)
+#define V_ip6_maxfragsperpacket VNET(ip6_maxfragsperpacket)
#define V_ip6_accept_rtadv VNET(ip6_accept_rtadv)
#define V_ip6_no_radr VNET(ip6_no_radr)
#define V_ip6_norbit_raif VNET(ip6_norbit_raif)
@@ -404,6 +407,7 @@ int ip6_fragment(struct ifnet *, struct mbuf *, int, u_char, int,
int route6_input(struct mbuf **, int *, int);
+void frag6_set_bucketsize(void);
void frag6_init(void);
int frag6_input(struct mbuf **, int *, int);
void frag6_slowtimo(void);
diff --git a/freebsd/sys/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c
index 0c82d5ff..b00f03ef 100644
--- a/freebsd/sys/netinet6/mld6.c
+++ b/freebsd/sys/netinet6/mld6.c
@@ -209,11 +209,11 @@ static MALLOC_DEFINE(M_MLD, "mld", "mld state");
/*
* VIMAGE-wide globals.
*/
-static VNET_DEFINE(struct timeval, mld_gsrdelay) = {10, 0};
-static VNET_DEFINE(LIST_HEAD(, mld_ifsoftc), mli_head);
-static VNET_DEFINE(int, interface_timers_running6);
-static VNET_DEFINE(int, state_change_timers_running6);
-static VNET_DEFINE(int, current_state_timers_running6);
+VNET_DEFINE_STATIC(struct timeval, mld_gsrdelay) = {10, 0};
+VNET_DEFINE_STATIC(LIST_HEAD(, mld_ifsoftc), mli_head);
+VNET_DEFINE_STATIC(int, interface_timers_running6);
+VNET_DEFINE_STATIC(int, state_change_timers_running6);
+VNET_DEFINE_STATIC(int, current_state_timers_running6);
#define V_mld_gsrdelay VNET(mld_gsrdelay)
#define V_mli_head VNET(mli_head)
@@ -559,6 +559,7 @@ mld_ifdetach(struct ifnet *ifp)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
if (inm->in6m_state == MLD_LEAVING_MEMBER) {
+ in6m_disconnect(inm);
in6m_rele_locked(&inmh, inm);
ifma->ifma_protospec = NULL;
}
@@ -1485,6 +1486,7 @@ mld_v1_process_group_timer(struct in6_multi_head *inmh, struct in6_multi *inm)
case MLD_REPORTING_MEMBER:
if (report_timer_expired) {
inm->in6m_state = MLD_IDLE_MEMBER;
+ in6m_disconnect(inm);
in6m_rele_locked(inmh, inm);
}
break;
@@ -1609,6 +1611,7 @@ mld_v2_process_group_timers(struct in6_multi_head *inmh,
if (inm->in6m_state == MLD_LEAVING_MEMBER &&
inm->in6m_scrv == 0) {
inm->in6m_state = MLD_NOT_MEMBER;
+ in6m_disconnect(inm);
in6m_rele_locked(inmh, inm);
}
}
@@ -1681,7 +1684,8 @@ mld_v2_cancel_link_timers(struct mld_ifsoftc *mli)
IF_ADDR_WLOCK(ifp);
restart:
CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) {
- if (ifma->ifma_addr->sa_family != AF_INET6)
+ if (ifma->ifma_addr->sa_family != AF_INET6 ||
+ ifma->ifma_protospec == NULL)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
switch (inm->in6m_state) {
@@ -1698,6 +1702,7 @@ mld_v2_cancel_link_timers(struct mld_ifsoftc *mli)
* version, we need to release the final
* reference held for issuing the INCLUDE {}.
*/
+ in6m_disconnect(inm);
in6m_rele_locked(&inmh, inm);
ifma->ifma_protospec = NULL;
/* FALLTHROUGH */
@@ -1795,8 +1800,11 @@ mld_v1_transmit_report(struct in6_multi *in6m, const int type)
IN6_MULTI_LIST_LOCK_ASSERT();
MLD_LOCK_ASSERT();
-
+
ifp = in6m->in6m_ifp;
+ /* in process of being freed */
+ if (ifp == NULL)
+ return (0);
ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
/* ia may be NULL if link-local address is tentative. */
@@ -1894,16 +1902,15 @@ mld_change_state(struct in6_multi *inm, const int delay)
*/
KASSERT(inm->in6m_ifma != NULL, ("%s: no ifma", __func__));
ifp = inm->in6m_ifma->ifma_ifp;
- if (ifp != NULL) {
- /*
- * Sanity check that netinet6's notion of ifp is the
- * same as net's.
- */
- KASSERT(inm->in6m_ifp == ifp, ("%s: bad ifp", __func__));
- }
+ if (ifp == NULL)
+ return (0);
+ /*
+ * Sanity check that netinet6's notion of ifp is the
+ * same as net's.
+ */
+ KASSERT(inm->in6m_ifp == ifp, ("%s: bad ifp", __func__));
MLD_LOCK();
-
mli = MLD_IFINFO(ifp);
KASSERT(mli != NULL, ("%s: no mld_ifsoftc for ifp %p", __func__, ifp));
@@ -1997,9 +2004,9 @@ mld_initial_join(struct in6_multi *inm, struct mld_ifsoftc *mli,
* group around for the final INCLUDE {} enqueue.
*/
if (mli->mli_version == MLD_VERSION_2 &&
- inm->in6m_state == MLD_LEAVING_MEMBER)
- in6m_release_deferred(inm);
-
+ inm->in6m_state == MLD_LEAVING_MEMBER) {
+ inm->in6m_refcount--;
+ }
inm->in6m_state = MLD_REPORTING_MEMBER;
switch (mli->mli_version) {
diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c
index 6a36803f..f065815c 100644
--- a/freebsd/sys/netinet6/nd6.c
+++ b/freebsd/sys/netinet6/nd6.c
@@ -100,11 +100,11 @@ VNET_DEFINE(int, nd6_gctimer) = (60 * 60 * 24); /* 1 day: garbage
* collection timer */
/* preventing too many loops in ND option parsing */
-static VNET_DEFINE(int, nd6_maxndopt) = 10; /* max # of ND options allowed */
+VNET_DEFINE_STATIC(int, nd6_maxndopt) = 10; /* max # of ND options allowed */
VNET_DEFINE(int, nd6_maxnudhint) = 0; /* max # of subsequent upper
* layer hints */
-static VNET_DEFINE(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved
+VNET_DEFINE_STATIC(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved
* ND entries */
#define V_nd6_maxndopt VNET(nd6_maxndopt)
#define V_nd6_maxqueuelen VNET(nd6_maxqueuelen)
@@ -144,7 +144,7 @@ static int nd6_resolve_slow(struct ifnet *, int, struct mbuf *,
static int nd6_need_cache(struct ifnet *);
-static VNET_DEFINE(struct callout, nd6_slowtimo_ch);
+VNET_DEFINE_STATIC(struct callout, nd6_slowtimo_ch);
#define V_nd6_slowtimo_ch VNET(nd6_slowtimo_ch)
VNET_DEFINE(struct callout, nd6_timer_ch);
diff --git a/freebsd/sys/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c
index d4ab38af..49810020 100644
--- a/freebsd/sys/netinet6/nd6_nbr.c
+++ b/freebsd/sys/netinet6/nd6_nbr.c
@@ -101,7 +101,7 @@ static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
static void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, const struct in6_addr *, uint8_t *, u_int);
-static VNET_DEFINE(int, dad_enhanced) = 1;
+VNET_DEFINE_STATIC(int, dad_enhanced) = 1;
#define V_dad_enhanced VNET(dad_enhanced)
SYSCTL_DECL(_net_inet6_ip6);
@@ -109,7 +109,7 @@ SYSCTL_INT(_net_inet6_ip6, OID_AUTO, dad_enhanced, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(dad_enhanced), 0,
"Enable Enhanced DAD, which adds a random nonce to NS messages for DAD.");
-static VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to
+VNET_DEFINE_STATIC(int, dad_maxtry) = 15; /* max # of *tries* to
transmit DAD packet */
#define V_dad_maxtry VNET(dad_maxtry)
@@ -1122,8 +1122,8 @@ struct dadq {
bool dad_ondadq; /* on dadq? Protected by DADQ_WLOCK. */
};
-static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
-static VNET_DEFINE(struct rwlock, dad_rwlock);
+VNET_DEFINE_STATIC(TAILQ_HEAD(, dadq), dadq);
+VNET_DEFINE_STATIC(struct rwlock, dad_rwlock);
#define V_dadq VNET(dadq)
#define V_dad_rwlock VNET(dad_rwlock)
diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c
index fab7c7c2..a60e7c66 100644
--- a/freebsd/sys/netinet6/nd6_rtr.c
+++ b/freebsd/sys/netinet6/nd6_rtr.c
@@ -96,7 +96,7 @@ static int rt6_deleteroute(const struct rtentry *, void *);
VNET_DECLARE(int, nd6_recalc_reachtm_interval);
#define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval)
-static VNET_DEFINE(struct ifnet *, nd6_defifp);
+VNET_DEFINE_STATIC(struct ifnet *, nd6_defifp);
VNET_DEFINE(int, nd6_defifindex);
#define V_nd6_defifp VNET(nd6_defifp)
diff --git a/freebsd/sys/netinet6/pim6_var.h b/freebsd/sys/netinet6/pim6_var.h
index 7afe89b9..7288c67e 100644
--- a/freebsd/sys/netinet6/pim6_var.h
+++ b/freebsd/sys/netinet6/pim6_var.h
@@ -53,10 +53,6 @@ struct pim6stat {
uint64_t pim6s_snd_registers; /* sent registers */
};
-#if (defined(KERNEL)) || (defined(_KERNEL))
-int pim6_input(struct mbuf **, int*, int);
-#endif /* KERNEL */
-
/*
* Identifiers for PIM sysctl nodes
*/
diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c
index c05399b3..9c3d7a61 100644
--- a/freebsd/sys/netinet6/raw_ip6.c
+++ b/freebsd/sys/netinet6/raw_ip6.c
@@ -167,6 +167,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
struct inpcb *last = NULL;
struct mbuf *opts = NULL;
struct sockaddr_in6 fromsa;
+ struct epoch_tracker et;
RIP6STAT_INC(rip6s_ipackets);
@@ -174,8 +175,8 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
ifp = m->m_pkthdr.rcvif;
- INP_INFO_RLOCK(&V_ripcbinfo);
- LIST_FOREACH(in6p, &V_ripcb, inp_list) {
+ INP_INFO_RLOCK_ET(&V_ripcbinfo, et);
+ CK_LIST_FOREACH(in6p, &V_ripcb, inp_list) {
/* XXX inp locking */
if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
@@ -293,7 +294,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
}
last = in6p;
}
- INP_INFO_RUNLOCK(&V_ripcbinfo);
+ INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/*
* Check AH/ESP integrity.
diff --git a/freebsd/sys/netinet6/scope6.c b/freebsd/sys/netinet6/scope6.c
index 40218287..64b866dd 100644
--- a/freebsd/sys/netinet6/scope6.c
+++ b/freebsd/sys/netinet6/scope6.c
@@ -78,7 +78,7 @@ static struct mtx scope6_lock;
#define SCOPE6_UNLOCK() mtx_unlock(&scope6_lock)
#define SCOPE6_LOCK_ASSERT() mtx_assert(&scope6_lock, MA_OWNED)
-static VNET_DEFINE(struct scope6_id, sid_default);
+VNET_DEFINE_STATIC(struct scope6_id, sid_default);
#define V_sid_default VNET(sid_default)
#define SID(ifp) \
@@ -455,7 +455,7 @@ in6_clearscope(struct in6_addr *in6)
* Return the scope identifier or zero.
*/
uint16_t
-in6_getscope(struct in6_addr *in6)
+in6_getscope(const struct in6_addr *in6)
{
if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
diff --git a/freebsd/sys/netinet6/scope6_var.h b/freebsd/sys/netinet6/scope6_var.h
index a2a9137d..f4e59a19 100644
--- a/freebsd/sys/netinet6/scope6_var.h
+++ b/freebsd/sys/netinet6/scope6_var.h
@@ -63,7 +63,7 @@ int sa6_checkzone(struct sockaddr_in6 *);
int sa6_checkzone_ifp(struct ifnet *, struct sockaddr_in6 *);
int in6_setscope(struct in6_addr *, struct ifnet *, u_int32_t *);
int in6_clearscope(struct in6_addr *);
-uint16_t in6_getscope(struct in6_addr *);
+uint16_t in6_getscope(const struct in6_addr *);
uint32_t in6_getscopezone(const struct ifnet *, int);
void in6_splitscope(const struct in6_addr *, struct in6_addr *, uint32_t *);
struct ifnet* in6_getlinkifnet(uint32_t);
diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c
index fd963fb3..6a3391ee 100644
--- a/freebsd/sys/netinet6/sctp6_usrreq.c
+++ b/freebsd/sys/netinet6/sctp6_usrreq.c
@@ -273,6 +273,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
pktdst->sa_len != sizeof(struct sockaddr_in6)) {
return;
}
+
if ((unsigned)cmd >= PRC_NCMDS) {
return;
}
@@ -296,6 +297,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
if (ip6cp->ip6c_m == NULL) {
return;
}
+
/*
* Check if we can safely examine the ports and the
* verification tag of the SCTP common header.
@@ -304,6 +306,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
(int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) {
return;
}
+
/* Copy out the port numbers and the verification tag. */
memset(&sh, 0, sizeof(sh));
m_copydata(ip6cp->ip6c_m,
@@ -529,6 +532,7 @@ sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNU
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
+
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
if (error)
@@ -569,6 +573,7 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
+
if (addr) {
switch (addr->sa_family) {
#ifdef INET
@@ -918,7 +923,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
/* initialize authentication parameters for the assoc */
@@ -1105,6 +1110,7 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
+
/* allow v6 addresses precedence */
error = sctp6_getaddr(so, nam);
#ifdef INET
@@ -1140,6 +1146,7 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
+
/* allow v6 addresses precedence */
error = sctp6_peeraddr(so, nam);
#ifdef INET
diff --git a/freebsd/sys/netinet6/sctp6_var.h b/freebsd/sys/netinet6/sctp6_var.h
index e3c4359a..4ad0ca28 100644
--- a/freebsd/sys/netinet6/sctp6_var.h
+++ b/freebsd/sys/netinet6/sctp6_var.h
@@ -45,11 +45,11 @@ extern struct pr_usrreqs sctp6_usrreqs;
int sctp6_input(struct mbuf **, int *, int);
int sctp6_input_with_port(struct mbuf **, int *, uint16_t);
-int
+int
sctp6_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct proc *);
void sctp6_ctlinput(int, struct sockaddr *, void *);
-void
+void
sctp6_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *,
uint8_t, uint8_t, uint32_t);
#endif
diff --git a/freebsd/sys/netinet6/udp6_usrreq.c b/freebsd/sys/netinet6/udp6_usrreq.c
index c2b32eb1..67ed0e35 100644
--- a/freebsd/sys/netinet6/udp6_usrreq.c
+++ b/freebsd/sys/netinet6/udp6_usrreq.c
@@ -216,6 +216,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
int off = *offp;
int cscov_partial;
int plen, ulen;
+ struct epoch_tracker et;
struct sockaddr_in6 fromsa[2];
struct m_tag *fwd_tag;
uint16_t uh_sum;
@@ -302,7 +303,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
struct inpcbhead *pcblist;
struct ip6_moptions *imo;
- INP_INFO_RLOCK(pcbinfo);
+ INP_INFO_RLOCK_ET(pcbinfo, et);
/*
* In the event that laddr should be set to the link-local
* address (this happens in RIPng), the multicast address
@@ -320,7 +321,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
*/
pcblist = udp_get_pcblist(nxt);
last = NULL;
- LIST_FOREACH(inp, pcblist, inp_list) {
+ CK_LIST_FOREACH(inp, pcblist, inp_list) {
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
if (inp->inp_lport != uh->uh_dport)
@@ -357,6 +358,10 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
int blocked;
INP_RLOCK(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_RUNLOCK(inp);
+ continue;
+ }
bzero(&mcaddr, sizeof(struct sockaddr_in6));
mcaddr.sin6_len = sizeof(struct sockaddr_in6);
@@ -384,10 +389,16 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) !=
NULL) {
INP_RLOCK(last);
- UDP_PROBE(receive, NULL, last, ip6,
- last, uh);
- if (udp6_append(last, n, off, fromsa))
- goto inp_lost;
+ if (__predict_true(last->inp_flags2 & INP_FREED) == 0) {
+ if (nxt == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, last,
+ ip6, last, uh);
+ else
+ UDP_PROBE(receive, NULL, last,
+ ip6, last, uh);
+ if (udp6_append(last, n, off, fromsa))
+ goto inp_lost;
+ }
INP_RUNLOCK(last);
}
}
@@ -401,7 +412,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
* will never clear these options after setting them.
*/
if ((last->inp_socket->so_options &
- (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+ (SO_REUSEPORT|SO_REUSEPORT_LB|SO_REUSEADDR)) == 0)
break;
}
@@ -416,10 +427,16 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
goto badheadlocked;
}
INP_RLOCK(last);
- INP_INFO_RUNLOCK(pcbinfo);
- UDP_PROBE(receive, NULL, last, ip6, last, uh);
- if (udp6_append(last, m, off, fromsa) == 0)
+ if (__predict_true(last->inp_flags2 & INP_FREED) == 0) {
+ if (nxt == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, last, ip6, last, uh);
+ else
+ UDP_PROBE(receive, NULL, last, ip6, last, uh);
+ if (udp6_append(last, m, off, fromsa) == 0)
+ INP_RUNLOCK(last);
+ } else
INP_RUNLOCK(last);
+ INP_INFO_RUNLOCK_ET(pcbinfo, et);
inp_lost:
return (IPPROTO_DONE);
}
@@ -475,6 +492,10 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ntohs(uh->uh_sport));
}
+ if (nxt == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, NULL, ip6, NULL, uh);
+ else
+ UDP_PROBE(receive, NULL, NULL, ip6, NULL, uh);
UDPSTAT_INC(udps_noport);
if (m->m_flags & M_MCAST) {
printf("UDP6: M_MCAST is set in a unicast packet.\n");
@@ -495,13 +516,16 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
return (IPPROTO_DONE);
}
}
- UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
+ if (nxt == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(receive, NULL, inp, ip6, inp, uh);
+ else
+ UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
if (udp6_append(inp, m, off, fromsa) == 0)
INP_RUNLOCK(inp);
return (IPPROTO_DONE);
badheadlocked:
- INP_INFO_RUNLOCK(pcbinfo);
+ INP_INFO_RUNLOCK_ET(pcbinfo, et);
badunlocked:
if (m)
m_freem(m);
@@ -657,35 +681,38 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW, 0,
0, udp6_getcred, "S,xucred", "Get the xucred of a UDP6 connection");
+#define UH_WLOCKED 2
+#define UH_RLOCKED 1
+#define UH_UNLOCKED 0
static int
-udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
- struct mbuf *control, struct thread *td)
+udp6_output(struct socket *so, int flags_arg, struct mbuf *m,
+ struct sockaddr *addr6, struct mbuf *control, struct thread *td)
{
- u_int32_t ulen = m->m_pkthdr.len;
- u_int32_t plen = sizeof(struct udphdr) + ulen;
+ struct inpcbinfo *pcbinfo;
+ struct inpcb *inp;
struct ip6_hdr *ip6;
struct udphdr *udp6;
struct in6_addr *laddr, *faddr, in6a;
- struct sockaddr_in6 *sin6 = NULL;
- int cscov_partial = 0;
- int scope_ambiguous = 0;
- u_short fport;
- int error = 0;
- uint8_t nxt;
- uint16_t cscov = 0;
struct ip6_pktopts *optp, opt;
- int af = AF_INET6, hlen = sizeof(struct ip6_hdr);
- int flags;
- struct sockaddr_in6 tmp;
+ struct sockaddr_in6 *sin6, tmp;
+ struct epoch_tracker et;
+ int cscov_partial, error, flags, hlen, scope_ambiguous;
+ u_int32_t ulen, plen;
+ uint16_t cscov;
+ u_short fport;
+ uint8_t nxt, unlock_udbinfo;
- INP_WLOCK_ASSERT(inp);
- INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
+ /* addr6 has been validated in udp6_send(). */
+ sin6 = (struct sockaddr_in6 *)addr6;
- if (addr6) {
- /* addr6 has been validated in udp6_send(). */
- sin6 = (struct sockaddr_in6 *)addr6;
+ /*
+ * In contrast to to IPv4 we do not validate the max. packet length
+ * here due to IPv6 Jumbograms (RFC2675).
+ */
- /* protect *sin6 from overwrites */
+ scope_ambiguous = 0;
+ if (sin6) {
+ /* Protect *addr6 from overwrites. */
tmp = *sin6;
sin6 = &tmp;
@@ -699,22 +726,86 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
*/
if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone)
scope_ambiguous = 1;
- if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0)
+ if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) {
+ if (control)
+ m_freem(control);
+ m_freem(m);
return (error);
+ }
}
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
+ INP_RLOCK(inp);
nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ?
IPPROTO_UDP : IPPROTO_UDPLITE;
+
+#ifdef INET
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
+ int hasv4addr;
+
+ if (sin6 == NULL)
+ hasv4addr = (inp->inp_vflag & INP_IPV4);
+ else
+ hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
+ ? 1 : 0;
+ if (hasv4addr) {
+ struct pr_usrreqs *pru;
+
+ /*
+ * XXXRW: We release UDP-layer locks before calling
+ * udp_send() in order to avoid recursion. However,
+ * this does mean there is a short window where inp's
+ * fields are unstable. Could this lead to a
+ * potential race in which the factors causing us to
+ * select the UDPv4 output routine are invalidated?
+ */
+ INP_RUNLOCK(inp);
+ if (sin6)
+ in6_sin6_2_sin_in_sock((struct sockaddr *)sin6);
+ pru = inetsw[ip_protox[nxt]].pr_usrreqs;
+ /* addr will just be freed in sendit(). */
+ return ((*pru->pru_send)(so, flags_arg, m,
+ (struct sockaddr *)sin6, control, td));
+ }
+ }
+#endif
+
if (control) {
if ((error = ip6_setpktopts(control, &opt,
- inp->in6p_outputopts, td->td_ucred, nxt)) != 0)
- goto release;
+ inp->in6p_outputopts, td->td_ucred, nxt)) != 0) {
+ INP_RUNLOCK(inp);
+ ip6_clearpktopts(&opt, -1);
+ if (control)
+ m_freem(control);
+ m_freem(m);
+ return (error);
+ }
optp = &opt;
} else
optp = inp->in6p_outputopts;
+ pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
+ if (sin6 != NULL &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) && inp->inp_lport == 0) {
+ INP_RUNLOCK(inp);
+ /*
+ * XXX there is a short window here which could lead to a race;
+ * should we re-check that what got us here is still valid?
+ */
+ INP_WLOCK(inp);
+ INP_HASH_WLOCK(pcbinfo);
+ unlock_udbinfo = UH_WLOCKED;
+ } else if (sin6 != NULL &&
+ (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) ||
+ inp->inp_lport == 0)) {
+ INP_HASH_RLOCK_ET(pcbinfo, et);
+ unlock_udbinfo = UH_RLOCKED;
+ } else
+ unlock_udbinfo = UH_UNLOCKED;
+
if (sin6) {
- faddr = &sin6->sin6_addr;
/*
* Since we saw no essential reason for calling in_pcbconnect,
@@ -733,85 +824,47 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
goto release;
}
- fport = sin6->sin6_port; /* allow 0 port */
+ /*
+ * Given we handle the v4mapped case in the INET block above
+ * assert here that it must not happen anymore.
+ */
+ KASSERT(!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr),
+ ("%s: sin6(%p)->sin6_addr is v4mapped which we "
+ "should have handled.", __func__, sin6));
- if (IN6_IS_ADDR_V4MAPPED(faddr)) {
- if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
- /*
- * I believe we should explicitly discard the
- * packet when mapped addresses are disabled,
- * rather than send the packet as an IPv6 one.
- * If we chose the latter approach, the packet
- * might be sent out on the wire based on the
- * default route, the situation which we'd
- * probably want to avoid.
- * (20010421 jinmei@kame.net)
- */
- error = EINVAL;
- goto release;
- }
- if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
- !IN6_IS_ADDR_V4MAPPED(&inp->in6p_laddr)) {
- /*
- * when remote addr is an IPv4-mapped address,
- * local addr should not be an IPv6 address,
- * since you cannot determine how to map IPv6
- * source address to IPv4.
- */
- error = EINVAL;
- goto release;
- }
+ /* This only requires read-locking. */
+ error = in6_selectsrc_socket(sin6, optp, inp,
+ td->td_ucred, scope_ambiguous, &in6a, NULL);
+ if (error)
+ goto release;
+ laddr = &in6a;
- af = AF_INET;
- }
+ if (inp->inp_lport == 0) {
- if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
- error = in6_selectsrc_socket(sin6, optp, inp,
- td->td_ucred, scope_ambiguous, &in6a, NULL);
- if (error)
+ INP_WLOCK_ASSERT(inp);
+ error = in6_pcbsetport(laddr, inp, td->td_ucred);
+ if (error != 0) {
+ /* Undo an address bind that may have occurred. */
+ inp->in6p_laddr = in6addr_any;
goto release;
- laddr = &in6a;
- } else
- laddr = &inp->in6p_laddr; /* XXX */
- if (laddr == NULL) {
- if (error == 0)
- error = EADDRNOTAVAIL;
- goto release;
- }
- if (inp->inp_lport == 0 &&
- (error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0) {
- /* Undo an address bind that may have occurred. */
- inp->in6p_laddr = in6addr_any;
- goto release;
+ }
}
+ faddr = &sin6->sin6_addr;
+ fport = sin6->sin6_port; /* allow 0 port */
+
} else {
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
error = ENOTCONN;
goto release;
}
- if (IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) {
- if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
- /*
- * XXX: this case would happen when the
- * application sets the V6ONLY flag after
- * connecting the foreign address.
- * Such applications should be fixed,
- * so we bark here.
- */
- log(LOG_INFO, "udp6_output: IPV6_V6ONLY "
- "option was set for a connected socket\n");
- error = EINVAL;
- goto release;
- } else
- af = AF_INET;
- }
laddr = &inp->in6p_laddr;
faddr = &inp->in6p_faddr;
fport = inp->inp_fport;
}
- if (af == AF_INET)
- hlen = sizeof(struct ip);
+ ulen = m->m_pkthdr.len;
+ plen = sizeof(struct udphdr) + ulen;
+ hlen = sizeof(struct ip6_hdr);
/*
* Calculate data length and get a mbuf
@@ -826,6 +879,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
/*
* Stuff checksum and output datagram.
*/
+ cscov = cscov_partial = 0;
udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */
udp6->uh_dport = fport;
@@ -848,59 +902,59 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
udp6->uh_ulen = 0;
udp6->uh_sum = 0;
- switch (af) {
- case AF_INET6:
- ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_flow = inp->inp_flow & IPV6_FLOWINFO_MASK;
- ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
- ip6->ip6_vfc |= IPV6_VERSION;
- ip6->ip6_plen = htons((u_short)plen);
- ip6->ip6_nxt = nxt;
- ip6->ip6_hlim = in6_selecthlim(inp, NULL);
- ip6->ip6_src = *laddr;
- ip6->ip6_dst = *faddr;
-
- if (cscov_partial) {
- if ((udp6->uh_sum = in6_cksum_partial(m, nxt,
- sizeof(struct ip6_hdr), plen, cscov)) == 0)
- udp6->uh_sum = 0xffff;
- } else {
- udp6->uh_sum = in6_cksum_pseudo(ip6, plen, nxt, 0);
- m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
- m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
- }
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_flow = inp->inp_flow & IPV6_FLOWINFO_MASK;
+ ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
+ ip6->ip6_vfc |= IPV6_VERSION;
+ ip6->ip6_plen = htons((u_short)plen);
+ ip6->ip6_nxt = nxt;
+ ip6->ip6_hlim = in6_selecthlim(inp, NULL);
+ ip6->ip6_src = *laddr;
+ ip6->ip6_dst = *faddr;
+#ifdef MAC
+ mac_inpcb_create_mbuf(inp, m);
+#endif
+
+ if (cscov_partial) {
+ if ((udp6->uh_sum = in6_cksum_partial(m, nxt,
+ sizeof(struct ip6_hdr), plen, cscov)) == 0)
+ udp6->uh_sum = 0xffff;
+ } else {
+ udp6->uh_sum = in6_cksum_pseudo(ip6, plen, nxt, 0);
+ m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
+ m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+ }
+
+ flags = 0;
#ifdef RSS
- {
- uint32_t hash_val, hash_type;
- uint8_t pr;
+ {
+ uint32_t hash_val, hash_type;
+ uint8_t pr;
- pr = inp->inp_socket->so_proto->pr_protocol;
- /*
- * Calculate an appropriate RSS hash for UDP and
- * UDP Lite.
- *
- * The called function will take care of figuring out
- * whether a 2-tuple or 4-tuple hash is required based
- * on the currently configured scheme.
- *
- * Later later on connected socket values should be
- * cached in the inpcb and reused, rather than constantly
- * re-calculating it.
- *
- * UDP Lite is a different protocol number and will
- * likely end up being hashed as a 2-tuple until
- * RSS / NICs grow UDP Lite protocol awareness.
- */
- if (rss_proto_software_hash_v6(faddr, laddr, fport,
- inp->inp_lport, pr, &hash_val, &hash_type) == 0) {
- m->m_pkthdr.flowid = hash_val;
- M_HASHTYPE_SET(m, hash_type);
- }
+ pr = inp->inp_socket->so_proto->pr_protocol;
+ /*
+ * Calculate an appropriate RSS hash for UDP and
+ * UDP Lite.
+ *
+ * The called function will take care of figuring out
+ * whether a 2-tuple or 4-tuple hash is required based
+ * on the currently configured scheme.
+ *
+ * Later later on connected socket values should be
+ * cached in the inpcb and reused, rather than constantly
+ * re-calculating it.
+ *
+ * UDP Lite is a different protocol number and will
+ * likely end up being hashed as a 2-tuple until
+ * RSS / NICs grow UDP Lite protocol awareness.
+ */
+ if (rss_proto_software_hash_v6(faddr, laddr, fport,
+ inp->inp_lport, pr, &hash_val, &hash_type) == 0) {
+ m->m_pkthdr.flowid = hash_val;
+ M_HASHTYPE_SET(m, hash_type);
}
-#endif
- flags = 0;
-#ifdef RSS
+
/*
* Don't override with the inp cached flowid.
*
@@ -908,27 +962,46 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
* be incorrect.
*/
flags |= IP_NODEFAULTFLOWID;
+ }
#endif
+ UDPSTAT_INC(udps_opackets);
+ if (unlock_udbinfo == UH_WLOCKED)
+ INP_HASH_WUNLOCK(pcbinfo);
+ else if (unlock_udbinfo == UH_RLOCKED)
+ INP_HASH_RUNLOCK_ET(pcbinfo, et);
+ if (nxt == IPPROTO_UDPLITE)
+ UDPLITE_PROBE(send, NULL, inp, ip6, inp, udp6);
+ else
UDP_PROBE(send, NULL, inp, ip6, inp, udp6);
- UDPSTAT_INC(udps_opackets);
- error = ip6_output(m, optp, &inp->inp_route6, flags,
- inp->in6p_moptions, NULL, inp);
- break;
- case AF_INET:
- error = EAFNOSUPPORT;
- goto release;
+ error = ip6_output(m, optp, &inp->inp_route6, flags,
+ inp->in6p_moptions, NULL, inp);
+ if (unlock_udbinfo == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
+
+ if (control) {
+ ip6_clearpktopts(&opt, -1);
+ m_freem(control);
}
- goto releaseopt;
+ return (error);
release:
- m_freem(m);
-
-releaseopt:
+ if (unlock_udbinfo == UH_WLOCKED) {
+ INP_HASH_WUNLOCK(pcbinfo);
+ INP_WUNLOCK(inp);
+ } else if (unlock_udbinfo == UH_RLOCKED) {
+ INP_HASH_RUNLOCK_ET(pcbinfo, et);
+ INP_RUNLOCK(inp);
+ } else
+ INP_RUNLOCK(inp);
if (control) {
ip6_clearpktopts(&opt, -1);
m_freem(control);
}
+ m_freem(m);
+
return (error);
}
@@ -1232,15 +1305,8 @@ static int
udp6_send(struct socket *so, int flags, struct mbuf *m,
struct sockaddr *addr, struct mbuf *control, struct thread *td)
{
- struct inpcb *inp;
- struct inpcbinfo *pcbinfo;
- int error = 0;
-
- pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
- inp = sotoinpcb(so);
- KASSERT(inp != NULL, ("udp6_send: inp == NULL"));
+ int error;
- INP_WLOCK(inp);
if (addr) {
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
error = EINVAL;
@@ -1252,53 +1318,11 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
}
}
-#ifdef INET
- if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
- int hasv4addr;
- struct sockaddr_in6 *sin6 = NULL;
-
- if (addr == NULL)
- hasv4addr = (inp->inp_vflag & INP_IPV4);
- else {
- sin6 = (struct sockaddr_in6 *)addr;
- hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
- ? 1 : 0;
- }
- if (hasv4addr) {
- struct pr_usrreqs *pru;
- uint8_t nxt;
-
- nxt = (inp->inp_socket->so_proto->pr_protocol ==
- IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE;
- /*
- * XXXRW: We release UDP-layer locks before calling
- * udp_send() in order to avoid recursion. However,
- * this does mean there is a short window where inp's
- * fields are unstable. Could this lead to a
- * potential race in which the factors causing us to
- * select the UDPv4 output routine are invalidated?
- */
- INP_WUNLOCK(inp);
- if (sin6)
- in6_sin6_2_sin_in_sock(addr);
- pru = inetsw[ip_protox[nxt]].pr_usrreqs;
- /* addr will just be freed in sendit(). */
- return ((*pru->pru_send)(so, flags, m, addr, control,
- td));
- }
- }
-#endif
-#ifdef MAC
- mac_inpcb_create_mbuf(inp, m);
-#endif
- INP_HASH_WLOCK(pcbinfo);
- error = udp6_output(inp, m, addr, control, td);
- INP_HASH_WUNLOCK(pcbinfo);
- INP_WUNLOCK(inp);
- return (error);
+ return (udp6_output(so, flags, m, addr, control, td));
bad:
- INP_WUNLOCK(inp);
+ if (control)
+ m_freem(control);
m_freem(m);
return (error);
}
diff --git a/freebsd/sys/netipsec/ipsec.c b/freebsd/sys/netipsec/ipsec.c
index 24a6df5b..116557ed 100644
--- a/freebsd/sys/netipsec/ipsec.c
+++ b/freebsd/sys/netipsec/ipsec.c
@@ -121,11 +121,11 @@ VNET_DEFINE(int, ip4_ah_net_deflev) = IPSEC_LEVEL_USE;
/* ECN ignore(-1)/forbidden(0)/allowed(1) */
VNET_DEFINE(int, ip4_ipsec_ecn) = 0;
-static VNET_DEFINE(int, ip4_filtertunnel) = 0;
+VNET_DEFINE_STATIC(int, ip4_filtertunnel) = 0;
#define V_ip4_filtertunnel VNET(ip4_filtertunnel)
-static VNET_DEFINE(int, check_policy_history) = 0;
+VNET_DEFINE_STATIC(int, check_policy_history) = 0;
#define V_check_policy_history VNET(check_policy_history)
-static VNET_DEFINE(struct secpolicy *, def_policy) = NULL;
+VNET_DEFINE_STATIC(struct secpolicy *, def_policy) = NULL;
#define V_def_policy VNET(def_policy)
static int
sysctl_def_policy(SYSCTL_HANDLER_ARGS)
@@ -251,7 +251,7 @@ VNET_DEFINE(int, ip6_ah_trans_deflev) = IPSEC_LEVEL_USE;
VNET_DEFINE(int, ip6_ah_net_deflev) = IPSEC_LEVEL_USE;
VNET_DEFINE(int, ip6_ipsec_ecn) = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
-static VNET_DEFINE(int, ip6_filtertunnel) = 0;
+VNET_DEFINE_STATIC(int, ip6_filtertunnel) = 0;
#define V_ip6_filtertunnel VNET(ip6_filtertunnel)
SYSCTL_DECL(_net_inet6_ipsec6);
@@ -1324,9 +1324,10 @@ ok:
}
int
-ipsec_updateid(struct secasvar *sav, uint64_t *new, uint64_t *old)
+ipsec_updateid(struct secasvar *sav, crypto_session_t *new,
+ crypto_session_t *old)
{
- uint64_t tmp;
+ crypto_session_t tmp;
/*
* tdb_cryptoid is initialized by xform_init().
@@ -1352,8 +1353,8 @@ ipsec_updateid(struct secasvar *sav, uint64_t *new, uint64_t *old)
* XXXAE: check this more carefully.
*/
KEYDBG(IPSEC_STAMP,
- printf("%s: SA(%p) moves cryptoid %jd -> %jd\n",
- __func__, sav, (uintmax_t)(*old), (uintmax_t)(*new)));
+ printf("%s: SA(%p) moves cryptoid %p -> %p\n",
+ __func__, sav, *old, *new));
KEYDBG(IPSEC_DATA, kdebug_secasv(sav));
SECASVAR_LOCK(sav);
if (sav->tdb_cryptoid != *old) {
diff --git a/freebsd/sys/netipsec/ipsec.h b/freebsd/sys/netipsec/ipsec.h
index 936e7bca..eed2d077 100644
--- a/freebsd/sys/netipsec/ipsec.h
+++ b/freebsd/sys/netipsec/ipsec.h
@@ -332,7 +332,7 @@ int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *);
int ipsec_chkreplay(uint32_t, struct secasvar *);
int ipsec_updatereplay(uint32_t, struct secasvar *);
-int ipsec_updateid(struct secasvar *, uint64_t *, uint64_t *);
+int ipsec_updateid(struct secasvar *, crypto_session_t *, crypto_session_t *);
int ipsec_initialized(void);
void ipsec_setspidx_inpcb(struct inpcb *, struct secpolicyindex *, u_int);
diff --git a/freebsd/sys/netipsec/key.c b/freebsd/sys/netipsec/key.c
index fbf12f41..9bd3f234 100644
--- a/freebsd/sys/netipsec/key.c
+++ b/freebsd/sys/netipsec/key.c
@@ -115,20 +115,20 @@
*/
VNET_DEFINE(u_int32_t, key_debug_level) = 0;
-static VNET_DEFINE(u_int, key_spi_trycnt) = 1000;
-static VNET_DEFINE(u_int32_t, key_spi_minval) = 0x100;
-static VNET_DEFINE(u_int32_t, key_spi_maxval) = 0x0fffffff; /* XXX */
-static VNET_DEFINE(u_int32_t, policy_id) = 0;
+VNET_DEFINE_STATIC(u_int, key_spi_trycnt) = 1000;
+VNET_DEFINE_STATIC(u_int32_t, key_spi_minval) = 0x100;
+VNET_DEFINE_STATIC(u_int32_t, key_spi_maxval) = 0x0fffffff; /* XXX */
+VNET_DEFINE_STATIC(u_int32_t, policy_id) = 0;
/*interval to initialize randseed,1(m)*/
-static VNET_DEFINE(u_int, key_int_random) = 60;
+VNET_DEFINE_STATIC(u_int, key_int_random) = 60;
/* interval to expire acquiring, 30(s)*/
-static VNET_DEFINE(u_int, key_larval_lifetime) = 30;
+VNET_DEFINE_STATIC(u_int, key_larval_lifetime) = 30;
/* counter for blocking SADB_ACQUIRE.*/
-static VNET_DEFINE(int, key_blockacq_count) = 10;
+VNET_DEFINE_STATIC(int, key_blockacq_count) = 10;
/* lifetime for blocking SADB_ACQUIRE.*/
-static VNET_DEFINE(int, key_blockacq_lifetime) = 20;
+VNET_DEFINE_STATIC(int, key_blockacq_lifetime) = 20;
/* preferred old sa rather than new sa.*/
-static VNET_DEFINE(int, key_preferred_oldsa) = 1;
+VNET_DEFINE_STATIC(int, key_preferred_oldsa) = 1;
#define V_key_spi_trycnt VNET(key_spi_trycnt)
#define V_key_spi_minval VNET(key_spi_minval)
#define V_key_spi_maxval VNET(key_spi_maxval)
@@ -139,17 +139,17 @@ static VNET_DEFINE(int, key_preferred_oldsa) = 1;
#define V_key_blockacq_lifetime VNET(key_blockacq_lifetime)
#define V_key_preferred_oldsa VNET(key_preferred_oldsa)
-static VNET_DEFINE(u_int32_t, acq_seq) = 0;
+VNET_DEFINE_STATIC(u_int32_t, acq_seq) = 0;
#define V_acq_seq VNET(acq_seq)
-static VNET_DEFINE(uint32_t, sp_genid) = 0;
+VNET_DEFINE_STATIC(uint32_t, sp_genid) = 0;
#define V_sp_genid VNET(sp_genid)
/* SPD */
TAILQ_HEAD(secpolicy_queue, secpolicy);
LIST_HEAD(secpolicy_list, secpolicy);
-static VNET_DEFINE(struct secpolicy_queue, sptree[IPSEC_DIR_MAX]);
-static VNET_DEFINE(struct secpolicy_queue, sptree_ifnet[IPSEC_DIR_MAX]);
+VNET_DEFINE_STATIC(struct secpolicy_queue, sptree[IPSEC_DIR_MAX]);
+VNET_DEFINE_STATIC(struct secpolicy_queue, sptree_ifnet[IPSEC_DIR_MAX]);
static struct rmlock sptree_lock;
#define V_sptree VNET(sptree)
#define V_sptree_ifnet VNET(sptree_ifnet)
@@ -165,8 +165,8 @@ static struct rmlock sptree_lock;
#define SPTREE_UNLOCK_ASSERT() rm_assert(&sptree_lock, RA_UNLOCKED)
/* Hash table for lookup SP using unique id */
-static VNET_DEFINE(struct secpolicy_list *, sphashtbl);
-static VNET_DEFINE(u_long, sphash_mask);
+VNET_DEFINE_STATIC(struct secpolicy_list *, sphashtbl);
+VNET_DEFINE_STATIC(u_long, sphash_mask);
#define V_sphashtbl VNET(sphashtbl)
#define V_sphash_mask VNET(sphash_mask)
@@ -186,19 +186,19 @@ LIST_HEAD(spdcache_entry_list, spdcache_entry);
#define SPDCACHE_MAX_ENTRIES_PER_HASH 8
-static VNET_DEFINE(u_int, key_spdcache_maxentries) = 0;
+VNET_DEFINE_STATIC(u_int, key_spdcache_maxentries) = 0;
#define V_key_spdcache_maxentries VNET(key_spdcache_maxentries)
-static VNET_DEFINE(u_int, key_spdcache_threshold) = 32;
+VNET_DEFINE_STATIC(u_int, key_spdcache_threshold) = 32;
#define V_key_spdcache_threshold VNET(key_spdcache_threshold)
-static VNET_DEFINE(unsigned long, spd_size) = 0;
+VNET_DEFINE_STATIC(unsigned long, spd_size) = 0;
#define V_spd_size VNET(spd_size)
#define SPDCACHE_ENABLED() (V_key_spdcache_maxentries != 0)
#define SPDCACHE_ACTIVE() \
(SPDCACHE_ENABLED() && V_spd_size >= V_key_spdcache_threshold)
-static VNET_DEFINE(struct spdcache_entry_list *, spdcachehashtbl);
-static VNET_DEFINE(u_long, spdcachehash_mask);
+VNET_DEFINE_STATIC(struct spdcache_entry_list *, spdcachehashtbl);
+VNET_DEFINE_STATIC(u_long, spdcachehash_mask);
#define V_spdcachehashtbl VNET(spdcachehashtbl)
#define V_spdcachehash_mask VNET(spdcachehash_mask)
@@ -207,7 +207,7 @@ static VNET_DEFINE(u_long, spdcachehash_mask);
V_spdcachehash_mask)
/* Each cache line is protected by a mutex */
-static VNET_DEFINE(struct mtx *, spdcache_lock);
+VNET_DEFINE_STATIC(struct mtx *, spdcache_lock);
#define V_spdcache_lock VNET(spdcache_lock)
#define SPDCACHE_LOCK_INIT(a) \
@@ -220,7 +220,7 @@ static VNET_DEFINE(struct mtx *, spdcache_lock);
/* SAD */
TAILQ_HEAD(secashead_queue, secashead);
LIST_HEAD(secashead_list, secashead);
-static VNET_DEFINE(struct secashead_queue, sahtree);
+VNET_DEFINE_STATIC(struct secashead_queue, sahtree);
static struct rmlock sahtree_lock;
#define V_sahtree VNET(sahtree)
#define SAHTREE_LOCK_INIT() rm_init(&sahtree_lock, "sahtree")
@@ -235,8 +235,8 @@ static struct rmlock sahtree_lock;
#define SAHTREE_UNLOCK_ASSERT() rm_assert(&sahtree_lock, RA_UNLOCKED)
/* Hash table for lookup in SAD using SA addresses */
-static VNET_DEFINE(struct secashead_list *, sahaddrhashtbl);
-static VNET_DEFINE(u_long, sahaddrhash_mask);
+VNET_DEFINE_STATIC(struct secashead_list *, sahaddrhashtbl);
+VNET_DEFINE_STATIC(u_long, sahaddrhash_mask);
#define V_sahaddrhashtbl VNET(sahaddrhashtbl)
#define V_sahaddrhash_mask VNET(sahaddrhash_mask)
@@ -250,8 +250,8 @@ static VNET_DEFINE(u_long, sahaddrhash_mask);
/* Hash table for lookup in SAD using SPI */
LIST_HEAD(secasvar_list, secasvar);
-static VNET_DEFINE(struct secasvar_list *, savhashtbl);
-static VNET_DEFINE(u_long, savhash_mask);
+VNET_DEFINE_STATIC(struct secasvar_list *, savhashtbl);
+VNET_DEFINE_STATIC(u_long, savhash_mask);
#define V_savhashtbl VNET(savhashtbl)
#define V_savhash_mask VNET(savhash_mask)
#define SAVHASH_NHASH_LOG2 7
@@ -300,7 +300,7 @@ key_u32hash(uint32_t val)
}
/* registed list */
-static VNET_DEFINE(LIST_HEAD(_regtree, secreg), regtree[SADB_SATYPE_MAX + 1]);
+VNET_DEFINE_STATIC(LIST_HEAD(_regtree, secreg), regtree[SADB_SATYPE_MAX + 1]);
#define V_regtree VNET(regtree)
static struct mtx regtree_lock;
#define REGTREE_LOCK_INIT() \
@@ -312,7 +312,7 @@ static struct mtx regtree_lock;
/* Acquiring list */
LIST_HEAD(secacq_list, secacq);
-static VNET_DEFINE(struct secacq_list, acqtree);
+VNET_DEFINE_STATIC(struct secacq_list, acqtree);
#define V_acqtree VNET(acqtree)
static struct mtx acq_lock;
#define ACQ_LOCK_INIT() \
@@ -323,14 +323,14 @@ static struct mtx acq_lock;
#define ACQ_LOCK_ASSERT() mtx_assert(&acq_lock, MA_OWNED)
/* Hash table for lookup in ACQ list using SA addresses */
-static VNET_DEFINE(struct secacq_list *, acqaddrhashtbl);
-static VNET_DEFINE(u_long, acqaddrhash_mask);
+VNET_DEFINE_STATIC(struct secacq_list *, acqaddrhashtbl);
+VNET_DEFINE_STATIC(u_long, acqaddrhash_mask);
#define V_acqaddrhashtbl VNET(acqaddrhashtbl)
#define V_acqaddrhash_mask VNET(acqaddrhash_mask)
/* Hash table for lookup in ACQ list using SEQ number */
-static VNET_DEFINE(struct secacq_list *, acqseqhashtbl);
-static VNET_DEFINE(u_long, acqseqhash_mask);
+VNET_DEFINE_STATIC(struct secacq_list *, acqseqhashtbl);
+VNET_DEFINE_STATIC(u_long, acqseqhash_mask);
#define V_acqseqhashtbl VNET(acqseqhashtbl)
#define V_acqseqhash_mask VNET(acqseqhash_mask)
@@ -346,7 +346,7 @@ static VNET_DEFINE(u_long, acqseqhash_mask);
#define ACQSEQHASH_HASH(seq) \
&V_acqseqhashtbl[ACQSEQHASH_HASHVAL(seq)]
/* SP acquiring list */
-static VNET_DEFINE(LIST_HEAD(_spacqtree, secspacq), spacqtree);
+VNET_DEFINE_STATIC(LIST_HEAD(_spacqtree, secspacq), spacqtree);
#define V_spacqtree VNET(spacqtree)
static struct mtx spacq_lock;
#define SPACQ_LOCK_INIT() \
@@ -435,9 +435,9 @@ _Static_assert(sizeof(maxsize)/sizeof(int) == SADB_EXT_MAX + 1, "minsize size mi
((_mhp)->extlen[(_ext)] > maxsize[(_ext)])))
#define SADB_CHECKHDR(_mhp, _ext) ((_mhp)->ext[(_ext)] == NULL)
-static VNET_DEFINE(int, ipsec_esp_keymin) = 256;
-static VNET_DEFINE(int, ipsec_esp_auth) = 0;
-static VNET_DEFINE(int, ipsec_ah_keymin) = 128;
+VNET_DEFINE_STATIC(int, ipsec_esp_keymin) = 256;
+VNET_DEFINE_STATIC(int, ipsec_esp_auth) = 0;
+VNET_DEFINE_STATIC(int, ipsec_ah_keymin) = 128;
#define V_ipsec_esp_keymin VNET(ipsec_esp_keymin)
#define V_ipsec_esp_auth VNET(ipsec_esp_auth)
@@ -533,7 +533,7 @@ MALLOC_DEFINE(M_IPSEC_SAQ, "ipsec-saq", "ipsec sa acquire");
MALLOC_DEFINE(M_IPSEC_SAR, "ipsec-reg", "ipsec sa acquire");
MALLOC_DEFINE(M_IPSEC_SPDCACHE, "ipsec-spdcache", "ipsec SPD cache");
-static VNET_DEFINE(uma_zone_t, key_lft_zone);
+VNET_DEFINE_STATIC(uma_zone_t, key_lft_zone);
#define V_key_lft_zone VNET(key_lft_zone)
static LIST_HEAD(xforms_list, xformsw) xforms = LIST_HEAD_INITIALIZER();
@@ -2959,7 +2959,7 @@ key_newsav(const struct sadb_msghdr *mhp, struct secasindex *saidx,
goto done;
}
mtx_init(sav->lock, "ipsec association", NULL, MTX_DEF);
- sav->lft_c = uma_zalloc(V_key_lft_zone, M_NOWAIT);
+ sav->lft_c = uma_zalloc_pcpu(V_key_lft_zone, M_NOWAIT);
if (sav->lft_c == NULL) {
*errp = ENOBUFS;
goto done;
@@ -3051,7 +3051,7 @@ done:
free(sav->lock, M_IPSEC_MISC);
}
if (sav->lft_c != NULL)
- uma_zfree(V_key_lft_zone, sav->lft_c);
+ uma_zfree_pcpu(V_key_lft_zone, sav->lft_c);
free(sav, M_IPSEC_SA), sav = NULL;
}
if (sah != NULL)
diff --git a/freebsd/sys/netipsec/key_debug.c b/freebsd/sys/netipsec/key_debug.c
index 12cfe34e..07eec79e 100644
--- a/freebsd/sys/netipsec/key_debug.c
+++ b/freebsd/sys/netipsec/key_debug.c
@@ -87,6 +87,85 @@ static void kdebug_sadb_x_natt(struct sadb_ext *);
/* NOTE: host byte order */
+static const char*
+kdebug_sadb_type(uint8_t type)
+{
+#define SADB_NAME(n) case SADB_ ## n: return (#n)
+
+ switch (type) {
+ SADB_NAME(RESERVED);
+ SADB_NAME(GETSPI);
+ SADB_NAME(UPDATE);
+ SADB_NAME(ADD);
+ SADB_NAME(DELETE);
+ SADB_NAME(GET);
+ SADB_NAME(ACQUIRE);
+ SADB_NAME(REGISTER);
+ SADB_NAME(EXPIRE);
+ SADB_NAME(FLUSH);
+ SADB_NAME(DUMP);
+ SADB_NAME(X_PROMISC);
+ SADB_NAME(X_PCHANGE);
+ SADB_NAME(X_SPDUPDATE);
+ SADB_NAME(X_SPDADD);
+ SADB_NAME(X_SPDDELETE);
+ SADB_NAME(X_SPDGET);
+ SADB_NAME(X_SPDACQUIRE);
+ SADB_NAME(X_SPDDUMP);
+ SADB_NAME(X_SPDFLUSH);
+ SADB_NAME(X_SPDSETIDX);
+ SADB_NAME(X_SPDEXPIRE);
+ SADB_NAME(X_SPDDELETE2);
+ default:
+ return ("UNKNOWN");
+ }
+#undef SADB_NAME
+}
+
+static const char*
+kdebug_sadb_exttype(uint16_t type)
+{
+#define EXT_NAME(n) case SADB_EXT_ ## n: return (#n)
+#define X_NAME(n) case SADB_X_EXT_ ## n: return (#n)
+
+ switch (type) {
+ EXT_NAME(RESERVED);
+ EXT_NAME(SA);
+ EXT_NAME(LIFETIME_CURRENT);
+ EXT_NAME(LIFETIME_HARD);
+ EXT_NAME(LIFETIME_SOFT);
+ EXT_NAME(ADDRESS_SRC);
+ EXT_NAME(ADDRESS_DST);
+ EXT_NAME(ADDRESS_PROXY);
+ EXT_NAME(KEY_AUTH);
+ EXT_NAME(KEY_ENCRYPT);
+ EXT_NAME(IDENTITY_SRC);
+ EXT_NAME(IDENTITY_DST);
+ EXT_NAME(SENSITIVITY);
+ EXT_NAME(PROPOSAL);
+ EXT_NAME(SUPPORTED_AUTH);
+ EXT_NAME(SUPPORTED_ENCRYPT);
+ EXT_NAME(SPIRANGE);
+ X_NAME(KMPRIVATE);
+ X_NAME(POLICY);
+ X_NAME(SA2);
+ X_NAME(NAT_T_TYPE);
+ X_NAME(NAT_T_SPORT);
+ X_NAME(NAT_T_DPORT);
+ X_NAME(NAT_T_OAI);
+ X_NAME(NAT_T_OAR);
+ X_NAME(NAT_T_FRAG);
+ X_NAME(SA_REPLAY);
+ X_NAME(NEW_ADDRESS_SRC);
+ X_NAME(NEW_ADDRESS_DST);
+ default:
+ return ("UNKNOWN");
+ };
+#undef EXT_NAME
+#undef X_NAME
+}
+
+
/* %%%: about struct sadb_msg */
void
kdebug_sadb(struct sadb_msg *base)
@@ -98,8 +177,9 @@ kdebug_sadb(struct sadb_msg *base)
if (base == NULL)
panic("%s: NULL pointer was passed.\n", __func__);
- printf("sadb_msg{ version=%u type=%u errno=%u satype=%u\n",
+ printf("sadb_msg{ version=%u type=%u(%s) errno=%u satype=%u\n",
base->sadb_msg_version, base->sadb_msg_type,
+ kdebug_sadb_type(base->sadb_msg_type),
base->sadb_msg_errno, base->sadb_msg_satype);
printf(" len=%u reserved=%u seq=%u pid=%u\n",
base->sadb_msg_len, base->sadb_msg_reserved,
@@ -109,8 +189,9 @@ kdebug_sadb(struct sadb_msg *base)
ext = (struct sadb_ext *)((caddr_t)base + sizeof(struct sadb_msg));
while (tlen > 0) {
- printf("sadb_ext{ len=%u type=%u }\n",
- ext->sadb_ext_len, ext->sadb_ext_type);
+ printf("sadb_ext{ len=%u type=%u(%s) }\n",
+ ext->sadb_ext_len, ext->sadb_ext_type,
+ kdebug_sadb_exttype(ext->sadb_ext_type));
if (ext->sadb_ext_len == 0) {
printf("%s: invalid ext_len=0 was passed.\n", __func__);
diff --git a/freebsd/sys/netipsec/keydb.h b/freebsd/sys/netipsec/keydb.h
index 19eae767..6993b4e4 100644
--- a/freebsd/sys/netipsec/keydb.h
+++ b/freebsd/sys/netipsec/keydb.h
@@ -41,6 +41,7 @@
#include <sys/mutex.h>
#include <netipsec/key_var.h>
+#include <opencrypto/_cryptodev.h>
#ifndef _SOCKADDR_UNION_DEFINED
#define _SOCKADDR_UNION_DEFINED
@@ -162,7 +163,7 @@ struct secasvar {
const struct enc_xform *tdb_encalgxform;/* encoding algorithm */
const struct auth_hash *tdb_authalgxform;/* authentication algorithm */
const struct comp_algo *tdb_compalgxform;/* compression algorithm */
- uint64_t tdb_cryptoid; /* crypto session id */
+ crypto_session_t tdb_cryptoid; /* crypto session */
uint8_t alg_auth; /* Authentication Algorithm Identifier*/
uint8_t alg_enc; /* Cipher Algorithm Identifier */
diff --git a/freebsd/sys/netipsec/keysock.c b/freebsd/sys/netipsec/keysock.c
index 170335bc..9ea1d8f1 100644
--- a/freebsd/sys/netipsec/keysock.c
+++ b/freebsd/sys/netipsec/keysock.c
@@ -73,7 +73,7 @@ struct key_cb {
int key_count;
int any_count;
};
-static VNET_DEFINE(struct key_cb, key_cb);
+VNET_DEFINE_STATIC(struct key_cb, key_cb);
#define V_key_cb VNET(key_cb)
static struct sockaddr key_src = { 2, PF_KEY, };
diff --git a/freebsd/sys/netipsec/xform.h b/freebsd/sys/netipsec/xform.h
index 2720f72a..389d0b66 100644
--- a/freebsd/sys/netipsec/xform.h
+++ b/freebsd/sys/netipsec/xform.h
@@ -71,7 +71,7 @@ struct xform_history {
struct xform_data {
struct secpolicy *sp; /* security policy */
struct secasvar *sav; /* related SA */
- uint64_t cryptoid; /* used crypto session id */
+ crypto_session_t cryptoid; /* used crypto session */
u_int idx; /* IPsec request index */
int protoff; /* current protocol offset */
int skip; /* data offset */
diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index 13999f41..84ba6c16 100644
--- a/freebsd/sys/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
@@ -149,11 +149,21 @@ ah_hdrsiz(struct secasvar *sav)
size_t size;
if (sav != NULL) {
- int authsize;
+ int authsize, rplen, align;
+
IPSEC_ASSERT(sav->tdb_authalgxform != NULL, ("null xform"));
/*XXX not right for null algorithm--does it matter??*/
+
+ /* RFC4302: use the correct alignment. */
+ align = sizeof(uint32_t);
+#ifdef INET6
+ if (sav->sah->saidx.dst.sa.sa_family == AF_INET6) {
+ align = sizeof(uint64_t);
+ }
+#endif
+ rplen = HDRSIZE(sav);
authsize = AUTHSIZE(sav);
- size = roundup(authsize, sizeof (u_int32_t)) + HDRSIZE(sav);
+ size = roundup(rplen + authsize, align);
} else {
/* default guess */
size = sizeof (struct ah) + sizeof (u_int32_t) + 16;
@@ -237,16 +247,15 @@ ah_init(struct secasvar *sav, struct xformsw *xsp)
int
ah_zeroize(struct secasvar *sav)
{
- int err;
if (sav->key_auth)
bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
- err = crypto_freesession(sav->tdb_cryptoid);
- sav->tdb_cryptoid = 0;
+ crypto_freesession(sav->tdb_cryptoid);
+ sav->tdb_cryptoid = NULL;
sav->tdb_authalgxform = NULL;
sav->tdb_xform = NULL;
- return err;
+ return 0;
}
/*
@@ -536,8 +545,8 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
struct cryptop *crp;
struct xform_data *xd;
struct newah *ah;
- uint64_t cryptoid;
- int hl, rplen, authsize, error;
+ crypto_session_t cryptoid;
+ int hl, rplen, authsize, ahsize, error;
IPSEC_ASSERT(sav != NULL, ("null SA"));
IPSEC_ASSERT(sav->key_auth != NULL, ("null authentication key"));
@@ -571,23 +580,24 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
SECASVAR_UNLOCK(sav);
/* Verify AH header length. */
- hl = ah->ah_len * sizeof (u_int32_t);
+ hl = sizeof(struct ah) + (ah->ah_len * sizeof (u_int32_t));
ahx = sav->tdb_authalgxform;
authsize = AUTHSIZE(sav);
- if (hl != authsize + rplen - sizeof (struct ah)) {
+ ahsize = ah_hdrsiz(sav);
+ if (hl != ahsize) {
DPRINTF(("%s: bad authenticator length %u (expecting %lu)"
" for packet in SA %s/%08lx\n", __func__, hl,
- (u_long) (authsize + rplen - sizeof (struct ah)),
+ (u_long)ahsize,
ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
(u_long) ntohl(sav->spi)));
AHSTAT_INC(ahs_badauthl);
error = EACCES;
goto bad;
}
- if (skip + authsize + rplen > m->m_pkthdr.len) {
+ if (skip + ahsize > m->m_pkthdr.len) {
DPRINTF(("%s: bad mbuf length %u (expecting %lu)"
" for packet in SA %s/%08lx\n", __func__,
- m->m_pkthdr.len, (u_long) (skip + authsize + rplen),
+ m->m_pkthdr.len, (u_long)(skip + ahsize),
ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
(u_long) ntohl(sav->spi)));
AHSTAT_INC(ahs_badauthl);
@@ -660,7 +670,7 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
crp->crp_flags |= CRYPTO_F_ASYNC | CRYPTO_F_ASYNC_KEEPORDER;
crp->crp_buf = (caddr_t) m;
crp->crp_callback = ah_input_cb;
- crp->crp_sid = cryptoid;
+ crp->crp_session = cryptoid;
crp->crp_opaque = (caddr_t) xd;
/* These are passed as-is to the callback. */
@@ -690,8 +700,8 @@ ah_input_cb(struct cryptop *crp)
struct secasvar *sav;
struct secasindex *saidx;
caddr_t ptr;
- uint64_t cryptoid;
- int authsize, rplen, error, skip, protoff;
+ crypto_session_t cryptoid;
+ int authsize, rplen, ahsize, error, skip, protoff;
uint8_t nxt;
m = (struct mbuf *) crp->crp_buf;
@@ -711,9 +721,9 @@ ah_input_cb(struct cryptop *crp)
if (crp->crp_etype) {
if (crp->crp_etype == EAGAIN) {
/* Reset the session ID */
- if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
+ if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
- xd->cryptoid = crp->crp_sid;
+ xd->cryptoid = crp->crp_session;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
@@ -738,6 +748,7 @@ ah_input_cb(struct cryptop *crp)
/* Figure out header size. */
rplen = HDRSIZE(sav);
authsize = AUTHSIZE(sav);
+ ahsize = ah_hdrsiz(sav);
/* Copy authenticator off the packet. */
m_copydata(m, skip + rplen, authsize, calc);
@@ -786,7 +797,7 @@ ah_input_cb(struct cryptop *crp)
/*
* Remove the AH header and authenticator from the mbuf.
*/
- error = m_striphdr(m, skip, rplen + authsize);
+ error = m_striphdr(m, skip, ahsize);
if (error) {
DPRINTF(("%s: mangled mbuf chain for SA %s/%08lx\n", __func__,
ipsec_address(&saidx->dst, buf, sizeof(buf)),
@@ -839,9 +850,9 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
struct mbuf *mi;
struct cryptop *crp;
struct newah *ah;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
uint16_t iplen;
- int error, rplen, authsize, maxpacketsize, roff;
+ int error, rplen, authsize, ahsize, maxpacketsize, roff;
uint8_t prot;
IPSEC_ASSERT(sav != NULL, ("null SA"));
@@ -852,6 +863,8 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
/* Figure out header size. */
rplen = HDRSIZE(sav);
+ authsize = AUTHSIZE(sav);
+ ahsize = ah_hdrsiz(sav);
/* Check for maximum packet size violations. */
switch (sav->sah->saidx.dst.sa.sa_family) {
@@ -875,13 +888,12 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
error = EPFNOSUPPORT;
goto bad;
}
- authsize = AUTHSIZE(sav);
- if (rplen + authsize + m->m_pkthdr.len > maxpacketsize) {
+ if (ahsize + m->m_pkthdr.len > maxpacketsize) {
DPRINTF(("%s: packet in SA %s/%08lx got too big "
"(len %u, max len %u)\n", __func__,
ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
(u_long) ntohl(sav->spi),
- rplen + authsize + m->m_pkthdr.len, maxpacketsize));
+ ahsize + m->m_pkthdr.len, maxpacketsize));
AHSTAT_INC(ahs_toobig);
error = EMSGSIZE;
goto bad;
@@ -901,11 +913,10 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
}
/* Inject AH header. */
- mi = m_makespace(m, skip, rplen + authsize, &roff);
+ mi = m_makespace(m, skip, ahsize, &roff);
if (mi == NULL) {
DPRINTF(("%s: failed to inject %u byte AH header for SA "
- "%s/%08lx\n", __func__,
- rplen + authsize,
+ "%s/%08lx\n", __func__, ahsize,
ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
(u_long) ntohl(sav->spi)));
AHSTAT_INC(ahs_hdrops); /*XXX differs from openbsd */
@@ -921,13 +932,17 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
/* Initialize the AH header. */
m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nxt);
- ah->ah_len = (rplen + authsize - sizeof(struct ah)) / sizeof(u_int32_t);
+ ah->ah_len = (ahsize - sizeof(struct ah)) / sizeof(u_int32_t);
ah->ah_reserve = 0;
ah->ah_spi = sav->spi;
/* Zeroize authenticator. */
m_copyback(m, skip + rplen, authsize, ipseczeroes);
+ /* Zeroize padding */
+ m_copyback(m, skip + rplen + authsize, ahsize - (rplen + authsize),
+ ipseczeroes);
+
/* Insert packet replay counter, as requested. */
SECASVAR_LOCK(sav);
if (sav->replay) {
@@ -996,7 +1011,7 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
bcopy(((caddr_t)(xd + 1)) +
offsetof(struct ip, ip_len),
(caddr_t) &iplen, sizeof(u_int16_t));
- iplen = htons(ntohs(iplen) + rplen + authsize);
+ iplen = htons(ntohs(iplen) + ahsize);
m_copyback(m, offsetof(struct ip, ip_len),
sizeof(u_int16_t), (caddr_t) &iplen);
break;
@@ -1007,7 +1022,7 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
bcopy(((caddr_t)(xd + 1)) +
offsetof(struct ip6_hdr, ip6_plen),
(caddr_t) &iplen, sizeof(uint16_t));
- iplen = htons(ntohs(iplen) + rplen + authsize);
+ iplen = htons(ntohs(iplen) + ahsize);
m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),
sizeof(uint16_t), (caddr_t) &iplen);
break;
@@ -1038,7 +1053,7 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
crp->crp_flags |= CRYPTO_F_ASYNC | CRYPTO_F_ASYNC_KEEPORDER;
crp->crp_buf = (caddr_t) m;
crp->crp_callback = ah_output_cb;
- crp->crp_sid = cryptoid;
+ crp->crp_session = cryptoid;
crp->crp_opaque = (caddr_t) xd;
/* These are passed as-is to the callback. */
@@ -1068,7 +1083,7 @@ ah_output_cb(struct cryptop *crp)
struct secpolicy *sp;
struct secasvar *sav;
struct mbuf *m;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
caddr_t ptr;
u_int idx;
int skip, error;
@@ -1087,9 +1102,9 @@ ah_output_cb(struct cryptop *crp)
if (crp->crp_etype) {
if (crp->crp_etype == EAGAIN) {
/* Reset the session ID */
- if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
+ if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
- xd->cryptoid = crp->crp_sid;
+ xd->cryptoid = crp->crp_session;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
diff --git a/freebsd/sys/netipsec/xform_esp.c b/freebsd/sys/netipsec/xform_esp.c
index 49b08ba6..f8473575 100644
--- a/freebsd/sys/netipsec/xform_esp.c
+++ b/freebsd/sys/netipsec/xform_esp.c
@@ -273,7 +273,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
struct cryptop *crp;
struct newesp *esp;
uint8_t *ivp;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
int alen, error, hlen, plen;
IPSEC_ASSERT(sav != NULL, ("null SA"));
@@ -391,7 +391,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
crp->crp_flags |= CRYPTO_F_ASYNC | CRYPTO_F_ASYNC_KEEPORDER;
crp->crp_buf = (caddr_t) m;
crp->crp_callback = esp_input_cb;
- crp->crp_sid = cryptoid;
+ crp->crp_session = cryptoid;
crp->crp_opaque = (caddr_t) xd;
/* These are passed as-is to the callback */
@@ -450,7 +450,7 @@ esp_input_cb(struct cryptop *crp)
struct secasvar *sav;
struct secasindex *saidx;
caddr_t ptr;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
int hlen, skip, protoff, error, alen;
crd = crp->crp_desc;
@@ -470,9 +470,9 @@ esp_input_cb(struct cryptop *crp)
if (crp->crp_etype) {
if (crp->crp_etype == EAGAIN) {
/* Reset the session ID */
- if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
+ if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
- xd->cryptoid = crp->crp_sid;
+ xd->cryptoid = crp->crp_session;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
@@ -639,7 +639,8 @@ esp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
struct secasindex *saidx;
unsigned char *pad;
uint8_t *ivp;
- uint64_t cntr, cryptoid;
+ uint64_t cntr;
+ crypto_session_t cryptoid;
int hlen, rlen, padding, blks, alen, i, roff;
int error, maxpacketsize;
uint8_t prot;
@@ -854,7 +855,7 @@ esp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
crp->crp_buf = (caddr_t) m;
crp->crp_callback = esp_output_cb;
crp->crp_opaque = (caddr_t) xd;
- crp->crp_sid = cryptoid;
+ crp->crp_session = cryptoid;
if (esph) {
/* Authentication descriptor. */
@@ -885,7 +886,7 @@ esp_output_cb(struct cryptop *crp)
struct secpolicy *sp;
struct secasvar *sav;
struct mbuf *m;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
u_int idx;
int error;
@@ -901,9 +902,9 @@ esp_output_cb(struct cryptop *crp)
if (crp->crp_etype) {
if (crp->crp_etype == EAGAIN) {
/* Reset the session ID */
- if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
+ if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
- xd->cryptoid = crp->crp_sid;
+ xd->cryptoid = crp->crp_session;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
diff --git a/freebsd/sys/netipsec/xform_ipcomp.c b/freebsd/sys/netipsec/xform_ipcomp.c
index b3fdee49..86addc87 100644
--- a/freebsd/sys/netipsec/xform_ipcomp.c
+++ b/freebsd/sys/netipsec/xform_ipcomp.c
@@ -120,7 +120,7 @@ ipcomp_encapcheck(union sockaddr_union *src, union sockaddr_union *dst)
}
static int
-ipcomp_nonexp_input(struct mbuf **mp, int *offp, int proto)
+ipcomp_nonexp_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
int isr;
@@ -137,13 +137,13 @@ ipcomp_nonexp_input(struct mbuf **mp, int *offp, int proto)
#endif
default:
IPCOMPSTAT_INC(ipcomps_nopf);
- m_freem(*mp);
+ m_freem(m);
return (IPPROTO_DONE);
}
- m_adj(*mp, *offp);
- IPCOMPSTAT_ADD(ipcomps_ibytes, (*mp)->m_pkthdr.len);
+ m_adj(m, off);
+ IPCOMPSTAT_ADD(ipcomps_ibytes, m->m_pkthdr.len);
IPCOMPSTAT_INC(ipcomps_input);
- netisr_dispatch(isr, *mp);
+ netisr_dispatch(isr, m);
return (IPPROTO_DONE);
}
@@ -180,11 +180,10 @@ ipcomp_init(struct secasvar *sav, struct xformsw *xsp)
static int
ipcomp_zeroize(struct secasvar *sav)
{
- int err;
- err = crypto_freesession(sav->tdb_cryptoid);
- sav->tdb_cryptoid = 0;
- return err;
+ crypto_freesession(sav->tdb_cryptoid);
+ sav->tdb_cryptoid = NULL;
+ return 0;
}
/*
@@ -260,7 +259,7 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
xd->vnet = curvnet;
SECASVAR_LOCK(sav);
- crp->crp_sid = xd->cryptoid = sav->tdb_cryptoid;
+ crp->crp_session = xd->cryptoid = sav->tdb_cryptoid;
SECASVAR_UNLOCK(sav);
return crypto_dispatch(crp);
@@ -282,7 +281,7 @@ ipcomp_input_cb(struct cryptop *crp)
struct secasvar *sav;
struct secasindex *saidx;
caddr_t addr;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
int hlen = IPCOMP_HLENGTH, error, clen;
int skip, protoff;
uint8_t nproto;
@@ -303,9 +302,9 @@ ipcomp_input_cb(struct cryptop *crp)
if (crp->crp_etype) {
if (crp->crp_etype == EAGAIN) {
/* Reset the session ID */
- if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
+ if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
- xd->cryptoid = crp->crp_sid;
+ xd->cryptoid = crp->crp_session;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
@@ -510,7 +509,7 @@ ipcomp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
crp->crp_opaque = (caddr_t) xd;
SECASVAR_LOCK(sav);
- crp->crp_sid = xd->cryptoid = sav->tdb_cryptoid;
+ crp->crp_session = xd->cryptoid = sav->tdb_cryptoid;
SECASVAR_UNLOCK(sav);
return crypto_dispatch(crp);
@@ -533,7 +532,7 @@ ipcomp_output_cb(struct cryptop *crp)
struct secpolicy *sp;
struct secasvar *sav;
struct mbuf *m;
- uint64_t cryptoid;
+ crypto_session_t cryptoid;
u_int idx;
int error, skip, protoff;
@@ -551,9 +550,9 @@ ipcomp_output_cb(struct cryptop *crp)
if (crp->crp_etype) {
if (crp->crp_etype == EAGAIN) {
/* Reset the session ID */
- if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
+ if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
- xd->cryptoid = crp->crp_sid;
+ xd->cryptoid = crp->crp_session;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
@@ -664,19 +663,6 @@ bad:
}
#ifdef INET
-static const struct encaptab *ipe4_cookie = NULL;
-extern struct domain inetdomain;
-static struct protosw ipcomp4_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = 0 /* IPPROTO_IPV[46] */,
- .pr_flags = PR_ATOMIC | PR_ADDR | PR_LASTHDR,
- .pr_input = ipcomp_nonexp_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
static int
ipcomp4_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
void *arg __unused)
@@ -697,21 +683,17 @@ ipcomp4_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
dst.sin.sin_addr = ip->ip_dst;
return (ipcomp_encapcheck(&src, &dst));
}
+
+static const struct encaptab *ipe4_cookie = NULL;
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = -1,
+ .min_length = sizeof(struct ip),
+ .exact_match = sizeof(in_addr_t) << 4,
+ .check = ipcomp4_nonexp_encapcheck,
+ .input = ipcomp_nonexp_input
+};
#endif
#ifdef INET6
-static const struct encaptab *ipe6_cookie = NULL;
-extern struct domain inet6domain;
-static struct protosw ipcomp6_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = 0 /* IPPROTO_IPV[46] */,
- .pr_flags = PR_ATOMIC | PR_ADDR | PR_LASTHDR,
- .pr_input = ipcomp_nonexp_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
-
static int
ipcomp6_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
void *arg __unused)
@@ -744,6 +726,15 @@ ipcomp6_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
}
return (ipcomp_encapcheck(&src, &dst));
}
+
+static const struct encaptab *ipe6_cookie = NULL;
+static const struct encap_config ipv6_encap_cfg = {
+ .proto = -1,
+ .min_length = sizeof(struct ip6_hdr),
+ .exact_match = sizeof(struct in6_addr) << 4,
+ .check = ipcomp6_nonexp_encapcheck,
+ .input = ipcomp_nonexp_input
+};
#endif
static struct xformsw ipcomp_xformsw = {
@@ -760,12 +751,10 @@ ipcomp_attach(void)
{
#ifdef INET
- ipe4_cookie = encap_attach_func(AF_INET, -1,
- ipcomp4_nonexp_encapcheck, &ipcomp4_protosw, NULL);
+ ipe4_cookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
#endif
#ifdef INET6
- ipe6_cookie = encap_attach_func(AF_INET6, -1,
- ipcomp6_nonexp_encapcheck, &ipcomp6_protosw, NULL);
+ ipe6_cookie = ip6_encap_attach(&ipv6_encap_cfg, NULL, M_WAITOK);
#endif
xform_attach(&ipcomp_xformsw);
}
@@ -775,10 +764,10 @@ ipcomp_detach(void)
{
#ifdef INET
- encap_detach(ipe4_cookie);
+ ip_encap_detach(ipe4_cookie);
#endif
#ifdef INET6
- encap_detach(ipe6_cookie);
+ ip6_encap_detach(ipe6_cookie);
#endif
xform_detach(&ipcomp_xformsw);
}
diff --git a/freebsd/sys/netipsec/xform_tcp.c b/freebsd/sys/netipsec/xform_tcp.c
index 9310cf2c..f9cd3964 100644
--- a/freebsd/sys/netipsec/xform_tcp.c
+++ b/freebsd/sys/netipsec/xform_tcp.c
@@ -82,23 +82,24 @@ tcp_ipsec_pcbctl(struct inpcb *inp, struct sockopt *sopt)
struct tcpcb *tp;
int error, optval;
- INP_WLOCK_ASSERT(inp);
if (sopt->sopt_name != TCP_MD5SIG) {
- INP_WUNLOCK(inp);
return (ENOPROTOOPT);
}
- tp = intotcpcb(inp);
if (sopt->sopt_dir == SOPT_GET) {
+ INP_RLOCK(inp);
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_RUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ tp = intotcpcb(inp);
optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
/* On success return with released INP_WLOCK */
return (sooptcopyout(sopt, &optval, sizeof(optval)));
}
- INP_WUNLOCK(inp);
-
error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
if (error != 0)
return (error);
@@ -109,12 +110,13 @@ tcp_ipsec_pcbctl(struct inpcb *inp, struct sockopt *sopt)
INP_WUNLOCK(inp);
return (ECONNRESET);
}
+ tp = intotcpcb(inp);
if (optval > 0)
tp->t_flags |= TF_SIGNATURE;
else
tp->t_flags &= ~TF_SIGNATURE;
- /* On success return with acquired INP_WLOCK */
+ INP_WUNLOCK(inp);
return (error);
}
diff --git a/freebsd/sys/netpfil/pf/if_pflog.c b/freebsd/sys/netpfil/pf/if_pflog.c
index 53cf94c8..3da5d8c0 100644
--- a/freebsd/sys/netpfil/pf/if_pflog.c
+++ b/freebsd/sys/netpfil/pf/if_pflog.c
@@ -98,7 +98,7 @@ static void pflog_clone_destroy(struct ifnet *);
static const char pflogname[] = "pflog";
-static VNET_DEFINE(struct if_clone *, pflog_cloner);
+VNET_DEFINE_STATIC(struct if_clone *, pflog_cloner);
#define V_pflog_cloner VNET(pflog_cloner)
VNET_DEFINE(struct ifnet *, pflogifs[PFLOGIFS_MAX]); /* for fast access */
diff --git a/freebsd/sys/netpfil/pf/if_pfsync.c b/freebsd/sys/netpfil/pf/if_pfsync.c
index 9b457818..dae091db 100644
--- a/freebsd/sys/netpfil/pf/if_pfsync.c
+++ b/freebsd/sys/netpfil/pf/if_pfsync.c
@@ -231,13 +231,13 @@ struct pfsync_softc {
static const char pfsyncname[] = "pfsync";
static MALLOC_DEFINE(M_PFSYNC, pfsyncname, "pfsync(4) data");
-static VNET_DEFINE(struct pfsync_softc *, pfsyncif) = NULL;
+VNET_DEFINE_STATIC(struct pfsync_softc *, pfsyncif) = NULL;
#define V_pfsyncif VNET(pfsyncif)
-static VNET_DEFINE(void *, pfsync_swi_cookie) = NULL;
+VNET_DEFINE_STATIC(void *, pfsync_swi_cookie) = NULL;
#define V_pfsync_swi_cookie VNET(pfsync_swi_cookie)
-static VNET_DEFINE(struct pfsyncstats, pfsyncstats);
+VNET_DEFINE_STATIC(struct pfsyncstats, pfsyncstats);
#define V_pfsyncstats VNET(pfsyncstats)
-static VNET_DEFINE(int, pfsync_carp_adj) = CARP_MAXSKEW;
+VNET_DEFINE_STATIC(int, pfsync_carp_adj) = CARP_MAXSKEW;
#define V_pfsync_carp_adj VNET(pfsync_carp_adj)
static void pfsync_timeout(void *);
@@ -871,7 +871,7 @@ pfsync_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
st = pf_find_state_byid(sp->id, sp->creatorid);
if (st == NULL) {
/* insert the update */
- if (pfsync_state_import(sp, 0))
+ if (pfsync_state_import(sp, pkt->flags))
V_pfsyncstats.pfsyncs_badstate++;
continue;
}
diff --git a/freebsd/sys/netpfil/pf/pf.c b/freebsd/sys/netpfil/pf/pf.c
index 3cc4ff11..f765350d 100644
--- a/freebsd/sys/netpfil/pf/pf.c
+++ b/freebsd/sys/netpfil/pf/pf.c
@@ -137,7 +137,7 @@ VNET_DEFINE(int, pf_tcp_iss_off);
VNET_DECLARE(int, pf_vnet_active);
#define V_pf_vnet_active VNET(pf_vnet_active)
-static VNET_DEFINE(uint32_t, pf_purge_idx);
+VNET_DEFINE_STATIC(uint32_t, pf_purge_idx);
#define V_pf_purge_idx VNET(pf_purge_idx)
/*
@@ -161,7 +161,7 @@ struct pf_send_entry {
};
STAILQ_HEAD(pf_send_head, pf_send_entry);
-static VNET_DEFINE(struct pf_send_head, pf_sendqueue);
+VNET_DEFINE_STATIC(struct pf_send_head, pf_sendqueue);
#define V_pf_sendqueue VNET(pf_sendqueue)
static struct mtx pf_sendqueue_mtx;
@@ -181,9 +181,9 @@ struct pf_overload_entry {
};
SLIST_HEAD(pf_overload_head, pf_overload_entry);
-static VNET_DEFINE(struct pf_overload_head, pf_overloadqueue);
+VNET_DEFINE_STATIC(struct pf_overload_head, pf_overloadqueue);
#define V_pf_overloadqueue VNET(pf_overloadqueue)
-static VNET_DEFINE(struct task, pf_overloadtask);
+VNET_DEFINE_STATIC(struct task, pf_overloadtask);
#define V_pf_overloadtask VNET(pf_overloadtask)
static struct mtx pf_overloadqueue_mtx;
@@ -197,7 +197,7 @@ struct mtx pf_unlnkdrules_mtx;
MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules",
MTX_DEF);
-static VNET_DEFINE(uma_zone_t, pf_sources_z);
+VNET_DEFINE_STATIC(uma_zone_t, pf_sources_z);
#define V_pf_sources_z VNET(pf_sources_z)
uma_zone_t pf_mtag_z;
VNET_DEFINE(uma_zone_t, pf_state_z);
@@ -297,14 +297,14 @@ static void pf_mtag_free(struct m_tag *);
#ifdef INET
static void pf_route(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *,
- struct pf_pdesc *);
+ struct pf_pdesc *, struct inpcb *);
#endif /* INET */
#ifdef INET6
static void pf_change_a6(struct pf_addr *, u_int16_t *,
struct pf_addr *, u_int8_t);
static void pf_route6(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *,
- struct pf_pdesc *);
+ struct pf_pdesc *, struct inpcb *);
#endif /* INET6 */
int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
@@ -1721,24 +1721,28 @@ pf_purge_expired_states(u_int i, int maxcheck)
while (maxcheck > 0) {
ih = &V_pf_idhash[i];
+
+ /* only take the lock if we expect to do work */
+ if (!LIST_EMPTY(&ih->states)) {
relock:
- PF_HASHROW_LOCK(ih);
- LIST_FOREACH(s, &ih->states, entry) {
- if (pf_state_expires(s) <= time_uptime) {
- V_pf_status.states -=
- pf_unlink_state(s, PF_ENTER_LOCKED);
- goto relock;
+ PF_HASHROW_LOCK(ih);
+ LIST_FOREACH(s, &ih->states, entry) {
+ if (pf_state_expires(s) <= time_uptime) {
+ V_pf_status.states -=
+ pf_unlink_state(s, PF_ENTER_LOCKED);
+ goto relock;
+ }
+ s->rule.ptr->rule_flag |= PFRULE_REFS;
+ if (s->nat_rule.ptr != NULL)
+ s->nat_rule.ptr->rule_flag |= PFRULE_REFS;
+ if (s->anchor.ptr != NULL)
+ s->anchor.ptr->rule_flag |= PFRULE_REFS;
+ s->kif->pfik_flags |= PFI_IFLAG_REFS;
+ if (s->rt_kif)
+ s->rt_kif->pfik_flags |= PFI_IFLAG_REFS;
}
- s->rule.ptr->rule_flag |= PFRULE_REFS;
- if (s->nat_rule.ptr != NULL)
- s->nat_rule.ptr->rule_flag |= PFRULE_REFS;
- if (s->anchor.ptr != NULL)
- s->anchor.ptr->rule_flag |= PFRULE_REFS;
- s->kif->pfik_flags |= PFI_IFLAG_REFS;
- if (s->rt_kif)
- s->rt_kif->pfik_flags |= PFI_IFLAG_REFS;
+ PF_HASHROW_UNLOCK(ih);
}
- PF_HASHROW_UNLOCK(ih);
/* Return when we hit end of hash. */
if (++i > pf_hashmask) {
@@ -2501,6 +2505,81 @@ pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af,
pf_send(pfse);
}
+static void
+pf_return(struct pf_rule *r, struct pf_rule *nr, struct pf_pdesc *pd,
+ struct pf_state_key *sk, int off, struct mbuf *m, struct tcphdr *th,
+ struct pfi_kif *kif, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen,
+ u_short *reason)
+{
+ struct pf_addr * const saddr = pd->src;
+ struct pf_addr * const daddr = pd->dst;
+ sa_family_t af = pd->af;
+
+ /* undo NAT changes, if they have taken place */
+ if (nr != NULL) {
+ PF_ACPY(saddr, &sk->addr[pd->sidx], af);
+ PF_ACPY(daddr, &sk->addr[pd->didx], af);
+ if (pd->sport)
+ *pd->sport = sk->port[pd->sidx];
+ if (pd->dport)
+ *pd->dport = sk->port[pd->didx];
+ if (pd->proto_sum)
+ *pd->proto_sum = bproto_sum;
+ if (pd->ip_sum)
+ *pd->ip_sum = bip_sum;
+ m_copyback(m, off, hdrlen, pd->hdr.any);
+ }
+ if (pd->proto == IPPROTO_TCP &&
+ ((r->rule_flag & PFRULE_RETURNRST) ||
+ (r->rule_flag & PFRULE_RETURN)) &&
+ !(th->th_flags & TH_RST)) {
+ u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
+ int len = 0;
+#ifdef INET
+ struct ip *h4;
+#endif
+#ifdef INET6
+ struct ip6_hdr *h6;
+#endif
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ h4 = mtod(m, struct ip *);
+ len = ntohs(h4->ip_len) - off;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ h6 = mtod(m, struct ip6_hdr *);
+ len = ntohs(h6->ip6_plen) - (off - sizeof(*h6));
+ break;
+#endif
+ }
+
+ if (pf_check_proto_cksum(m, off, len, IPPROTO_TCP, af))
+ REASON_SET(reason, PFRES_PROTCKSUM);
+ else {
+ if (th->th_flags & TH_SYN)
+ ack++;
+ if (th->th_flags & TH_FIN)
+ ack++;
+ pf_send_tcp(m, r, af, pd->dst,
+ pd->src, th->th_dport, th->th_sport,
+ ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
+ r->return_ttl, 1, 0, kif->pfik_ifp);
+ }
+ } else if (pd->proto != IPPROTO_ICMP && af == AF_INET &&
+ r->return_icmp)
+ pf_send_icmp(m, r->return_icmp >> 8,
+ r->return_icmp & 255, af, r);
+ else if (pd->proto != IPPROTO_ICMPV6 && af == AF_INET6 &&
+ r->return_icmp6)
+ pf_send_icmp(m, r->return_icmp6 >> 8,
+ r->return_icmp6 & 255, af, r);
+}
+
+
static int
pf_ieee8021q_setpcp(struct mbuf *m, u_int8_t prio)
{
@@ -3475,68 +3554,8 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
((r->rule_flag & PFRULE_RETURNRST) ||
(r->rule_flag & PFRULE_RETURNICMP) ||
(r->rule_flag & PFRULE_RETURN))) {
- /* undo NAT changes, if they have taken place */
- if (nr != NULL) {
- PF_ACPY(saddr, &sk->addr[pd->sidx], af);
- PF_ACPY(daddr, &sk->addr[pd->didx], af);
- if (pd->sport)
- *pd->sport = sk->port[pd->sidx];
- if (pd->dport)
- *pd->dport = sk->port[pd->didx];
- if (pd->proto_sum)
- *pd->proto_sum = bproto_sum;
- if (pd->ip_sum)
- *pd->ip_sum = bip_sum;
- m_copyback(m, off, hdrlen, pd->hdr.any);
- }
- if (pd->proto == IPPROTO_TCP &&
- ((r->rule_flag & PFRULE_RETURNRST) ||
- (r->rule_flag & PFRULE_RETURN)) &&
- !(th->th_flags & TH_RST)) {
- u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
- int len = 0;
-#ifdef INET
- struct ip *h4;
-#endif
-#ifdef INET6
- struct ip6_hdr *h6;
-#endif
-
- switch (af) {
-#ifdef INET
- case AF_INET:
- h4 = mtod(m, struct ip *);
- len = ntohs(h4->ip_len) - off;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- h6 = mtod(m, struct ip6_hdr *);
- len = ntohs(h6->ip6_plen) - (off - sizeof(*h6));
- break;
-#endif
- }
-
- if (pf_check_proto_cksum(m, off, len, IPPROTO_TCP, af))
- REASON_SET(&reason, PFRES_PROTCKSUM);
- else {
- if (th->th_flags & TH_SYN)
- ack++;
- if (th->th_flags & TH_FIN)
- ack++;
- pf_send_tcp(m, r, af, pd->dst,
- pd->src, th->th_dport, th->th_sport,
- ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
- r->return_ttl, 1, 0, kif->pfik_ifp);
- }
- } else if (pd->proto != IPPROTO_ICMP && af == AF_INET &&
- r->return_icmp)
- pf_send_icmp(m, r->return_icmp >> 8,
- r->return_icmp & 255, af, r);
- else if (pd->proto != IPPROTO_ICMPV6 && af == AF_INET6 &&
- r->return_icmp6)
- pf_send_icmp(m, r->return_icmp6 >> 8,
- r->return_icmp6 & 255, af, r);
+ pf_return(r, nr, pd, sk, off, m, th, kif, bproto_sum,
+ bip_sum, hdrlen, &reason);
}
if (r->action == PF_DROP)
@@ -3555,8 +3574,13 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
action = pf_create_state(r, nr, a, pd, nsn, nk, sk, m, off,
sport, dport, &rewrite, kif, sm, tag, bproto_sum, bip_sum,
hdrlen);
- if (action != PF_PASS)
+ if (action != PF_PASS) {
+ if (action == PF_DROP &&
+ (r->rule_flag & PFRULE_RETURN))
+ pf_return(r, nr, pd, sk, off, m, th, kif,
+ bproto_sum, bip_sum, hdrlen, &reason);
return (action);
+ }
} else {
if (sk != NULL)
uma_zfree(V_pf_state_key_z, sk);
@@ -5454,7 +5478,7 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif,
#ifdef INET
static void
pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
- struct pf_state *s, struct pf_pdesc *pd)
+ struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp)
{
struct mbuf *m0, *m1;
struct sockaddr_in dst;
@@ -5522,7 +5546,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
goto bad;
if (oifp != ifp) {
- if (pf_test(PF_OUT, 0, ifp, &m0, NULL) != PF_PASS)
+ if (pf_test(PF_OUT, 0, ifp, &m0, inp) != PF_PASS)
goto bad;
else if (m0 == NULL)
goto done;
@@ -5615,7 +5639,7 @@ bad:
#ifdef INET6
static void
pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
- struct pf_state *s, struct pf_pdesc *pd)
+ struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp)
{
struct mbuf *m0;
struct sockaddr_in6 dst;
@@ -5684,7 +5708,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
goto bad;
if (oifp != ifp) {
- if (pf_test6(PF_OUT, PFIL_FWD, ifp, &m0, NULL) != PF_PASS)
+ if (pf_test6(PF_OUT, PFIL_FWD, ifp, &m0, inp) != PF_PASS)
goto bad;
else if (m0 == NULL)
goto done;
@@ -6248,7 +6272,7 @@ done:
default:
/* pf_route() returns unlocked. */
if (r->rt) {
- pf_route(m0, r, dir, kif->pfik_ifp, s, &pd);
+ pf_route(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
return (action);
}
break;
@@ -6645,7 +6669,7 @@ done:
default:
/* pf_route6() returns unlocked. */
if (r->rt) {
- pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd);
+ pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
return (action);
}
break;
diff --git a/freebsd/sys/netpfil/pf/pf_altq.h b/freebsd/sys/netpfil/pf/pf_altq.h
index f6d578d3..35d2d5cb 100644
--- a/freebsd/sys/netpfil/pf/pf_altq.h
+++ b/freebsd/sys/netpfil/pf/pf_altq.h
@@ -57,7 +57,7 @@ struct priq_opts {
int flags;
};
-struct hfsc_opts {
+struct hfsc_opts_v0 {
/* real-time service curve */
u_int rtsc_m1; /* slope of the 1st segment in bps */
u_int rtsc_d; /* the x-projection of m1 in msec */
@@ -73,6 +73,31 @@ struct hfsc_opts {
int flags;
};
+struct hfsc_opts_v1 {
+ /* real-time service curve */
+ u_int64_t rtsc_m1; /* slope of the 1st segment in bps */
+ u_int rtsc_d; /* the x-projection of m1 in msec */
+ u_int64_t rtsc_m2; /* slope of the 2nd segment in bps */
+ /* link-sharing service curve */
+ u_int64_t lssc_m1;
+ u_int lssc_d;
+ u_int64_t lssc_m2;
+ /* upper-limit service curve */
+ u_int64_t ulsc_m1;
+ u_int ulsc_d;
+ u_int64_t ulsc_m2;
+ int flags;
+};
+
+/*
+ * struct hfsc_opts doesn't have a version indicator macro or
+ * backwards-compat and convenience macros because both in the kernel and
+ * the pfctl parser, there are struct hfsc_opts instances named 'hfsc_opts'.
+ * It is believed that only in-tree code uses struct hfsc_opts, so
+ * backwards-compat macros are not necessary. The few in-tree uses can just
+ * be updated to the latest versioned struct tag.
+ */
+
/*
* XXX this needs some work
*/
@@ -87,11 +112,22 @@ struct fairq_opts {
u_int lssc_m2;
};
-struct pf_altq {
+/*
+ * struct pf_altq_v0, struct pf_altq_v1, etc. are the ioctl argument
+ * structures corresponding to struct pfioc_altq_v0, struct pfioc_altq_v1,
+ * etc.
+ *
+ */
+struct pf_altq_v0 {
char ifname[IFNAMSIZ];
- void *altq_disc; /* discipline-specific state */
- TAILQ_ENTRY(pf_altq) entries;
+ /*
+ * This member is a holdover from when the kernel state structure
+ * was reused as the ioctl argument structure, and remains to
+ * preserve the size and layout of this struct for backwards compat.
+ */
+ void *unused1;
+ TAILQ_ENTRY(pf_altq_v0) entries;
/* scheduler spec */
uint8_t scheduler; /* scheduler type */
@@ -113,11 +149,110 @@ struct pf_altq {
struct cbq_opts cbq_opts;
struct codel_opts codel_opts;
struct priq_opts priq_opts;
- struct hfsc_opts hfsc_opts;
+ struct hfsc_opts_v0 hfsc_opts;
+ struct fairq_opts fairq_opts;
+ } pq_u;
+
+ uint32_t qid; /* return value */
+};
+
+struct pf_altq_v1 {
+ char ifname[IFNAMSIZ];
+
+ TAILQ_ENTRY(pf_altq_v1) entries;
+
+ /* scheduler spec */
+ uint8_t scheduler; /* scheduler type */
+ uint32_t tbrsize; /* tokenbucket regulator size */
+ uint64_t ifbandwidth; /* interface bandwidth */
+
+ /* queue spec */
+ char qname[PF_QNAME_SIZE]; /* queue name */
+ char parent[PF_QNAME_SIZE]; /* parent name */
+ uint32_t parent_qid; /* parent queue id */
+ uint64_t bandwidth; /* queue bandwidth */
+ uint8_t priority; /* priority */
+ uint8_t local_flags; /* dynamic interface, see _v0 */
+
+ uint16_t qlimit; /* queue size limit */
+ uint16_t flags; /* misc flags */
+ union {
+ struct cbq_opts cbq_opts;
+ struct codel_opts codel_opts;
+ struct priq_opts priq_opts;
+ struct hfsc_opts_v1 hfsc_opts;
struct fairq_opts fairq_opts;
} pq_u;
uint32_t qid; /* return value */
};
+/* Latest version of struct pf_altq_vX */
+#define PF_ALTQ_VERSION 1
+
+#ifdef _KERNEL
+struct pf_kaltq {
+ char ifname[IFNAMSIZ];
+
+ void *altq_disc; /* discipline-specific state */
+ TAILQ_ENTRY(pf_kaltq) entries;
+
+ /* scheduler spec */
+ uint8_t scheduler; /* scheduler type */
+ uint32_t tbrsize; /* tokenbucket regulator size */
+ uint64_t ifbandwidth; /* interface bandwidth */
+
+ /* queue spec */
+ char qname[PF_QNAME_SIZE]; /* queue name */
+ char parent[PF_QNAME_SIZE]; /* parent name */
+ uint32_t parent_qid; /* parent queue id */
+ uint64_t bandwidth; /* queue bandwidth */
+ uint8_t priority; /* priority */
+ uint8_t local_flags; /* dynamic interface, see _v0 */
+
+ uint16_t qlimit; /* queue size limit */
+ uint16_t flags; /* misc flags */
+ union {
+ struct cbq_opts cbq_opts;
+ struct codel_opts codel_opts;
+ struct priq_opts priq_opts;
+ struct hfsc_opts_v1 hfsc_opts;
+ struct fairq_opts fairq_opts;
+ } pq_u;
+
+ uint32_t qid; /* return value */
+};
+#endif /* _KERNEL */
+
+/*
+ * Compatibility and convenience macros
+ */
+#ifdef _KERNEL
+/*
+ * Avoid a patch with 100+ lines of name substitution.
+ */
+#define pf_altq pf_kaltq
+
+#else /* _KERNEL */
+
+#ifdef PFIOC_USE_LATEST
+/*
+ * Maintaining in-tree consumers of the ioctl interface is easier when that
+ * code can be written in terms old names that refer to the latest interface
+ * version as that reduces the required changes in the consumers to those
+ * that are functionally necessary to accommodate a new interface version.
+ */
+#define pf_altq __CONCAT(pf_altq_v, PF_ALTQ_VERSION)
+
+#else /* PFIOC_USE_LATEST */
+/*
+ * When building out-of-tree code that is written for the old interface,
+ * such as may exist in ports for example, resolve the old pf_altq struct
+ * tag to the v0 version.
+ */
+#define pf_altq __CONCAT(pf_altq_v, 0)
+
+#endif /* PFIOC_USE_LATEST */
+#endif /* _KERNEL */
+
#endif /* _NET_PF_ALTQ_H_ */
diff --git a/freebsd/sys/netpfil/pf/pf_if.c b/freebsd/sys/netpfil/pf/pf_if.c
index 2ac76ff2..2c321118 100644
--- a/freebsd/sys/netpfil/pf/pf_if.c
+++ b/freebsd/sys/netpfil/pf/pf_if.c
@@ -57,16 +57,16 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
VNET_DEFINE(struct pfi_kif *, pfi_all);
-static VNET_DEFINE(long, pfi_update);
+VNET_DEFINE_STATIC(long, pfi_update);
#define V_pfi_update VNET(pfi_update)
#define PFI_BUFFER_MAX 0x10000
VNET_DECLARE(int, pf_vnet_active);
#define V_pf_vnet_active VNET(pf_vnet_active)
-static VNET_DEFINE(struct pfr_addr *, pfi_buffer);
-static VNET_DEFINE(int, pfi_buffer_cnt);
-static VNET_DEFINE(int, pfi_buffer_max);
+VNET_DEFINE_STATIC(struct pfr_addr *, pfi_buffer);
+VNET_DEFINE_STATIC(int, pfi_buffer_cnt);
+VNET_DEFINE_STATIC(int, pfi_buffer_max);
#define V_pfi_buffer VNET(pfi_buffer)
#define V_pfi_buffer_cnt VNET(pfi_buffer_cnt)
#define V_pfi_buffer_max VNET(pfi_buffer_max)
@@ -100,14 +100,14 @@ static void pfi_ifaddr_event(void * __unused, struct ifnet *);
RB_HEAD(pfi_ifhead, pfi_kif);
static RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
static RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
-static VNET_DEFINE(struct pfi_ifhead, pfi_ifs);
+VNET_DEFINE_STATIC(struct pfi_ifhead, pfi_ifs);
#define V_pfi_ifs VNET(pfi_ifs)
#define PFI_BUFFER_MAX 0x10000
MALLOC_DEFINE(PFI_MTYPE, "pf_ifnet", "pf(4) interface database");
LIST_HEAD(pfi_list, pfi_kif);
-static VNET_DEFINE(struct pfi_list, pfi_unlinked_kifs);
+VNET_DEFINE_STATIC(struct pfi_list, pfi_unlinked_kifs);
#define V_pfi_unlinked_kifs VNET(pfi_unlinked_kifs)
static struct mtx pfi_unlnkdkifs_mtx;
MTX_SYSINIT(pfi_unlnkdkifs_mtx, &pfi_unlnkdkifs_mtx, "pf unlinked interfaces",
@@ -299,11 +299,16 @@ pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif)
if (rule_kif == NULL || rule_kif == packet_kif)
return (1);
- if (rule_kif->pfik_group != NULL)
- /* XXXGL: locking? */
+ if (rule_kif->pfik_group != NULL) {
+ IF_ADDR_RLOCK(packet_kif->pfik_ifp);
CK_STAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next)
- if (p->ifgl_group == rule_kif->pfik_group)
+ if (p->ifgl_group == rule_kif->pfik_group) {
+ IF_ADDR_RUNLOCK(packet_kif->pfik_ifp);
return (1);
+ }
+ IF_ADDR_RUNLOCK(packet_kif->pfik_ifp);
+ }
+
return (0);
}
@@ -737,6 +742,7 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
static int
pfi_skip_if(const char *filter, struct pfi_kif *p)
{
+ struct ifg_list *i;
int n;
if (filter == NULL || !*filter)
@@ -747,10 +753,19 @@ pfi_skip_if(const char *filter, struct pfi_kif *p)
if (n < 1 || n >= IFNAMSIZ)
return (1); /* sanity check */
if (filter[n-1] >= '0' && filter[n-1] <= '9')
- return (1); /* only do exact match in that case */
- if (strncmp(p->pfik_name, filter, n))
- return (1); /* prefix doesn't match */
- return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9');
+ return (1); /* group names may not end in a digit */
+ if (p->pfik_ifp != NULL) {
+ IF_ADDR_RLOCK(p->pfik_ifp);
+ CK_STAILQ_FOREACH(i, &p->pfik_ifp->if_groups, ifgl_next) {
+ if (!strncmp(i->ifgl_group->ifg_group, filter,
+ IFNAMSIZ)) {
+ IF_ADDR_RUNLOCK(p->pfik_ifp);
+ return (0); /* iface is in group "filter" */
+ }
+ }
+ IF_ADDR_RUNLOCK(p->pfik_ifp);
+ }
+ return (1);
}
int
diff --git a/freebsd/sys/netpfil/pf/pf_ioctl.c b/freebsd/sys/netpfil/pf/pf_ioctl.c
index 837ad31c..9ca15a41 100644
--- a/freebsd/sys/netpfil/pf/pf_ioctl.c
+++ b/freebsd/sys/netpfil/pf/pf_ioctl.c
@@ -115,11 +115,17 @@ static int pf_commit_rules(u_int32_t, int, char *);
static int pf_addr_setup(struct pf_ruleset *,
struct pf_addr_wrap *, sa_family_t);
static void pf_addr_copyout(struct pf_addr_wrap *);
+#ifdef ALTQ
+static int pf_export_kaltq(struct pf_altq *,
+ struct pfioc_altq_v1 *, size_t);
+static int pf_import_kaltq(struct pfioc_altq_v1 *,
+ struct pf_altq *, size_t);
+#endif /* ALTQ */
VNET_DEFINE(struct pf_rule, pf_default_rule);
#ifdef ALTQ
-static VNET_DEFINE(int, pf_altq_running);
+VNET_DEFINE_STATIC(int, pf_altq_running);
#define V_pf_altq_running VNET(pf_altq_running)
#endif
@@ -189,7 +195,7 @@ static struct cdevsw pf_cdevsw = {
.d_version = D_VERSION,
};
-static volatile VNET_DEFINE(int, pf_pfil_hooked);
+volatile VNET_DEFINE_STATIC(int, pf_pfil_hooked);
#define V_pf_pfil_hooked VNET(pf_pfil_hooked)
/*
@@ -992,6 +998,222 @@ pf_addr_copyout(struct pf_addr_wrap *addr)
}
}
+#ifdef ALTQ
+/*
+ * Handle export of struct pf_kaltq to user binaries that may be using any
+ * version of struct pf_altq.
+ */
+static int
+pf_export_kaltq(struct pf_altq *q, struct pfioc_altq_v1 *pa, size_t ioc_size)
+{
+ u_int32_t version;
+
+ if (ioc_size == sizeof(struct pfioc_altq_v0))
+ version = 0;
+ else
+ version = pa->version;
+
+ if (version > PFIOC_ALTQ_VERSION)
+ return (EINVAL);
+
+#define ASSIGN(x) exported_q->x = q->x
+#define COPY(x) \
+ bcopy(&q->x, &exported_q->x, min(sizeof(q->x), sizeof(exported_q->x)))
+#define SATU16(x) (u_int32_t)uqmin((x), USHRT_MAX)
+#define SATU32(x) (u_int32_t)uqmin((x), UINT_MAX)
+
+ switch (version) {
+ case 0: {
+ struct pf_altq_v0 *exported_q =
+ &((struct pfioc_altq_v0 *)pa)->altq;
+
+ COPY(ifname);
+
+ ASSIGN(scheduler);
+ ASSIGN(tbrsize);
+ exported_q->tbrsize = SATU16(q->tbrsize);
+ exported_q->ifbandwidth = SATU32(q->ifbandwidth);
+
+ COPY(qname);
+ COPY(parent);
+ ASSIGN(parent_qid);
+ exported_q->bandwidth = SATU32(q->bandwidth);
+ ASSIGN(priority);
+ ASSIGN(local_flags);
+
+ ASSIGN(qlimit);
+ ASSIGN(flags);
+
+ if (q->scheduler == ALTQT_HFSC) {
+#define ASSIGN_OPT(x) exported_q->pq_u.hfsc_opts.x = q->pq_u.hfsc_opts.x
+#define ASSIGN_OPT_SATU32(x) exported_q->pq_u.hfsc_opts.x = \
+ SATU32(q->pq_u.hfsc_opts.x)
+
+ ASSIGN_OPT_SATU32(rtsc_m1);
+ ASSIGN_OPT(rtsc_d);
+ ASSIGN_OPT_SATU32(rtsc_m2);
+
+ ASSIGN_OPT_SATU32(lssc_m1);
+ ASSIGN_OPT(lssc_d);
+ ASSIGN_OPT_SATU32(lssc_m2);
+
+ ASSIGN_OPT_SATU32(ulsc_m1);
+ ASSIGN_OPT(ulsc_d);
+ ASSIGN_OPT_SATU32(ulsc_m2);
+
+ ASSIGN_OPT(flags);
+
+#undef ASSIGN_OPT
+#undef ASSIGN_OPT_SATU32
+ } else
+ COPY(pq_u);
+
+ ASSIGN(qid);
+ break;
+ }
+ case 1: {
+ struct pf_altq_v1 *exported_q =
+ &((struct pfioc_altq_v1 *)pa)->altq;
+
+ COPY(ifname);
+
+ ASSIGN(scheduler);
+ ASSIGN(tbrsize);
+ ASSIGN(ifbandwidth);
+
+ COPY(qname);
+ COPY(parent);
+ ASSIGN(parent_qid);
+ ASSIGN(bandwidth);
+ ASSIGN(priority);
+ ASSIGN(local_flags);
+
+ ASSIGN(qlimit);
+ ASSIGN(flags);
+ COPY(pq_u);
+
+ ASSIGN(qid);
+ break;
+ }
+ default:
+ panic("%s: unhandled struct pfioc_altq version", __func__);
+ break;
+ }
+
+#undef ASSIGN
+#undef COPY
+#undef SATU16
+#undef SATU32
+
+ return (0);
+}
+
+/*
+ * Handle import to struct pf_kaltq of struct pf_altq from user binaries
+ * that may be using any version of it.
+ */
+static int
+pf_import_kaltq(struct pfioc_altq_v1 *pa, struct pf_altq *q, size_t ioc_size)
+{
+ u_int32_t version;
+
+ if (ioc_size == sizeof(struct pfioc_altq_v0))
+ version = 0;
+ else
+ version = pa->version;
+
+ if (version > PFIOC_ALTQ_VERSION)
+ return (EINVAL);
+
+#define ASSIGN(x) q->x = imported_q->x
+#define COPY(x) \
+ bcopy(&imported_q->x, &q->x, min(sizeof(imported_q->x), sizeof(q->x)))
+
+ switch (version) {
+ case 0: {
+ struct pf_altq_v0 *imported_q =
+ &((struct pfioc_altq_v0 *)pa)->altq;
+
+ COPY(ifname);
+
+ ASSIGN(scheduler);
+ ASSIGN(tbrsize); /* 16-bit -> 32-bit */
+ ASSIGN(ifbandwidth); /* 32-bit -> 64-bit */
+
+ COPY(qname);
+ COPY(parent);
+ ASSIGN(parent_qid);
+ ASSIGN(bandwidth); /* 32-bit -> 64-bit */
+ ASSIGN(priority);
+ ASSIGN(local_flags);
+
+ ASSIGN(qlimit);
+ ASSIGN(flags);
+
+ if (imported_q->scheduler == ALTQT_HFSC) {
+#define ASSIGN_OPT(x) q->pq_u.hfsc_opts.x = imported_q->pq_u.hfsc_opts.x
+
+ /*
+ * The m1 and m2 parameters are being copied from
+ * 32-bit to 64-bit.
+ */
+ ASSIGN_OPT(rtsc_m1);
+ ASSIGN_OPT(rtsc_d);
+ ASSIGN_OPT(rtsc_m2);
+
+ ASSIGN_OPT(lssc_m1);
+ ASSIGN_OPT(lssc_d);
+ ASSIGN_OPT(lssc_m2);
+
+ ASSIGN_OPT(ulsc_m1);
+ ASSIGN_OPT(ulsc_d);
+ ASSIGN_OPT(ulsc_m2);
+
+ ASSIGN_OPT(flags);
+
+#undef ASSIGN_OPT
+ } else
+ COPY(pq_u);
+
+ ASSIGN(qid);
+ break;
+ }
+ case 1: {
+ struct pf_altq_v1 *imported_q =
+ &((struct pfioc_altq_v1 *)pa)->altq;
+
+ COPY(ifname);
+
+ ASSIGN(scheduler);
+ ASSIGN(tbrsize);
+ ASSIGN(ifbandwidth);
+
+ COPY(qname);
+ COPY(parent);
+ ASSIGN(parent_qid);
+ ASSIGN(bandwidth);
+ ASSIGN(priority);
+ ASSIGN(local_flags);
+
+ ASSIGN(qlimit);
+ ASSIGN(flags);
+ COPY(pq_u);
+
+ ASSIGN(qid);
+ break;
+ }
+ default:
+ panic("%s: unhandled struct pfioc_altq version", __func__);
+ break;
+ }
+
+#undef ASSIGN
+#undef COPY
+
+ return (0);
+}
+#endif /* ALTQ */
+
static int
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{
@@ -1015,9 +1237,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETTIMEOUT:
case DIOCCLRRULECTRS:
case DIOCGETLIMIT:
- case DIOCGETALTQS:
- case DIOCGETALTQ:
- case DIOCGETQSTATS:
+ case DIOCGETALTQSV0:
+ case DIOCGETALTQSV1:
+ case DIOCGETALTQV0:
+ case DIOCGETALTQV1:
+ case DIOCGETQSTATSV0:
+ case DIOCGETQSTATSV1:
case DIOCGETRULESETS:
case DIOCGETRULESET:
case DIOCRGETTABLES:
@@ -1035,7 +1260,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETSRCNODES:
case DIOCCLRSRCNODES:
case DIOCIGETIFACES:
- case DIOCGIFSPEED:
+ case DIOCGIFSPEEDV0:
+ case DIOCGIFSPEEDV1:
case DIOCSETIFFLAG:
case DIOCCLRIFFLAG:
break;
@@ -1061,9 +1287,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETSTATES:
case DIOCGETTIMEOUT:
case DIOCGETLIMIT:
- case DIOCGETALTQS:
- case DIOCGETALTQ:
- case DIOCGETQSTATS:
+ case DIOCGETALTQSV0:
+ case DIOCGETALTQSV1:
+ case DIOCGETALTQV0:
+ case DIOCGETALTQV1:
+ case DIOCGETQSTATSV0:
+ case DIOCGETQSTATSV1:
case DIOCGETRULESETS:
case DIOCGETRULESET:
case DIOCNATLOOK:
@@ -1075,7 +1304,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCOSFPGET:
case DIOCGETSRCNODES:
case DIOCIGETIFACES:
- case DIOCGIFSPEED:
+ case DIOCGIFSPEEDV1:
+ case DIOCGIFSPEEDV0:
break;
case DIOCRCLRTABLES:
case DIOCRADDTABLES:
@@ -2013,18 +2243,22 @@ DIOCGETSTATES_full:
break;
}
- case DIOCGIFSPEED: {
- struct pf_ifspeed *psp = (struct pf_ifspeed *)addr;
- struct pf_ifspeed ps;
+ case DIOCGIFSPEEDV0:
+ case DIOCGIFSPEEDV1: {
+ struct pf_ifspeed_v1 *psp = (struct pf_ifspeed_v1 *)addr;
+ struct pf_ifspeed_v1 ps;
struct ifnet *ifp;
if (psp->ifname[0] != 0) {
/* Can we completely trust user-land? */
strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
ifp = ifunit(ps.ifname);
- if (ifp != NULL)
- psp->baudrate = ifp->if_baudrate;
- else
+ if (ifp != NULL) {
+ psp->baudrate32 =
+ (u_int32_t)uqmin(ifp->if_baudrate, UINT_MAX);
+ if (cmd == DIOCGIFSPEEDV1)
+ psp->baudrate = ifp->if_baudrate;
+ } else
error = EINVAL;
} else
error = EINVAL;
@@ -2072,13 +2306,16 @@ DIOCGETSTATES_full:
break;
}
- case DIOCADDALTQ: {
- struct pfioc_altq *pa = (struct pfioc_altq *)addr;
+ case DIOCADDALTQV0:
+ case DIOCADDALTQV1: {
+ struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
struct pf_altq *altq, *a;
struct ifnet *ifp;
- altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK);
- bcopy(&pa->altq, altq, sizeof(struct pf_altq));
+ altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO);
+ error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd));
+ if (error)
+ break;
altq->local_flags = 0;
PF_RULES_WLOCK();
@@ -2122,13 +2359,15 @@ DIOCGETSTATES_full:
}
TAILQ_INSERT_TAIL(V_pf_altqs_inactive, altq, entries);
- bcopy(altq, &pa->altq, sizeof(struct pf_altq));
+ /* version error check done on import above */
+ pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
PF_RULES_WUNLOCK();
break;
}
- case DIOCGETALTQS: {
- struct pfioc_altq *pa = (struct pfioc_altq *)addr;
+ case DIOCGETALTQSV0:
+ case DIOCGETALTQSV1: {
+ struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
struct pf_altq *altq;
PF_RULES_RLOCK();
@@ -2140,8 +2379,9 @@ DIOCGETSTATES_full:
break;
}
- case DIOCGETALTQ: {
- struct pfioc_altq *pa = (struct pfioc_altq *)addr;
+ case DIOCGETALTQV0:
+ case DIOCGETALTQV1: {
+ struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
struct pf_altq *altq;
u_int32_t nr;
@@ -2162,21 +2402,24 @@ DIOCGETSTATES_full:
error = EBUSY;
break;
}
- bcopy(altq, &pa->altq, sizeof(struct pf_altq));
+ pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
PF_RULES_RUNLOCK();
break;
}
- case DIOCCHANGEALTQ:
+ case DIOCCHANGEALTQV0:
+ case DIOCCHANGEALTQV1:
/* CHANGEALTQ not supported yet! */
error = ENODEV;
break;
- case DIOCGETQSTATS: {
- struct pfioc_qstats *pq = (struct pfioc_qstats *)addr;
+ case DIOCGETQSTATSV0:
+ case DIOCGETQSTATSV1: {
+ struct pfioc_qstats_v1 *pq = (struct pfioc_qstats_v1 *)addr;
struct pf_altq *altq;
u_int32_t nr;
int nbytes;
+ u_int32_t version;
PF_RULES_RLOCK();
if (pq->ticket != V_ticket_altqs_active) {
@@ -2203,7 +2446,11 @@ DIOCGETSTATES_full:
break;
}
PF_RULES_RUNLOCK();
- error = altq_getqstats(altq, pq->buf, &nbytes);
+ if (cmd == DIOCGETQSTATSV0)
+ version = 0; /* DIOCGETQSTATSV0 means stats struct v0 */
+ else
+ version = pq->version;
+ error = altq_getqstats(altq, pq->buf, &nbytes, version);
if (error == 0) {
pq->scheduler = altq->scheduler;
pq->nbytes = nbytes;
@@ -3963,7 +4210,6 @@ pf_unload_vnet(void)
V_pf_vnet_active = 0;
V_pf_status.running = 0;
- swi_remove(V_pf_swi_cookie);
error = dehook_pf();
if (error) {
/*
@@ -3979,6 +4225,8 @@ pf_unload_vnet(void)
shutdown_pf();
PF_RULES_WUNLOCK();
+ swi_remove(V_pf_swi_cookie);
+
pf_unload_vnet_purge();
pf_normalize_cleanup();
diff --git a/freebsd/sys/netpfil/pf/pf_norm.c b/freebsd/sys/netpfil/pf/pf_norm.c
index 61da5e4f..0f98c669 100644
--- a/freebsd/sys/netpfil/pf/pf_norm.c
+++ b/freebsd/sys/netpfil/pf/pf_norm.c
@@ -93,8 +93,10 @@ struct pf_fragment {
TAILQ_ENTRY(pf_fragment) frag_next;
uint32_t fr_timeout;
uint16_t fr_maxlen; /* maximum length of single fragment */
+ uint16_t fr_entries; /* Total number of pf_fragment entries */
TAILQ_HEAD(pf_fragq, pf_frent) fr_queue;
};
+#define PF_MAX_FRENT_PER_FRAGMENT 64
struct pf_fragment_tag {
uint16_t ft_hdrlen; /* header length of reassembled pkt */
@@ -111,17 +113,17 @@ MTX_SYSINIT(pf_frag_mtx, &pf_frag_mtx, "pf fragments", MTX_DEF);
VNET_DEFINE(uma_zone_t, pf_state_scrub_z); /* XXX: shared with pfsync */
-static VNET_DEFINE(uma_zone_t, pf_frent_z);
+VNET_DEFINE_STATIC(uma_zone_t, pf_frent_z);
#define V_pf_frent_z VNET(pf_frent_z)
-static VNET_DEFINE(uma_zone_t, pf_frag_z);
+VNET_DEFINE_STATIC(uma_zone_t, pf_frag_z);
#define V_pf_frag_z VNET(pf_frag_z)
TAILQ_HEAD(pf_fragqueue, pf_fragment);
TAILQ_HEAD(pf_cachequeue, pf_fragment);
-static VNET_DEFINE(struct pf_fragqueue, pf_fragqueue);
+VNET_DEFINE_STATIC(struct pf_fragqueue, pf_fragqueue);
#define V_pf_fragqueue VNET(pf_fragqueue)
RB_HEAD(pf_frag_tree, pf_fragment);
-static VNET_DEFINE(struct pf_frag_tree, pf_frag_tree);
+VNET_DEFINE_STATIC(struct pf_frag_tree, pf_frag_tree);
#define V_pf_frag_tree VNET(pf_frag_tree)
static int pf_frag_compare(struct pf_fragment *,
struct pf_fragment *);
@@ -386,6 +388,7 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
*(struct pf_fragment_cmp *)frag = *key;
frag->fr_timeout = time_uptime;
frag->fr_maxlen = frent->fe_len;
+ frag->fr_entries = 0;
TAILQ_INIT(&frag->fr_queue);
RB_INSERT(pf_frag_tree, &V_pf_frag_tree, frag);
@@ -397,6 +400,9 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
return (frag);
}
+ if (frag->fr_entries >= PF_MAX_FRENT_PER_FRAGMENT)
+ goto bad_fragment;
+
KASSERT(!TAILQ_EMPTY(&frag->fr_queue), ("!TAILQ_EMPTY()->fr_queue"));
/* Remember maximum fragment len for refragmentation. */
@@ -469,6 +475,8 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
else
TAILQ_INSERT_AFTER(&frag->fr_queue, prev, frent, fr_next);
+ frag->fr_entries++;
+
return (frag);
bad_fragment:
diff --git a/freebsd/sys/netpfil/pf/pf_osfp.c b/freebsd/sys/netpfil/pf/pf_osfp.c
index b87d39bd..8723830c 100644
--- a/freebsd/sys/netpfil/pf/pf_osfp.c
+++ b/freebsd/sys/netpfil/pf/pf_osfp.c
@@ -49,7 +49,7 @@ static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints")
printf(format , ##x)
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
-static VNET_DEFINE(struct pf_osfp_list, pf_osfp_list) =
+VNET_DEFINE_STATIC(struct pf_osfp_list, pf_osfp_list) =
SLIST_HEAD_INITIALIZER();
#define V_pf_osfp_list VNET(pf_osfp_list)
diff --git a/freebsd/sys/netpfil/pf/pf_table.c b/freebsd/sys/netpfil/pf/pf_table.c
index 04a275d9..1fadd38c 100644
--- a/freebsd/sys/netpfil/pf/pf_table.c
+++ b/freebsd/sys/netpfil/pf/pf_table.c
@@ -124,9 +124,9 @@ struct pfr_walktree {
#define senderr(e) do { rv = (e); goto _bad; } while (0)
static MALLOC_DEFINE(M_PFTABLE, "pf_table", "pf(4) tables structures");
-static VNET_DEFINE(uma_zone_t, pfr_kentry_z);
+VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_z);
#define V_pfr_kentry_z VNET(pfr_kentry_z)
-static VNET_DEFINE(uma_zone_t, pfr_kcounters_z);
+VNET_DEFINE_STATIC(uma_zone_t, pfr_kcounters_z);
#define V_pfr_kcounters_z VNET(pfr_kcounters_z)
static struct pf_addr pfr_ffaddr = {
@@ -186,13 +186,13 @@ static struct pfr_kentry
static RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
static RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
-static VNET_DEFINE(struct pfr_ktablehead, pfr_ktables);
+VNET_DEFINE_STATIC(struct pfr_ktablehead, pfr_ktables);
#define V_pfr_ktables VNET(pfr_ktables)
-static VNET_DEFINE(struct pfr_table, pfr_nulltable);
+VNET_DEFINE_STATIC(struct pfr_table, pfr_nulltable);
#define V_pfr_nulltable VNET(pfr_nulltable)
-static VNET_DEFINE(int, pfr_ktable_cnt);
+VNET_DEFINE_STATIC(int, pfr_ktable_cnt);
#define V_pfr_ktable_cnt VNET(pfr_ktable_cnt)
void
diff --git a/freebsd/sys/opencrypto/_cryptodev.h b/freebsd/sys/opencrypto/_cryptodev.h
new file mode 100644
index 00000000..d13b41da
--- /dev/null
+++ b/freebsd/sys/opencrypto/_cryptodev.h
@@ -0,0 +1,8 @@
+/*
+ * This trivial work is released to the public domain, or licensed under the
+ * terms of the CC0, at your option.
+ * $FreeBSD$
+ */
+#pragma once
+
+typedef struct crypto_session *crypto_session_t;
diff --git a/freebsd/sys/opencrypto/crypto.c b/freebsd/sys/opencrypto/crypto.c
index 5db2e872..d66fe5d5 100644
--- a/freebsd/sys/opencrypto/crypto.c
+++ b/freebsd/sys/opencrypto/crypto.c
@@ -91,6 +91,13 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#endif
+struct crypto_session {
+ device_t parent;
+ void *softc;
+ uint32_t hid;
+ uint32_t capabilities;
+};
+
SDT_PROVIDER_DEFINE(opencrypto);
/*
@@ -127,6 +134,7 @@ struct cryptocap {
#define CRYPTOCAP_F_CLEANUP 0x80000000 /* needs resource cleanup */
int cc_qblocked; /* (q) symmetric q blocked */
int cc_kqblocked; /* (q) asymmetric q blocked */
+ size_t cc_session_size;
};
static struct cryptocap *crypto_drivers = NULL;
static int crypto_drivers_num = 0;
@@ -187,6 +195,7 @@ SYSCTL_INT(_kern, OID_AUTO, crypto_workers_num, CTLFLAG_RDTUN,
static uma_zone_t cryptop_zone;
static uma_zone_t cryptodesc_zone;
+static uma_zone_t cryptoses_zone;
int crypto_userasymcrypto = 1; /* userland may do asym crypto reqs */
SYSCTL_INT(_kern, OID_AUTO, userasymcrypto, CTLFLAG_RW,
@@ -205,6 +214,7 @@ static void crypto_ret_proc(struct crypto_ret_worker *ret_worker);
static void crypto_destroy(void);
static int crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint);
static int crypto_kinvoke(struct cryptkop *krp, int flags);
+static void crypto_remove(struct cryptocap *cap);
static void crypto_task_invoke(void *ctx, int pending);
static void crypto_batch_enqueue(struct cryptop *crp);
@@ -268,7 +278,12 @@ crypto_init(void)
cryptodesc_zone = uma_zcreate("cryptodesc", sizeof (struct cryptodesc),
0, 0, 0, 0,
UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
- if (cryptodesc_zone == NULL || cryptop_zone == NULL) {
+ cryptoses_zone = uma_zcreate("crypto_session",
+ sizeof(struct crypto_session), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
+
+ if (cryptodesc_zone == NULL || cryptop_zone == NULL ||
+ cryptoses_zone == NULL) {
printf("crypto_init: cannot setup crypto zones\n");
error = ENOMEM;
goto bad;
@@ -395,6 +410,8 @@ crypto_destroy(void)
if (crypto_drivers != NULL)
free(crypto_drivers, M_CRYPTO_DATA);
+ if (cryptoses_zone != NULL)
+ uma_zdestroy(cryptoses_zone);
if (cryptodesc_zone != NULL)
uma_zdestroy(cryptodesc_zone);
if (cryptop_zone != NULL)
@@ -408,6 +425,24 @@ crypto_destroy(void)
mtx_destroy(&crypto_drivers_mtx);
}
+uint32_t
+crypto_ses2hid(crypto_session_t crypto_session)
+{
+ return (crypto_session->hid);
+}
+
+uint32_t
+crypto_ses2caps(crypto_session_t crypto_session)
+{
+ return (crypto_session->capabilities);
+}
+
+void *
+crypto_get_driver_session(crypto_session_t crypto_session)
+{
+ return (crypto_session->softc);
+}
+
static struct cryptocap *
crypto_checkdriver(u_int32_t hid)
{
@@ -495,12 +530,19 @@ again:
* must be capable of the requested crypto algorithms.
*/
int
-crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid)
+crypto_newsession(crypto_session_t *cses, struct cryptoini *cri, int crid)
{
+ crypto_session_t res;
+ void *softc_mem;
struct cryptocap *cap;
- u_int32_t hid, lid;
+ u_int32_t hid;
+ size_t softc_size;
int err;
+restart:
+ res = NULL;
+ softc_mem = NULL;
+
CRYPTO_DRIVER_LOCK();
if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
/*
@@ -520,24 +562,53 @@ crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid)
* XXX layer right about here.
*/
}
- if (cap != NULL) {
- /* Call the driver initialization routine. */
- hid = cap - crypto_drivers;
- lid = hid; /* Pass the driver ID. */
- err = CRYPTODEV_NEWSESSION(cap->cc_dev, &lid, cri);
- if (err == 0) {
- (*sid) = (cap->cc_flags & 0xff000000)
- | (hid & 0x00ffffff);
- (*sid) <<= 32;
- (*sid) |= (lid & 0xffffffff);
- cap->cc_sessions++;
- } else
- CRYPTDEB("dev newsession failed: %d", err);
- } else {
+ if (cap == NULL) {
CRYPTDEB("no driver");
err = EOPNOTSUPP;
+ goto out;
+ }
+ cap->cc_sessions++;
+ softc_size = cap->cc_session_size;
+ hid = cap - crypto_drivers;
+ cap = NULL;
+ CRYPTO_DRIVER_UNLOCK();
+
+ softc_mem = malloc(softc_size, M_CRYPTO_DATA, M_WAITOK | M_ZERO);
+ res = uma_zalloc(cryptoses_zone, M_WAITOK | M_ZERO);
+ res->softc = softc_mem;
+
+ CRYPTO_DRIVER_LOCK();
+ cap = crypto_checkdriver(hid);
+ if (cap != NULL && (cap->cc_flags & CRYPTOCAP_F_CLEANUP) != 0) {
+ cap->cc_sessions--;
+ crypto_remove(cap);
+ cap = NULL;
+ }
+ if (cap == NULL) {
+ free(softc_mem, M_CRYPTO_DATA);
+ uma_zfree(cryptoses_zone, res);
+ CRYPTO_DRIVER_UNLOCK();
+ goto restart;
+ }
+
+ /* Call the driver initialization routine. */
+ err = CRYPTODEV_NEWSESSION(cap->cc_dev, res, cri);
+ if (err != 0) {
+ CRYPTDEB("dev newsession failed: %d", err);
+ goto out;
}
+
+ res->capabilities = cap->cc_flags & 0xff000000;
+ res->hid = hid;
+ *cses = res;
+
+out:
CRYPTO_DRIVER_UNLOCK();
+ if (err != 0) {
+ free(softc_mem, M_CRYPTO_DATA);
+ if (res != NULL)
+ uma_zfree(cryptoses_zone, res);
+ }
return err;
}
@@ -554,41 +625,41 @@ crypto_remove(struct cryptocap *cap)
* Delete an existing session (or a reserved session on an unregistered
* driver).
*/
-int
-crypto_freesession(u_int64_t sid)
+void
+crypto_freesession(crypto_session_t cses)
{
struct cryptocap *cap;
+ void *ses;
+ size_t ses_size;
u_int32_t hid;
- int err;
- CRYPTO_DRIVER_LOCK();
-
- if (crypto_drivers == NULL) {
- err = EINVAL;
- goto done;
- }
+ if (cses == NULL)
+ return;
- /* Determine two IDs. */
- hid = CRYPTO_SESID2HID(sid);
+ CRYPTO_DRIVER_LOCK();
- if (hid >= crypto_drivers_num) {
- err = ENOENT;
- goto done;
- }
+ hid = crypto_ses2hid(cses);
+ KASSERT(hid < crypto_drivers_num,
+ ("bogus crypto_session %p hid %u", cses, hid));
cap = &crypto_drivers[hid];
+ ses = cses->softc;
+ ses_size = cap->cc_session_size;
+
if (cap->cc_sessions)
cap->cc_sessions--;
/* Call the driver cleanup routine, if available. */
- err = CRYPTODEV_FREESESSION(cap->cc_dev, sid);
+ CRYPTODEV_FREESESSION(cap->cc_dev, cses);
+
+ explicit_bzero(ses, ses_size);
+ free(ses, M_CRYPTO_DATA);
+ uma_zfree(cryptoses_zone, cses);
if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
crypto_remove(cap);
-done:
CRYPTO_DRIVER_UNLOCK();
- return err;
}
/*
@@ -596,7 +667,7 @@ done:
* support for the algorithms they handle.
*/
int32_t
-crypto_get_driverid(device_t dev, int flags)
+crypto_get_driverid(device_t dev, size_t sessionsize, int flags)
{
struct cryptocap *newdrv;
int i;
@@ -646,6 +717,7 @@ crypto_get_driverid(device_t dev, int flags)
crypto_drivers[i].cc_sessions = 1; /* Mark */
crypto_drivers[i].cc_dev = dev;
crypto_drivers[i].cc_flags = flags;
+ crypto_drivers[i].cc_session_size = sessionsize;
if (bootverbose)
printf("crypto: assign %s driver id %u, flags 0x%x\n",
device_get_nameunit(dev), i, flags);
@@ -903,7 +975,7 @@ crypto_dispatch(struct cryptop *crp)
binuptime(&crp->crp_tstamp);
#endif
- crp->crp_retw_id = crp->crp_sid % crypto_workers_num;
+ crp->crp_retw_id = ((uintptr_t)crp->crp_session) % crypto_workers_num;
if (CRYPTOP_ASYNC(crp)) {
if (crp->crp_flags & CRYPTO_F_ASYNC_KEEPORDER) {
@@ -922,7 +994,7 @@ crypto_dispatch(struct cryptop *crp)
}
if ((crp->crp_flags & CRYPTO_F_BATCH) == 0) {
- hid = CRYPTO_SESID2HID(crp->crp_sid);
+ hid = crypto_ses2hid(crp->crp_session);
/*
* Caller marked the request to be processed
@@ -1143,7 +1215,7 @@ crypto_task_invoke(void *ctx, int pending)
crp = (struct cryptop *)ctx;
- hid = CRYPTO_SESID2HID(crp->crp_sid);
+ hid = crypto_ses2hid(crp->crp_session);
cap = crypto_checkdriver(hid);
result = crypto_invoke(cap, crp, 0);
@@ -1169,7 +1241,7 @@ crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint)
#endif
if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) {
struct cryptodesc *crd;
- u_int64_t nid;
+ crypto_session_t nses;
/*
* Driver has unregistered; migrate the session and return
@@ -1178,15 +1250,15 @@ crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint)
* XXX: What if there are more already queued requests for this
* session?
*/
- crypto_freesession(crp->crp_sid);
+ crypto_freesession(crp->crp_session);
for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)
crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);
/* XXX propagate flags from initial session? */
- if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI),
+ if (crypto_newsession(&nses, &(crp->crp_desc->CRD_INI),
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE) == 0)
- crp->crp_sid = nid;
+ crp->crp_session = nses;
crp->crp_etype = EAGAIN;
crypto_done(crp);
@@ -1292,7 +1364,7 @@ crypto_done(struct cryptop *crp)
if (!CRYPTOP_ASYNC_KEEPORDER(crp) &&
((crp->crp_flags & CRYPTO_F_CBIMM) ||
((crp->crp_flags & CRYPTO_F_CBIFSYNC) &&
- (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC)))) {
+ (crypto_ses2caps(crp->crp_session) & CRYPTOCAP_F_SYNC)))) {
/*
* Do the callback directly. This is ok when the
* callback routine does very little (e.g. the
@@ -1454,7 +1526,7 @@ crypto_proc(void)
submit = NULL;
hint = 0;
TAILQ_FOREACH(crp, &crp_q, crp_next) {
- hid = CRYPTO_SESID2HID(crp->crp_sid);
+ hid = crypto_ses2hid(crp->crp_session);
cap = crypto_checkdriver(hid);
/*
* Driver cannot disappeared when there is an active
@@ -1478,7 +1550,7 @@ crypto_proc(void)
* better to just use a per-driver
* queue instead.
*/
- if (CRYPTO_SESID2HID(submit->crp_sid) == hid)
+ if (crypto_ses2hid(submit->crp_session) == hid)
hint = CRYPTO_HINT_MORE;
break;
} else {
@@ -1491,7 +1563,7 @@ crypto_proc(void)
}
if (submit != NULL) {
TAILQ_REMOVE(&crp_q, submit, crp_next);
- hid = CRYPTO_SESID2HID(submit->crp_sid);
+ hid = crypto_ses2hid(submit->crp_session);
cap = crypto_checkdriver(hid);
KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
__func__, __LINE__));
@@ -1507,7 +1579,7 @@ crypto_proc(void)
* it at the end does not work.
*/
/* XXX validate sid again? */
- crypto_drivers[CRYPTO_SESID2HID(submit->crp_sid)].cc_qblocked = 1;
+ crypto_drivers[crypto_ses2hid(submit->crp_session)].cc_qblocked = 1;
TAILQ_INSERT_HEAD(&crp_q, submit, crp_next);
cryptostats.cs_blocks++;
}
@@ -1696,8 +1768,8 @@ DB_SHOW_COMMAND(crypto, db_show_crypto)
"Desc", "Callback");
TAILQ_FOREACH(crp, &crp_q, crp_next) {
db_printf("%4u %08x %4u %4u %4u %04x %8p %8p\n"
- , (int) CRYPTO_SESID2HID(crp->crp_sid)
- , (int) CRYPTO_SESID2CAPS(crp->crp_sid)
+ , (int) crypto_ses2hid(crp->crp_session)
+ , (int) crypto_ses2caps(crp->crp_session)
, crp->crp_ilen, crp->crp_olen
, crp->crp_etype
, crp->crp_flags
@@ -1712,7 +1784,7 @@ DB_SHOW_COMMAND(crypto, db_show_crypto)
TAILQ_FOREACH(crp, &ret_worker->crp_ret_q, crp_next) {
db_printf("%8td %4u %4u %04x %8p\n"
, CRYPTO_RETW_ID(ret_worker)
- , (int) CRYPTO_SESID2HID(crp->crp_sid)
+ , (int) crypto_ses2hid(crp->crp_session)
, crp->crp_etype
, crp->crp_flags
, crp->crp_callback
diff --git a/freebsd/sys/opencrypto/cryptodev.c b/freebsd/sys/opencrypto/cryptodev.c
index 162a247c..b569cbf7 100644
--- a/freebsd/sys/opencrypto/cryptodev.c
+++ b/freebsd/sys/opencrypto/cryptodev.c
@@ -267,7 +267,7 @@ crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to)
struct csession {
TAILQ_ENTRY(csession) next;
- u_int64_t sid;
+ crypto_session_t cses;
u_int32_t ses;
struct mtx lock; /* for op submission */
@@ -326,10 +326,10 @@ static const rtems_filesystem_file_handlers_r cryptofops;
static struct csession *csefind(struct fcrypt *, u_int);
static int csedelete(struct fcrypt *, struct csession *);
static struct csession *cseadd(struct fcrypt *, struct csession *);
-static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t,
+static struct csession *csecreate(struct fcrypt *, crypto_session_t, caddr_t,
u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
struct auth_hash *);
-static int csefree(struct csession *);
+static void csefree(struct csession *);
static int cryptodev_op(struct csession *, struct crypt_op *,
struct ucred *, struct thread *td);
@@ -384,7 +384,7 @@ cryptof_ioctl(
struct enc_xform *txform = NULL;
struct auth_hash *thash = NULL;
struct crypt_kop *kop;
- u_int64_t sid;
+ crypto_session_t cses;
u_int32_t ses;
int error = 0, crid;
#ifdef COMPAT_FREEBSD32
@@ -463,9 +463,15 @@ cryptof_ioctl(
case CRYPTO_MD5_HMAC:
thash = &auth_hash_hmac_md5;
break;
+ case CRYPTO_POLY1305:
+ thash = &auth_hash_poly1305;
+ break;
case CRYPTO_SHA1_HMAC:
thash = &auth_hash_hmac_sha1;
break;
+ case CRYPTO_SHA2_224_HMAC:
+ thash = &auth_hash_hmac_sha2_224;
+ break;
case CRYPTO_SHA2_256_HMAC:
thash = &auth_hash_hmac_sha2_256;
break;
@@ -492,10 +498,23 @@ cryptof_ioctl(
case CRYPTO_MD5:
thash = &auth_hash_md5;
break;
+#endif
case CRYPTO_SHA1:
thash = &auth_hash_sha1;
break;
-#endif
+ case CRYPTO_SHA2_224:
+ thash = &auth_hash_sha2_224;
+ break;
+ case CRYPTO_SHA2_256:
+ thash = &auth_hash_sha2_256;
+ break;
+ case CRYPTO_SHA2_384:
+ thash = &auth_hash_sha2_384;
+ break;
+ case CRYPTO_SHA2_512:
+ thash = &auth_hash_sha2_512;
+ break;
+
case CRYPTO_NULL_HMAC:
thash = &auth_hash_null;
break;
@@ -582,19 +601,19 @@ cryptof_ioctl(
}
} else
crid = CRYPTOCAP_F_HARDWARE;
- error = crypto_newsession(&sid, (txform ? &crie : &cria), crid);
+ error = crypto_newsession(&cses, (txform ? &crie : &cria), crid);
if (error) {
CRYPTDEB("crypto_newsession");
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto bail;
}
- cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
+ cse = csecreate(fcr, cses, crie.cri_key, crie.cri_klen,
cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
thash);
if (cse == NULL) {
- crypto_freesession(sid);
+ crypto_freesession(cses);
error = EINVAL;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
CRYPTDEB("csecreate");
@@ -607,7 +626,7 @@ cryptof_ioctl(
#endif
) {
/* return hardware/driver id */
- SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid);
+ SES2(sop)->crid = crypto_ses2hid(cse->cses);
}
bail:
if (error) {
@@ -634,7 +653,7 @@ bail:
return (EINVAL);
}
csedelete(fcr, cse);
- error = csefree(cse);
+ csefree(cse);
break;
case CIOCCRYPT:
#ifdef COMPAT_FREEBSD32
@@ -867,7 +886,7 @@ cryptodev_op(
| (cop->flags & COP_F_BATCH);
crp->crp_uio = &cod->uio;
crp->crp_callback = cryptodev_cb;
- crp->crp_sid = cse->sid;
+ crp->crp_session = cse->cses;
crp->crp_opaque = cod;
if (cop->iv) {
@@ -1043,7 +1062,7 @@ cryptodev_aead(
| (caead->flags & COP_F_BATCH);
crp->crp_uio = &cod->uio;
crp->crp_callback = cryptodev_cb;
- crp->crp_sid = cse->sid;
+ crp->crp_session = cse->cses;
crp->crp_opaque = cod;
if (caead->iv) {
@@ -1318,7 +1337,7 @@ cryptof_close(struct file *fp, struct thread *td)
while ((cse = TAILQ_FIRST(&fcr->csessions))) {
TAILQ_REMOVE(&fcr->csessions, cse, next);
- (void)csefree(cse);
+ csefree(cse);
}
free(fcr, M_XDATA);
fp->f_data = NULL;
@@ -1389,7 +1408,7 @@ cseadd(struct fcrypt *fcr, struct csession *cse)
}
struct csession *
-csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
+csecreate(struct fcrypt *fcr, crypto_session_t cses, caddr_t key, u_int64_t keylen,
caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
struct enc_xform *txform, struct auth_hash *thash)
{
@@ -1403,7 +1422,7 @@ csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
cse->keylen = keylen/8;
cse->mackey = mackey;
cse->mackeylen = mackeylen/8;
- cse->sid = sid;
+ cse->cses = cses;
cse->cipher = cipher;
cse->mac = mac;
cse->txform = txform;
@@ -1412,19 +1431,17 @@ csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
return (cse);
}
-static int
+static void
csefree(struct csession *cse)
{
- int error;
- error = crypto_freesession(cse->sid);
+ crypto_freesession(cse->cses);
mtx_destroy(&cse->lock);
if (cse->key)
free(cse->key, M_XDATA);
if (cse->mackey)
free(cse->mackey, M_XDATA);
free(cse, M_XDATA);
- return (error);
}
static int
diff --git a/freebsd/sys/opencrypto/cryptodev.h b/freebsd/sys/opencrypto/cryptodev.h
index 65422541..b3f81563 100644
--- a/freebsd/sys/opencrypto/cryptodev.h
+++ b/freebsd/sys/opencrypto/cryptodev.h
@@ -65,6 +65,10 @@
#include <sys/ioccom.h>
#include <sys/_task.h>
+#ifdef _KERNEL
+#include <opencrypto/_cryptodev.h>
+#endif
+
/* Some initial values */
#define CRYPTO_DRIVERS_INITIAL 4
#define CRYPTO_SW_SESSIONS 32
@@ -74,25 +78,29 @@
#define MD5_HASH_LEN 16
#define SHA1_HASH_LEN 20
#define RIPEMD160_HASH_LEN 20
+#define SHA2_224_HASH_LEN 28
#define SHA2_256_HASH_LEN 32
#define SHA2_384_HASH_LEN 48
#define SHA2_512_HASH_LEN 64
#define MD5_KPDK_HASH_LEN 16
#define SHA1_KPDK_HASH_LEN 20
#define AES_GMAC_HASH_LEN 16
+#define POLY1305_HASH_LEN 16
/* Maximum hash algorithm result length */
#define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */
+#define MD5_BLOCK_LEN 64
+#define SHA1_BLOCK_LEN 64
+#define RIPEMD160_BLOCK_LEN 64
+#define SHA2_224_BLOCK_LEN 64
+#define SHA2_256_BLOCK_LEN 64
+#define SHA2_384_BLOCK_LEN 128
+#define SHA2_512_BLOCK_LEN 128
+
/* HMAC values */
#define NULL_HMAC_BLOCK_LEN 64
-#define MD5_HMAC_BLOCK_LEN 64
-#define SHA1_HMAC_BLOCK_LEN 64
-#define RIPEMD160_HMAC_BLOCK_LEN 64
-#define SHA2_256_HMAC_BLOCK_LEN 64
-#define SHA2_384_HMAC_BLOCK_LEN 128
-#define SHA2_512_HMAC_BLOCK_LEN 128
/* Maximum HMAC block length */
-#define HMAC_MAX_BLOCK_LEN SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */
+#define HMAC_MAX_BLOCK_LEN SHA2_512_BLOCK_LEN /* Keep this updated */
#define HMAC_IPAD_VAL 0x36
#define HMAC_OPAD_VAL 0x5C
/* HMAC Key Length */
@@ -100,6 +108,8 @@
#define AES_192_GMAC_KEY_LEN 24
#define AES_256_GMAC_KEY_LEN 32
+#define POLY1305_KEY_LEN 32
+
/* Encryption algorithm block sizes */
#define NULL_BLOCK_LEN 4 /* IPsec to maintain alignment */
#define DES_BLOCK_LEN 8
@@ -182,7 +192,14 @@
#define CRYPTO_BLAKE2B 29 /* Blake2b hash */
#define CRYPTO_BLAKE2S 30 /* Blake2s hash */
#define CRYPTO_CHACHA20 31 /* Chacha20 stream cipher */
-#define CRYPTO_ALGORITHM_MAX 31 /* Keep updated - see below */
+#define CRYPTO_SHA2_224_HMAC 32
+#define CRYPTO_RIPEMD160 33
+#define CRYPTO_SHA2_224 34
+#define CRYPTO_SHA2_256 35
+#define CRYPTO_SHA2_384 36
+#define CRYPTO_SHA2_512 37
+#define CRYPTO_POLY1305 38
+#define CRYPTO_ALGORITHM_MAX 38 /* Keep updated - see below */
#define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \
(x) <= CRYPTO_ALGORITHM_MAX)
@@ -216,6 +233,11 @@ struct session_op {
u_int32_t ses; /* returns: session # */
};
+/*
+ * session and crypt _op structs are used by userspace programs to interact
+ * with /dev/crypto. Confusingly, the internal kernel interface is named
+ * "cryptop" (no underscore).
+ */
struct session2_op {
u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
@@ -399,7 +421,7 @@ struct cryptop {
struct task crp_task;
- u_int64_t crp_sid; /* Session ID */
+ crypto_session_t crp_session; /* Session */
int crp_ilen; /* Input data total length */
int crp_olen; /* Result total length */
@@ -408,7 +430,7 @@ struct cryptop {
* All error codes except EAGAIN
* indicate possible data corruption (as in,
* the data have been touched). On all
- * errors, the crp_sid may have changed
+ * errors, the crp_session may have changed
* (reset to a new one), so the caller
* should always check and use the new
* value on future requests.
@@ -450,7 +472,7 @@ struct cryptop {
#define CRYPTOP_ASYNC(crp) \
(((crp)->crp_flags & CRYPTO_F_ASYNC) && \
- CRYPTO_SESID2CAPS((crp)->crp_sid) & CRYPTOCAP_F_SYNC)
+ crypto_ses2caps((crp)->crp_session) & CRYPTOCAP_F_SYNC)
#define CRYPTOP_ASYNC_KEEPORDER(crp) \
(CRYPTOP_ASYNC(crp) && \
(crp)->crp_flags & CRYPTO_F_ASYNC_KEEPORDER)
@@ -480,25 +502,19 @@ struct cryptkop {
int (*krp_callback)(struct cryptkop *);
};
-/*
- * Session ids are 64 bits. The lower 32 bits contain a "local id" which
- * is a driver-private session identifier. The upper 32 bits contain a
- * "hardware id" used by the core crypto code to identify the driver and
- * a copy of the driver's capabilities that can be used by client code to
- * optimize operation.
- */
-#define CRYPTO_SESID2HID(_sid) (((_sid) >> 32) & 0x00ffffff)
-#define CRYPTO_SESID2CAPS(_sid) (((_sid) >> 32) & 0xff000000)
-#define CRYPTO_SESID2LID(_sid) (((u_int32_t) (_sid)) & 0xffffffff)
+uint32_t crypto_ses2hid(crypto_session_t crypto_session);
+uint32_t crypto_ses2caps(crypto_session_t crypto_session);
+void *crypto_get_driver_session(crypto_session_t crypto_session);
MALLOC_DECLARE(M_CRYPTO_DATA);
-extern int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard);
-extern int crypto_freesession(u_int64_t sid);
+extern int crypto_newsession(crypto_session_t *cses, struct cryptoini *cri, int hard);
+extern void crypto_freesession(crypto_session_t cses);
#define CRYPTOCAP_F_HARDWARE CRYPTO_FLAG_HARDWARE
#define CRYPTOCAP_F_SOFTWARE CRYPTO_FLAG_SOFTWARE
#define CRYPTOCAP_F_SYNC 0x04000000 /* operates synchronously */
-extern int32_t crypto_get_driverid(device_t dev, int flags);
+extern int32_t crypto_get_driverid(device_t dev, size_t session_size,
+ int flags);
extern int crypto_find_driver(const char *);
extern device_t crypto_find_device_byhid(int hid);
extern int crypto_getcaps(int hid);
diff --git a/freebsd/sys/opencrypto/cryptosoft.c b/freebsd/sys/opencrypto/cryptosoft.c
index 69993ae0..8dff61c1 100644
--- a/freebsd/sys/opencrypto/cryptosoft.c
+++ b/freebsd/sys/opencrypto/cryptosoft.c
@@ -64,10 +64,6 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/cryptodev_if.h>
static int32_t swcr_id;
-static struct swcr_data **swcr_sessions = NULL;
-static u_int32_t swcr_sesnum;
-/* Protects swcr_sessions pointer, not data. */
-static struct rwlock swcr_sessions_lock;
u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN];
u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN];
@@ -76,8 +72,7 @@ static int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
static int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int);
static int swcr_authenc(struct cryptop *crp);
static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
-static int swcr_freesession(device_t dev, u_int64_t tid);
-static int swcr_freesession_locked(device_t dev, u_int64_t tid);
+static void swcr_freesession(device_t dev, crypto_session_t cses);
/*
* Apply a symmetric encryption/decryption algorithm.
@@ -328,7 +323,7 @@ out:
return (error);
}
-static void
+static int __result_use_check
swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key,
int klen)
{
@@ -339,6 +334,7 @@ swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key,
switch (axf->type) {
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
@@ -383,6 +379,12 @@ swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key,
axf->Final(buf, sw->sw_ictx);
break;
}
+ case CRYPTO_POLY1305:
+ if (klen != POLY1305_KEY_LEN) {
+ CRYPTDEB("bad poly1305 key size %d", klen);
+ return EINVAL;
+ }
+ /* FALLTHROUGH */
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
axf->Setkey(sw->sw_ictx, key, klen);
@@ -391,7 +393,9 @@ swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key,
default:
printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d "
"doesn't use keys.\n", __func__, axf->type);
+ return EINVAL;
}
+ return 0;
}
/*
@@ -411,8 +415,11 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
axf = sw->sw_axf;
- if (crd->crd_flags & CRD_F_KEY_EXPLICIT)
- swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen);
+ if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
+ err = swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen);
+ if (err != 0)
+ return err;
+ }
bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
@@ -422,8 +429,17 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
return err;
switch (sw->sw_alg) {
+ case CRYPTO_SHA1:
+ case CRYPTO_SHA2_224:
+ case CRYPTO_SHA2_256:
+ case CRYPTO_SHA2_384:
+ case CRYPTO_SHA2_512:
+ axf->Final(aalg, &ctx);
+ break;
+
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
@@ -457,6 +473,7 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
case CRYPTO_NULL_HMAC:
+ case CRYPTO_POLY1305:
axf->Final(aalg, &ctx);
break;
}
@@ -482,6 +499,7 @@ swcr_authenc(struct cryptop *crp)
u_char uaalg[AALG_MAX_RESULT_LEN];
u_char iv[EALG_MAX_BLOCK_LEN];
union authctx ctx;
+ struct swcr_session *ses;
struct cryptodesc *crd, *crda = NULL, *crde = NULL;
struct swcr_data *sw, *swa, *swe = NULL;
struct auth_hash *axf = NULL;
@@ -492,14 +510,16 @@ swcr_authenc(struct cryptop *crp)
ivlen = blksz = iskip = oskip = 0;
+ ses = crypto_get_driver_session(crp->crp_session);
+
for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
- for (sw = swcr_sessions[crp->crp_sid & 0xffffffff];
- sw && sw->sw_alg != crd->crd_alg;
- sw = sw->sw_next)
+ for (i = 0; i < nitems(ses->swcr_algorithms) &&
+ ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++)
;
- if (sw == NULL)
+ if (i == nitems(ses->swcr_algorithms))
return (EINVAL);
+ sw = &ses->swcr_algorithms[i];
switch (sw->sw_alg) {
case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_NIST_GMAC:
@@ -732,68 +752,24 @@ swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
* Generate a new software session.
*/
static int
-swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri)
{
- struct swcr_data **swd;
+ struct swcr_session *ses;
+ struct swcr_data *swd;
struct auth_hash *axf;
struct enc_xform *txf;
struct comp_algo *cxf;
- u_int32_t i;
+ size_t i;
int len;
int error;
- if (sid == NULL || cri == NULL)
+ if (cses == NULL || cri == NULL)
return EINVAL;
- rw_wlock(&swcr_sessions_lock);
- if (swcr_sessions) {
- for (i = 1; i < swcr_sesnum; i++)
- if (swcr_sessions[i] == NULL)
- break;
- } else
- i = 1; /* NB: to silence compiler warning */
-
- if (swcr_sessions == NULL || i == swcr_sesnum) {
- if (swcr_sessions == NULL) {
- i = 1; /* We leave swcr_sessions[0] empty */
- swcr_sesnum = CRYPTO_SW_SESSIONS;
- } else
- swcr_sesnum *= 2;
-
- swd = malloc(swcr_sesnum * sizeof(struct swcr_data *),
- M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
- if (swd == NULL) {
- /* Reset session number */
- if (swcr_sesnum == CRYPTO_SW_SESSIONS)
- swcr_sesnum = 0;
- else
- swcr_sesnum /= 2;
- rw_wunlock(&swcr_sessions_lock);
- return ENOBUFS;
- }
-
- /* Copy existing sessions */
- if (swcr_sessions != NULL) {
- bcopy(swcr_sessions, swd,
- (swcr_sesnum / 2) * sizeof(struct swcr_data *));
- free(swcr_sessions, M_CRYPTO_DATA);
- }
-
- swcr_sessions = swd;
- }
+ ses = crypto_get_driver_session(cses);
- rw_downgrade(&swcr_sessions_lock);
- swd = &swcr_sessions[i];
- *sid = i;
-
- while (cri) {
- *swd = malloc(sizeof(struct swcr_data),
- M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
- if (*swd == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
- return ENOBUFS;
- }
+ for (i = 0; cri != NULL && i < nitems(ses->swcr_algorithms); i++) {
+ swd = &ses->swcr_algorithms[i];
switch (cri->cri_alg) {
case CRYPTO_DES_CBC:
@@ -825,7 +801,7 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
goto enccommon;
case CRYPTO_AES_NIST_GMAC:
txf = &enc_xform_aes_nist_gmac;
- (*swd)->sw_exf = txf;
+ swd->sw_exf = txf;
break;
case CRYPTO_CAMELLIA_CBC:
txf = &enc_xform_camellia;
@@ -838,15 +814,14 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
goto enccommon;
enccommon:
if (cri->cri_key != NULL) {
- error = txf->setkey(&((*swd)->sw_kschedule),
+ error = txf->setkey(&swd->sw_kschedule,
cri->cri_key, cri->cri_klen / 8);
if (error) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ swcr_freesession(dev, cses);
return error;
}
}
- (*swd)->sw_exf = txf;
+ swd->sw_exf = txf;
break;
case CRYPTO_MD5_HMAC:
@@ -855,6 +830,9 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_SHA1_HMAC:
axf = &auth_hash_hmac_sha1;
goto authcommon;
+ case CRYPTO_SHA2_224_HMAC:
+ axf = &auth_hash_hmac_sha2_224;
+ goto authcommon;
case CRYPTO_SHA2_256_HMAC:
axf = &auth_hash_hmac_sha2_256;
goto authcommon;
@@ -870,29 +848,31 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_RIPEMD160_HMAC:
axf = &auth_hash_hmac_ripemd_160;
authcommon:
- (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
- if ((*swd)->sw_ictx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_ictx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
- (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ swd->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
- if ((*swd)->sw_octx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_octx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
if (cri->cri_key != NULL) {
- swcr_authprepare(axf, *swd, cri->cri_key,
- cri->cri_klen);
+ error = swcr_authprepare(axf, swd,
+ cri->cri_key, cri->cri_klen);
+ if (error != 0) {
+ swcr_freesession(dev, cses);
+ return error;
+ }
}
- (*swd)->sw_mlen = cri->cri_mlen;
- (*swd)->sw_axf = axf;
+ swd->sw_mlen = cri->cri_mlen;
+ swd->sw_axf = axf;
break;
case CRYPTO_MD5_KPDK:
@@ -902,52 +882,66 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_SHA1_KPDK:
axf = &auth_hash_key_sha1;
auth2common:
- (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
- if ((*swd)->sw_ictx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_ictx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
- (*swd)->sw_octx = malloc(cri->cri_klen / 8,
+ swd->sw_octx = malloc(cri->cri_klen / 8,
M_CRYPTO_DATA, M_NOWAIT);
- if ((*swd)->sw_octx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_octx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
/* Store the key so we can "append" it to the payload */
if (cri->cri_key != NULL) {
- swcr_authprepare(axf, *swd, cri->cri_key,
- cri->cri_klen);
+ error = swcr_authprepare(axf, swd,
+ cri->cri_key, cri->cri_klen);
+ if (error != 0) {
+ swcr_freesession(dev, cses);
+ return error;
+ }
}
- (*swd)->sw_mlen = cri->cri_mlen;
- (*swd)->sw_axf = axf;
+ swd->sw_mlen = cri->cri_mlen;
+ swd->sw_axf = axf;
break;
#ifdef notdef
case CRYPTO_MD5:
axf = &auth_hash_md5;
goto auth3common;
+#endif
case CRYPTO_SHA1:
axf = &auth_hash_sha1;
+ goto auth3common;
+ case CRYPTO_SHA2_224:
+ axf = &auth_hash_sha2_224;
+ goto auth3common;
+ case CRYPTO_SHA2_256:
+ axf = &auth_hash_sha2_256;
+ goto auth3common;
+ case CRYPTO_SHA2_384:
+ axf = &auth_hash_sha2_384;
+ goto auth3common;
+ case CRYPTO_SHA2_512:
+ axf = &auth_hash_sha2_512;
+
auth3common:
- (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
- if ((*swd)->sw_ictx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_ictx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
- axf->Init((*swd)->sw_ictx);
- (*swd)->sw_mlen = cri->cri_mlen;
- (*swd)->sw_axf = axf;
+ axf->Init(swd->sw_ictx);
+ swd->sw_mlen = cri->cri_mlen;
+ swd->sw_axf = axf;
break;
-#endif
case CRYPTO_AES_128_NIST_GMAC:
axf = &auth_hash_nist_gmac_aes_128;
@@ -962,21 +956,19 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
auth4common:
len = cri->cri_klen / 8;
if (len != 16 && len != 24 && len != 32) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ swcr_freesession(dev, cses);
return EINVAL;
}
- (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
- if ((*swd)->sw_ictx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_ictx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
- axf->Init((*swd)->sw_ictx);
- axf->Setkey((*swd)->sw_ictx, cri->cri_key, len);
- (*swd)->sw_axf = axf;
+ axf->Init(swd->sw_ictx);
+ axf->Setkey(swd->sw_ictx, cri->cri_key, len);
+ swd->sw_axf = axf;
break;
case CRYPTO_BLAKE2B:
@@ -984,70 +976,56 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
goto auth5common;
case CRYPTO_BLAKE2S:
axf = &auth_hash_blake2s;
+ goto auth5common;
+ case CRYPTO_POLY1305:
+ axf = &auth_hash_poly1305;
auth5common:
- (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
+ swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
- if ((*swd)->sw_ictx == NULL) {
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ if (swd->sw_ictx == NULL) {
+ swcr_freesession(dev, cses);
return ENOBUFS;
}
- axf->Setkey((*swd)->sw_ictx, cri->cri_key,
+ axf->Setkey(swd->sw_ictx, cri->cri_key,
cri->cri_klen / 8);
- axf->Init((*swd)->sw_ictx);
- (*swd)->sw_axf = axf;
+ axf->Init(swd->sw_ictx);
+ swd->sw_axf = axf;
break;
case CRYPTO_DEFLATE_COMP:
cxf = &comp_algo_deflate;
- (*swd)->sw_cxf = cxf;
+ swd->sw_cxf = cxf;
break;
default:
- swcr_freesession_locked(dev, i);
- rw_runlock(&swcr_sessions_lock);
+ swcr_freesession(dev, cses);
return EINVAL;
}
- (*swd)->sw_alg = cri->cri_alg;
+ swd->sw_alg = cri->cri_alg;
cri = cri->cri_next;
- swd = &((*swd)->sw_next);
+ ses->swcr_nalgs++;
}
- rw_runlock(&swcr_sessions_lock);
- return 0;
-}
-static int
-swcr_freesession(device_t dev, u_int64_t tid)
-{
- int error;
-
- rw_rlock(&swcr_sessions_lock);
- error = swcr_freesession_locked(dev, tid);
- rw_runlock(&swcr_sessions_lock);
- return error;
+ if (cri != NULL) {
+ CRYPTDEB("Bogus session request for three or more algorithms");
+ return EINVAL;
+ }
+ return 0;
}
-/*
- * Free a session.
- */
-static int
-swcr_freesession_locked(device_t dev, u_int64_t tid)
+static void
+swcr_freesession(device_t dev, crypto_session_t cses)
{
+ struct swcr_session *ses;
struct swcr_data *swd;
struct enc_xform *txf;
struct auth_hash *axf;
- u_int32_t sid = CRYPTO_SESID2LID(tid);
-
- if (sid > swcr_sesnum || swcr_sessions == NULL ||
- swcr_sessions[sid] == NULL)
- return EINVAL;
+ size_t i;
- /* Silently accept and return */
- if (sid == 0)
- return 0;
+ ses = crypto_get_driver_session(cses);
- while ((swd = swcr_sessions[sid]) != NULL) {
- swcr_sessions[sid] = swd->sw_next;
+ for (i = 0; i < nitems(ses->swcr_algorithms); i++) {
+ swd = &ses->swcr_algorithms[i];
switch (swd->sw_alg) {
case CRYPTO_DES_CBC:
@@ -1071,6 +1049,7 @@ swcr_freesession_locked(device_t dev, u_int64_t tid)
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
@@ -1105,7 +1084,12 @@ swcr_freesession_locked(device_t dev, u_int64_t tid)
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
case CRYPTO_MD5:
+ case CRYPTO_POLY1305:
case CRYPTO_SHA1:
+ case CRYPTO_SHA2_224:
+ case CRYPTO_SHA2_256:
+ case CRYPTO_SHA2_384:
+ case CRYPTO_SHA2_512:
axf = swd->sw_axf;
if (swd->sw_ictx) {
@@ -1118,10 +1102,7 @@ swcr_freesession_locked(device_t dev, u_int64_t tid)
/* Nothing to do */
break;
}
-
- free(swd, M_CRYPTO_DATA);
}
- return 0;
}
/*
@@ -1130,9 +1111,10 @@ swcr_freesession_locked(device_t dev, u_int64_t tid)
static int
swcr_process(device_t dev, struct cryptop *crp, int hint)
{
+ struct swcr_session *ses;
struct cryptodesc *crd;
struct swcr_data *sw;
- u_int32_t lid;
+ size_t i;
/* Sanity check */
if (crp == NULL)
@@ -1143,15 +1125,7 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
goto done;
}
- lid = CRYPTO_SESID2LID(crp->crp_sid);
- rw_rlock(&swcr_sessions_lock);
- if (swcr_sessions == NULL || lid >= swcr_sesnum || lid == 0 ||
- swcr_sessions[lid] == NULL) {
- rw_runlock(&swcr_sessions_lock);
- crp->crp_etype = ENOENT;
- goto done;
- }
- rw_runlock(&swcr_sessions_lock);
+ ses = crypto_get_driver_session(crp->crp_session);
/* Go through crypto descriptors, processing as we go */
for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
@@ -1165,23 +1139,16 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
* XXX between the various instances of an algorithm (so we can
* XXX locate the correct crypto context).
*/
- rw_rlock(&swcr_sessions_lock);
- if (swcr_sessions == NULL) {
- rw_runlock(&swcr_sessions_lock);
- crp->crp_etype = ENOENT;
- goto done;
- }
- for (sw = swcr_sessions[lid];
- sw && sw->sw_alg != crd->crd_alg;
- sw = sw->sw_next)
+ for (i = 0; i < nitems(ses->swcr_algorithms) &&
+ ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++)
;
- rw_runlock(&swcr_sessions_lock);
/* No such context ? */
- if (sw == NULL) {
+ if (i == nitems(ses->swcr_algorithms)) {
crp->crp_etype = EINVAL;
goto done;
}
+ sw = &ses->swcr_algorithms[i];
switch (sw->sw_alg) {
case CRYPTO_DES_CBC:
case CRYPTO_3DES_CBC:
@@ -1202,6 +1169,7 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
break;
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
@@ -1211,8 +1179,13 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
case CRYPTO_SHA1_KPDK:
case CRYPTO_MD5:
case CRYPTO_SHA1:
+ case CRYPTO_SHA2_224:
+ case CRYPTO_SHA2_256:
+ case CRYPTO_SHA2_384:
+ case CRYPTO_SHA2_512:
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
+ case CRYPTO_POLY1305:
if ((crp->crp_etype = swcr_authcompute(crd, sw,
crp->crp_buf, crp->crp_flags)) != 0)
goto done;
@@ -1265,11 +1238,10 @@ swcr_probe(device_t dev)
static int
swcr_attach(device_t dev)
{
- rw_init(&swcr_sessions_lock, "swcr_sessions_lock");
memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN);
memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN);
- swcr_id = crypto_get_driverid(dev,
+ swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
if (swcr_id < 0) {
device_printf(dev, "cannot initialize!");
@@ -1285,6 +1257,7 @@ swcr_attach(device_t dev)
REGISTER(CRYPTO_NULL_CBC);
REGISTER(CRYPTO_MD5_HMAC);
REGISTER(CRYPTO_SHA1_HMAC);
+ REGISTER(CRYPTO_SHA2_224_HMAC);
REGISTER(CRYPTO_SHA2_256_HMAC);
REGISTER(CRYPTO_SHA2_384_HMAC);
REGISTER(CRYPTO_SHA2_512_HMAC);
@@ -1294,6 +1267,10 @@ swcr_attach(device_t dev)
REGISTER(CRYPTO_SHA1_KPDK);
REGISTER(CRYPTO_MD5);
REGISTER(CRYPTO_SHA1);
+ REGISTER(CRYPTO_SHA2_224);
+ REGISTER(CRYPTO_SHA2_256);
+ REGISTER(CRYPTO_SHA2_384);
+ REGISTER(CRYPTO_SHA2_512);
REGISTER(CRYPTO_RIJNDAEL128_CBC);
REGISTER(CRYPTO_AES_XTS);
REGISTER(CRYPTO_AES_ICM);
@@ -1307,6 +1284,7 @@ swcr_attach(device_t dev)
REGISTER(CRYPTO_BLAKE2B);
REGISTER(CRYPTO_BLAKE2S);
REGISTER(CRYPTO_CHACHA20);
+ REGISTER(CRYPTO_POLY1305);
#undef REGISTER
return 0;
@@ -1316,11 +1294,6 @@ static int
swcr_detach(device_t dev)
{
crypto_unregister_all(swcr_id);
- rw_wlock(&swcr_sessions_lock);
- free(swcr_sessions, M_CRYPTO_DATA);
- swcr_sessions = NULL;
- rw_wunlock(&swcr_sessions_lock);
- rw_destroy(&swcr_sessions_lock);
return 0;
}
diff --git a/freebsd/sys/opencrypto/cryptosoft.h b/freebsd/sys/opencrypto/cryptosoft.h
index af78dc18..d88b09d4 100644
--- a/freebsd/sys/opencrypto/cryptosoft.h
+++ b/freebsd/sys/opencrypto/cryptosoft.h
@@ -55,8 +55,11 @@ struct swcr_data {
#define sw_exf SWCR_UN.SWCR_ENC.SW_exf
#define sw_size SWCR_UN.SWCR_COMP.SW_size
#define sw_cxf SWCR_UN.SWCR_COMP.SW_cxf
+};
- struct swcr_data *sw_next;
+struct swcr_session {
+ struct swcr_data swcr_algorithms[2];
+ unsigned swcr_nalgs;
};
#ifdef _KERNEL
diff --git a/freebsd/sys/opencrypto/xform_auth.h b/freebsd/sys/opencrypto/xform_auth.h
index 74c6d063..06183868 100644
--- a/freebsd/sys/opencrypto/xform_auth.h
+++ b/freebsd/sys/opencrypto/xform_auth.h
@@ -69,14 +69,21 @@ extern struct auth_hash auth_hash_key_sha1;
extern struct auth_hash auth_hash_hmac_md5;
extern struct auth_hash auth_hash_hmac_sha1;
extern struct auth_hash auth_hash_hmac_ripemd_160;
+extern struct auth_hash auth_hash_hmac_sha2_224;
extern struct auth_hash auth_hash_hmac_sha2_256;
extern struct auth_hash auth_hash_hmac_sha2_384;
extern struct auth_hash auth_hash_hmac_sha2_512;
+extern struct auth_hash auth_hash_sha1;
+extern struct auth_hash auth_hash_sha2_224;
+extern struct auth_hash auth_hash_sha2_256;
+extern struct auth_hash auth_hash_sha2_384;
+extern struct auth_hash auth_hash_sha2_512;
extern struct auth_hash auth_hash_nist_gmac_aes_128;
extern struct auth_hash auth_hash_nist_gmac_aes_192;
extern struct auth_hash auth_hash_nist_gmac_aes_256;
extern struct auth_hash auth_hash_blake2b;
extern struct auth_hash auth_hash_blake2s;
+extern struct auth_hash auth_hash_poly1305;
union authctx {
MD5_CTX md5ctx;
diff --git a/freebsd/sys/opencrypto/xform_md5.c b/freebsd/sys/opencrypto/xform_md5.c
index 47dfc75c..5611ee39 100644
--- a/freebsd/sys/opencrypto/xform_md5.c
+++ b/freebsd/sys/opencrypto/xform_md5.c
@@ -59,10 +59,10 @@ static int MD5Update_int(void *, const u_int8_t *, u_int16_t);
struct auth_hash auth_hash_hmac_md5 = {
.type = CRYPTO_MD5_HMAC,
.name = "HMAC-MD5",
- .keysize = MD5_HMAC_BLOCK_LEN,
+ .keysize = MD5_BLOCK_LEN,
.hashsize = MD5_HASH_LEN,
.ctxsize = sizeof(MD5_CTX),
- .blocksize = MD5_HMAC_BLOCK_LEN,
+ .blocksize = MD5_BLOCK_LEN,
.Init = (void (*) (void *)) MD5Init,
.Update = MD5Update_int,
.Final = (void (*) (u_int8_t *, void *)) MD5Final,
diff --git a/freebsd/sys/opencrypto/xform_poly1305.c b/freebsd/sys/opencrypto/xform_poly1305.c
new file mode 100644
index 00000000..a138a3f5
--- /dev/null
+++ b/freebsd/sys/opencrypto/xform_poly1305.c
@@ -0,0 +1,93 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/* This file is in the public domain. */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <opencrypto/xform_auth.h>
+#include <opencrypto/xform_poly1305.h>
+
+#include <sodium/crypto_onetimeauth_poly1305.h>
+
+struct poly1305_xform_ctx {
+ struct crypto_onetimeauth_poly1305_state state;
+};
+CTASSERT(sizeof(union authctx) >= sizeof(struct poly1305_xform_ctx));
+
+CTASSERT(POLY1305_KEY_LEN == crypto_onetimeauth_poly1305_KEYBYTES);
+CTASSERT(POLY1305_HASH_LEN == crypto_onetimeauth_poly1305_BYTES);
+
+void
+Poly1305_Init(struct poly1305_xform_ctx *polyctx)
+{
+ /* Nop */
+}
+
+void
+Poly1305_Setkey(struct poly1305_xform_ctx *polyctx,
+ const uint8_t key[__min_size(POLY1305_KEY_LEN)], size_t klen)
+{
+ int rc;
+
+ if (klen != POLY1305_KEY_LEN)
+ panic("%s: Bogus keylen: %u bytes", __func__, (unsigned)klen);
+
+ rc = crypto_onetimeauth_poly1305_init(&polyctx->state, key);
+ if (rc != 0)
+ panic("%s: Invariant violated: %d", __func__, rc);
+}
+
+static void
+xform_Poly1305_Setkey(void *ctx, const uint8_t *key, uint16_t klen)
+{
+ Poly1305_Setkey(ctx, key, klen);
+}
+
+int
+Poly1305_Update(struct poly1305_xform_ctx *polyctx, const void *data,
+ size_t len)
+{
+ int rc;
+
+ rc = crypto_onetimeauth_poly1305_update(&polyctx->state, data, len);
+ if (rc != 0)
+ panic("%s: Invariant violated: %d", __func__, rc);
+ return (0);
+}
+
+static int
+xform_Poly1305_Update(void *ctx, const uint8_t *data, uint16_t len)
+{
+ return (Poly1305_Update(ctx, data, len));
+}
+
+void
+Poly1305_Final(uint8_t digest[__min_size(POLY1305_HASH_LEN)],
+ struct poly1305_xform_ctx *polyctx)
+{
+ int rc;
+
+ rc = crypto_onetimeauth_poly1305_final(&polyctx->state, digest);
+ if (rc != 0)
+ panic("%s: Invariant violated: %d", __func__, rc);
+}
+
+static void
+xform_Poly1305_Final(uint8_t *digest, void *ctx)
+{
+ Poly1305_Final(digest, ctx);
+}
+
+struct auth_hash auth_hash_poly1305 = {
+ .type = CRYPTO_POLY1305,
+ .name = "Poly-1305",
+ .keysize = POLY1305_KEY_LEN,
+ .hashsize = POLY1305_HASH_LEN,
+ .ctxsize = sizeof(struct poly1305_xform_ctx),
+ .blocksize = crypto_onetimeauth_poly1305_BYTES,
+ .Init = (void *)Poly1305_Init,
+ .Setkey = xform_Poly1305_Setkey,
+ .Update = xform_Poly1305_Update,
+ .Final = xform_Poly1305_Final,
+};
diff --git a/freebsd/sys/opencrypto/xform_poly1305.h b/freebsd/sys/opencrypto/xform_poly1305.h
new file mode 100644
index 00000000..7364ecde
--- /dev/null
+++ b/freebsd/sys/opencrypto/xform_poly1305.h
@@ -0,0 +1,16 @@
+/* This file is in the public domain. */
+/* $FreeBSD$ */
+#pragma once
+
+#include <sys/types.h>
+
+struct poly1305_xform_ctx;
+
+void Poly1305_Init(struct poly1305_xform_ctx *);
+
+void Poly1305_Setkey(struct poly1305_xform_ctx *,
+ const uint8_t [__min_size(32)], size_t);
+
+int Poly1305_Update(struct poly1305_xform_ctx *, const void *, size_t);
+
+void Poly1305_Final(uint8_t [__min_size(16)], struct poly1305_xform_ctx *);
diff --git a/freebsd/sys/opencrypto/xform_rmd160.c b/freebsd/sys/opencrypto/xform_rmd160.c
index ee344e80..98297308 100644
--- a/freebsd/sys/opencrypto/xform_rmd160.c
+++ b/freebsd/sys/opencrypto/xform_rmd160.c
@@ -59,10 +59,10 @@ static int RMD160Update_int(void *, const u_int8_t *, u_int16_t);
struct auth_hash auth_hash_hmac_ripemd_160 = {
.type = CRYPTO_RIPEMD160_HMAC,
.name = "HMAC-RIPEMD-160",
- .keysize = RIPEMD160_HMAC_BLOCK_LEN,
+ .keysize = RIPEMD160_BLOCK_LEN,
.hashsize = RIPEMD160_HASH_LEN,
.ctxsize = sizeof(RMD160_CTX),
- .blocksize = RIPEMD160_HMAC_BLOCK_LEN,
+ .blocksize = RIPEMD160_BLOCK_LEN,
.Init = (void (*)(void *)) RMD160Init,
.Update = RMD160Update_int,
.Final = (void (*)(u_int8_t *, void *)) RMD160Final,
diff --git a/freebsd/sys/opencrypto/xform_sha1.c b/freebsd/sys/opencrypto/xform_sha1.c
index 974dfb8a..44ac8c0e 100644
--- a/freebsd/sys/opencrypto/xform_sha1.c
+++ b/freebsd/sys/opencrypto/xform_sha1.c
@@ -57,14 +57,26 @@ static void SHA1Init_int(void *);
static int SHA1Update_int(void *, const u_int8_t *, u_int16_t);
static void SHA1Final_int(u_int8_t *, void *);
+/* Plain hash */
+struct auth_hash auth_hash_sha1 = {
+ .type = CRYPTO_SHA1,
+ .name = "SHA1",
+ .hashsize = SHA1_HASH_LEN,
+ .ctxsize = sizeof(SHA1_CTX),
+ .blocksize = SHA1_BLOCK_LEN,
+ .Init = SHA1Init_int,
+ .Update = SHA1Update_int,
+ .Final = SHA1Final_int,
+};
+
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha1 = {
.type = CRYPTO_SHA1_HMAC,
.name = "HMAC-SHA1",
- .keysize = SHA1_HMAC_BLOCK_LEN,
+ .keysize = SHA1_BLOCK_LEN,
.hashsize = SHA1_HASH_LEN,
.ctxsize = sizeof(SHA1_CTX),
- .blocksize = SHA1_HMAC_BLOCK_LEN,
+ .blocksize = SHA1_BLOCK_LEN,
.Init = SHA1Init_int,
.Update = SHA1Update_int,
.Final = SHA1Final_int,
diff --git a/freebsd/sys/opencrypto/xform_sha2.c b/freebsd/sys/opencrypto/xform_sha2.c
index 7844b8ff..0775247a 100644
--- a/freebsd/sys/opencrypto/xform_sha2.c
+++ b/freebsd/sys/opencrypto/xform_sha2.c
@@ -50,23 +50,85 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <crypto/sha2/sha224.h>
#include <crypto/sha2/sha256.h>
#include <crypto/sha2/sha384.h>
#include <crypto/sha2/sha512.h>
#include <opencrypto/xform_auth.h>
+static int SHA224Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA256Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA384Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
+/* Plain hashes */
+struct auth_hash auth_hash_sha2_224 = {
+ .type = CRYPTO_SHA2_224,
+ .name = "SHA2-224",
+ .hashsize = SHA2_224_HASH_LEN,
+ .ctxsize = sizeof(SHA224_CTX),
+ .blocksize = SHA2_224_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA224_Init,
+ .Update = SHA224Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA224_Final,
+};
+
+struct auth_hash auth_hash_sha2_256 = {
+ .type = CRYPTO_SHA2_256,
+ .name = "SHA2-256",
+ .keysize = SHA2_256_BLOCK_LEN,
+ .hashsize = SHA2_256_HASH_LEN,
+ .ctxsize = sizeof(SHA256_CTX),
+ .blocksize = SHA2_256_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA256_Init,
+ .Update = SHA256Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA256_Final,
+};
+
+struct auth_hash auth_hash_sha2_384 = {
+ .type = CRYPTO_SHA2_384,
+ .name = "SHA2-384",
+ .keysize = SHA2_384_BLOCK_LEN,
+ .hashsize = SHA2_384_HASH_LEN,
+ .ctxsize = sizeof(SHA384_CTX),
+ .blocksize = SHA2_384_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA384_Init,
+ .Update = SHA384Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA384_Final,
+};
+
+struct auth_hash auth_hash_sha2_512 = {
+ .type = CRYPTO_SHA2_512,
+ .name = "SHA2-512",
+ .keysize = SHA2_512_BLOCK_LEN,
+ .hashsize = SHA2_512_HASH_LEN,
+ .ctxsize = sizeof(SHA512_CTX),
+ .blocksize = SHA2_512_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA512_Init,
+ .Update = SHA512Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA512_Final,
+};
+
/* Authentication instances */
+struct auth_hash auth_hash_hmac_sha2_224 = {
+ .type = CRYPTO_SHA2_224_HMAC,
+ .name = "HMAC-SHA2-224",
+ .keysize = SHA2_224_BLOCK_LEN,
+ .hashsize = SHA2_224_HASH_LEN,
+ .ctxsize = sizeof(SHA224_CTX),
+ .blocksize = SHA2_224_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA224_Init,
+ .Update = SHA224Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA224_Final,
+};
+
struct auth_hash auth_hash_hmac_sha2_256 = {
.type = CRYPTO_SHA2_256_HMAC,
.name = "HMAC-SHA2-256",
- .keysize = SHA2_256_HMAC_BLOCK_LEN,
+ .keysize = SHA2_256_BLOCK_LEN,
.hashsize = SHA2_256_HASH_LEN,
.ctxsize = sizeof(SHA256_CTX),
- .blocksize = SHA2_256_HMAC_BLOCK_LEN,
+ .blocksize = SHA2_256_BLOCK_LEN,
.Init = (void (*)(void *)) SHA256_Init,
.Update = SHA256Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA256_Final,
@@ -75,10 +137,10 @@ struct auth_hash auth_hash_hmac_sha2_256 = {
struct auth_hash auth_hash_hmac_sha2_384 = {
.type = CRYPTO_SHA2_384_HMAC,
.name = "HMAC-SHA2-384",
- .keysize = SHA2_384_HMAC_BLOCK_LEN,
+ .keysize = SHA2_384_BLOCK_LEN,
.hashsize = SHA2_384_HASH_LEN,
.ctxsize = sizeof(SHA384_CTX),
- .blocksize = SHA2_384_HMAC_BLOCK_LEN,
+ .blocksize = SHA2_384_BLOCK_LEN,
.Init = (void (*)(void *)) SHA384_Init,
.Update = SHA384Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA384_Final,
@@ -87,10 +149,10 @@ struct auth_hash auth_hash_hmac_sha2_384 = {
struct auth_hash auth_hash_hmac_sha2_512 = {
.type = CRYPTO_SHA2_512_HMAC,
.name = "HMAC-SHA2-512",
- .keysize = SHA2_512_HMAC_BLOCK_LEN,
+ .keysize = SHA2_512_BLOCK_LEN,
.hashsize = SHA2_512_HASH_LEN,
.ctxsize = sizeof(SHA512_CTX),
- .blocksize = SHA2_512_HMAC_BLOCK_LEN,
+ .blocksize = SHA2_512_BLOCK_LEN,
.Init = (void (*)(void *)) SHA512_Init,
.Update = SHA512Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA512_Final,
@@ -100,6 +162,13 @@ struct auth_hash auth_hash_hmac_sha2_512 = {
* And now for auth.
*/
static int
+SHA224Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
+{
+ SHA224_Update(ctx, buf, len);
+ return 0;
+}
+
+static int
SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA256_Update(ctx, buf, len);
diff --git a/freebsd/sys/powerpc/include/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h
index f4769c86..fba367cb 100644
--- a/freebsd/sys/powerpc/include/machine/spr.h
+++ b/freebsd/sys/powerpc/include/machine/spr.h
@@ -229,7 +229,6 @@
#define EPCR_DGTMI 0x00800000
#define EPCR_DMIUH 0x00400000
#define EPCR_PMGS 0x00200000
-#define SPR_SPEFSCR 0x200 /* ..8 Signal Processing Engine FSCR. */
#define SPR_HSRR0 0x13a
#define SPR_HSRR1 0x13b
@@ -245,7 +244,7 @@
#define SPR_LPID 0x13f /* Logical Partitioning Control */
#define SPR_PTCR 0x1d0 /* Partition Table Control Register */
-#define SPR_IBAT0U 0x210 /* .68 Instruction BAT Reg 0 Upper */
+#define SPR_SPEFSCR 0x200 /* ..8 Signal Processing Engine FSCR. */
#define SPR_IBAT0U 0x210 /* .6. Instruction BAT Reg 0 Upper */
#define SPR_IBAT0L 0x211 /* .6. Instruction BAT Reg 0 Lower */
#define SPR_IBAT1U 0x212 /* .6. Instruction BAT Reg 1 Upper */
@@ -384,6 +383,7 @@
#define SPR_MD_RAM0 0x339 /* ..8 IMMU RAM entry read reg 0 */
#define SPR_MD_RAM1 0x33a /* ..8 IMMU RAM entry read reg 1 */
#define SPR_PSSCR 0x357 /* Processor Stop Status and Control Register (ISA 3.0) */
+#define SPR_PMCR 0x374 /* Processor Management Control Register */
#define SPR_UMMCR2 0x3a0 /* .6. User Monitor Mode Control Register 2 */
#define SPR_UMMCR0 0x3a8 /* .6. User Monitor Mode Control Register 0 */
#define SPR_USIA 0x3ab /* .6. User Sampled Instruction Address */
diff --git a/freebsd/sys/sys/bus.h b/freebsd/sys/sys/bus.h
index f3c54f36..74a48f81 100644
--- a/freebsd/sys/sys/bus.h
+++ b/freebsd/sys/sys/bus.h
@@ -92,7 +92,9 @@ struct u_device {
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
#define DF_REBID 0x80 /* Can rebid after attach */
#define DF_SUSPENDED 0x100 /* Device is suspended. */
-#define DF_QUIET_CHILDREN 0x200 /* Default to quiet for all my children */
+#define DF_QUIET_CHILDREN 0x200 /* Default to quiet for all my children */
+#define DF_ATTACHED_ONCE 0x400 /* Has been attached at least once */
+#define DF_NEEDNOMATCH 0x800 /* Has a pending NOMATCH event */
/**
* @brief Device request structure used for ioctl's.
@@ -126,6 +128,8 @@ struct devreq {
#define DEV_CLEAR_DRIVER _IOW('D', 8, struct devreq)
#define DEV_RESCAN _IOW('D', 9, struct devreq)
#define DEV_DELETE _IOW('D', 10, struct devreq)
+#define DEV_FREEZE _IOW('D', 11, struct devreq)
+#define DEV_THAW _IOW('D', 12, struct devreq)
/* Flags for DEV_DETACH and DEV_DISABLE. */
#define DEVF_FORCE_DETACH 0x0000001
@@ -156,7 +160,8 @@ void devctl_notify(const char *__system, const char *__subsystem,
const char *__type, const char *__data);
void devctl_queue_data_f(char *__data, int __flags);
void devctl_queue_data(char *__data);
-void devctl_safe_quote(char *__dst, const char *__src, size_t len);
+struct sbuf;
+void devctl_safe_quote_sb(struct sbuf *__sb, const char *__src);
/**
* Device name parsers. Hook to allow device enumerators to map
diff --git a/freebsd/sys/sys/cpu.h b/freebsd/sys/sys/cpu.h
index b3b745ab..8a74e470 100644
--- a/freebsd/sys/sys/cpu.h
+++ b/freebsd/sys/sys/cpu.h
@@ -87,7 +87,7 @@ struct cf_setting {
};
/* Maximum number of settings a given driver can have. */
-#define MAX_SETTINGS 24
+#define MAX_SETTINGS 256
/* A combination of settings is a level. */
struct cf_level {
diff --git a/freebsd/sys/sys/file.h b/freebsd/sys/sys/file.h
index a566e69c..20beac22 100644
--- a/freebsd/sys/sys/file.h
+++ b/freebsd/sys/sys/file.h
@@ -297,18 +297,23 @@ rtems_bsd_error_to_status_and_errno(int error)
* Userland version of struct file, for sysctl
*/
struct xfile {
- size_t xf_size; /* size of struct xfile */
+ ksize_t xf_size; /* size of struct xfile */
pid_t xf_pid; /* owning process */
uid_t xf_uid; /* effective uid of owning process */
int xf_fd; /* descriptor number */
- void *xf_file; /* address of struct file */
+ int _xf_int_pad1;
+ kvaddr_t xf_file; /* address of struct file */
short xf_type; /* descriptor type */
+ short _xf_short_pad1;
int xf_count; /* reference count */
int xf_msgcount; /* references from message queue */
+ int _xf_int_pad2;
off_t xf_offset; /* file offset */
- void *xf_data; /* file descriptor specific data */
- void *xf_vnode; /* vnode pointer */
+ kvaddr_t xf_data; /* file descriptor specific data */
+ kvaddr_t xf_vnode; /* vnode pointer */
u_int xf_flag; /* flags (see fcntl.h) */
+ int _xf_int_pad3;
+ int64_t _xf_int64_pad[6];
};
#ifdef _KERNEL
diff --git a/freebsd/sys/sys/interrupt.h b/freebsd/sys/sys/interrupt.h
index 7c9aad4d..105bb968 100644
--- a/freebsd/sys/sys/interrupt.h
+++ b/freebsd/sys/sys/interrupt.h
@@ -33,6 +33,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
+#include <sys/ck.h>
struct intr_event;
struct intr_thread;
@@ -52,7 +53,7 @@ struct intr_handler {
char ih_name[MAXCOMLEN + 1]; /* Name of handler. */
struct intr_event *ih_event; /* Event we are connected to. */
int ih_need; /* Needs service. */
- TAILQ_ENTRY(intr_handler) ih_next; /* Next handler for this event. */
+ CK_SLIST_ENTRY(intr_handler) ih_next; /* Next handler for this event. */
u_char ih_pri; /* Priority of this handler. */
struct intr_thread *ih_thread; /* Ithread for filtered handler. */
};
@@ -105,7 +106,7 @@ struct intr_handler {
*/
struct intr_event {
TAILQ_ENTRY(intr_event) ie_list;
- TAILQ_HEAD(, intr_handler) ie_handlers; /* Interrupt handlers. */
+ CK_SLIST_HEAD(, intr_handler) ie_handlers; /* Interrupt handlers. */
char ie_name[MAXCOMLEN + 1]; /* Individual event name. */
char ie_fullname[MAXCOMLEN + 1];
struct mtx ie_lock;
@@ -121,6 +122,8 @@ struct intr_event {
struct timeval ie_warntm;
int ie_irq; /* Physical irq number if !SOFT. */
int ie_cpu; /* CPU this event is bound to. */
+ volatile int ie_phase; /* Switched to establish a barrier. */
+ volatile int ie_active[2]; /* Filters in ISR context. */
};
/* Interrupt event flags kept in ie_flags. */
@@ -151,8 +154,13 @@ extern struct intr_event *clk_intr_event;
extern void *vm_ih;
/* Counts and names for statistics (defined in MD code). */
+#if defined(__amd64__) || defined(__i386__)
+extern u_long *intrcnt; /* counts for for each device and stray */
+extern char *intrnames; /* string table containing device names */
+#else
extern u_long intrcnt[]; /* counts for for each device and stray */
extern char intrnames[]; /* string table containing device names */
+#endif
extern size_t sintrcnt; /* size of intrcnt table */
extern size_t sintrnames; /* size of intrnames table */
@@ -174,7 +182,6 @@ int intr_event_create(struct intr_event **event, void *source,
int intr_event_describe_handler(struct intr_event *ie, void *cookie,
const char *descr);
int intr_event_destroy(struct intr_event *ie);
-void intr_event_execute_handlers(struct proc *p, struct intr_event *ie);
int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
int intr_event_remove_handler(void *cookie);
int intr_getaffinity(int irq, int mode, void *mask);
diff --git a/freebsd/sys/sys/jail.h b/freebsd/sys/sys/jail.h
index c42964fe..6f8c9aa5 100644
--- a/freebsd/sys/sys/jail.h
+++ b/freebsd/sys/sys/jail.h
@@ -227,9 +227,10 @@ struct prison_racct {
#define PR_ALLOW_MOUNT 0x00000010
#define PR_ALLOW_QUOTAS 0x00000020
#define PR_ALLOW_SOCKET_AF 0x00000040
+#define PR_ALLOW_MLOCK 0x00000080
#define PR_ALLOW_RESERVED_PORTS 0x00008000
#define PR_ALLOW_KMEM_ACCESS 0x00010000 /* reserved, not used yet */
-#define PR_ALLOW_ALL_STATIC 0x0001807f
+#define PR_ALLOW_ALL_STATIC 0x000180ff
/*
* OSD methods
@@ -417,6 +418,8 @@ int prison_if(struct ucred *cred, struct sockaddr *sa);
char *prison_name(struct prison *, struct prison *);
int prison_priv_check(struct ucred *cred, int priv);
int sysctl_jail_param(SYSCTL_HANDLER_ARGS);
+unsigned prison_add_allow(const char *prefix, const char *name,
+ const char *prefix_descr, const char *descr);
void prison_add_vfs(struct vfsconf *vfsp);
void prison_racct_foreach(void (*callback)(struct racct *racct,
void *arg2, void *arg3), void (*pre)(void), void (*post)(void),
diff --git a/freebsd/sys/sys/libkern.h b/freebsd/sys/sys/libkern.h
index dc24036b..28da25ca 100644
--- a/freebsd/sys/sys/libkern.h
+++ b/freebsd/sys/sys/libkern.h
@@ -144,11 +144,6 @@ arc4rand(void *ptr, u_int len, int reseed)
arc4random_buf(ptr, len);
}
#endif /* __rtems__ */
-#ifndef __rtems__
-int bcmp(const void *, const void *, size_t);
-#else /* __rtems__ */
-#define bcmp(m1, m2, n) memcmp(m1, m2, n)
-#endif /* __rtems__ */
int timingsafe_bcmp(const void *, const void *, size_t);
void *bsearch(const void *, const void *, size_t,
size_t, int (*)(const void *, const void *));
@@ -210,7 +205,6 @@ int fnmatch(const char *, const char *, int);
int locc(int, char *, u_int);
void *memchr(const void *s, int c, size_t n);
void *memcchr(const void *s, int c, size_t n);
-int memcmp(const void *b1, const void *b2, size_t len);
void *memmem(const void *l, size_t l_len, const void *s, size_t s_len);
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
@@ -290,23 +284,6 @@ uint32_t armv8_crc32c(uint32_t, const unsigned char *, unsigned int);
#endif
#endif
-
-LIBKERN_INLINE void *memset(void *, int, size_t);
-#ifdef LIBKERN_BODY
-LIBKERN_INLINE void *
-memset(void *b, int c, size_t len)
-{
- char *bb;
-
- if (c == 0)
- bzero(b, len);
- else
- for (bb = (char *)b; len--; )
- *bb++ = c;
- return (b);
-}
-#endif
-
#ifndef __rtems__
static __inline char *
index(const char *p, int ch)
diff --git a/freebsd/sys/sys/linker.h b/freebsd/sys/sys/linker.h
index 21c5a41e..8aae31d9 100644
--- a/freebsd/sys/sys/linker.h
+++ b/freebsd/sys/sys/linker.h
@@ -273,10 +273,9 @@ extern int kld_debug;
typedef int elf_lookup_fn(linker_file_t, Elf_Size, int, Elf_Addr *);
/* Support functions */
+bool elf_is_ifunc_reloc(Elf_Size r_info);
int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel,
int _type, elf_lookup_fn _lu);
-int elf_reloc_ifunc(linker_file_t _lf, Elf_Addr base, const void *_rel,
- int _type, elf_lookup_fn _lu);
int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel,
int _type, elf_lookup_fn _lu);
Elf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr);
diff --git a/freebsd/sys/sys/malloc.h b/freebsd/sys/sys/malloc.h
index 8c66fe81..33e1aab9 100644
--- a/freebsd/sys/sys/malloc.h
+++ b/freebsd/sys/sys/malloc.h
@@ -38,6 +38,9 @@
#define _SYS_MALLOC_H_
#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#endif
#include <sys/queue.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
@@ -46,7 +49,7 @@
#define MINALLOCSIZE UMA_SMALLEST_UNIT
/*
- * flags to malloc.
+ * Flags to memory allocation functions.
*/
#define M_NOWAIT 0x0001 /* do not block */
#define M_WAITOK 0x0002 /* ok to block */
@@ -56,16 +59,10 @@
#define M_NODUMP 0x0800 /* don't dump pages in this allocation */
#define M_FIRSTFIT 0x1000 /* Only for vmem, fast fit. */
#define M_BESTFIT 0x2000 /* Only for vmem, low fragmentation. */
+#define M_EXEC 0x4000 /* allocate executable space. */
#define M_MAGIC 877983977 /* time when first defined :-) */
-#ifdef INVARIANTS
-#define M_ZERO_INVARIANTS M_ZERO
-#else
-#define M_ZERO_INVARIANTS 0
-#endif
-
-
/*
* Two malloc type structures are present: malloc_type, which is used by a
* type owner to declare the type, and malloc_type_internal, which holds
@@ -142,7 +139,6 @@ struct malloc_type_header {
#ifdef _KERNEL
#ifdef __rtems__
#include <stdlib.h>
-#define malloc _bsd_malloc
#define realloc _bsd_realloc
#define reallocf _bsd_reallocf
#define free _bsd_free
@@ -188,8 +184,70 @@ void *contigmalloc_domain(unsigned long size, struct malloc_type *type,
__malloc_like __result_use_check __alloc_size(1) __alloc_align(6);
void free(void *addr, struct malloc_type *type);
void free_domain(void *addr, struct malloc_type *type);
+#ifndef __rtems__
void *malloc(size_t size, struct malloc_type *type, int flags) __malloc_like
__result_use_check __alloc_size(1);
+#else /* __rtems__ */
+void *_bsd_malloc(size_t size, struct malloc_type *type, int flags)
+ __malloc_like __result_use_check __alloc_size(1);
+#endif /* __rtems__ */
+/*
+ * Try to optimize malloc(..., ..., M_ZERO) allocations by doing zeroing in
+ * place if the size is known at compilation time.
+ *
+ * Passing the flag down requires malloc to blindly zero the entire object.
+ * In practice a lot of the zeroing can be avoided if most of the object
+ * gets explicitly initialized after the allocation. Letting the compiler
+ * zero in place gives it the opportunity to take advantage of this state.
+ *
+ * Note that the operation is only applicable if both flags and size are
+ * known at compilation time. If M_ZERO is passed but M_WAITOK is not, the
+ * allocation can fail and a NULL check is needed. However, if M_WAITOK is
+ * passed we know the allocation must succeed and the check can be elided.
+ *
+ * _malloc_item = malloc(_size, type, (flags) &~ M_ZERO);
+ * if (((flags) & M_WAITOK) != 0 || _malloc_item != NULL)
+ * bzero(_malloc_item, _size);
+ *
+ * If the flag is set, the compiler knows the left side is always true,
+ * therefore the entire statement is true and the callsite is:
+ *
+ * _malloc_item = malloc(_size, type, (flags) &~ M_ZERO);
+ * bzero(_malloc_item, _size);
+ *
+ * If the flag is not set, the compiler knows the left size is always false
+ * and the NULL check is needed, therefore the callsite is:
+ *
+ * _malloc_item = malloc(_size, type, (flags) &~ M_ZERO);
+ * if (_malloc_item != NULL)
+ * bzero(_malloc_item, _size);
+ *
+ * The implementation is a macro because of what appears to be a clang 6 bug:
+ * an inline function variant ended up being compiled to a mere malloc call
+ * regardless of argument. gcc generates expected code (like the above).
+ */
+#ifdef __rtems__
+/*
+ * The macro below was modified without the __rtems__ guards. This macro looks
+ * quite brittle and it is better to provoke a merge conflict in case of a
+ * FreeBSD baseline update.
+ */
+#endif /* __rtems__ */
+#define malloc(size, type, flags) ({ \
+ void *_malloc_item; \
+ size_t _size = (size); \
+ if (__builtin_constant_p(size) && __builtin_constant_p(flags) &&\
+ ((flags) & M_ZERO) != 0) { \
+ _malloc_item = _bsd_malloc(_size, type, (flags) &~ M_ZERO); \
+ if (((flags) & M_WAITOK) != 0 || \
+ __predict_true(_malloc_item != NULL)) \
+ bzero(_malloc_item, _size); \
+ } else { \
+ _malloc_item = _bsd_malloc(_size, type, flags); \
+ } \
+ _malloc_item; \
+})
+
void *malloc_domain(size_t size, struct malloc_type *type, int domain,
int flags) __malloc_like __result_use_check __alloc_size(1);
void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type,
diff --git a/freebsd/sys/sys/mbuf.h b/freebsd/sys/sys/mbuf.h
index 4d2a3223..0423b580 100644
--- a/freebsd/sys/sys/mbuf.h
+++ b/freebsd/sys/sys/mbuf.h
@@ -304,7 +304,7 @@ struct mbuf {
#define M_MCAST 0x00000020 /* send/received as link-level multicast */
#define M_PROMISC 0x00000040 /* packet was not for us */
#define M_VLANTAG 0x00000080 /* ether_vtag is valid */
-#define M_UNUSED_8 0x00000100 /* --available-- */
+#define M_NOMAP 0x00000100 /* mbuf data is unmapped (soon from Drew) */
#define M_NOFREE 0x00000200 /* do not free mbuf, embedded in cluster */
#define M_TSTMP 0x00000400 /* rcv_tstmp field is valid */
#define M_TSTMP_HPREC 0x00000800 /* rcv_tstmp is high-prec, typically
@@ -570,8 +570,8 @@ struct mbuf {
#define MT_EXP4 12 /* for experimental use */
#define MT_CONTROL 14 /* extra-data protocol message */
-#define MT_OOBDATA 15 /* expedited data */
-#define MT_NTYPES 16 /* number of mbuf types for mbtypes[] */
+#define MT_EXTCONTROL 15 /* control message with externalized contents */
+#define MT_OOBDATA 16 /* expedited data */
#define MT_NOINIT 255 /* Not a type but a flag to allocate
a non-initialized mbuf */
@@ -636,6 +636,7 @@ void m_demote_pkthdr(struct mbuf *);
void m_demote(struct mbuf *, int, int);
struct mbuf *m_devget(char *, int, int, struct ifnet *,
void (*)(char *, caddr_t, u_int));
+void m_dispose_extcontrolm(struct mbuf *m);
struct mbuf *m_dup(const struct mbuf *, int);
int m_dup_pkthdr(struct mbuf *, const struct mbuf *, int);
void m_extadd(struct mbuf *, char *, u_int, m_ext_free_t,
diff --git a/freebsd/sys/sys/module.h b/freebsd/sys/sys/module.h
index 6799b179..b40870d3 100644
--- a/freebsd/sys/sys/module.h
+++ b/freebsd/sys/sys/module.h
@@ -146,8 +146,13 @@ struct mod_pnp_match_info
SYSINIT(name##module, sub, order, module_register_init, &data); \
struct __hack
+#ifdef KLD_TIED
#define DECLARE_MODULE(name, data, sub, order) \
+ DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, __FreeBSD_version)
+#else
+#define DECLARE_MODULE(name, data, sub, order) \
DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, MODULE_KERNEL_MAXVER)
+#endif
/*
* The module declared with DECLARE_MODULE_TIED can only be loaded
diff --git a/freebsd/sys/sys/mouse.h b/freebsd/sys/sys/mouse.h
index a1f950cf..882d59c9 100644
--- a/freebsd/sys/sys/mouse.h
+++ b/freebsd/sys/sys/mouse.h
@@ -38,8 +38,6 @@
#define MOUSE_SETMODE _IOW('M', 3, mousemode_t)
#define MOUSE_GETLEVEL _IOR('M', 4, int)
#define MOUSE_SETLEVEL _IOW('M', 5, int)
-#define MOUSE_GETVARS _IOR('M', 6, mousevar_t)
-#define MOUSE_SETVARS _IOW('M', 7, mousevar_t)
#define MOUSE_READSTATE _IOWR('M', 8, mousedata_t)
#define MOUSE_READDATA _IOWR('M', 9, mousedata_t)
@@ -228,19 +226,6 @@ typedef struct mousedata {
int buf[16]; /* data buffer */
} mousedata_t;
-#if (defined(MOUSE_GETVARS))
-
-typedef struct mousevar {
- int var[16];
-} mousevar_t;
-
-/* magic numbers in var[0] */
-#define MOUSE_VARS_PS2_SIG 0x00325350 /* 'PS2' */
-#define MOUSE_VARS_BUS_SIG 0x00535542 /* 'BUS' */
-#define MOUSE_VARS_INPORT_SIG 0x00504e49 /* 'INP' */
-
-#endif /* MOUSE_GETVARS */
-
/* Synaptics Touchpad */
#define MOUSE_SYNAPTICS_PACKETSIZE 6 /* '3' works better */
diff --git a/freebsd/sys/sys/mutex.h b/freebsd/sys/sys/mutex.h
index e15de1ae..e9c91f80 100644
--- a/freebsd/sys/sys/mutex.h
+++ b/freebsd/sys/sys/mutex.h
@@ -161,7 +161,7 @@ void _thread_lock(struct thread *td, int opts, const char *file, int line);
void _thread_lock(struct thread *);
#endif
-#if defined(LOCK_PROFILING) || defined(KLD_MODULE)
+#if defined(LOCK_PROFILING) || (defined(KLD_MODULE) && !defined(KLD_TIED))
#define thread_lock(tdp) \
thread_lock_flags_((tdp), 0, __FILE__, __LINE__)
#elif LOCK_DEBUG > 0
diff --git a/freebsd/sys/sys/nv.h b/freebsd/sys/sys/nv.h
index bf40f8f3..80fb8777 100644
--- a/freebsd/sys/sys/nv.h
+++ b/freebsd/sys/sys/nv.h
@@ -162,6 +162,14 @@ void nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value);
void nvlist_add_descriptor_array(nvlist_t *nvl, const char *name, const int *value, size_t nitems);
#endif
+void nvlist_append_bool_array(nvlist_t *nvl, const char *name, const bool value);
+void nvlist_append_number_array(nvlist_t *nvl, const char *name, const uint64_t value);
+void nvlist_append_string_array(nvlist_t *nvl, const char *name, const char * const value);
+void nvlist_append_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t * const value);
+#ifndef _KERNEL
+void nvlist_append_descriptor_array(nvlist_t *nvl, const char *name, int value);
+#endif
+
/*
* The nvlist_move functions add the given name/value pair.
* The functions consumes provided buffer.
diff --git a/freebsd/sys/sys/pciio.h b/freebsd/sys/sys/pciio.h
index 80d2019b..50e9116d 100644
--- a/freebsd/sys/sys/pciio.h
+++ b/freebsd/sys/sys/pciio.h
@@ -138,11 +138,30 @@ struct pci_list_vpd_io {
struct pci_vpd_element *plvi_data;
};
+struct pci_bar_mmap {
+ void *pbm_map_base; /* (sometimes IN)/OUT mmaped base */
+ size_t pbm_map_length; /* mapped length of the BAR, multiple
+ of pages */
+ uint64_t pbm_bar_length; /* actual length of the BAR */
+ int pbm_bar_off; /* offset from the mapped base to the
+ start of BAR */
+ struct pcisel pbm_sel; /* device to operate on */
+ int pbm_reg; /* starting address of BAR */
+ int pbm_flags;
+ int pbm_memattr;
+};
+
+#define PCIIO_BAR_MMAP_FIXED 0x01
+#define PCIIO_BAR_MMAP_EXCL 0x02
+#define PCIIO_BAR_MMAP_RW 0x04
+#define PCIIO_BAR_MMAP_ACTIVATE 0x08
+
#define PCIOCGETCONF _IOWR('p', 5, struct pci_conf_io)
#define PCIOCREAD _IOWR('p', 2, struct pci_io)
#define PCIOCWRITE _IOWR('p', 3, struct pci_io)
#define PCIOCATTACHED _IOWR('p', 4, struct pci_io)
#define PCIOCGETBAR _IOWR('p', 6, struct pci_bar_io)
#define PCIOCLISTVPD _IOWR('p', 7, struct pci_list_vpd_io)
+#define PCIOCBARMMAP _IOWR('p', 8, struct pci_bar_mmap)
#endif /* !_SYS_PCIIO_H_ */
diff --git a/freebsd/sys/sys/pcpu.h b/freebsd/sys/sys/pcpu.h
index bfa7f34d..7aad9f2e 100644
--- a/freebsd/sys/sys/pcpu.h
+++ b/freebsd/sys/sys/pcpu.h
@@ -81,7 +81,31 @@ extern uintptr_t dpcpu_off[];
*/
#define DPCPU_NAME(n) pcpu_entry_##n
#define DPCPU_DECLARE(t, n) extern t DPCPU_NAME(n)
-#define DPCPU_DEFINE(t, n) t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used
+/* struct _hack is to stop this from being used with the static keyword. */
+#define DPCPU_DEFINE(t, n) \
+ struct _hack; t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used
+#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv))
+/*
+ * On some architectures the compiler will use PC-relative load to
+ * find the address of DPCPU data with the static keyword. We then
+ * use this to find the offset of the data in a per-CPU region.
+ * This works for in the kernel as we can allocate the space ahead
+ * of time, however modules need to allocate a sepatate space and
+ * then use relocations to fix the address of the data. As
+ * PC-relative data doesn't have a relocation there is nothing for
+ * the kernel module linker to fix so data is accessed from the
+ * wrong location.
+ *
+ * This is a workaround until a better solution can be found.
+ *
+ * VNET_DEFINE_STATIC also has the same workaround.
+ */
+#define DPCPU_DEFINE_STATIC(t, n) \
+ t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used
+#else
+#define DPCPU_DEFINE_STATIC(t, n) \
+ static t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used
+#endif
/*
* Accessors with a given base.
@@ -189,14 +213,6 @@ struct pcpu {
#endif /* __rtems__ */
} __aligned(CACHE_LINE_SIZE);
-#ifdef CTASSERT
-/*
- * To minimize memory waste in per-cpu UMA zones, size of struct pcpu
- * should be denominator of PAGE_SIZE.
- */
-CTASSERT((PAGE_SIZE / sizeof(struct pcpu)) * sizeof(struct pcpu) == PAGE_SIZE);
-#endif
-
#ifdef _KERNEL
STAILQ_HEAD(cpuhead, pcpu);
@@ -211,15 +227,34 @@ extern struct pcpu *cpuid_to_pcpu[];
#endif
#define curvidata PCPU_GET(vidata)
+#ifndef __rtems__
+#define UMA_PCPU_ALLOC_SIZE PAGE_SIZE
+
+#ifdef CTASSERT
+#if defined(__i386__) || defined(__amd64__)
+/* Required for counters(9) to work on x86. */
+CTASSERT(sizeof(struct pcpu) == UMA_PCPU_ALLOC_SIZE);
+#else
+/*
+ * To minimize memory waste in per-cpu UMA zones, size of struct pcpu
+ * should be denominator of PAGE_SIZE.
+ */
+CTASSERT((PAGE_SIZE / sizeof(struct pcpu)) * sizeof(struct pcpu) == PAGE_SIZE);
+#endif /* UMA_PCPU_ALLOC_SIZE && x86 */
+#endif /* CTASSERT */
+#else /* __rtems__ */
+#define UMA_PCPU_ALLOC_SIZE sizeof(struct pcpu)
+#endif /* __rtems__ */
+
/* Accessor to elements allocated via UMA_ZONE_PCPU zone. */
static inline void *
zpcpu_get(void *base)
{
#ifndef __rtems__
- return ((char *)(base) + sizeof(struct pcpu) * curcpu);
+ return ((char *)(base) + UMA_PCPU_ALLOC_SIZE * curcpu);
#else /* __rtems__ */
- return ((char *)(base) + sizeof(struct pcpu) * _SMP_Get_current_processor());
+ return ((char *)(base) + UMA_PCPU_ALLOC_SIZE * _SMP_Get_current_processor());
#endif /* __rtems__ */
}
@@ -227,7 +262,7 @@ static inline void *
zpcpu_get_cpu(void *base, int cpu)
{
- return ((char *)(base) + sizeof(struct pcpu) * cpu);
+ return ((char *)(base) + UMA_PCPU_ALLOC_SIZE * cpu);
}
/*
diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h
index 36ed69cc..9372b3a0 100644
--- a/freebsd/sys/sys/proc.h
+++ b/freebsd/sys/sys/proc.h
@@ -74,19 +74,6 @@
#include <machine/cpu.h>
#endif
-
-/*
- * A section object may be passed to every begin-end pair to allow for
- * forward progress guarantees with-in prolonged active sections.
- *
- * We can't include ck_epoch.h so we define our own variant here and
- * then CTASSERT that it's the same size in subr_epoch.c
- */
-struct epoch_section {
- unsigned int bucket;
-};
-typedef struct epoch_section epoch_section_t;
-
/*
* One structure allocated per session.
*
@@ -408,8 +395,7 @@ struct thread {
int td_lastcpu; /* (t) Last cpu we were on. */
int td_oncpu; /* (t) Which cpu we are on. */
void *td_lkpi_task; /* LinuxKPI task struct pointer */
- TAILQ_ENTRY(thread) td_epochq; /* (t) Epoch queue. */
- epoch_section_t td_epoch_section; /* (t) epoch section object */
+ int td_pmcpend;
#endif /* __rtems__ */
};
@@ -677,7 +663,7 @@ struct proc {
u_int p_stype; /* (c) Stop event type. */
char p_step; /* (c) Process is stopped. */
u_char p_pfsflags; /* (c) Procfs flags. */
- u_int p_ptevents; /* (c) ptrace() event mask. */
+ u_int p_ptevents; /* (c + e) ptrace() event mask. */
struct nlminfo *p_nlminfo; /* (?) Only used by/for lockd. */
struct kaioinfo *p_aioinfo; /* (y) ASYNC I/O info. */
struct thread *p_singlethread;/* (c + j) If single threading this is it */
@@ -729,8 +715,6 @@ struct proc {
LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/
struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */
struct cv p_pwait; /* (*) wait cv for exit/exec. */
- struct cv p_dbgwait; /* (*) wait cv for debugger attach
- after fork. */
uint64_t p_prev_runtime; /* (c) Resource usage accounting. */
struct racct *p_racct; /* (b) Resource accounting. */
int p_throttled; /* (c) Flag for racct pcpu throttling */
@@ -1127,6 +1111,7 @@ struct proc *proc_realparent(struct proc *child);
void proc_reap(struct thread *td, struct proc *p, int *status, int options);
void proc_reparent(struct proc *child, struct proc *newparent);
void proc_set_traced(struct proc *p, bool stop);
+void proc_wkilled(struct proc *p);
struct pstats *pstats_alloc(void);
void pstats_fork(struct pstats *src, struct pstats *dst);
void pstats_free(struct pstats *ps);
diff --git a/freebsd/sys/sys/random.h b/freebsd/sys/sys/random.h
index c717a686..f32d3f66 100644
--- a/freebsd/sys/sys/random.h
+++ b/freebsd/sys/sys/random.h
@@ -35,12 +35,6 @@
#ifdef _KERNEL
-#if !defined(KLD_MODULE)
-#if defined(RANDOM_LOADABLE) && defined(RANDOM_YARROW)
-#error "Cannot define both RANDOM_LOADABLE and RANDOM_YARROW"
-#endif
-#endif
-
struct uio;
#if defined(DEV_RANDOM)
@@ -105,6 +99,7 @@ enum random_entropy_source {
RANDOM_PURE_VIRTIO,
RANDOM_PURE_BROADCOM,
RANDOM_PURE_CCP,
+ RANDOM_PURE_DARN,
ENTROPYSOURCE
};
@@ -117,57 +112,54 @@ enum random_entropy_source {
#if defined(DEV_RANDOM)
extern u_int hc_source_mask;
-void random_harvest_queue_(const void *, u_int, u_int, enum random_entropy_source);
-void random_harvest_fast_(const void *, u_int, u_int);
-void random_harvest_direct_(const void *, u_int, u_int, enum random_entropy_source);
+void random_harvest_queue_(const void *, u_int, enum random_entropy_source);
+void random_harvest_fast_(const void *, u_int);
+void random_harvest_direct_(const void *, u_int, enum random_entropy_source);
static __inline void
-random_harvest_queue(const void *entropy, u_int size, u_int bits,
- enum random_entropy_source origin)
+random_harvest_queue(const void *entropy, u_int size, enum random_entropy_source origin)
{
if (hc_source_mask & (1 << origin))
- random_harvest_queue_(entropy, size, bits, origin);
+ random_harvest_queue_(entropy, size, origin);
}
static __inline void
-random_harvest_fast(const void *entropy, u_int size, u_int bits,
- enum random_entropy_source origin)
+random_harvest_fast(const void *entropy, u_int size, enum random_entropy_source origin)
{
if (hc_source_mask & (1 << origin))
- random_harvest_fast_(entropy, size, bits);
+ random_harvest_fast_(entropy, size);
}
static __inline void
-random_harvest_direct(const void *entropy, u_int size, u_int bits,
- enum random_entropy_source origin)
+random_harvest_direct(const void *entropy, u_int size, enum random_entropy_source origin)
{
if (hc_source_mask & (1 << origin))
- random_harvest_direct_(entropy, size, bits, origin);
+ random_harvest_direct_(entropy, size, origin);
}
void random_harvest_register_source(enum random_entropy_source);
void random_harvest_deregister_source(enum random_entropy_source);
#else
-#define random_harvest_queue(a, b, c, d) do {} while (0)
-#define random_harvest_fast(a, b, c, d) do {} while (0)
-#define random_harvest_direct(a, b, c, d) do {} while (0)
+#define random_harvest_queue(a, b, c) do {} while (0)
+#define random_harvest_fast(a, b, c) do {} while (0)
+#define random_harvest_direct(a, b, c) do {} while (0)
#define random_harvest_register_source(a) do {} while (0)
#define random_harvest_deregister_source(a) do {} while (0)
#endif
#if defined(RANDOM_ENABLE_UMA)
-#define random_harvest_fast_uma(a, b, c, d) random_harvest_fast(a, b, c, d)
+#define random_harvest_fast_uma(a, b, c) random_harvest_fast(a, b, c)
#else /* !defined(RANDOM_ENABLE_UMA) */
-#define random_harvest_fast_uma(a, b, c, d) do {} while (0)
+#define random_harvest_fast_uma(a, b, c) do {} while (0)
#endif /* defined(RANDOM_ENABLE_UMA) */
#if defined(RANDOM_ENABLE_ETHER)
-#define random_harvest_queue_ether(a, b, c) random_harvest_queue(a, b, c, RANDOM_NET_ETHER)
+#define random_harvest_queue_ether(a, b) random_harvest_queue(a, b, RANDOM_NET_ETHER)
#else /* !defined(RANDOM_ENABLE_ETHER) */
-#define random_harvest_queue_ether(a, b, c) do {} while (0)
+#define random_harvest_queue_ether(a, b) do {} while (0)
#endif /* defined(RANDOM_ENABLE_ETHER) */
diff --git a/freebsd/sys/sys/reboot.h b/freebsd/sys/sys/reboot.h
index d0dff609..20b91f8e 100644
--- a/freebsd/sys/sys/reboot.h
+++ b/freebsd/sys/sys/reboot.h
@@ -41,28 +41,29 @@
*/
#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */
-#define RB_ASKNAME 0x001 /* ask for file name to reboot from */
+#define RB_ASKNAME 0x001 /* force prompt of device of root filesystem */
#define RB_SINGLE 0x002 /* reboot to single user only */
#define RB_NOSYNC 0x004 /* dont sync before reboot */
#define RB_HALT 0x008 /* don't reboot, just halt */
-#define RB_INITNAME 0x010 /* name given for /etc/init (unused) */
+#define RB_INITNAME 0x010 /* Unused placeholder to specify init path */
#define RB_DFLTROOT 0x020 /* use compiled-in rootdev */
#define RB_KDB 0x040 /* give control to kernel debugger */
#define RB_RDONLY 0x080 /* mount root fs read-only */
#define RB_DUMP 0x100 /* dump kernel memory before reboot */
-#define RB_MINIROOT 0x200 /* mini-root present in memory at boot time */
+#define RB_MINIROOT 0x200 /* Unused placeholder */
#define RB_VERBOSE 0x800 /* print all potentially useful info */
#define RB_SERIAL 0x1000 /* use serial port as console */
#define RB_CDROM 0x2000 /* use cdrom as root */
#define RB_POWEROFF 0x4000 /* turn the power off if possible */
#define RB_GDB 0x8000 /* use GDB remote debugger instead of DDB */
#define RB_MUTE 0x10000 /* start up with the console muted */
-#define RB_SELFTEST 0x20000 /* don't complete the boot; do selftest */
+#define RB_SELFTEST 0x20000 /* unused placeholder */
#define RB_RESERVED1 0x40000 /* reserved for internal use of boot blocks */
#define RB_RESERVED2 0x80000 /* reserved for internal use of boot blocks */
#define RB_PAUSE 0x100000 /* pause after each output line during probe */
#define RB_REROOT 0x200000 /* unmount the rootfs and mount it again */
#define RB_POWERCYCLE 0x400000 /* Power cycle if possible */
+#define RB_PROBE 0x10000000 /* Probe multiple consoles */
#define RB_MULTIPLE 0x20000000 /* use multiple consoles */
#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
diff --git a/freebsd/sys/sys/sglist.h b/freebsd/sys/sys/sglist.h
new file mode 100644
index 00000000..5674416c
--- /dev/null
+++ b/freebsd/sys/sys/sglist.h
@@ -0,0 +1,113 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * A scatter/gather list describes a group of physical address ranges.
+ * Each physical address range consists of a starting address and a
+ * length.
+ */
+
+#ifndef __SGLIST_H__
+#define __SGLIST_H__
+
+#include <sys/refcount.h>
+
+struct sglist_seg {
+ vm_paddr_t ss_paddr;
+ size_t ss_len;
+};
+
+struct sglist {
+ struct sglist_seg *sg_segs;
+ u_int sg_refs;
+ u_short sg_nseg;
+ u_short sg_maxseg;
+};
+
+struct bio;
+struct mbuf;
+struct uio;
+
+static __inline void
+sglist_init(struct sglist *sg, u_short maxsegs, struct sglist_seg *segs)
+{
+
+ sg->sg_segs = segs;
+ sg->sg_nseg = 0;
+ sg->sg_maxseg = maxsegs;
+ refcount_init(&sg->sg_refs, 1);
+}
+
+static __inline void
+sglist_reset(struct sglist *sg)
+{
+
+ sg->sg_nseg = 0;
+}
+
+static __inline struct sglist *
+sglist_hold(struct sglist *sg)
+{
+
+ refcount_acquire(&sg->sg_refs);
+ return (sg);
+}
+
+struct sglist *sglist_alloc(int nsegs, int mflags);
+int sglist_append(struct sglist *sg, void *buf, size_t len);
+int sglist_append_bio(struct sglist *sg, struct bio *bp);
+int sglist_append_mbuf(struct sglist *sg, struct mbuf *m0);
+int sglist_append_phys(struct sglist *sg, vm_paddr_t paddr,
+ size_t len);
+int sglist_append_sglist(struct sglist *sg, struct sglist *source,
+ size_t offset, size_t length);
+int sglist_append_uio(struct sglist *sg, struct uio *uio);
+int sglist_append_user(struct sglist *sg, void *buf, size_t len,
+ struct thread *td);
+int sglist_append_vmpages(struct sglist *sg, vm_page_t *m, size_t pgoff,
+ size_t len);
+struct sglist *sglist_build(void *buf, size_t len, int mflags);
+struct sglist *sglist_clone(struct sglist *sg, int mflags);
+int sglist_consume_uio(struct sglist *sg, struct uio *uio, size_t resid);
+int sglist_count(void *buf, size_t len);
+int sglist_count_vmpages(vm_page_t *m, size_t pgoff, size_t len);
+void sglist_free(struct sglist *sg);
+int sglist_join(struct sglist *first, struct sglist *second);
+size_t sglist_length(struct sglist *sg);
+int sglist_slice(struct sglist *original, struct sglist **slice,
+ size_t offset, size_t length, int mflags);
+int sglist_split(struct sglist *original, struct sglist **head,
+ size_t length, int mflags);
+
+#endif /* !__SGLIST_H__ */
diff --git a/freebsd/sys/sys/sockbuf.h b/freebsd/sys/sys/sockbuf.h
index 91a30b6f..915fee0b 100644
--- a/freebsd/sys/sys/sockbuf.h
+++ b/freebsd/sys/sys/sockbuf.h
@@ -141,9 +141,9 @@ int sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa,
struct mbuf *m0, struct mbuf *control);
int sbappendaddr_nospacecheck_locked(struct sockbuf *sb,
const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control);
-int sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
+void sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control);
-int sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
+void sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control);
void sbappendrecord(struct sockbuf *sb, struct mbuf *m0);
void sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0);
@@ -168,6 +168,10 @@ int sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so,
struct mbuf *
sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff);
struct mbuf *
+ sbsndptr_noadv(struct sockbuf *sb, u_int off, u_int *moff);
+void
+ sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, u_int len);
+struct mbuf *
sbsndmbuf(struct sockbuf *sb, u_int off, u_int *moff);
int sbwait(struct sockbuf *sb);
int sblock(struct sockbuf *sb, int flags);
diff --git a/freebsd/sys/sys/socketvar.h b/freebsd/sys/sys/socketvar.h
index f877a0df..96ba4a01 100644
--- a/freebsd/sys/sys/socketvar.h
+++ b/freebsd/sys/sys/socketvar.h
@@ -63,6 +63,7 @@ struct vnet;
* private data and error information.
*/
typedef int so_upcall_t(struct socket *, void *, int);
+typedef void so_dtor_t(struct socket *);
struct socket;
@@ -84,7 +85,7 @@ struct socket {
struct selinfo so_rdsel; /* (b/cr) for so_rcv/so_comp */
struct selinfo so_wrsel; /* (b/cs) for so_snd */
short so_type; /* (a) generic type, see socket.h */
- short so_options; /* (b) from socket call, see socket.h */
+ int so_options; /* (b) from socket call, see socket.h */
short so_linger; /* time to linger close(2) */
short so_state; /* (b) internal state flags SS_* */
void *so_pcb; /* protocol control block */
@@ -99,6 +100,7 @@ struct socket {
/* NB: generation count must not be first. */
so_gen_t so_gencnt; /* (h) generation count */
void *so_emuldata; /* (b) private data for emulators */
+ so_dtor_t *so_dtor; /* (b) optional destructor */
struct osd osd; /* Object Specific extensions */
/*
* so_fibnum, so_user_cookie and friends can be used to attach
@@ -399,6 +401,7 @@ int soconnect2(struct socket *so1, struct socket *so2);
int socreate(int dom, struct socket **aso, int type, int proto,
struct ucred *cred, struct thread *td);
int sodisconnect(struct socket *so);
+void sodtor_set(struct socket *, so_dtor_t *);
struct sockaddr *sodupsockaddr(const struct sockaddr *sa, int mflags);
void sofree(struct socket *so);
void sohasoutofband(struct socket *so);
@@ -477,15 +480,9 @@ int accept_filt_generic_mod_event(module_t mod, int event, void *data);
* Structure to export socket from kernel to utilities, via sysctl(3).
*/
struct xsocket {
- size_t xso_len; /* length of this structure */
- union {
- void *xso_so; /* kernel address of struct socket */
- int64_t ph_so;
- };
- union {
- void *so_pcb; /* kernel address of struct inpcb */
- int64_t ph_pcb;
- };
+ ksize_t xso_len; /* length of this structure */
+ kvaddr_t xso_so; /* kernel address of struct socket */
+ kvaddr_t so_pcb; /* kernel address of struct inpcb */
uint64_t so_oobmark;
int64_t so_spare64[8];
int32_t xso_protocol;
diff --git a/freebsd/sys/sys/sockopt.h b/freebsd/sys/sys/sockopt.h
index 7f19ecf8..e7cc6cf0 100644
--- a/freebsd/sys/sys/sockopt.h
+++ b/freebsd/sys/sys/sockopt.h
@@ -62,7 +62,6 @@ int sosetopt(struct socket *so, struct sockopt *sopt);
int sogetopt(struct socket *so, struct sockopt *sopt);
int sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen);
int sooptcopyout(struct sockopt *sopt, const void *buf, size_t len);
-/* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */
int soopt_getm(struct sockopt *sopt, struct mbuf **mp);
int soopt_mcopyin(struct sockopt *sopt, struct mbuf *m);
int soopt_mcopyout(struct sockopt *sopt, struct mbuf *m);
diff --git a/freebsd/sys/sys/sx.h b/freebsd/sys/sys/sx.h
index 566137bd..10cfb10a 100644
--- a/freebsd/sys/sys/sx.h
+++ b/freebsd/sys/sys/sx.h
@@ -76,8 +76,8 @@
#define SX_LOCK_SHARED 0x01
#define SX_LOCK_SHARED_WAITERS 0x02
#define SX_LOCK_EXCLUSIVE_WAITERS 0x04
-#define SX_LOCK_RECURSED 0x08
-#define SX_LOCK_WRITE_SPINNER 0x10
+#define SX_LOCK_WRITE_SPINNER 0x08
+#define SX_LOCK_RECURSED 0x10
#define SX_LOCK_FLAGMASK \
(SX_LOCK_SHARED | SX_LOCK_SHARED_WAITERS | \
SX_LOCK_EXCLUSIVE_WAITERS | SX_LOCK_RECURSED | SX_LOCK_WRITE_SPINNER)
diff --git a/freebsd/sys/sys/sysproto.h b/freebsd/sys/sys/sysproto.h
index b328cb51..89467f3b 100644
--- a/freebsd/sys/sys/sysproto.h
+++ b/freebsd/sys/sys/sysproto.h
@@ -90,7 +90,7 @@ struct chown_args {
char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)];
char gid_l_[PADL_(int)]; int gid; char gid_r_[PADR_(int)];
};
-struct obreak_args {
+struct break_args {
char nsize_l_[PADL_(char *)]; char * nsize; char nsize_r_[PADR_(char *)];
};
struct getpid_args {
@@ -1831,7 +1831,7 @@ int sys_chdir(struct thread *, struct chdir_args *);
int sys_fchdir(struct thread *, struct fchdir_args *);
int sys_chmod(struct thread *, struct chmod_args *);
int sys_chown(struct thread *, struct chown_args *);
-int sys_obreak(struct thread *, struct obreak_args *);
+int sys_break(struct thread *, struct break_args *);
int sys_getpid(struct thread *, struct getpid_args *);
int sys_mount(struct thread *, struct mount_args *);
int sys_unmount(struct thread *, struct unmount_args *);
diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h
index 9c21f589..4145be2c 100644
--- a/freebsd/sys/sys/systm.h
+++ b/freebsd/sys/sys/systm.h
@@ -48,6 +48,7 @@
#include <sys/stdint.h> /* for people using printf mainly */
#ifdef __rtems__
#include <string.h>
+#include <rtems/score/threaddispatch.h>
#endif /* __rtems__ */
__NULLABILITY_PRAGMA_PUSH
@@ -106,12 +107,21 @@ extern int vm_guest; /* Running as virtual machine guest? */
enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN, VM_GUEST_HV,
VM_GUEST_VMWARE, VM_GUEST_KVM, VM_GUEST_BHYVE, VM_LAST };
+/*
+ * These functions need to be declared before the KASSERT macro is invoked in
+ * !KASSERT_PANIC_OPTIONAL builds, so their declarations are sort of out of
+ * place compared to other function definitions in this header. On the other
+ * hand, this header is a bit disorganized anyway.
+ */
+void panic(const char *, ...) __dead2 __printflike(1, 2);
+void vpanic(const char *, __va_list) __dead2 __printflike(1, 0);
+
#if defined(WITNESS) || defined(INVARIANT_SUPPORT)
-#ifndef __rtems__
+#ifdef KASSERT_PANIC_OPTIONAL
void kassert_panic(const char *fmt, ...) __printflike(1, 2);
-#else /* __rtems__ */
-#define kassert_panic panic
-#endif /* __rtems__ */
+#else
+#define kassert_panic panic
+#endif
#endif
#ifdef INVARIANTS /* The option is always available */
@@ -137,6 +147,12 @@ void kassert_panic(const char *fmt, ...) __printflike(1, 2);
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
#endif
+#if defined(_KERNEL)
+#include <sys/param.h> /* MAXCPU */
+#include <sys/pcpu.h> /* curthread */
+#include <sys/kpilite.h>
+#endif
+
/*
* Assert that a pointer can be loaded from memory atomically.
*
@@ -184,11 +200,10 @@ void kassert_panic(const char *fmt, ...) __printflike(1, 2);
* XXX most of these variables should be const.
*/
extern int osreldate;
-extern int envmode;
-extern int hintmode; /* 0 = off. 1 = config, 2 = fallback */
-extern int dynamic_kenv;
+extern bool dynamic_kenv;
extern struct mtx kenv_lock;
extern char *kern_envp;
+extern char *md_envp;
extern char static_env[];
extern char static_hints[]; /* by config for now */
@@ -244,34 +259,57 @@ void *phashinit_flags(int count, struct malloc_type *type, u_long *nentries,
int flags);
void g_waitidle(void);
-void panic(const char *, ...) __dead2 __printflike(1, 2);
-void vpanic(const char *, __va_list) __dead2 __printflike(1, 0);
-
void cpu_boot(int);
void cpu_flush_dcache(void *, size_t);
void cpu_rootconf(void);
-#ifndef __rtems__
-void critical_enter(void);
-void critical_exit(void);
-#else /* __rtems__ */
-#include <rtems/score/threaddispatch.h>
+void critical_enter_KBI(void);
+void critical_exit_KBI(void);
+void critical_exit_preempt(void);
+void init_param1(void);
+void init_param2(long physpages);
+void init_static_kenv(char *, size_t);
+void tablefull(const char *);
+#if defined(KLD_MODULE) || defined(KTR_CRITICAL) || !defined(_KERNEL) || defined(GENOFFSET)
+#define critical_enter() critical_enter_KBI()
+#define critical_exit() critical_exit_KBI()
+#else
static __inline void
critical_enter(void)
{
+#ifndef __rtems__
+ struct thread_lite *td;
+
+ td = (struct thread_lite *)curthread;
+ td->td_critnest++;
+ __compiler_membar();
+#else /* __rtems__ */
_Thread_Dispatch_disable();
+#endif /* __rtems__ */
}
static __inline void
critical_exit(void)
{
+#ifndef __rtems__
+ struct thread_lite *td;
+
+ td = (struct thread_lite *)curthread;
+ KASSERT(td->td_critnest != 0,
+ ("critical_exit: td_critnest == 0"));
+ __compiler_membar();
+ td->td_critnest--;
+ __compiler_membar();
+ if (__predict_false(td->td_owepreempt))
+ critical_exit_preempt();
+#else /* __rtems__ */
_Thread_Dispatch_enable(_Per_CPU_Get());
-}
#endif /* __rtems__ */
-void init_param1(void);
-void init_param2(long physpages);
-void init_static_kenv(char *, size_t);
-void tablefull(const char *);
+
+}
+#endif
+
+
#ifdef EARLY_PRINTF
typedef void early_putc_t(int ch);
extern early_putc_t *early_putc;
@@ -329,30 +367,22 @@ void hexdump(const void *ptr, int length, const char *hdr, int flags);
#define HD_OMIT_CHARS (1 << 18)
#define ovbcopy(f, t, l) bcopy((f), (t), (l))
-#ifndef __rtems__
void bcopy(const void * _Nonnull from, void * _Nonnull to, size_t len);
-#define bcopy(from, to, len) ({ \
- if (__builtin_constant_p(len) && (len) <= 64) \
- __builtin_memmove((to), (from), (len)); \
- else \
- bcopy((from), (to), (len)); \
-})
+#define bcopy(from, to, len) __builtin_memmove((to), (from), (len))
void bzero(void * _Nonnull buf, size_t len);
-#define bzero(buf, len) ({ \
- if (__builtin_constant_p(len) && (len) <= 64) \
- __builtin_memset((buf), 0, (len)); \
- else \
- bzero((buf), (len)); \
-})
-#else /* __rtems__ */
-#define bcopy(src, dst, len) memmove((dst), (src), (len))
-#define bzero(buf, size) memset((buf), 0, (size))
-#endif /* __rtems__ */
+#define bzero(buf, len) __builtin_memset((buf), 0, (len))
void explicit_bzero(void * _Nonnull, size_t);
+int bcmp(const void *b1, const void *b2, size_t len);
+#define bcmp(b1, b2, len) __builtin_memcmp((b1), (b2), (len))
+void *memset(void * _Nonnull buf, int c, size_t len);
+#define memset(buf, c, len) __builtin_memset((buf), (c), (len))
void *memcpy(void * _Nonnull to, const void * _Nonnull from, size_t len);
-#define memcpy(to, from, len) __builtin_memcpy(to, from, len)
+#define memcpy(to, from, len) __builtin_memcpy((to), (from), (len))
void *memmove(void * _Nonnull dest, const void * _Nonnull src, size_t n);
+#define memmove(dest, src, n) __builtin_memmove((dest), (src), (n))
+int memcmp(const void *b1, const void *b2, size_t len);
+#define memcmp(b1, b2, len) __builtin_memcmp((b1), (b2), (len))
#ifndef __rtems__
int copystr(const void * _Nonnull __restrict kfaddr,
@@ -451,17 +481,13 @@ void realitexpire(void *);
int sysbeep(int hertz, int period);
-void hardclock(int usermode, uintfptr_t pc);
-void hardclock_cnt(int cnt, int usermode);
-void hardclock_cpu(int usermode);
+void hardclock(int cnt, int usermode);
void hardclock_sync(int cpu);
#ifndef __rtems__
void softclock(void *);
+void statclock(int cnt, int usermode);
+void profclock(int cnt, int usermode, uintfptr_t pc);
#endif /* __rtems__ */
-void statclock(int usermode);
-void statclock_cnt(int cnt, int usermode);
-void profclock(int usermode, uintfptr_t pc);
-void profclock_cnt(int cnt, int usermode, uintfptr_t pc);
int hardclockintr(void);
@@ -492,6 +518,11 @@ int kern_setenv(const char *name, const char *value);
int kern_unsetenv(const char *name);
int testenv(const char *name);
+int getenv_array(const char *name, void *data, int size, int *psize,
+ int type_size, bool allow_signed);
+#define GETENV_UNSIGNED false /* negative numbers not allowed */
+#define GETENV_SIGNED true /* negative numbers allowed */
+
typedef uint64_t (cpu_tick_f)(void);
void set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var);
extern cpu_tick_f *cpu_ticks;
diff --git a/freebsd/sys/sys/unpcb.h b/freebsd/sys/sys/unpcb.h
index d80b1384..7d7a20ac 100644
--- a/freebsd/sys/sys/unpcb.h
+++ b/freebsd/sys/sys/unpcb.h
@@ -142,12 +142,12 @@ struct unpcb {
*/
#ifdef _SYS_SOCKETVAR_H_
struct xunpcb {
- size_t xu_len; /* length of this structure */
- void *xu_unpp; /* to help netstat, fstat */
- void *unp_vnode; /* (s) */
- void *unp_conn; /* (s) */
- void *xu_firstref; /* (s) */
- void *xu_nextref; /* (s) */
+ ksize_t xu_len; /* length of this structure */
+ kvaddr_t xu_unpp; /* to help netstat, fstat */
+ kvaddr_t unp_vnode; /* (s) */
+ kvaddr_t unp_conn; /* (s) */
+ kvaddr_t xu_firstref; /* (s) */
+ kvaddr_t xu_nextref; /* (s) */
unp_gen_t unp_gencnt; /* (s) */
int64_t xu_spare64[8];
int32_t xu_spare32[8];
@@ -163,11 +163,20 @@ struct xunpcb {
} __aligned(8);
struct xunpgen {
- size_t xug_len;
+ ksize_t xug_len;
u_int xug_count;
unp_gen_t xug_gen;
so_gen_t xug_sogen;
} __aligned(8);;
#endif /* _SYS_SOCKETVAR_H_ */
+#if defined(_KERNEL)
+struct thread;
+
+/* In uipc_userreq.c */
+void
+unp_copy_peercred(struct thread *td, struct unpcb *client_unp,
+ struct unpcb *server_unp, struct unpcb *listen_unp);
+#endif
+
#endif /* _SYS_UNPCB_H_ */
diff --git a/freebsd/sys/sys/vmmeter.h b/freebsd/sys/sys/vmmeter.h
index 3c570b0a..c41b151f 100644
--- a/freebsd/sys/sys/vmmeter.h
+++ b/freebsd/sys/sys/vmmeter.h
@@ -187,6 +187,13 @@ vm_page_count_severe(void)
return (!DOMAINSET_EMPTY(&vm_severe_domains));
}
+static inline int
+vm_page_count_severe_set(domainset_t *mask)
+{
+
+ return (DOMAINSET_SUBSET(&vm_severe_domains, mask));
+}
+
/*
* Return TRUE if we are under our minimum low-free-pages threshold.
*
diff --git a/freebsd/sys/vm/uma.h b/freebsd/sys/vm/uma.h
index d71f0ee3..3ab65563 100644
--- a/freebsd/sys/vm/uma.h
+++ b/freebsd/sys/vm/uma.h
@@ -279,8 +279,7 @@ uma_zone_t uma_zcache_create(char *name, int size, uma_ctor ctor, uma_dtor dtor,
* mini-dumps.
*/
#define UMA_ZONE_PCPU 0x8000 /*
- * Allocates mp_maxid + 1 slabs sized to
- * sizeof(struct pcpu).
+ * Allocates mp_maxid + 1 slabs of PAGE_SIZE
*/
#define UMA_ZONE_NUMA 0x10000 /*
* NUMA aware Zone. Implements a best
@@ -333,6 +332,7 @@ void uma_zdestroy(uma_zone_t zone);
*/
void *uma_zalloc_arg(uma_zone_t zone, void *arg, int flags);
+void *uma_zalloc_pcpu_arg(uma_zone_t zone, void *arg, int flags);
/*
* Allocate an item from a specific NUMA domain. This uses a slow path in
@@ -354,6 +354,7 @@ void *uma_zalloc_domain(uma_zone_t zone, void *arg, int domain, int flags);
*
*/
static __inline void *uma_zalloc(uma_zone_t zone, int flags);
+static __inline void *uma_zalloc_pcpu(uma_zone_t zone, int flags);
static __inline void *
uma_zalloc(uma_zone_t zone, int flags)
@@ -361,6 +362,12 @@ uma_zalloc(uma_zone_t zone, int flags)
return uma_zalloc_arg(zone, NULL, flags);
}
+static __inline void *
+uma_zalloc_pcpu(uma_zone_t zone, int flags)
+{
+ return uma_zalloc_pcpu_arg(zone, NULL, flags);
+}
+
/*
* Frees an item back into the specified zone.
*
@@ -374,6 +381,7 @@ uma_zalloc(uma_zone_t zone, int flags)
*/
void uma_zfree_arg(uma_zone_t zone, void *item, void *arg);
+void uma_zfree_pcpu_arg(uma_zone_t zone, void *item, void *arg);
/*
* Frees an item back to the specified zone's domain specific pool.
@@ -392,6 +400,7 @@ void uma_zfree_domain(uma_zone_t zone, void *item, void *arg);
*
*/
static __inline void uma_zfree(uma_zone_t zone, void *item);
+static __inline void uma_zfree_pcpu(uma_zone_t zone, void *item);
static __inline void
uma_zfree(uma_zone_t zone, void *item)
@@ -399,6 +408,12 @@ uma_zfree(uma_zone_t zone, void *item)
uma_zfree_arg(zone, item, NULL);
}
+static __inline void
+uma_zfree_pcpu(uma_zone_t zone, void *item)
+{
+ uma_zfree_pcpu_arg(zone, item, NULL);
+}
+
/*
* Wait until the specified zone can allocate an item.
*/
@@ -603,12 +618,12 @@ void uma_zone_set_freef(uma_zone_t zone, uma_free freef);
#ifndef __rtems__
#define UMA_SLAB_BOOT 0x01 /* Slab alloced from boot pages */
#endif /* __rtems__ */
-#define UMA_SLAB_KERNEL 0x04 /* Slab alloced from kernel_map */
+#define UMA_SLAB_KERNEL 0x04 /* Slab alloced from kmem */
#ifndef __rtems__
#define UMA_SLAB_PRIV 0x08 /* Slab alloced from priv allocator */
#define UMA_SLAB_OFFP 0x10 /* Slab is managed separately */
#define UMA_SLAB_MALLOC 0x20 /* Slab is a large malloc slab */
-/* 0x02, 0x40 and 0x80 are available */
+/* 0x02, 0x40, and 0x80 are available */
#endif /* __rtems__ */
/*
diff --git a/freebsd/sys/vm/uma_core.c b/freebsd/sys/vm/uma_core.c
index b8145c72..0f4bbb35 100644
--- a/freebsd/sys/vm/uma_core.c
+++ b/freebsd/sys/vm/uma_core.c
@@ -276,9 +276,13 @@ static void *noobj_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int);
#endif /* __rtems__ */
static void *page_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int);
#ifndef __rtems__
+static void *pcpu_page_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int);
static void *startup_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int);
#endif /* __rtems__ */
static void page_free(void *, vm_size_t, uint8_t);
+#ifndef __rtems__
+static void pcpu_page_free(void *, vm_size_t, uint8_t);
+#endif /* __rtems__ */
static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int, int);
static void cache_drain(uma_zone_t);
static void bucket_drain(uma_zone_t, uma_bucket_t);
@@ -323,8 +327,25 @@ static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS);
static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS);
#ifdef INVARIANTS
+static bool uma_dbg_kskip(uma_keg_t keg, void *mem);
+static bool uma_dbg_zskip(uma_zone_t zone, void *mem);
static void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item);
static void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item);
+
+static SYSCTL_NODE(_vm, OID_AUTO, debug, CTLFLAG_RD, 0,
+ "Memory allocation debugging");
+
+static u_int dbg_divisor = 1;
+SYSCTL_UINT(_vm_debug, OID_AUTO, divisor,
+ CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &dbg_divisor, 0,
+ "Debug & thrash every this item in memory allocator");
+
+static counter_u64_t uma_dbg_cnt = EARLY_COUNTER;
+static counter_u64_t uma_skip_cnt = EARLY_COUNTER;
+SYSCTL_COUNTER_U64(_vm_debug, OID_AUTO, trashed, CTLFLAG_RD,
+ &uma_dbg_cnt, "memory items debugged");
+SYSCTL_COUNTER_U64(_vm_debug, OID_AUTO, skipped, CTLFLAG_RD,
+ &uma_skip_cnt, "memory items skipped, not debugged");
#endif
SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL);
@@ -910,6 +931,18 @@ keg_free_slab(uma_keg_t keg, uma_slab_t slab, int start)
i = start;
if (keg->uk_fini != NULL) {
for (i--; i > -1; i--)
+#ifdef INVARIANTS
+ /*
+ * trash_fini implies that dtor was trash_dtor. trash_fini
+ * would check that memory hasn't been modified since free,
+ * which executed trash_dtor.
+ * That's why we need to run uma_dbg_kskip() check here,
+ * albeit we don't make skip check for other init/fini
+ * invocations.
+ */
+ if (!uma_dbg_kskip(keg, slab->us_data + (keg->uk_rsize * i)) ||
+ keg->uk_fini != trash_fini)
+#endif
keg->uk_fini(slab->us_data + (keg->uk_rsize * i),
keg->uk_size);
}
@@ -1209,6 +1242,57 @@ page_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag,
}
#ifndef __rtems__
+static void *
+pcpu_page_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag,
+ int wait)
+{
+ struct pglist alloctail;
+ vm_offset_t addr, zkva;
+ int cpu, flags;
+ vm_page_t p, p_next;
+#ifdef NUMA
+ struct pcpu *pc;
+#endif
+
+ MPASS(bytes == (mp_maxid + 1) * PAGE_SIZE);
+
+ TAILQ_INIT(&alloctail);
+ flags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ |
+ malloc2vm_flags(wait);
+ *pflag = UMA_SLAB_KERNEL;
+ for (cpu = 0; cpu <= mp_maxid; cpu++) {
+ if (CPU_ABSENT(cpu)) {
+ p = vm_page_alloc(NULL, 0, flags);
+ } else {
+#ifndef NUMA
+ p = vm_page_alloc(NULL, 0, flags);
+#else
+ pc = pcpu_find(cpu);
+ p = vm_page_alloc_domain(NULL, 0, pc->pc_domain, flags);
+ if (__predict_false(p == NULL))
+ p = vm_page_alloc(NULL, 0, flags);
+#endif
+ }
+ if (__predict_false(p == NULL))
+ goto fail;
+ TAILQ_INSERT_TAIL(&alloctail, p, listq);
+ }
+ if ((addr = kva_alloc(bytes)) == 0)
+ goto fail;
+ zkva = addr;
+ TAILQ_FOREACH(p, &alloctail, listq) {
+ pmap_qenter(zkva, &p, 1);
+ zkva += PAGE_SIZE;
+ }
+ return ((void*)addr);
+ fail:
+ TAILQ_FOREACH_SAFE(p, &alloctail, listq, p_next) {
+ vm_page_unwire(p, PQ_NONE);
+ vm_page_free(p);
+ }
+ return (NULL);
+}
+
/*
* Allocates a number of pages from within an object
*
@@ -1286,14 +1370,11 @@ static void
page_free(void *mem, vm_size_t size, uint8_t flags)
{
#ifndef __rtems__
- struct vmem *vmem;
- if (flags & UMA_SLAB_KERNEL)
- vmem = kernel_arena;
- else
+ if ((flags & UMA_SLAB_KERNEL) == 0)
panic("UMA: page_free used with invalid flags %x", flags);
- kmem_free(vmem, (vm_offset_t)mem, size);
+ kmem_free((vm_offset_t)mem, size);
#else /* __rtems__ */
if (flags & UMA_SLAB_KERNEL)
free(mem, M_TEMP);
@@ -1302,6 +1383,39 @@ page_free(void *mem, vm_size_t size, uint8_t flags)
#endif /* __rtems__ */
}
+#ifndef __rtems__
+/*
+ * Frees pcpu zone allocations
+ *
+ * Arguments:
+ * mem A pointer to the memory to be freed
+ * size The size of the memory being freed
+ * flags The original p->us_flags field
+ *
+ * Returns:
+ * Nothing
+ */
+static void
+pcpu_page_free(void *mem, vm_size_t size, uint8_t flags)
+{
+ vm_offset_t sva, curva;
+ vm_paddr_t paddr;
+ vm_page_t m;
+
+ MPASS(size == (mp_maxid+1)*PAGE_SIZE);
+ sva = (vm_offset_t)mem;
+ for (curva = sva; curva < sva + size; curva += PAGE_SIZE) {
+ paddr = pmap_kextract(curva);
+ m = PHYS_TO_VM_PAGE(paddr);
+ vm_page_unwire(m, PQ_NONE);
+ vm_page_free(m);
+ }
+ pmap_qremove(sva, size >> PAGE_SHIFT);
+ kva_free(sva, size);
+}
+#endif /* __rtems__ */
+
+
/*
* Zero fill initializer
*
@@ -1335,9 +1449,8 @@ keg_small_init(uma_keg_t keg)
if (keg->uk_flags & UMA_ZONE_PCPU) {
u_int ncpus = (mp_maxid + 1) ? (mp_maxid + 1) : MAXCPU;
- slabsize = sizeof(struct pcpu);
- keg->uk_ppera = howmany(ncpus * sizeof(struct pcpu),
- PAGE_SIZE);
+ slabsize = UMA_PCPU_ALLOC_SIZE;
+ keg->uk_ppera = ncpus;
} else {
slabsize = UMA_SLAB_SIZE;
keg->uk_ppera = 1;
@@ -1356,7 +1469,7 @@ keg_small_init(uma_keg_t keg)
keg->uk_rsize = rsize;
KASSERT((keg->uk_flags & UMA_ZONE_PCPU) == 0 ||
- keg->uk_rsize < sizeof(struct pcpu),
+ keg->uk_rsize < UMA_PCPU_ALLOC_SIZE,
("%s: size %u too large", __func__, keg->uk_rsize));
if (keg->uk_flags & UMA_ZONE_OFFPAGE)
@@ -1575,6 +1688,8 @@ keg_ctor(void *mem, int size, void *udata, int flags)
else if (keg->uk_ppera == 1)
keg->uk_allocf = uma_small_alloc;
#endif
+ else if (keg->uk_flags & UMA_ZONE_PCPU)
+ keg->uk_allocf = pcpu_page_alloc;
else
#endif /* __rtems__ */
keg->uk_allocf = page_alloc;
@@ -1584,6 +1699,9 @@ keg_ctor(void *mem, int size, void *udata, int flags)
keg->uk_freef = uma_small_free;
else
#endif
+ if (keg->uk_flags & UMA_ZONE_PCPU)
+ keg->uk_freef = pcpu_page_free;
+ else
#endif /* __rtems__ */
keg->uk_freef = page_free;
@@ -2066,11 +2184,16 @@ static void
uma_startup3(void)
{
+#ifdef INVARIANTS
+ TUNABLE_INT_FETCH("vm.debug.divisor", &dbg_divisor);
+ uma_dbg_cnt = counter_u64_alloc(M_WAITOK);
+ uma_skip_cnt = counter_u64_alloc(M_WAITOK);
+#endif
+ callout_init(&uma_callout, 1);
+ callout_reset(&uma_callout, UMA_TIMEOUT * hz, uma_timeout, NULL);
#ifndef __rtems__
booted = BOOT_RUNNING;
#endif /* __rtems__ */
- callout_init(&uma_callout, 1);
- callout_reset(&uma_callout, UMA_TIMEOUT * hz, uma_timeout, NULL);
}
static uma_keg_t
@@ -2324,6 +2447,40 @@ uma_zwait(uma_zone_t zone)
uma_zfree(zone, item);
}
+void *
+uma_zalloc_pcpu_arg(uma_zone_t zone, void *udata, int flags)
+{
+ void *item;
+#ifdef SMP
+ int i;
+
+ MPASS(zone->uz_flags & UMA_ZONE_PCPU);
+#endif
+ item = uma_zalloc_arg(zone, udata, flags & ~M_ZERO);
+ if (item != NULL && (flags & M_ZERO)) {
+#ifdef SMP
+ for (i = 0; i <= mp_maxid; i++)
+ bzero(zpcpu_get_cpu(item, i), zone->uz_size);
+#else
+ bzero(item, zone->uz_size);
+#endif
+ }
+ return (item);
+}
+
+/*
+ * A stub while both regular and pcpu cases are identical.
+ */
+void
+uma_zfree_pcpu_arg(uma_zone_t zone, void *item, void *udata)
+{
+
+#ifdef SMP
+ MPASS(zone->uz_flags & UMA_ZONE_PCPU);
+#endif
+ uma_zfree_arg(zone, item, udata);
+}
+
/* See uma.h */
void *
uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
@@ -2333,9 +2490,12 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
uma_cache_t cache;
void *item;
int cpu, domain, lockfail;
+#ifdef INVARIANTS
+ bool skipdbg;
+#endif
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
- random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
+ random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
/* This is the fast path allocation */
CTR4(KTR_UMA, "uma_zalloc_arg thread %x zone %s(%p) flags %d",
@@ -2346,8 +2506,12 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
"uma_zalloc_arg: zone \"%s\"", zone->uz_name);
}
#ifndef __rtems__
+ KASSERT((flags & M_EXEC) == 0, ("uma_zalloc_arg: called with M_EXEC"));
KASSERT(curthread->td_critnest == 0 || SCHEDULER_STOPPED(),
("uma_zalloc_arg: called with spinlock or critical section held"));
+ if (zone->uz_flags & UMA_ZONE_PCPU)
+ KASSERT((flags & M_ZERO) == 0, ("allocating from a pcpu zone "
+ "with M_ZERO passed"));
#endif /* __rtems__ */
#ifdef DEBUG_MEMGUARD
@@ -2394,14 +2558,22 @@ zalloc_start:
KASSERT(item != NULL, ("uma_zalloc: Bucket pointer mangled."));
cache->uc_allocs++;
critical_exit();
+#ifdef INVARIANTS
+ skipdbg = uma_dbg_zskip(zone, item);
+#endif
if (zone->uz_ctor != NULL &&
+#ifdef INVARIANTS
+ (!skipdbg || zone->uz_ctor != trash_ctor ||
+ zone->uz_dtor != trash_dtor) &&
+#endif
zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) {
atomic_add_long(&zone->uz_fails, 1);
zone_free_item(zone, item, udata, SKIP_DTOR);
return (NULL);
}
#ifdef INVARIANTS
- uma_dbg_alloc(zone, NULL, item);
+ if (!skipdbg)
+ uma_dbg_alloc(zone, NULL, item);
#endif
if (flags & M_ZERO)
uma_zero_item(item, zone);
@@ -2534,7 +2706,7 @@ uma_zalloc_domain(uma_zone_t zone, void *udata, int domain, int flags)
{
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
- random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
+ random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
/* This is the fast path allocation */
CTR5(KTR_UMA,
@@ -2820,9 +2992,9 @@ zone_import(uma_zone_t zone, void **bucket, int max, int domain, int flags)
{
uma_slab_t slab;
uma_keg_t keg;
-#ifndef __rtems__
+#ifdef NUMA
int stripe;
-#endif /* __rtems__ */
+#endif
int i;
slab = NULL;
@@ -2832,9 +3004,9 @@ zone_import(uma_zone_t zone, void **bucket, int max, int domain, int flags)
if ((slab = zone->uz_slab(zone, keg, domain, flags)) == NULL)
break;
keg = slab->us_keg;
-#ifndef __rtems__
+#ifdef NUMA
stripe = howmany(max, vm_ndomains);
-#endif /* __rtems__ */
+#endif
while (slab->us_freecount && i < max) {
bucket[i++] = slab_alloc_item(keg, slab);
if (keg->uk_free <= keg->uk_reserve)
@@ -2930,6 +3102,9 @@ static void *
zone_alloc_item(uma_zone_t zone, void *udata, int domain, int flags)
{
void *item;
+#ifdef INVARIANTS
+ bool skipdbg;
+#endif
item = NULL;
@@ -2937,6 +3112,9 @@ zone_alloc_item(uma_zone_t zone, void *udata, int domain, int flags)
goto fail;
atomic_add_long(&zone->uz_allocs, 1);
+#ifdef INVARIANTS
+ skipdbg = uma_dbg_zskip(zone, item);
+#endif
/*
* We have to call both the zone's init (not the keg's init)
* and the zone's ctor. This is because the item is going from
@@ -2949,14 +3127,18 @@ zone_alloc_item(uma_zone_t zone, void *udata, int domain, int flags)
goto fail;
}
}
- if (zone->uz_ctor != NULL) {
- if (zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) {
- zone_free_item(zone, item, udata, SKIP_DTOR);
- goto fail;
- }
+ if (zone->uz_ctor != NULL &&
+#ifdef INVARIANTS
+ (!skipdbg || zone->uz_ctor != trash_ctor ||
+ zone->uz_dtor != trash_dtor) &&
+#endif
+ zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) {
+ zone_free_item(zone, item, udata, SKIP_DTOR);
+ goto fail;
}
#ifdef INVARIANTS
- uma_dbg_alloc(zone, NULL, item);
+ if (!skipdbg)
+ uma_dbg_alloc(zone, NULL, item);
#endif
if (flags & M_ZERO)
uma_zero_item(item, zone);
@@ -2981,9 +3163,12 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
uma_bucket_t bucket;
uma_zone_domain_t zdom;
int cpu, domain, lockfail;
+#ifdef INVARIANTS
+ bool skipdbg;
+#endif
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
- random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
+ random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
CTR2(KTR_UMA, "uma_zfree_arg thread %x zone %s", curthread,
zone->uz_name);
@@ -3007,12 +3192,18 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
}
#endif
#ifdef INVARIANTS
- if (zone->uz_flags & UMA_ZONE_MALLOC)
- uma_dbg_free(zone, udata, item);
- else
- uma_dbg_free(zone, NULL, item);
-#endif
+ skipdbg = uma_dbg_zskip(zone, item);
+ if (skipdbg == false) {
+ if (zone->uz_flags & UMA_ZONE_MALLOC)
+ uma_dbg_free(zone, udata, item);
+ else
+ uma_dbg_free(zone, NULL, item);
+ }
+ if (zone->uz_dtor != NULL && (!skipdbg ||
+ zone->uz_dtor != trash_dtor || zone->uz_ctor != trash_ctor))
+#else
if (zone->uz_dtor != NULL)
+#endif
zone->uz_dtor(item, zone->uz_size, udata);
/*
@@ -3079,14 +3270,6 @@ zfree_start:
cpu = curcpu;
cache = &zone->uz_cpu[cpu];
- /*
- * Since we have locked the zone we may as well send back our stats.
- */
- atomic_add_long(&zone->uz_allocs, cache->uc_allocs);
- atomic_add_long(&zone->uz_frees, cache->uc_frees);
- cache->uc_allocs = 0;
- cache->uc_frees = 0;
-
bucket = cache->uc_freebucket;
if (bucket != NULL && bucket->ub_cnt < bucket->ub_entries) {
ZONE_UNLOCK(zone);
@@ -3163,7 +3346,7 @@ uma_zfree_domain(uma_zone_t zone, void *item, void *udata)
{
/* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
- random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
+ random_harvest_fast_uma(&zone, sizeof(zone), RANDOM_UMA);
CTR2(KTR_UMA, "uma_zfree_domain thread %x zone %s", curthread,
zone->uz_name);
@@ -3276,16 +3459,23 @@ zone_release(uma_zone_t zone, void **bucket, int cnt)
static void
zone_free_item(uma_zone_t zone, void *item, void *udata, enum zfreeskip skip)
{
-
#ifdef INVARIANTS
- if (skip == SKIP_NONE) {
+ bool skipdbg;
+
+ skipdbg = uma_dbg_zskip(zone, item);
+ if (skip == SKIP_NONE && !skipdbg) {
if (zone->uz_flags & UMA_ZONE_MALLOC)
uma_dbg_free(zone, udata, item);
else
uma_dbg_free(zone, NULL, item);
}
+
+ if (skip < SKIP_DTOR && zone->uz_dtor != NULL &&
+ (!skipdbg || zone->uz_dtor != trash_dtor ||
+ zone->uz_ctor != trash_ctor))
+#else
+ if (skip < SKIP_DTOR && zone->uz_dtor != NULL)
#endif
- if (skip < SKIP_DTOR && zone->uz_dtor)
zone->uz_dtor(item, zone->uz_size, udata);
if (skip < SKIP_FINI && zone->uz_fini)
@@ -3648,7 +3838,7 @@ uma_large_malloc_domain(vm_size_t size, int domain, int wait)
if (slab == NULL)
return (NULL);
if (domain == UMA_ANYDOMAIN)
- addr = kmem_malloc(kernel_arena, size, wait);
+ addr = kmem_malloc(size, wait);
else
addr = kmem_malloc_domain(domain, size, wait);
if (addr != 0) {
@@ -3679,7 +3869,7 @@ uma_large_free(uma_slab_t slab)
KASSERT((slab->us_flags & UMA_SLAB_KERNEL) != 0,
("uma_large_free: Memory not allocated with uma_large_malloc."));
- kmem_free(kernel_arena, (vm_offset_t)slab->us_data, slab->us_size);
+ kmem_free((vm_offset_t)slab->us_data, slab->us_size);
uma_total_dec(slab->us_size);
zone_free_item(slabzone, slab, NULL, SKIP_NONE);
}
@@ -3688,13 +3878,8 @@ uma_large_free(uma_slab_t slab)
static void
uma_zero_item(void *item, uma_zone_t zone)
{
- int i;
- if (zone->uz_flags & UMA_ZONE_PCPU) {
- CPU_FOREACH(i)
- bzero(zpcpu_get_cpu(item, i), zone->uz_size);
- } else
- bzero(item, zone->uz_size);
+ bzero(item, zone->uz_size);
}
unsigned long
@@ -4022,6 +4207,43 @@ uma_dbg_getslab(uma_zone_t zone, void *item)
return (slab);
}
+static bool
+uma_dbg_zskip(uma_zone_t zone, void *mem)
+{
+ uma_keg_t keg;
+
+ if ((keg = zone_first_keg(zone)) == NULL)
+ return (true);
+
+ return (uma_dbg_kskip(keg, mem));
+}
+
+static bool
+uma_dbg_kskip(uma_keg_t keg, void *mem)
+{
+ uintptr_t idx;
+
+ if (dbg_divisor == 0)
+ return (true);
+
+ if (dbg_divisor == 1)
+ return (false);
+
+ idx = (uintptr_t)mem >> PAGE_SHIFT;
+ if (keg->uk_ipers > 1) {
+ idx *= keg->uk_ipers;
+ idx += ((uintptr_t)mem & PAGE_MASK) / keg->uk_rsize;
+ }
+
+ if ((idx / dbg_divisor) * dbg_divisor != idx) {
+ counter_u64_add(uma_skip_cnt, 1);
+ return (true);
+ }
+ counter_u64_add(uma_dbg_cnt, 1);
+
+ return (false);
+}
+
/*
* Set up the slab's freei data such that uma_dbg_free can function.
*
@@ -4032,8 +4254,6 @@ uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item)
uma_keg_t keg;
int freei;
- if (zone_first_keg(zone) == NULL)
- return;
if (slab == NULL) {
slab = uma_dbg_getslab(zone, item);
if (slab == NULL)
@@ -4062,8 +4282,6 @@ uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
uma_keg_t keg;
int freei;
- if (zone_first_keg(zone) == NULL)
- return;
if (slab == NULL) {
slab = uma_dbg_getslab(zone, item);
if (slab == NULL)
diff --git a/freebsd/sys/vm/uma_int.h b/freebsd/sys/vm/uma_int.h
index 8d58fa33..5f787dfa 100644
--- a/freebsd/sys/vm/uma_int.h
+++ b/freebsd/sys/vm/uma_int.h
@@ -176,7 +176,7 @@ struct uma_hash {
/*
* align field or structure to cache line
*/
-#if defined(__amd64__)
+#if defined(__amd64__) || defined(__powerpc64__)
#define UMA_ALIGN __aligned(128)
#else
#define UMA_ALIGN
@@ -188,7 +188,7 @@ struct uma_hash {
struct uma_bucket {
LIST_ENTRY(uma_bucket) ub_link; /* Link into the zone */
- int16_t ub_cnt; /* Count of free items. */
+ int16_t ub_cnt; /* Count of items in bucket. */
int16_t ub_entries; /* Max items. */
void *ub_bucket[]; /* actual allocation storage */
};
@@ -222,9 +222,8 @@ typedef struct uma_domain * uma_domain_t;
*
*/
struct uma_keg {
- struct mtx_padalign uk_lock; /* Lock for the keg */
+ struct mtx uk_lock; /* Lock for the keg */
struct uma_hash uk_hash;
-
LIST_HEAD(,uma_zone) uk_zones; /* Keg's zones */
uint32_t uk_cursor; /* Domain alloc cursor. */
@@ -319,41 +318,49 @@ typedef struct uma_zone_domain * uma_zone_domain_t;
*
*/
struct uma_zone {
- struct mtx_padalign uz_lock; /* Lock for the zone */
- struct mtx_padalign *uz_lockptr;
- const char *uz_name; /* Text name of the zone */
-
- LIST_ENTRY(uma_zone) uz_link; /* List of all zones in keg */
+ /* Offset 0, used in alloc/free fast/medium fast path and const. */
+ struct mtx *uz_lockptr;
+ const char *uz_name; /* Text name of the zone */
struct uma_zone_domain *uz_domain; /* per-domain buckets */
-
- LIST_HEAD(,uma_klink) uz_kegs; /* List of kegs. */
- struct uma_klink uz_klink; /* klink for first keg. */
-
- uma_slaballoc uz_slab; /* Allocate a slab from the backend. */
+ uint32_t uz_flags; /* Flags inherited from kegs */
+ uint32_t uz_size; /* Size inherited from kegs */
uma_ctor uz_ctor; /* Constructor for each allocation */
uma_dtor uz_dtor; /* Destructor */
uma_init uz_init; /* Initializer for each item */
uma_fini uz_fini; /* Finalizer for each item. */
+
+ /* Offset 64, used in bucket replenish. */
uma_import uz_import; /* Import new memory to cache. */
uma_release uz_release; /* Release memory from cache. */
void *uz_arg; /* Import/release argument. */
-
- uint32_t uz_flags; /* Flags inherited from kegs */
- uint32_t uz_size; /* Size inherited from kegs */
-
- volatile u_long uz_allocs UMA_ALIGN; /* Total number of allocations */
- volatile u_long uz_fails; /* Total number of alloc failures */
- volatile u_long uz_frees; /* Total number of frees */
- uint64_t uz_sleeps; /* Total number of alloc sleeps */
+ uma_slaballoc uz_slab; /* Allocate a slab from the backend. */
uint16_t uz_count; /* Amount of items in full bucket */
uint16_t uz_count_min; /* Minimal amount of items there */
+ /* 32bit pad on 64bit. */
+ LIST_ENTRY(uma_zone) uz_link; /* List of all zones in keg */
+ LIST_HEAD(,uma_klink) uz_kegs; /* List of kegs. */
+ /* Offset 128 Rare. */
+ /*
+ * The lock is placed here to avoid adjacent line prefetcher
+ * in fast paths and to take up space near infrequently accessed
+ * members to reduce alignment overhead.
+ */
+ struct mtx uz_lock; /* Lock for the zone */
+ struct uma_klink uz_klink; /* klink for first keg. */
/* The next two fields are used to print a rate-limited warnings. */
const char *uz_warning; /* Warning to print on failure */
struct timeval uz_ratecheck; /* Warnings rate-limiting */
-
struct task uz_maxaction; /* Task to run when at limit */
+ /* 16 bytes of pad. */
+
+ /* Offset 256, atomic stats. */
+ volatile u_long uz_allocs UMA_ALIGN; /* Total number of allocations */
+ volatile u_long uz_fails; /* Total number of alloc failures */
+ volatile u_long uz_frees; /* Total number of frees */
+ uint64_t uz_sleeps; /* Total number of alloc sleeps */
+
/*
* This HAS to be the last item because we adjust the zone size
* based on NCPU and then allocate the space for the zones.
diff --git a/freebsd/sys/vm/vm_extern.h b/freebsd/sys/vm/vm_extern.h
index 47e35b2d..b2f1d726 100644
--- a/freebsd/sys/vm/vm_extern.h
+++ b/freebsd/sys/vm/vm_extern.h
@@ -54,19 +54,19 @@ vm_offset_t kmap_alloc_wait(vm_map_t, vm_size_t);
void kmap_free_wakeup(vm_map_t, vm_offset_t, vm_size_t);
/* These operate on virtual addresses backed by memory. */
-vm_offset_t kmem_alloc_attr(struct vmem *, vm_size_t size, int flags,
+vm_offset_t kmem_alloc_attr(vm_size_t size, int flags,
vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr);
vm_offset_t kmem_alloc_attr_domain(int domain, vm_size_t size, int flags,
vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr);
-vm_offset_t kmem_alloc_contig(struct vmem *, vm_size_t size, int flags,
+vm_offset_t kmem_alloc_contig(vm_size_t size, int flags,
vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary,
vm_memattr_t memattr);
vm_offset_t kmem_alloc_contig_domain(int domain, vm_size_t size, int flags,
vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary,
vm_memattr_t memattr);
-vm_offset_t kmem_malloc(struct vmem *, vm_size_t size, int flags);
+vm_offset_t kmem_malloc(vm_size_t size, int flags);
vm_offset_t kmem_malloc_domain(int domain, vm_size_t size, int flags);
-void kmem_free(struct vmem *, vm_offset_t, vm_size_t);
+void kmem_free(vm_offset_t addr, vm_size_t size);
/* This provides memory for previously allocated address space. */
int kmem_back(vm_object_t, vm_offset_t, vm_size_t, int);
@@ -74,6 +74,7 @@ int kmem_back_domain(int, vm_object_t, vm_offset_t, vm_size_t, int);
void kmem_unback(vm_object_t, vm_offset_t, vm_size_t);
/* Bootstrapping. */
+void kmem_bootstrap_free(vm_offset_t, vm_size_t);
vm_map_t kmem_suballoc(vm_map_t, vm_offset_t *, vm_offset_t *, vm_size_t,
boolean_t);
void kmem_init(vm_offset_t, vm_offset_t);
diff --git a/freebsd/usr.bin/netstat/inet.c b/freebsd/usr.bin/netstat/inet.c
index 6b2e50d6..4eb80816 100644
--- a/freebsd/usr.bin/netstat/inet.c
+++ b/freebsd/usr.bin/netstat/inet.c
@@ -171,12 +171,12 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
bzero(xso, sizeof *xso);
xso->xso_len = sizeof *xso;
- xso->xso_so = so;
+ xso->xso_so = (uintptr_t)so;
xso->so_type = so->so_type;
xso->so_options = so->so_options;
xso->so_linger = so->so_linger;
xso->so_state = so->so_state;
- xso->so_pcb = so->so_pcb;
+ xso->so_pcb = (uintptr_t)so->so_pcb;
if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
return (-1);
xso->xso_protocol = proto.pr_protocol;
diff --git a/freebsd/usr.bin/netstat/unix.c b/freebsd/usr.bin/netstat/unix.c
index bca42672..690caa75 100644
--- a/freebsd/usr.bin/netstat/unix.c
+++ b/freebsd/usr.bin/netstat/unix.c
@@ -166,7 +166,7 @@ pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
xu.xu_len = sizeof xu;
KREAD(head_off, &head, sizeof(head));
LIST_FOREACH(unp, &head, unp_link) {
- xu.xu_unpp = unp;
+ xu.xu_unpp = (uintptr_t)unp;
KREAD(unp, &unp0, sizeof (*unp));
unp = &unp0;
diff --git a/freebsd/usr.bin/vmstat/vmstat.c b/freebsd/usr.bin/vmstat/vmstat.c
index 19b1f7ef..fcdb6314 100644
--- a/freebsd/usr.bin/vmstat/vmstat.c
+++ b/freebsd/usr.bin/vmstat/vmstat.c
@@ -95,7 +95,7 @@ __FBSDID("$FreeBSD$");
static char da[] = "da";
enum x_stats { X_SUM, X_HZ, X_STATHZ, X_NCHSTATS, X_INTRNAMES, X_SINTRNAMES,
- X_INTRCNT, X_SINTRCNT, X_DEFICIT, X_REC, X_PGIN, X_XSTATS };
+ X_INTRCNT, X_SINTRCNT, X_NINTRCNT };
static struct nlist namelist[] = {
[X_SUM] = { .n_name = "_vm_cnt", },
@@ -106,12 +106,7 @@ static struct nlist namelist[] = {
[X_SINTRNAMES] = { .n_name = "_sintrnames", },
[X_INTRCNT] = { .n_name = "_intrcnt", },
[X_SINTRCNT] = { .n_name = "_sintrcnt", },
-#ifdef notyet
- [X_DEFICIT] = { .n_name = "_deficit", },
- [X_REC] = { .n_name = "_rectime", },
- [X_PGIN] = { .n_name = "_pgintime", },
- [X_XSTATS] = { .n_name = "_xstats", },
-#endif
+ [X_NINTRCNT] = { .n_name = "_nintrcnt", },
{ .n_name = NULL, },
};
@@ -217,6 +212,7 @@ static void domemstat_zone(void);
#ifndef __rtems__
static void kread(int, void *, size_t);
static void kreado(int, void *, size_t, size_t);
+static void kreadptr(uintptr_t, void *, size_t);
static void needhdr(int);
static void needresize(int);
static void doresize(void);
@@ -253,7 +249,8 @@ main(int argc, char *argv[])
#endif /* __rtems__ */
float f;
#ifndef __rtems__
- int bufsize, c, len, reps, todo;
+ int bufsize, c, reps, todo;
+ size_t len;
#else /* __rtems__ */
int c, reps, todo;
#endif /* __rtems__ */
@@ -284,7 +281,7 @@ main(int argc, char *argv[])
if (argc < 0)
return (argc);
- while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:oPp:stw:z")) != -1) {
+ while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:oPp:sw:z")) != -1) {
switch (c) {
#ifndef __rtems__
case 'a':
@@ -335,14 +332,6 @@ main(int argc, char *argv[])
case 's':
todo |= SUMSTAT;
break;
- case 't':
-#ifdef notyet
- todo |= TIMESTAT;
-#else
- xo_errx(EX_USAGE,
- "sorry, -t is not (re)implemented yet");
-#endif
- break;
case 'w':
/* Convert to milliseconds. */
f = atof(optarg);
@@ -374,7 +363,8 @@ main(int argc, char *argv[])
retry_nlist:
if (kd != NULL && (c = kvm_nlist(kd, namelist)) != 0) {
if (c > 0) {
- bufsize = 0, len = 0;
+ bufsize = 0;
+ len = 0;
/*
* 'cnt' was renamed to 'vm_cnt'. If 'vm_cnt' is not
@@ -386,6 +376,13 @@ retry_nlist:
goto retry_nlist;
}
+ /*
+ * 'nintrcnt' doesn't exist in older kernels, but
+ * that isn't fatal.
+ */
+ if (namelist[X_NINTRCNT].n_type == 0 && c == 1)
+ goto nlist_ok;
+
for (c = 0; c < (int)(nitems(namelist)); c++)
if (namelist[c].n_type == 0)
bufsize += strlen(namelist[c].n_name)
@@ -409,6 +406,7 @@ retry_nlist:
xo_finish();
exit(1);
}
+nlist_ok:
if (kd && Pflag)
xo_errx(1, "Cannot use -P with crash dumps");
@@ -452,10 +450,6 @@ retry_nlist:
dosum();
if (todo & OBJSTAT)
doobjstat();
-#ifdef notyet
- if (todo & TIMESTAT)
- dotimes();
-#endif
if (todo & INTRSTAT)
dointr(interval, reps);
if (todo & VMSTAT)
@@ -498,8 +492,11 @@ getdrivedata(char **argv)
if (isdigit(**argv))
break;
num_devices_specified++;
- specified_devices = realloc(specified_devices,
+ specified_devices = reallocf(specified_devices,
sizeof(char *) * num_devices_specified);
+ if (specified_devices == NULL) {
+ xo_errx(1, "%s", "reallocf (specified_devices)");
+ }
specified_devices[num_devices_specified - 1] = *argv;
}
dev_select = NULL;
@@ -1024,29 +1021,6 @@ doresize(void)
wresized = 0;
}
-#ifdef notyet
-static void
-dotimes(void)
-{
- unsigned int pgintime, rectime;
-
- kread(X_REC, &rectime, sizeof(rectime));
- kread(X_PGIN, &pgintime, sizeof(pgintime));
- kread(X_SUM, &sum, sizeof(sum));
- xo_emit("{:page-reclaims/%u} {N:reclaims}, "
- "{:reclaim-time/%u} {N:total time (usec)}\n",
- sum.v_pgrec, rectime);
- xo_emit("{L:average}: {:reclaim-average/%u} {N:usec \\/ reclaim}\n",
- rectime / sum.v_pgrec);
- xo_emit("\n");
- xo_emit("{:page-ins/%u} {N:page ins}, "
- "{:page-in-time/%u} {N:total time (msec)}\n",
- sum.v_pgin, pgintime / 10);
- xo_emit("{L:average}: {:average/%8.1f} {N:msec \\/ page in}\n",
- pgintime / (sum.v_pgin * 10.0));
-}
-#endif
-
static long
pct(long top, long bot)
{
@@ -1268,7 +1242,7 @@ cpustats(void)
total = 0;
for (state = 0; state < CPUSTATES; ++state)
total += cur.cp_time[state];
- if (total)
+ if (total > 0)
lpct = 100.0 / total;
else
lpct = 0.0;
@@ -1330,12 +1304,18 @@ static unsigned int
read_intrcnts(unsigned long **intrcnts)
{
size_t intrcntlen;
+ uintptr_t kaddr;
if (kd != NULL) {
kread(X_SINTRCNT, &intrcntlen, sizeof(intrcntlen));
if ((*intrcnts = malloc(intrcntlen)) == NULL)
err(1, "malloc()");
- kread(X_INTRCNT, *intrcnts, intrcntlen);
+ if (namelist[X_NINTRCNT].n_type == 0)
+ kread(X_INTRCNT, *intrcnts, intrcntlen);
+ else {
+ kread(X_INTRCNT, &kaddr, sizeof(kaddr));
+ kreadptr(kaddr, *intrcnts, intrcntlen);
+ }
} else {
for (*intrcnts = NULL, intrcntlen = 1024; ; intrcntlen *= 2) {
*intrcnts = reallocf(*intrcnts, intrcntlen);
@@ -1392,6 +1372,7 @@ dointr(unsigned int interval, int reps)
char *intrname, *intrnames;
long long period_ms, old_uptime, uptime;
size_t clen, inamlen, istrnamlen;
+ uintptr_t kaddr;
unsigned int nintr;
old_intrcnts = NULL;
@@ -1402,7 +1383,12 @@ dointr(unsigned int interval, int reps)
kread(X_SINTRNAMES, &inamlen, sizeof(inamlen));
if ((intrnames = malloc(inamlen)) == NULL)
xo_err(1, "malloc()");
- kread(X_INTRNAMES, intrnames, inamlen);
+ if (namelist[X_NINTRCNT].n_type == 0)
+ kread(X_INTRNAMES, intrnames, inamlen);
+ else {
+ kread(X_INTRNAMES, &kaddr, sizeof(kaddr));
+ kreadptr(kaddr, intrnames, inamlen);
+ }
} else {
for (intrnames = NULL, inamlen = 1024; ; inamlen *= 2) {
if ((intrnames = reallocf(intrnames, inamlen)) == NULL)
@@ -1755,6 +1741,14 @@ kread(int nlx, void *addr, size_t size)
#endif /* __rtems__ */
static void
+kreadptr(uintptr_t addr, void *buf, size_t size)
+{
+
+ if ((size_t)kvm_read(kd, addr, buf, size) != size)
+ xo_errx(1, "%s", kvm_geterr(kd));
+}
+
+static void __dead2
usage(void)
{
xo_error("%s%s",
diff --git a/libbsd.py b/libbsd.py
index dc6f5702..0ac6c1a1 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -59,12 +59,15 @@ _defaults = {
'include-paths': ['rtemsbsd/include',
'freebsd/sys',
'freebsd/sys/contrib/ck/include',
+ 'freebsd/sys/contrib/libsodium/src/libsodium/include',
+ 'freebsd/sys/contrib/libsodium/src/libsodium/include/sodium',
'freebsd/sys/contrib/pf',
'freebsd/crypto',
'freebsd/sys/net',
'freebsd/include',
'freebsd/lib',
'freebsd/lib/libbsdstat',
+ 'freebsd/lib/libcapsicum',
'freebsd/lib/libcasper',
'freebsd/lib/libc/include',
'freebsd/lib/libc/isc/include',
@@ -386,6 +389,8 @@ class base(builder.Module):
'sys/contrib/ck/include/gcc/x86/ck_f_pr.h',
'sys/contrib/ck/include/gcc/x86/ck_pr.h',
'sys/fs/devfs/devfs_int.h',
+ 'sys/rpc/netconfig.h',
+ 'sys/rpc/types.h',
'sys/security/audit/audit.h',
'sys/security/mac/mac_framework.h',
'sys/sys/acl.h',
@@ -426,8 +431,8 @@ class base(builder.Module):
'sys/sys/khelp.h',
'sys/sys/kobj.h',
'sys/sys/kthread.h',
- 'sys/sys/ktr.h',
'sys/sys/ktr_class.h',
+ 'sys/sys/ktr.h',
'sys/sys/libkern.h',
'sys/sys/limits.h',
'sys/sys/linker.h',
@@ -446,6 +451,7 @@ class base(builder.Module):
'sys/sys/mount.h',
'sys/sys/_mutex.h',
'sys/sys/mutex.h',
+ 'sys/sys/nlist_aout.h',
'sys/sys/_null.h',
'sys/sys/nv.h',
'sys/sys/osd.h',
@@ -473,10 +479,11 @@ class base(builder.Module):
'sys/sys/_semaphore.h',
'sys/sys/seq.h',
'sys/sys/sf_buf.h',
+ 'sys/sys/sglist.h',
'sys/sys/sigio.h',
'sys/sys/signalvar.h',
- 'sys/sys/smp.h',
'sys/sys/sleepqueue.h',
+ 'sys/sys/smp.h',
'sys/sys/sockbuf.h',
'sys/sys/socketvar.h',
'sys/sys/sockopt.h',
@@ -490,11 +497,8 @@ class base(builder.Module):
'sys/sys/systm.h',
'sys/sys/_task.h',
'sys/sys/taskqueue.h',
- 'sys/sys/tslog.h',
- 'sys/sys/nlist_aout.h',
- 'sys/rpc/netconfig.h',
- 'sys/rpc/types.h',
'sys/sys/tree.h',
+ 'sys/sys/tslog.h',
'sys/sys/ucred.h',
'sys/sys/un.h',
'sys/sys/unpcb.h',
@@ -666,10 +670,6 @@ class mmc(builder.Module):
mm = self.manager
self.addKernelSpaceHeaderFiles(
[
- 'sys/arm/at91/at91_mcireg.h',
- 'sys/arm/at91/at91_pdcreg.h',
- 'sys/arm/at91/at91reg.h',
- 'sys/arm/at91/at91var.h',
'sys/dev/mmc/bridge.h',
'sys/dev/mmc/mmcbrvar.h',
'sys/dev/mmc/mmc_ioctl.h',
@@ -682,13 +682,18 @@ class mmc(builder.Module):
)
self.addKernelSpaceSourceFiles(
[
- 'sys/arm/at91/at91_mci.c',
'sys/dev/mmc/mmc.c',
'sys/dev/mmc/mmcsd.c',
'sys/dev/mmc/mmc_subr.c',
],
mm.generator['source']()
)
+ self.addRTEMSSourceFiles(
+ [
+ 'sys/arm/at91/at91_mci.c',
+ ],
+ mm.generator['source']()
+ )
#
# MMC
@@ -2318,8 +2323,22 @@ class opencrypto(builder.Module):
mm = self.manager
self.addKernelSpaceHeaderFiles(
[
+ 'sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h',
+ 'sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h',
+ 'sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_16.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_32.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_64.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/export.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/private/common.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/private/implementations.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/randombytes.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/runtime.h',
+ 'sys/contrib/libsodium/src/libsodium/include/sodium/utils.h',
'sys/opencrypto/cast.h',
'sys/opencrypto/castsb.h',
+ 'sys/opencrypto/_cryptodev.h',
'sys/opencrypto/cryptodev.h',
'sys/opencrypto/cryptosoft.h',
'sys/opencrypto/deflate.h',
@@ -2327,31 +2346,36 @@ class opencrypto(builder.Module):
'sys/opencrypto/gmac.h',
'sys/opencrypto/rmd160.h',
'sys/opencrypto/skipjack.h',
- 'sys/opencrypto/xform_auth.h',
- 'sys/opencrypto/xform_comp.h',
- 'sys/opencrypto/xform_enc.h',
- 'sys/opencrypto/xform.h',
- 'sys/opencrypto/xform_userland.h',
'sys/opencrypto/xform_aes_icm.c',
'sys/opencrypto/xform_aes_xts.c',
+ 'sys/opencrypto/xform_auth.h',
'sys/opencrypto/xform_blf.c',
'sys/opencrypto/xform_cast5.c',
'sys/opencrypto/xform_cml.c',
+ 'sys/opencrypto/xform_comp.h',
'sys/opencrypto/xform_deflate.c',
'sys/opencrypto/xform_des1.c',
'sys/opencrypto/xform_des3.c',
+ 'sys/opencrypto/xform_enc.h',
'sys/opencrypto/xform_gmac.c',
+ 'sys/opencrypto/xform.h',
'sys/opencrypto/xform_md5.c',
'sys/opencrypto/xform_null.c',
+ 'sys/opencrypto/xform_poly1305.h',
'sys/opencrypto/xform_rijndael.c',
'sys/opencrypto/xform_rmd160.c',
'sys/opencrypto/xform_sha1.c',
'sys/opencrypto/xform_sha2.c',
'sys/opencrypto/xform_skipjack.c',
+ 'sys/opencrypto/xform_userland.h',
]
)
self.addKernelSpaceSourceFiles(
[
+ 'sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c',
+ 'sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c',
+ 'sys/contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c',
+ 'sys/crypto/libsodium/utils.c',
'sys/opencrypto/cast.c',
'sys/opencrypto/criov.c',
'sys/opencrypto/crypto.c',
@@ -2363,6 +2387,7 @@ class opencrypto(builder.Module):
'sys/opencrypto/rmd160.c',
'sys/opencrypto/skipjack.c',
'sys/opencrypto/xform.c',
+ 'sys/opencrypto/xform_poly1305.c',
],
mm.generator['source']()
)
@@ -2397,6 +2422,7 @@ class crypto(builder.Module):
'sys/crypto/rijndael/rijndael.h',
'sys/crypto/rijndael/rijndael_local.h',
'sys/crypto/sha1.h',
+ 'sys/crypto/sha2/sha224.h',
'sys/crypto/sha2/sha256.h',
'sys/crypto/sha2/sha384.h',
'sys/crypto/sha2/sha512.h',
@@ -2594,8 +2620,8 @@ class user_space(builder.Module):
'include/ifaddrs.h',
'include/mpool.h',
'include/netconfig.h',
- 'include/netdb.h',
'include/nlist.h',
+ 'include/nl_types.h',
'include/nsswitch.h',
'include/resolv.h',
'include/res_update.h',
@@ -2632,6 +2658,7 @@ class user_space(builder.Module):
'include/sysexits.h',
'lib/lib80211/lib80211_ioctl.h',
'lib/lib80211/lib80211_regdomain.h',
+ 'lib/libcapsicum/capsicum_helpers.h',
'lib/libcasper/libcasper/libcasper.h',
'lib/libcasper/services/cap_dns/cap_dns.h',
'lib/libcasper/services/cap_syslog/cap_syslog.h',
@@ -2998,165 +3025,166 @@ class crypto_openssl(builder.Module):
mm = self.manager
self.addUserSpaceHeaderFiles(
[
- 'crypto/openssl/engines/e_cswift_err.h',
- 'crypto/openssl/engines/e_aep_err.h',
- 'crypto/openssl/engines/e_gmp_err.h',
- 'crypto/openssl/engines/ccgost/gost2001_keyx.h',
- 'crypto/openssl/engines/ccgost/e_gost_err.h',
- 'crypto/openssl/engines/ccgost/gost_params.h',
- 'crypto/openssl/engines/ccgost/gost_lcl.h',
- 'crypto/openssl/engines/ccgost/gost89.h',
- 'crypto/openssl/engines/ccgost/gost_keywrap.h',
- 'crypto/openssl/engines/ccgost/gosthash.h',
- 'crypto/openssl/engines/e_chil_err.h',
- 'crypto/openssl/engines/e_4758cca_err.h',
- 'crypto/openssl/engines/e_capi_err.h',
- 'crypto/openssl/engines/e_nuron_err.h',
- 'crypto/openssl/engines/e_atalla_err.h',
- 'crypto/openssl/engines/vendor_defns/sureware.h',
- 'crypto/openssl/engines/vendor_defns/cswift.h',
- 'crypto/openssl/engines/vendor_defns/atalla.h',
- 'crypto/openssl/engines/vendor_defns/hwcryptohook.h',
- 'crypto/openssl/engines/vendor_defns/hw_4758_cca.h',
- 'crypto/openssl/engines/vendor_defns/aep.h',
- 'crypto/openssl/engines/vendor_defns/hw_ubsec.h',
- 'crypto/openssl/engines/e_sureware_err.h',
- 'crypto/openssl/engines/e_ubsec_err.h',
- 'crypto/openssl/ssl/ssl2.h',
- 'crypto/openssl/ssl/ssl3.h',
- 'crypto/openssl/ssl/dtls1.h',
- 'crypto/openssl/ssl/kssl_lcl.h',
- 'crypto/openssl/ssl/srtp.h',
- 'crypto/openssl/ssl/tls1.h',
- 'crypto/openssl/ssl/ssl23.h',
- 'crypto/openssl/ssl/ssl_locl.h',
- 'crypto/openssl/ssl/kssl.h',
- 'crypto/openssl/ssl/ssl.h',
- 'crypto/openssl/e_os.h',
- 'crypto/openssl/e_os2.h',
- 'crypto/openssl/crypto/bio/bio_lcl.h',
+ 'crypto/openssl/crypto/aes/aes.h',
+ 'crypto/openssl/crypto/aes/aes_locl.h',
+ 'crypto/openssl/crypto/arm_arch.h',
+ 'crypto/openssl/crypto/asn1/asn1.h',
+ 'crypto/openssl/crypto/asn1/asn1_int.h',
+ 'crypto/openssl/crypto/asn1/asn1_locl.h',
+ 'crypto/openssl/crypto/asn1/asn1_mac.h',
+ 'crypto/openssl/crypto/asn1/asn1t.h',
+ 'crypto/openssl/crypto/asn1/charmap.h',
+ 'crypto/openssl/crypto/bf/bf_locl.h',
+ 'crypto/openssl/crypto/bf/bf_pi.h',
+ 'crypto/openssl/crypto/bf/blowfish.h',
'crypto/openssl/crypto/bio/bio.h',
- 'crypto/openssl/crypto/modes/modes_lcl.h',
- 'crypto/openssl/crypto/modes/modes.h',
- 'crypto/openssl/crypto/cms/cms.h',
- 'crypto/openssl/crypto/cms/cms_lcl.h',
- 'crypto/openssl/crypto/bn/bn_prime.h',
- 'crypto/openssl/crypto/bn/bn_lcl.h',
+ 'crypto/openssl/crypto/bio/bio_lcl.h',
'crypto/openssl/crypto/bn/bn.h',
+ 'crypto/openssl/crypto/bn/bn_lcl.h',
+ 'crypto/openssl/crypto/bn/bn_prime.h',
+ 'crypto/openssl/crypto/bn_int.h',
'crypto/openssl/crypto/bn/rsaz_exp.h',
- 'crypto/openssl/crypto/ecdh/ecdh.h',
- 'crypto/openssl/crypto/ecdh/ech_locl.h',
- 'crypto/openssl/crypto/dh/dh.h',
- 'crypto/openssl/crypto/opensslv.h',
- 'crypto/openssl/crypto/ripemd/ripemd.h',
- 'crypto/openssl/crypto/ripemd/rmd_locl.h',
- 'crypto/openssl/crypto/ripemd/rmdconst.h',
- 'crypto/openssl/crypto/hmac/hmac.h',
- 'crypto/openssl/crypto/rand/rand_lcl.h',
- 'crypto/openssl/crypto/rand/rand.h',
- 'crypto/openssl/crypto/stack/safestack.h',
- 'crypto/openssl/crypto/stack/stack.h',
- 'crypto/openssl/crypto/pem/pem.h',
- 'crypto/openssl/crypto/pem/pem2.h',
- 'crypto/openssl/crypto/evp/evp_locl.h',
- 'crypto/openssl/crypto/evp/evp.h',
- 'crypto/openssl/crypto/constant_time_locl.h',
- 'crypto/openssl/crypto/txt_db/txt_db.h',
- 'crypto/openssl/crypto/ebcdic.h',
+ 'crypto/openssl/crypto/buffer/buffer.h',
+ 'crypto/openssl/crypto/camellia/camellia.h',
+ 'crypto/openssl/crypto/camellia/cmll_locl.h',
+ 'crypto/openssl/crypto/cast/cast.h',
+ 'crypto/openssl/crypto/cast/cast_lcl.h',
+ 'crypto/openssl/crypto/cast/cast_s.h',
'crypto/openssl/crypto/cmac/cmac.h',
- 'crypto/openssl/crypto/ppc_arch.h',
+ 'crypto/openssl/crypto/cms/cms.h',
+ 'crypto/openssl/crypto/cms/cms_lcl.h',
+ 'crypto/openssl/crypto/comp/comp.h',
+ 'crypto/openssl/crypto/conf/conf_api.h',
+ 'crypto/openssl/crypto/conf/conf_def.h',
+ 'crypto/openssl/crypto/conf/conf.h',
+ 'crypto/openssl/crypto/constant_time_locl.h',
+ 'crypto/openssl/crypto/cryptlib.h',
+ 'crypto/openssl/crypto/crypto.h',
+ 'crypto/openssl/crypto/des/des.h',
+ 'crypto/openssl/crypto/des/des_locl.h',
+ 'crypto/openssl/crypto/des/des_old.h',
+ 'crypto/openssl/crypto/des/des_ver.h',
+ 'crypto/openssl/crypto/des/rpc_des.h',
+ 'crypto/openssl/crypto/des/spr.h',
+ 'crypto/openssl/crypto/dh/dh.h',
'crypto/openssl/crypto/dsa/dsa.h',
'crypto/openssl/crypto/dsa/dsa_locl.h',
- 'crypto/openssl/crypto/md4/md4_locl.h',
- 'crypto/openssl/crypto/md4/md4.h',
- 'crypto/openssl/crypto/sha/sha_locl.h',
- 'crypto/openssl/crypto/sha/sha.h',
- 'crypto/openssl/crypto/arm_arch.h',
- 'crypto/openssl/crypto/o_str.h',
- 'crypto/openssl/crypto/ui/ui_locl.h',
- 'crypto/openssl/crypto/ui/ui_compat.h',
- 'crypto/openssl/crypto/ui/ui.h',
- 'crypto/openssl/crypto/md32_common.h',
- 'crypto/openssl/crypto/pkcs7/pkcs7.h',
- 'crypto/openssl/crypto/crypto.h',
- 'crypto/openssl/crypto/ossl_typ.h',
- 'crypto/openssl/crypto/err/err.h',
- 'crypto/openssl/crypto/sparc_arch.h',
'crypto/openssl/crypto/dso/dso.h',
- 'crypto/openssl/crypto/o_dir.h',
- 'crypto/openssl/crypto/idea/idea.h',
- 'crypto/openssl/crypto/idea/idea_lcl.h',
- 'crypto/openssl/crypto/engine/eng_int.h',
- 'crypto/openssl/crypto/engine/engine.h',
- 'crypto/openssl/crypto/fips_err.h',
- 'crypto/openssl/crypto/comp/comp.h',
+ 'crypto/openssl/crypto/ebcdic.h',
+ 'crypto/openssl/crypto/ecdh/ecdh.h',
+ 'crypto/openssl/crypto/ecdh/ech_locl.h',
'crypto/openssl/crypto/ecdsa/ecdsa.h',
'crypto/openssl/crypto/ecdsa/ecs_locl.h',
- 'crypto/openssl/crypto/pkcs12/pkcs12.h',
- 'crypto/openssl/crypto/srp/srp_lcl.h',
- 'crypto/openssl/crypto/srp/srp_grps.h',
- 'crypto/openssl/crypto/srp/srp.h',
- 'crypto/openssl/crypto/x509v3/x509v3.h',
- 'crypto/openssl/crypto/x509v3/pcy_int.h',
- 'crypto/openssl/crypto/x509v3/ext_dat.h',
- 'crypto/openssl/crypto/symhacks.h',
- 'crypto/openssl/crypto/aes/aes.h',
- 'crypto/openssl/crypto/aes/aes_locl.h',
- 'crypto/openssl/crypto/bf/bf_locl.h',
- 'crypto/openssl/crypto/bf/bf_pi.h',
- 'crypto/openssl/crypto/bf/blowfish.h',
- 'crypto/openssl/crypto/rc4/rc4_locl.h',
- 'crypto/openssl/crypto/rc4/rc4.h',
+ 'crypto/openssl/crypto/ec/ec.h',
+ 'crypto/openssl/crypto/ec/ec_lcl.h',
+ 'crypto/openssl/crypto/engine/engine.h',
+ 'crypto/openssl/crypto/engine/eng_int.h',
+ 'crypto/openssl/crypto/err/err.h',
+ 'crypto/openssl/crypto/evp/evp.h',
+ 'crypto/openssl/crypto/evp/evp_locl.h',
+ 'crypto/openssl/crypto/fips_err.h',
+ 'crypto/openssl/crypto/hmac/hmac.h',
+ 'crypto/openssl/crypto/idea/idea.h',
+ 'crypto/openssl/crypto/idea/idea_lcl.h',
+ 'crypto/openssl/crypto/krb5/krb5_asn.h',
+ 'crypto/openssl/crypto/lhash/lhash.h',
+ 'crypto/openssl/crypto/md32_common.h',
+ 'crypto/openssl/crypto/md4/md4.h',
+ 'crypto/openssl/crypto/md4/md4_locl.h',
+ 'crypto/openssl/crypto/md5/md5.h',
+ 'crypto/openssl/crypto/md5/md5_locl.h',
+ 'crypto/openssl/crypto/mdc2/mdc2.h',
+ 'crypto/openssl/crypto/modes/modes.h',
+ 'crypto/openssl/crypto/modes/modes_lcl.h',
+ 'crypto/openssl/crypto/objects/obj_dat.h',
+ 'crypto/openssl/crypto/objects/objects.h',
+ 'crypto/openssl/crypto/objects/obj_mac.h',
+ 'crypto/openssl/crypto/objects/obj_xref.h',
'crypto/openssl/crypto/ocsp/ocsp.h',
+ 'crypto/openssl/crypto/o_dir.h',
+ 'crypto/openssl/crypto/opensslconf.h',
+ 'crypto/openssl/crypto/opensslv.h',
+ 'crypto/openssl/crypto/ossl_typ.h',
+ 'crypto/openssl/crypto/o_str.h',
+ 'crypto/openssl/crypto/o_time.h',
+ 'crypto/openssl/crypto/pem/pem2.h',
+ 'crypto/openssl/crypto/pem/pem.h',
+ 'crypto/openssl/crypto/pkcs12/pkcs12.h',
+ 'crypto/openssl/crypto/pkcs7/pkcs7.h',
+ 'crypto/openssl/crypto/ppc_arch.h',
+ 'crypto/openssl/crypto/pqueue/pqueue.h',
+ 'crypto/openssl/crypto/rand/rand.h',
+ 'crypto/openssl/crypto/rand/rand_lcl.h',
'crypto/openssl/crypto/rc2/rc2.h',
'crypto/openssl/crypto/rc2/rc2_locl.h',
- 'crypto/openssl/crypto/md5/md5_locl.h',
- 'crypto/openssl/crypto/md5/md5.h',
- 'crypto/openssl/crypto/des/des_locl.h',
- 'crypto/openssl/crypto/des/rpc_des.h',
- 'crypto/openssl/crypto/des/des.h',
- 'crypto/openssl/crypto/des/spr.h',
- 'crypto/openssl/crypto/des/des_ver.h',
- 'crypto/openssl/crypto/des/des_old.h',
- 'crypto/openssl/crypto/cryptlib.h',
- 'crypto/openssl/crypto/krb5/krb5_asn.h',
- 'crypto/openssl/crypto/o_time.h',
- 'crypto/openssl/crypto/opensslconf.h',
- 'crypto/openssl/crypto/camellia/cmll_locl.h',
- 'crypto/openssl/crypto/camellia/camellia.h',
- 'crypto/openssl/crypto/x509/x509.h',
- 'crypto/openssl/crypto/x509/vpm_int.h',
- 'crypto/openssl/crypto/x509/x509_vfy.h',
- 'crypto/openssl/crypto/seed/seed_locl.h',
+ 'crypto/openssl/crypto/rc4/rc4.h',
+ 'crypto/openssl/crypto/rc4/rc4_locl.h',
+ 'crypto/openssl/crypto/ripemd/ripemd.h',
+ 'crypto/openssl/crypto/ripemd/rmdconst.h',
+ 'crypto/openssl/crypto/ripemd/rmd_locl.h',
+ 'crypto/openssl/crypto/rsa/rsa.h',
+ 'crypto/openssl/crypto/rsa/rsa_locl.h',
'crypto/openssl/crypto/seed/seed.h',
- 'crypto/openssl/crypto/objects/obj_xref.h',
- 'crypto/openssl/crypto/objects/obj_mac.h',
- 'crypto/openssl/crypto/objects/objects.h',
- 'crypto/openssl/crypto/objects/obj_dat.h',
+ 'crypto/openssl/crypto/seed/seed_locl.h',
+ 'crypto/openssl/crypto/sha/sha.h',
+ 'crypto/openssl/crypto/sha/sha_locl.h',
+ 'crypto/openssl/crypto/sparc_arch.h',
+ 'crypto/openssl/crypto/srp/srp_grps.h',
+ 'crypto/openssl/crypto/srp/srp.h',
+ 'crypto/openssl/crypto/srp/srp_lcl.h',
+ 'crypto/openssl/crypto/stack/safestack.h',
+ 'crypto/openssl/crypto/stack/stack.h',
+ 'crypto/openssl/crypto/symhacks.h',
'crypto/openssl/crypto/ts/ts.h',
- 'crypto/openssl/crypto/mdc2/mdc2.h',
- 'crypto/openssl/crypto/pqueue/pqueue.h',
+ 'crypto/openssl/crypto/txt_db/txt_db.h',
+ 'crypto/openssl/crypto/ui/ui_compat.h',
+ 'crypto/openssl/crypto/ui/ui.h',
+ 'crypto/openssl/crypto/ui/ui_locl.h',
'crypto/openssl/crypto/vms_rms.h',
- 'crypto/openssl/crypto/buffer/buffer.h',
- 'crypto/openssl/crypto/cast/cast.h',
- 'crypto/openssl/crypto/cast/cast_s.h',
- 'crypto/openssl/crypto/cast/cast_lcl.h',
- 'crypto/openssl/crypto/rsa/rsa.h',
- 'crypto/openssl/crypto/rsa/rsa_locl.h',
'crypto/openssl/crypto/whrlpool/whrlpool.h',
'crypto/openssl/crypto/whrlpool/wp_locl.h',
- 'crypto/openssl/crypto/asn1/asn1.h',
- 'crypto/openssl/crypto/asn1/asn1_int.h',
- 'crypto/openssl/crypto/asn1/asn1_locl.h',
- 'crypto/openssl/crypto/asn1/asn1_mac.h',
- 'crypto/openssl/crypto/asn1/asn1t.h',
- 'crypto/openssl/crypto/asn1/charmap.h',
- 'crypto/openssl/crypto/ec/ec_lcl.h',
- 'crypto/openssl/crypto/ec/ec.h',
- 'crypto/openssl/crypto/conf/conf.h',
- 'crypto/openssl/crypto/conf/conf_def.h',
- 'crypto/openssl/crypto/conf/conf_api.h',
- 'crypto/openssl/crypto/lhash/lhash.h',
+ 'crypto/openssl/crypto/x509v3/ext_dat.h',
+ 'crypto/openssl/crypto/x509v3/pcy_int.h',
+ 'crypto/openssl/crypto/x509v3/x509v3.h',
+ 'crypto/openssl/crypto/x509/vpm_int.h',
+ 'crypto/openssl/crypto/x509/x509.h',
+ 'crypto/openssl/crypto/x509/x509_vfy.h',
+ 'crypto/openssl/engines/ccgost/e_gost_err.h',
+ 'crypto/openssl/engines/ccgost/gost2001_keyx.h',
+ 'crypto/openssl/engines/ccgost/gost89.h',
+ 'crypto/openssl/engines/ccgost/gosthash.h',
+ 'crypto/openssl/engines/ccgost/gost_keywrap.h',
+ 'crypto/openssl/engines/ccgost/gost_lcl.h',
+ 'crypto/openssl/engines/ccgost/gost_params.h',
+ 'crypto/openssl/engines/e_4758cca_err.h',
+ 'crypto/openssl/engines/e_aep_err.h',
+ 'crypto/openssl/engines/e_atalla_err.h',
+ 'crypto/openssl/engines/e_capi_err.h',
+ 'crypto/openssl/engines/e_chil_err.h',
+ 'crypto/openssl/engines/e_cswift_err.h',
+ 'crypto/openssl/engines/e_gmp_err.h',
+ 'crypto/openssl/engines/e_nuron_err.h',
+ 'crypto/openssl/engines/e_sureware_err.h',
+ 'crypto/openssl/engines/e_ubsec_err.h',
+ 'crypto/openssl/engines/vendor_defns/aep.h',
+ 'crypto/openssl/engines/vendor_defns/atalla.h',
+ 'crypto/openssl/engines/vendor_defns/cswift.h',
+ 'crypto/openssl/engines/vendor_defns/hw_4758_cca.h',
+ 'crypto/openssl/engines/vendor_defns/hwcryptohook.h',
+ 'crypto/openssl/engines/vendor_defns/hw_ubsec.h',
+ 'crypto/openssl/engines/vendor_defns/sureware.h',
+ 'crypto/openssl/e_os2.h',
+ 'crypto/openssl/e_os.h',
+ 'crypto/openssl/ssl/dtls1.h',
+ 'crypto/openssl/ssl/kssl.h',
+ 'crypto/openssl/ssl/kssl_lcl.h',
+ 'crypto/openssl/ssl/srtp.h',
+ 'crypto/openssl/ssl/ssl23.h',
+ 'crypto/openssl/ssl/ssl2.h',
+ 'crypto/openssl/ssl/ssl3.h',
+ 'crypto/openssl/ssl/ssl.h',
+ 'crypto/openssl/ssl/ssl_locl.h',
+ 'crypto/openssl/ssl/tls1.h',
]
)
self.addUserSpaceSourceFiles(
@@ -4333,118 +4361,56 @@ class usr_sbin_wpa_supplicant(builder.Module):
mm = self.manager
self.addUserSpaceHeaderFiles(
[
- 'contrib/wpa/wpa_supplicant/ap.h',
- 'contrib/wpa/wpa_supplicant/blacklist.h',
- 'contrib/wpa/wpa_supplicant/bss.h',
- 'contrib/wpa/wpa_supplicant/config.h',
- 'contrib/wpa/wpa_supplicant/config_ssid.h',
- 'contrib/wpa/wpa_supplicant/ctrl_iface.h',
- 'contrib/wpa/wpa_supplicant/driver_i.h',
- 'contrib/wpa/wpa_supplicant/gas_query.h',
- 'contrib/wpa/wpa_supplicant/hs20_supplicant.h',
- 'contrib/wpa/wpa_supplicant/interworking.h',
- 'contrib/wpa/wpa_supplicant/mesh.h',
- 'contrib/wpa/wpa_supplicant/mesh_mpm.h',
- 'contrib/wpa/wpa_supplicant/mesh_rsn.h',
- 'contrib/wpa/wpa_supplicant/notify.h',
- 'contrib/wpa/wpa_supplicant/offchannel.h',
- 'contrib/wpa/wpa_supplicant/scan.h',
- 'contrib/wpa/wpa_supplicant/autoscan.h',
- 'contrib/wpa/wpa_supplicant/wmm_ac.h',
- 'contrib/wpa/wpa_supplicant/wnm_sta.h',
- 'contrib/wpa/wpa_supplicant/wpas_glue.h',
- 'contrib/wpa/wpa_supplicant/wpas_kay.h',
- 'contrib/wpa/wpa_supplicant/wpa_supplicant_i.h',
- 'contrib/wpa/wpa_supplicant/wps_supplicant.h',
- 'contrib/wpa/wpa_supplicant/ibss_rsn.h',
- 'contrib/wpa/wpa_supplicant/p2p_supplicant.h',
- 'contrib/wpa/wpa_supplicant/wifi_display.h',
- 'contrib/wpa/wpa_supplicant/sme.h',
- 'contrib/wpa/wpa_supplicant/bgscan.h',
- 'contrib/wpa/wpa_supplicant/dbus/dbus_common.h',
- 'contrib/wpa/wpa_supplicant/dbus/dbus_old.h',
- 'contrib/wpa/wpa_supplicant/dbus/dbus_new.h',
'contrib/wpa/src/ap/ap_config.h',
'contrib/wpa/src/ap/ap_drv_ops.h',
- 'contrib/wpa/src/ap/hs20.h',
'contrib/wpa/src/ap/hostapd.h',
- 'contrib/wpa/src/ap/ieee802_11.h',
+ 'contrib/wpa/src/ap/hs20.h',
'contrib/wpa/src/ap/ieee802_11_auth.h',
+ 'contrib/wpa/src/ap/ieee802_11.h',
'contrib/wpa/src/ap/p2p_hostapd.h',
'contrib/wpa/src/ap/pmksa_cache_auth.h',
'contrib/wpa/src/ap/sta_info.h',
+ 'contrib/wpa/src/ap/vlan.h',
+ 'contrib/wpa/src/ap/wmm.h',
'contrib/wpa/src/ap/wpa_auth.h',
- 'contrib/wpa/src/ap/wpa_auth_i.h',
'contrib/wpa/src/ap/wpa_auth_ie.h',
- 'contrib/wpa/src/ap/wmm.h',
- 'contrib/wpa/src/utils/includes.h',
- 'contrib/wpa/src/utils/base64.h',
- 'contrib/wpa/src/utils/bitfield.h',
- 'contrib/wpa/src/utils/build_config.h',
- 'contrib/wpa/src/utils/common.h',
- 'contrib/wpa/src/utils/eloop.h',
- 'contrib/wpa/src/utils/ip_addr.h',
- 'contrib/wpa/src/utils/list.h',
- 'contrib/wpa/src/utils/os.h',
- 'contrib/wpa/src/utils/platform.h',
- 'contrib/wpa/src/utils/uuid.h',
- 'contrib/wpa/src/utils/wpa_debug.h',
- 'contrib/wpa/src/utils/wpabuf.h',
- 'contrib/wpa/src/utils/trace.h',
- 'contrib/wpa/src/utils/pcsc_funcs.h',
- 'contrib/wpa/src/utils/ext_password.h',
- 'contrib/wpa/src/utils/state_machine.h',
+ 'contrib/wpa/src/ap/wpa_auth_i.h',
+ 'contrib/wpa/src/common/ctrl_iface_common.h',
+ 'contrib/wpa/src/common/defs.h',
+ 'contrib/wpa/src/common/eapol_common.h',
'contrib/wpa/src/common/gas.h',
'contrib/wpa/src/common/hw_features_common.h',
'contrib/wpa/src/common/ieee802_11_common.h',
'contrib/wpa/src/common/ieee802_11_defs.h',
- 'contrib/wpa/src/common/wpa_common.h',
- 'contrib/wpa/src/common/defs.h',
'contrib/wpa/src/common/qca-vendor.h',
- 'contrib/wpa/src/common/eapol_common.h',
'contrib/wpa/src/common/sae.h',
- 'contrib/wpa/src/common/wpa_ctrl.h',
'contrib/wpa/src/common/version.h',
- 'contrib/wpa/src/drivers/driver.h',
- 'contrib/wpa/src/drivers/driver_ndis.h',
- 'contrib/wpa/src/drivers/driver_nl80211.h',
- 'contrib/wpa/src/drivers/linux_defines.h',
- 'contrib/wpa/src/wps/http.h',
- 'contrib/wpa/src/wps/http_client.h',
- 'contrib/wpa/src/wps/http_server.h',
- 'contrib/wpa/src/wps/httpread.h',
- 'contrib/wpa/src/wps/wps.h',
- 'contrib/wpa/src/wps/wps_i.h',
- 'contrib/wpa/src/wps/wps_defs.h',
- 'contrib/wpa/src/wps/upnp_xml.h',
- 'contrib/wpa/src/wps/wps_attr_parse.h',
- 'contrib/wpa/src/wps/wps_dev_attr.h',
- 'contrib/wpa/src/wps/wps_er.h',
- 'contrib/wpa/src/wps/wps_upnp.h',
- 'contrib/wpa/src/wps/wps_upnp_i.h',
- 'contrib/wpa/src/l2_packet/l2_packet.h',
- 'contrib/wpa/src/rsn_supp/peerkey.h',
- 'contrib/wpa/src/rsn_supp/pmksa_cache.h',
- 'contrib/wpa/src/rsn_supp/preauth.h',
- 'contrib/wpa/src/rsn_supp/wpa.h',
- 'contrib/wpa/src/rsn_supp/wpa_i.h',
- 'contrib/wpa/src/rsn_supp/wpa_ie.h',
- 'contrib/wpa/src/p2p/p2p.h',
- 'contrib/wpa/src/fst/fst.h',
- 'contrib/wpa/src/fst/fst_ctrl_iface.h',
- 'contrib/wpa/src/fst/fst_ctrl_aux.h',
- 'contrib/wpa/src/crypto/md5.h',
- 'contrib/wpa/src/crypto/sha256.h',
- 'contrib/wpa/src/crypto/sha384.h',
+ 'contrib/wpa/src/common/wpa_common.h',
+ 'contrib/wpa/src/common/wpa_ctrl.h',
+ 'contrib/wpa/src/crypto/aes.h',
'contrib/wpa/src/crypto/aes_wrap.h',
'contrib/wpa/src/crypto/crypto.h',
- 'contrib/wpa/src/crypto/random.h',
'contrib/wpa/src/crypto/dh_group5.h',
- 'contrib/wpa/src/crypto/sha1.h',
- 'contrib/wpa/src/crypto/tls.h',
+ 'contrib/wpa/src/crypto/md5.h',
'contrib/wpa/src/crypto/ms_funcs.h',
- 'contrib/wpa/src/crypto/aes.h',
+ 'contrib/wpa/src/crypto/random.h',
+ 'contrib/wpa/src/crypto/sha1.h',
+ 'contrib/wpa/src/crypto/sha256.h',
'contrib/wpa/src/crypto/sha256_i.h',
+ 'contrib/wpa/src/crypto/sha384.h',
+ 'contrib/wpa/src/crypto/tls.h',
+ 'contrib/wpa/src/drivers/driver.h',
+ 'contrib/wpa/src/drivers/driver_ndis.h',
+ 'contrib/wpa/src/drivers/driver_nl80211.h',
+ 'contrib/wpa/src/drivers/linux_defines.h',
+ 'contrib/wpa/src/eap_common/chap.h',
+ 'contrib/wpa/src/eap_common/eap_common.h',
+ 'contrib/wpa/src/eap_common/eap_defs.h',
+ 'contrib/wpa/src/eap_common/eap_peap_common.h',
+ 'contrib/wpa/src/eap_common/eap_psk_common.h',
+ 'contrib/wpa/src/eap_common/eap_tlv_common.h',
+ 'contrib/wpa/src/eap_common/eap_ttls.h',
+ 'contrib/wpa/src/eap_common/eap_wsc_common.h',
'contrib/wpa/src/eapol_auth/eapol_auth_sm.h',
'contrib/wpa/src/eapol_supp/eapol_supp_sm.h',
'contrib/wpa/src/eap_peer/eap_config.h',
@@ -4452,25 +4418,90 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/eap_peer/eap_i.h',
'contrib/wpa/src/eap_peer/eap_methods.h',
'contrib/wpa/src/eap_peer/eap_proxy.h',
+ 'contrib/wpa/src/eap_peer/eap_tls_common.h',
'contrib/wpa/src/eap_peer/mschapv2.h',
'contrib/wpa/src/eap_peer/tncc.h',
- 'contrib/wpa/src/eap_peer/eap_tls_common.h',
- 'contrib/wpa/src/eap_common/eap_defs.h',
- 'contrib/wpa/src/eap_common/eap_wsc_common.h',
- 'contrib/wpa/src/eap_common/eap_peap_common.h',
- 'contrib/wpa/src/eap_common/eap_psk_common.h',
- 'contrib/wpa/src/eap_common/eap_tlv_common.h',
- 'contrib/wpa/src/eap_common/eap_common.h',
- 'contrib/wpa/src/eap_common/chap.h',
- 'contrib/wpa/src/eap_common/eap_ttls.h',
'contrib/wpa/src/eap_server/eap_methods.h',
- 'contrib/wpa/src/eapol_supp/eapol_supp_sm.h',
+ 'contrib/wpa/src/fst/fst_ctrl_aux.h',
+ 'contrib/wpa/src/fst/fst_ctrl_iface.h',
+ 'contrib/wpa/src/fst/fst.h',
+ 'contrib/wpa/src/l2_packet/l2_packet.h',
+ 'contrib/wpa/src/p2p/p2p.h',
'contrib/wpa/src/radius/radius.h',
+ 'contrib/wpa/src/rsn_supp/peerkey.h',
+ 'contrib/wpa/src/rsn_supp/pmksa_cache.h',
+ 'contrib/wpa/src/rsn_supp/preauth.h',
+ 'contrib/wpa/src/rsn_supp/wpa.h',
+ 'contrib/wpa/src/rsn_supp/wpa_ie.h',
+ 'contrib/wpa/src/rsn_supp/wpa_i.h',
'contrib/wpa/src/tls/tlsv1_client.h',
'contrib/wpa/src/tls/tlsv1_cred.h',
'contrib/wpa/src/tls/tlsv1_server.h',
- 'usr.sbin/wpa/wpa_supplicant/Packet32.h',
+ 'contrib/wpa/src/utils/base64.h',
+ 'contrib/wpa/src/utils/bitfield.h',
+ 'contrib/wpa/src/utils/build_config.h',
+ 'contrib/wpa/src/utils/common.h',
+ 'contrib/wpa/src/utils/eloop.h',
+ 'contrib/wpa/src/utils/ext_password.h',
+ 'contrib/wpa/src/utils/includes.h',
+ 'contrib/wpa/src/utils/ip_addr.h',
+ 'contrib/wpa/src/utils/list.h',
+ 'contrib/wpa/src/utils/module_tests.h',
+ 'contrib/wpa/src/utils/os.h',
+ 'contrib/wpa/src/utils/pcsc_funcs.h',
+ 'contrib/wpa/src/utils/platform.h',
+ 'contrib/wpa/src/utils/state_machine.h',
+ 'contrib/wpa/src/utils/trace.h',
+ 'contrib/wpa/src/utils/uuid.h',
+ 'contrib/wpa/src/utils/wpabuf.h',
+ 'contrib/wpa/src/utils/wpa_debug.h',
+ 'contrib/wpa/src/wps/http_client.h',
+ 'contrib/wpa/src/wps/http.h',
+ 'contrib/wpa/src/wps/httpread.h',
+ 'contrib/wpa/src/wps/http_server.h',
+ 'contrib/wpa/src/wps/upnp_xml.h',
+ 'contrib/wpa/src/wps/wps_attr_parse.h',
+ 'contrib/wpa/src/wps/wps_defs.h',
+ 'contrib/wpa/src/wps/wps_dev_attr.h',
+ 'contrib/wpa/src/wps/wps_er.h',
+ 'contrib/wpa/src/wps/wps.h',
+ 'contrib/wpa/src/wps/wps_i.h',
+ 'contrib/wpa/src/wps/wps_upnp.h',
+ 'contrib/wpa/src/wps/wps_upnp_i.h',
+ 'contrib/wpa/wpa_supplicant/ap.h',
+ 'contrib/wpa/wpa_supplicant/autoscan.h',
+ 'contrib/wpa/wpa_supplicant/bgscan.h',
+ 'contrib/wpa/wpa_supplicant/binder/binder.h',
+ 'contrib/wpa/wpa_supplicant/blacklist.h',
+ 'contrib/wpa/wpa_supplicant/bss.h',
+ 'contrib/wpa/wpa_supplicant/config.h',
+ 'contrib/wpa/wpa_supplicant/config_ssid.h',
+ 'contrib/wpa/wpa_supplicant/ctrl_iface.h',
+ 'contrib/wpa/wpa_supplicant/dbus/dbus_common.h',
+ 'contrib/wpa/wpa_supplicant/dbus/dbus_new.h',
+ 'contrib/wpa/wpa_supplicant/dbus/dbus_old.h',
+ 'contrib/wpa/wpa_supplicant/driver_i.h',
+ 'contrib/wpa/wpa_supplicant/gas_query.h',
+ 'contrib/wpa/wpa_supplicant/hs20_supplicant.h',
+ 'contrib/wpa/wpa_supplicant/ibss_rsn.h',
+ 'contrib/wpa/wpa_supplicant/interworking.h',
+ 'contrib/wpa/wpa_supplicant/mesh.h',
+ 'contrib/wpa/wpa_supplicant/mesh_mpm.h',
+ 'contrib/wpa/wpa_supplicant/mesh_rsn.h',
+ 'contrib/wpa/wpa_supplicant/notify.h',
+ 'contrib/wpa/wpa_supplicant/offchannel.h',
+ 'contrib/wpa/wpa_supplicant/p2p_supplicant.h',
+ 'contrib/wpa/wpa_supplicant/scan.h',
+ 'contrib/wpa/wpa_supplicant/sme.h',
+ 'contrib/wpa/wpa_supplicant/wifi_display.h',
+ 'contrib/wpa/wpa_supplicant/wmm_ac.h',
+ 'contrib/wpa/wpa_supplicant/wnm_sta.h',
+ 'contrib/wpa/wpa_supplicant/wpas_glue.h',
+ 'contrib/wpa/wpa_supplicant/wpas_kay.h',
+ 'contrib/wpa/wpa_supplicant/wpa_supplicant_i.h',
+ 'contrib/wpa/wpa_supplicant/wps_supplicant.h',
'usr.sbin/wpa/wpa_supplicant/ntddndis.h',
+ 'usr.sbin/wpa/wpa_supplicant/Packet32.h',
]
)
self.addUserSpaceSourceFiles(
@@ -4506,6 +4537,7 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/utils/uuid.c',
'contrib/wpa/src/utils/wpa_debug.c',
'contrib/wpa/src/utils/wpabuf.c',
+ 'contrib/wpa/src/common/ctrl_iface_common.c',
'contrib/wpa/src/common/gas.c',
'contrib/wpa/src/common/hw_features_common.c',
'contrib/wpa/src/common/ieee802_11_common.c',
diff --git a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
index f0c4ceb0..0a63324b 100644
--- a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
+++ b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
@@ -58,6 +58,7 @@
#define auth_hash_hmac_md5 _bsd_auth_hash_hmac_md5
#define auth_hash_hmac_ripemd_160 _bsd_auth_hash_hmac_ripemd_160
#define auth_hash_hmac_sha1 _bsd_auth_hash_hmac_sha1
+#define auth_hash_hmac_sha2_224 _bsd_auth_hash_hmac_sha2_224
#define auth_hash_hmac_sha2_256 _bsd_auth_hash_hmac_sha2_256
#define auth_hash_hmac_sha2_384 _bsd_auth_hash_hmac_sha2_384
#define auth_hash_hmac_sha2_512 _bsd_auth_hash_hmac_sha2_512
@@ -67,6 +68,12 @@
#define auth_hash_nist_gmac_aes_192 _bsd_auth_hash_nist_gmac_aes_192
#define auth_hash_nist_gmac_aes_256 _bsd_auth_hash_nist_gmac_aes_256
#define auth_hash_null _bsd_auth_hash_null
+#define auth_hash_poly1305 _bsd_auth_hash_poly1305
+#define auth_hash_sha1 _bsd_auth_hash_sha1
+#define auth_hash_sha2_224 _bsd_auth_hash_sha2_224
+#define auth_hash_sha2_256 _bsd_auth_hash_sha2_256
+#define auth_hash_sha2_384 _bsd_auth_hash_sha2_384
+#define auth_hash_sha2_512 _bsd_auth_hash_sha2_512
#define badport_bandlim _bsd_badport_bandlim
#define bcd2bin_data _bsd_bcd2bin_data
#define bce_COM_b06FwBss _bsd_bce_COM_b06FwBss
@@ -575,6 +582,7 @@
#define crypto_freesession _bsd_crypto_freesession
#define crypto_getcaps _bsd_crypto_getcaps
#define crypto_get_driverid _bsd_crypto_get_driverid
+#define crypto_get_driver_session _bsd_crypto_get_driver_session
#define crypto_getfeat _bsd_crypto_getfeat
#define crypto_getreq _bsd_crypto_getreq
#define crypto_kdispatch _bsd_crypto_kdispatch
@@ -583,12 +591,31 @@
#define crypto_mbuftoiov _bsd_crypto_mbuftoiov
#define crypto_modevent _bsd_crypto_modevent
#define crypto_newsession _bsd_crypto_newsession
+#define crypto_onetimeauth_poly1305 _bsd_crypto_onetimeauth_poly1305
+#define crypto_onetimeauth_poly1305_bytes _bsd_crypto_onetimeauth_poly1305_bytes
+#define crypto_onetimeauth_poly1305_donna_implementation _bsd_crypto_onetimeauth_poly1305_donna_implementation
+#define crypto_onetimeauth_poly1305_final _bsd_crypto_onetimeauth_poly1305_final
+#define crypto_onetimeauth_poly1305_init _bsd_crypto_onetimeauth_poly1305_init
+#define crypto_onetimeauth_poly1305_keybytes _bsd_crypto_onetimeauth_poly1305_keybytes
+#define crypto_onetimeauth_poly1305_keygen _bsd_crypto_onetimeauth_poly1305_keygen
+#define _crypto_onetimeauth_poly1305_pick_best_implementation _bsd__crypto_onetimeauth_poly1305_pick_best_implementation
+#define crypto_onetimeauth_poly1305_statebytes _bsd_crypto_onetimeauth_poly1305_statebytes
+#define crypto_onetimeauth_poly1305_update _bsd_crypto_onetimeauth_poly1305_update
+#define crypto_onetimeauth_poly1305_verify _bsd_crypto_onetimeauth_poly1305_verify
#define crypto_register _bsd_crypto_register
+#define crypto_ses2caps _bsd_crypto_ses2caps
+#define crypto_ses2hid _bsd_crypto_ses2hid
#define crypto_support _bsd_crypto_support
#define crypto_unblock _bsd_crypto_unblock
#define crypto_unregister _bsd_crypto_unregister
#define crypto_unregister_all _bsd_crypto_unregister_all
#define crypto_userasymcrypto _bsd_crypto_userasymcrypto
+#define crypto_verify_16 _bsd_crypto_verify_16
+#define crypto_verify_16_bytes _bsd_crypto_verify_16_bytes
+#define crypto_verify_32 _bsd_crypto_verify_32
+#define crypto_verify_32_bytes _bsd_crypto_verify_32_bytes
+#define crypto_verify_64 _bsd_crypto_verify_64
+#define crypto_verify_64_bytes _bsd_crypto_verify_64_bytes
#define ctl_subtype_name _bsd_ctl_subtype_name
#define cuio_apply _bsd_cuio_apply
#define cuio_copyback _bsd_cuio_copyback
@@ -1069,10 +1096,6 @@
#define enc_algorithm_lookup _bsd_enc_algorithm_lookup
#define encap4_input _bsd_encap4_input
#define encap6_input _bsd_encap6_input
-#define encap_attach _bsd_encap_attach
-#define encap_attach_func _bsd_encap_attach_func
-#define encap_detach _bsd_encap_detach
-#define encap_getarg _bsd_encap_getarg
#define enc_xform_3des _bsd_enc_xform_3des
#define enc_xform_aes_icm _bsd_enc_xform_aes_icm
#define enc_xform_aes_nist_gcm _bsd_enc_xform_aes_nist_gcm
@@ -1117,11 +1140,11 @@
#define evdev_client_push _bsd_evdev_client_push
#define evdev_dispose_client _bsd_evdev_dispose_client
#define evdev_event_supported _bsd_evdev_event_supported
-#define evdev_ev_kbd_event _bsd_evdev_ev_kbd_event
#define evdev_free _bsd_evdev_free
#define evdev_get_last_mt_slot _bsd_evdev_get_last_mt_slot
#define evdev_get_mt_slot_by_tracking_id _bsd_evdev_get_mt_slot_by_tracking_id
#define evdev_get_mt_value _bsd_evdev_get_mt_value
+#define evdev_get_softc _bsd_evdev_get_softc
#define evdev_grab_client _bsd_evdev_grab_client
#define evdev_hid2key _bsd_evdev_hid2key
#define evdev_inject_event _bsd_evdev_inject_event
@@ -1236,6 +1259,8 @@
#define frag6_drain _bsd_frag6_drain
#define frag6_init _bsd_frag6_init
#define frag6_input _bsd_frag6_input
+#define frag6_nfrags _bsd_frag6_nfrags
+#define frag6_set_bucketsize _bsd_frag6_set_bucketsize
#define frag6_slowtimo _bsd_frag6_slowtimo
#define free_unr _bsd_free_unr
#define genkbd_commonioctl _bsd_genkbd_commonioctl
@@ -1269,7 +1294,8 @@
#define gf128_mul4 _bsd_gf128_mul4
#define gf128_mul4b _bsd_gf128_mul4b
#define Giant _bsd_Giant
-#define gif_encapcheck _bsd_gif_encapcheck
+#define gif_hashdestroy _bsd_gif_hashdestroy
+#define gif_hashinit _bsd_gif_hashinit
#define gif_input _bsd_gif_input
#define gif_output _bsd_gif_output
#define global_epoch _bsd_global_epoch
@@ -1285,7 +1311,10 @@
#define gpiobus_init_softc _bsd_gpiobus_init_softc
#define gpiobus_release_pin _bsd_gpiobus_release_pin
#define gpio_check_flags _bsd_gpio_check_flags
+#define gre_hashdestroy _bsd_gre_hashdestroy
+#define gre_hashinit _bsd_gre_hashinit
#define gre_input _bsd_gre_input
+#define gre_updatehdr _bsd_gre_updatehdr
#define grouptaskqueue_enqueue _bsd_grouptaskqueue_enqueue
#define gtaskqueue_block _bsd_gtaskqueue_block
#define gtaskqueue_cancel _bsd_gtaskqueue_cancel
@@ -1927,6 +1956,7 @@
#define if_simloop _bsd_if_simloop
#define if_start _bsd_if_start
#define if_togglecapenable _bsd_if_togglecapenable
+#define if_tunnel_check_nesting _bsd_if_tunnel_check_nesting
#define ifunit _bsd_ifunit
#define ifunit_ref _bsd_ifunit_ref
#define if_up _bsd_if_up
@@ -1965,9 +1995,11 @@
#define in6_getscopezone _bsd_in6_getscopezone
#define in6_getsockaddr _bsd_in6_getsockaddr
#define in6_get_tmpifid _bsd_in6_get_tmpifid
-#define in6_gif_attach _bsd_in6_gif_attach
-#define in6_gif_encapcheck _bsd_in6_gif_encapcheck
+#define in6_gif_init _bsd_in6_gif_init
+#define in6_gif_ioctl _bsd_in6_gif_ioctl
#define in6_gif_output _bsd_in6_gif_output
+#define in6_gif_setopts _bsd_in6_gif_setopts
+#define in6_gif_uninit _bsd_in6_gif_uninit
#define in6_if2idlen _bsd_in6_if2idlen
#define in6_ifaddrhashtbl _bsd_in6_ifaddrhashtbl
#define in6_ifaddrhead _bsd_in6_ifaddrhead
@@ -2078,11 +2110,16 @@
#define inetsw _bsd_inetsw
#define in_getpeeraddr _bsd_in_getpeeraddr
#define in_getsockaddr _bsd_in_getsockaddr
-#define in_gif_attach _bsd_in_gif_attach
-#define in_gif_encapcheck _bsd_in_gif_encapcheck
+#define in_gif_init _bsd_in_gif_init
+#define in_gif_ioctl _bsd_in_gif_ioctl
#define in_gif_output _bsd_in_gif_output
-#define in_gre_attach _bsd_in_gre_attach
+#define in_gif_setopts _bsd_in_gif_setopts
+#define in_gif_uninit _bsd_in_gif_uninit
+#define in_gre_init _bsd_in_gre_init
+#define in_gre_ioctl _bsd_in_gre_ioctl
#define in_gre_output _bsd_in_gre_output
+#define in_gre_setopts _bsd_in_gre_setopts
+#define in_gre_uninit _bsd_in_gre_uninit
#define in_ifaddr_broadcast _bsd_in_ifaddr_broadcast
#define in_ifaddrhashtbl _bsd_in_ifaddrhashtbl
#define in_ifaddrhead _bsd_in_ifaddrhead
@@ -2161,6 +2198,7 @@
#define inp_setmoptions _bsd_inp_setmoptions
#define in_pseudo _bsd_in_pseudo
#define inp_so_options _bsd_inp_so_options
+#define inp_to_cpuid _bsd_inp_to_cpuid
#define inp_wlock _bsd_inp_wlock
#define inp_wunlock _bsd_inp_wunlock
#define in_rtalloc_ign _bsd_in_rtalloc_ign
@@ -2169,7 +2207,6 @@
#define in_sockaddr _bsd_in_sockaddr
#define intr_event_add_handler _bsd_intr_event_add_handler
#define intr_event_create _bsd_intr_event_create
-#define intr_event_execute_handlers _bsd_intr_event_execute_handlers
#define ip4_ah_net_deflev _bsd_ip4_ah_net_deflev
#define ip4_ah_trans_deflev _bsd_ip4_ah_trans_deflev
#define ip4_esp_net_deflev _bsd_ip4_esp_net_deflev
@@ -2191,6 +2228,8 @@
#define ip6_desync_factor _bsd_ip6_desync_factor
#define ip6_ecn_egress _bsd_ip6_ecn_egress
#define ip6_ecn_ingress _bsd_ip6_ecn_ingress
+#define ip6_encap_attach _bsd_ip6_encap_attach
+#define ip6_encap_detach _bsd_ip6_encap_detach
#define ip6_esp_net_deflev _bsd_ip6_esp_net_deflev
#define ip6_esp_trans_deflev _bsd_ip6_esp_trans_deflev
#define ip6_forward _bsd_ip6_forward
@@ -2208,8 +2247,10 @@
#define ip6_lasthdr _bsd_ip6_lasthdr
#define ip6_log_interval _bsd_ip6_log_interval
#define ip6_log_time _bsd_ip6_log_time
+#define ip6_maxfragbucketsize _bsd_ip6_maxfragbucketsize
#define ip6_maxfragpackets _bsd_ip6_maxfragpackets
#define ip6_maxfrags _bsd_ip6_maxfrags
+#define ip6_maxfragsperpacket _bsd_ip6_maxfragsperpacket
#define ip6_mcast_pmtu _bsd_ip6_mcast_pmtu
#define ip6_mforward _bsd_ip6_mforward
#define ip6_mloopback _bsd_ip6_mloopback
@@ -2271,6 +2312,8 @@
#define ip_drain _bsd_ip_drain
#define ip_ecn_egress _bsd_ip_ecn_egress
#define ip_ecn_ingress _bsd_ip_ecn_ingress
+#define ip_encap_attach _bsd_ip_encap_attach
+#define ip_encap_detach _bsd_ip_encap_detach
#define ip_fillid _bsd_ip_fillid
#define ip_forward _bsd_ip_forward
#define ipforwarding _bsd_ipforwarding
@@ -2390,6 +2433,7 @@
#define kbd_configure _bsd_kbd_configure
#define kbd_delete_driver _bsd_kbd_delete_driver
#define kbd_detach _bsd_kbd_detach
+#define kbd_ev_event _bsd_kbd_ev_event
#define kbd_find_keyboard _bsd_kbd_find_keyboard
#define kbd_find_keyboard2 _bsd_kbd_find_keyboard2
#define kbd_get_keyboard _bsd_kbd_get_keyboard
@@ -2556,6 +2600,9 @@
#define LibAliasSetTarget _bsd_LibAliasSetTarget
#define LibAliasUnaliasOut _bsd_LibAliasUnaliasOut
#define LibAliasUninit _bsd_LibAliasUninit
+#define _libmd_SHA224_Final _bsd__libmd_SHA224_Final
+#define _libmd_SHA224_Init _bsd__libmd_SHA224_Init
+#define _libmd_SHA224_Update _bsd__libmd_SHA224_Update
#define _libmd_SHA512_224_Final _bsd__libmd_SHA512_224_Final
#define _libmd_SHA512_224_Init _bsd__libmd_SHA512_224_Init
#define _libmd_SHA512_224_Update _bsd__libmd_SHA512_224_Update
@@ -2660,6 +2707,7 @@
#define m_demote_pkthdr _bsd_m_demote_pkthdr
#define M_DEVBUF _bsd_M_DEVBUF
#define m_devget _bsd_m_devget
+#define m_dispose_extcontrolm _bsd_m_dispose_extcontrolm
#define m_dup _bsd_m_dup
#define m_dup_pkthdr _bsd_m_dup_pkthdr
#define mesh_airtime_calc _bsd_mesh_airtime_calc
@@ -2673,6 +2721,8 @@
#define m_getjcl _bsd_m_getjcl
#define m_getm2 _bsd_m_getm2
#define m_getptr _bsd_m_getptr
+#define M_GIF _bsd_M_GIF
+#define M_GRE _bsd_M_GRE
#define mgt_subtype_name _bsd_mgt_subtype_name
#define M_IFADDR _bsd_M_IFADDR
#define M_IFMADDR _bsd_M_IFMADDR
@@ -3069,6 +3119,7 @@
#define pci_get_vpd_readonly_method _bsd_pci_get_vpd_readonly_method
#define pci_ht_map_msi _bsd_pci_ht_map_msi
#define pci_mapsize _bsd_pci_mapsize
+#define pci_match_device _bsd_pci_match_device
#define pci_msi_count_method _bsd_pci_msi_count_method
#define pci_msi_device_blacklisted _bsd_pci_msi_device_blacklisted
#define pci_msix_count_method _bsd_pci_msix_count_method
@@ -3078,6 +3129,7 @@
#define pci_numdevs _bsd_pci_numdevs
#define pci_pending_msix _bsd_pci_pending_msix
#define pci_print_child _bsd_pci_print_child
+#define pci_print_faulted_dev _bsd_pci_print_faulted_dev
#define pci_print_verbose _bsd_pci_print_verbose
#define pci_probe_nomatch _bsd_pci_probe_nomatch
#define pci_read_bar _bsd_pci_read_bar
@@ -3344,14 +3396,16 @@
#define pgsigio _bsd_pgsigio
#define phashinit _bsd_phashinit
#define phashinit_flags _bsd_phashinit_flags
-#define pim6_input _bsd_pim6_input
-#define pim_input _bsd_pim_input
#define pipe_dtor _bsd_pipe_dtor
#define pipe_named_ctor _bsd_pipe_named_ctor
#define pipeselwakeup _bsd_pipeselwakeup
#define pmtu_expire _bsd_pmtu_expire
#define pmtu_probe _bsd_pmtu_probe
#define poll_no_poll _bsd_poll_no_poll
+#define Poly1305_Final _bsd_Poly1305_Final
+#define Poly1305_Init _bsd_Poly1305_Init
+#define Poly1305_Setkey _bsd_Poly1305_Setkey
+#define Poly1305_Update _bsd_Poly1305_Update
#define ppsratecheck _bsd_ppsratecheck
#define preload_addr_relocate _bsd_preload_addr_relocate
#define preload_bootstrap_relocate _bsd_preload_bootstrap_relocate
@@ -3461,6 +3515,7 @@
#define r12au_init_ampdu _bsd_r12au_init_ampdu
#define r12au_init_ampdu_fwhw _bsd_r12au_init_ampdu_fwhw
#define r12au_init_burstlen _bsd_r12au_init_burstlen
+#define r12au_init_burstlen_usb2 _bsd_r12au_init_burstlen_usb2
#define r12au_init_rx_agg _bsd_r12au_init_rx_agg
#define r12au_post_init _bsd_r12au_post_init
#define r12a_vap_preattach _bsd_r12a_vap_preattach
@@ -3482,7 +3537,6 @@
#define r21a_set_led _bsd_r21a_set_led
#define r21au_attach _bsd_r21au_attach
#define r21au_chan_check _bsd_r21au_chan_check
-#define r21au_init_burstlen _bsd_r21au_init_burstlen
#define r21au_init_tx_agg _bsd_r21au_init_tx_agg
#define r21au_newstate _bsd_r21au_newstate
#define r21au_scan_end _bsd_r21au_scan_end
@@ -3912,6 +3966,8 @@
#define sbsetopt _bsd_sbsetopt
#define sbsndmbuf _bsd_sbsndmbuf
#define sbsndptr _bsd_sbsndptr
+#define sbsndptr_adv _bsd_sbsndptr_adv
+#define sbsndptr_noadv _bsd_sbsndptr_noadv
#define sbtoxsockbuf _bsd_sbtoxsockbuf
#define sbt_tickthreshold _bsd_sbt_tickthreshold
#define sbt_timethreshold _bsd_sbt_timethreshold
@@ -4032,6 +4088,7 @@
#define sctp_addr_mgmt_ep_sa _bsd_sctp_addr_mgmt_ep_sa
#define sctp_add_stream_reset_result _bsd_sctp_add_stream_reset_result
#define sctp_add_stream_reset_result_tsn _bsd_sctp_add_stream_reset_result_tsn
+#define sctp_add_substate _bsd_sctp_add_substate
#define sctp_add_to_readq _bsd_sctp_add_to_readq
#define sctp_add_vtag_to_timewait _bsd_sctp_add_vtag_to_timewait
#define SctpAlias _bsd_SctpAlias
@@ -4296,6 +4353,7 @@
#define sctp_set_primary_addr _bsd_sctp_set_primary_addr
#define sctp_set_primary_ip_address_sa _bsd_sctp_set_primary_ip_address_sa
#define sctp_set_rwnd _bsd_sctp_set_rwnd
+#define sctp_set_state _bsd_sctp_set_state
#define SctpShowAliasStats _bsd_SctpShowAliasStats
#define sctp_show_key _bsd_sctp_show_key
#define sctp_shutdown _bsd_sctp_shutdown
@@ -4480,6 +4538,8 @@
#define soconnectat _bsd_soconnectat
#define socreate _bsd_socreate
#define sodisconnect _bsd_sodisconnect
+#define sodium_memzero _bsd_sodium_memzero
+#define sodtor_set _bsd_sodtor_set
#define sodupsockaddr _bsd_sodupsockaddr
#define so_error_get _bsd_so_error_get
#define so_error_set _bsd_so_error_set
@@ -4708,7 +4768,6 @@
#define taskqgroup_detach _bsd_taskqgroup_detach
#define TB_DRAIN_WAITER _bsd_TB_DRAIN_WAITER
#define tbr_dequeue_ptr _bsd_tbr_dequeue_ptr
-#define tbr_get _bsd_tbr_get
#define tbr_set _bsd_tbr_set
#define tcb _bsd_tcb
#define tcbinfo _bsd_tcbinfo
@@ -4764,7 +4823,6 @@
#define tcp_hc_updatemtu _bsd_tcp_hc_updatemtu
#define tcp_init _bsd_tcp_init
#define tcp_initcwnd_segments _bsd_tcp_initcwnd_segments
-#define tcp_inpinfo_lock_add _bsd_tcp_inpinfo_lock_add
#define tcp_inpinfo_lock_del _bsd_tcp_inpinfo_lock_del
#define tcp_inptoxtp _bsd_tcp_inptoxtp
#define tcp_input _bsd_tcp_input
@@ -4792,6 +4850,7 @@
#define tcp_maxmtu6 _bsd_tcp_maxmtu6
#define tcp_maxpersistidle _bsd_tcp_maxpersistidle
#define tcp_maxseg _bsd_tcp_maxseg
+#define tcp_m_copym _bsd_tcp_m_copym
#define tcp_minmss _bsd_tcp_minmss
#define tcp_msl _bsd_tcp_msl
#define tcp_mss _bsd_tcp_mss
@@ -4801,6 +4860,7 @@
#define tcp_new_isn _bsd_tcp_new_isn
#define tcp_newreno_partial_ack _bsd_tcp_newreno_partial_ack
#define tcp_newtcpcb _bsd_tcp_newtcpcb
+#define tcp_new_ts_offset _bsd_tcp_new_ts_offset
#define tcp_offload_connect _bsd_tcp_offload_connect
#define tcp_offload_ctloutput _bsd_tcp_offload_ctloutput
#define tcp_offload_detach _bsd_tcp_offload_detach
@@ -4820,6 +4880,7 @@
#define tc_precexp _bsd_tc_precexp
#define tcp_recvspace _bsd_tcp_recvspace
#define tcp_respond _bsd_tcp_respond
+#define tcp_rexmit_drop_options _bsd_tcp_rexmit_drop_options
#define tcp_rexmit_min _bsd_tcp_rexmit_min
#define tcp_rexmit_slop _bsd_tcp_rexmit_slop
#define tcprexmtthresh _bsd_tcprexmtthresh
@@ -4850,6 +4911,9 @@
#define tcp_timer_persist _bsd_tcp_timer_persist
#define tcp_timer_rexmt _bsd_tcp_timer_rexmt
#define tcp_timer_stop _bsd_tcp_timer_stop
+#define tcp_timers_unsuspend _bsd_tcp_timers_unsuspend
+#define tcp_timer_suspend _bsd_tcp_timer_suspend
+#define tcp_totbackoff _bsd_tcp_totbackoff
#define tcp_trace _bsd_tcp_trace
#define tcp_tw_2msl_scan _bsd_tcp_tw_2msl_scan
#define tcp_twcheck _bsd_tcp_twcheck
@@ -5046,11 +5110,13 @@
#define uma_startup _bsd_uma_startup
#define uma_zalloc_arg _bsd_uma_zalloc_arg
#define uma_zalloc_domain _bsd_uma_zalloc_domain
+#define uma_zalloc_pcpu_arg _bsd_uma_zalloc_pcpu_arg
#define uma_zcache_create _bsd_uma_zcache_create
#define uma_zcreate _bsd_uma_zcreate
#define uma_zdestroy _bsd_uma_zdestroy
#define uma_zfree_arg _bsd_uma_zfree_arg
#define uma_zfree_domain _bsd_uma_zfree_domain
+#define uma_zfree_pcpu_arg _bsd_uma_zfree_pcpu_arg
#define uma_zone_exhausted _bsd_uma_zone_exhausted
#define uma_zone_exhausted_nolock _bsd_uma_zone_exhausted_nolock
#define uma_zone_get_cur _bsd_uma_zone_get_cur
@@ -5067,6 +5133,7 @@
#define uma_zone_set_zinit _bsd_uma_zone_set_zinit
#define uma_zsecond_create _bsd_uma_zsecond_create
#define uma_zwait _bsd_uma_zwait
+#define unp_copy_peercred _bsd_unp_copy_peercred
#define untimeout _bsd_untimeout
#define usb_alloc_device _bsd_usb_alloc_device
#define usb_alloc_mbufs _bsd_usb_alloc_mbufs
@@ -5353,6 +5420,7 @@
#define vlan_input_p _bsd_vlan_input_p
#define vlan_link_state_p _bsd_vlan_link_state_p
#define vlan_mtag_pcp _bsd_vlan_mtag_pcp
+#define vlan_pcp_p _bsd_vlan_pcp_p
#define vlan_setcookie_p _bsd_vlan_setcookie_p
#define vlan_tag_p _bsd_vlan_tag_p
#define vlan_trunk_cap_p _bsd_vlan_trunk_cap_p
diff --git a/rtemsbsd/include/rtems/bsd/local/cryptodev_if.h b/rtemsbsd/include/rtems/bsd/local/cryptodev_if.h
index 752527ed..a789317b 100644
--- a/rtemsbsd/include/rtems/bsd/local/cryptodev_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/cryptodev_if.h
@@ -17,27 +17,43 @@
/** @brief Unique descriptor for the CRYPTODEV_NEWSESSION() method */
extern struct kobjop_desc cryptodev_newsession_desc;
/** @brief A function implementing the CRYPTODEV_NEWSESSION() method */
-typedef int cryptodev_newsession_t(device_t dev, uint32_t *sid,
+typedef int cryptodev_newsession_t(device_t dev,
+ crypto_session_t crypto_session,
struct cryptoini *cri);
+/**
+ * Crypto driver method to initialize a new session object with the given
+ * initialization parameters (cryptoini). The driver's session memory object
+ * is already allocated and zeroed, like driver softcs. It is accessed with
+ * crypto_get_driver_session().
+ */
-static __inline int CRYPTODEV_NEWSESSION(device_t dev, uint32_t *sid,
+static __inline int CRYPTODEV_NEWSESSION(device_t dev,
+ crypto_session_t crypto_session,
struct cryptoini *cri)
{
kobjop_t _m;
+ int rc;
KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_newsession);
- return ((cryptodev_newsession_t *) _m)(dev, sid, cri);
+ rc = ((cryptodev_newsession_t *) _m)(dev, crypto_session, cri);
+ return (rc);
}
/** @brief Unique descriptor for the CRYPTODEV_FREESESSION() method */
extern struct kobjop_desc cryptodev_freesession_desc;
/** @brief A function implementing the CRYPTODEV_FREESESSION() method */
-typedef int cryptodev_freesession_t(device_t dev, uint64_t sid);
+typedef void cryptodev_freesession_t(device_t dev,
+ crypto_session_t crypto_session);
+/**
+ * Optional crypto driver method to release any additional allocations. OCF
+ * owns session memory itself; it is zeroed before release.
+ */
-static __inline int CRYPTODEV_FREESESSION(device_t dev, uint64_t sid)
+static __inline void CRYPTODEV_FREESESSION(device_t dev,
+ crypto_session_t crypto_session)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_freesession);
- return ((cryptodev_freesession_t *) _m)(dev, sid);
+ ((cryptodev_freesession_t *) _m)(dev, crypto_session);
}
/** @brief Unique descriptor for the CRYPTODEV_PROCESS() method */
@@ -49,8 +65,10 @@ static __inline int CRYPTODEV_PROCESS(device_t dev, struct cryptop *op,
int flags)
{
kobjop_t _m;
+ int rc;
KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_process);
- return ((cryptodev_process_t *) _m)(dev, op, flags);
+ rc = ((cryptodev_process_t *) _m)(dev, op, flags);
+ return (rc);
}
/** @brief Unique descriptor for the CRYPTODEV_KPROCESS() method */
@@ -62,8 +80,10 @@ static __inline int CRYPTODEV_KPROCESS(device_t dev, struct cryptkop *op,
int flags)
{
kobjop_t _m;
+ int rc;
KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_kprocess);
- return ((cryptodev_kprocess_t *) _m)(dev, op, flags);
+ rc = ((cryptodev_kprocess_t *) _m)(dev, op, flags);
+ return (rc);
}
#endif /* _cryptodev_if_h_ */
diff --git a/rtemsbsd/include/rtems/bsd/local/sdhci_if.h b/rtemsbsd/include/rtems/bsd/local/sdhci_if.h
index 531090f8..f8ee4fe4 100644
--- a/rtemsbsd/include/rtems/bsd/local/sdhci_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/sdhci_if.h
@@ -24,8 +24,10 @@ static __inline uint8_t SDHCI_READ_1(device_t brdev, struct sdhci_slot *slot,
bus_size_t off)
{
kobjop_t _m;
+ uint8_t rc;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,sdhci_read_1);
- return ((sdhci_read_1_t *) _m)(brdev, slot, off);
+ rc = ((sdhci_read_1_t *) _m)(brdev, slot, off);
+ return (rc);
}
/** @brief Unique descriptor for the SDHCI_READ_2() method */
@@ -38,8 +40,10 @@ static __inline uint16_t SDHCI_READ_2(device_t brdev, struct sdhci_slot *slot,
bus_size_t off)
{
kobjop_t _m;
+ uint16_t rc;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,sdhci_read_2);
- return ((sdhci_read_2_t *) _m)(brdev, slot, off);
+ rc = ((sdhci_read_2_t *) _m)(brdev, slot, off);
+ return (rc);
}
/** @brief Unique descriptor for the SDHCI_READ_4() method */
@@ -52,8 +56,10 @@ static __inline uint32_t SDHCI_READ_4(device_t brdev, struct sdhci_slot *slot,
bus_size_t off)
{
kobjop_t _m;
+ uint32_t rc;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,sdhci_read_4);
- return ((sdhci_read_4_t *) _m)(brdev, slot, off);
+ rc = ((sdhci_read_4_t *) _m)(brdev, slot, off);
+ return (rc);
}
/** @brief Unique descriptor for the SDHCI_READ_MULTI_4() method */
@@ -141,8 +147,10 @@ static __inline int SDHCI_PLATFORM_WILL_HANDLE(device_t brdev,
struct sdhci_slot *slot)
{
kobjop_t _m;
+ int rc;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,sdhci_platform_will_handle);
- return ((sdhci_platform_will_handle_t *) _m)(brdev, slot);
+ rc = ((sdhci_platform_will_handle_t *) _m)(brdev, slot);
+ return (rc);
}
/** @brief Unique descriptor for the SDHCI_PLATFORM_START_TRANSFER() method */
@@ -183,8 +191,10 @@ typedef uint32_t sdhci_min_freq_t(device_t brdev, struct sdhci_slot *slot);
static __inline uint32_t SDHCI_MIN_FREQ(device_t brdev, struct sdhci_slot *slot)
{
kobjop_t _m;
+ uint32_t rc;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,sdhci_min_freq);
- return ((sdhci_min_freq_t *) _m)(brdev, slot);
+ rc = ((sdhci_min_freq_t *) _m)(brdev, slot);
+ return (rc);
}
/** @brief Unique descriptor for the SDHCI_GET_CARD_PRESENT() method */
@@ -196,8 +206,10 @@ static __inline bool SDHCI_GET_CARD_PRESENT(device_t brdev,
struct sdhci_slot *slot)
{
kobjop_t _m;
+ bool rc;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,sdhci_get_card_present);
- return ((sdhci_get_card_present_t *) _m)(brdev, slot);
+ rc = ((sdhci_get_card_present_t *) _m)(brdev, slot);
+ return (rc);
}
/** @brief Unique descriptor for the SDHCI_SET_UHS_TIMING() method */
diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs.h b/rtemsbsd/include/rtems/bsd/local/usbdevs.h
index 5eee5c10..ce48f040 100644
--- a/rtemsbsd/include/rtems/bsd/local/usbdevs.h
+++ b/rtemsbsd/include/rtems/bsd/local/usbdevs.h
@@ -65,7 +65,7 @@
#define USB_VENDOR_EGALAX2 0x0123 /* eGalax, Inc. */
#define USB_VENDOR_CHIPSBANK 0x0204 /* Chipsbank Microelectronics Co. */
#define USB_VENDOR_HUMAX 0x02ad /* HUMAX */
-#define USB_VENDOR_INTENSO 0x2109 /* INTENSO */
+#define USB_VENDOR_QUAN 0x01e1 /* Quan */
#define USB_VENDOR_LTS 0x0386 /* LTS */
#define USB_VENDOR_BWCT 0x03da /* Bernd Walter Computer Technology */
#define USB_VENDOR_AOX 0x03e8 /* AOX */
@@ -97,7 +97,7 @@
#define USB_VENDOR_QUANTA 0x0408 /* Quanta */
#define USB_VENDOR_NEC 0x0409 /* NEC */
#define USB_VENDOR_KODAK 0x040a /* Eastman Kodak */
-#define USB_VENDOR_WELTREND 0x040b /* Weltrend */
+#define USB_VENDOR_WELTREND 0x040b /* Weltrend Semiconductor */
#define USB_VENDOR_VIA 0x040d /* VIA */
#define USB_VENDOR_MCCI 0x040e /* MCCI */
#define USB_VENDOR_MELCO 0x0411 /* Melco */
@@ -108,7 +108,7 @@
#define USB_VENDOR_NOKIA 0x0421 /* Nokia */
#define USB_VENDOR_ADI 0x0422 /* ADI Systems */
#define USB_VENDOR_CATC 0x0423 /* Computer Access Technology */
-#define USB_VENDOR_SMC2 0x0424 /* Standard Microsystems */
+#define USB_VENDOR_SMC2 0x0424 /* Microchip (Standard Microsystems) */
#define USB_VENDOR_MOTOROLA_HK 0x0425 /* Motorola HK */
#define USB_VENDOR_GRAVIS 0x0428 /* Advanced Gravis Computer */
#define USB_VENDOR_CIRRUSLOGIC 0x0429 /* Cirrus Logic */
@@ -150,7 +150,7 @@
#define USB_VENDOR_PLANTRONICS 0x047f /* Plantronics */
#define USB_VENDOR_KYOCERA 0x0482 /* Kyocera Wireless Corp. */
#define USB_VENDOR_STMICRO 0x0483 /* STMicroelectronics */
-#define USB_VENDOR_FOXCONN 0x0489 /* Foxconn */
+#define USB_VENDOR_FOXCONN 0x0489 /* Foxconn / Hon Hai */
#define USB_VENDOR_MEIZU 0x0492 /* Meizu Electronics */
#define USB_VENDOR_YAMAHA 0x0499 /* YAMAHA */
#define USB_VENDOR_COMPAQ 0x049f /* Compaq */
@@ -202,7 +202,7 @@
#define USB_VENDOR_ANNABOOKS 0x04ed /* Annabooks */
#define USB_VENDOR_JVC 0x04f1 /* JVC */
#define USB_VENDOR_CHICONY 0x04f2 /* Chicony Electronics */
-#define USB_VENDOR_ELAN 0x04f3 /* Elan */
+#define USB_VENDOR_ELAN 0x04f3 /* ELAN Microelectronics */
#define USB_VENDOR_NEWNEX 0x04f7 /* Newnex */
#define USB_VENDOR_BROTHER 0x04f9 /* Brother Industries */
#define USB_VENDOR_DALLAS 0x04fa /* Dallas Semiconductor */
@@ -259,6 +259,7 @@
#define USB_VENDOR_BAFO 0x0576 /* BAFO/Quality Computer Accessories */
#define USB_VENDOR_YEDATA 0x057b /* Y-E Data */
#define USB_VENDOR_AVM 0x057c /* AVM */
+#define USB_VENDOR_NINTENDO 0x057e /* Nintendo */
#define USB_VENDOR_QUICKSHOT 0x057f /* Quickshot */
#define USB_VENDOR_ROLAND 0x0582 /* Roland */
#define USB_VENDOR_ROCKFIRE 0x0583 /* Rockfire */
@@ -316,6 +317,7 @@
#define USB_VENDOR_CHIC 0x05fe /* Chic Technology */
#define USB_VENDOR_BARCO 0x0600 /* Barco Display Systems */
#define USB_VENDOR_BRIDGE 0x0607 /* Bridge Information */
+#define USB_VENDOR_SMK 0x0609 /* SMK */
#define USB_VENDOR_SOLIDYEAR 0x060b /* Solid Year */
#define USB_VENDOR_BIORAD 0x0614 /* Bio-Rad Laboratories */
#define USB_VENDOR_MACALLY 0x0618 /* Macally */
@@ -370,6 +372,7 @@
#define USB_VENDOR_TECLAST 0x071b /* Teclast */
#define USB_VENDOR_SONYERICSSON 0x0731 /* Sony Ericsson */
#define USB_VENDOR_EICON 0x0734 /* Eicon Networks */
+#define USB_VENDOR_MADCATZ 0x0738 /* Mad Catz, Inc. */
#define USB_VENDOR_SYNTECH 0x0745 /* Syntech Information */
#define USB_VENDOR_DIGITALSTREAM 0x074e /* Digital Stream */
#define USB_VENDOR_AUREAL 0x0755 /* Aureal Semiconductor */
@@ -399,6 +402,7 @@
#define USB_VENDOR_GENERALINSTMNTS 0x07b2 /* General Instruments (Motorola) */
#define USB_VENDOR_OLYMPUS 0x07b4 /* Olympus */
#define USB_VENDOR_ABOCOM 0x07b8 /* AboCom Systems */
+#define USB_VENDOR_KINGSUN 0x07c0 /* KingSun */
#define USB_VENDOR_KEISOKUGIKEN 0x07c1 /* Keisokugiken */
#define USB_VENDOR_ONSPEC 0x07c4 /* OnSpec */
#define USB_VENDOR_APG 0x07c5 /* APG Cash Drawer */
@@ -412,11 +416,13 @@
#define USB_VENDOR_ARASAN 0x07da /* Arasan Chip Systems */
#define USB_VENDOR_ALLIEDCABLE 0x07e6 /* Allied Cable */
#define USB_VENDOR_STSN 0x07ef /* STSN */
+#define USB_VENDOR_BEWAN 0x07fa /* Bewan */
#define USB_VENDOR_CENTURY 0x07f7 /* Century Corp */
#define USB_VENDOR_NEWLINK 0x07ff /* NEWlink */
#define USB_VENDOR_MAGTEK 0x0801 /* Mag-Tek */
#define USB_VENDOR_ZOOM 0x0803 /* Zoom Telephonics */
#define USB_VENDOR_PCS 0x0810 /* Personal Communication Systems */
+#define USB_VENDOR_SYNET 0x0812 /* Synet Electronics */
#define USB_VENDOR_ALPHASMART 0x081e /* AlphaSmart, Inc. */
#define USB_VENDOR_BROADLOGIC 0x0827 /* BroadLogic */
#define USB_VENDOR_HANDSPRING 0x082d /* Handspring */
@@ -466,6 +472,7 @@
#define USB_VENDOR_INTREPIDCS 0x093c /* Intrepid */
#define USB_VENDOR_YANO 0x094f /* Yano */
#define USB_VENDOR_KINGSTON 0x0951 /* Kingston Technology */
+#define USB_VENDOR_NVIDIA 0x0955 /* NVIDIA Corporation */
#define USB_VENDOR_BLUEWATER 0x0956 /* BlueWater Systems */
#define USB_VENDOR_AGILENT 0x0957 /* Agilent Technologies */
#define USB_VENDOR_GUDE 0x0959 /* Gude ADS */
@@ -474,8 +481,10 @@
#define USB_VENDOR_ADIRONDACK 0x0976 /* Adirondack Wire & Cable */
#define USB_VENDOR_BECKHOFF 0x0978 /* Beckhoff */
#define USB_VENDOR_MINDSATWORK 0x097a /* Minds At Work */
+#define USB_VENDOR_ZIPPY 0x099a /* Zippy Technology Corporation */
#define USB_VENDOR_POINTCHIPS 0x09a6 /* PointChips */
#define USB_VENDOR_INTERSIL 0x09aa /* Intersil */
+#define USB_VENDOR_TRIPPLITE2 0x09ae /* Tripp Lite */
#define USB_VENDOR_ALTIUS 0x09b3 /* Altius Solutions */
#define USB_VENDOR_ARRIS 0x09c1 /* Arris Interactive */
#define USB_VENDOR_ACTIVCARD 0x09c3 /* ACTIVCARD */
@@ -512,7 +521,7 @@
#define USB_VENDOR_EMS 0x0b43 /* EMS Production */
#define USB_VENDOR_NEC2 0x0b62 /* NEC */
#define USB_VENDOR_ADLINK 0x0b63 /* ADLINK Technoligy, Inc. */
-#define USB_VENDOR_ATI2 0x0b6f /* ATI */
+#define USB_VENDOR_ATI2 0x0b6f /* ATI Technologies */
#define USB_VENDOR_ZEEVO 0x0b7a /* Zeevo, Inc. */
#define USB_VENDOR_KURUSUGAWA 0x0b7e /* Kurusugawa Electronics, Inc. */
#define USB_VENDOR_SMART 0x0b8c /* Smart Technologies */
@@ -578,12 +587,14 @@
#define USB_VENDOR_LARSENBRUSGAARD 0x0fd8 /* Larsen and Brusgaard */
#define USB_VENDOR_OWL 0x0fde /* OWL */
#define USB_VENDOR_KONTRON 0x0fe6 /* Kontron AG */
+#define USB_VENDOR_DVICO 0x0fe9 /* DViCO */
#define USB_VENDOR_QUALCOMM 0x1004 /* Qualcomm */
#define USB_VENDOR_APACER 0x1005 /* Apacer */
#define USB_VENDOR_MOTOROLA4 0x100d /* Motorola */
#define USB_VENDOR_HP3 0x103c /* Hewlett Packard */
#define USB_VENDOR_AIRPLUS 0x1011 /* Airplus */
#define USB_VENDOR_DESKNOTE 0x1019 /* Desknote */
+#define USB_VENDOR_AMD2 0x1022 /* Advanced Micro Devices */
#define USB_VENDOR_NEC3 0x1033 /* NEC */
#define USB_VENDOR_TTI 0x103e /* Thurlby Thandar Instruments */
#define USB_VENDOR_GIGABYTE 0x1044 /* GIGABYTE */
@@ -618,6 +629,7 @@
#define USB_VENDOR_NETINDEX 0x11f6 /* NetIndex */
#define USB_VENDOR_ALCATEL 0x11f7 /* Alcatel */
#define USB_VENDOR_INTERBIOMETRICS 0x1209 /* Interbiometrics */
+#define USB_VENDOR_FUJITSU3 0x1221 /* Fujitsu Ltd. */
#define USB_VENDOR_UNKNOWN3 0x1233 /* Unknown vendor */
#define USB_VENDOR_TSUNAMI 0x1241 /* Tsunami */
#define USB_VENDOR_PHEENET 0x124a /* Pheenet */
@@ -635,6 +647,7 @@
#define USB_VENDOR_MOBILITY 0x1342 /* Mobility */
#define USB_VENDOR_DICKSMITH 0x1371 /* Dick Smith Electronics */
#define USB_VENDOR_NETGEAR3 0x1385 /* Netgear */
+#define USB_VENDOR_VALIDITY 0x138a /* Validity Sensors, Inc. */
#define USB_VENDOR_BALTECH 0x13ad /* Baltech */
#define USB_VENDOR_CISCOLINKSYS 0x13b1 /* Cisco-Linksys */
#define USB_VENDOR_SHARK 0x13d2 /* Shark */
@@ -642,6 +655,7 @@
#define USB_VENDOR_INITIO 0x13fd /* Initio Corporation */
#define USB_VENDOR_EMTEC 0x13fe /* Emtec */
#define USB_VENDOR_NOVATEL 0x1410 /* Novatel Wireless */
+#define USB_VENDOR_OMNIVISION2 0x1415 /* OmniVision Technologies, Inc. */
#define USB_VENDOR_MERLIN 0x1416 /* Merlin */
#define USB_VENDOR_REDOCTANE 0x1430 /* RedOctane */
#define USB_VENDOR_WISTRONNEWEB 0x1435 /* Wistron NeWeb */
@@ -696,17 +710,24 @@
#define USB_VENDOR_SWEEX2 0x177f /* Sweex */
#define USB_VENDOR_METAGEEK 0x1781 /* MetaGeek */
#define USB_VENDOR_KAMSTRUP 0x17a8 /* Kamstrup A/S */
+#define USB_VENDOR_MISC 0x1781 /* Misc Vendors */
#define USB_VENDOR_DISPLAYLINK 0x17e9 /* DisplayLink */
#define USB_VENDOR_LENOVO 0x17ef /* Lenovo */
#define USB_VENDOR_WAVESENSE 0x17f4 /* WaveSense */
#define USB_VENDOR_VAISALA 0x1843 /* Vaisala */
+#define USB_VENDOR_E3C 0x18b4 /* E3C Technologies */
#define USB_VENDOR_AMIT 0x18c5 /* AMIT */
#define USB_VENDOR_GOOGLE 0x18d1 /* Google */
#define USB_VENDOR_QCOM 0x18e8 /* Qcom */
#define USB_VENDOR_ELV 0x18ef /* ELV */
#define USB_VENDOR_LINKSYS3 0x1915 /* Linksys */
+#define USB_VENDOR_MEINBERG 0x1938 /* Meinberg Funkuhren */
+#define USB_VENDOR_BECEEM 0x198f /* Beceem Communications */
+#define USB_VENDOR_ZTE 0x19d2 /* ZTE */
#define USB_VENDOR_QUALCOMMINC 0x19d2 /* Qualcomm, Incorporated */
#define USB_VENDOR_QUALCOMM3 0x19f5 /* Qualcomm, Inc. */
+#define USB_VENDOR_QUANTA2 0x1a32 /* Quanta */
+#define USB_VENDOR_TERMINUS 0x1a40 /* Terminus Technology */
#define USB_VENDOR_ABBOTT 0x1a61 /* Abbott Diabetics */
#define USB_VENDOR_BAYER 0x1a79 /* Bayer */
#define USB_VENDOR_WCH2 0x1a86 /* QinHeng Electronics */
@@ -745,17 +766,22 @@
#define USB_VENDOR_PARA 0x20b8 /* PARA Industrial */
#define USB_VENDOR_SIMTEC 0x20df /* Simtec Electronics */
#define USB_VENDOR_TRENDNET 0x20f4 /* TRENDnet */
-#define USB_VENDOR_RTSYSTEMS 0x2100 /* RTSYSTEMS */
+#define USB_VENDOR_RTSYSTEMS 0x2100 /* RT Systems */
+#define USB_VENDOR_DLINK4 0x2101 /* D-Link */
+#define USB_VENDOR_INTENSO 0x2109 /* INTENSO */
#define USB_VENDOR_VIALABS 0x2109 /* VIA Labs */
#define USB_VENDOR_ERICSSON 0x2282 /* Ericsson */
#define USB_VENDOR_MOTOROLA2 0x22b8 /* Motorola */
#define USB_VENDOR_WETELECOM 0x22de /* WeTelecom */
+#define USB_VENDOR_PINNACLE 0x2304 /* Pinnacle Systems */
+#define USB_VENDOR_ARDUINO 0x2341 /* Arduino SA */
#define USB_VENDOR_TPLINK 0x2357 /* TP-Link */
#define USB_VENDOR_WESTMOUNTAIN 0x2405 /* West Mountain Radio */
#define USB_VENDOR_TRIPPLITE 0x2478 /* Tripp-Lite */
#define USB_VENDOR_HIROSE 0x2631 /* Hirose Electric */
#define USB_VENDOR_NHJ 0x2770 /* NHJ */
#define USB_VENDOR_THINGM 0x27b8 /* ThingM */
+#define USB_VENDOR_PERASO 0x2932 /* Peraso Technologies, Inc. */
#define USB_VENDOR_PLANEX 0x2c02 /* Planex Communications */
#define USB_VENDOR_QUECTEL 0x2c7c /* Quectel Wireless Solutions */
#define USB_VENDOR_VIDZMEDIA 0x3275 /* VidzMedia Pte Ltd */
@@ -778,7 +804,9 @@
#define USB_VENDOR_PROLIFIC2 0x5372 /* Prolific Technologies */
#define USB_VENDOR_ONSPEC2 0x55aa /* OnSpec Electronic Inc. */
#define USB_VENDOR_ZINWELL 0x5a57 /* Zinwell */
+#define USB_VENDOR_INGENIC 0x601a /* Ingenic Semiconductor Ltd. */
#define USB_VENDOR_SITECOM 0x6189 /* Sitecom */
+#define USB_VENDOR_SPRINGERDESIGN 0x6400 /* Springer Design, Inc. */
#define USB_VENDOR_ARKMICRO 0x6547 /* Arkmicro Technologies Inc. */
#define USB_VENDOR_3COM2 0x6891 /* 3Com */
#define USB_VENDOR_EDIMAX 0x7392 /* Edimax */
@@ -791,8 +819,10 @@
#define USB_VENDOR_MARVELL 0x9e88 /* Marvell Technology Group Ltd. */
#define USB_VENDOR_3COM3 0xa727 /* 3Com */
#define USB_VENDOR_CACE 0xcace /* CACE Technologies */
-#define USB_VENDOR_EVOLUTION 0xdeee /* Evolution Robotics products */
+#define USB_VENDOR_COMPARE 0xcdab /* Compare */
#define USB_VENDOR_DATAAPEX 0xdaae /* DataApex */
+#define USB_VENDOR_EVOLUTION 0xdeee /* Evolution Robotics */
+#define USB_VENDOR_EMPIA 0xeb1a /* eMPIA Technology */
#define USB_VENDOR_HP2 0xf003 /* Hewlett Packard */
#define USB_VENDOR_LOGILINK 0xfc08 /* LogiLink */
#define USB_VENDOR_USRP 0xfffe /* GNU Radio USRP */
@@ -802,7 +832,7 @@
*/
/* 3Com products */
-#define USB_PRODUCT_3COM_HOMECONN 0x009d /* HomeConnect Camera */
+#define USB_PRODUCT_3COM_HOMECONN 0x009d /* HomeConnect USB Camera */
#define USB_PRODUCT_3COM_3CREB96 0x00a0 /* Bluetooth USB Adapter */
#define USB_PRODUCT_3COM_3C19250 0x03e8 /* 3C19250 Ethernet Adapter */
#define USB_PRODUCT_3COM_3CRSHEW696 0x0a01 /* 3CRSHEW696 Wireless Adapter */
@@ -826,6 +856,10 @@
/* ABIT products */
#define USB_PRODUCT_ABIT_AK_020 0x7d0e /* 3G modem */
+#define USB_PRODUCT_ACDC_HUB 0x2315 /* USB Pen Drive HUB */
+#define USB_PRODUCT_ACDC_SECWRITE 0x2316 /* USB Pen Drive Secure Write */
+#define USB_PRODUCT_ACDC_PEN 0x2317 /* USB Pen Drive with Secure Write */
+
/* AboCom products */
#define USB_PRODUCT_ABOCOM_XX1 0x110c /* XX1 */
#define USB_PRODUCT_ABOCOM_XX2 0x200c /* XX2 */
@@ -933,6 +967,9 @@
/* Adaptec products */
#define USB_PRODUCT_ADAPTEC_AWN8020 0x0020 /* AWN-8020 WLAN */
+/* Addonics products */
+#define USB_PRODUCT_ADDONICS2_205 0xa001 /* Cable 205 */
+
/* Addtron products */
#define USB_PRODUCT_ADDTRON_AWU120 0xff31 /* AWU-120 */
@@ -1025,6 +1062,7 @@
/* Alink products */
#define USB_PRODUCT_ALINK_DWM652U5 0xce16 /* DWM-652 */
#define USB_PRODUCT_ALINK_3G 0x9000 /* 3G modem */
+#define USB_PRODUCT_ALINK_SIM7600E 0x9001 /* LTE modem */
#define USB_PRODUCT_ALINK_3GU 0x9200 /* 3G modem */
/* Altec Lansing products */
@@ -1672,6 +1710,7 @@
#define USB_PRODUCT_DLINK_RT2870 0x3c09 /* RT2870 */
#define USB_PRODUCT_DLINK_RT3072 0x3c0a /* RT3072 */
#define USB_PRODUCT_DLINK_DWA140B3 0x3c15 /* DWA-140 rev B3 */
+#define USB_PRODUCT_DLINK_DWA125A3 0x3c19 /* DWA-125 rev A3 */
#define USB_PRODUCT_DLINK_DWA160B2 0x3c1a /* DWA-160 rev B2 */
#define USB_PRODUCT_DLINK_DWA127 0x3c1b /* DWA-127 Wireless Adapter */
#define USB_PRODUCT_DLINK_DWA162 0x3c1f /* DWA-162 Wireless Adapter */
@@ -2204,9 +2243,12 @@
#define USB_PRODUCT_GENESYS_GL650 0x0604 /* GL650 HUB */
#define USB_PRODUCT_GENESYS_GL606 0x0606 /* GL606 USB 2.0 HUB */
#define USB_PRODUCT_GENESYS_GL850G 0x0608 /* GL850G USB 2.0 HUB */
+#define USB_PRODUCT_GENESYS_GL3520_2 0x0610 /* GL3520 4-Port USB 2.0 DataPath */
+#define USB_PRODUCT_GENESYS_GL3520_SS 0x0616 /* GL3520 4-Port USB 3.0 DataPath */
#define USB_PRODUCT_GENESYS_GL641USB 0x0700 /* GL641USB CompactFlash Card Reader */
#define USB_PRODUCT_GENESYS_GL641USB2IDE_2 0x0701 /* GL641USB USB-IDE Bridge No 2 */
#define USB_PRODUCT_GENESYS_GL641USB2IDE 0x0702 /* GL641USB USB-IDE Bridge */
+#define USB_PRODUCT_GENESYS_GL3233 0x0743 /* GL3233 USB 3.0 AiO Card Reader */
#define USB_PRODUCT_GENESYS_GL641USB_2 0x0760 /* GL641USB 6-in-1 Card Reader */
/* GIGABYTE products */
@@ -2237,6 +2279,7 @@
#define USB_PRODUCT_GLOBALSUN_AR5523_2_NF 0x7812 /* AR5523 (no firmware) */
/* Globespan products */
+#define USB_PRODUCT_GLOBESPAN_MODEM_1 0x1329 /* USB Modem */
#define USB_PRODUCT_GLOBESPAN_PRISM_GT_1 0x2000 /* PrismGT USB 2.0 WLAN */
#define USB_PRODUCT_GLOBESPAN_PRISM_GT_2 0x2002 /* PrismGT USB 2.0 WLAN */
@@ -2525,6 +2568,10 @@
#define USB_PRODUCT_INTEL2_IRMH2 0x0024 /* Integrated Rate Matching Hub */
#define USB_PRODUCT_INTEL2_IRMH3 0x8000 /* Integrated Rate Matching Hub */
#define USB_PRODUCT_INTEL2_IRMH4 0x8008 /* Integrated Rate Matching Hub */
+#define USB_PRODUCT_INTEL2_SFP 0x0aa7 /* Sandy Peak (3168) Bluetooth Module */
+#define USB_PRODUCT_INTEL2_JFP 0x0aaa /* Jefferson Peak (9460/9560) Bluetooth Module */
+#define USB_PRODUCT_INTEL2_THP 0x0025 /* Thunder Peak (9160/9260) Bluetooth Module */
+#define USB_PRODUCT_INTEL2_HSP 0x0026 /* Harrison Peak (22560) Bluetooth Module */
/* Interbiometric products */
#define USB_PRODUCT_INTERBIOMETRICS_IOBOARD 0x1002 /* FTDI compatible adapter */
@@ -3415,6 +3462,9 @@
#define USB_PRODUCT_NOVATEL_MC679 0x7031 /* Novatel MC679 */
#define USB_PRODUCT_NOVATEL2_FLEXPACKGPS 0x0100 /* NovAtel FlexPack GPS receiver */
+/* NVIDIA products */
+#define USB_PRODUCT_NVIDIA_RTL8153 0x09ff /* USB 3.0 Ethernet */
+
/* Merlin products */
#define USB_PRODUCT_MERLIN_V620 0x1110 /* Merlin V620 */
@@ -3587,12 +3637,16 @@
#define USB_PRODUCT_PERACOM_ENET3 0x0003 /* At Home Ethernet */
#define USB_PRODUCT_PERACOM_ENET2 0x0005 /* Ethernet */
+/* Peraso Technologies, Inc products */
+#define USB_PRODUCT_PERASO_PRS4001 0x4001 /* PRS4001 WLAN */
+
/* Philips products */
#define USB_PRODUCT_PHILIPS_DSS350 0x0101 /* DSS 350 Digital Speaker System */
#define USB_PRODUCT_PHILIPS_DSS 0x0104 /* DSS XXX Digital Speaker System */
#define USB_PRODUCT_PHILIPS_HUB 0x0201 /* hub */
#define USB_PRODUCT_PHILIPS_PCA646VC 0x0303 /* PCA646VC PC Camera */
#define USB_PRODUCT_PHILIPS_PCVC680K 0x0308 /* PCVC680K Vesta Pro PC Camera */
+#define USB_PRODUCT_PHILIPS_SPC900NC 0x0329 /* SPC 900NC CCD PC Camera */
#define USB_PRODUCT_PHILIPS_DSS150 0x0471 /* DSS 150 Digital Speaker System */
#define USB_PRODUCT_PHILIPS_ACE1001 0x066a /* AKTAKOM ACE-1001 cable */
#define USB_PRODUCT_PHILIPS_SPE3030CC 0x083a /* USB 2.0 External Disk */
@@ -3856,6 +3910,7 @@
#define USB_PRODUCT_RALINK_RT3572 0x3572 /* RT3572 */
#define USB_PRODUCT_RALINK_RT3573 0x3573 /* RT3573 */
#define USB_PRODUCT_RALINK_RT5370 0x5370 /* RT5370 */
+#define USB_PRODUCT_RALINK_RT5372 0x5372 /* RT5372 */
#define USB_PRODUCT_RALINK_RT5572 0x5572 /* RT5572 */
#define USB_PRODUCT_RALINK_RT8070 0x8070 /* RT8070 */
#define USB_PRODUCT_RALINK_RT2570_3 0x9020 /* RT2500USB Wireless Adapter */
@@ -4325,6 +4380,9 @@
#define USB_PRODUCT_SMC2_2020HUB 0x2020 /* USB Hub */
#define USB_PRODUCT_SMC2_2514HUB 0x2514 /* USB Hub */
#define USB_PRODUCT_SMC3_2662WUSB 0xa002 /* 2662W-AR Wireless */
+#define USB_PRODUCT_SMC2_LAN7800_ETH 0x7800 /* USB/Ethernet */
+#define USB_PRODUCT_SMC2_LAN7801_ETH 0x7801 /* USB/Ethernet */
+#define USB_PRODUCT_SMC2_LAN7850_ETH 0x7850 /* USB/Ethernet */
#define USB_PRODUCT_SMC2_LAN9500_ETH 0x9500 /* USB/Ethernet */
#define USB_PRODUCT_SMC2_LAN9505_ETH 0x9505 /* USB/Ethernet */
#define USB_PRODUCT_SMC2_LAN9530_ETH 0x9530 /* USB/Ethernet */
@@ -4743,7 +4801,18 @@
/* Yamaha products */
#define USB_PRODUCT_YAMAHA_UX256 0x1000 /* UX256 MIDI I/F */
+#define USB_PRODUCT_YAMAHA_MU1000 0x1001 /* MU1000 MIDI Synth. */
+#define USB_PRODUCT_YAMAHA_MU2000 0x1002 /* MU2000 MIDI Synth. */
+#define USB_PRODUCT_YAMAHA_MU500 0x1003 /* MU500 MIDI Synth. */
+#define USB_PRODUCT_YAMAHA_UW500 0x1004 /* UW500 USB Audio I/F */
+#define USB_PRODUCT_YAMAHA_MOTIF6 0x1005 /* MOTIF6 MIDI Synth. Workstation */
+#define USB_PRODUCT_YAMAHA_MOTIF7 0x1006 /* MOTIF7 MIDI Synth. Workstation */
+#define USB_PRODUCT_YAMAHA_MOTIF8 0x1007 /* MOTIF8 MIDI Synth. Workstation */
#define USB_PRODUCT_YAMAHA_UX96 0x1008 /* UX96 MIDI I/F */
+#define USB_PRODUCT_YAMAHA_UX16 0x1009 /* UX16 MIDI I/F */
+#define USB_PRODUCT_YAMAHA_S08 0x100e /* S08 MIDI Keyboard */
+#define USB_PRODUCT_YAMAHA_CLP150 0x100f /* CLP-150 digital piano */
+#define USB_PRODUCT_YAMAHA_CLP170 0x1010 /* CLP-170 digital piano */
#define USB_PRODUCT_YAMAHA_RPU200 0x3104 /* RP-U200 */
#define USB_PRODUCT_YAMAHA_RTA54I 0x4000 /* NetVolante RTA54i Broadband&ISDN Router */
#define USB_PRODUCT_YAMAHA_RTW65B 0x4001 /* NetVolante RTW65b Broadband Wireless Router */
@@ -4778,6 +4847,9 @@
#define USB_PRODUCT_ZCOM_RT2870_2 0x0025 /* RT2870 */
#define USB_PRODUCT_ZCOM_UB82 0x0026 /* UB82 */
+/* Zeevo, Inc. products */
+#define USB_PRODUCT_ZEEVO_BLUETOOTH 0x07d0 /* BT-500 Bluetooth USB Adapter */
+
/* Zinwell products */
#define USB_PRODUCT_ZINWELL_RT2570 0x0260 /* RT2570 */
#define USB_PRODUCT_ZINWELL_RT2870_1 0x0280 /* RT2870 */
@@ -4788,14 +4860,28 @@
/* Zoom Telephonics, Inc. products */
#define USB_PRODUCT_ZOOM_2986L 0x9700 /* 2986L Fax modem */
+#define USB_PRODUCT_ZOOM_3095 0x3095 /* 3095 USB Fax modem */
/* Zoran Microelectronics products */
#define USB_PRODUCT_ZORAN_EX20DSC 0x4343 /* Digital Camera EX-20 DSC */
+/* ZTE products */
+#define USB_PRODUCT_ZTE_MF622 0x0001 /* MF622 modem */
+#define USB_PRODUCT_ZTE_MF628 0x0015 /* MF628 modem */
+#define USB_PRODUCT_ZTE_MF626 0x0031 /* MF626 modem */
+#define USB_PRODUCT_ZTE_MF820D_INSTALLER 0x0166 /* MF820D CD */
+#define USB_PRODUCT_ZTE_MF820D 0x0167 /* MF820D modem */
+#define USB_PRODUCT_ZTE_INSTALLER 0x2000 /* UMTS CD */
+#define USB_PRODUCT_ZTE_MC2718 0xffe8 /* MC2718 modem */
+#define USB_PRODUCT_ZTE_AC8700 0xfffe /* CDMA 1xEVDO USB modem */
+
/* Zydas Technology Corporation products */
+#define USB_PRODUCT_ZYDAS_ZD1201 0x1201 /* ZD1201 */
#define USB_PRODUCT_ZYDAS_ZD1211 0x1211 /* ZD1211 WLAN abg */
#define USB_PRODUCT_ZYDAS_ZD1211B 0x1215 /* ZD1211B */
#define USB_PRODUCT_ZYDAS_ZD1221 0x1221 /* ZD1221 */
+#define USB_PRODUCT_ZYDAS_ALL0298 0xa211 /* ALL0298 */
+#define USB_PRODUCT_ZYDAS_ZD1211B_2 0xb215 /* ZD1211B */
/* ZyXEL Communication Co. products */
#define USB_PRODUCT_ZYXEL_OMNI56K 0x1500 /* Omni 56K Plus */
@@ -4804,8 +4890,10 @@
#define USB_PRODUCT_ZYXEL_G200V2 0x3407 /* G-200 v2 */
#define USB_PRODUCT_ZYXEL_AG225H 0x3409 /* AG-225H */
#define USB_PRODUCT_ZYXEL_M202 0x340a /* M-202 */
+#define USB_PRODUCT_ZYXEL_G270S 0x340c /* G-270S */
#define USB_PRODUCT_ZYXEL_G220V2 0x340f /* G-220 v2 */
#define USB_PRODUCT_ZYXEL_G202 0x3410 /* G-202 */
+#define USB_PRODUCT_ZYXEL_RT2573 0x3415 /* RT2573 */
#define USB_PRODUCT_ZYXEL_RT2870_1 0x3416 /* RT2870 */
#define USB_PRODUCT_ZYXEL_NWD271N 0x3417 /* NWD-271N */
#define USB_PRODUCT_ZYXEL_NWD211AN 0x3418 /* NWD-211AN */
@@ -4813,4 +4901,5 @@
#define USB_PRODUCT_ZYXEL_RT3070 0x341e /* NWD2105 */
#define USB_PRODUCT_ZYXEL_RTL8192CU 0x341f /* RTL8192CU */
#define USB_PRODUCT_ZYXEL_NWD2705 0x3421 /* NWD2705 */
-#define USB_PRODUCT_ZYXEL_NWD6605 0x3426 /* NWD6605 */
+#define USB_PRODUCT_ZYXEL_NWD6605 0x3426 /* ND6605 */
+#define USB_PRODUCT_ZYXEL_PRESTIGE 0x401a /* Prestige */
diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
index 49ac75d7..6317c2d1 100644
--- a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
+++ b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
@@ -41,7 +41,7 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_3COM, USB_PRODUCT_3COM_HOMECONN,
0,
"3Com",
- "HomeConnect Camera",
+ "HomeConnect USB Camera",
},
{
USB_VENDOR_3COM, USB_PRODUCT_3COM_3CREB96,
@@ -146,6 +146,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"3G modem",
},
{
+ USB_VENDOR_ACDC, USB_PRODUCT_ACDC_HUB,
+ 0,
+ "American Computer & Digital Components",
+ "USB Pen Drive HUB",
+ },
+ {
+ USB_VENDOR_ACDC, USB_PRODUCT_ACDC_SECWRITE,
+ 0,
+ "American Computer & Digital Components",
+ "USB Pen Drive Secure Write",
+ },
+ {
+ USB_VENDOR_ACDC, USB_PRODUCT_ACDC_PEN,
+ 0,
+ "American Computer & Digital Components",
+ "USB Pen Drive with Secure Write",
+ },
+ {
USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX1,
0,
"AboCom Systems",
@@ -632,6 +650,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"AWN-8020 WLAN",
},
{
+ USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_205,
+ 0,
+ "Addonics Technology",
+ "Cable 205",
+ },
+ {
USB_VENDOR_ADDTRON, USB_PRODUCT_ADDTRON_AWU120,
0,
"Addtron",
@@ -950,6 +974,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"3G modem",
},
{
+ USB_VENDOR_ALINK, USB_PRODUCT_ALINK_SIM7600E,
+ 0,
+ "Alink",
+ "LTE modem",
+ },
+ {
USB_VENDOR_ALINK, USB_PRODUCT_ALINK_3GU,
0,
"Alink",
@@ -3752,6 +3782,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"DWA-140 rev B3",
},
{
+ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWA125A3,
+ 0,
+ "D-Link",
+ "DWA-125 rev A3",
+ },
+ {
USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWA160B2,
0,
"D-Link",
@@ -4774,19 +4810,19 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_EVOLUTION, USB_PRODUCT_EVOLUTION_ER1,
0,
- "Evolution Robotics products",
+ "Evolution Robotics",
"FTDI compatible adapter",
},
{
USB_VENDOR_EVOLUTION, USB_PRODUCT_EVOLUTION_HYBRID,
0,
- "Evolution Robotics products",
+ "Evolution Robotics",
"FTDI compatible adapter",
},
{
USB_VENDOR_EVOLUTION, USB_PRODUCT_EVOLUTION_RCM4,
0,
- "Evolution Robotics products",
+ "Evolution Robotics",
"FTDI compatible adapter",
},
{
@@ -4876,13 +4912,13 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_FOXCONN, USB_PRODUCT_FOXCONN_TCOM_TC_300,
0,
- "Foxconn",
+ "Foxconn / Hon Hai",
"T-Com TC 300",
},
{
USB_VENDOR_FOXCONN, USB_PRODUCT_FOXCONN_PIRELLI_DP_L10,
0,
- "Foxconn",
+ "Foxconn / Hon Hai",
"Pirelli DP-L10",
},
{
@@ -6398,6 +6434,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"GL850G USB 2.0 HUB",
},
{
+ USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL3520_2,
+ 0,
+ "Genesys Logic",
+ "GL3520 4-Port USB 2.0 DataPath",
+ },
+ {
+ USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL3520_SS,
+ 0,
+ "Genesys Logic",
+ "GL3520 4-Port USB 3.0 DataPath",
+ },
+ {
USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB,
0,
"Genesys Logic",
@@ -6416,6 +6464,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"GL641USB USB-IDE Bridge",
},
{
+ USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL3233,
+ 0,
+ "Genesys Logic",
+ "GL3233 USB 3.0 AiO Card Reader",
+ },
+ {
USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB_2,
0,
"Genesys Logic",
@@ -6548,6 +6602,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"AR5523 (no firmware)",
},
{
+ USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_MODEM_1,
+ 0,
+ "Globespan",
+ "USB Modem",
+ },
+ {
USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_1,
0,
"Globespan",
@@ -7904,6 +7964,30 @@ const struct usb_knowndev usb_knowndevs[] = {
"Integrated Rate Matching Hub",
},
{
+ USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_SFP,
+ 0,
+ "Intel",
+ "Sandy Peak (3168) Bluetooth Module",
+ },
+ {
+ USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_JFP,
+ 0,
+ "Intel",
+ "Jefferson Peak (9460/9560) Bluetooth Module",
+ },
+ {
+ USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_THP,
+ 0,
+ "Intel",
+ "Thunder Peak (9160/9260) Bluetooth Module",
+ },
+ {
+ USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_HSP,
+ 0,
+ "Intel",
+ "Harrison Peak (22560) Bluetooth Module",
+ },
+ {
USB_VENDOR_INTERBIOMETRICS, USB_PRODUCT_INTERBIOMETRICS_IOBOARD,
0,
"Interbiometrics",
@@ -12128,6 +12212,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"NovAtel FlexPack GPS receiver",
},
{
+ USB_VENDOR_NVIDIA, USB_PRODUCT_NVIDIA_RTL8153,
+ 0,
+ "NVIDIA Corporation",
+ "USB 3.0 Ethernet",
+ },
+ {
USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620,
0,
"Merlin",
@@ -12920,6 +13010,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Ethernet",
},
{
+ USB_VENDOR_PERASO, USB_PRODUCT_PERASO_PRS4001,
+ 0,
+ "Peraso Technologies, Inc.",
+ "PRS4001 WLAN",
+ },
+ {
USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS350,
0,
"Philips",
@@ -12950,6 +13046,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"PCVC680K Vesta Pro PC Camera",
},
{
+ USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SPC900NC,
+ 0,
+ "Philips",
+ "SPC 900NC CCD PC Camera",
+ },
+ {
USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS150,
0,
"Philips",
@@ -14240,6 +14342,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT5370",
},
{
+ USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT5372,
+ 0,
+ "Ralink Technology",
+ "RT5372",
+ },
+ {
USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT5572,
0,
"Ralink Technology",
@@ -14686,13 +14794,13 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_RTSYSTEMS, USB_PRODUCT_RTSYSTEMS_CT29B,
0,
- "RTSYSTEMS",
+ "RT Systems",
"FTDI compatible adapter",
},
{
USB_VENDOR_RTSYSTEMS, USB_PRODUCT_RTSYSTEMS_SERIAL_VX7,
0,
- "RTSYSTEMS",
+ "RT Systems",
"FTDI compatible adapter",
},
{
@@ -16570,13 +16678,13 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_2020HUB,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB Hub",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_2514HUB,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB Hub",
},
{
@@ -16586,111 +16694,129 @@ const struct usb_knowndev usb_knowndevs[] = {
"2662W-AR Wireless",
},
{
+ USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7800_ETH,
+ 0,
+ "Microchip (Standard Microsystems)",
+ "USB/Ethernet",
+ },
+ {
+ USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7801_ETH,
+ 0,
+ "Microchip (Standard Microsystems)",
+ "USB/Ethernet",
+ },
+ {
+ USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7850_ETH,
+ 0,
+ "Microchip (Standard Microsystems)",
+ "USB/Ethernet",
+ },
+ {
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9505_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9530_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9730_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500_SAL10,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9505_SAL10,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500A_SAL10,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9505A_SAL10,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9514_SAL10,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500A_HAL,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9505A_HAL,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500_ETH_2,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500A_ETH_2,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9514_ETH_2,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9500A_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9505A_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN89530_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9514_ETH,
0,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
"USB/Ethernet",
},
{
@@ -18140,12 +18266,78 @@ const struct usb_knowndev usb_knowndevs[] = {
"UX256 MIDI I/F",
},
{
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_MU1000,
+ 0,
+ "YAMAHA",
+ "MU1000 MIDI Synth.",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_MU2000,
+ 0,
+ "YAMAHA",
+ "MU2000 MIDI Synth.",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_MU500,
+ 0,
+ "YAMAHA",
+ "MU500 MIDI Synth.",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_UW500,
+ 0,
+ "YAMAHA",
+ "UW500 USB Audio I/F",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_MOTIF6,
+ 0,
+ "YAMAHA",
+ "MOTIF6 MIDI Synth. Workstation",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_MOTIF7,
+ 0,
+ "YAMAHA",
+ "MOTIF7 MIDI Synth. Workstation",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_MOTIF8,
+ 0,
+ "YAMAHA",
+ "MOTIF8 MIDI Synth. Workstation",
+ },
+ {
USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_UX96,
0,
"YAMAHA",
"UX96 MIDI I/F",
},
{
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_UX16,
+ 0,
+ "YAMAHA",
+ "UX16 MIDI I/F",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_S08,
+ 0,
+ "YAMAHA",
+ "S08 MIDI Keyboard",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_CLP150,
+ 0,
+ "YAMAHA",
+ "CLP-150 digital piano",
+ },
+ {
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_CLP170,
+ 0,
+ "YAMAHA",
+ "CLP-170 digital piano",
+ },
+ {
USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RPU200,
0,
"YAMAHA",
@@ -18284,6 +18476,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"UB82",
},
{
+ USB_VENDOR_ZEEVO, USB_PRODUCT_ZEEVO_BLUETOOTH,
+ 0,
+ "Zeevo, Inc.",
+ "BT-500 Bluetooth USB Adapter",
+ },
+ {
USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570,
0,
"Zinwell",
@@ -18326,12 +18524,72 @@ const struct usb_knowndev usb_knowndevs[] = {
"2986L Fax modem",
},
{
+ USB_VENDOR_ZOOM, USB_PRODUCT_ZOOM_3095,
+ 0,
+ "Zoom Telephonics",
+ "3095 USB Fax modem",
+ },
+ {
USB_VENDOR_ZORAN, USB_PRODUCT_ZORAN_EX20DSC,
0,
"Zoran Microelectronics",
"Digital Camera EX-20 DSC",
},
{
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF622,
+ 0,
+ "ZTE",
+ "MF622 modem",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF628,
+ 0,
+ "ZTE",
+ "MF628 modem",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF626,
+ 0,
+ "ZTE",
+ "MF626 modem",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF820D_INSTALLER,
+ 0,
+ "ZTE",
+ "MF820D CD",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF820D,
+ 0,
+ "ZTE",
+ "MF820D modem",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_INSTALLER,
+ 0,
+ "ZTE",
+ "UMTS CD",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MC2718,
+ 0,
+ "ZTE",
+ "MC2718 modem",
+ },
+ {
+ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_AC8700,
+ 0,
+ "ZTE",
+ "CDMA 1xEVDO USB modem",
+ },
+ {
+ USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1201,
+ 0,
+ "Zydas Technology Corporation",
+ "ZD1201",
+ },
+ {
USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211,
0,
"Zydas Technology Corporation",
@@ -18350,6 +18608,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"ZD1221",
},
{
+ USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ALL0298,
+ 0,
+ "Zydas Technology Corporation",
+ "ALL0298",
+ },
+ {
+ USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211B_2,
+ 0,
+ "Zydas Technology Corporation",
+ "ZD1211B",
+ },
+ {
USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_OMNI56K,
0,
"ZyXEL Communication",
@@ -18386,6 +18656,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"M-202",
},
{
+ USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G270S,
+ 0,
+ "ZyXEL Communication",
+ "G-270S",
+ },
+ {
USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G220V2,
0,
"ZyXEL Communication",
@@ -18398,6 +18674,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"G-202",
},
{
+ USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RT2573,
+ 0,
+ "ZyXEL Communication",
+ "RT2573",
+ },
+ {
USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RT2870_1,
0,
"ZyXEL Communication",
@@ -18443,7 +18725,13 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_NWD6605,
0,
"ZyXEL Communication",
- "NWD6605",
+ "ND6605",
+ },
+ {
+ USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_PRESTIGE,
+ 0,
+ "ZyXEL Communication",
+ "Prestige",
},
{
USB_VENDOR_UNKNOWN1, 0,
@@ -18476,9 +18764,9 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
- USB_VENDOR_INTENSO, 0,
+ USB_VENDOR_QUAN, 0,
USB_KNOWNDEV_NOPROD,
- "INTENSO",
+ "Quan",
NULL,
},
{
@@ -18670,7 +18958,7 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_WELTREND, 0,
USB_KNOWNDEV_NOPROD,
- "Weltrend",
+ "Weltrend Semiconductor",
NULL,
},
{
@@ -18736,7 +19024,7 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_SMC2, 0,
USB_KNOWNDEV_NOPROD,
- "Standard Microsystems",
+ "Microchip (Standard Microsystems)",
NULL,
},
{
@@ -18988,7 +19276,7 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_FOXCONN, 0,
USB_KNOWNDEV_NOPROD,
- "Foxconn",
+ "Foxconn / Hon Hai",
NULL,
},
{
@@ -19300,7 +19588,7 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_ELAN, 0,
USB_KNOWNDEV_NOPROD,
- "Elan",
+ "ELAN Microelectronics",
NULL,
},
{
@@ -19640,6 +19928,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_NINTENDO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Nintendo",
+ NULL,
+ },
+ {
USB_VENDOR_QUICKSHOT, 0,
USB_KNOWNDEV_NOPROD,
"Quickshot",
@@ -19982,6 +20276,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_SMK, 0,
+ USB_KNOWNDEV_NOPROD,
+ "SMK",
+ NULL,
+ },
+ {
USB_VENDOR_SOLIDYEAR, 0,
USB_KNOWNDEV_NOPROD,
"Solid Year",
@@ -20306,6 +20606,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MADCATZ, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Mad Catz, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_SYNTECH, 0,
USB_KNOWNDEV_NOPROD,
"Syntech Information",
@@ -20480,6 +20786,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_KINGSUN, 0,
+ USB_KNOWNDEV_NOPROD,
+ "KingSun",
+ NULL,
+ },
+ {
USB_VENDOR_KEISOKUGIKEN, 0,
USB_KNOWNDEV_NOPROD,
"Keisokugiken",
@@ -20558,6 +20870,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_BEWAN, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Bewan",
+ NULL,
+ },
+ {
USB_VENDOR_CENTURY, 0,
USB_KNOWNDEV_NOPROD,
"Century Corp",
@@ -20588,6 +20906,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_SYNET, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Synet Electronics",
+ NULL,
+ },
+ {
USB_VENDOR_ALPHASMART, 0,
USB_KNOWNDEV_NOPROD,
"AlphaSmart, Inc.",
@@ -20882,6 +21206,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_NVIDIA, 0,
+ USB_KNOWNDEV_NOPROD,
+ "NVIDIA Corporation",
+ NULL,
+ },
+ {
USB_VENDOR_BLUEWATER, 0,
USB_KNOWNDEV_NOPROD,
"BlueWater Systems",
@@ -20930,6 +21260,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_ZIPPY, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Zippy Technology Corporation",
+ NULL,
+ },
+ {
USB_VENDOR_POINTCHIPS, 0,
USB_KNOWNDEV_NOPROD,
"PointChips",
@@ -20942,6 +21278,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_TRIPPLITE2, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Tripp Lite",
+ NULL,
+ },
+ {
USB_VENDOR_ALTIUS, 0,
USB_KNOWNDEV_NOPROD,
"Altius Solutions",
@@ -21160,7 +21502,7 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_ATI2, 0,
USB_KNOWNDEV_NOPROD,
- "ATI",
+ "ATI Technologies",
NULL,
},
{
@@ -21554,6 +21896,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_DVICO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "DViCO",
+ NULL,
+ },
+ {
USB_VENDOR_QUALCOMM, 0,
USB_KNOWNDEV_NOPROD,
"Qualcomm",
@@ -21590,6 +21938,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_AMD2, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Advanced Micro Devices",
+ NULL,
+ },
+ {
USB_VENDOR_NEC3, 0,
USB_KNOWNDEV_NOPROD,
"NEC",
@@ -21794,6 +22148,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_FUJITSU3, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Fujitsu Ltd.",
+ NULL,
+ },
+ {
USB_VENDOR_UNKNOWN3, 0,
USB_KNOWNDEV_NOPROD,
"Unknown vendor",
@@ -21896,6 +22256,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_VALIDITY, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Validity Sensors, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_BALTECH, 0,
USB_KNOWNDEV_NOPROD,
"Baltech",
@@ -21938,6 +22304,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_OMNIVISION2, 0,
+ USB_KNOWNDEV_NOPROD,
+ "OmniVision Technologies, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_MERLIN, 0,
USB_KNOWNDEV_NOPROD,
"Merlin",
@@ -22262,6 +22634,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MISC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Misc Vendors",
+ NULL,
+ },
+ {
USB_VENDOR_DISPLAYLINK, 0,
USB_KNOWNDEV_NOPROD,
"DisplayLink",
@@ -22286,6 +22664,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_E3C, 0,
+ USB_KNOWNDEV_NOPROD,
+ "E3C Technologies",
+ NULL,
+ },
+ {
USB_VENDOR_AMIT, 0,
USB_KNOWNDEV_NOPROD,
"AMIT",
@@ -22316,6 +22700,24 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MEINBERG, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Meinberg Funkuhren",
+ NULL,
+ },
+ {
+ USB_VENDOR_BECEEM, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Beceem Communications",
+ NULL,
+ },
+ {
+ USB_VENDOR_ZTE, 0,
+ USB_KNOWNDEV_NOPROD,
+ "ZTE",
+ NULL,
+ },
+ {
USB_VENDOR_QUALCOMMINC, 0,
USB_KNOWNDEV_NOPROD,
"Qualcomm, Incorporated",
@@ -22328,6 +22730,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_QUANTA2, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Quanta",
+ NULL,
+ },
+ {
+ USB_VENDOR_TERMINUS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Terminus Technology",
+ NULL,
+ },
+ {
USB_VENDOR_ABBOTT, 0,
USB_KNOWNDEV_NOPROD,
"Abbott Diabetics",
@@ -22558,7 +22972,19 @@ const struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_RTSYSTEMS, 0,
USB_KNOWNDEV_NOPROD,
- "RTSYSTEMS",
+ "RT Systems",
+ NULL,
+ },
+ {
+ USB_VENDOR_DLINK4, 0,
+ USB_KNOWNDEV_NOPROD,
+ "D-Link",
+ NULL,
+ },
+ {
+ USB_VENDOR_INTENSO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "INTENSO",
NULL,
},
{
@@ -22586,6 +23012,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_PINNACLE, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Pinnacle Systems",
+ NULL,
+ },
+ {
+ USB_VENDOR_ARDUINO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Arduino SA",
+ NULL,
+ },
+ {
USB_VENDOR_TPLINK, 0,
USB_KNOWNDEV_NOPROD,
"TP-Link",
@@ -22622,6 +23060,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_PERASO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Peraso Technologies, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_PLANEX, 0,
USB_KNOWNDEV_NOPROD,
"Planex Communications",
@@ -22754,12 +23198,24 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_INGENIC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Ingenic Semiconductor Ltd.",
+ NULL,
+ },
+ {
USB_VENDOR_SITECOM, 0,
USB_KNOWNDEV_NOPROD,
"Sitecom",
NULL,
},
{
+ USB_VENDOR_SPRINGERDESIGN, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Springer Design, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_ARKMICRO, 0,
USB_KNOWNDEV_NOPROD,
"Arkmicro Technologies Inc.",
@@ -22832,9 +23288,9 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
- USB_VENDOR_EVOLUTION, 0,
+ USB_VENDOR_COMPARE, 0,
USB_KNOWNDEV_NOPROD,
- "Evolution Robotics products",
+ "Compare",
NULL,
},
{
@@ -22844,6 +23300,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_EVOLUTION, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Evolution Robotics",
+ NULL,
+ },
+ {
+ USB_VENDOR_EMPIA, 0,
+ USB_KNOWNDEV_NOPROD,
+ "eMPIA Technology",
+ NULL,
+ },
+ {
USB_VENDOR_HP2, 0,
USB_KNOWNDEV_NOPROD,
"Hewlett Packard",
diff --git a/rtemsbsd/include/sys/boot.h b/rtemsbsd/include/sys/boot.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rtemsbsd/include/sys/boot.h
diff --git a/rtemsbsd/include/sys/epoch.h b/rtemsbsd/include/sys/epoch.h
index 25000a6d..d268efff 100644
--- a/rtemsbsd/include/sys/epoch.h
+++ b/rtemsbsd/include/sys/epoch.h
@@ -100,8 +100,8 @@ SYSINIT(epoch_##name, SI_SUB_TUNABLES, SI_ORDER_THIRD, \
void _bsd_epoch_init(epoch_t epoch, uintptr_t pcpu_record_offset,
int flags);
-void epoch_enter_preempt(epoch_t epoch);
-void epoch_exit_preempt(epoch_t epoch);
+void epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et);
void epoch_wait(epoch_t epoch);
void epoch_wait_preempt(epoch_t epoch);
diff --git a/rtemsbsd/include/sys/kpilite.h b/rtemsbsd/include/sys/kpilite.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rtemsbsd/include/sys/kpilite.h
diff --git a/rtemsbsd/include/vm/vm_pager.h b/rtemsbsd/include/vm/vm_pager.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rtemsbsd/include/vm/vm_pager.h
diff --git a/rtemsbsd/local/cryptodev_if.c b/rtemsbsd/local/cryptodev_if.c
index 648003d8..a989d0e8 100644
--- a/rtemsbsd/local/cryptodev_if.c
+++ b/rtemsbsd/local/cryptodev_if.c
@@ -20,35 +20,26 @@
#include <opencrypto/cryptodev.h>
#include <rtems/bsd/local/cryptodev_if.h>
-struct kobj_method cryptodev_newsession_method_default = {
- &cryptodev_newsession_desc, (kobjop_t) kobj_error_method
-};
-struct kobjop_desc cryptodev_newsession_desc = {
- 0, &cryptodev_newsession_method_default
-};
+static int null_freesession(device_t dev,
+ crypto_session_t crypto_session)
+{
+ return 0;
+}
-struct kobj_method cryptodev_freesession_method_default = {
- &cryptodev_freesession_desc, (kobjop_t) kobj_error_method
+struct kobjop_desc cryptodev_newsession_desc = {
+ 0, { &cryptodev_newsession_desc, (kobjop_t)kobj_error_method }
};
struct kobjop_desc cryptodev_freesession_desc = {
- 0, &cryptodev_freesession_method_default
-};
-
-struct kobj_method cryptodev_process_method_default = {
- &cryptodev_process_desc, (kobjop_t) kobj_error_method
+ 0, { &cryptodev_freesession_desc, (kobjop_t)null_freesession }
};
struct kobjop_desc cryptodev_process_desc = {
- 0, &cryptodev_process_method_default
-};
-
-struct kobj_method cryptodev_kprocess_method_default = {
- &cryptodev_kprocess_desc, (kobjop_t) kobj_error_method
+ 0, { &cryptodev_process_desc, (kobjop_t)kobj_error_method }
};
struct kobjop_desc cryptodev_kprocess_desc = {
- 0, &cryptodev_kprocess_method_default
+ 0, { &cryptodev_kprocess_desc, (kobjop_t)kobj_error_method }
};
diff --git a/rtemsbsd/local/ifdi_if.c b/rtemsbsd/local/ifdi_if.c
index e5a81946..e9337b8d 100644
--- a/rtemsbsd/local/ifdi_if.c
+++ b/rtemsbsd/local/ifdi_if.c
@@ -26,6 +26,9 @@
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/iflib.h>
+#include <net/if_clone.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
#include <rtems/bsd/local/ifdi_if.h>
@@ -35,6 +38,18 @@
{
}
+ static int
+ null_knlist_add(if_ctx_t _ctx __unused, struct knote *_kn)
+ {
+ return (0);
+ }
+
+ static int
+ null_knote_event(if_ctx_t _ctx __unused, struct knote *_kn, int _hint)
+ {
+ return (0);
+ }
+
static void
null_timer_op(if_ctx_t _ctx __unused, uint16_t _qsidx __unused)
{
@@ -47,6 +62,12 @@
}
static int
+ null_int_int_op(if_ctx_t _ctx __unused, int arg0 __unused)
+ {
+ return (ENOTSUP);
+ }
+
+ static int
null_queue_intr_enable(if_ctx_t _ctx __unused, uint16_t _qid __unused)
{
return (ENOTSUP);
@@ -98,12 +119,73 @@
return (ENOTSUP);
}
+ static void
+ null_media_status(if_ctx_t ctx __unused, struct ifmediareq *ifmr)
+ {
+ ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+ ifmr->ifm_active = IFM_ETHER | IFM_25G_ACC | IFM_FDX;
+ }
+
+ static int
+ null_cloneattach(if_ctx_t ctx __unused, struct if_clone *ifc __unused,
+ const char *name __unused, caddr_t params __unused)
+ {
+ return (0);
+ }
+
+ static void
+ null_rx_clset(if_ctx_t _ctx __unused, uint16_t _flid __unused,
+ uint16_t _qid __unused, caddr_t *_sdcl __unused)
+ {
+ }
+ static void
+ null_object_info_get(if_ctx_t ctx __unused, void *data __unused, int size __unused)
+ {
+ }
+ static int
+ default_mac_set(if_ctx_t ctx, const uint8_t *mac)
+ {
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ struct sockaddr_dl *sdl;
+
+ if (ifp && ifp->if_addr) {
+ sdl = (struct sockaddr_dl *)ifp->if_addr->ifa_addr;
+ MPASS(sdl->sdl_type == IFT_ETHER);
+ memcpy(LLADDR(sdl), mac, ETHER_ADDR_LEN);
+ }
+ return (0);
+ }
+
+struct kobjop_desc ifdi_knlist_add_desc = {
+ 0, { &ifdi_knlist_add_desc, (kobjop_t)null_knlist_add }
+};
+
+struct kobjop_desc ifdi_knote_event_desc = {
+ 0, { &ifdi_knote_event_desc, (kobjop_t)null_knote_event }
+};
+
+struct kobjop_desc ifdi_object_info_get_desc = {
+ 0, { &ifdi_object_info_get_desc, (kobjop_t)null_object_info_get }
+};
+
struct kobjop_desc ifdi_attach_pre_desc = {
- 0, { &ifdi_attach_pre_desc, (kobjop_t)kobj_error_method }
+ 0, { &ifdi_attach_pre_desc, (kobjop_t)null_int_op }
};
struct kobjop_desc ifdi_attach_post_desc = {
- 0, { &ifdi_attach_post_desc, (kobjop_t)kobj_error_method }
+ 0, { &ifdi_attach_post_desc, (kobjop_t)null_int_op }
+};
+
+struct kobjop_desc ifdi_reinit_pre_desc = {
+ 0, { &ifdi_reinit_pre_desc, (kobjop_t)null_int_op }
+};
+
+struct kobjop_desc ifdi_reinit_post_desc = {
+ 0, { &ifdi_reinit_post_desc, (kobjop_t)null_int_op }
+};
+
+struct kobjop_desc ifdi_cloneattach_desc = {
+ 0, { &ifdi_cloneattach_desc, (kobjop_t)null_cloneattach }
};
struct kobjop_desc ifdi_detach_desc = {
@@ -131,7 +213,11 @@ struct kobjop_desc ifdi_rx_queues_alloc_desc = {
};
struct kobjop_desc ifdi_queues_free_desc = {
- 0, { &ifdi_queues_free_desc, (kobjop_t)kobj_error_method }
+ 0, { &ifdi_queues_free_desc, (kobjop_t)null_void_op }
+};
+
+struct kobjop_desc ifdi_rx_clset_desc = {
+ 0, { &ifdi_rx_clset_desc, (kobjop_t)null_rx_clset }
};
struct kobjop_desc ifdi_init_desc = {
@@ -143,7 +229,7 @@ struct kobjop_desc ifdi_stop_desc = {
};
struct kobjop_desc ifdi_msix_intr_assign_desc = {
- 0, { &ifdi_msix_intr_assign_desc, (kobjop_t)kobj_error_method }
+ 0, { &ifdi_msix_intr_assign_desc, (kobjop_t)null_int_int_op }
};
struct kobjop_desc ifdi_intr_enable_desc = {
@@ -174,6 +260,10 @@ struct kobjop_desc ifdi_mtu_set_desc = {
0, { &ifdi_mtu_set_desc, (kobjop_t)kobj_error_method }
};
+struct kobjop_desc ifdi_mac_set_desc = {
+ 0, { &ifdi_mac_set_desc, (kobjop_t)default_mac_set }
+};
+
struct kobjop_desc ifdi_media_set_desc = {
0, { &ifdi_media_set_desc, (kobjop_t)null_void_op }
};
@@ -207,11 +297,11 @@ struct kobjop_desc ifdi_update_admin_status_desc = {
};
struct kobjop_desc ifdi_media_status_desc = {
- 0, { &ifdi_media_status_desc, (kobjop_t)kobj_error_method }
+ 0, { &ifdi_media_status_desc, (kobjop_t)null_media_status }
};
struct kobjop_desc ifdi_media_change_desc = {
- 0, { &ifdi_media_change_desc, (kobjop_t)kobj_error_method }
+ 0, { &ifdi_media_change_desc, (kobjop_t)null_int_op }
};
struct kobjop_desc ifdi_get_counter_desc = {
@@ -242,6 +332,10 @@ struct kobjop_desc ifdi_watchdog_reset_desc = {
0, { &ifdi_watchdog_reset_desc, (kobjop_t)null_void_op }
};
+struct kobjop_desc ifdi_watchdog_reset_queue_desc = {
+ 0, { &ifdi_watchdog_reset_queue_desc, (kobjop_t)null_timer_op }
+};
+
struct kobjop_desc ifdi_led_func_desc = {
0, { &ifdi_led_func_desc, (kobjop_t)null_led_func }
};
diff --git a/rtemsbsd/local/sdhci_if.c b/rtemsbsd/local/sdhci_if.c
index 1d6c26d4..e50e7a47 100644
--- a/rtemsbsd/local/sdhci_if.c
+++ b/rtemsbsd/local/sdhci_if.c
@@ -16,10 +16,12 @@
#include <sys/queue.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/types.h>
-#include <sys/bus.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
+#include <machine/bus.h>
#include <dev/mmc/bridge.h>
#include <dev/sdhci/sdhci.h>
diff --git a/rtemsbsd/rtems/rtems-kernel-epoch.c b/rtemsbsd/rtems/rtems-kernel-epoch.c
index 9eb8487c..7d42bf32 100644
--- a/rtemsbsd/rtems/rtems-kernel-epoch.c
+++ b/rtemsbsd/rtems/rtems-kernel-epoch.c
@@ -165,8 +165,8 @@ epoch_sysinit(void)
}
SYSINIT(epoch, SI_SUB_TUNABLES, SI_ORDER_SECOND, epoch_sysinit, NULL);
-static void
-epoch_enter_preempt_next(epoch_t epoch, epoch_tracker_t et)
+void
+epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
{
Per_CPU_Control *cpu_self;
ISR_lock_Context lock_context;
@@ -189,8 +189,8 @@ epoch_enter_preempt_next(epoch_t epoch, epoch_tracker_t et)
_Thread_Dispatch_enable(cpu_self);
}
-static void
-epoch_exit_preempt_next(epoch_t epoch, epoch_tracker_t et)
+void
+epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
{
Per_CPU_Control *cpu_self;
ISR_lock_Context lock_context;
@@ -215,23 +215,6 @@ epoch_exit_preempt_next(epoch_t epoch, epoch_tracker_t et)
}
}
-/* FIXME: Must be removed in next FreeBSD baseline update step. */
-static __thread epoch_tracker_t et;
-
-void
-epoch_enter_preempt(epoch_t epoch)
-{
-
- epoch_enter_preempt_next(epoch, &et);
-}
-
-void
-epoch_exit_preempt(epoch_t epoch)
-{
-
- epoch_exit_preempt_next(epoch, &et);
-}
-
static void
epoch_block_handler(struct ck_epoch *g __unused, ck_epoch_record_t *c __unused,
void *arg __unused)
diff --git a/freebsd/sys/arm/at91/at91_mci.c b/rtemsbsd/sys/arm/at91/at91_mci.c
index c25983b7..c25983b7 100644
--- a/freebsd/sys/arm/at91/at91_mci.c
+++ b/rtemsbsd/sys/arm/at91/at91_mci.c
diff --git a/freebsd/sys/arm/at91/at91_mcireg.h b/rtemsbsd/sys/arm/at91/at91_mcireg.h
index 80acf48d..80acf48d 100644
--- a/freebsd/sys/arm/at91/at91_mcireg.h
+++ b/rtemsbsd/sys/arm/at91/at91_mcireg.h
diff --git a/freebsd/sys/arm/at91/at91_pdcreg.h b/rtemsbsd/sys/arm/at91/at91_pdcreg.h
index 659804bd..659804bd 100644
--- a/freebsd/sys/arm/at91/at91_pdcreg.h
+++ b/rtemsbsd/sys/arm/at91/at91_pdcreg.h
diff --git a/freebsd/sys/arm/at91/at91reg.h b/rtemsbsd/sys/arm/at91/at91reg.h
index f5791bd7..f5791bd7 100644
--- a/freebsd/sys/arm/at91/at91reg.h
+++ b/rtemsbsd/sys/arm/at91/at91reg.h
diff --git a/freebsd/sys/arm/at91/at91var.h b/rtemsbsd/sys/arm/at91/at91var.h
index 84c898fb..84c898fb 100644
--- a/freebsd/sys/arm/at91/at91var.h
+++ b/rtemsbsd/sys/arm/at91/at91var.h
diff --git a/testsuite/epoch01/test_main.c b/testsuite/epoch01/test_main.c
index 7f8003b5..7f90fc5f 100644
--- a/testsuite/epoch01/test_main.c
+++ b/testsuite/epoch01/test_main.c
@@ -282,9 +282,11 @@ test_enter_exit_preempt_body(rtems_test_parallel_context *base, void *arg,
counter = 0;
while (!rtems_test_parallel_stop_job(&ctx->base)) {
- epoch_enter_preempt(e);
+ struct epoch_tracker et;
+
+ epoch_enter_preempt(e, &et);
++counter;
- epoch_exit_preempt(e);
+ epoch_exit_preempt(e, &et);
}
ctx->stats.counter[worker_index] = counter;
@@ -315,12 +317,13 @@ test_enter_list_op_exit_preempt_body(rtems_test_parallel_context *base,
memset(item_counter, 0, sizeof(item_counter));
while (!rtems_test_parallel_stop_job(&ctx->base)) {
+ struct epoch_tracker et;
test_item *prev;
test_item *item;
test_item *tmp;
test_item *rm;
- epoch_enter_preempt(e);
+ epoch_enter_preempt(e, &et);
++counter;
prev = NULL;
@@ -343,7 +346,7 @@ test_enter_list_op_exit_preempt_body(rtems_test_parallel_context *base,
prev = item;
}
- epoch_exit_preempt(e);
+ epoch_exit_preempt(e, &et);
if (rm != NULL) {
epoch_call(e, &rm->ec, test_list_callback);
@@ -410,11 +413,13 @@ test_enter_mutex_exit_preempt_body(rtems_test_parallel_context *base,
mtx = &ctx->mtx[worker_index % RTEMS_ARRAY_SIZE(ctx->mtx)];
while (!rtems_test_parallel_stop_job(&ctx->base)) {
- epoch_enter_preempt(e);
+ struct epoch_tracker et;
+
+ epoch_enter_preempt(e, &et);
rtems_mutex_lock(mtx);
++counter;
rtems_mutex_unlock(mtx);
- epoch_exit_preempt(e);
+ epoch_exit_preempt(e, &et);
}
ctx->stats.counter[worker_index] = counter;