From 3489e3b6396ee9944a6a2e19e675ca54c36993b4 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 22 Aug 2018 14:59:50 +0200 Subject: Update to FreeBSD head 2018-09-17 Git mirror commit 6c2192b1ef8c50788c751f878552526800b1e319. Update #3472. --- Makefile.todo | 14 +- freebsd-org | 2 +- freebsd/contrib/tcpdump/tcpdump.c | 3 + freebsd/contrib/wpa/src/ap/ap_config.h | 55 +- freebsd/contrib/wpa/src/ap/ap_drv_ops.c | 228 +- freebsd/contrib/wpa/src/ap/ap_drv_ops.h | 18 +- freebsd/contrib/wpa/src/ap/hostapd.h | 56 +- freebsd/contrib/wpa/src/ap/ieee802_11.h | 33 +- freebsd/contrib/wpa/src/ap/ieee802_11_auth.h | 5 +- freebsd/contrib/wpa/src/ap/ieee802_11_shared.c | 78 + freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h | 14 +- freebsd/contrib/wpa/src/ap/sta_info.h | 74 +- freebsd/contrib/wpa/src/ap/vlan.h | 30 + freebsd/contrib/wpa/src/ap/wpa_auth.c | 226 +- freebsd/contrib/wpa/src/ap/wpa_auth.h | 42 +- freebsd/contrib/wpa/src/ap/wpa_auth_ft.c | 10 +- freebsd/contrib/wpa/src/ap/wpa_auth_i.h | 4 +- freebsd/contrib/wpa/src/common/ctrl_iface_common.c | 175 + freebsd/contrib/wpa/src/common/ctrl_iface_common.h | 38 + freebsd/contrib/wpa/src/common/defs.h | 15 +- freebsd/contrib/wpa/src/common/eapol_common.h | 2 +- freebsd/contrib/wpa/src/common/ieee802_11_common.c | 212 +- freebsd/contrib/wpa/src/common/ieee802_11_common.h | 28 + freebsd/contrib/wpa/src/common/ieee802_11_defs.h | 245 +- freebsd/contrib/wpa/src/common/qca-vendor.h | 1235 +++++- freebsd/contrib/wpa/src/common/sae.h | 1 + freebsd/contrib/wpa/src/common/version.h | 6 +- freebsd/contrib/wpa/src/common/wpa_common.c | 141 +- freebsd/contrib/wpa/src/common/wpa_common.h | 4 +- freebsd/contrib/wpa/src/common/wpa_ctrl.h | 32 + freebsd/contrib/wpa/src/crypto/aes-omac1.c | 3 + freebsd/contrib/wpa/src/crypto/crypto.h | 25 +- freebsd/contrib/wpa/src/crypto/crypto_openssl.c | 403 +- freebsd/contrib/wpa/src/crypto/ms_funcs.c | 2 +- freebsd/contrib/wpa/src/crypto/sha256-internal.c | 3 + freebsd/contrib/wpa/src/crypto/sha256-prf.c | 26 +- freebsd/contrib/wpa/src/crypto/sha256.h | 12 +- freebsd/contrib/wpa/src/crypto/tls.h | 47 +- freebsd/contrib/wpa/src/crypto/tls_internal.c | 64 +- freebsd/contrib/wpa/src/drivers/driver.h | 344 +- freebsd/contrib/wpa/src/drivers/driver_bsd.c | 355 +- freebsd/contrib/wpa/src/drivers/driver_common.c | 57 +- freebsd/contrib/wpa/src/drivers/driver_ndis.c | 16 +- freebsd/contrib/wpa/src/drivers/driver_nl80211.h | 36 +- freebsd/contrib/wpa/src/drivers/driver_wired.c | 14 +- freebsd/contrib/wpa/src/drivers/drivers.c | 36 - freebsd/contrib/wpa/src/eap_peer/eap.c | 80 +- freebsd/contrib/wpa/src/eap_peer/eap_config.h | 20 +- freebsd/contrib/wpa/src/eap_peer/eap_gtc.c | 6 +- freebsd/contrib/wpa/src/eap_peer/eap_i.h | 2 + freebsd/contrib/wpa/src/eap_peer/eap_leap.c | 6 +- freebsd/contrib/wpa/src/eap_peer/eap_md5.c | 6 +- freebsd/contrib/wpa/src/eap_peer/eap_methods.c | 17 +- freebsd/contrib/wpa/src/eap_peer/eap_methods.h | 1 - freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c | 6 +- freebsd/contrib/wpa/src/eap_peer/eap_otp.c | 6 +- freebsd/contrib/wpa/src/eap_peer/eap_peap.c | 76 +- freebsd/contrib/wpa/src/eap_peer/eap_psk.c | 6 +- freebsd/contrib/wpa/src/eap_peer/eap_tls.c | 60 +- freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c | 23 +- freebsd/contrib/wpa/src/eap_peer/eap_ttls.c | 128 +- freebsd/contrib/wpa/src/eap_server/eap_methods.h | 1 - freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c | 10 + freebsd/contrib/wpa/src/p2p/p2p.h | 71 +- freebsd/contrib/wpa/src/radius/radius.h | 19 +- freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c | 13 +- freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h | 8 +- freebsd/contrib/wpa/src/rsn_supp/preauth.c | 6 +- freebsd/contrib/wpa/src/rsn_supp/preauth.h | 6 +- freebsd/contrib/wpa/src/rsn_supp/wpa.c | 172 +- freebsd/contrib/wpa/src/rsn_supp/wpa.h | 14 +- freebsd/contrib/wpa/src/rsn_supp/wpa_i.h | 15 +- freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c | 6 +- freebsd/contrib/wpa/src/tls/tlsv1_client.h | 10 +- freebsd/contrib/wpa/src/tls/tlsv1_cred.h | 8 + freebsd/contrib/wpa/src/utils/common.c | 83 +- freebsd/contrib/wpa/src/utils/common.h | 16 + freebsd/contrib/wpa/src/utils/eloop.c | 292 +- freebsd/contrib/wpa/src/utils/eloop.h | 8 + freebsd/contrib/wpa/src/utils/module_tests.h | 20 + freebsd/contrib/wpa/src/utils/os.h | 4 + freebsd/contrib/wpa/src/utils/os_unix.c | 7 +- freebsd/contrib/wpa/src/utils/platform.h | 4 +- freebsd/contrib/wpa/src/utils/trace.h | 2 + freebsd/contrib/wpa/src/utils/wpa_debug.c | 24 +- freebsd/contrib/wpa/src/utils/wpabuf.c | 30 + freebsd/contrib/wpa/src/utils/wpabuf.h | 17 +- freebsd/contrib/wpa/src/wps/wps.c | 6 +- freebsd/contrib/wpa/src/wps/wps.h | 14 +- freebsd/contrib/wpa/src/wps/wps_attr_build.c | 31 +- freebsd/contrib/wpa/src/wps/wps_attr_parse.c | 4 +- freebsd/contrib/wpa/src/wps/wps_attr_process.c | 10 + freebsd/contrib/wpa/src/wps/wps_common.c | 47 +- freebsd/contrib/wpa/src/wps/wps_defs.h | 4 + freebsd/contrib/wpa/src/wps/wps_enrollee.c | 33 +- freebsd/contrib/wpa/src/wps/wps_i.h | 4 +- freebsd/contrib/wpa/src/wps/wps_registrar.c | 77 +- freebsd/contrib/wpa/src/wps/wps_upnp.c | 11 +- freebsd/contrib/wpa/src/wps/wps_upnp.h | 3 + freebsd/contrib/wpa/src/wps/wps_upnp_i.h | 3 +- freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c | 6 - freebsd/contrib/wpa/src/wps/wps_upnp_web.c | 88 +- freebsd/contrib/wpa/wpa_supplicant/ap.h | 10 +- freebsd/contrib/wpa/wpa_supplicant/autoscan.h | 10 + freebsd/contrib/wpa/wpa_supplicant/bgscan.h | 9 + freebsd/contrib/wpa/wpa_supplicant/binder/binder.h | 46 + freebsd/contrib/wpa/wpa_supplicant/bss.c | 97 +- freebsd/contrib/wpa/wpa_supplicant/bss.h | 20 + freebsd/contrib/wpa/wpa_supplicant/config.c | 190 +- freebsd/contrib/wpa/wpa_supplicant/config.h | 88 +- freebsd/contrib/wpa/wpa_supplicant/config_file.c | 45 + freebsd/contrib/wpa/wpa_supplicant/config_ssid.h | 45 + freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c | 1051 +++-- .../contrib/wpa/wpa_supplicant/ctrl_iface_unix.c | 358 +- freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h | 7 +- freebsd/contrib/wpa/wpa_supplicant/driver_i.h | 82 +- freebsd/contrib/wpa/wpa_supplicant/events.c | 529 ++- freebsd/contrib/wpa/wpa_supplicant/gas_query.c | 154 +- freebsd/contrib/wpa/wpa_supplicant/gas_query.h | 2 - .../contrib/wpa/wpa_supplicant/hs20_supplicant.c | 313 +- .../contrib/wpa/wpa_supplicant/hs20_supplicant.h | 15 +- freebsd/contrib/wpa/wpa_supplicant/ibss_rsn.h | 3 +- freebsd/contrib/wpa/wpa_supplicant/interworking.c | 231 +- freebsd/contrib/wpa/wpa_supplicant/interworking.h | 3 +- freebsd/contrib/wpa/wpa_supplicant/main.c | 96 +- freebsd/contrib/wpa/wpa_supplicant/mesh.h | 3 + freebsd/contrib/wpa/wpa_supplicant/mesh_mpm.h | 5 +- freebsd/contrib/wpa/wpa_supplicant/mesh_rsn.h | 11 +- freebsd/contrib/wpa/wpa_supplicant/notify.c | 25 +- freebsd/contrib/wpa/wpa_supplicant/notify.h | 3 +- freebsd/contrib/wpa/wpa_supplicant/offchannel.c | 52 +- .../contrib/wpa/wpa_supplicant/p2p_supplicant.h | 26 +- freebsd/contrib/wpa/wpa_supplicant/scan.c | 471 ++- freebsd/contrib/wpa/wpa_supplicant/scan.h | 13 +- freebsd/contrib/wpa/wpa_supplicant/wmm_ac.h | 2 +- freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h | 2 +- .../contrib/wpa/wpa_supplicant/wpa_supplicant.c | 1197 +++++- .../contrib/wpa/wpa_supplicant/wpa_supplicant_i.h | 148 +- freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c | 11 +- .../contrib/wpa/wpa_supplicant/wps_supplicant.c | 46 +- .../contrib/wpa/wpa_supplicant/wps_supplicant.h | 7 + freebsd/crypto/openssl/crypto/asn1/a_bool.c | 24 +- freebsd/crypto/openssl/crypto/asn1/a_object.c | 21 +- freebsd/crypto/openssl/crypto/asn1/a_strex.c | 27 +- freebsd/crypto/openssl/crypto/asn1/ameth_lib.c | 14 +- freebsd/crypto/openssl/crypto/asn1/asn1.h | 8 +- freebsd/crypto/openssl/crypto/asn1/asn1_err.c | 3 + freebsd/crypto/openssl/crypto/asn1/tasn_enc.c | 4 +- freebsd/crypto/openssl/crypto/bio/bss_log.c | 4 +- freebsd/crypto/openssl/crypto/bio/bss_mem.c | 2 + freebsd/crypto/openssl/crypto/bn/bn.h | 106 +- freebsd/crypto/openssl/crypto/bn/bn_div.c | 1 + freebsd/crypto/openssl/crypto/bn/bn_exp.c | 69 +- freebsd/crypto/openssl/crypto/bn/bn_gf2m.c | 34 +- freebsd/crypto/openssl/crypto/bn/bn_lcl.h | 3 +- freebsd/crypto/openssl/crypto/bn/bn_lib.c | 57 +- freebsd/crypto/openssl/crypto/bn/bn_mod.c | 69 +- freebsd/crypto/openssl/crypto/bn/bn_mont.c | 58 +- freebsd/crypto/openssl/crypto/bn/bn_sqr.c | 10 +- freebsd/crypto/openssl/crypto/bn_int.h | 15 + freebsd/crypto/openssl/crypto/conf/conf_api.c | 2 + freebsd/crypto/openssl/crypto/dh/dh_key.c | 7 +- freebsd/crypto/openssl/crypto/dh/dh_pmeth.c | 4 +- freebsd/crypto/openssl/crypto/dsa/dsa.h | 9 +- freebsd/crypto/openssl/crypto/dsa/dsa_err.c | 3 +- freebsd/crypto/openssl/crypto/dsa/dsa_gen.c | 13 +- freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c | 73 +- freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c | 12 +- freebsd/crypto/openssl/crypto/ec/ec_ameth.c | 22 +- freebsd/crypto/openssl/crypto/ec/ec_lib.c | 10 +- freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c | 23 +- freebsd/crypto/openssl/crypto/ecdsa/ecdsatest.c | 11 +- freebsd/crypto/openssl/crypto/ecdsa/ecs_ossl.c | 32 +- freebsd/crypto/openssl/crypto/engine/eng_lib.c | 8 +- freebsd/crypto/openssl/crypto/engine/tb_asnmth.c | 4 +- freebsd/crypto/openssl/crypto/o_time.c | 4 + freebsd/crypto/openssl/crypto/opensslv.h | 6 +- freebsd/crypto/openssl/crypto/pem/pem.h | 3 +- freebsd/crypto/openssl/crypto/pem/pem_lib.c | 59 +- freebsd/crypto/openssl/crypto/pem/pem_pk8.c | 2 +- freebsd/crypto/openssl/crypto/pem/pem_pkey.c | 2 +- freebsd/crypto/openssl/crypto/pem/pvkfmt.c | 4 +- freebsd/crypto/openssl/crypto/pkcs12/p12_asn.c | 4 +- freebsd/crypto/openssl/crypto/rsa/rsa_eay.c | 41 +- freebsd/crypto/openssl/crypto/rsa/rsa_gen.c | 2 + freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c | 41 +- freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c | 62 +- freebsd/crypto/openssl/crypto/rsa/rsa_sign.c | 4 +- freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c | 8 + freebsd/crypto/openssl/crypto/ui/ui_openssl.c | 8 +- freebsd/crypto/openssl/crypto/x509/x509_cmp.c | 2 +- freebsd/crypto/openssl/crypto/x509/x509_lu.c | 16 + freebsd/crypto/openssl/crypto/x509/x509_vfy.c | 147 +- freebsd/crypto/openssl/crypto/x509v3/v3_purp.c | 27 +- freebsd/crypto/openssl/ssl/d1_both.c | 5 +- freebsd/crypto/openssl/ssl/s3_lib.c | 12 +- freebsd/crypto/openssl/ssl/s3_srvr.c | 26 +- freebsd/crypto/openssl/ssl/ssl.h | 7 +- freebsd/crypto/openssl/ssl/ssl_lib.c | 31 +- freebsd/crypto/openssl/ssl/ssl_locl.h | 4 +- freebsd/crypto/openssl/ssl/t1_lib.c | 5 +- freebsd/crypto/openssl/ssl/t1_trce.c | 16 +- freebsd/include/nl_types.h | 99 + freebsd/lib/libc/gen/err.c | 4 +- freebsd/lib/libc/gen/getdomainname.c | 4 +- freebsd/lib/libc/gen/gethostname.c | 4 +- freebsd/lib/libc/gen/sethostname.c | 4 +- freebsd/lib/libc/include/libc_private.h | 2 - freebsd/lib/libc/include/namespace.h | 1 + freebsd/lib/libc/include/un-namespace.h | 1 + freebsd/lib/libc/inet/inet_addr.c | 7 +- freebsd/lib/libc/resolv/res_init.c | 2 + freebsd/lib/libcapsicum/capsicum_helpers.h | 149 + freebsd/lib/libcasper/libcasper/libcasper.h | 6 +- freebsd/lib/libkvm/kvm.h | 4 - freebsd/lib/libutil/libutil.h | 1 + freebsd/sbin/dhclient/bpf.c | 8 +- freebsd/sbin/dhclient/clparse.c | 5 +- freebsd/sbin/dhclient/conflex.c | 5 +- freebsd/sbin/dhclient/dhclient.c | 78 +- freebsd/sbin/dhclient/dhcpd.h | 4 +- freebsd/sbin/dhclient/dispatch.c | 22 +- freebsd/sbin/dhclient/options.c | 4 +- freebsd/sbin/dhclient/privsep.c | 6 +- freebsd/sbin/dhclient/privsep.h | 5 - freebsd/sbin/ifconfig/ifconfig.c | 2 +- freebsd/sbin/ifconfig/ifieee80211.c | 20 +- freebsd/sbin/pfctl/parse.c | 4272 ++++++++++---------- freebsd/sbin/pfctl/parse.h | 127 +- freebsd/sbin/pfctl/parse.y | 51 +- freebsd/sbin/pfctl/pfctl.c | 97 +- freebsd/sbin/pfctl/pfctl_altq.c | 69 +- freebsd/sbin/pfctl/pfctl_parser.c | 6 + freebsd/sbin/pfctl/pfctl_parser.h | 4 +- freebsd/sbin/pfctl/pfctl_qstats.c | 10 +- freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h | 4 +- freebsd/sbin/pfctl/rtems-bsd-pfctl-parse-data.h | 1 + freebsd/sbin/sysctl/sysctl.c | 40 +- freebsd/sys/arm/at91/at91_mci.c | 1713 -------- freebsd/sys/arm/at91/at91_mcireg.h | 183 - freebsd/sys/arm/at91/at91_pdcreg.h | 50 - freebsd/sys/arm/at91/at91reg.h | 92 - freebsd/sys/arm/at91/at91var.h | 175 - freebsd/sys/arm/include/machine/cpufunc.h | 157 +- freebsd/sys/cam/cam_ccb.h | 42 - freebsd/sys/cam/cam_xpt.h | 1 + freebsd/sys/cam/mmc/mmc.h | 8 + freebsd/sys/contrib/ck/include/ck_pr.h | 49 +- freebsd/sys/contrib/ck/include/ck_queue.h | 14 +- freebsd/sys/contrib/ck/include/gcc/ppc/ck_pr.h | 32 +- freebsd/sys/contrib/ck/include/gcc/x86/ck_pr.h | 10 +- freebsd/sys/contrib/ck/include/gcc/x86_64/ck_pr.h | 10 +- .../poly1305/donna/poly1305_donna.c | 126 + .../poly1305/donna/poly1305_donna.h | 12 + .../poly1305/donna/poly1305_donna32.h | 235 ++ .../poly1305/onetimeauth_poly1305.c | 92 + .../poly1305/onetimeauth_poly1305.h | 21 + .../src/libsodium/crypto_verify/sodium/verify.c | 100 + .../include/sodium/crypto_onetimeauth_poly1305.h | 67 + .../libsodium/include/sodium/crypto_verify_16.h | 23 + .../libsodium/include/sodium/crypto_verify_32.h | 23 + .../libsodium/include/sodium/crypto_verify_64.h | 23 + .../src/libsodium/include/sodium/export.h | 57 + .../src/libsodium/include/sodium/private/common.h | 246 ++ .../include/sodium/private/implementations.h | 11 + .../src/libsodium/include/sodium/randombytes.h | 68 + .../src/libsodium/include/sodium/runtime.h | 52 + .../libsodium/src/libsodium/include/sodium/utils.h | 170 + freebsd/sys/crypto/chacha20/chacha.c | 11 +- freebsd/sys/crypto/chacha20/chacha.h | 12 +- freebsd/sys/crypto/libsodium/utils.c | 16 + freebsd/sys/crypto/sha2/sha224.h | 96 + freebsd/sys/crypto/sha2/sha256c.c | 60 +- freebsd/sys/crypto/sha2/sha512c.c | 8 +- freebsd/sys/crypto/skein/skein.c | 3 + freebsd/sys/dev/bfe/if_bfe.c | 2 + freebsd/sys/dev/bge/if_bge.c | 16 +- freebsd/sys/dev/dc/if_dc.c | 2 + freebsd/sys/dev/e1000/if_em.c | 134 +- freebsd/sys/dev/e1000/if_em.h | 7 +- freebsd/sys/dev/evdev/cdev.c | 4 +- freebsd/sys/dev/evdev/evdev.c | 14 +- freebsd/sys/dev/evdev/evdev.h | 11 +- freebsd/sys/dev/evdev/evdev_utils.c | 42 - freebsd/sys/dev/evdev/input-event-codes.h | 36 + freebsd/sys/dev/evdev/input.h | 6 + freebsd/sys/dev/evdev/uinput.c | 6 +- freebsd/sys/dev/fxp/if_fxp.c | 2 + freebsd/sys/dev/kbd/kbd.c | 39 + freebsd/sys/dev/kbd/kbdreg.h | 4 + freebsd/sys/dev/mii/icsphy.c | 2 - freebsd/sys/dev/mmc/mmc.c | 57 +- freebsd/sys/dev/mmc/mmcbrvar.h | 15 +- freebsd/sys/dev/mmc/mmcsd.c | 18 +- freebsd/sys/dev/nvme/nvme.h | 13 +- freebsd/sys/dev/ofw/ofw_bus_subr.c | 4 + freebsd/sys/dev/ofw/ofw_fdt.c | 7 +- freebsd/sys/dev/ofw/ofw_subr.c | 47 +- freebsd/sys/dev/pci/pci.c | 257 +- freebsd/sys/dev/pci/pci_user.c | 113 +- freebsd/sys/dev/pci/pcivar.h | 64 +- freebsd/sys/dev/rtwn/rtl8812a/r12a_reg.h | 10 + freebsd/sys/dev/rtwn/rtl8812a/usb/r12au.h | 1 + freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_init.c | 33 +- freebsd/sys/dev/rtwn/rtl8821a/usb/r21au.h | 1 - freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c | 2 +- freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_init.c | 11 - freebsd/sys/dev/sdhci/sdhci.c | 65 +- freebsd/sys/dev/usb/controller/usb_controller.c | 1 - freebsd/sys/dev/usb/input/uep.c | 105 +- freebsd/sys/dev/usb/input/ukbd.c | 20 +- freebsd/sys/dev/usb/input/ums.c | 12 +- freebsd/sys/dev/usb/net/if_ure.c | 1 + freebsd/sys/dev/usb/serial/u3g.c | 1 + freebsd/sys/dev/usb/usb_hid.c | 18 +- freebsd/sys/dev/usb/usb_request.c | 29 +- freebsd/sys/dev/usb/wlan/if_run.c | 2 + freebsd/sys/i386/include/machine/cpufunc.h | 9 + freebsd/sys/i386/include/machine/intr_machdep.h | 190 +- freebsd/sys/kern/init_main.c | 24 +- freebsd/sys/kern/kern_event.c | 116 +- freebsd/sys/kern/kern_intr.c | 193 +- freebsd/sys/kern/kern_sysctl.c | 102 +- freebsd/sys/kern/kern_time.c | 4 +- freebsd/sys/kern/subr_blist.c | 14 +- freebsd/sys/kern/subr_bus.c | 133 +- freebsd/sys/kern/subr_counter.c | 15 +- freebsd/sys/kern/subr_gtaskqueue.c | 18 + freebsd/sys/kern/subr_hints.c | 353 +- freebsd/sys/kern/subr_module.c | 36 +- freebsd/sys/kern/subr_pcpu.c | 2 +- freebsd/sys/kern/subr_prf.c | 25 +- freebsd/sys/kern/sys_pipe.c | 99 +- freebsd/sys/kern/uipc_sockbuf.c | 79 +- freebsd/sys/kern/uipc_socket.c | 28 +- freebsd/sys/kern/uipc_syscalls.c | 97 +- freebsd/sys/kern/uipc_usrreq.c | 157 +- freebsd/sys/mips/include/machine/cpuregs.h | 94 +- freebsd/sys/net/altq/altq.h | 29 +- freebsd/sys/net/altq/altq_cbq.c | 2 +- freebsd/sys/net/altq/altq_cbq.h | 6 + freebsd/sys/net/altq/altq_codel.c | 2 +- freebsd/sys/net/altq/altq_codel.h | 6 + freebsd/sys/net/altq/altq_fairq.c | 2 +- freebsd/sys/net/altq/altq_fairq.h | 6 + freebsd/sys/net/altq/altq_hfsc.c | 161 +- freebsd/sys/net/altq/altq_hfsc.h | 97 +- freebsd/sys/net/altq/altq_priq.c | 2 +- freebsd/sys/net/altq/altq_priq.h | 6 + freebsd/sys/net/altq/altq_subr.c | 58 +- freebsd/sys/net/altq/altq_var.h | 13 +- freebsd/sys/net/altq/if_altq.h | 4 + freebsd/sys/net/bpf.c | 16 +- freebsd/sys/net/bpf_jitter.c | 6 +- freebsd/sys/net/bpf_jitter.h | 1 - freebsd/sys/net/bpfdesc.h | 5 - freebsd/sys/net/ieee8023ad_lacp.c | 69 +- freebsd/sys/net/if.c | 89 +- freebsd/sys/net/if_bridge.c | 24 +- freebsd/sys/net/if_clone.c | 2 +- freebsd/sys/net/if_disc.c | 2 +- freebsd/sys/net/if_edsc.c | 2 +- freebsd/sys/net/if_enc.c | 12 +- freebsd/sys/net/if_epair.c | 17 +- freebsd/sys/net/if_ethersubr.c | 7 +- freebsd/sys/net/if_gif.c | 547 +-- freebsd/sys/net/if_gif.h | 58 +- freebsd/sys/net/if_gre.c | 668 +-- freebsd/sys/net/if_gre.h | 46 +- freebsd/sys/net/if_ipsec.c | 8 +- freebsd/sys/net/if_lagg.c | 32 +- freebsd/sys/net/if_llatbl.c | 7 +- freebsd/sys/net/if_loop.c | 3 +- freebsd/sys/net/if_media.h | 168 + freebsd/sys/net/if_stf.c | 42 +- freebsd/sys/net/if_tun.c | 2 +- freebsd/sys/net/if_var.h | 31 +- freebsd/sys/net/if_vlan.c | 17 +- freebsd/sys/net/if_vlan_var.h | 3 + freebsd/sys/net/iflib.h | 10 +- freebsd/sys/net/netisr.c | 2 +- freebsd/sys/net/pfvar.h | 120 +- freebsd/sys/net/radix.c | 2 +- freebsd/sys/net/radix.h | 26 +- freebsd/sys/net/radix_mpath.c | 3 + freebsd/sys/net/route.c | 9 +- freebsd/sys/net/route.h | 6 +- freebsd/sys/net/route_var.h | 19 +- freebsd/sys/net/rtsock.c | 14 +- freebsd/sys/net/vnet.h | 20 +- freebsd/sys/net80211/ieee80211.c | 23 +- freebsd/sys/net80211/ieee80211_hwmp.c | 2 +- freebsd/sys/net80211/ieee80211_node.c | 19 +- freebsd/sys/netinet/cc/cc_newreno.c | 8 +- freebsd/sys/netinet/if_ether.c | 12 +- freebsd/sys/netinet/igmp.c | 26 +- freebsd/sys/netinet/in.c | 9 +- freebsd/sys/netinet/in_fib.c | 4 +- freebsd/sys/netinet/in_gif.c | 311 +- freebsd/sys/netinet/in_gif.h | 45 - freebsd/sys/netinet/in_kdtrace.h | 23 + freebsd/sys/netinet/in_mcast.c | 39 +- freebsd/sys/netinet/in_pcb.c | 589 ++- freebsd/sys/netinet/in_pcb.h | 167 +- freebsd/sys/netinet/ip.h | 5 + freebsd/sys/netinet/ip6.h | 1 + freebsd/sys/netinet/ip_carp.c | 46 +- freebsd/sys/netinet/ip_divert.c | 49 +- freebsd/sys/netinet/ip_encap.c | 470 +-- freebsd/sys/netinet/ip_encap.h | 47 +- freebsd/sys/netinet/ip_fastfwd.c | 26 +- freebsd/sys/netinet/ip_fw.h | 2 + freebsd/sys/netinet/ip_gre.c | 243 +- freebsd/sys/netinet/ip_icmp.c | 24 +- freebsd/sys/netinet/ip_id.c | 20 +- freebsd/sys/netinet/ip_input.c | 10 +- freebsd/sys/netinet/ip_mroute.c | 86 +- freebsd/sys/netinet/ip_options.c | 4 +- freebsd/sys/netinet/ip_output.c | 71 +- freebsd/sys/netinet/ip_reass.c | 203 +- freebsd/sys/netinet/libalias/alias.c | 12 +- freebsd/sys/netinet/libalias/alias_irc.c | 3 +- freebsd/sys/netinet/libalias/alias_mod.h | 8 +- freebsd/sys/netinet/pim_var.h | 2 - freebsd/sys/netinet/raw_ip.c | 102 +- freebsd/sys/netinet/sctp.h | 2 +- freebsd/sys/netinet/sctp_asconf.c | 39 +- freebsd/sys/netinet/sctp_asconf.h | 4 +- freebsd/sys/netinet/sctp_auth.c | 8 + freebsd/sys/netinet/sctp_auth.h | 40 +- freebsd/sys/netinet/sctp_bsd_addr.c | 2 + freebsd/sys/netinet/sctp_cc_functions.c | 10 +- freebsd/sys/netinet/sctp_constants.h | 12 +- freebsd/sys/netinet/sctp_dtrace_define.h | 2 +- freebsd/sys/netinet/sctp_header.h | 26 +- freebsd/sys/netinet/sctp_indata.c | 66 +- freebsd/sys/netinet/sctp_indata.h | 3 +- freebsd/sys/netinet/sctp_input.c | 154 +- freebsd/sys/netinet/sctp_input.h | 2 +- freebsd/sys/netinet/sctp_os_bsd.h | 2 +- freebsd/sys/netinet/sctp_output.c | 145 +- freebsd/sys/netinet/sctp_output.h | 10 +- freebsd/sys/netinet/sctp_pcb.c | 67 +- freebsd/sys/netinet/sctp_pcb.h | 14 +- freebsd/sys/netinet/sctp_peeloff.c | 6 +- freebsd/sys/netinet/sctp_structs.h | 57 +- freebsd/sys/netinet/sctp_sysctl.c | 2 +- freebsd/sys/netinet/sctp_timer.c | 23 +- freebsd/sys/netinet/sctp_uio.h | 71 +- freebsd/sys/netinet/sctp_usrreq.c | 71 +- freebsd/sys/netinet/sctp_var.h | 4 +- freebsd/sys/netinet/sctputil.c | 112 +- freebsd/sys/netinet/sctputil.h | 31 +- freebsd/sys/netinet/tcp_hostcache.c | 4 +- freebsd/sys/netinet/tcp_hpts.h | 4 +- freebsd/sys/netinet/tcp_input.c | 167 +- freebsd/sys/netinet/tcp_log_buf.h | 6 +- freebsd/sys/netinet/tcp_output.c | 245 +- freebsd/sys/netinet/tcp_reass.c | 975 ++++- freebsd/sys/netinet/tcp_subr.c | 165 +- freebsd/sys/netinet/tcp_syncache.c | 92 +- freebsd/sys/netinet/tcp_syncache.h | 1 - freebsd/sys/netinet/tcp_timer.c | 197 +- freebsd/sys/netinet/tcp_timer.h | 17 +- freebsd/sys/netinet/tcp_timewait.c | 116 +- freebsd/sys/netinet/tcp_usrreq.c | 238 +- freebsd/sys/netinet/tcp_var.h | 56 +- freebsd/sys/netinet/udp_usrreq.c | 105 +- freebsd/sys/netinet/udplite.h | 11 + freebsd/sys/netinet6/frag6.c | 331 +- freebsd/sys/netinet6/icmp6.c | 11 +- freebsd/sys/netinet6/in6.c | 3 - freebsd/sys/netinet6/in6_fib.c | 4 +- freebsd/sys/netinet6/in6_gif.c | 337 +- freebsd/sys/netinet6/in6_ifattach.c | 2 +- freebsd/sys/netinet6/in6_mcast.c | 46 +- freebsd/sys/netinet6/in6_pcb.c | 189 +- freebsd/sys/netinet6/in6_proto.c | 37 +- freebsd/sys/netinet6/in6_rmx.c | 4 +- freebsd/sys/netinet6/in6_src.c | 6 +- freebsd/sys/netinet6/in6_var.h | 2 +- freebsd/sys/netinet6/ip6_input.c | 4 +- freebsd/sys/netinet6/ip6_mroute.c | 55 +- freebsd/sys/netinet6/ip6_output.c | 57 +- freebsd/sys/netinet6/ip6_var.h | 8 +- freebsd/sys/netinet6/mld6.c | 43 +- freebsd/sys/netinet6/nd6.c | 6 +- freebsd/sys/netinet6/nd6_nbr.c | 8 +- freebsd/sys/netinet6/nd6_rtr.c | 2 +- freebsd/sys/netinet6/pim6_var.h | 4 - freebsd/sys/netinet6/raw_ip6.c | 7 +- freebsd/sys/netinet6/scope6.c | 4 +- freebsd/sys/netinet6/scope6_var.h | 2 +- freebsd/sys/netinet6/sctp6_usrreq.c | 9 +- freebsd/sys/netinet6/sctp6_var.h | 4 +- freebsd/sys/netinet6/udp6_usrreq.c | 450 ++- freebsd/sys/netipsec/ipsec.c | 17 +- freebsd/sys/netipsec/ipsec.h | 2 +- freebsd/sys/netipsec/key.c | 78 +- freebsd/sys/netipsec/key_debug.c | 87 +- freebsd/sys/netipsec/keydb.h | 3 +- freebsd/sys/netipsec/keysock.c | 2 +- freebsd/sys/netipsec/xform.h | 2 +- freebsd/sys/netipsec/xform_ah.c | 83 +- freebsd/sys/netipsec/xform_esp.c | 21 +- freebsd/sys/netipsec/xform_ipcomp.c | 87 +- freebsd/sys/netipsec/xform_tcp.c | 16 +- freebsd/sys/netpfil/pf/if_pflog.c | 2 +- freebsd/sys/netpfil/pf/if_pfsync.c | 10 +- freebsd/sys/netpfil/pf/pf.c | 206 +- freebsd/sys/netpfil/pf/pf_altq.h | 145 +- freebsd/sys/netpfil/pf/pf_if.c | 41 +- freebsd/sys/netpfil/pf/pf_ioctl.c | 310 +- freebsd/sys/netpfil/pf/pf_norm.c | 16 +- freebsd/sys/netpfil/pf/pf_osfp.c | 2 +- freebsd/sys/netpfil/pf/pf_table.c | 10 +- freebsd/sys/opencrypto/_cryptodev.h | 8 + freebsd/sys/opencrypto/crypto.c | 174 +- freebsd/sys/opencrypto/cryptodev.c | 55 +- freebsd/sys/opencrypto/cryptodev.h | 64 +- freebsd/sys/opencrypto/cryptosoft.c | 335 +- freebsd/sys/opencrypto/cryptosoft.h | 5 +- freebsd/sys/opencrypto/xform_auth.h | 7 + freebsd/sys/opencrypto/xform_md5.c | 4 +- freebsd/sys/opencrypto/xform_poly1305.c | 93 + freebsd/sys/opencrypto/xform_poly1305.h | 16 + freebsd/sys/opencrypto/xform_rmd160.c | 4 +- freebsd/sys/opencrypto/xform_sha1.c | 16 +- freebsd/sys/opencrypto/xform_sha2.c | 81 +- freebsd/sys/powerpc/include/machine/spr.h | 4 +- freebsd/sys/sys/bus.h | 9 +- freebsd/sys/sys/cpu.h | 2 +- freebsd/sys/sys/file.h | 13 +- freebsd/sys/sys/interrupt.h | 13 +- freebsd/sys/sys/jail.h | 5 +- freebsd/sys/sys/libkern.h | 23 - freebsd/sys/sys/linker.h | 3 +- freebsd/sys/sys/malloc.h | 76 +- freebsd/sys/sys/mbuf.h | 7 +- freebsd/sys/sys/module.h | 5 + freebsd/sys/sys/mouse.h | 15 - freebsd/sys/sys/mutex.h | 2 +- freebsd/sys/sys/nv.h | 8 + freebsd/sys/sys/pciio.h | 19 + freebsd/sys/sys/pcpu.h | 59 +- freebsd/sys/sys/proc.h | 21 +- freebsd/sys/sys/random.h | 42 +- freebsd/sys/sys/reboot.h | 9 +- freebsd/sys/sys/sglist.h | 113 + freebsd/sys/sys/sockbuf.h | 8 +- freebsd/sys/sys/socketvar.h | 17 +- freebsd/sys/sys/sockopt.h | 1 - freebsd/sys/sys/sx.h | 4 +- freebsd/sys/sys/sysproto.h | 4 +- freebsd/sys/sys/systm.h | 121 +- freebsd/sys/sys/unpcb.h | 23 +- freebsd/sys/sys/vmmeter.h | 7 + freebsd/sys/vm/uma.h | 23 +- freebsd/sys/vm/uma_core.c | 326 +- freebsd/sys/vm/uma_int.h | 53 +- freebsd/sys/vm/vm_extern.h | 9 +- freebsd/usr.bin/netstat/inet.c | 4 +- freebsd/usr.bin/netstat/unix.c | 2 +- freebsd/usr.bin/vmstat/vmstat.c | 92 +- libbsd.py | 556 +-- .../include/machine/rtems-bsd-kernel-namespace.h | 102 +- rtemsbsd/include/rtems/bsd/local/cryptodev_if.h | 36 +- rtemsbsd/include/rtems/bsd/local/sdhci_if.h | 24 +- rtemsbsd/include/rtems/bsd/local/usbdevs.h | 109 +- rtemsbsd/include/rtems/bsd/local/usbdevs_data.h | 546 ++- rtemsbsd/include/sys/boot.h | 0 rtemsbsd/include/sys/epoch.h | 4 +- rtemsbsd/include/sys/kpilite.h | 0 rtemsbsd/include/vm/vm_pager.h | 0 rtemsbsd/local/cryptodev_if.c | 29 +- rtemsbsd/local/ifdi_if.c | 106 +- rtemsbsd/local/sdhci_if.c | 4 +- rtemsbsd/rtems/rtems-kernel-epoch.c | 25 +- rtemsbsd/sys/arm/at91/at91_mci.c | 1713 ++++++++ rtemsbsd/sys/arm/at91/at91_mcireg.h | 183 + rtemsbsd/sys/arm/at91/at91_pdcreg.h | 50 + rtemsbsd/sys/arm/at91/at91reg.h | 92 + rtemsbsd/sys/arm/at91/at91var.h | 175 + testsuite/epoch01/test_main.c | 17 +- 584 files changed, 28794 insertions(+), 13433 deletions(-) create mode 100644 freebsd/contrib/wpa/src/ap/vlan.h create mode 100644 freebsd/contrib/wpa/src/common/ctrl_iface_common.c create mode 100644 freebsd/contrib/wpa/src/common/ctrl_iface_common.h create mode 100644 freebsd/contrib/wpa/src/utils/module_tests.h create mode 100644 freebsd/contrib/wpa/wpa_supplicant/binder/binder.h create mode 100644 freebsd/crypto/openssl/crypto/bn_int.h create mode 100644 freebsd/include/nl_types.h create mode 100644 freebsd/lib/libcapsicum/capsicum_helpers.h delete mode 100644 freebsd/sys/arm/at91/at91_mci.c delete mode 100644 freebsd/sys/arm/at91/at91_mcireg.h delete mode 100644 freebsd/sys/arm/at91/at91_pdcreg.h delete mode 100644 freebsd/sys/arm/at91/at91reg.h delete mode 100644 freebsd/sys/arm/at91/at91var.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_16.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_32.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/crypto_verify_64.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/export.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/common.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/private/implementations.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/randombytes.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/runtime.h create mode 100644 freebsd/sys/contrib/libsodium/src/libsodium/include/sodium/utils.h create mode 100644 freebsd/sys/crypto/libsodium/utils.c create mode 100644 freebsd/sys/crypto/sha2/sha224.h delete mode 100644 freebsd/sys/netinet/in_gif.h create mode 100644 freebsd/sys/opencrypto/_cryptodev.h create mode 100644 freebsd/sys/opencrypto/xform_poly1305.c create mode 100644 freebsd/sys/opencrypto/xform_poly1305.h create mode 100644 freebsd/sys/sys/sglist.h create mode 100644 rtemsbsd/include/sys/boot.h create mode 100644 rtemsbsd/include/sys/kpilite.h create mode 100644 rtemsbsd/include/vm/vm_pager.h create mode 100644 rtemsbsd/sys/arm/at91/at91_mci.c create mode 100644 rtemsbsd/sys/arm/at91/at91_mcireg.h create mode 100644 rtemsbsd/sys/arm/at91/at91_pdcreg.h create mode 100644 rtemsbsd/sys/arm/at91/at91reg.h create mode 100644 rtemsbsd/sys/arm/at91/at91var.h 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 index fb63610a..6c2192b1 160000 --- a/freebsd-org +++ b/freebsd-org @@ -1 +1 @@ -Subproject commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9 +Subproject commit 6c2192b1ef8c50788c751f878552526800b1e319 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, ¶ms); } @@ -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); } @@ -648,17 +624,29 @@ 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); @@ -688,6 +676,36 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, 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; @@ -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 + * + * 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 + +/* + * Common hostapd/wpa_supplicant ctrl iface code. + * Copyright (c) 2002-2013, Jouni Malinen + * 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 +#include + +#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 + * 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 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= 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: */ #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 @@ -79,6 +79,28 @@ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, 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) @@ -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 + * Copyright (c) 2003-2016, Jouni Malinen * * 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 + * Copyright (c) 2003-2016, Jouni Malinen * * 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 */ @@ -283,6 +299,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() */ @@ -1882,6 +1980,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 +#undef IFNAMSIZ #include #ifdef __linux__ #include #include -#include #endif /* __linux__ */ #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) #include @@ -25,10 +30,6 @@ #include #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 + * Copyright (c) 2004-2015, Jouni Malinen * * 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 + * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen * * 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 + * Copyright (c) 2004-2015, Jouni Malinen * * 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 */ @@ -223,6 +227,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 */ @@ -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 @@ -1690,6 +1716,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 */ @@ -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 @@ -2099,6 +2133,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() @@ -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 + * Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen * * 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 + * 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 #endif /* CONFIG_ELOOP_EPOLL */ +#ifdef CONFIG_ELOOP_KQUEUE +#include +#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 @@ -312,6 +312,14 @@ int eloop_register_signal_terminate(eloop_signal_handler handler, 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 * 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 + * + * 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 + * Copyright (c) 2007-2016, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -663,6 +663,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_*) */ @@ -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 + * Copyright (c) 2008-2016, Jouni Malinen * * 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 + * Copyright (c) 2008-2016, Jouni Malinen * * 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 + * Copyright (c) 2004-2016, Roshan Pius + * + * 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: ... + */ + 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 @@ -359,6 +359,19 @@ struct wpa_ssid { WPAS_MODE_MESH = 5, } 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 * @@ -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 * @@ -457,6 +486,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 * @@ -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: "" 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, /* <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] * [persistent|persistent=] * [join] [auth] [go_intent=<0..15>] [freq=] [provdisc] - * [ht40] [vht] [auto] */ + * [ht40] [vht] [auto] [ssid=] */ 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 = 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= datarate= ssi_signal= frame= */ + + 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; /* * TABTABTABTAB - * TAB[TAB] + * TAB[TAB[TAB]] */ 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 #ifdef __linux__ #include -#include #endif /* __linux__ */ #ifdef ANDROID #include @@ -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); @@ -3122,6 +3337,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); @@ -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,14 +4060,27 @@ 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 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 = ¶ms.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 = ¶ms; 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 = ¶ms; 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(¶ms, 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, ¶ms, interval); + ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms); 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 + * Copyright (c) 2003-2016, Jouni Malinen * * 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 +#include +#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 and contributors"; +"Copyright (c) 2003-2016, Jouni Malinen 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(¶ms, 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, ¶ms); 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 */ @@ -2560,6 +2770,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 @@ -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 +/* + * 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 +# 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,11 +125,22 @@ #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; @@ -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 #include #include +#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 /* ==================================================================== - * 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 #include #include +#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 #include #include #include @@ -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 +#include + +#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 +__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 +__SCCSID("@(#)gethostname.c 8.1 (Berkeley) 6/4/93"); __FBSDID("$FreeBSD$"); #include 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 +__SCCSID("@(#)gethostname.c 8.1 (Berkeley) 6/4/93"); __FBSDID("$FreeBSD$"); #include 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 +__SCCSID("@(#)sethostname.c 8.1 (Berkeley) 6/4/93"); __FBSDID("$FreeBSD$"); #include 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 + * 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 +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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 #include +#include +#include + #include + #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 #include #include /* NB: for offsetof */ +#include +#include #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 -__FBSDID("$FreeBSD$"); -#ifdef __rtems__ -#include +/* 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 #endif /* __rtems__ */ +#include +__FBSDID("$FreeBSD$"); + +#define PFIOC_USE_LATEST + #include #include #include @@ -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, 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, 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, 3144, 0, 629, 629, 629, 0, - 0, 0, 263, 0, 0, 964, 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, 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, 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, - 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, 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, 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, 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, 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, 9, 0, 0, 0, 0, 0, 0, - 0, 43, -17, 0, 0, 0, 0, 209, 0, 653, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 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, 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, 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, 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, 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, - 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, - 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, 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, + 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, - 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, + 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, 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, 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, - 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, -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, 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, - 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 /* 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 -__FBSDID("$FreeBSD$"); -#ifdef __rtems__ -#include +/* 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 #endif /* __rtems__ */ +#include +__FBSDID("$FreeBSD$"); + +#define PFIOC_USE_LATEST + #include #include #include @@ -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 -__FBSDID("$FreeBSD$"); - #ifdef __rtems__ #define __need_getopt_newlib #include #include #include + +/* 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 +__FBSDID("$FreeBSD$"); + +#define PFIOC_USE_LATEST + #include #include #include @@ -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); } @@ -1180,6 +1230,20 @@ pfctl_show_status(int dev, int opts) return (0); } +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) { @@ -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 -__FBSDID("$FreeBSD$"); - #ifdef __rtems__ #include #endif /* __rtems__ */ +#include +__FBSDID("$FreeBSD$"); + +#define PFIOC_USE_LATEST + #include #include #include @@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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 @@ -628,6 +628,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) { 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 -__FBSDID("$FreeBSD$"); - #ifdef __rtems__ #include #endif /* __rtems__ */ +#include +__FBSDID("$FreeBSD$"); + +#define PFIOC_USE_LATEST + #include #include #include @@ -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 = ""; printf("\n%23s %012jx %12p %08jx ", type, (uintmax_t)map->md_phys, map->md_virt, diff --git a/freebsd/sys/arm/at91/at91_mci.c b/freebsd/sys/arm/at91/at91_mci.c deleted file mode 100644 index c25983b7..00000000 --- a/freebsd/sys/arm/at91/at91_mci.c +++ /dev/null @@ -1,1713 +0,0 @@ -#include - -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. - * Copyright (c) 2010 Greg Ansley. 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 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 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. - */ - -#include - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#ifdef FDT -#include -#include -#endif - -#include - -#include - -#ifdef __rtems__ -#include -#endif /* __rtems__ */ -#if defined(__rtems__) && defined(LIBBSP_ARM_ATSAM_BSP_H) -#ifdef __rtems__ -#include -#include - -#define AT91_MCI_HAS_4WIRE 1 - -#define at91_master_clock BOARD_MCK - -static sXdmad *pXdmad = &XDMAD_Instance; -#endif /* __rtems__ */ -/* - * About running the MCI bus above 25MHz - * - * Historically, the MCI bus has been run at 30MHz on systems with a 60MHz - * master clock, in part due to a bug in dev/mmc.c making always request - * 30MHz, and in part over clocking the bus because 15MHz was too slow. - * Fixing that bug causes the mmc driver to request a 25MHz clock (as it - * should) and the logic in at91_mci_update_ios() picks the highest speed that - * doesn't exceed that limit. With a 60MHz MCK that would be 15MHz, and - * that's a real performance buzzkill when you've been getting away with 30MHz - * all along. - * - * By defining AT91_MCI_ALLOW_OVERCLOCK (or setting the allow_overclock=1 - * device hint or sysctl) you can enable logic in at91_mci_update_ios() to - * overlcock the SD bus a little by running it at MCK / 2 when the requested - * speed is 25MHz and the next highest speed is 15MHz or less. This appears - * to work on virtually all SD cards, since it is what this driver has been - * doing prior to the introduction of this option, where the overclocking vs - * underclocking decision was automatically "overclock". Modern SD cards can - * run at 45mhz/1-bit in standard mode (high speed mode enable commands not - * sent) without problems. - * - * Speaking of high-speed mode, the rm9200 manual says the MCI device supports - * the SD v1.0 specification and can run up to 50MHz. This is interesting in - * that the SD v1.0 spec caps the speed at 25MHz; high speed mode was added in - * the v1.10 spec. Furthermore, high speed mode doesn't just crank up the - * clock, it alters the signal timing. The rm9200 MCI device doesn't support - * these altered timings. So while speeds over 25MHz may work, they only work - * in what the SD spec calls "default" speed mode, and it amounts to violating - * the spec by overclocking the bus. - * - * If you also enable 4-wire mode it's possible transfers faster than 25MHz - * will fail. On the AT91RM9200, due to bugs in the bus contention logic, if - * you have the USB host device and OHCI driver enabled will fail. Even - * underclocking to 15MHz, intermittant overrun and underrun errors occur. - * Note that you don't even need to have usb devices attached to the system, - * the errors begin to occur as soon as the OHCI driver sets the register bit - * to enable periodic transfers. It appears (based on brief investigation) - * that the usb host controller uses so much ASB bandwidth that sometimes the - * DMA for MCI transfers doesn't get a bus grant in time and data gets - * dropped. Adding even a modicum of network activity changes the symptom - * from intermittant to very frequent. Members of the AT91SAM9 family have - * corrected this problem, or are at least better about their use of the bus. - */ -#ifndef AT91_MCI_ALLOW_OVERCLOCK -#define AT91_MCI_ALLOW_OVERCLOCK 1 -#endif - -/* - * Allocate 2 bounce buffers we'll use to endian-swap the data due to the rm9200 - * erratum. We use a pair of buffers because when reading that lets us begin - * endian-swapping the data in the first buffer while the DMA is reading into - * the second buffer. (We can't use the same trick for writing because we might - * not get all the data in the 2nd buffer swapped before the hardware needs it; - * dealing with that would add complexity to the driver.) - * - * The buffers are sized at 16K each due to the way the busdma cache sync - * operations work on arm. A dcache_inv_range() operation on a range larger - * than 16K gets turned into a dcache_wbinv_all(). That needlessly flushes the - * entire data cache, impacting overall system performance. - */ -#ifndef __rtems__ -#define BBCOUNT 2 -#define BBSIZE (32*1024) -#define MAX_BLOCKS ((BBSIZE)/512) -/* FIXME: It would be better to split the DMA up in that case like in the - * original driver. But that would need some rework. */ -#else /* __rtems__ */ -#define MAX_BLOCKS 256 -#endif /* __rtems__ */ - -#ifndef __rtems__ -static int mci_debug; -#else /* __rtems__ */ -#define mci_debug 0 -#endif /* __rtems__ */ - -struct at91_mci_softc { - void *intrhand; /* Interrupt handle */ - device_t dev; - int sc_cap; -#define CAP_HAS_4WIRE 1 /* Has 4 wire bus */ -#define CAP_NEEDS_BYTESWAP 2 /* broken hardware needing bounce */ -#define CAP_MCI1_REV2XX 4 /* MCI 1 rev 2.x */ - int flags; -#define PENDING_CMD 0x01 -#define PENDING_STOP 0x02 -#define CMD_MULTIREAD 0x10 -#define CMD_MULTIWRITE 0x20 - int has_4wire; - int allow_overclock; - struct resource *irq_res; /* IRQ resource */ - struct resource *mem_res; /* Memory resource */ - struct mtx sc_mtx; -#ifdef __rtems__ - RTEMS_INTERRUPT_LOCK_MEMBER(sc_lock) -#endif /* __rtems__ */ -#ifndef __rtems__ - bus_dma_tag_t dmatag; -#endif /* __rtems__ */ - struct mmc_host host; - int bus_busy; - struct mmc_request *req; - struct mmc_command *curcmd; -#ifndef __rtems__ - bus_dmamap_t bbuf_map[BBCOUNT]; - char * bbuf_vaddr[BBCOUNT]; /* bounce bufs in KVA space */ - uint32_t bbuf_len[BBCOUNT]; /* len currently queued for bounce buf */ - uint32_t bbuf_curidx; /* which bbuf is the active DMA buffer */ - uint32_t xfer_offset; /* offset so far into caller's buf */ -#else /* __rtems__ */ - LinkedListDescriporView1 xdma_desc; - uint32_t xdma_tx_channel; - uint32_t xdma_rx_channel; - uint8_t xdma_tx_perid; - uint8_t xdma_rx_perid; - sXdmadCfg xdma_tx_cfg; - sXdmadCfg xdma_rx_cfg; -#endif /* __rtems__ */ -}; - -/* bus entry points */ -static int at91_mci_probe(device_t dev); -static int at91_mci_attach(device_t dev); -static int at91_mci_detach(device_t dev); -static void at91_mci_intr(void *); - -/* helper routines */ -static int at91_mci_activate(device_t dev); -static void at91_mci_deactivate(device_t dev); -static int at91_mci_is_mci1rev2xx(void); -#ifndef __rtems__ -static void at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr); -#endif /* __rtems__ */ -static void at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr); - -#ifndef __rtems__ -#define AT91_MCI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define AT91_MCI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define AT91_MCI_LOCK_INIT(_sc) \ - mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ - "mci", MTX_DEF) -#define AT91_MCI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); -#define AT91_MCI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); -#define AT91_MCI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); -#else /* __rtems__ */ -#define AT91_MCI_LOCK(_sc) \ - rtems_interrupt_lock_context at91_mci_lock_context; \ - rtems_interrupt_lock_acquire(&(_sc)->sc_lock, &at91_mci_lock_context) -#define AT91_MCI_UNLOCK(_sc) \ - rtems_interrupt_lock_release(&(_sc)->sc_lock, &at91_mci_lock_context) -#define AT91_MCI_LOCK_INIT(_sc) \ - rtems_interrupt_lock_initialize(&(_sc)->sc_lock, \ - device_get_nameunit((_sc)->dev)) -#define AT91_MCI_LOCK_DESTROY(_sc) \ - rtems_interrupt_lock_destroy(&(_sc)->sc_mtx) -#define AT91_MCI_BUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define AT91_MCI_BUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define AT91_MCI_BUS_LOCK_INIT(_sc) \ - mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->dev), \ - "mci", MTX_DEF) -#endif /* __rtems__ */ - -static inline uint32_t -RD4(struct at91_mci_softc *sc, bus_size_t off) -{ - return (bus_read_4(sc->mem_res, off)); -} - -static inline void -WR4(struct at91_mci_softc *sc, bus_size_t off, uint32_t val) -{ - bus_write_4(sc->mem_res, off, val); -} - -#ifndef __rtems__ -static void -at91_bswap_buf(struct at91_mci_softc *sc, void * dptr, void * sptr, uint32_t memsize) -{ - uint32_t * dst = (uint32_t *)dptr; - uint32_t * src = (uint32_t *)sptr; - uint32_t i; - - /* - * If the hardware doesn't need byte-swapping, let bcopy() do the - * work. Use bounce buffer even if we don't need byteswap, since - * buffer may straddle a page boundary, and we don't handle - * multi-segment transfers in hardware. Seen from 'bsdlabel -w' which - * uses raw geom access to the volume. Greg Ansley (gja (at) - * ansley.com) - */ - if (!(sc->sc_cap & CAP_NEEDS_BYTESWAP)) { - memcpy(dptr, sptr, memsize); - return; - } - - /* - * Nice performance boost for slightly unrolling this loop. - * (But very little extra boost for further unrolling it.) - */ - for (i = 0; i < memsize; i += 16) { - *dst++ = bswap32(*src++); - *dst++ = bswap32(*src++); - *dst++ = bswap32(*src++); - *dst++ = bswap32(*src++); - } - - /* Mop up the last 1-3 words, if any. */ - for (i = 0; i < (memsize & 0x0F); i += 4) { - *dst++ = bswap32(*src++); - } -} - -static void -at91_mci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) -{ - if (error != 0) - return; - *(bus_addr_t *)arg = segs[0].ds_addr; -} -#endif /* __rtems__ */ - -static void -at91_mci_pdc_disable(struct at91_mci_softc *sc) -{ -#ifndef __rtems__ - WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); - WR4(sc, PDC_RPR, 0); - WR4(sc, PDC_RCR, 0); - WR4(sc, PDC_RNPR, 0); - WR4(sc, PDC_RNCR, 0); - WR4(sc, PDC_TPR, 0); - WR4(sc, PDC_TCR, 0); - WR4(sc, PDC_TNPR, 0); - WR4(sc, PDC_TNCR, 0); -#else /* __rtems__ */ - /* On SAMV71 there is no PDC but a DMAC */ - XDMAD_StopTransfer(pXdmad, sc->xdma_rx_channel); - XDMAD_StopTransfer(pXdmad, sc->xdma_tx_channel); - WR4(sc, MCI_DMA, 0); -#endif /* __rtems__ */ -} - -/* - * Reset the controller, then restore most of the current state. - * - * This is called after detecting an error. It's also called after stopping a - * multi-block write, to un-wedge the device so that it will handle the NOTBUSY - * signal correctly. See comments in at91_mci_stop_done() for more details. - */ -static void at91_mci_reset(struct at91_mci_softc *sc) -{ - uint32_t mr; - uint32_t sdcr; - uint32_t dtor; - uint32_t imr; - - at91_mci_pdc_disable(sc); - - /* save current state */ - - imr = RD4(sc, MCI_IMR); -#ifndef __rtems__ - mr = RD4(sc, MCI_MR) & 0x7fff; -#else /* __rtems__ */ - mr = RD4(sc, MCI_MR); -#endif /* __rtems__ */ - sdcr = RD4(sc, MCI_SDCR); - dtor = RD4(sc, MCI_DTOR); - - /* reset the controller */ - - WR4(sc, MCI_IDR, 0xffffffff); - WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); - - /* restore state */ - - WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN); - WR4(sc, MCI_MR, mr); - WR4(sc, MCI_SDCR, sdcr); - WR4(sc, MCI_DTOR, dtor); - WR4(sc, MCI_IER, imr); - - /* - * Make sure sdio interrupts will fire. Not sure why reading - * SR ensures that, but this is in the linux driver. - */ - - RD4(sc, MCI_SR); -} - -static void -at91_mci_init(device_t dev) -{ - struct at91_mci_softc *sc = device_get_softc(dev); - uint32_t val; - - WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */ - WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */ - WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1M | 1); -#ifndef __rtems__ - val = MCI_MR_PDCMODE; -#else /* __rtems__ */ - val = 0; - val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF; -#endif /* __rtems__ */ - val |= 0x34a; /* PWSDIV = 3; CLKDIV = 74 */ -// if (sc->sc_cap & CAP_MCI1_REV2XX) -// val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF; - WR4(sc, MCI_MR, val); -#ifndef AT91_MCI_SLOT_B - WR4(sc, MCI_SDCR, 0); /* SLOT A, 1 bit bus */ -#else - /* - * XXX Really should add second "unit" but nobody using using - * a two slot card that we know of. XXX - */ - WR4(sc, MCI_SDCR, 1); /* SLOT B, 1 bit bus */ -#endif - /* - * Enable controller, including power-save. The slower clock - * of the power-save mode is only in effect when there is no - * transfer in progress, so it can be left in this mode all - * the time. - */ - WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN); -} - -static void -at91_mci_fini(device_t dev) -{ - struct at91_mci_softc *sc = device_get_softc(dev); - - WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */ - at91_mci_pdc_disable(sc); - WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */ -} - -static int -at91_mci_probe(device_t dev) -{ -#ifdef FDT - if (!ofw_bus_is_compatible(dev, "atmel,hsmci")) - return (ENXIO); -#endif - device_set_desc(dev, "MCI mmc/sd host bridge"); - return (0); -} - -static int -at91_mci_attach(device_t dev) -{ - struct at91_mci_softc *sc = device_get_softc(dev); - struct sysctl_ctx_list *sctx; - struct sysctl_oid *soid; - device_t child; -#ifndef __rtems__ - int err, i; -#else /* __rtems__ */ - int err; -#endif /* __rtems__ */ - -#ifdef __rtems__ -#ifdef LIBBSP_ARM_ATSAM_BSP_H - PMC_EnablePeripheral(ID_HSMCI); - sc->xdma_tx_channel = XDMAD_ALLOC_FAILED; - sc->xdma_rx_channel = XDMAD_ALLOC_FAILED; -#endif /* LIBBSP_ARM_ATSAM_BSP_H */ -#endif /* __rtems__ */ - sctx = device_get_sysctl_ctx(dev); - soid = device_get_sysctl_tree(dev); - - sc->dev = dev; - sc->sc_cap = 0; -#ifndef __rtems__ - if (at91_is_rm92()) - sc->sc_cap |= CAP_NEEDS_BYTESWAP; -#endif /* __rtems__ */ - /* - * MCI1 Rev 2 controllers need some workarounds, flag if so. - */ - if (at91_mci_is_mci1rev2xx()) - sc->sc_cap |= CAP_MCI1_REV2XX; - - err = at91_mci_activate(dev); - if (err) - goto out; - -#ifdef __rtems__ - eXdmadRC rc; - - /* Prepare some configurations so they don't have to be fetched on every - * setup */ - sc->xdma_rx_perid = XDMAIF_Get_ChannelNumber(ID_HSMCI, - XDMAD_TRANSFER_RX); - sc->xdma_tx_perid = XDMAIF_Get_ChannelNumber(ID_HSMCI, - XDMAD_TRANSFER_TX); - memset(&sc->xdma_rx_cfg, 0, sizeof(sc->xdma_rx_cfg)); - sc->xdma_rx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | - XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_PER2MEM | - XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE | - XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD | - XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 | - XDMAC_CC_SAM_FIXED_AM | XDMAC_CC_DAM_INCREMENTED_AM | - XDMAC_CC_PERID( - XDMAIF_Get_ChannelNumber(ID_HSMCI,XDMAD_TRANSFER_RX)); - memset(&sc->xdma_tx_cfg, 0, sizeof(sc->xdma_tx_cfg)); - sc->xdma_tx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | - XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER | - XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE | - XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD | - XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 | - XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_FIXED_AM | - XDMAC_CC_PERID( - XDMAIF_Get_ChannelNumber(ID_HSMCI,XDMAD_TRANSFER_TX)); - - sc->xdma_tx_channel = XDMAD_AllocateChannel(pXdmad, - XDMAD_TRANSFER_MEMORY, ID_HSMCI); - if (sc->xdma_tx_channel == XDMAD_ALLOC_FAILED) - goto out; - - /* FIXME: The two DMA channels are not really necessary for the driver. - * But the XDMAD interface does not allow to allocate one and use it - * into two directions. The current (2017-07-11) implementation of - * the XDMAD interface should work with it. So we might could try it. */ - sc->xdma_rx_channel = XDMAD_AllocateChannel(pXdmad, ID_HSMCI, - XDMAD_TRANSFER_MEMORY); - if (sc->xdma_rx_channel == XDMAD_ALLOC_FAILED) - goto out; - - rc = XDMAD_PrepareChannel(pXdmad, sc->xdma_rx_channel); - if (rc != XDMAD_OK) - goto out; - - rc = XDMAD_PrepareChannel(pXdmad, sc->xdma_tx_channel); - if (rc != XDMAD_OK) - goto out; - - AT91_MCI_BUS_LOCK_INIT(sc); -#endif /* __rtems__ */ - AT91_MCI_LOCK_INIT(sc); - - at91_mci_fini(dev); - at91_mci_init(dev); - -#ifndef __rtems__ - /* - * Allocate DMA tags and maps and bounce buffers. - * - * The parms in the tag_create call cause the dmamem_alloc call to - * create each bounce buffer as a single contiguous buffer of BBSIZE - * bytes aligned to a 4096 byte boundary. - * - * Do not use DMA_COHERENT for these buffers because that maps the - * memory as non-cachable, which prevents cache line burst fills/writes, - * which is something we need since we're trying to overlap the - * byte-swapping with the DMA operations. - */ - err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BBSIZE, 1, BBSIZE, 0, NULL, NULL, &sc->dmatag); - if (err != 0) - goto out; - - for (i = 0; i < BBCOUNT; ++i) { - err = bus_dmamem_alloc(sc->dmatag, (void **)&sc->bbuf_vaddr[i], - BUS_DMA_NOWAIT, &sc->bbuf_map[i]); - if (err != 0) - goto out; - } - - /* - * Activate the interrupt - */ - err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, - NULL, at91_mci_intr, sc, &sc->intrhand); -#else /* __rtems__ */ - err = rtems_interrupt_handler_install(rman_get_start(sc->irq_res), - device_get_nameunit(dev), RTEMS_INTERRUPT_SHARED, at91_mci_intr, - sc); -#endif /* __rtems__ */ - if (err) { - AT91_MCI_LOCK_DESTROY(sc); - goto out; - } - - /* - * Allow 4-wire to be initially set via #define. - * Allow a device hint to override that. - * Allow a sysctl to override that. - */ -#if defined(AT91_MCI_HAS_4WIRE) && AT91_MCI_HAS_4WIRE != 0 - sc->has_4wire = 1; -#endif - resource_int_value(device_get_name(dev), device_get_unit(dev), - "4wire", &sc->has_4wire); - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "4wire", - CTLFLAG_RW, &sc->has_4wire, 0, "has 4 wire SD Card bus"); - if (sc->has_4wire) - sc->sc_cap |= CAP_HAS_4WIRE; - - sc->allow_overclock = AT91_MCI_ALLOW_OVERCLOCK; - resource_int_value(device_get_name(dev), device_get_unit(dev), - "allow_overclock", &sc->allow_overclock); - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "allow_overclock", - CTLFLAG_RW, &sc->allow_overclock, 0, - "Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less."); - -#ifndef __rtems__ - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug", - CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output"); -#endif /* __rtems__ */ - - /* - * Our real min freq is master_clock/512, but upper driver layers are - * going to set the min speed during card discovery, and the right speed - * for that is 400kHz, so advertise a safe value just under that. - * - * For max speed, while the rm9200 manual says the max is 50mhz, it also - * says it supports only the SD v1.0 spec, which means the real limit is - * 25mhz. On the other hand, historical use has been to slightly violate - * the standard by running the bus at 30MHz. For more information on - * that, see the comments at the top of this file. - */ - sc->host.f_min = 375000; - sc->host.f_max = at91_master_clock / 2; - if (sc->host.f_max > 25000000) - sc->host.f_max = 25000000; - sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; - sc->host.caps = 0; - if (sc->sc_cap & CAP_HAS_4WIRE) - sc->host.caps |= MMC_CAP_4_BIT_DATA; - - child = device_add_child(dev, "mmc", 0); -#ifdef __rtems__ - (void)child; -#endif /* __rtems__ */ - device_set_ivars(dev, &sc->host); - err = bus_generic_attach(dev); -out: - if (err) - at91_mci_deactivate(dev); - return (err); -} - -static int -at91_mci_detach(device_t dev) -{ -#ifndef __rtems__ - struct at91_mci_softc *sc = device_get_softc(dev); -#endif /* __rtems__ */ - - at91_mci_fini(dev); - at91_mci_deactivate(dev); - -#ifndef __rtems__ - bus_dmamem_free(sc->dmatag, sc->bbuf_vaddr[0], sc->bbuf_map[0]); - bus_dmamem_free(sc->dmatag, sc->bbuf_vaddr[1], sc->bbuf_map[1]); - bus_dma_tag_destroy(sc->dmatag); -#endif /* __rtems__ */ - - return (EBUSY); /* XXX */ -} - -static int -at91_mci_activate(device_t dev) -{ - struct at91_mci_softc *sc; - int rid; - - sc = device_get_softc(dev); - rid = 0; - sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (sc->mem_res == NULL) - goto errout; - - rid = 0; - sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_ACTIVE); - if (sc->irq_res == NULL) - goto errout; - - return (0); -errout: - at91_mci_deactivate(dev); - return (ENOMEM); -} - -static void -at91_mci_deactivate(device_t dev) -{ - struct at91_mci_softc *sc; - - sc = device_get_softc(dev); - if (sc->intrhand) - bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = NULL; - bus_generic_detach(sc->dev); - if (sc->mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, - rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = NULL; - if (sc->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = NULL; -#ifdef __rtems__ - if (sc->xdma_rx_channel != XDMAD_ALLOC_FAILED) { - XDMAD_FreeChannel(pXdmad, sc->xdma_rx_channel); - } - if (sc->xdma_tx_channel != XDMAD_ALLOC_FAILED) { - XDMAD_FreeChannel(pXdmad, sc->xdma_tx_channel); - } -#endif /* __rtems__ */ - return; -} - -static int -at91_mci_is_mci1rev2xx(void) -{ - -#ifndef __rtems__ - switch (soc_info.type) { - case AT91_T_SAM9260: - case AT91_T_SAM9263: - case AT91_T_CAP9: - case AT91_T_SAM9G10: - case AT91_T_SAM9G20: - case AT91_T_SAM9RL: - return(1); - default: - return (0); - } -#else /* __rtems__ */ - /* Currently only supports the SAM V71 */ - return (1); -#endif /* __rtems__ */ -} - -static int -at91_mci_update_ios(device_t brdev, device_t reqdev) -{ - struct at91_mci_softc *sc; - struct mmc_ios *ios; - uint32_t clkdiv; - uint32_t freq; - - sc = device_get_softc(brdev); - ios = &sc->host.ios; - - /* - * Calculate our closest available clock speed that doesn't exceed the - * requested speed. - * - * When overclocking is allowed, the requested clock is 25MHz, the - * computed frequency is 15MHz or smaller and clockdiv is 1, use - * clockdiv of 0 to double that. If less than 12.5MHz, double - * regardless of the overclocking setting. - * - * Whatever we come up with, store it back into ios->clock so that the - * upper layer drivers can report the actual speed of the bus. - */ - if (ios->clock == 0) { - WR4(sc, MCI_CR, MCI_CR_MCIDIS); - clkdiv = 0; - } else { - WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN); - if ((at91_master_clock % (ios->clock * 2)) == 0) - clkdiv = ((at91_master_clock / ios->clock) / 2) - 1; - else - clkdiv = (at91_master_clock / ios->clock) / 2; - freq = at91_master_clock / ((clkdiv+1) * 2); - if (clkdiv == 1 && ios->clock == 25000000 && freq <= 15000000) { - if (sc->allow_overclock || freq <= 12500000) { - clkdiv = 0; - freq = at91_master_clock / ((clkdiv+1) * 2); - } - } - ios->clock = freq; - } - if (ios->bus_width == bus_width_4) - WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) | MCI_SDCR_SDCBUS); - else - WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) & ~MCI_SDCR_SDCBUS); - WR4(sc, MCI_MR, (RD4(sc, MCI_MR) & ~MCI_MR_CLKDIV) | clkdiv); - /* Do we need a settle time here? */ - /* XXX We need to turn the device on/off here with a GPIO pin */ - return (0); -} - -#ifdef __rtems__ -static void -at91_mci_setup_xdma(struct at91_mci_softc *sc, bool read, void *data, - uint32_t len) -{ - const uint32_t xdma_cndc = XDMAC_CNDC_NDVIEW_NDV1 | - XDMAC_CNDC_NDE_DSCR_FETCH_EN | - XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | - XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED; - const uint32_t xdma_interrupt = XDMAC_CIE_BIE | XDMAC_CIE_DIE | - XDMAC_CIE_FIE | XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE; - sXdmadCfg *xdma_cfg; - uint32_t xdma_channel; - eXdmadRC rc; - - if (len % 4 != 0) - panic("invalid XDMA transfer length"); - - if (read) { - xdma_cfg = &sc->xdma_rx_cfg; - xdma_channel = sc->xdma_rx_channel; - sc->xdma_desc.mbr_sa = (uint32_t)(sc->mem_res->r_bushandle + - MCI_RDR); - sc->xdma_desc.mbr_da = (uint32_t)data; - rtems_cache_invalidate_multiple_data_lines(data, len); - } else { - xdma_cfg = &sc->xdma_tx_cfg; - xdma_channel = sc->xdma_tx_channel; - sc->xdma_desc.mbr_sa = (uint32_t)data; - sc->xdma_desc.mbr_da = (uint32_t)(sc->mem_res->r_bushandle + - MCI_TDR); - rtems_cache_flush_multiple_data_lines(data, len); - } - - sc->xdma_desc.mbr_ubc = XDMA_UBC_NVIEW_NDV1 | - XDMA_UBC_NDEN_UPDATED | (len / 4); - sc->xdma_desc.mbr_ubc |= XDMA_UBC_NDE_FETCH_DIS; - sc->xdma_desc.mbr_nda = 0; - - rc = XDMAD_ConfigureTransfer(pXdmad, xdma_channel, xdma_cfg, xdma_cndc, - (uint32_t)&sc->xdma_desc, xdma_interrupt); - if (rc != XDMAD_OK) - panic("configure XDMA failed: %d", rc); - - rtems_cache_flush_multiple_data_lines(&sc->xdma_desc, sizeof(sc->xdma_desc)); - - rc = XDMAD_StartTransfer(pXdmad, xdma_channel); - if (rc != XDMAD_OK) - panic("start XDMA failed: %d", rc); -} -#endif /* __rtems__ */ -static void -at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) -{ - uint32_t cmdr, mr; - struct mmc_data *data; -#ifdef __rtems__ - uint32_t block_count; - uint32_t block_size; -#endif /* __rtems__ */ - - sc->curcmd = cmd; - data = cmd->data; - - /* XXX Upper layers don't always set this */ - cmd->mrq = sc->req; - - /* Begin setting up command register. */ - - cmdr = cmd->opcode; - - if (sc->host.ios.bus_mode == opendrain) - cmdr |= MCI_CMDR_OPDCMD; - - /* Set up response handling. Allow max timeout for responses. */ - - if (MMC_RSP(cmd->flags) == MMC_RSP_NONE) - cmdr |= MCI_CMDR_RSPTYP_NO; - else { - cmdr |= MCI_CMDR_MAXLAT; - if (cmd->flags & MMC_RSP_136) - cmdr |= MCI_CMDR_RSPTYP_136; - else - cmdr |= MCI_CMDR_RSPTYP_48; - } - - /* - * If there is no data transfer, just set up the right interrupt mask - * and start the command. - * - * The interrupt mask needs to be CMDRDY plus all non-data-transfer - * errors. It's important to leave the transfer-related errors out, to - * avoid spurious timeout or crc errors on a STOP command following a - * multiblock read. When a multiblock read is in progress, sending a - * STOP in the middle of a block occasionally triggers such errors, but - * we're totally disinterested in them because we've already gotten all - * the data we wanted without error before sending the STOP command. - */ - - if (data == NULL) { - uint32_t ier = MCI_SR_CMDRDY | - MCI_SR_RTOE | MCI_SR_RENDE | - MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE; - - at91_mci_pdc_disable(sc); - - if (cmd->opcode == MMC_STOP_TRANSMISSION) - cmdr |= MCI_CMDR_TRCMD_STOP; - - /* Ignore response CRC on CMD2 and ACMD41, per standard. */ - - if (cmd->opcode == MMC_SEND_OP_COND || - cmd->opcode == ACMD_SD_SEND_OP_COND) - ier &= ~MCI_SR_RCRCE; - - if (mci_debug) - printf("CMDR %x (opcode %d) ARGR %x no data\n", - cmdr, cmd->opcode, cmd->arg); - - WR4(sc, MCI_ARGR, cmd->arg); - WR4(sc, MCI_CMDR, cmdr); - WR4(sc, MCI_IDR, 0xffffffff); - WR4(sc, MCI_IER, ier); - return; - } - - /* There is data, set up the transfer-related parts of the command. */ - - if (data->flags & MMC_DATA_READ) - cmdr |= MCI_CMDR_TRDIR; - - if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) - cmdr |= MCI_CMDR_TRCMD_START; - - if (data->flags & MMC_DATA_STREAM) - cmdr |= MCI_CMDR_TRTYP_STREAM; - else if (data->flags & MMC_DATA_MULTI) { - cmdr |= MCI_CMDR_TRTYP_MULTIPLE; - sc->flags |= (data->flags & MMC_DATA_READ) ? - CMD_MULTIREAD : CMD_MULTIWRITE; - } - - /* - * Disable PDC until we're ready. - * - * Set block size and turn on PDC mode for dma xfer. - * Note that the block size is the smaller of the amount of data to be - * transferred, or 512 bytes. The 512 size is fixed by the standard; - * smaller blocks are possible, but never larger. - */ - -#ifndef __rtems__ - WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); - - mr = RD4(sc,MCI_MR) & ~MCI_MR_BLKLEN; - mr |= min(data->len, 512) << 16; - WR4(sc, MCI_MR, mr | MCI_MR_PDCMODE|MCI_MR_PDCPADV); - - /* - * Set up DMA. - * - * Use bounce buffers even if we don't need to byteswap, because doing - * multi-block IO with large DMA buffers is way fast (compared to - * single-block IO), even after incurring the overhead of also copying - * from/to the caller's buffers (which may be in non-contiguous physical - * pages). - * - * In an ideal non-byteswap world we could create a dma tag that allows - * for discontiguous segments and do the IO directly from/to the - * caller's buffer(s), using ENDRX/ENDTX interrupts to chain the - * discontiguous buffers through the PDC. Someday. - * - * If a read is bigger than 2k, split it in half so that we can start - * byte-swapping the first half while the second half is on the wire. - * It would be best if we could split it into 8k chunks, but we can't - * always keep up with the byte-swapping due to other system activity, - * and if an RXBUFF interrupt happens while we're still handling the - * byte-swap from the prior buffer (IE, we haven't returned from - * handling the prior interrupt yet), then data will get dropped on the - * floor and we can't easily recover from that. The right fix for that - * would be to have the interrupt handling only keep the DMA flowing and - * enqueue filled buffers to be byte-swapped in a non-interrupt context. - * Even that won't work on the write side of things though; in that - * context we have to have all the data ready to go before starting the - * dma. - * - * XXX what about stream transfers? - */ - sc->xfer_offset = 0; - sc->bbuf_curidx = 0; -#else /* __rtems__ */ - mr = RD4(sc,MCI_MR); - WR4(sc, MCI_MR, mr | MCI_MR_PDCPADV); - - WR4(sc, MCI_DMA, MCI_DMA_DMAEN | MCI_DMA_CHKSIZE_1); - - block_size = min(data->len, 512); - block_count = data->len / block_size; - WR4(sc, MCI_BLKR, (block_size << 16) | block_count); -#endif /* __rtems__ */ - - if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) { -#ifndef __rtems__ - uint32_t len; - uint32_t remaining = data->len; - bus_addr_t paddr; - int err; - - if (remaining > (BBCOUNT*BBSIZE)) - panic("IO read size exceeds MAXDATA\n"); -#endif /* __rtems__ */ - - if (data->flags & MMC_DATA_READ) { -#ifndef __rtems__ - if (remaining > 2048) // XXX - len = remaining / 2; - else - len = remaining; - err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], - sc->bbuf_vaddr[0], len, at91_mci_getaddr, - &paddr, BUS_DMA_NOWAIT); - if (err != 0) - panic("IO read dmamap_load failed\n"); - bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], - BUS_DMASYNC_PREREAD); - WR4(sc, PDC_RPR, paddr); - WR4(sc, PDC_RCR, len / 4); - sc->bbuf_len[0] = len; - remaining -= len; - if (remaining == 0) { - sc->bbuf_len[1] = 0; - } else { - len = remaining; - err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1], - sc->bbuf_vaddr[1], len, at91_mci_getaddr, - &paddr, BUS_DMA_NOWAIT); - if (err != 0) - panic("IO read dmamap_load failed\n"); - bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], - BUS_DMASYNC_PREREAD); - WR4(sc, PDC_RNPR, paddr); - WR4(sc, PDC_RNCR, len / 4); - sc->bbuf_len[1] = len; - remaining -= len; - } - WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); -#else /* __rtems__ */ - at91_mci_setup_xdma(sc, true, data->data, data->len); -#endif /* __rtems__ */ - } else { -#ifndef __rtems__ - len = min(BBSIZE, remaining); - at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len); - err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], - sc->bbuf_vaddr[0], len, at91_mci_getaddr, - &paddr, BUS_DMA_NOWAIT); - if (err != 0) - panic("IO write dmamap_load failed\n"); - bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], - BUS_DMASYNC_PREWRITE); - /* - * Erratum workaround: PDC transfer length on a write - * must not be smaller than 12 bytes (3 words); only - * blklen bytes (set above) are actually transferred. - */ - WR4(sc, PDC_TPR,paddr); - WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4); - sc->bbuf_len[0] = len; - remaining -= len; - if (remaining == 0) { - sc->bbuf_len[1] = 0; - } else { - len = remaining; - at91_bswap_buf(sc, sc->bbuf_vaddr[1], - ((char *)data->data)+BBSIZE, len); - err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1], - sc->bbuf_vaddr[1], len, at91_mci_getaddr, - &paddr, BUS_DMA_NOWAIT); - if (err != 0) - panic("IO write dmamap_load failed\n"); - bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], - BUS_DMASYNC_PREWRITE); - WR4(sc, PDC_TNPR, paddr); - WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4); - sc->bbuf_len[1] = len; - remaining -= len; - } - /* do not enable PDC xfer until CMDRDY asserted */ -#else /* __rtems__ */ - at91_mci_setup_xdma(sc, false, data->data, data->len); -#endif /* __rtems__ */ - } - data->xfer_len = 0; /* XXX what's this? appears to be unused. */ - } - - if (mci_debug) - printf("CMDR %x (opcode %d) ARGR %x with data len %d\n", - cmdr, cmd->opcode, cmd->arg, cmd->data->len); - - WR4(sc, MCI_ARGR, cmd->arg); - WR4(sc, MCI_CMDR, cmdr); - WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_CMDRDY); -} - -static void -at91_mci_next_operation(struct at91_mci_softc *sc) -{ - struct mmc_request *req; - - req = sc->req; - if (req == NULL) - return; - - if (sc->flags & PENDING_CMD) { - sc->flags &= ~PENDING_CMD; - at91_mci_start_cmd(sc, req->cmd); - return; - } else if (sc->flags & PENDING_STOP) { - sc->flags &= ~PENDING_STOP; - at91_mci_start_cmd(sc, req->stop); - return; - } - - WR4(sc, MCI_IDR, 0xffffffff); - sc->req = NULL; - sc->curcmd = NULL; - //printf("req done\n"); - req->done(req); -} - -static int -at91_mci_request(device_t brdev, device_t reqdev, struct mmc_request *req) -{ - struct at91_mci_softc *sc = device_get_softc(brdev); - - AT91_MCI_LOCK(sc); - if (sc->req != NULL) { - AT91_MCI_UNLOCK(sc); - return (EBUSY); - } - //printf("new req\n"); - sc->req = req; - sc->flags = PENDING_CMD; - if (sc->req->stop) - sc->flags |= PENDING_STOP; - at91_mci_next_operation(sc); - AT91_MCI_UNLOCK(sc); - return (0); -} - -static int -at91_mci_get_ro(device_t brdev, device_t reqdev) -{ - return (0); -} - -static int -at91_mci_acquire_host(device_t brdev, device_t reqdev) -{ - struct at91_mci_softc *sc = device_get_softc(brdev); - int err = 0; - -#ifndef __rtems__ - AT91_MCI_LOCK(sc); -#else /* __rtems__ */ - AT91_MCI_BUS_LOCK(sc); -#endif /* __rtems__ */ - while (sc->bus_busy) - msleep(sc, &sc->sc_mtx, PZERO, "mciah", hz / 5); - sc->bus_busy++; -#ifndef __rtems__ - AT91_MCI_UNLOCK(sc); -#else /* __rtems__ */ - AT91_MCI_BUS_UNLOCK(sc); -#endif /* __rtems__ */ - return (err); -} - -static int -at91_mci_release_host(device_t brdev, device_t reqdev) -{ - struct at91_mci_softc *sc = device_get_softc(brdev); - -#ifndef __rtems__ - AT91_MCI_LOCK(sc); -#else /* __rtems__ */ - AT91_MCI_BUS_LOCK(sc); -#endif /* __rtems__ */ - sc->bus_busy--; - wakeup(sc); -#ifndef __rtems__ - AT91_MCI_UNLOCK(sc); -#else /* __rtems__ */ - AT91_MCI_BUS_UNLOCK(sc); -#endif /* __rtems__ */ - return (0); -} - -#ifndef __rtems__ -static void -at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr) -{ - struct mmc_command *cmd = sc->curcmd; - char * dataptr = (char *)cmd->data->data; - uint32_t curidx = sc->bbuf_curidx; - uint32_t len = sc->bbuf_len[curidx]; - - /* - * We arrive here when a DMA transfer for a read is done, whether it's - * a single or multi-block read. - * - * We byte-swap the buffer that just completed, and if that is the - * last buffer that's part of this read then we move on to the next - * operation, otherwise we wait for another ENDRX for the next bufer. - */ - - bus_dmamap_sync(sc->dmatag, sc->bbuf_map[curidx], BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->dmatag, sc->bbuf_map[curidx]); - - at91_bswap_buf(sc, dataptr + sc->xfer_offset, sc->bbuf_vaddr[curidx], len); - - if (mci_debug) { - printf("read done sr %x curidx %d len %d xfer_offset %d\n", - sr, curidx, len, sc->xfer_offset); - } - - sc->xfer_offset += len; - sc->bbuf_curidx = !curidx; /* swap buffers */ - - /* - * If we've transferred all the data, move on to the next operation. - * - * If we're still transferring the last buffer, RNCR is already zero but - * we have to write a zero anyway to clear the ENDRX status so we don't - * re-interrupt until the last buffer is done. - */ - if (sc->xfer_offset == cmd->data->len) { - WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); - cmd->error = MMC_ERR_NONE; - at91_mci_next_operation(sc); - } else { - WR4(sc, PDC_RNCR, 0); - WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_ENDRX); - } -} -#endif /* __rtems__ */ - -static void -at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr) -{ - struct mmc_command *cmd = sc->curcmd; - - /* - * We arrive here when the entire DMA transfer for a write is done, - * whether it's a single or multi-block write. If it's multi-block we - * have to immediately move on to the next operation which is to send - * the stop command. If it's a single-block transfer we need to wait - * for NOTBUSY, but if that's already asserted we can avoid another - * interrupt and just move on to completing the request right away. - */ - - WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); - -#ifndef __rtems__ - bus_dmamap_sync(sc->dmatag, sc->bbuf_map[sc->bbuf_curidx], - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmatag, sc->bbuf_map[sc->bbuf_curidx]); -#endif /* __rtems__ */ - - if ((cmd->data->flags & MMC_DATA_MULTI) || (sr & MCI_SR_NOTBUSY)) { - cmd->error = MMC_ERR_NONE; - at91_mci_next_operation(sc); - } else { - WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY); - } -} - -static void -at91_mci_notbusy(struct at91_mci_softc *sc) -{ - struct mmc_command *cmd = sc->curcmd; - - /* - * We arrive here by either completion of a single-block write, or - * completion of the stop command that ended a multi-block write (and, - * I suppose, after a card-select or erase, but I haven't tested - * those). Anyway, we're done and it's time to move on to the next - * command. - */ - - cmd->error = MMC_ERR_NONE; - at91_mci_next_operation(sc); -} - -static void -at91_mci_stop_done(struct at91_mci_softc *sc, uint32_t sr) -{ - struct mmc_command *cmd = sc->curcmd; - - /* - * We arrive here after receiving CMDRDY for a MMC_STOP_TRANSMISSION - * command. Depending on the operation being stopped, we may have to - * do some unusual things to work around hardware bugs. - */ - - /* - * This is known to be true of at91rm9200 hardware; it may or may not - * apply to more recent chips: - * - * After stopping a multi-block write, the NOTBUSY bit in MCI_SR does - * not properly reflect the actual busy state of the card as signaled - * on the DAT0 line; it always claims the card is not-busy. If we - * believe that and let operations continue, following commands will - * fail with response timeouts (except of course MMC_SEND_STATUS -- it - * indicates the card is busy in the PRG state, which was the smoking - * gun that showed MCI_SR NOTBUSY was not tracking DAT0 correctly). - * - * The atmel docs are emphatic: "This flag [NOTBUSY] must be used only - * for Write Operations." I guess technically since we sent a stop - * it's not a write operation anymore. But then just what did they - * think it meant for the stop command to have "...an optional busy - * signal transmitted on the data line" according to the SD spec? - * - * I tried a variety of things to un-wedge the MCI and get the status - * register to reflect NOTBUSY correctly again, but the only thing - * that worked was a full device reset. It feels like an awfully big - * hammer, but doing a full reset after every multiblock write is - * still faster than doing single-block IO (by almost two orders of - * magnitude: 20KB/sec improves to about 1.8MB/sec best case). - * - * After doing the reset, wait for a NOTBUSY interrupt before - * continuing with the next operation. - * - * This workaround breaks multiwrite on the rev2xx parts, but some other - * workaround is needed. - */ - if ((sc->flags & CMD_MULTIWRITE) && (sc->sc_cap & CAP_NEEDS_BYTESWAP)) { - at91_mci_reset(sc); - WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY); - return; - } - - /* - * This is known to be true of at91rm9200 hardware; it may or may not - * apply to more recent chips: - * - * After stopping a multi-block read, loop to read and discard any - * data that coasts in after we sent the stop command. The docs don't - * say anything about it, but empirical testing shows that 1-3 - * additional words of data get buffered up in some unmentioned - * internal fifo and if we don't read and discard them here they end - * up on the front of the next read DMA transfer we do. - * - * This appears to be unnecessary for rev2xx parts. - */ - if ((sc->flags & CMD_MULTIREAD) && (sc->sc_cap & CAP_NEEDS_BYTESWAP)) { - uint32_t sr; - int count = 0; - - do { - sr = RD4(sc, MCI_SR); - if (sr & MCI_SR_RXRDY) { - RD4(sc, MCI_RDR); - ++count; - } - } while (sr & MCI_SR_RXRDY); - at91_mci_reset(sc); - } - - cmd->error = MMC_ERR_NONE; - at91_mci_next_operation(sc); - -} - -static void -at91_mci_cmdrdy(struct at91_mci_softc *sc, uint32_t sr) -{ - struct mmc_command *cmd = sc->curcmd; - int i; - - if (cmd == NULL) - return; - - /* - * We get here at the end of EVERY command. We retrieve the command - * response (if any) then decide what to do next based on the command. - */ - - if (cmd->flags & MMC_RSP_PRESENT) { - for (i = 0; i < ((cmd->flags & MMC_RSP_136) ? 4 : 1); i++) { - cmd->resp[i] = RD4(sc, MCI_RSPR + i * 4); - if (mci_debug) - printf("RSPR[%d] = %x sr=%x\n", i, cmd->resp[i], sr); - } - } - - /* - * If this was a stop command, go handle the various special - * conditions (read: bugs) that have to be dealt with following a stop. - */ - if (cmd->opcode == MMC_STOP_TRANSMISSION) { - at91_mci_stop_done(sc, sr); - return; - } - - /* - * If this command can continue to assert BUSY beyond the response then - * we need to wait for NOTBUSY before the command is really done. - * - * Note that this may not work properly on the at91rm9200. It certainly - * doesn't work for the STOP command that follows a multi-block write, - * so post-stop CMDRDY is handled separately; see the special handling - * in at91_mci_stop_done(). - * - * Beside STOP, there are other R1B-type commands that use the busy - * signal after CMDRDY: CMD7 (card select), CMD28-29 (write protect), - * CMD38 (erase). I haven't tested any of them, but I rather expect - * them all to have the same sort of problem with MCI_SR not actually - * reflecting the state of the DAT0-line busy indicator. So this code - * may need to grow some sort of special handling for them too. (This - * just in: CMD7 isn't a problem right now because dev/mmc.c incorrectly - * sets the response flags to R1 rather than R1B.) XXX - */ - if ((cmd->flags & MMC_RSP_BUSY)) { - WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY); - return; - } - - /* - * If there is a data transfer with this command, then... - * - If it's a read, we need to wait for ENDRX. - * - If it's a write, now is the time to enable the PDC, and we need - * to wait for a BLKE that follows a TXBUFE, because if we're doing - * a split transfer we get a BLKE after the first half (when TPR/TCR - * get loaded from TNPR/TNCR). So first we wait for the TXBUFE, and - * the handling for that interrupt will then invoke the wait for the - * subsequent BLKE which indicates actual completion. - */ - if (cmd->data) { - uint32_t ier; -#ifndef __rtems__ - if (cmd->data->flags & MMC_DATA_READ) { - ier = MCI_SR_ENDRX; - } else { - ier = MCI_SR_TXBUFE; - WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN); - } -#else /* __rtems__ */ - ier = MCI_SR_XFRDONE; -#endif /* __rtems__ */ - WR4(sc, MCI_IER, MCI_SR_ERROR | ier); - return; - } - - /* - * If we made it to here, we don't need to wait for anything more for - * the current command, move on to the next command (will complete the - * request if there is no next command). - */ - cmd->error = MMC_ERR_NONE; - at91_mci_next_operation(sc); -} - -static void -at91_mci_intr(void *arg) -{ - struct at91_mci_softc *sc = (struct at91_mci_softc*)arg; - struct mmc_command *cmd = sc->curcmd; - uint32_t sr, isr; - - AT91_MCI_LOCK(sc); - - sr = RD4(sc, MCI_SR); - isr = sr & RD4(sc, MCI_IMR); - - if (mci_debug) - printf("i 0x%x sr 0x%x\n", isr, sr); - - /* - * All interrupts are one-shot; disable it now. - * The next operation will re-enable whatever interrupts it wants. - */ - WR4(sc, MCI_IDR, isr); - if (isr & MCI_SR_ERROR) { - if (isr & (MCI_SR_RTOE | MCI_SR_DTOE)) - cmd->error = MMC_ERR_TIMEOUT; - else if (isr & (MCI_SR_RCRCE | MCI_SR_DCRCE)) - cmd->error = MMC_ERR_BADCRC; - else if (isr & (MCI_SR_OVRE | MCI_SR_UNRE)) - cmd->error = MMC_ERR_FIFO; - else - cmd->error = MMC_ERR_FAILED; - /* - * CMD8 is used to probe for SDHC cards, a standard SD card - * will get a response timeout; don't report it because it's a - * normal and expected condition. One might argue that all - * error reporting should be left to higher levels, but when - * they report at all it's always EIO, which isn't very - * helpful. XXX bootverbose? - */ - if (cmd->opcode != 8) { - device_printf(sc->dev, - "IO error; status MCI_SR = 0x%b cmd opcode = %d%s\n", - sr, MCI_SR_BITSTRING, cmd->opcode, - (cmd->opcode != 12) ? "" : - (sc->flags & CMD_MULTIREAD) ? " after read" : " after write"); - /* XXX not sure RTOE needs a full reset, just a retry */ - at91_mci_reset(sc); - } - at91_mci_next_operation(sc); - } else { -#ifndef __rtems__ - if (isr & MCI_SR_TXBUFE) { -// printf("TXBUFE\n"); - /* - * We need to wait for a BLKE that follows TXBUFE - * (intermediate BLKEs might happen after ENDTXes if - * we're chaining multiple buffers). If BLKE is also - * asserted at the time we get TXBUFE, we can avoid - * another interrupt and process it right away, below. - */ - if (sr & MCI_SR_BLKE) - isr |= MCI_SR_BLKE; - else - WR4(sc, MCI_IER, MCI_SR_BLKE); - } - if (isr & MCI_SR_RXBUFF) { -// printf("RXBUFF\n"); - } - if (isr & MCI_SR_ENDTX) { -// printf("ENDTX\n"); - } - if (isr & MCI_SR_ENDRX) { -// printf("ENDRX\n"); - at91_mci_read_done(sc, sr); - } -#else /* __rtems__ */ - if (isr & MCI_SR_XFRDONE) { - if (cmd->data->flags & MMC_DATA_READ) { - WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | - PDC_PTCR_TXTDIS); - cmd->error = MMC_ERR_NONE; - at91_mci_next_operation(sc); - } else { - if (sr & MCI_SR_BLKE) - isr |= MCI_SR_BLKE; - else - WR4(sc, MCI_IER, MCI_SR_BLKE); - } - } -#endif /* __rtems__ */ - if (isr & MCI_SR_NOTBUSY) { -// printf("NOTBUSY\n"); - at91_mci_notbusy(sc); - } - if (isr & MCI_SR_DTIP) { -// printf("Data transfer in progress\n"); - } - if (isr & MCI_SR_BLKE) { -// printf("Block transfer end\n"); - at91_mci_write_done(sc, sr); - } - if (isr & MCI_SR_TXRDY) { -// printf("Ready to transmit\n"); - } - if (isr & MCI_SR_RXRDY) { -// printf("Ready to receive\n"); - } - if (isr & MCI_SR_CMDRDY) { -// printf("Command ready\n"); - at91_mci_cmdrdy(sc, sr); - } - } - AT91_MCI_UNLOCK(sc); -} - -static int -at91_mci_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) -{ - struct at91_mci_softc *sc = device_get_softc(bus); - - switch (which) { - default: - return (EINVAL); - case MMCBR_IVAR_BUS_MODE: - *(int *)result = sc->host.ios.bus_mode; - break; - case MMCBR_IVAR_BUS_WIDTH: - *(int *)result = sc->host.ios.bus_width; - break; - case MMCBR_IVAR_CHIP_SELECT: - *(int *)result = sc->host.ios.chip_select; - break; - case MMCBR_IVAR_CLOCK: - *(int *)result = sc->host.ios.clock; - break; - case MMCBR_IVAR_F_MIN: - *(int *)result = sc->host.f_min; - break; - case MMCBR_IVAR_F_MAX: - *(int *)result = sc->host.f_max; - break; - case MMCBR_IVAR_HOST_OCR: - *(int *)result = sc->host.host_ocr; - break; - case MMCBR_IVAR_MODE: - *(int *)result = sc->host.mode; - break; - case MMCBR_IVAR_OCR: - *(int *)result = sc->host.ocr; - break; - case MMCBR_IVAR_POWER_MODE: - *(int *)result = sc->host.ios.power_mode; - break; - case MMCBR_IVAR_VDD: - *(int *)result = sc->host.ios.vdd; - break; - case MMCBR_IVAR_CAPS: - if (sc->has_4wire) { - sc->sc_cap |= CAP_HAS_4WIRE; - sc->host.caps |= MMC_CAP_4_BIT_DATA; - } else { - sc->sc_cap &= ~CAP_HAS_4WIRE; - sc->host.caps &= ~MMC_CAP_4_BIT_DATA; - } - *(int *)result = sc->host.caps; - break; -#ifdef __rtems__ - case MMCBR_IVAR_TIMING: - *result = sc->host.ios.timing; - break; -#endif /* __rtems__ */ - case MMCBR_IVAR_MAX_DATA: - /* - * Something is wrong with the 2x parts and multiblock, so - * just do 1 block at a time for now, which really kills - * performance. - */ - if (sc->sc_cap & CAP_MCI1_REV2XX) - *(int *)result = 1; - else - *(int *)result = MAX_BLOCKS; - break; - } - return (0); -} - -static int -at91_mci_write_ivar(device_t bus, device_t child, int which, uintptr_t value) -{ - struct at91_mci_softc *sc = device_get_softc(bus); - - switch (which) { - default: - return (EINVAL); - case MMCBR_IVAR_BUS_MODE: - sc->host.ios.bus_mode = value; - break; - case MMCBR_IVAR_BUS_WIDTH: - sc->host.ios.bus_width = value; - break; - case MMCBR_IVAR_CHIP_SELECT: - sc->host.ios.chip_select = value; - break; - case MMCBR_IVAR_CLOCK: - sc->host.ios.clock = value; - break; - case MMCBR_IVAR_MODE: - sc->host.mode = value; - break; - case MMCBR_IVAR_OCR: - sc->host.ocr = value; - break; - case MMCBR_IVAR_POWER_MODE: - sc->host.ios.power_mode = value; - break; - case MMCBR_IVAR_VDD: - sc->host.ios.vdd = value; - break; -#ifdef __rtems__ - case MMCBR_IVAR_TIMING: - sc->host.ios.timing = value; - break; -#endif /* __rtems__ */ - /* These are read-only */ - case MMCBR_IVAR_CAPS: - case MMCBR_IVAR_HOST_OCR: - case MMCBR_IVAR_F_MIN: - case MMCBR_IVAR_F_MAX: - case MMCBR_IVAR_MAX_DATA: - return (EINVAL); - } - return (0); -} - -static device_method_t at91_mci_methods[] = { - /* device_if */ - DEVMETHOD(device_probe, at91_mci_probe), - DEVMETHOD(device_attach, at91_mci_attach), - DEVMETHOD(device_detach, at91_mci_detach), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, at91_mci_read_ivar), - DEVMETHOD(bus_write_ivar, at91_mci_write_ivar), - - /* mmcbr_if */ - DEVMETHOD(mmcbr_update_ios, at91_mci_update_ios), - DEVMETHOD(mmcbr_request, at91_mci_request), - DEVMETHOD(mmcbr_get_ro, at91_mci_get_ro), - DEVMETHOD(mmcbr_acquire_host, at91_mci_acquire_host), - DEVMETHOD(mmcbr_release_host, at91_mci_release_host), - - DEVMETHOD_END -}; - -static driver_t at91_mci_driver = { - "at91_mci", - at91_mci_methods, - sizeof(struct at91_mci_softc), -}; - -static devclass_t at91_mci_devclass; - -#ifndef __rtems__ -#ifdef FDT -DRIVER_MODULE(at91_mci, simplebus, at91_mci_driver, at91_mci_devclass, NULL, - NULL); -#else -DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, NULL, - NULL); -#endif - -MMC_DECLARE_BRIDGE(at91_mci); -#else /* __rtems__ */ -DRIVER_MODULE(at91_mci, nexus, at91_mci_driver, at91_mci_devclass, NULL, NULL); -#endif /* __rtems__ */ -DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL); -MODULE_DEPEND(at91_mci, mmc, 1, 1, 1); -#endif /* __rtems__ && LIBBSP_ARM_ATSAM_BSP_H */ diff --git a/freebsd/sys/arm/at91/at91_mcireg.h b/freebsd/sys/arm/at91/at91_mcireg.h deleted file mode 100644 index 80acf48d..00000000 --- a/freebsd/sys/arm/at91/at91_mcireg.h +++ /dev/null @@ -1,183 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2006 Berndt Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. - * - * 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 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 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 ARM_AT91_AT91_MCIREG_H -#define ARM_AT91_AT91_MCIREG_H - -#define MMC_MAX 30 - -#define MCI_CR 0x00 /* MCI Control Register */ -#define MCI_MR 0x04 /* MCI Mode Register */ -#define MCI_DTOR 0x08 /* MCI Data Timeout Register */ -#define MCI_SDCR 0x0c /* MCI SD Card Register */ -#define MCI_ARGR 0x10 /* MCI Argument Register */ -#define MCI_CMDR 0x14 /* MCI Command Register */ -#ifdef __rtems__ -#define MCI_BLKR 0x18 /* MCI Block Register */ -#endif /* __rtems__ */ -#define MCI_RSPR 0x20 /* MCI Response Registers - 4 of them */ -#define MCI_RDR 0x30 /* MCI Receive Data Register */ -#define MCI_TDR 0x34 /* MCI Transmit Data Register */ -#define MCI_SR 0x40 /* MCI Status Register */ -#define MCI_IER 0x44 /* MCI Interrupt Enable Register */ -#define MCI_IDR 0x48 /* MCI Interrupt Disable Register */ -#define MCI_IMR 0x4c /* MCI Interrupt Mask Register */ -#ifdef __rtems__ -#define MCI_DMA 0x50 /* MCI DMA Control Register */ -#endif /* __rtems__ */ - -/* -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register -------- */ -#define MCI_CR_MCIEN (0x1u << 0) /* (MCI) Multimedia Interface Enable */ -#define MCI_CR_MCIDIS (0x1u << 1) /* (MCI) Multimedia Interface Disable */ -#define MCI_CR_PWSEN (0x1u << 2) /* (MCI) Power Save Mode Enable */ -#define MCI_CR_PWSDIS (0x1u << 3) /* (MCI) Power Save Mode Disable */ -#define MCI_CR_SWRST (0x1u << 7) /* (MCI) Software Reset */ -/* -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register -------- */ -#define MCI_MR_CLKDIV (0xffu << 0) /* (MCI) Clock Divider */ -#define MCI_MR_PWSDIV (0x3fu << 8) /* (MCI) Power Saving Divider */ -#define MCI_MR_RDPROOF (0x1u << 11) /* (MCI) Read Proof Enable */ -#define MCI_MR_WRPROOF (0x1u << 12) /* (MCI) Write Proof Enable */ -#define MCI_MR_PDCFBYTE (0x1u << 13) /* (MCI) PDC Force Byte Transfer */ -#define MCI_MR_PDCPADV (0x1u << 14) /* (MCI) PDC Padding Value */ -#define MCI_MR_PDCMODE (0x1u << 15) /* (MCI) PDC Oriented Mode */ -#define MCI_MR_CLKODD (0x1u << 16) /* (MCI) Clock Divider is Odd */ -#define MCI_MR_BLKLEN 0x3fff0000ul /* (MCI) Data Block Length */ -/* -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register -------- */ -#define MCI_DTOR_DTOCYC (0xfu << 0) /* (MCI) Data Timeout Cycle Number */ -#define MCI_DTOR_DTOMUL (0x7u << 4) /* (MCI) Data Timeout Multiplier */ -#define MCI_DTOR_DTOMUL_1 (0x0u << 4) /* (MCI) DTOCYC x 1 */ -#define MCI_DTOR_DTOMUL_16 (0x1u << 4) /* (MCI) DTOCYC x 16 */ -#define MCI_DTOR_DTOMUL_128 (0x2u << 4) /* (MCI) DTOCYC x 128 */ -#define MCI_DTOR_DTOMUL_256 (0x3u << 4) /* (MCI) DTOCYC x 256 */ -#define MCI_DTOR_DTOMUL_1k (0x4u << 4) /* (MCI) DTOCYC x 1024 */ -#define MCI_DTOR_DTOMUL_4k (0x5u << 4) /* (MCI) DTOCYC x 4096 */ -#define MCI_DTOR_DTOMUL_64k (0x6u << 4) /* (MCI) DTOCYC x 65536 */ -#define MCI_DTOR_DTOMUL_1M (0x7u << 4) /* (MCI) DTOCYC x 1048576 */ -/* -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register -------- */ -#define MCI_SDCR_SDCSEL (0x1u << 0) /* (MCI) SD Card Selector */ -#define MCI_SDCR_SDCBUS (0x1u << 7) /* (MCI) SD Card Bus Width */ -/* -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register -------- */ -#define MCI_CMDR_CMDNB (0x1Fu << 0) /* (MCI) Command Number */ -#define MCI_CMDR_RSPTYP (0x3u << 6) /* (MCI) Response Type */ -#define MCI_CMDR_RSPTYP_NO (0x0u << 6) /* (MCI) No response */ -#define MCI_CMDR_RSPTYP_48 (0x1u << 6) /* (MCI) 48-bit response */ -#define MCI_CMDR_RSPTYP_136 (0x2u << 6) /* (MCI) 136-bit response */ -#define MCI_CMDR_SPCMD (0x7u << 8) /* (MCI) Special CMD */ -#define MCI_CMDR_SPCMD_NONE (0x0u << 8) /* (MCI) Not a special CMD */ -#define MCI_CMDR_SPCMD_INIT (0x1u << 8) /* (MCI) Initialization CMD */ -#define MCI_CMDR_SPCMD_SYNC (0x2u << 8) /* (MCI) Synchronized CMD */ -#define MCI_CMDR_SPCMD_IT_CMD (0x4u << 8) /* (MCI) Interrupt command */ -#define MCI_CMDR_SPCMD_IT_REP (0x5u << 8) /* (MCI) Interrupt response */ -#define MCI_CMDR_OPDCMD (0x1u << 11) /* (MCI) Open Drain Command */ -#define MCI_CMDR_MAXLAT (0x1u << 12) /* (MCI) Maximum Latency for Command to respond */ -#define MCI_CMDR_TRCMD (0x3u << 16) /* (MCI) Transfer CMD */ -#define MCI_CMDR_TRCMD_NO (0x0u << 16) /* (MCI) No transfer */ -#define MCI_CMDR_TRCMD_START (0x1u << 16) /* (MCI) Start transfer */ -#define MCI_CMDR_TRCMD_STOP (0x2u << 16) /* (MCI) Stop transfer */ -#define MCI_CMDR_TRDIR (0x1u << 18) /* (MCI) Transfer Direction */ -#define MCI_CMDR_TRTYP (0x3u << 19) /* (MCI) Transfer Type */ -#define MCI_CMDR_TRTYP_BLOCK (0x0u << 19) /* (MCI) Block Transfer type */ -#define MCI_CMDR_TRTYP_MULTIPLE (0x1u << 19) /* (MCI) Multiple Block transfer type */ -#define MCI_CMDR_TRTYP_STREAM (0x2u << 19) /* (MCI) Stream transfer type */ -#ifdef __rtems__ -/* -------- MCI_BLKR : (MCI Offset: 0x18) MCI Block Register -------- */ -#define MCI_BLKR_BCNT (0xFFFFu << 0) -#define MCI_BLKR_BLKLEN (0xFFFFu << 16) -#endif /* __rtems__ */ -/* -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register -------- */ -#define MCI_SR_CMDRDY (0x1u << 0) /* (MCI) Command Ready flag */ -#define MCI_SR_RXRDY (0x1u << 1) /* (MCI) RX Ready flag */ -#define MCI_SR_TXRDY (0x1u << 2) /* (MCI) TX Ready flag */ -#define MCI_SR_BLKE (0x1u << 3) /* (MCI) Data Block Transfer Ended flag */ -#define MCI_SR_DTIP (0x1u << 4) /* (MCI) Data Transfer in Progress flag */ -#define MCI_SR_NOTBUSY (0x1u << 5) /* (MCI) Data Line Not Busy flag */ -#define MCI_SR_ENDRX (0x1u << 6) /* (MCI) End of RX Buffer flag */ -#define MCI_SR_ENDTX (0x1u << 7) /* (MCI) End of TX Buffer flag */ -#define MCI_SR_RXBUFF (0x1u << 14) /* (MCI) RX Buffer Full flag */ -#define MCI_SR_TXBUFE (0x1u << 15) /* (MCI) TX Buffer Empty flag */ -#define MCI_SR_RINDE (0x1u << 16) /* (MCI) Response Index Error flag */ -#define MCI_SR_RDIRE (0x1u << 17) /* (MCI) Response Direction Error flag */ -#define MCI_SR_RCRCE (0x1u << 18) /* (MCI) Response CRC Error flag */ -#define MCI_SR_RENDE (0x1u << 19) /* (MCI) Response End Bit Error flag */ -#define MCI_SR_RTOE (0x1u << 20) /* (MCI) Response Time-out Error flag */ -#define MCI_SR_DCRCE (0x1u << 21) /* (MCI) data CRC Error flag */ -#define MCI_SR_DTOE (0x1u << 22) /* (MCI) Data timeout Error flag */ -#define MCI_SR_OVRE (0x1u << 30) /* (MCI) Overrun flag */ -#define MCI_SR_UNRE (0x1u << 31) /* (MCI) Underrun flag */ -#ifdef __rtems__ -#define MCI_SR_XFRDONE (0x1u << 27) /* (MCI) Underrun flag */ -#endif /* __rtems__ */ -#ifdef __rtems__ -/* -------- MCI_DMA : (MCI Offset: 0x50) MCI DMA Control Register -------- */ -#define MCI_DMA_DMAEN (0x1u << 8) -#define MCI_DMA_CHKSIZE (0x7u << 4) -#define MCI_DMA_CHKSIZE_1 (0x0u << 4) -#define MCI_DMA_CHKSIZE_2 (0x1u << 4) -#define MCI_DMA_CHKSIZE_4 (0x2u << 4) -#define MCI_DMA_CHKSIZE_8 (0x3u << 4) -#define MCI_DMA_CHKSIZE_16 (0x4u << 4) -#endif /* __rtems__ */ - -/* TXRDY,DTIP,ENDTX,TXBUFE,RTOE */ - -#define MCI_SR_BITSTRING \ - "\020" \ - "\001CMDRDY" \ - "\002RXRDY" \ - "\003TXRDY" \ - "\004BLKE" \ - "\005DTIP" \ - "\006NOTBUSY" \ - "\007ENDRX" \ - "\010ENDTX" \ - "\017RXBUFF" \ - "\020TXBUFE" \ - "\021RINDE" \ - "\022RDIRE" \ - "\023RCRCE" \ - "\024RENDE" \ - "\025RTOE" \ - "\026DCRCE" \ - "\027DTOE" \ - "\037OVRE" \ - "\040UNRE" - -/* -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register -------- */ -/* -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register -------- */ -/* -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register -------- */ - -#define MCI_SR_ERROR (MCI_SR_UNRE | MCI_SR_OVRE | MCI_SR_DTOE | \ - MCI_SR_DCRCE | MCI_SR_RTOE | MCI_SR_RENDE | \ - MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE) - -#define AT91C_BUS_WIDTH_1BIT 0x00 -#define AT91C_BUS_WIDTH_4BITS 0x02 - -#endif /* ARM_AT91_AT91_MCIREG_H */ diff --git a/freebsd/sys/arm/at91/at91_pdcreg.h b/freebsd/sys/arm/at91/at91_pdcreg.h deleted file mode 100644 index 659804bd..00000000 --- a/freebsd/sys/arm/at91/at91_pdcreg.h +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2006 M. Warner Losh. - * - * 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 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 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 ARM_AT91_AT91_PDCREG_H -#define ARM_AT91_AT91_PDCREG_H - -#define PDC_RPR 0x100 /* PDC Receive Pointer Register */ -#define PDC_RCR 0x104 /* PDC Receive Counter Register */ -#define PDC_TPR 0x108 /* PDC Transmit Pointer Register */ -#define PDC_TCR 0x10c /* PDC Transmit Counter Register */ -#define PDC_RNPR 0x110 /* PDC Receive Next Pointer Register */ -#define PDC_RNCR 0x114 /* PDC Receive Next Counter Register */ -#define PDC_TNPR 0x118 /* PDC Transmit Next Pointer Reg */ -#define PDC_TNCR 0x11c /* PDC Transmit Next Counter Reg */ -#define PDC_PTCR 0x120 /* PDC Transfer Control Register */ -#define PDC_PTSR 0x124 /* PDC Transfer Status Register */ - -/* PTCR/PTSR */ -#define PDC_PTCR_RXTEN (1UL << 0) /* RXTEN: Receiver Transfer Enable */ -#define PDC_PTCR_RXTDIS (1UL << 1) /* RXTDIS: Receiver Transfer Disable */ -#define PDC_PTCR_TXTEN (1UL << 8) /* TXTEN: Transmitter Transfer En */ -#define PDC_PTCR_TXTDIS (1UL << 9) /* TXTDIS: Transmitter Transmit Dis */ - -#endif /* ARM_AT91_AT91_PDCREG_H */ diff --git a/freebsd/sys/arm/at91/at91reg.h b/freebsd/sys/arm/at91/at91reg.h deleted file mode 100644 index f5791bd7..00000000 --- a/freebsd/sys/arm/at91/at91reg.h +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2009 Greg Ansley 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 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 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 _AT91REG_H_ -#define _AT91REG_H_ - -#include - -/* Where builtin peripherals start in KVM */ -#define AT91_BASE 0xd0000000 - -/* Where builtin peripherals start PA */ -#define AT91_PA_BASE 0xf0000000 - -/* A few things that we count on being the same - * throughout the whole family of SOCs */ - -/* SYSC System Controller */ -/* System Registers */ -#define AT91_SYS_BASE 0xffff000 -#define AT91_SYS_SIZE 0x1000 - -#define AT91_DBGU0 0x0ffff200 /* Most */ -#define AT91_DBGU1 0x0fffee00 /* SAM9263, CAP9, and SAM9G45 */ - -#define AT91_DBGU_SIZE 0x200 -#define DBGU_C1R (64) /* Chip ID1 Register */ -#define DBGU_C2R (68) /* Chip ID2 Register */ -#define DBGU_FNTR (72) /* Force NTRST Register */ - -#define AT91_CPU_VERSION_MASK 0x0000001f -#define AT91_CPU_FAMILY_MASK 0x0ff00000 - -#define AT91_CPU_RM9200 0x09290780 -#define AT91_CPU_SAM9260 0x019803a0 -#define AT91_CPU_SAM9261 0x019703a0 -#define AT91_CPU_SAM9263 0x019607a0 -#define AT91_CPU_SAM9G10 0x819903a0 -#define AT91_CPU_SAM9G20 0x019905a0 -#define AT91_CPU_SAM9G45 0x819b05a0 -#define AT91_CPU_SAM9N12 0x819a07a0 -#define AT91_CPU_SAM9RL64 0x019b03a0 -#define AT91_CPU_SAM9X5 0x819a05a0 - -#define AT91_CPU_SAM9XE128 0x329973a0 -#define AT91_CPU_SAM9XE256 0x329a93a0 -#define AT91_CPU_SAM9XE512 0x329aa3a0 - -#define AT91_CPU_CAP9 0x039a03a0 - -#define AT91_EXID_SAM9M11 0x00000001 -#define AT91_EXID_SAM9M10 0x00000002 -#define AT91_EXID_SAM9G46 0x00000003 -#define AT91_EXID_SAM9G45 0x00000004 - -#define AT91_EXID_SAM9G15 0x00000000 -#define AT91_EXID_SAM9G35 0x00000001 -#define AT91_EXID_SAM9X35 0x00000002 -#define AT91_EXID_SAM9G25 0x00000003 -#define AT91_EXID_SAM9X25 0x00000004 - -#define AT91_IRQ_SYSTEM 1 - -#endif /* _AT91REG_H_ */ diff --git a/freebsd/sys/arm/at91/at91var.h b/freebsd/sys/arm/at91/at91var.h deleted file mode 100644 index 84c898fb..00000000 --- a/freebsd/sys/arm/at91/at91var.h +++ /dev/null @@ -1,175 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2005 Olivier Houchard. 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 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 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 _AT91VAR_H_ -#define _AT91VAR_H_ - -#include -#include - -#include - -struct at91_softc { - device_t dev; - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - bus_space_handle_t sc_aic_sh; - struct rman sc_irq_rman; - struct rman sc_mem_rman; -}; - -struct at91_ivar { - struct resource_list resources; -}; - -struct cpu_devs -{ - const char *name; - int unit; - bus_addr_t mem_base; - bus_size_t mem_len; - int irq0; - int irq1; - int irq2; - const char *parent_clk; -}; - -enum at91_soc_type { - AT91_T_NONE = 0, - AT91_T_CAP9, - AT91_T_RM9200, - AT91_T_SAM9260, - AT91_T_SAM9261, - AT91_T_SAM9263, - AT91_T_SAM9G10, - AT91_T_SAM9G20, - AT91_T_SAM9G45, - AT91_T_SAM9N12, - AT91_T_SAM9RL, - AT91_T_SAM9X5, -}; - -enum at91_soc_subtype { - AT91_ST_ANY = -1, /* Match any type */ - AT91_ST_NONE = 0, - /* AT91RM9200 */ - AT91_ST_RM9200_BGA, - AT91_ST_RM9200_PQFP, - /* AT91SAM9260 */ - AT91_ST_SAM9XE, - /* AT91SAM9G45 */ - AT91_ST_SAM9G45, - AT91_ST_SAM9M10, - AT91_ST_SAM9G46, - AT91_ST_SAM9M11, - /* AT91SAM9X5 */ - AT91_ST_SAM9G15, - AT91_ST_SAM9G25, - AT91_ST_SAM9G35, - AT91_ST_SAM9X25, - AT91_ST_SAM9X35, -}; - -enum at91_soc_family { - AT91_FAMILY_SAM9 = 0x19, - AT91_FAMILY_SAM9XE = 0x29, - AT91_FAMILY_RM92 = 0x92, -}; - -#define AT91_SOC_NAME_MAX 50 - -typedef void (*DELAY_t)(int); -typedef void (*cpu_reset_t)(void); -typedef void (*clk_init_t)(void); - -struct at91_soc_data { - DELAY_t soc_delay; /* SoC specific delay function */ - cpu_reset_t soc_reset; /* SoC specific reset function */ - clk_init_t soc_clock_init; /* SoC specific clock init function */ - const int *soc_irq_prio; /* SoC specific IRQ priorities */ - const struct cpu_devs *soc_children; /* SoC specific children list */ - const uint32_t *soc_pio_base; /* SoC specific PIO base registers */ - size_t soc_pio_count; /* Count of PIO units (not pins) in SoC */ -}; - -struct at91_soc_info { - enum at91_soc_type type; - enum at91_soc_subtype subtype; - enum at91_soc_family family; - uint32_t cidr; - uint32_t exid; - char name[AT91_SOC_NAME_MAX]; - uint32_t dbgu_base; - struct at91_soc_data *soc_data; -}; - -extern struct at91_soc_info soc_info; - -static inline int at91_is_rm92(void); -static inline int at91_is_sam9(void); -static inline int at91_is_sam9xe(void); -static inline int at91_cpu_is(u_int cpu); - -static inline int -at91_is_rm92(void) -{ - - return (soc_info.type == AT91_T_RM9200); -} - -static inline int -at91_is_sam9(void) -{ - - return (soc_info.family == AT91_FAMILY_SAM9); -} - -static inline int -at91_is_sam9xe(void) -{ - - return (soc_info.family == AT91_FAMILY_SAM9XE); -} - -static inline int -at91_cpu_is(u_int cpu) -{ - - return (soc_info.type == cpu); -} - -void at91_add_child(device_t dev, int prio, const char *name, int unit, - bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2); - -extern uint32_t at91_irq_system; -extern uint32_t at91_master_clock; -void at91_pmc_init_clock(void); -void at91_soc_id(void); - -#endif /* _AT91VAR_H_ */ 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 #include @@ -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 */ @@ -461,12 +331,6 @@ intr_restore(register_t s) 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 @@ -1366,48 +1366,6 @@ union ccb { sizeof(*(ccbp)) - sizeof((ccbp)->ccb_h)) __BEGIN_DECLS -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); - -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 *), 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 + + +#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 + +#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 + + +#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 + + +#include +#include + +#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 + +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 +#include +#include + +#include + +#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 +#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 +#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 +#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 +#include +#include + +#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 +#include +#include + +#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 + +# 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 +#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 +#include + +#include + +#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 + +#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 - 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 + +/* This file is in the public domain. */ + +#include +__FBSDID("$FreeBSD$"); +#include +#include + +#include + +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 +#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 #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 #include -#include - #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 +#include #include #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) @@ -105,6 +104,20 @@ MMCBR_ACCESSOR(timing, TIMING, int) 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 #include #include +#include #include #include #include @@ -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 +#include #include #include #include @@ -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 /* XXX trim includes */ +#include #include #include #include @@ -41,13 +42,19 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include -#include +#include +#include #include #include #include +#include +#include +#include +#include #include #include @@ -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 @@ -73,20 +73,33 @@ r12au_init_rx_agg(struct rtwn_softc *sc) R92C_TRXDMA_CTRL_RXDMA_AGG_EN); } +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 + #include #include #include @@ -51,9 +53,14 @@ #include #include +#ifdef EVDEV_SUPPORT +#include +#include +#else #include #include #include +#endif #define USB_DEBUG_VAR uep_debug #include @@ -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 - * 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 -#include -#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 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; } @@ -717,6 +717,45 @@ intr_handler_source(void *cookie) return (ie->ie_source); } +/* + * 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. * @@ -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 #include #include +#include #include #include #include @@ -60,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -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 - + 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(>ask_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 #include +#include #include #include #include #include #include -/* - * 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 #include +#include +#include + /* * 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 "---<>---" +#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; @@ -3866,6 +3873,17 @@ sodupsockaddr(const struct sockaddr *sa, int mflags) return sa2; } +/* + * 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. */ @@ -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 #include #include +#include +#include #ifdef KTRACE #include #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 +#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 #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 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; @@ -457,29 +470,6 @@ tbr_timeout(arg) tbr_timer = 0; /* don't need tbr_timer anymore */ } -/* - * 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. @@ -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); } @@ -3921,6 +3934,44 @@ if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req) return (0); } +/* + * 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. * 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 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -87,8 +86,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #endif /* INET6 */ #include @@ -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 * 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 -#include - -#include 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 + * Copyright (c) 2014, 2018 Andrey V. Elsukov * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -43,17 +43,13 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include -#include #include #include #include #include #include -#include -#include #include #include #include @@ -72,7 +68,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef INET -#include #include #include #include @@ -82,7 +77,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #endif #include @@ -93,24 +87,16 @@ __FBSDID("$FreeBSD$"); #include #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 #include -#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 #include #include -#include #include #include #include @@ -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 #include -#include +#include #include #include #include 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 #include -#include +#include #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 #include +#include #include +#include #include #include #include #include #include +#include #include #include #include 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 #include #include +#include +#include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 #include -#include -#include +#include +#include #include #include #include - + #include #include #include @@ -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 #include #include -#include +#include #include #include #include @@ -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 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,18 +41,18 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include +#include #include #include #include #include #include #include -#include #include +#include +#include #include #include #include @@ -72,35 +73,161 @@ __FBSDID("$FreeBSD$"); #include -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 +#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 */ @@ -588,6 +813,12 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, int lookupflags = 0, reuseport = (so->so_options & SO_REUSEPORT); 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. */ @@ -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) @@ -1995,6 +2298,18 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr, if (tmpinp != NULL) 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. */ @@ -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); @@ -2232,10 +2543,23 @@ in_pcbinshash_internal(struct inpcb *inp, int do_pcbgroup_update) pcbporthash = &pcbinfo->ipi_porthashbase[ 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 #include #include +#include +#include #include #endif +#include #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 @@ -507,6 +511,13 @@ struct inpcbinfo { struct inpcbhead *ipi_wildbase; /* (p) */ 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 */ @@ -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 @@ -93,6 +93,11 @@ struct ip { #define IPTOS_PREC_PRIORITY IPTOS_DSCP_CS1 #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. */ 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; @@ -2103,6 +2117,24 @@ carp_allow_sysctl(SYSCTL_HANDLER_ARGS) return (0); } +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) { 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 * 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 __FBSDID("$FreeBSD$"); -#include #include #include #include #include +#include #include +#include #include -#include -#include #include #include -#include -#include +#include #include -#include +#include #include -#include -#include #include #include #ifdef INET6 -#include #include #endif -#include +static MALLOC_DEFINE(M_NETADDR, "encap_export_host", + "Export host address structure"); -#include -#include -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 * 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; @@ -295,12 +295,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 */ @@ -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 + * Copyright (c) 2014, 2018 Andrey V. Elsukov * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -43,18 +43,17 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include -#include #include -#include -#include +#include +#include #include -#include #include -#include -#include #include -#include +#include +#include + #include #include #include @@ -71,61 +70,177 @@ __FBSDID("$FreeBSD$"); #include -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 -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 #include #include + +#include +#include + #ifdef SCTP #include #include @@ -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 #include #include +#include #include #include #include @@ -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,8 +600,22 @@ 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, @@ -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 #include -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 #endif +#include #include @@ -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 #include +#include @@ -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 #include +#include #include #ifdef INET6 #include @@ -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 = 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 #include #include +#include +#include #include #include #ifdef TCPDEBUG #include #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 #include +#include #include #include #include @@ -104,19 +105,19 @@ __FBSDID("$FreeBSD$"); #include -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 #include #include +#include #include #ifdef INET6 #include @@ -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 #include +#include #include #include #include @@ -98,7 +99,7 @@ __FBSDID("$FreeBSD$"); #include -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 #include +#include #include #include #include @@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include #include @@ -67,58 +70,110 @@ __FBSDID("$FreeBSD$"); #include -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 #include #include -#include +#include #include #include #include @@ -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 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,20 +41,19 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include +#include #include #include #include #include #include -#include #include #include -#include #include +#include +#include #include #include #include @@ -63,52 +63,189 @@ __FBSDID("$FreeBSD$"); #include #ifdef INET #include +#include #endif #include -#ifdef INET6 #include #include #include -#endif -#include -#ifdef INET6 +#include #include #include -#endif #include #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; @@ -1116,6 +1178,18 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, if (tmpinp != NULL) 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. */ @@ -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 #include #include -#include #include #include @@ -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 #include +#include #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 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 #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 #include +#ifdef _KERNEL +#include +#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 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 + +/* This file is in the public domain. */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include + +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 + +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 __FBSDID("$FreeBSD$"); +#include #include #include #include #include +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, @@ -99,6 +161,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) { 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 #include +#include 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 +#ifdef _KERNEL +#include +#endif #include #include #include @@ -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 -#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 #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 + * + * 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 + +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); @@ -167,6 +167,10 @@ int sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so, struct thread *td); 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); 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 /* for people using printf mainly */ #ifdef __rtems__ #include +#include #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 /* MAXCPU */ +#include /* curthread */ +#include +#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 +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/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/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/dso/dso.h', + 'crypto/openssl/crypto/ebcdic.h', 'crypto/openssl/crypto/ecdh/ecdh.h', 'crypto/openssl/crypto/ecdh/ech_locl.h', - 'crypto/openssl/crypto/dh/dh.h', + 'crypto/openssl/crypto/ecdsa/ecdsa.h', + 'crypto/openssl/crypto/ecdsa/ecs_locl.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/rc4/rc4.h', + 'crypto/openssl/crypto/rc4/rc4_locl.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/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/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/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/symhacks.h', + 'crypto/openssl/crypto/ts/ts.h', 'crypto/openssl/crypto/txt_db/txt_db.h', - 'crypto/openssl/crypto/ebcdic.h', - 'crypto/openssl/crypto/cmac/cmac.h', - 'crypto/openssl/crypto/ppc_arch.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/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/ui/ui_locl.h', + 'crypto/openssl/crypto/vms_rms.h', + 'crypto/openssl/crypto/whrlpool/whrlpool.h', + 'crypto/openssl/crypto/whrlpool/wp_locl.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/ocsp/ocsp.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/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/crypto/seed/seed_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/ts/ts.h', - 'crypto/openssl/crypto/mdc2/mdc2.h', - 'crypto/openssl/crypto/pqueue/pqueue.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/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, @@ -145,6 +145,24 @@ const struct usb_knowndev usb_knowndevs[] = { "ABIT Corporation", "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, @@ -631,6 +649,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Adaptec", "AWN-8020 WLAN", }, + { + USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_205, + 0, + "Addonics Technology", + "Cable 205", + }, { USB_VENDOR_ADDTRON, USB_PRODUCT_ADDTRON_AWU120, 0, @@ -949,6 +973,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Alink", "3G modem", }, + { + USB_VENDOR_ALINK, USB_PRODUCT_ALINK_SIM7600E, + 0, + "Alink", + "LTE modem", + }, { USB_VENDOR_ALINK, USB_PRODUCT_ALINK_3GU, 0, @@ -3751,6 +3781,12 @@ const struct usb_knowndev usb_knowndevs[] = { "D-Link", "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, @@ -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", }, { @@ -6397,6 +6433,18 @@ const struct usb_knowndev usb_knowndevs[] = { "Genesys Logic", "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, @@ -6415,6 +6463,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Genesys Logic", "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, @@ -6547,6 +6601,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Global Sun Technology", "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, @@ -7903,6 +7963,30 @@ const struct usb_knowndev usb_knowndevs[] = { "Intel", "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, @@ -12127,6 +12211,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Novatel Wireless", "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, @@ -12919,6 +13009,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Peracom Networks", "Ethernet", }, + { + USB_VENDOR_PERASO, USB_PRODUCT_PERASO_PRS4001, + 0, + "Peraso Technologies, Inc.", + "PRS4001 WLAN", + }, { USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS350, 0, @@ -12949,6 +13045,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Philips", "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, @@ -14239,6 +14341,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Ralink Technology", "RT5370", }, + { + USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT5372, + 0, + "Ralink Technology", + "RT5372", + }, { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT5572, 0, @@ -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", }, { @@ -16585,112 +16693,130 @@ const struct usb_knowndev usb_knowndevs[] = { "Standard Microsystems", "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", }, { @@ -18139,12 +18265,78 @@ const struct usb_knowndev usb_knowndevs[] = { "YAMAHA", "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, @@ -18283,6 +18475,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Z-Com", "UB82", }, + { + USB_VENDOR_ZEEVO, USB_PRODUCT_ZEEVO_BLUETOOTH, + 0, + "Zeevo, Inc.", + "BT-500 Bluetooth USB Adapter", + }, { USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570, 0, @@ -18325,12 +18523,72 @@ const struct usb_knowndev usb_knowndevs[] = { "Zoom Telephonics", "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, @@ -18349,6 +18607,18 @@ const struct usb_knowndev usb_knowndevs[] = { "Zydas Technology Corporation", "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, @@ -18385,6 +18655,12 @@ const struct usb_knowndev usb_knowndevs[] = { "ZyXEL Communication", "M-202", }, + { + USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G270S, + 0, + "ZyXEL Communication", + "G-270S", + }, { USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G220V2, 0, @@ -18397,6 +18673,12 @@ const struct usb_knowndev usb_knowndevs[] = { "ZyXEL Communication", "G-202", }, + { + USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RT2573, + 0, + "ZyXEL Communication", + "RT2573", + }, { USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RT2870_1, 0, @@ -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, }, { @@ -19639,6 +19927,12 @@ const struct usb_knowndev usb_knowndevs[] = { "AVM", NULL, }, + { + USB_VENDOR_NINTENDO, 0, + USB_KNOWNDEV_NOPROD, + "Nintendo", + NULL, + }, { USB_VENDOR_QUICKSHOT, 0, USB_KNOWNDEV_NOPROD, @@ -19981,6 +20275,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Bridge Information", NULL, }, + { + USB_VENDOR_SMK, 0, + USB_KNOWNDEV_NOPROD, + "SMK", + NULL, + }, { USB_VENDOR_SOLIDYEAR, 0, USB_KNOWNDEV_NOPROD, @@ -20305,6 +20605,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Eicon Networks", NULL, }, + { + USB_VENDOR_MADCATZ, 0, + USB_KNOWNDEV_NOPROD, + "Mad Catz, Inc.", + NULL, + }, { USB_VENDOR_SYNTECH, 0, USB_KNOWNDEV_NOPROD, @@ -20479,6 +20785,12 @@ const struct usb_knowndev usb_knowndevs[] = { "AboCom Systems", NULL, }, + { + USB_VENDOR_KINGSUN, 0, + USB_KNOWNDEV_NOPROD, + "KingSun", + NULL, + }, { USB_VENDOR_KEISOKUGIKEN, 0, USB_KNOWNDEV_NOPROD, @@ -20557,6 +20869,12 @@ const struct usb_knowndev usb_knowndevs[] = { "STSN", NULL, }, + { + USB_VENDOR_BEWAN, 0, + USB_KNOWNDEV_NOPROD, + "Bewan", + NULL, + }, { USB_VENDOR_CENTURY, 0, USB_KNOWNDEV_NOPROD, @@ -20587,6 +20905,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Personal Communication Systems", NULL, }, + { + USB_VENDOR_SYNET, 0, + USB_KNOWNDEV_NOPROD, + "Synet Electronics", + NULL, + }, { USB_VENDOR_ALPHASMART, 0, USB_KNOWNDEV_NOPROD, @@ -20881,6 +21205,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Kingston Technology", NULL, }, + { + USB_VENDOR_NVIDIA, 0, + USB_KNOWNDEV_NOPROD, + "NVIDIA Corporation", + NULL, + }, { USB_VENDOR_BLUEWATER, 0, USB_KNOWNDEV_NOPROD, @@ -20929,6 +21259,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Minds At Work", NULL, }, + { + USB_VENDOR_ZIPPY, 0, + USB_KNOWNDEV_NOPROD, + "Zippy Technology Corporation", + NULL, + }, { USB_VENDOR_POINTCHIPS, 0, USB_KNOWNDEV_NOPROD, @@ -20941,6 +21277,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Intersil", NULL, }, + { + USB_VENDOR_TRIPPLITE2, 0, + USB_KNOWNDEV_NOPROD, + "Tripp Lite", + NULL, + }, { USB_VENDOR_ALTIUS, 0, USB_KNOWNDEV_NOPROD, @@ -21160,7 +21502,7 @@ const struct usb_knowndev usb_knowndevs[] = { { USB_VENDOR_ATI2, 0, USB_KNOWNDEV_NOPROD, - "ATI", + "ATI Technologies", NULL, }, { @@ -21553,6 +21895,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Kontron AG", NULL, }, + { + USB_VENDOR_DVICO, 0, + USB_KNOWNDEV_NOPROD, + "DViCO", + NULL, + }, { USB_VENDOR_QUALCOMM, 0, USB_KNOWNDEV_NOPROD, @@ -21589,6 +21937,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Desknote", NULL, }, + { + USB_VENDOR_AMD2, 0, + USB_KNOWNDEV_NOPROD, + "Advanced Micro Devices", + NULL, + }, { USB_VENDOR_NEC3, 0, USB_KNOWNDEV_NOPROD, @@ -21793,6 +22147,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Interbiometrics", NULL, }, + { + USB_VENDOR_FUJITSU3, 0, + USB_KNOWNDEV_NOPROD, + "Fujitsu Ltd.", + NULL, + }, { USB_VENDOR_UNKNOWN3, 0, USB_KNOWNDEV_NOPROD, @@ -21895,6 +22255,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Netgear", NULL, }, + { + USB_VENDOR_VALIDITY, 0, + USB_KNOWNDEV_NOPROD, + "Validity Sensors, Inc.", + NULL, + }, { USB_VENDOR_BALTECH, 0, USB_KNOWNDEV_NOPROD, @@ -21937,6 +22303,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Novatel Wireless", NULL, }, + { + USB_VENDOR_OMNIVISION2, 0, + USB_KNOWNDEV_NOPROD, + "OmniVision Technologies, Inc.", + NULL, + }, { USB_VENDOR_MERLIN, 0, USB_KNOWNDEV_NOPROD, @@ -22261,6 +22633,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Kamstrup A/S", NULL, }, + { + USB_VENDOR_MISC, 0, + USB_KNOWNDEV_NOPROD, + "Misc Vendors", + NULL, + }, { USB_VENDOR_DISPLAYLINK, 0, USB_KNOWNDEV_NOPROD, @@ -22285,6 +22663,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Vaisala", NULL, }, + { + USB_VENDOR_E3C, 0, + USB_KNOWNDEV_NOPROD, + "E3C Technologies", + NULL, + }, { USB_VENDOR_AMIT, 0, USB_KNOWNDEV_NOPROD, @@ -22315,6 +22699,24 @@ const struct usb_knowndev usb_knowndevs[] = { "Linksys", 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, @@ -22327,6 +22729,18 @@ const struct usb_knowndev usb_knowndevs[] = { "Qualcomm, Inc.", 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, @@ -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, }, { @@ -22585,6 +23011,18 @@ const struct usb_knowndev usb_knowndevs[] = { "WeTelecom", 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, @@ -22621,6 +23059,12 @@ const struct usb_knowndev usb_knowndevs[] = { "ThingM", NULL, }, + { + USB_VENDOR_PERASO, 0, + USB_KNOWNDEV_NOPROD, + "Peraso Technologies, Inc.", + NULL, + }, { USB_VENDOR_PLANEX, 0, USB_KNOWNDEV_NOPROD, @@ -22753,12 +23197,24 @@ const struct usb_knowndev usb_knowndevs[] = { "Zinwell", 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, @@ -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, }, { @@ -22843,6 +23299,18 @@ const struct usb_knowndev usb_knowndevs[] = { "DataApex", 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, diff --git a/rtemsbsd/include/sys/boot.h b/rtemsbsd/include/sys/boot.h new file mode 100644 index 00000000..e69de29b 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 diff --git a/rtemsbsd/include/vm/vm_pager.h b/rtemsbsd/include/vm/vm_pager.h new file mode 100644 index 00000000..e69de29b 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 #include -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 #include #include +#include +#include +#include #include @@ -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) { @@ -46,6 +61,12 @@ return (0); } + 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) { @@ -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 #include #include +#include +#include #include -#include #include #include +#include #include #include 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/rtemsbsd/sys/arm/at91/at91_mci.c b/rtemsbsd/sys/arm/at91/at91_mci.c new file mode 100644 index 00000000..c25983b7 --- /dev/null +++ b/rtemsbsd/sys/arm/at91/at91_mci.c @@ -0,0 +1,1713 @@ +#include + +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Bernd Walter. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. + * Copyright (c) 2010 Greg Ansley. 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 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 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. + */ + +#include + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef FDT +#include +#include +#endif + +#include + +#include + +#ifdef __rtems__ +#include +#endif /* __rtems__ */ +#if defined(__rtems__) && defined(LIBBSP_ARM_ATSAM_BSP_H) +#ifdef __rtems__ +#include +#include + +#define AT91_MCI_HAS_4WIRE 1 + +#define at91_master_clock BOARD_MCK + +static sXdmad *pXdmad = &XDMAD_Instance; +#endif /* __rtems__ */ +/* + * About running the MCI bus above 25MHz + * + * Historically, the MCI bus has been run at 30MHz on systems with a 60MHz + * master clock, in part due to a bug in dev/mmc.c making always request + * 30MHz, and in part over clocking the bus because 15MHz was too slow. + * Fixing that bug causes the mmc driver to request a 25MHz clock (as it + * should) and the logic in at91_mci_update_ios() picks the highest speed that + * doesn't exceed that limit. With a 60MHz MCK that would be 15MHz, and + * that's a real performance buzzkill when you've been getting away with 30MHz + * all along. + * + * By defining AT91_MCI_ALLOW_OVERCLOCK (or setting the allow_overclock=1 + * device hint or sysctl) you can enable logic in at91_mci_update_ios() to + * overlcock the SD bus a little by running it at MCK / 2 when the requested + * speed is 25MHz and the next highest speed is 15MHz or less. This appears + * to work on virtually all SD cards, since it is what this driver has been + * doing prior to the introduction of this option, where the overclocking vs + * underclocking decision was automatically "overclock". Modern SD cards can + * run at 45mhz/1-bit in standard mode (high speed mode enable commands not + * sent) without problems. + * + * Speaking of high-speed mode, the rm9200 manual says the MCI device supports + * the SD v1.0 specification and can run up to 50MHz. This is interesting in + * that the SD v1.0 spec caps the speed at 25MHz; high speed mode was added in + * the v1.10 spec. Furthermore, high speed mode doesn't just crank up the + * clock, it alters the signal timing. The rm9200 MCI device doesn't support + * these altered timings. So while speeds over 25MHz may work, they only work + * in what the SD spec calls "default" speed mode, and it amounts to violating + * the spec by overclocking the bus. + * + * If you also enable 4-wire mode it's possible transfers faster than 25MHz + * will fail. On the AT91RM9200, due to bugs in the bus contention logic, if + * you have the USB host device and OHCI driver enabled will fail. Even + * underclocking to 15MHz, intermittant overrun and underrun errors occur. + * Note that you don't even need to have usb devices attached to the system, + * the errors begin to occur as soon as the OHCI driver sets the register bit + * to enable periodic transfers. It appears (based on brief investigation) + * that the usb host controller uses so much ASB bandwidth that sometimes the + * DMA for MCI transfers doesn't get a bus grant in time and data gets + * dropped. Adding even a modicum of network activity changes the symptom + * from intermittant to very frequent. Members of the AT91SAM9 family have + * corrected this problem, or are at least better about their use of the bus. + */ +#ifndef AT91_MCI_ALLOW_OVERCLOCK +#define AT91_MCI_ALLOW_OVERCLOCK 1 +#endif + +/* + * Allocate 2 bounce buffers we'll use to endian-swap the data due to the rm9200 + * erratum. We use a pair of buffers because when reading that lets us begin + * endian-swapping the data in the first buffer while the DMA is reading into + * the second buffer. (We can't use the same trick for writing because we might + * not get all the data in the 2nd buffer swapped before the hardware needs it; + * dealing with that would add complexity to the driver.) + * + * The buffers are sized at 16K each due to the way the busdma cache sync + * operations work on arm. A dcache_inv_range() operation on a range larger + * than 16K gets turned into a dcache_wbinv_all(). That needlessly flushes the + * entire data cache, impacting overall system performance. + */ +#ifndef __rtems__ +#define BBCOUNT 2 +#define BBSIZE (32*1024) +#define MAX_BLOCKS ((BBSIZE)/512) +/* FIXME: It would be better to split the DMA up in that case like in the + * original driver. But that would need some rework. */ +#else /* __rtems__ */ +#define MAX_BLOCKS 256 +#endif /* __rtems__ */ + +#ifndef __rtems__ +static int mci_debug; +#else /* __rtems__ */ +#define mci_debug 0 +#endif /* __rtems__ */ + +struct at91_mci_softc { + void *intrhand; /* Interrupt handle */ + device_t dev; + int sc_cap; +#define CAP_HAS_4WIRE 1 /* Has 4 wire bus */ +#define CAP_NEEDS_BYTESWAP 2 /* broken hardware needing bounce */ +#define CAP_MCI1_REV2XX 4 /* MCI 1 rev 2.x */ + int flags; +#define PENDING_CMD 0x01 +#define PENDING_STOP 0x02 +#define CMD_MULTIREAD 0x10 +#define CMD_MULTIWRITE 0x20 + int has_4wire; + int allow_overclock; + struct resource *irq_res; /* IRQ resource */ + struct resource *mem_res; /* Memory resource */ + struct mtx sc_mtx; +#ifdef __rtems__ + RTEMS_INTERRUPT_LOCK_MEMBER(sc_lock) +#endif /* __rtems__ */ +#ifndef __rtems__ + bus_dma_tag_t dmatag; +#endif /* __rtems__ */ + struct mmc_host host; + int bus_busy; + struct mmc_request *req; + struct mmc_command *curcmd; +#ifndef __rtems__ + bus_dmamap_t bbuf_map[BBCOUNT]; + char * bbuf_vaddr[BBCOUNT]; /* bounce bufs in KVA space */ + uint32_t bbuf_len[BBCOUNT]; /* len currently queued for bounce buf */ + uint32_t bbuf_curidx; /* which bbuf is the active DMA buffer */ + uint32_t xfer_offset; /* offset so far into caller's buf */ +#else /* __rtems__ */ + LinkedListDescriporView1 xdma_desc; + uint32_t xdma_tx_channel; + uint32_t xdma_rx_channel; + uint8_t xdma_tx_perid; + uint8_t xdma_rx_perid; + sXdmadCfg xdma_tx_cfg; + sXdmadCfg xdma_rx_cfg; +#endif /* __rtems__ */ +}; + +/* bus entry points */ +static int at91_mci_probe(device_t dev); +static int at91_mci_attach(device_t dev); +static int at91_mci_detach(device_t dev); +static void at91_mci_intr(void *); + +/* helper routines */ +static int at91_mci_activate(device_t dev); +static void at91_mci_deactivate(device_t dev); +static int at91_mci_is_mci1rev2xx(void); +#ifndef __rtems__ +static void at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr); +#endif /* __rtems__ */ +static void at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr); + +#ifndef __rtems__ +#define AT91_MCI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define AT91_MCI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define AT91_MCI_LOCK_INIT(_sc) \ + mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ + "mci", MTX_DEF) +#define AT91_MCI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); +#define AT91_MCI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); +#define AT91_MCI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); +#else /* __rtems__ */ +#define AT91_MCI_LOCK(_sc) \ + rtems_interrupt_lock_context at91_mci_lock_context; \ + rtems_interrupt_lock_acquire(&(_sc)->sc_lock, &at91_mci_lock_context) +#define AT91_MCI_UNLOCK(_sc) \ + rtems_interrupt_lock_release(&(_sc)->sc_lock, &at91_mci_lock_context) +#define AT91_MCI_LOCK_INIT(_sc) \ + rtems_interrupt_lock_initialize(&(_sc)->sc_lock, \ + device_get_nameunit((_sc)->dev)) +#define AT91_MCI_LOCK_DESTROY(_sc) \ + rtems_interrupt_lock_destroy(&(_sc)->sc_mtx) +#define AT91_MCI_BUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define AT91_MCI_BUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define AT91_MCI_BUS_LOCK_INIT(_sc) \ + mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->dev), \ + "mci", MTX_DEF) +#endif /* __rtems__ */ + +static inline uint32_t +RD4(struct at91_mci_softc *sc, bus_size_t off) +{ + return (bus_read_4(sc->mem_res, off)); +} + +static inline void +WR4(struct at91_mci_softc *sc, bus_size_t off, uint32_t val) +{ + bus_write_4(sc->mem_res, off, val); +} + +#ifndef __rtems__ +static void +at91_bswap_buf(struct at91_mci_softc *sc, void * dptr, void * sptr, uint32_t memsize) +{ + uint32_t * dst = (uint32_t *)dptr; + uint32_t * src = (uint32_t *)sptr; + uint32_t i; + + /* + * If the hardware doesn't need byte-swapping, let bcopy() do the + * work. Use bounce buffer even if we don't need byteswap, since + * buffer may straddle a page boundary, and we don't handle + * multi-segment transfers in hardware. Seen from 'bsdlabel -w' which + * uses raw geom access to the volume. Greg Ansley (gja (at) + * ansley.com) + */ + if (!(sc->sc_cap & CAP_NEEDS_BYTESWAP)) { + memcpy(dptr, sptr, memsize); + return; + } + + /* + * Nice performance boost for slightly unrolling this loop. + * (But very little extra boost for further unrolling it.) + */ + for (i = 0; i < memsize; i += 16) { + *dst++ = bswap32(*src++); + *dst++ = bswap32(*src++); + *dst++ = bswap32(*src++); + *dst++ = bswap32(*src++); + } + + /* Mop up the last 1-3 words, if any. */ + for (i = 0; i < (memsize & 0x0F); i += 4) { + *dst++ = bswap32(*src++); + } +} + +static void +at91_mci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + if (error != 0) + return; + *(bus_addr_t *)arg = segs[0].ds_addr; +} +#endif /* __rtems__ */ + +static void +at91_mci_pdc_disable(struct at91_mci_softc *sc) +{ +#ifndef __rtems__ + WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); + WR4(sc, PDC_RPR, 0); + WR4(sc, PDC_RCR, 0); + WR4(sc, PDC_RNPR, 0); + WR4(sc, PDC_RNCR, 0); + WR4(sc, PDC_TPR, 0); + WR4(sc, PDC_TCR, 0); + WR4(sc, PDC_TNPR, 0); + WR4(sc, PDC_TNCR, 0); +#else /* __rtems__ */ + /* On SAMV71 there is no PDC but a DMAC */ + XDMAD_StopTransfer(pXdmad, sc->xdma_rx_channel); + XDMAD_StopTransfer(pXdmad, sc->xdma_tx_channel); + WR4(sc, MCI_DMA, 0); +#endif /* __rtems__ */ +} + +/* + * Reset the controller, then restore most of the current state. + * + * This is called after detecting an error. It's also called after stopping a + * multi-block write, to un-wedge the device so that it will handle the NOTBUSY + * signal correctly. See comments in at91_mci_stop_done() for more details. + */ +static void at91_mci_reset(struct at91_mci_softc *sc) +{ + uint32_t mr; + uint32_t sdcr; + uint32_t dtor; + uint32_t imr; + + at91_mci_pdc_disable(sc); + + /* save current state */ + + imr = RD4(sc, MCI_IMR); +#ifndef __rtems__ + mr = RD4(sc, MCI_MR) & 0x7fff; +#else /* __rtems__ */ + mr = RD4(sc, MCI_MR); +#endif /* __rtems__ */ + sdcr = RD4(sc, MCI_SDCR); + dtor = RD4(sc, MCI_DTOR); + + /* reset the controller */ + + WR4(sc, MCI_IDR, 0xffffffff); + WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); + + /* restore state */ + + WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN); + WR4(sc, MCI_MR, mr); + WR4(sc, MCI_SDCR, sdcr); + WR4(sc, MCI_DTOR, dtor); + WR4(sc, MCI_IER, imr); + + /* + * Make sure sdio interrupts will fire. Not sure why reading + * SR ensures that, but this is in the linux driver. + */ + + RD4(sc, MCI_SR); +} + +static void +at91_mci_init(device_t dev) +{ + struct at91_mci_softc *sc = device_get_softc(dev); + uint32_t val; + + WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */ + WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */ + WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1M | 1); +#ifndef __rtems__ + val = MCI_MR_PDCMODE; +#else /* __rtems__ */ + val = 0; + val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF; +#endif /* __rtems__ */ + val |= 0x34a; /* PWSDIV = 3; CLKDIV = 74 */ +// if (sc->sc_cap & CAP_MCI1_REV2XX) +// val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF; + WR4(sc, MCI_MR, val); +#ifndef AT91_MCI_SLOT_B + WR4(sc, MCI_SDCR, 0); /* SLOT A, 1 bit bus */ +#else + /* + * XXX Really should add second "unit" but nobody using using + * a two slot card that we know of. XXX + */ + WR4(sc, MCI_SDCR, 1); /* SLOT B, 1 bit bus */ +#endif + /* + * Enable controller, including power-save. The slower clock + * of the power-save mode is only in effect when there is no + * transfer in progress, so it can be left in this mode all + * the time. + */ + WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN); +} + +static void +at91_mci_fini(device_t dev) +{ + struct at91_mci_softc *sc = device_get_softc(dev); + + WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */ + at91_mci_pdc_disable(sc); + WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */ +} + +static int +at91_mci_probe(device_t dev) +{ +#ifdef FDT + if (!ofw_bus_is_compatible(dev, "atmel,hsmci")) + return (ENXIO); +#endif + device_set_desc(dev, "MCI mmc/sd host bridge"); + return (0); +} + +static int +at91_mci_attach(device_t dev) +{ + struct at91_mci_softc *sc = device_get_softc(dev); + struct sysctl_ctx_list *sctx; + struct sysctl_oid *soid; + device_t child; +#ifndef __rtems__ + int err, i; +#else /* __rtems__ */ + int err; +#endif /* __rtems__ */ + +#ifdef __rtems__ +#ifdef LIBBSP_ARM_ATSAM_BSP_H + PMC_EnablePeripheral(ID_HSMCI); + sc->xdma_tx_channel = XDMAD_ALLOC_FAILED; + sc->xdma_rx_channel = XDMAD_ALLOC_FAILED; +#endif /* LIBBSP_ARM_ATSAM_BSP_H */ +#endif /* __rtems__ */ + sctx = device_get_sysctl_ctx(dev); + soid = device_get_sysctl_tree(dev); + + sc->dev = dev; + sc->sc_cap = 0; +#ifndef __rtems__ + if (at91_is_rm92()) + sc->sc_cap |= CAP_NEEDS_BYTESWAP; +#endif /* __rtems__ */ + /* + * MCI1 Rev 2 controllers need some workarounds, flag if so. + */ + if (at91_mci_is_mci1rev2xx()) + sc->sc_cap |= CAP_MCI1_REV2XX; + + err = at91_mci_activate(dev); + if (err) + goto out; + +#ifdef __rtems__ + eXdmadRC rc; + + /* Prepare some configurations so they don't have to be fetched on every + * setup */ + sc->xdma_rx_perid = XDMAIF_Get_ChannelNumber(ID_HSMCI, + XDMAD_TRANSFER_RX); + sc->xdma_tx_perid = XDMAIF_Get_ChannelNumber(ID_HSMCI, + XDMAD_TRANSFER_TX); + memset(&sc->xdma_rx_cfg, 0, sizeof(sc->xdma_rx_cfg)); + sc->xdma_rx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | + XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_PER2MEM | + XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE | + XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD | + XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 | + XDMAC_CC_SAM_FIXED_AM | XDMAC_CC_DAM_INCREMENTED_AM | + XDMAC_CC_PERID( + XDMAIF_Get_ChannelNumber(ID_HSMCI,XDMAD_TRANSFER_RX)); + memset(&sc->xdma_tx_cfg, 0, sizeof(sc->xdma_tx_cfg)); + sc->xdma_tx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | + XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER | + XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE | + XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD | + XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 | + XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_FIXED_AM | + XDMAC_CC_PERID( + XDMAIF_Get_ChannelNumber(ID_HSMCI,XDMAD_TRANSFER_TX)); + + sc->xdma_tx_channel = XDMAD_AllocateChannel(pXdmad, + XDMAD_TRANSFER_MEMORY, ID_HSMCI); + if (sc->xdma_tx_channel == XDMAD_ALLOC_FAILED) + goto out; + + /* FIXME: The two DMA channels are not really necessary for the driver. + * But the XDMAD interface does not allow to allocate one and use it + * into two directions. The current (2017-07-11) implementation of + * the XDMAD interface should work with it. So we might could try it. */ + sc->xdma_rx_channel = XDMAD_AllocateChannel(pXdmad, ID_HSMCI, + XDMAD_TRANSFER_MEMORY); + if (sc->xdma_rx_channel == XDMAD_ALLOC_FAILED) + goto out; + + rc = XDMAD_PrepareChannel(pXdmad, sc->xdma_rx_channel); + if (rc != XDMAD_OK) + goto out; + + rc = XDMAD_PrepareChannel(pXdmad, sc->xdma_tx_channel); + if (rc != XDMAD_OK) + goto out; + + AT91_MCI_BUS_LOCK_INIT(sc); +#endif /* __rtems__ */ + AT91_MCI_LOCK_INIT(sc); + + at91_mci_fini(dev); + at91_mci_init(dev); + +#ifndef __rtems__ + /* + * Allocate DMA tags and maps and bounce buffers. + * + * The parms in the tag_create call cause the dmamem_alloc call to + * create each bounce buffer as a single contiguous buffer of BBSIZE + * bytes aligned to a 4096 byte boundary. + * + * Do not use DMA_COHERENT for these buffers because that maps the + * memory as non-cachable, which prevents cache line burst fills/writes, + * which is something we need since we're trying to overlap the + * byte-swapping with the DMA operations. + */ + err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + BBSIZE, 1, BBSIZE, 0, NULL, NULL, &sc->dmatag); + if (err != 0) + goto out; + + for (i = 0; i < BBCOUNT; ++i) { + err = bus_dmamem_alloc(sc->dmatag, (void **)&sc->bbuf_vaddr[i], + BUS_DMA_NOWAIT, &sc->bbuf_map[i]); + if (err != 0) + goto out; + } + + /* + * Activate the interrupt + */ + err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, at91_mci_intr, sc, &sc->intrhand); +#else /* __rtems__ */ + err = rtems_interrupt_handler_install(rman_get_start(sc->irq_res), + device_get_nameunit(dev), RTEMS_INTERRUPT_SHARED, at91_mci_intr, + sc); +#endif /* __rtems__ */ + if (err) { + AT91_MCI_LOCK_DESTROY(sc); + goto out; + } + + /* + * Allow 4-wire to be initially set via #define. + * Allow a device hint to override that. + * Allow a sysctl to override that. + */ +#if defined(AT91_MCI_HAS_4WIRE) && AT91_MCI_HAS_4WIRE != 0 + sc->has_4wire = 1; +#endif + resource_int_value(device_get_name(dev), device_get_unit(dev), + "4wire", &sc->has_4wire); + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "4wire", + CTLFLAG_RW, &sc->has_4wire, 0, "has 4 wire SD Card bus"); + if (sc->has_4wire) + sc->sc_cap |= CAP_HAS_4WIRE; + + sc->allow_overclock = AT91_MCI_ALLOW_OVERCLOCK; + resource_int_value(device_get_name(dev), device_get_unit(dev), + "allow_overclock", &sc->allow_overclock); + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "allow_overclock", + CTLFLAG_RW, &sc->allow_overclock, 0, + "Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less."); + +#ifndef __rtems__ + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug", + CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output"); +#endif /* __rtems__ */ + + /* + * Our real min freq is master_clock/512, but upper driver layers are + * going to set the min speed during card discovery, and the right speed + * for that is 400kHz, so advertise a safe value just under that. + * + * For max speed, while the rm9200 manual says the max is 50mhz, it also + * says it supports only the SD v1.0 spec, which means the real limit is + * 25mhz. On the other hand, historical use has been to slightly violate + * the standard by running the bus at 30MHz. For more information on + * that, see the comments at the top of this file. + */ + sc->host.f_min = 375000; + sc->host.f_max = at91_master_clock / 2; + if (sc->host.f_max > 25000000) + sc->host.f_max = 25000000; + sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; + sc->host.caps = 0; + if (sc->sc_cap & CAP_HAS_4WIRE) + sc->host.caps |= MMC_CAP_4_BIT_DATA; + + child = device_add_child(dev, "mmc", 0); +#ifdef __rtems__ + (void)child; +#endif /* __rtems__ */ + device_set_ivars(dev, &sc->host); + err = bus_generic_attach(dev); +out: + if (err) + at91_mci_deactivate(dev); + return (err); +} + +static int +at91_mci_detach(device_t dev) +{ +#ifndef __rtems__ + struct at91_mci_softc *sc = device_get_softc(dev); +#endif /* __rtems__ */ + + at91_mci_fini(dev); + at91_mci_deactivate(dev); + +#ifndef __rtems__ + bus_dmamem_free(sc->dmatag, sc->bbuf_vaddr[0], sc->bbuf_map[0]); + bus_dmamem_free(sc->dmatag, sc->bbuf_vaddr[1], sc->bbuf_map[1]); + bus_dma_tag_destroy(sc->dmatag); +#endif /* __rtems__ */ + + return (EBUSY); /* XXX */ +} + +static int +at91_mci_activate(device_t dev) +{ + struct at91_mci_softc *sc; + int rid; + + sc = device_get_softc(dev); + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) + goto errout; + + rid = 0; + sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->irq_res == NULL) + goto errout; + + return (0); +errout: + at91_mci_deactivate(dev); + return (ENOMEM); +} + +static void +at91_mci_deactivate(device_t dev) +{ + struct at91_mci_softc *sc; + + sc = device_get_softc(dev); + if (sc->intrhand) + bus_teardown_intr(dev, sc->irq_res, sc->intrhand); + sc->intrhand = NULL; + bus_generic_detach(sc->dev); + if (sc->mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(sc->mem_res), sc->mem_res); + sc->mem_res = NULL; + if (sc->irq_res) + bus_release_resource(dev, SYS_RES_IRQ, + rman_get_rid(sc->irq_res), sc->irq_res); + sc->irq_res = NULL; +#ifdef __rtems__ + if (sc->xdma_rx_channel != XDMAD_ALLOC_FAILED) { + XDMAD_FreeChannel(pXdmad, sc->xdma_rx_channel); + } + if (sc->xdma_tx_channel != XDMAD_ALLOC_FAILED) { + XDMAD_FreeChannel(pXdmad, sc->xdma_tx_channel); + } +#endif /* __rtems__ */ + return; +} + +static int +at91_mci_is_mci1rev2xx(void) +{ + +#ifndef __rtems__ + switch (soc_info.type) { + case AT91_T_SAM9260: + case AT91_T_SAM9263: + case AT91_T_CAP9: + case AT91_T_SAM9G10: + case AT91_T_SAM9G20: + case AT91_T_SAM9RL: + return(1); + default: + return (0); + } +#else /* __rtems__ */ + /* Currently only supports the SAM V71 */ + return (1); +#endif /* __rtems__ */ +} + +static int +at91_mci_update_ios(device_t brdev, device_t reqdev) +{ + struct at91_mci_softc *sc; + struct mmc_ios *ios; + uint32_t clkdiv; + uint32_t freq; + + sc = device_get_softc(brdev); + ios = &sc->host.ios; + + /* + * Calculate our closest available clock speed that doesn't exceed the + * requested speed. + * + * When overclocking is allowed, the requested clock is 25MHz, the + * computed frequency is 15MHz or smaller and clockdiv is 1, use + * clockdiv of 0 to double that. If less than 12.5MHz, double + * regardless of the overclocking setting. + * + * Whatever we come up with, store it back into ios->clock so that the + * upper layer drivers can report the actual speed of the bus. + */ + if (ios->clock == 0) { + WR4(sc, MCI_CR, MCI_CR_MCIDIS); + clkdiv = 0; + } else { + WR4(sc, MCI_CR, MCI_CR_MCIEN|MCI_CR_PWSEN); + if ((at91_master_clock % (ios->clock * 2)) == 0) + clkdiv = ((at91_master_clock / ios->clock) / 2) - 1; + else + clkdiv = (at91_master_clock / ios->clock) / 2; + freq = at91_master_clock / ((clkdiv+1) * 2); + if (clkdiv == 1 && ios->clock == 25000000 && freq <= 15000000) { + if (sc->allow_overclock || freq <= 12500000) { + clkdiv = 0; + freq = at91_master_clock / ((clkdiv+1) * 2); + } + } + ios->clock = freq; + } + if (ios->bus_width == bus_width_4) + WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) | MCI_SDCR_SDCBUS); + else + WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) & ~MCI_SDCR_SDCBUS); + WR4(sc, MCI_MR, (RD4(sc, MCI_MR) & ~MCI_MR_CLKDIV) | clkdiv); + /* Do we need a settle time here? */ + /* XXX We need to turn the device on/off here with a GPIO pin */ + return (0); +} + +#ifdef __rtems__ +static void +at91_mci_setup_xdma(struct at91_mci_softc *sc, bool read, void *data, + uint32_t len) +{ + const uint32_t xdma_cndc = XDMAC_CNDC_NDVIEW_NDV1 | + XDMAC_CNDC_NDE_DSCR_FETCH_EN | + XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | + XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED; + const uint32_t xdma_interrupt = XDMAC_CIE_BIE | XDMAC_CIE_DIE | + XDMAC_CIE_FIE | XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE; + sXdmadCfg *xdma_cfg; + uint32_t xdma_channel; + eXdmadRC rc; + + if (len % 4 != 0) + panic("invalid XDMA transfer length"); + + if (read) { + xdma_cfg = &sc->xdma_rx_cfg; + xdma_channel = sc->xdma_rx_channel; + sc->xdma_desc.mbr_sa = (uint32_t)(sc->mem_res->r_bushandle + + MCI_RDR); + sc->xdma_desc.mbr_da = (uint32_t)data; + rtems_cache_invalidate_multiple_data_lines(data, len); + } else { + xdma_cfg = &sc->xdma_tx_cfg; + xdma_channel = sc->xdma_tx_channel; + sc->xdma_desc.mbr_sa = (uint32_t)data; + sc->xdma_desc.mbr_da = (uint32_t)(sc->mem_res->r_bushandle + + MCI_TDR); + rtems_cache_flush_multiple_data_lines(data, len); + } + + sc->xdma_desc.mbr_ubc = XDMA_UBC_NVIEW_NDV1 | + XDMA_UBC_NDEN_UPDATED | (len / 4); + sc->xdma_desc.mbr_ubc |= XDMA_UBC_NDE_FETCH_DIS; + sc->xdma_desc.mbr_nda = 0; + + rc = XDMAD_ConfigureTransfer(pXdmad, xdma_channel, xdma_cfg, xdma_cndc, + (uint32_t)&sc->xdma_desc, xdma_interrupt); + if (rc != XDMAD_OK) + panic("configure XDMA failed: %d", rc); + + rtems_cache_flush_multiple_data_lines(&sc->xdma_desc, sizeof(sc->xdma_desc)); + + rc = XDMAD_StartTransfer(pXdmad, xdma_channel); + if (rc != XDMAD_OK) + panic("start XDMA failed: %d", rc); +} +#endif /* __rtems__ */ +static void +at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) +{ + uint32_t cmdr, mr; + struct mmc_data *data; +#ifdef __rtems__ + uint32_t block_count; + uint32_t block_size; +#endif /* __rtems__ */ + + sc->curcmd = cmd; + data = cmd->data; + + /* XXX Upper layers don't always set this */ + cmd->mrq = sc->req; + + /* Begin setting up command register. */ + + cmdr = cmd->opcode; + + if (sc->host.ios.bus_mode == opendrain) + cmdr |= MCI_CMDR_OPDCMD; + + /* Set up response handling. Allow max timeout for responses. */ + + if (MMC_RSP(cmd->flags) == MMC_RSP_NONE) + cmdr |= MCI_CMDR_RSPTYP_NO; + else { + cmdr |= MCI_CMDR_MAXLAT; + if (cmd->flags & MMC_RSP_136) + cmdr |= MCI_CMDR_RSPTYP_136; + else + cmdr |= MCI_CMDR_RSPTYP_48; + } + + /* + * If there is no data transfer, just set up the right interrupt mask + * and start the command. + * + * The interrupt mask needs to be CMDRDY plus all non-data-transfer + * errors. It's important to leave the transfer-related errors out, to + * avoid spurious timeout or crc errors on a STOP command following a + * multiblock read. When a multiblock read is in progress, sending a + * STOP in the middle of a block occasionally triggers such errors, but + * we're totally disinterested in them because we've already gotten all + * the data we wanted without error before sending the STOP command. + */ + + if (data == NULL) { + uint32_t ier = MCI_SR_CMDRDY | + MCI_SR_RTOE | MCI_SR_RENDE | + MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE; + + at91_mci_pdc_disable(sc); + + if (cmd->opcode == MMC_STOP_TRANSMISSION) + cmdr |= MCI_CMDR_TRCMD_STOP; + + /* Ignore response CRC on CMD2 and ACMD41, per standard. */ + + if (cmd->opcode == MMC_SEND_OP_COND || + cmd->opcode == ACMD_SD_SEND_OP_COND) + ier &= ~MCI_SR_RCRCE; + + if (mci_debug) + printf("CMDR %x (opcode %d) ARGR %x no data\n", + cmdr, cmd->opcode, cmd->arg); + + WR4(sc, MCI_ARGR, cmd->arg); + WR4(sc, MCI_CMDR, cmdr); + WR4(sc, MCI_IDR, 0xffffffff); + WR4(sc, MCI_IER, ier); + return; + } + + /* There is data, set up the transfer-related parts of the command. */ + + if (data->flags & MMC_DATA_READ) + cmdr |= MCI_CMDR_TRDIR; + + if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) + cmdr |= MCI_CMDR_TRCMD_START; + + if (data->flags & MMC_DATA_STREAM) + cmdr |= MCI_CMDR_TRTYP_STREAM; + else if (data->flags & MMC_DATA_MULTI) { + cmdr |= MCI_CMDR_TRTYP_MULTIPLE; + sc->flags |= (data->flags & MMC_DATA_READ) ? + CMD_MULTIREAD : CMD_MULTIWRITE; + } + + /* + * Disable PDC until we're ready. + * + * Set block size and turn on PDC mode for dma xfer. + * Note that the block size is the smaller of the amount of data to be + * transferred, or 512 bytes. The 512 size is fixed by the standard; + * smaller blocks are possible, but never larger. + */ + +#ifndef __rtems__ + WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); + + mr = RD4(sc,MCI_MR) & ~MCI_MR_BLKLEN; + mr |= min(data->len, 512) << 16; + WR4(sc, MCI_MR, mr | MCI_MR_PDCMODE|MCI_MR_PDCPADV); + + /* + * Set up DMA. + * + * Use bounce buffers even if we don't need to byteswap, because doing + * multi-block IO with large DMA buffers is way fast (compared to + * single-block IO), even after incurring the overhead of also copying + * from/to the caller's buffers (which may be in non-contiguous physical + * pages). + * + * In an ideal non-byteswap world we could create a dma tag that allows + * for discontiguous segments and do the IO directly from/to the + * caller's buffer(s), using ENDRX/ENDTX interrupts to chain the + * discontiguous buffers through the PDC. Someday. + * + * If a read is bigger than 2k, split it in half so that we can start + * byte-swapping the first half while the second half is on the wire. + * It would be best if we could split it into 8k chunks, but we can't + * always keep up with the byte-swapping due to other system activity, + * and if an RXBUFF interrupt happens while we're still handling the + * byte-swap from the prior buffer (IE, we haven't returned from + * handling the prior interrupt yet), then data will get dropped on the + * floor and we can't easily recover from that. The right fix for that + * would be to have the interrupt handling only keep the DMA flowing and + * enqueue filled buffers to be byte-swapped in a non-interrupt context. + * Even that won't work on the write side of things though; in that + * context we have to have all the data ready to go before starting the + * dma. + * + * XXX what about stream transfers? + */ + sc->xfer_offset = 0; + sc->bbuf_curidx = 0; +#else /* __rtems__ */ + mr = RD4(sc,MCI_MR); + WR4(sc, MCI_MR, mr | MCI_MR_PDCPADV); + + WR4(sc, MCI_DMA, MCI_DMA_DMAEN | MCI_DMA_CHKSIZE_1); + + block_size = min(data->len, 512); + block_count = data->len / block_size; + WR4(sc, MCI_BLKR, (block_size << 16) | block_count); +#endif /* __rtems__ */ + + if (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) { +#ifndef __rtems__ + uint32_t len; + uint32_t remaining = data->len; + bus_addr_t paddr; + int err; + + if (remaining > (BBCOUNT*BBSIZE)) + panic("IO read size exceeds MAXDATA\n"); +#endif /* __rtems__ */ + + if (data->flags & MMC_DATA_READ) { +#ifndef __rtems__ + if (remaining > 2048) // XXX + len = remaining / 2; + else + len = remaining; + err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], + sc->bbuf_vaddr[0], len, at91_mci_getaddr, + &paddr, BUS_DMA_NOWAIT); + if (err != 0) + panic("IO read dmamap_load failed\n"); + bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], + BUS_DMASYNC_PREREAD); + WR4(sc, PDC_RPR, paddr); + WR4(sc, PDC_RCR, len / 4); + sc->bbuf_len[0] = len; + remaining -= len; + if (remaining == 0) { + sc->bbuf_len[1] = 0; + } else { + len = remaining; + err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1], + sc->bbuf_vaddr[1], len, at91_mci_getaddr, + &paddr, BUS_DMA_NOWAIT); + if (err != 0) + panic("IO read dmamap_load failed\n"); + bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], + BUS_DMASYNC_PREREAD); + WR4(sc, PDC_RNPR, paddr); + WR4(sc, PDC_RNCR, len / 4); + sc->bbuf_len[1] = len; + remaining -= len; + } + WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); +#else /* __rtems__ */ + at91_mci_setup_xdma(sc, true, data->data, data->len); +#endif /* __rtems__ */ + } else { +#ifndef __rtems__ + len = min(BBSIZE, remaining); + at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len); + err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], + sc->bbuf_vaddr[0], len, at91_mci_getaddr, + &paddr, BUS_DMA_NOWAIT); + if (err != 0) + panic("IO write dmamap_load failed\n"); + bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], + BUS_DMASYNC_PREWRITE); + /* + * Erratum workaround: PDC transfer length on a write + * must not be smaller than 12 bytes (3 words); only + * blklen bytes (set above) are actually transferred. + */ + WR4(sc, PDC_TPR,paddr); + WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4); + sc->bbuf_len[0] = len; + remaining -= len; + if (remaining == 0) { + sc->bbuf_len[1] = 0; + } else { + len = remaining; + at91_bswap_buf(sc, sc->bbuf_vaddr[1], + ((char *)data->data)+BBSIZE, len); + err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[1], + sc->bbuf_vaddr[1], len, at91_mci_getaddr, + &paddr, BUS_DMA_NOWAIT); + if (err != 0) + panic("IO write dmamap_load failed\n"); + bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], + BUS_DMASYNC_PREWRITE); + WR4(sc, PDC_TNPR, paddr); + WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4); + sc->bbuf_len[1] = len; + remaining -= len; + } + /* do not enable PDC xfer until CMDRDY asserted */ +#else /* __rtems__ */ + at91_mci_setup_xdma(sc, false, data->data, data->len); +#endif /* __rtems__ */ + } + data->xfer_len = 0; /* XXX what's this? appears to be unused. */ + } + + if (mci_debug) + printf("CMDR %x (opcode %d) ARGR %x with data len %d\n", + cmdr, cmd->opcode, cmd->arg, cmd->data->len); + + WR4(sc, MCI_ARGR, cmd->arg); + WR4(sc, MCI_CMDR, cmdr); + WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_CMDRDY); +} + +static void +at91_mci_next_operation(struct at91_mci_softc *sc) +{ + struct mmc_request *req; + + req = sc->req; + if (req == NULL) + return; + + if (sc->flags & PENDING_CMD) { + sc->flags &= ~PENDING_CMD; + at91_mci_start_cmd(sc, req->cmd); + return; + } else if (sc->flags & PENDING_STOP) { + sc->flags &= ~PENDING_STOP; + at91_mci_start_cmd(sc, req->stop); + return; + } + + WR4(sc, MCI_IDR, 0xffffffff); + sc->req = NULL; + sc->curcmd = NULL; + //printf("req done\n"); + req->done(req); +} + +static int +at91_mci_request(device_t brdev, device_t reqdev, struct mmc_request *req) +{ + struct at91_mci_softc *sc = device_get_softc(brdev); + + AT91_MCI_LOCK(sc); + if (sc->req != NULL) { + AT91_MCI_UNLOCK(sc); + return (EBUSY); + } + //printf("new req\n"); + sc->req = req; + sc->flags = PENDING_CMD; + if (sc->req->stop) + sc->flags |= PENDING_STOP; + at91_mci_next_operation(sc); + AT91_MCI_UNLOCK(sc); + return (0); +} + +static int +at91_mci_get_ro(device_t brdev, device_t reqdev) +{ + return (0); +} + +static int +at91_mci_acquire_host(device_t brdev, device_t reqdev) +{ + struct at91_mci_softc *sc = device_get_softc(brdev); + int err = 0; + +#ifndef __rtems__ + AT91_MCI_LOCK(sc); +#else /* __rtems__ */ + AT91_MCI_BUS_LOCK(sc); +#endif /* __rtems__ */ + while (sc->bus_busy) + msleep(sc, &sc->sc_mtx, PZERO, "mciah", hz / 5); + sc->bus_busy++; +#ifndef __rtems__ + AT91_MCI_UNLOCK(sc); +#else /* __rtems__ */ + AT91_MCI_BUS_UNLOCK(sc); +#endif /* __rtems__ */ + return (err); +} + +static int +at91_mci_release_host(device_t brdev, device_t reqdev) +{ + struct at91_mci_softc *sc = device_get_softc(brdev); + +#ifndef __rtems__ + AT91_MCI_LOCK(sc); +#else /* __rtems__ */ + AT91_MCI_BUS_LOCK(sc); +#endif /* __rtems__ */ + sc->bus_busy--; + wakeup(sc); +#ifndef __rtems__ + AT91_MCI_UNLOCK(sc); +#else /* __rtems__ */ + AT91_MCI_BUS_UNLOCK(sc); +#endif /* __rtems__ */ + return (0); +} + +#ifndef __rtems__ +static void +at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr) +{ + struct mmc_command *cmd = sc->curcmd; + char * dataptr = (char *)cmd->data->data; + uint32_t curidx = sc->bbuf_curidx; + uint32_t len = sc->bbuf_len[curidx]; + + /* + * We arrive here when a DMA transfer for a read is done, whether it's + * a single or multi-block read. + * + * We byte-swap the buffer that just completed, and if that is the + * last buffer that's part of this read then we move on to the next + * operation, otherwise we wait for another ENDRX for the next bufer. + */ + + bus_dmamap_sync(sc->dmatag, sc->bbuf_map[curidx], BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->dmatag, sc->bbuf_map[curidx]); + + at91_bswap_buf(sc, dataptr + sc->xfer_offset, sc->bbuf_vaddr[curidx], len); + + if (mci_debug) { + printf("read done sr %x curidx %d len %d xfer_offset %d\n", + sr, curidx, len, sc->xfer_offset); + } + + sc->xfer_offset += len; + sc->bbuf_curidx = !curidx; /* swap buffers */ + + /* + * If we've transferred all the data, move on to the next operation. + * + * If we're still transferring the last buffer, RNCR is already zero but + * we have to write a zero anyway to clear the ENDRX status so we don't + * re-interrupt until the last buffer is done. + */ + if (sc->xfer_offset == cmd->data->len) { + WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); + cmd->error = MMC_ERR_NONE; + at91_mci_next_operation(sc); + } else { + WR4(sc, PDC_RNCR, 0); + WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_ENDRX); + } +} +#endif /* __rtems__ */ + +static void +at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr) +{ + struct mmc_command *cmd = sc->curcmd; + + /* + * We arrive here when the entire DMA transfer for a write is done, + * whether it's a single or multi-block write. If it's multi-block we + * have to immediately move on to the next operation which is to send + * the stop command. If it's a single-block transfer we need to wait + * for NOTBUSY, but if that's already asserted we can avoid another + * interrupt and just move on to completing the request right away. + */ + + WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS); + +#ifndef __rtems__ + bus_dmamap_sync(sc->dmatag, sc->bbuf_map[sc->bbuf_curidx], + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmatag, sc->bbuf_map[sc->bbuf_curidx]); +#endif /* __rtems__ */ + + if ((cmd->data->flags & MMC_DATA_MULTI) || (sr & MCI_SR_NOTBUSY)) { + cmd->error = MMC_ERR_NONE; + at91_mci_next_operation(sc); + } else { + WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY); + } +} + +static void +at91_mci_notbusy(struct at91_mci_softc *sc) +{ + struct mmc_command *cmd = sc->curcmd; + + /* + * We arrive here by either completion of a single-block write, or + * completion of the stop command that ended a multi-block write (and, + * I suppose, after a card-select or erase, but I haven't tested + * those). Anyway, we're done and it's time to move on to the next + * command. + */ + + cmd->error = MMC_ERR_NONE; + at91_mci_next_operation(sc); +} + +static void +at91_mci_stop_done(struct at91_mci_softc *sc, uint32_t sr) +{ + struct mmc_command *cmd = sc->curcmd; + + /* + * We arrive here after receiving CMDRDY for a MMC_STOP_TRANSMISSION + * command. Depending on the operation being stopped, we may have to + * do some unusual things to work around hardware bugs. + */ + + /* + * This is known to be true of at91rm9200 hardware; it may or may not + * apply to more recent chips: + * + * After stopping a multi-block write, the NOTBUSY bit in MCI_SR does + * not properly reflect the actual busy state of the card as signaled + * on the DAT0 line; it always claims the card is not-busy. If we + * believe that and let operations continue, following commands will + * fail with response timeouts (except of course MMC_SEND_STATUS -- it + * indicates the card is busy in the PRG state, which was the smoking + * gun that showed MCI_SR NOTBUSY was not tracking DAT0 correctly). + * + * The atmel docs are emphatic: "This flag [NOTBUSY] must be used only + * for Write Operations." I guess technically since we sent a stop + * it's not a write operation anymore. But then just what did they + * think it meant for the stop command to have "...an optional busy + * signal transmitted on the data line" according to the SD spec? + * + * I tried a variety of things to un-wedge the MCI and get the status + * register to reflect NOTBUSY correctly again, but the only thing + * that worked was a full device reset. It feels like an awfully big + * hammer, but doing a full reset after every multiblock write is + * still faster than doing single-block IO (by almost two orders of + * magnitude: 20KB/sec improves to about 1.8MB/sec best case). + * + * After doing the reset, wait for a NOTBUSY interrupt before + * continuing with the next operation. + * + * This workaround breaks multiwrite on the rev2xx parts, but some other + * workaround is needed. + */ + if ((sc->flags & CMD_MULTIWRITE) && (sc->sc_cap & CAP_NEEDS_BYTESWAP)) { + at91_mci_reset(sc); + WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY); + return; + } + + /* + * This is known to be true of at91rm9200 hardware; it may or may not + * apply to more recent chips: + * + * After stopping a multi-block read, loop to read and discard any + * data that coasts in after we sent the stop command. The docs don't + * say anything about it, but empirical testing shows that 1-3 + * additional words of data get buffered up in some unmentioned + * internal fifo and if we don't read and discard them here they end + * up on the front of the next read DMA transfer we do. + * + * This appears to be unnecessary for rev2xx parts. + */ + if ((sc->flags & CMD_MULTIREAD) && (sc->sc_cap & CAP_NEEDS_BYTESWAP)) { + uint32_t sr; + int count = 0; + + do { + sr = RD4(sc, MCI_SR); + if (sr & MCI_SR_RXRDY) { + RD4(sc, MCI_RDR); + ++count; + } + } while (sr & MCI_SR_RXRDY); + at91_mci_reset(sc); + } + + cmd->error = MMC_ERR_NONE; + at91_mci_next_operation(sc); + +} + +static void +at91_mci_cmdrdy(struct at91_mci_softc *sc, uint32_t sr) +{ + struct mmc_command *cmd = sc->curcmd; + int i; + + if (cmd == NULL) + return; + + /* + * We get here at the end of EVERY command. We retrieve the command + * response (if any) then decide what to do next based on the command. + */ + + if (cmd->flags & MMC_RSP_PRESENT) { + for (i = 0; i < ((cmd->flags & MMC_RSP_136) ? 4 : 1); i++) { + cmd->resp[i] = RD4(sc, MCI_RSPR + i * 4); + if (mci_debug) + printf("RSPR[%d] = %x sr=%x\n", i, cmd->resp[i], sr); + } + } + + /* + * If this was a stop command, go handle the various special + * conditions (read: bugs) that have to be dealt with following a stop. + */ + if (cmd->opcode == MMC_STOP_TRANSMISSION) { + at91_mci_stop_done(sc, sr); + return; + } + + /* + * If this command can continue to assert BUSY beyond the response then + * we need to wait for NOTBUSY before the command is really done. + * + * Note that this may not work properly on the at91rm9200. It certainly + * doesn't work for the STOP command that follows a multi-block write, + * so post-stop CMDRDY is handled separately; see the special handling + * in at91_mci_stop_done(). + * + * Beside STOP, there are other R1B-type commands that use the busy + * signal after CMDRDY: CMD7 (card select), CMD28-29 (write protect), + * CMD38 (erase). I haven't tested any of them, but I rather expect + * them all to have the same sort of problem with MCI_SR not actually + * reflecting the state of the DAT0-line busy indicator. So this code + * may need to grow some sort of special handling for them too. (This + * just in: CMD7 isn't a problem right now because dev/mmc.c incorrectly + * sets the response flags to R1 rather than R1B.) XXX + */ + if ((cmd->flags & MMC_RSP_BUSY)) { + WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_NOTBUSY); + return; + } + + /* + * If there is a data transfer with this command, then... + * - If it's a read, we need to wait for ENDRX. + * - If it's a write, now is the time to enable the PDC, and we need + * to wait for a BLKE that follows a TXBUFE, because if we're doing + * a split transfer we get a BLKE after the first half (when TPR/TCR + * get loaded from TNPR/TNCR). So first we wait for the TXBUFE, and + * the handling for that interrupt will then invoke the wait for the + * subsequent BLKE which indicates actual completion. + */ + if (cmd->data) { + uint32_t ier; +#ifndef __rtems__ + if (cmd->data->flags & MMC_DATA_READ) { + ier = MCI_SR_ENDRX; + } else { + ier = MCI_SR_TXBUFE; + WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN); + } +#else /* __rtems__ */ + ier = MCI_SR_XFRDONE; +#endif /* __rtems__ */ + WR4(sc, MCI_IER, MCI_SR_ERROR | ier); + return; + } + + /* + * If we made it to here, we don't need to wait for anything more for + * the current command, move on to the next command (will complete the + * request if there is no next command). + */ + cmd->error = MMC_ERR_NONE; + at91_mci_next_operation(sc); +} + +static void +at91_mci_intr(void *arg) +{ + struct at91_mci_softc *sc = (struct at91_mci_softc*)arg; + struct mmc_command *cmd = sc->curcmd; + uint32_t sr, isr; + + AT91_MCI_LOCK(sc); + + sr = RD4(sc, MCI_SR); + isr = sr & RD4(sc, MCI_IMR); + + if (mci_debug) + printf("i 0x%x sr 0x%x\n", isr, sr); + + /* + * All interrupts are one-shot; disable it now. + * The next operation will re-enable whatever interrupts it wants. + */ + WR4(sc, MCI_IDR, isr); + if (isr & MCI_SR_ERROR) { + if (isr & (MCI_SR_RTOE | MCI_SR_DTOE)) + cmd->error = MMC_ERR_TIMEOUT; + else if (isr & (MCI_SR_RCRCE | MCI_SR_DCRCE)) + cmd->error = MMC_ERR_BADCRC; + else if (isr & (MCI_SR_OVRE | MCI_SR_UNRE)) + cmd->error = MMC_ERR_FIFO; + else + cmd->error = MMC_ERR_FAILED; + /* + * CMD8 is used to probe for SDHC cards, a standard SD card + * will get a response timeout; don't report it because it's a + * normal and expected condition. One might argue that all + * error reporting should be left to higher levels, but when + * they report at all it's always EIO, which isn't very + * helpful. XXX bootverbose? + */ + if (cmd->opcode != 8) { + device_printf(sc->dev, + "IO error; status MCI_SR = 0x%b cmd opcode = %d%s\n", + sr, MCI_SR_BITSTRING, cmd->opcode, + (cmd->opcode != 12) ? "" : + (sc->flags & CMD_MULTIREAD) ? " after read" : " after write"); + /* XXX not sure RTOE needs a full reset, just a retry */ + at91_mci_reset(sc); + } + at91_mci_next_operation(sc); + } else { +#ifndef __rtems__ + if (isr & MCI_SR_TXBUFE) { +// printf("TXBUFE\n"); + /* + * We need to wait for a BLKE that follows TXBUFE + * (intermediate BLKEs might happen after ENDTXes if + * we're chaining multiple buffers). If BLKE is also + * asserted at the time we get TXBUFE, we can avoid + * another interrupt and process it right away, below. + */ + if (sr & MCI_SR_BLKE) + isr |= MCI_SR_BLKE; + else + WR4(sc, MCI_IER, MCI_SR_BLKE); + } + if (isr & MCI_SR_RXBUFF) { +// printf("RXBUFF\n"); + } + if (isr & MCI_SR_ENDTX) { +// printf("ENDTX\n"); + } + if (isr & MCI_SR_ENDRX) { +// printf("ENDRX\n"); + at91_mci_read_done(sc, sr); + } +#else /* __rtems__ */ + if (isr & MCI_SR_XFRDONE) { + if (cmd->data->flags & MMC_DATA_READ) { + WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | + PDC_PTCR_TXTDIS); + cmd->error = MMC_ERR_NONE; + at91_mci_next_operation(sc); + } else { + if (sr & MCI_SR_BLKE) + isr |= MCI_SR_BLKE; + else + WR4(sc, MCI_IER, MCI_SR_BLKE); + } + } +#endif /* __rtems__ */ + if (isr & MCI_SR_NOTBUSY) { +// printf("NOTBUSY\n"); + at91_mci_notbusy(sc); + } + if (isr & MCI_SR_DTIP) { +// printf("Data transfer in progress\n"); + } + if (isr & MCI_SR_BLKE) { +// printf("Block transfer end\n"); + at91_mci_write_done(sc, sr); + } + if (isr & MCI_SR_TXRDY) { +// printf("Ready to transmit\n"); + } + if (isr & MCI_SR_RXRDY) { +// printf("Ready to receive\n"); + } + if (isr & MCI_SR_CMDRDY) { +// printf("Command ready\n"); + at91_mci_cmdrdy(sc, sr); + } + } + AT91_MCI_UNLOCK(sc); +} + +static int +at91_mci_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) +{ + struct at91_mci_softc *sc = device_get_softc(bus); + + switch (which) { + default: + return (EINVAL); + case MMCBR_IVAR_BUS_MODE: + *(int *)result = sc->host.ios.bus_mode; + break; + case MMCBR_IVAR_BUS_WIDTH: + *(int *)result = sc->host.ios.bus_width; + break; + case MMCBR_IVAR_CHIP_SELECT: + *(int *)result = sc->host.ios.chip_select; + break; + case MMCBR_IVAR_CLOCK: + *(int *)result = sc->host.ios.clock; + break; + case MMCBR_IVAR_F_MIN: + *(int *)result = sc->host.f_min; + break; + case MMCBR_IVAR_F_MAX: + *(int *)result = sc->host.f_max; + break; + case MMCBR_IVAR_HOST_OCR: + *(int *)result = sc->host.host_ocr; + break; + case MMCBR_IVAR_MODE: + *(int *)result = sc->host.mode; + break; + case MMCBR_IVAR_OCR: + *(int *)result = sc->host.ocr; + break; + case MMCBR_IVAR_POWER_MODE: + *(int *)result = sc->host.ios.power_mode; + break; + case MMCBR_IVAR_VDD: + *(int *)result = sc->host.ios.vdd; + break; + case MMCBR_IVAR_CAPS: + if (sc->has_4wire) { + sc->sc_cap |= CAP_HAS_4WIRE; + sc->host.caps |= MMC_CAP_4_BIT_DATA; + } else { + sc->sc_cap &= ~CAP_HAS_4WIRE; + sc->host.caps &= ~MMC_CAP_4_BIT_DATA; + } + *(int *)result = sc->host.caps; + break; +#ifdef __rtems__ + case MMCBR_IVAR_TIMING: + *result = sc->host.ios.timing; + break; +#endif /* __rtems__ */ + case MMCBR_IVAR_MAX_DATA: + /* + * Something is wrong with the 2x parts and multiblock, so + * just do 1 block at a time for now, which really kills + * performance. + */ + if (sc->sc_cap & CAP_MCI1_REV2XX) + *(int *)result = 1; + else + *(int *)result = MAX_BLOCKS; + break; + } + return (0); +} + +static int +at91_mci_write_ivar(device_t bus, device_t child, int which, uintptr_t value) +{ + struct at91_mci_softc *sc = device_get_softc(bus); + + switch (which) { + default: + return (EINVAL); + case MMCBR_IVAR_BUS_MODE: + sc->host.ios.bus_mode = value; + break; + case MMCBR_IVAR_BUS_WIDTH: + sc->host.ios.bus_width = value; + break; + case MMCBR_IVAR_CHIP_SELECT: + sc->host.ios.chip_select = value; + break; + case MMCBR_IVAR_CLOCK: + sc->host.ios.clock = value; + break; + case MMCBR_IVAR_MODE: + sc->host.mode = value; + break; + case MMCBR_IVAR_OCR: + sc->host.ocr = value; + break; + case MMCBR_IVAR_POWER_MODE: + sc->host.ios.power_mode = value; + break; + case MMCBR_IVAR_VDD: + sc->host.ios.vdd = value; + break; +#ifdef __rtems__ + case MMCBR_IVAR_TIMING: + sc->host.ios.timing = value; + break; +#endif /* __rtems__ */ + /* These are read-only */ + case MMCBR_IVAR_CAPS: + case MMCBR_IVAR_HOST_OCR: + case MMCBR_IVAR_F_MIN: + case MMCBR_IVAR_F_MAX: + case MMCBR_IVAR_MAX_DATA: + return (EINVAL); + } + return (0); +} + +static device_method_t at91_mci_methods[] = { + /* device_if */ + DEVMETHOD(device_probe, at91_mci_probe), + DEVMETHOD(device_attach, at91_mci_attach), + DEVMETHOD(device_detach, at91_mci_detach), + + /* Bus interface */ + DEVMETHOD(bus_read_ivar, at91_mci_read_ivar), + DEVMETHOD(bus_write_ivar, at91_mci_write_ivar), + + /* mmcbr_if */ + DEVMETHOD(mmcbr_update_ios, at91_mci_update_ios), + DEVMETHOD(mmcbr_request, at91_mci_request), + DEVMETHOD(mmcbr_get_ro, at91_mci_get_ro), + DEVMETHOD(mmcbr_acquire_host, at91_mci_acquire_host), + DEVMETHOD(mmcbr_release_host, at91_mci_release_host), + + DEVMETHOD_END +}; + +static driver_t at91_mci_driver = { + "at91_mci", + at91_mci_methods, + sizeof(struct at91_mci_softc), +}; + +static devclass_t at91_mci_devclass; + +#ifndef __rtems__ +#ifdef FDT +DRIVER_MODULE(at91_mci, simplebus, at91_mci_driver, at91_mci_devclass, NULL, + NULL); +#else +DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, NULL, + NULL); +#endif + +MMC_DECLARE_BRIDGE(at91_mci); +#else /* __rtems__ */ +DRIVER_MODULE(at91_mci, nexus, at91_mci_driver, at91_mci_devclass, NULL, NULL); +#endif /* __rtems__ */ +DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL); +MODULE_DEPEND(at91_mci, mmc, 1, 1, 1); +#endif /* __rtems__ && LIBBSP_ARM_ATSAM_BSP_H */ diff --git a/rtemsbsd/sys/arm/at91/at91_mcireg.h b/rtemsbsd/sys/arm/at91/at91_mcireg.h new file mode 100644 index 00000000..80acf48d --- /dev/null +++ b/rtemsbsd/sys/arm/at91/at91_mcireg.h @@ -0,0 +1,183 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Berndt Walter. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. + * + * 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 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 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 ARM_AT91_AT91_MCIREG_H +#define ARM_AT91_AT91_MCIREG_H + +#define MMC_MAX 30 + +#define MCI_CR 0x00 /* MCI Control Register */ +#define MCI_MR 0x04 /* MCI Mode Register */ +#define MCI_DTOR 0x08 /* MCI Data Timeout Register */ +#define MCI_SDCR 0x0c /* MCI SD Card Register */ +#define MCI_ARGR 0x10 /* MCI Argument Register */ +#define MCI_CMDR 0x14 /* MCI Command Register */ +#ifdef __rtems__ +#define MCI_BLKR 0x18 /* MCI Block Register */ +#endif /* __rtems__ */ +#define MCI_RSPR 0x20 /* MCI Response Registers - 4 of them */ +#define MCI_RDR 0x30 /* MCI Receive Data Register */ +#define MCI_TDR 0x34 /* MCI Transmit Data Register */ +#define MCI_SR 0x40 /* MCI Status Register */ +#define MCI_IER 0x44 /* MCI Interrupt Enable Register */ +#define MCI_IDR 0x48 /* MCI Interrupt Disable Register */ +#define MCI_IMR 0x4c /* MCI Interrupt Mask Register */ +#ifdef __rtems__ +#define MCI_DMA 0x50 /* MCI DMA Control Register */ +#endif /* __rtems__ */ + +/* -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register -------- */ +#define MCI_CR_MCIEN (0x1u << 0) /* (MCI) Multimedia Interface Enable */ +#define MCI_CR_MCIDIS (0x1u << 1) /* (MCI) Multimedia Interface Disable */ +#define MCI_CR_PWSEN (0x1u << 2) /* (MCI) Power Save Mode Enable */ +#define MCI_CR_PWSDIS (0x1u << 3) /* (MCI) Power Save Mode Disable */ +#define MCI_CR_SWRST (0x1u << 7) /* (MCI) Software Reset */ +/* -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register -------- */ +#define MCI_MR_CLKDIV (0xffu << 0) /* (MCI) Clock Divider */ +#define MCI_MR_PWSDIV (0x3fu << 8) /* (MCI) Power Saving Divider */ +#define MCI_MR_RDPROOF (0x1u << 11) /* (MCI) Read Proof Enable */ +#define MCI_MR_WRPROOF (0x1u << 12) /* (MCI) Write Proof Enable */ +#define MCI_MR_PDCFBYTE (0x1u << 13) /* (MCI) PDC Force Byte Transfer */ +#define MCI_MR_PDCPADV (0x1u << 14) /* (MCI) PDC Padding Value */ +#define MCI_MR_PDCMODE (0x1u << 15) /* (MCI) PDC Oriented Mode */ +#define MCI_MR_CLKODD (0x1u << 16) /* (MCI) Clock Divider is Odd */ +#define MCI_MR_BLKLEN 0x3fff0000ul /* (MCI) Data Block Length */ +/* -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register -------- */ +#define MCI_DTOR_DTOCYC (0xfu << 0) /* (MCI) Data Timeout Cycle Number */ +#define MCI_DTOR_DTOMUL (0x7u << 4) /* (MCI) Data Timeout Multiplier */ +#define MCI_DTOR_DTOMUL_1 (0x0u << 4) /* (MCI) DTOCYC x 1 */ +#define MCI_DTOR_DTOMUL_16 (0x1u << 4) /* (MCI) DTOCYC x 16 */ +#define MCI_DTOR_DTOMUL_128 (0x2u << 4) /* (MCI) DTOCYC x 128 */ +#define MCI_DTOR_DTOMUL_256 (0x3u << 4) /* (MCI) DTOCYC x 256 */ +#define MCI_DTOR_DTOMUL_1k (0x4u << 4) /* (MCI) DTOCYC x 1024 */ +#define MCI_DTOR_DTOMUL_4k (0x5u << 4) /* (MCI) DTOCYC x 4096 */ +#define MCI_DTOR_DTOMUL_64k (0x6u << 4) /* (MCI) DTOCYC x 65536 */ +#define MCI_DTOR_DTOMUL_1M (0x7u << 4) /* (MCI) DTOCYC x 1048576 */ +/* -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register -------- */ +#define MCI_SDCR_SDCSEL (0x1u << 0) /* (MCI) SD Card Selector */ +#define MCI_SDCR_SDCBUS (0x1u << 7) /* (MCI) SD Card Bus Width */ +/* -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register -------- */ +#define MCI_CMDR_CMDNB (0x1Fu << 0) /* (MCI) Command Number */ +#define MCI_CMDR_RSPTYP (0x3u << 6) /* (MCI) Response Type */ +#define MCI_CMDR_RSPTYP_NO (0x0u << 6) /* (MCI) No response */ +#define MCI_CMDR_RSPTYP_48 (0x1u << 6) /* (MCI) 48-bit response */ +#define MCI_CMDR_RSPTYP_136 (0x2u << 6) /* (MCI) 136-bit response */ +#define MCI_CMDR_SPCMD (0x7u << 8) /* (MCI) Special CMD */ +#define MCI_CMDR_SPCMD_NONE (0x0u << 8) /* (MCI) Not a special CMD */ +#define MCI_CMDR_SPCMD_INIT (0x1u << 8) /* (MCI) Initialization CMD */ +#define MCI_CMDR_SPCMD_SYNC (0x2u << 8) /* (MCI) Synchronized CMD */ +#define MCI_CMDR_SPCMD_IT_CMD (0x4u << 8) /* (MCI) Interrupt command */ +#define MCI_CMDR_SPCMD_IT_REP (0x5u << 8) /* (MCI) Interrupt response */ +#define MCI_CMDR_OPDCMD (0x1u << 11) /* (MCI) Open Drain Command */ +#define MCI_CMDR_MAXLAT (0x1u << 12) /* (MCI) Maximum Latency for Command to respond */ +#define MCI_CMDR_TRCMD (0x3u << 16) /* (MCI) Transfer CMD */ +#define MCI_CMDR_TRCMD_NO (0x0u << 16) /* (MCI) No transfer */ +#define MCI_CMDR_TRCMD_START (0x1u << 16) /* (MCI) Start transfer */ +#define MCI_CMDR_TRCMD_STOP (0x2u << 16) /* (MCI) Stop transfer */ +#define MCI_CMDR_TRDIR (0x1u << 18) /* (MCI) Transfer Direction */ +#define MCI_CMDR_TRTYP (0x3u << 19) /* (MCI) Transfer Type */ +#define MCI_CMDR_TRTYP_BLOCK (0x0u << 19) /* (MCI) Block Transfer type */ +#define MCI_CMDR_TRTYP_MULTIPLE (0x1u << 19) /* (MCI) Multiple Block transfer type */ +#define MCI_CMDR_TRTYP_STREAM (0x2u << 19) /* (MCI) Stream transfer type */ +#ifdef __rtems__ +/* -------- MCI_BLKR : (MCI Offset: 0x18) MCI Block Register -------- */ +#define MCI_BLKR_BCNT (0xFFFFu << 0) +#define MCI_BLKR_BLKLEN (0xFFFFu << 16) +#endif /* __rtems__ */ +/* -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register -------- */ +#define MCI_SR_CMDRDY (0x1u << 0) /* (MCI) Command Ready flag */ +#define MCI_SR_RXRDY (0x1u << 1) /* (MCI) RX Ready flag */ +#define MCI_SR_TXRDY (0x1u << 2) /* (MCI) TX Ready flag */ +#define MCI_SR_BLKE (0x1u << 3) /* (MCI) Data Block Transfer Ended flag */ +#define MCI_SR_DTIP (0x1u << 4) /* (MCI) Data Transfer in Progress flag */ +#define MCI_SR_NOTBUSY (0x1u << 5) /* (MCI) Data Line Not Busy flag */ +#define MCI_SR_ENDRX (0x1u << 6) /* (MCI) End of RX Buffer flag */ +#define MCI_SR_ENDTX (0x1u << 7) /* (MCI) End of TX Buffer flag */ +#define MCI_SR_RXBUFF (0x1u << 14) /* (MCI) RX Buffer Full flag */ +#define MCI_SR_TXBUFE (0x1u << 15) /* (MCI) TX Buffer Empty flag */ +#define MCI_SR_RINDE (0x1u << 16) /* (MCI) Response Index Error flag */ +#define MCI_SR_RDIRE (0x1u << 17) /* (MCI) Response Direction Error flag */ +#define MCI_SR_RCRCE (0x1u << 18) /* (MCI) Response CRC Error flag */ +#define MCI_SR_RENDE (0x1u << 19) /* (MCI) Response End Bit Error flag */ +#define MCI_SR_RTOE (0x1u << 20) /* (MCI) Response Time-out Error flag */ +#define MCI_SR_DCRCE (0x1u << 21) /* (MCI) data CRC Error flag */ +#define MCI_SR_DTOE (0x1u << 22) /* (MCI) Data timeout Error flag */ +#define MCI_SR_OVRE (0x1u << 30) /* (MCI) Overrun flag */ +#define MCI_SR_UNRE (0x1u << 31) /* (MCI) Underrun flag */ +#ifdef __rtems__ +#define MCI_SR_XFRDONE (0x1u << 27) /* (MCI) Underrun flag */ +#endif /* __rtems__ */ +#ifdef __rtems__ +/* -------- MCI_DMA : (MCI Offset: 0x50) MCI DMA Control Register -------- */ +#define MCI_DMA_DMAEN (0x1u << 8) +#define MCI_DMA_CHKSIZE (0x7u << 4) +#define MCI_DMA_CHKSIZE_1 (0x0u << 4) +#define MCI_DMA_CHKSIZE_2 (0x1u << 4) +#define MCI_DMA_CHKSIZE_4 (0x2u << 4) +#define MCI_DMA_CHKSIZE_8 (0x3u << 4) +#define MCI_DMA_CHKSIZE_16 (0x4u << 4) +#endif /* __rtems__ */ + +/* TXRDY,DTIP,ENDTX,TXBUFE,RTOE */ + +#define MCI_SR_BITSTRING \ + "\020" \ + "\001CMDRDY" \ + "\002RXRDY" \ + "\003TXRDY" \ + "\004BLKE" \ + "\005DTIP" \ + "\006NOTBUSY" \ + "\007ENDRX" \ + "\010ENDTX" \ + "\017RXBUFF" \ + "\020TXBUFE" \ + "\021RINDE" \ + "\022RDIRE" \ + "\023RCRCE" \ + "\024RENDE" \ + "\025RTOE" \ + "\026DCRCE" \ + "\027DTOE" \ + "\037OVRE" \ + "\040UNRE" + +/* -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register -------- */ +/* -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register -------- */ +/* -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register -------- */ + +#define MCI_SR_ERROR (MCI_SR_UNRE | MCI_SR_OVRE | MCI_SR_DTOE | \ + MCI_SR_DCRCE | MCI_SR_RTOE | MCI_SR_RENDE | \ + MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE) + +#define AT91C_BUS_WIDTH_1BIT 0x00 +#define AT91C_BUS_WIDTH_4BITS 0x02 + +#endif /* ARM_AT91_AT91_MCIREG_H */ diff --git a/rtemsbsd/sys/arm/at91/at91_pdcreg.h b/rtemsbsd/sys/arm/at91/at91_pdcreg.h new file mode 100644 index 00000000..659804bd --- /dev/null +++ b/rtemsbsd/sys/arm/at91/at91_pdcreg.h @@ -0,0 +1,50 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 M. Warner Losh. + * + * 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 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 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 ARM_AT91_AT91_PDCREG_H +#define ARM_AT91_AT91_PDCREG_H + +#define PDC_RPR 0x100 /* PDC Receive Pointer Register */ +#define PDC_RCR 0x104 /* PDC Receive Counter Register */ +#define PDC_TPR 0x108 /* PDC Transmit Pointer Register */ +#define PDC_TCR 0x10c /* PDC Transmit Counter Register */ +#define PDC_RNPR 0x110 /* PDC Receive Next Pointer Register */ +#define PDC_RNCR 0x114 /* PDC Receive Next Counter Register */ +#define PDC_TNPR 0x118 /* PDC Transmit Next Pointer Reg */ +#define PDC_TNCR 0x11c /* PDC Transmit Next Counter Reg */ +#define PDC_PTCR 0x120 /* PDC Transfer Control Register */ +#define PDC_PTSR 0x124 /* PDC Transfer Status Register */ + +/* PTCR/PTSR */ +#define PDC_PTCR_RXTEN (1UL << 0) /* RXTEN: Receiver Transfer Enable */ +#define PDC_PTCR_RXTDIS (1UL << 1) /* RXTDIS: Receiver Transfer Disable */ +#define PDC_PTCR_TXTEN (1UL << 8) /* TXTEN: Transmitter Transfer En */ +#define PDC_PTCR_TXTDIS (1UL << 9) /* TXTDIS: Transmitter Transmit Dis */ + +#endif /* ARM_AT91_AT91_PDCREG_H */ diff --git a/rtemsbsd/sys/arm/at91/at91reg.h b/rtemsbsd/sys/arm/at91/at91reg.h new file mode 100644 index 00000000..f5791bd7 --- /dev/null +++ b/rtemsbsd/sys/arm/at91/at91reg.h @@ -0,0 +1,92 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2009 Greg Ansley 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 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 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 _AT91REG_H_ +#define _AT91REG_H_ + +#include + +/* Where builtin peripherals start in KVM */ +#define AT91_BASE 0xd0000000 + +/* Where builtin peripherals start PA */ +#define AT91_PA_BASE 0xf0000000 + +/* A few things that we count on being the same + * throughout the whole family of SOCs */ + +/* SYSC System Controller */ +/* System Registers */ +#define AT91_SYS_BASE 0xffff000 +#define AT91_SYS_SIZE 0x1000 + +#define AT91_DBGU0 0x0ffff200 /* Most */ +#define AT91_DBGU1 0x0fffee00 /* SAM9263, CAP9, and SAM9G45 */ + +#define AT91_DBGU_SIZE 0x200 +#define DBGU_C1R (64) /* Chip ID1 Register */ +#define DBGU_C2R (68) /* Chip ID2 Register */ +#define DBGU_FNTR (72) /* Force NTRST Register */ + +#define AT91_CPU_VERSION_MASK 0x0000001f +#define AT91_CPU_FAMILY_MASK 0x0ff00000 + +#define AT91_CPU_RM9200 0x09290780 +#define AT91_CPU_SAM9260 0x019803a0 +#define AT91_CPU_SAM9261 0x019703a0 +#define AT91_CPU_SAM9263 0x019607a0 +#define AT91_CPU_SAM9G10 0x819903a0 +#define AT91_CPU_SAM9G20 0x019905a0 +#define AT91_CPU_SAM9G45 0x819b05a0 +#define AT91_CPU_SAM9N12 0x819a07a0 +#define AT91_CPU_SAM9RL64 0x019b03a0 +#define AT91_CPU_SAM9X5 0x819a05a0 + +#define AT91_CPU_SAM9XE128 0x329973a0 +#define AT91_CPU_SAM9XE256 0x329a93a0 +#define AT91_CPU_SAM9XE512 0x329aa3a0 + +#define AT91_CPU_CAP9 0x039a03a0 + +#define AT91_EXID_SAM9M11 0x00000001 +#define AT91_EXID_SAM9M10 0x00000002 +#define AT91_EXID_SAM9G46 0x00000003 +#define AT91_EXID_SAM9G45 0x00000004 + +#define AT91_EXID_SAM9G15 0x00000000 +#define AT91_EXID_SAM9G35 0x00000001 +#define AT91_EXID_SAM9X35 0x00000002 +#define AT91_EXID_SAM9G25 0x00000003 +#define AT91_EXID_SAM9X25 0x00000004 + +#define AT91_IRQ_SYSTEM 1 + +#endif /* _AT91REG_H_ */ diff --git a/rtemsbsd/sys/arm/at91/at91var.h b/rtemsbsd/sys/arm/at91/at91var.h new file mode 100644 index 00000000..84c898fb --- /dev/null +++ b/rtemsbsd/sys/arm/at91/at91var.h @@ -0,0 +1,175 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2005 Olivier Houchard. 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 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 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 _AT91VAR_H_ +#define _AT91VAR_H_ + +#include +#include + +#include + +struct at91_softc { + device_t dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_sh; + bus_space_handle_t sc_aic_sh; + struct rman sc_irq_rman; + struct rman sc_mem_rman; +}; + +struct at91_ivar { + struct resource_list resources; +}; + +struct cpu_devs +{ + const char *name; + int unit; + bus_addr_t mem_base; + bus_size_t mem_len; + int irq0; + int irq1; + int irq2; + const char *parent_clk; +}; + +enum at91_soc_type { + AT91_T_NONE = 0, + AT91_T_CAP9, + AT91_T_RM9200, + AT91_T_SAM9260, + AT91_T_SAM9261, + AT91_T_SAM9263, + AT91_T_SAM9G10, + AT91_T_SAM9G20, + AT91_T_SAM9G45, + AT91_T_SAM9N12, + AT91_T_SAM9RL, + AT91_T_SAM9X5, +}; + +enum at91_soc_subtype { + AT91_ST_ANY = -1, /* Match any type */ + AT91_ST_NONE = 0, + /* AT91RM9200 */ + AT91_ST_RM9200_BGA, + AT91_ST_RM9200_PQFP, + /* AT91SAM9260 */ + AT91_ST_SAM9XE, + /* AT91SAM9G45 */ + AT91_ST_SAM9G45, + AT91_ST_SAM9M10, + AT91_ST_SAM9G46, + AT91_ST_SAM9M11, + /* AT91SAM9X5 */ + AT91_ST_SAM9G15, + AT91_ST_SAM9G25, + AT91_ST_SAM9G35, + AT91_ST_SAM9X25, + AT91_ST_SAM9X35, +}; + +enum at91_soc_family { + AT91_FAMILY_SAM9 = 0x19, + AT91_FAMILY_SAM9XE = 0x29, + AT91_FAMILY_RM92 = 0x92, +}; + +#define AT91_SOC_NAME_MAX 50 + +typedef void (*DELAY_t)(int); +typedef void (*cpu_reset_t)(void); +typedef void (*clk_init_t)(void); + +struct at91_soc_data { + DELAY_t soc_delay; /* SoC specific delay function */ + cpu_reset_t soc_reset; /* SoC specific reset function */ + clk_init_t soc_clock_init; /* SoC specific clock init function */ + const int *soc_irq_prio; /* SoC specific IRQ priorities */ + const struct cpu_devs *soc_children; /* SoC specific children list */ + const uint32_t *soc_pio_base; /* SoC specific PIO base registers */ + size_t soc_pio_count; /* Count of PIO units (not pins) in SoC */ +}; + +struct at91_soc_info { + enum at91_soc_type type; + enum at91_soc_subtype subtype; + enum at91_soc_family family; + uint32_t cidr; + uint32_t exid; + char name[AT91_SOC_NAME_MAX]; + uint32_t dbgu_base; + struct at91_soc_data *soc_data; +}; + +extern struct at91_soc_info soc_info; + +static inline int at91_is_rm92(void); +static inline int at91_is_sam9(void); +static inline int at91_is_sam9xe(void); +static inline int at91_cpu_is(u_int cpu); + +static inline int +at91_is_rm92(void) +{ + + return (soc_info.type == AT91_T_RM9200); +} + +static inline int +at91_is_sam9(void) +{ + + return (soc_info.family == AT91_FAMILY_SAM9); +} + +static inline int +at91_is_sam9xe(void) +{ + + return (soc_info.family == AT91_FAMILY_SAM9XE); +} + +static inline int +at91_cpu_is(u_int cpu) +{ + + return (soc_info.type == cpu); +} + +void at91_add_child(device_t dev, int prio, const char *name, int unit, + bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2); + +extern uint32_t at91_irq_system; +extern uint32_t at91_master_clock; +void at91_pmc_init_clock(void); +void at91_soc_id(void); + +#endif /* _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; -- cgit v1.2.3