summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.inc18
-rw-r--r--Makefile.libcompat9
-rw-r--r--ObsoleteFiles.inc3
-rwxr-xr-xbin/ls/tests/ls_tests.sh2
-rw-r--r--bin/ps/keyword.c2
-rw-r--r--bin/ps/print.c2
-rw-r--r--bin/sh/parser.c2
-rw-r--r--bin/sh/sh.16
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs.816
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool-features.793
-rw-r--r--cddl/usr.sbin/Makefile4
-rw-r--r--cddl/usr.sbin/zfsd/Makefile13
-rw-r--r--cddl/usr.sbin/zfsd/Makefile.common42
-rw-r--r--cddl/usr.sbin/zfsd/callout.cc219
-rw-r--r--cddl/usr.sbin/zfsd/callout.h185
-rw-r--r--cddl/usr.sbin/zfsd/case_file.cc1103
-rw-r--r--cddl/usr.sbin/zfsd/case_file.h426
-rw-r--r--cddl/usr.sbin/zfsd/tests/Makefile45
-rw-r--r--cddl/usr.sbin/zfsd/tests/libmocks.c58
-rw-r--r--cddl/usr.sbin/zfsd/tests/libmocks.h58
-rw-r--r--cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc771
-rw-r--r--cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp138
-rw-r--r--cddl/usr.sbin/zfsd/vdev.cc357
-rw-r--r--cddl/usr.sbin/zfsd/vdev.h178
-rw-r--r--cddl/usr.sbin/zfsd/vdev_iterator.cc153
-rw-r--r--cddl/usr.sbin/zfsd/vdev_iterator.h123
-rw-r--r--cddl/usr.sbin/zfsd/zfsd.8157
-rw-r--r--cddl/usr.sbin/zfsd/zfsd.cc448
-rw-r--r--cddl/usr.sbin/zfsd/zfsd.h228
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_event.cc535
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_event.h168
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_exception.cc134
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_exception.h109
-rw-r--r--cddl/usr.sbin/zfsd/zfsd_main.cc90
-rw-r--r--cddl/usr.sbin/zfsd/zpool_list.cc121
-rw-r--r--cddl/usr.sbin/zfsd/zpool_list.h133
-rw-r--r--contrib/binutils/include/libiberty.h2
-rw-r--r--contrib/blacklist/Makefile5
-rw-r--r--contrib/blacklist/Makefile.inc10
-rw-r--r--contrib/blacklist/README103
-rw-r--r--contrib/blacklist/TODO21
-rw-r--r--contrib/blacklist/bin/Makefile15
-rw-r--r--contrib/blacklist/bin/blacklistctl.881
-rw-r--r--contrib/blacklist/bin/blacklistctl.c151
-rw-r--r--contrib/blacklist/bin/blacklistd.8222
-rw-r--r--contrib/blacklist/bin/blacklistd.c537
-rw-r--r--contrib/blacklist/bin/blacklistd.conf.5222
-rw-r--r--contrib/blacklist/bin/conf.c1142
-rw-r--r--contrib/blacklist/bin/conf.h65
-rw-r--r--contrib/blacklist/bin/internal.c48
-rw-r--r--contrib/blacklist/bin/internal.h57
-rw-r--r--contrib/blacklist/bin/run.c156
-rw-r--r--contrib/blacklist/bin/run.h41
-rw-r--r--contrib/blacklist/bin/state.c233
-rw-r--r--contrib/blacklist/bin/state.h62
-rw-r--r--contrib/blacklist/bin/support.c157
-rw-r--r--contrib/blacklist/bin/support.h44
-rw-r--r--contrib/blacklist/diff/ftpd.diff91
-rw-r--r--contrib/blacklist/diff/named.diff216
-rw-r--r--contrib/blacklist/diff/proftpd.diff124
-rw-r--r--contrib/blacklist/diff/ssh.diff231
-rw-r--r--contrib/blacklist/etc/Makefile10
-rw-r--r--contrib/blacklist/etc/blacklistd.conf14
-rw-r--r--contrib/blacklist/etc/npf.conf15
-rw-r--r--contrib/blacklist/etc/rc.d/Makefile6
-rw-r--r--contrib/blacklist/etc/rc.d/blacklistd57
-rw-r--r--contrib/blacklist/include/Makefile10
-rw-r--r--contrib/blacklist/include/bl.h76
-rw-r--r--contrib/blacklist/include/blacklist.h46
-rw-r--r--contrib/blacklist/lib/Makefile19
-rw-r--r--contrib/blacklist/lib/bl.c524
-rw-r--r--contrib/blacklist/lib/blacklist.c88
-rw-r--r--contrib/blacklist/lib/libblacklist.3125
-rw-r--r--contrib/blacklist/lib/shlib_version2
-rw-r--r--contrib/blacklist/libexec/Makefile6
-rw-r--r--contrib/blacklist/libexec/blacklistd-helper82
-rw-r--r--contrib/blacklist/port/Makefile.am25
-rw-r--r--contrib/blacklist/port/_strtoi.h93
-rw-r--r--contrib/blacklist/port/clock_gettime.c17
-rw-r--r--contrib/blacklist/port/config.h3
-rw-r--r--contrib/blacklist/port/configure.ac91
-rw-r--r--contrib/blacklist/port/fgetln.c106
-rw-r--r--contrib/blacklist/port/fparseln.c236
-rw-r--r--contrib/blacklist/port/getprogname.c24
-rw-r--r--contrib/blacklist/port/m4/.cvsignore1
-rw-r--r--contrib/blacklist/port/pidfile.c183
-rw-r--r--contrib/blacklist/port/popenve.c274
-rw-r--r--contrib/blacklist/port/port.h86
-rw-r--r--contrib/blacklist/port/sockaddr_snprintf.c383
-rw-r--r--contrib/blacklist/port/strlcat.c96
-rw-r--r--contrib/blacklist/port/strlcpy.c78
-rw-r--r--contrib/blacklist/port/strtoi.c61
-rw-r--r--contrib/blacklist/test/Makefile12
-rw-r--r--contrib/blacklist/test/cltest.c136
-rw-r--r--contrib/blacklist/test/srvtest.c220
-rw-r--r--contrib/libxo/configure.ac2
-rw-r--r--contrib/libxo/doc/libxo-manual.html12
-rw-r--r--contrib/libxo/doc/libxo.txt10
-rw-r--r--contrib/libxo/libxo/libxo.c30
-rw-r--r--contrib/libxo/libxo/xo_buf.h4
-rw-r--r--contrib/libxo/libxo/xo_encoder.c2
-rw-r--r--contrib/libxo/libxo/xo_format.56
-rw-r--r--contrib/libxo/libxo/xo_syslog.c2
-rw-r--r--contrib/libxo/tests/core/saved/test_03.E.out12
-rw-r--r--contrib/libxo/tests/core/saved/test_03.H.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_03.HIPx.out34
-rw-r--r--contrib/libxo/tests/core/saved/test_03.HP.out34
-rw-r--r--contrib/libxo/tests/core/saved/test_03.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_03.JP.out12
-rw-r--r--contrib/libxo/tests/core/saved/test_03.T.out4
-rw-r--r--contrib/libxo/tests/core/saved/test_03.X.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_03.XP.out8
-rw-r--r--contrib/libxo/tests/core/test_03.c59
-rw-r--r--contrib/llvm/lib/Target/X86/X86ISelLowering.cpp2
-rw-r--r--contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp4
-rw-r--r--etc/Makefile4
-rw-r--r--etc/blacklistd.conf17
-rw-r--r--etc/defaults/rc.conf6
-rw-r--r--etc/mtree/BSD.include.dist2
-rw-r--r--etc/mtree/BSD.tests.dist4
-rw-r--r--etc/mtree/BSD.var.dist4
-rwxr-xr-xetc/periodic/daily/480.leapfile-ntpd4
-rwxr-xr-xetc/periodic/security/520.pfdenied10
-rw-r--r--etc/rc.d/Makefile8
-rw-r--r--etc/rc.d/blacklistd45
-rwxr-xr-xetc/rc.d/dhclient2
-rwxr-xr-xetc/rc.d/ldconfig2
-rwxr-xr-xetc/rc.d/mountcritremote16
-rwxr-xr-xetc/rc.d/netif2
-rwxr-xr-xetc/rc.d/random4
-rwxr-xr-xetc/rc.d/routing5
-rw-r--r--etc/rc.d/zfsd17
-rw-r--r--include/dirent.h10
-rw-r--r--include/libgen.h12
-rw-r--r--include/monetary.h2
-rw-r--r--include/ndbm.h4
-rw-r--r--include/netdb.h12
-rw-r--r--include/signal.h2
-rw-r--r--include/wchar.h7
-rw-r--r--lib/Makefile7
-rw-r--r--lib/clang/include/clang/Basic/Version.inc2
-rw-r--r--lib/libblacklist/Makefile30
-rw-r--r--lib/libc++/Makefile4
-rw-r--r--lib/libc/db/hash/ndbm.c2
-rw-r--r--lib/libc/db/man/dbm.36
-rw-r--r--lib/libc/gen/psignal.34
-rw-r--r--lib/libc/gen/psignal.c4
-rw-r--r--lib/libc/iconv/citrus_esdb.c18
-rw-r--r--lib/libc/locale/ascii.c2
-rw-r--r--lib/libc/locale/none.c1
-rw-r--r--lib/libc/stdlib/div.c2
-rw-r--r--lib/libc/stdlib/imaxdiv.c2
-rw-r--r--lib/libc/stdlib/ldiv.c2
-rw-r--r--lib/libc/stdlib/lldiv.c2
-rw-r--r--lib/libc/stdlib/rand.c52
-rw-r--r--lib/libc/stdlib/random.c62
-rw-r--r--lib/libc/sys/_umtx_op.295
-rw-r--r--lib/libc/sys/jail.22
-rw-r--r--lib/libc/sys/thr_exit.226
-rw-r--r--lib/libc/sys/thr_kill.210
-rw-r--r--lib/libc/sys/thr_new.238
-rw-r--r--lib/libc/sys/thr_self.210
-rw-r--r--lib/libc/sys/thr_set_name.27
-rw-r--r--lib/libc/sys/wait.210
-rw-r--r--lib/libcasper/services/cap_grp/cap_grp.c4
-rw-r--r--lib/libcrypt/Makefile2
-rw-r--r--lib/libcxxrt/Makefile2
-rw-r--r--lib/libdevdctl/Makefile21
-rw-r--r--lib/libdevdctl/consumer.cc258
-rw-r--r--lib/libdevdctl/consumer.h174
-rw-r--r--lib/libdevdctl/event.cc602
-rw-r--r--lib/libdevdctl/event.h423
-rw-r--r--lib/libdevdctl/event_factory.cc99
-rw-r--r--lib/libdevdctl/event_factory.h94
-rw-r--r--lib/libdevdctl/exception.cc125
-rw-r--r--lib/libdevdctl/exception.h168
-rw-r--r--lib/libdevdctl/guid.cc82
-rw-r--r--lib/libdevdctl/guid.h143
-rw-r--r--lib/libdevdctl/tests/Makefile21
-rw-r--r--lib/libdevdctl/tests/libdevdctl_unittest.cc138
-rw-r--r--lib/libfetch/http.c3
-rw-r--r--lib/libmd/Makefile138
-rw-r--r--lib/libmd/mdX.38
-rw-r--r--lib/libmd/ripemd.37
-rw-r--r--lib/libmd/sha.36
-rw-r--r--lib/libmd/sha256.37
-rw-r--r--lib/libmd/sha512.350
-rw-r--r--lib/libmd/shadriver.c4
-rw-r--r--lib/libmd/skein.3214
-rw-r--r--lib/libmd/skeindriver.c68
-rw-r--r--lib/libthr/libthr.34
-rw-r--r--lib/libthr/thread/thr_cond.c24
-rw-r--r--lib/libthr/thread/thr_exit.c31
-rw-r--r--lib/libthr/thread/thr_mutex.c23
-rw-r--r--lib/libthr/thread/thr_printf.c25
-rw-r--r--lib/libthr/thread/thr_private.h11
-rw-r--r--lib/libxo/add.man4
-rw-r--r--lib/libxo/xo_config.h12
-rw-r--r--libexec/Makefile5
-rw-r--r--libexec/blacklistd-helper/Makefile7
-rw-r--r--release/doc/en_US.ISO8859-1/relnotes/article.xml42
-rw-r--r--release/tools/arm.subr1
-rw-r--r--sbin/ifconfig/af_inet.c37
-rw-r--r--sbin/ifconfig/af_inet6.c28
-rw-r--r--sbin/ifconfig/af_link.c17
-rw-r--r--sbin/ifconfig/ifconfig.898
-rw-r--r--sbin/ifconfig/ifconfig.c66
-rw-r--r--sbin/ipfw/ipfw.82
-rw-r--r--sbin/md5/Makefile12
-rw-r--r--sbin/md5/md5.124
-rw-r--r--sbin/md5/md5.c75
-rw-r--r--sbin/swapon/swapon.c14
-rw-r--r--share/man/man3/pthread_attr_get_np.32
-rw-r--r--share/man/man3/pthread_barrier_destroy.34
-rw-r--r--share/man/man3/pthread_barrierattr.319
-rw-r--r--share/man/man3/pthread_condattr.314
-rw-r--r--share/man/man3/pthread_resume_np.32
-rw-r--r--share/man/man3/pthread_rwlock_init.34
-rw-r--r--share/man/man3/pthread_rwlockattr_setpshared.38
-rw-r--r--share/man/man3/pthread_spin_init.319
-rw-r--r--share/man/man3/pthread_suspend_np.32
-rw-r--r--share/man/man9/domain.93
-rw-r--r--share/man/man9/memguard.916
-rw-r--r--share/misc/committers-src.dot2
-rw-r--r--share/misc/organization.dot4
-rw-r--r--share/mk/bsd.dep.mk16
-rw-r--r--share/mk/bsd.info.mk14
-rw-r--r--share/mk/bsd.kmod.mk2
-rw-r--r--share/mk/bsd.lib.mk42
-rw-r--r--share/mk/bsd.libnames.mk2
-rw-r--r--share/mk/bsd.man.mk8
-rw-r--r--share/mk/bsd.nls.mk2
-rw-r--r--share/mk/bsd.prog.mk8
-rw-r--r--share/mk/bsd.subdir.mk3
-rw-r--r--share/mk/bsd.sys.mk26
-rw-r--r--share/mk/src.libnames.mk14
-rw-r--r--share/mk/src.opts.mk2
-rw-r--r--share/mk/sys.mk50
-rw-r--r--share/timedef/am_ET.UTF-8.src4
-rw-r--r--share/timedef/be_BY.CP1131.src4
-rw-r--r--share/timedef/be_BY.CP1251.src4
-rw-r--r--share/timedef/be_BY.ISO8859-5.src4
-rw-r--r--share/timedef/be_BY.UTF-8.src4
-rw-r--r--share/timedef/bg_BG.CP1251.src4
-rw-r--r--share/timedef/bg_BG.UTF-8.src4
-rw-r--r--share/timedef/ca_IT.ISO8859-15.src4
-rw-r--r--share/timedef/ca_IT.UTF-8.src4
-rw-r--r--share/timedef/el_GR.ISO8859-7.src4
-rw-r--r--share/timedef/el_GR.UTF-8.src4
-rw-r--r--share/timedef/en_CA.UTF-8.src4
-rw-r--r--share/timedef/en_GB.UTF-8.src4
-rw-r--r--share/timedef/en_HK.UTF-8.src4
-rw-r--r--share/timedef/en_IE.UTF-8.src4
-rw-r--r--share/timedef/en_PH.UTF-8.src4
-rw-r--r--share/timedef/en_SG.UTF-8.src4
-rw-r--r--share/timedef/en_US.UTF-8.src4
-rw-r--r--share/timedef/fr_BE.ISO8859-15.src4
-rw-r--r--share/timedef/fr_BE.UTF-8.src4
-rw-r--r--share/timedef/fr_CA.ISO8859-15.src4
-rw-r--r--share/timedef/fr_CA.UTF-8.src4
-rw-r--r--share/timedef/fr_CH.ISO8859-15.src4
-rw-r--r--share/timedef/fr_CH.UTF-8.src4
-rw-r--r--share/timedef/fr_FR.ISO8859-15.src4
-rw-r--r--share/timedef/fr_FR.UTF-8.src4
-rw-r--r--share/timedef/hi_IN.ISCII-DEV.src4
-rw-r--r--share/timedef/hi_IN.UTF-8.src4
-rw-r--r--share/timedef/hy_AM.ARMSCII-8.src4
-rw-r--r--share/timedef/hy_AM.UTF-8.src4
-rw-r--r--share/timedef/it_CH.ISO8859-15.src4
-rw-r--r--share/timedef/it_CH.UTF-8.src4
-rw-r--r--share/timedef/it_IT.ISO8859-15.src4
-rw-r--r--share/timedef/it_IT.UTF-8.src4
-rw-r--r--share/timedef/kk_Cyrl_KZ.UTF-8.src4
-rw-r--r--share/timedef/nl_BE.UTF-8.src4
-rw-r--r--share/timedef/nl_NL.UTF-8.src4
-rw-r--r--share/timedef/pl_PL.ISO8859-2.src4
-rw-r--r--share/timedef/pl_PL.UTF-8.src4
-rw-r--r--share/timedef/ro_RO.ISO8859-2.src4
-rw-r--r--share/timedef/ro_RO.UTF-8.src4
-rw-r--r--share/timedef/ru_RU.CP1251.src8
-rw-r--r--share/timedef/ru_RU.CP866.src8
-rw-r--r--share/timedef/ru_RU.ISO8859-5.src8
-rw-r--r--share/timedef/ru_RU.KOI8-R.src8
-rw-r--r--share/timedef/ru_RU.UTF-8.src8
-rw-r--r--share/timedef/sv_FI.ISO8859-15.src4
-rw-r--r--share/timedef/sv_FI.UTF-8.src4
-rw-r--r--share/timedef/sv_SE.ISO8859-15.src4
-rw-r--r--share/timedef/sv_SE.UTF-8.src4
-rw-r--r--share/timedef/tr_TR.ISO8859-9.src4
-rw-r--r--share/timedef/tr_TR.UTF-8.src4
-rw-r--r--share/timedef/uk_UA.CP1251.src4
-rw-r--r--share/timedef/uk_UA.ISO8859-5.src4
-rw-r--r--share/timedef/uk_UA.KOI8-U.src4
-rw-r--r--share/timedef/uk_UA.UTF-8.src4
-rw-r--r--sys/arm/allwinner/aw_ccu.c2
-rw-r--r--sys/arm/arm/debug_monitor.c200
-rw-r--r--sys/arm/arm/gic.c9
-rw-r--r--sys/arm/arm/mp_machdep.c8
-rw-r--r--sys/arm/conf/ARMADA38X5
-rw-r--r--sys/arm/include/debug_monitor.h6
-rw-r--r--sys/arm/mv/mv_common.c31
-rw-r--r--sys/arm/mv/mv_machdep.c2
-rw-r--r--sys/arm/mv/mvwin.h13
-rw-r--r--sys/arm64/arm64/busdma_bounce.c2
-rw-r--r--sys/arm64/arm64/gic_v3_fdt.c4
-rw-r--r--sys/arm64/arm64/mp_machdep.c59
-rw-r--r--sys/arm64/cavium/thunder_pcie_fdt.c1
-rw-r--r--sys/arm64/cavium/thunder_pcie_pem.c27
-rw-r--r--sys/arm64/cavium/thunder_pcie_pem.h1
-rw-r--r--sys/boot/fdt/dts/arm/armada-388-gp.dts9
-rw-r--r--sys/boot/fdt/dts/arm/armada-38x.dtsi31
-rw-r--r--sys/boot/fdt/dts/arm/db78100.dts3
-rw-r--r--sys/boot/fdt/dts/arm/db88f6281.dts3
-rw-r--r--sys/boot/fdt/dts/arm/dockstar.dts3
-rw-r--r--sys/boot/fdt/dts/arm/dreamplug-1001.dts3
-rw-r--r--sys/boot/fdt/dts/arm/dreamplug-1001N.dts3
-rw-r--r--sys/boot/fdt/dts/arm/sheevaplug.dts3
-rw-r--r--sys/boot/geli/geliboot_crypto.c4
-rw-r--r--sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c4
-rw-r--r--sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h2
-rw-r--r--sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/Makefile.files1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c12
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c23
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/acl.h4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/sysevent.h4
-rw-r--r--sys/cddl/dev/dtrace/aarch64/dtrace_isa.c4
-rw-r--r--sys/compat/linux/linux_ioctl.c2
-rw-r--r--sys/compat/linux/linux_misc.c1
-rw-r--r--sys/conf/dtb.mk4
-rw-r--r--sys/conf/files8
-rw-r--r--sys/conf/files.amd648
-rw-r--r--sys/conf/files.arm642
-rw-r--r--sys/conf/files.i3868
-rw-r--r--sys/conf/kern.post.mk42
-rw-r--r--sys/conf/kern.pre.mk1
-rw-r--r--sys/conf/kmod.mk64
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c10
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c32
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c11
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h357
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c2
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c151
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c6
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c37
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c1
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h29
-rw-r--r--sys/crypto/sha2/sha256c.c174
-rw-r--r--sys/crypto/sha2/sha512c.c312
-rw-r--r--sys/crypto/sha2/sha512t.h125
-rw-r--r--sys/crypto/skein/amd64/skein_block_asm.s1328
-rw-r--r--sys/crypto/skein/skein.c858
-rw-r--r--sys/crypto/skein/skein.h333
-rw-r--r--sys/crypto/skein/skein_block.c706
-rw-r--r--sys/crypto/skein/skein_debug.c247
-rw-r--r--sys/crypto/skein/skein_debug.h48
-rw-r--r--sys/crypto/skein/skein_freebsd.h79
-rw-r--r--sys/crypto/skein/skein_iv.h200
-rw-r--r--sys/crypto/skein/skein_port.h158
-rw-r--r--sys/dev/ath/ath_hal/ah.h134
-rw-r--r--sys/dev/ath/ath_hal/ah_btcoex.h524
-rw-r--r--sys/dev/ath/ath_hal/ah_desc.h3
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c6
-rw-r--r--sys/dev/ath/if_ath.c14
-rw-r--r--sys/dev/ath/if_ath_btcoex.c92
-rw-r--r--sys/dev/ath/if_ath_btcoex.h4
-rw-r--r--sys/dev/ath/if_ath_btcoex_mci.c655
-rw-r--r--sys/dev/ath/if_ath_btcoex_mci.h42
-rw-r--r--sys/dev/ath/if_ath_debug.h5
-rw-r--r--sys/dev/ath/if_ath_tx.c9
-rw-r--r--sys/dev/ath/if_athvar.h29
-rw-r--r--sys/dev/bge/if_bge.c6
-rw-r--r--sys/dev/bge/if_bgereg.h2
-rw-r--r--sys/dev/cesa/cesa.c181
-rw-r--r--sys/dev/cesa/cesa.h65
-rw-r--r--sys/dev/cxgbe/cxgbei/icl_cxgbei.c2
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/cm.c12
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/ev.c11
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c6
-rw-r--r--sys/dev/filemon/filemon.c17
-rw-r--r--sys/dev/filemon/filemon_wrapper.c23
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c8
-rw-r--r--sys/dev/hyperv/include/hyperv.h6
-rw-r--r--sys/dev/hyperv/utilities/hv_kvp.c15
-rw-r--r--sys/dev/hyperv/vmbus/amd64/vmbus_vector.S (renamed from sys/dev/hyperv/vmbus/amd64/hv_vector.S)4
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c15
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c30
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h93
-rw-r--r--sys/dev/hyperv/vmbus/hyperv.c (renamed from sys/dev/hyperv/vmbus/hv_hv.c)16
-rw-r--r--sys/dev/hyperv/vmbus/hyperv_var.h6
-rw-r--r--sys/dev/hyperv/vmbus/i386/vmbus_vector.S (renamed from sys/dev/hyperv/vmbus/i386/hv_vector.S)24
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c (renamed from sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c)170
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_et.c (renamed from sys/dev/hyperv/vmbus/hv_et.c)141
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_reg.h82
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h25
-rw-r--r--sys/dev/ichiic/ig4_iic.c22
-rw-r--r--sys/dev/iscsi/iscsi.c26
-rw-r--r--sys/dev/iscsi/iscsi_ioctl.h3
-rw-r--r--sys/dev/iwm/if_iwm.c76
-rw-r--r--sys/dev/iwm/if_iwm_led.c182
-rw-r--r--sys/dev/iwm/if_iwm_led.h101
-rw-r--r--sys/dev/iwm/if_iwm_pcie_trans.c4
-rw-r--r--sys/dev/iwm/if_iwm_phy_db.h35
-rw-r--r--sys/dev/iwm/if_iwm_power.c24
-rw-r--r--sys/dev/iwm/if_iwm_scan.c1
-rw-r--r--sys/dev/iwm/if_iwm_util.c7
-rw-r--r--sys/dev/iwm/if_iwmreg.h51
-rw-r--r--sys/dev/iwm/if_iwmvar.h1
-rw-r--r--sys/dev/ixl/i40e_prototype.h2
-rw-r--r--sys/dev/mrsas/mrsas.c18
-rw-r--r--sys/dev/mrsas/mrsas.h2
-rw-r--r--sys/dev/mrsas/mrsas_cam.c24
-rw-r--r--sys/dev/mrsas/mrsas_fp.c12
-rw-r--r--sys/dev/pci/pci_host_generic.c35
-rw-r--r--sys/dev/pci/pci_host_generic.h2
-rw-r--r--sys/dev/sfxge/common/ef10_ev.c40
-rw-r--r--sys/dev/sfxge/common/ef10_impl.h1
-rw-r--r--sys/dev/sfxge/common/efx.h1
-rw-r--r--sys/dev/sfxge/common/efx_ev.c9
-rw-r--r--sys/dev/sfxge/common/efx_impl.h2
-rw-r--r--sys/dev/sfxge/common/efx_lic.c13
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.c1
-rw-r--r--sys/dev/sfxge/common/efx_regs_mcdi.h554
-rw-r--r--sys/dev/sfxge/sfxge.h37
-rw-r--r--sys/dev/sfxge/sfxge_ev.c34
-rw-r--r--sys/dev/sfxge/sfxge_rx.c3
-rw-r--r--sys/dev/sfxge/sfxge_rx.h18
-rw-r--r--sys/dev/sound/usb/uaudio.c22
-rw-r--r--sys/dev/sym/sym_hipd.c2
-rw-r--r--sys/dev/urtwn/if_urtwn.c27
-rw-r--r--sys/dev/usb/net/uhso.c4
-rw-r--r--sys/dev/usb/wlan/if_urtw.c4
-rw-r--r--sys/dev/xen/netfront/netfront.c375
-rw-r--r--sys/geom/mirror/g_mirror.c3
-rw-r--r--sys/kern/kern_jail.c34
-rw-r--r--sys/kern/kern_lock.c12
-rw-r--r--sys/kern/kern_mutex.c13
-rw-r--r--sys/kern/kern_rwlock.c4
-rw-r--r--sys/kern/kern_shutdown.c4
-rw-r--r--sys/kern/kern_sx.c5
-rw-r--r--sys/kern/subr_taskqueue.c10
-rw-r--r--sys/kern/uipc_domain.c4
-rw-r--r--sys/kern/vfs_subr.c2
-rw-r--r--sys/kern/vfs_syscalls.c1
-rw-r--r--sys/modules/Makefile8
-rw-r--r--sys/modules/ath/Makefile2
-rw-r--r--sys/modules/crypto/Makefile8
-rw-r--r--sys/modules/dummynet/Makefile4
-rw-r--r--sys/modules/gpio/Makefile2
-rw-r--r--sys/modules/hyperv/vmbus/Makefile13
-rw-r--r--sys/modules/iwm/Makefile2
-rw-r--r--sys/modules/zfs/Makefile3
-rw-r--r--sys/net/flowtable.c9
-rw-r--r--sys/net/if.c3
-rw-r--r--sys/net/if_arcsubr.c6
-rw-r--r--sys/net/if_ethersubr.c47
-rw-r--r--sys/net/if_fddisubr.c4
-rw-r--r--sys/net/if_fwsubr.c5
-rw-r--r--sys/net/if_iso88025subr.c4
-rw-r--r--sys/net/if_llatbl.h1
-rw-r--r--sys/net/route.c2
-rw-r--r--sys/net/route.h15
-rw-r--r--sys/net80211/ieee80211_input.c19
-rw-r--r--sys/net80211/ieee80211_output.c12
-rw-r--r--sys/netinet/if_ether.c20
-rw-r--r--sys/netinet/if_ether.h7
-rw-r--r--sys/netinet/in_pcb.c5
-rw-r--r--sys/netinet/in_proto.c20
-rw-r--r--sys/netinet/ip_divert.c19
-rw-r--r--sys/netinet/ip_input.c6
-rw-r--r--sys/netinet/ip_output.c6
-rw-r--r--sys/netinet/ip_var.h6
-rw-r--r--sys/netinet/raw_ip.c5
-rw-r--r--sys/netinet/sctp_output.c2
-rw-r--r--sys/netinet/sctp_usrreq.c9
-rw-r--r--sys/netinet/sctp_var.h1
-rw-r--r--sys/netinet/tcp_output.c14
-rw-r--r--sys/netinet/tcp_subr.c5
-rw-r--r--sys/netinet/tcp_var.h3
-rw-r--r--sys/netinet/toecore.c4
-rw-r--r--sys/netinet/udp_usrreq.c11
-rw-r--r--sys/netinet/udp_var.h4
-rw-r--r--sys/netinet6/in6.h5
-rw-r--r--sys/netinet6/in6_pcb.c5
-rw-r--r--sys/netinet6/in6_proto.c5
-rw-r--r--sys/netinet6/ip6_input.c6
-rw-r--r--sys/netinet6/ip6_output.c3
-rw-r--r--sys/netinet6/ip6_var.h3
-rw-r--r--sys/netinet6/nd6.c16
-rw-r--r--sys/netinet6/nd6.h2
-rw-r--r--sys/netinet6/nd6_nbr.c8
-rw-r--r--sys/netinet6/nd6_rtr.c11
-rw-r--r--sys/netpfil/ipfw/dn_aqm_pie.c26
-rw-r--r--sys/netpfil/ipfw/dn_aqm_pie.h6
-rw-r--r--sys/netpfil/ipfw/dn_sched_fq_pie.c26
-rw-r--r--sys/ofed/drivers/infiniband/core/addr.c4
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c4
-rw-r--r--sys/riscv/conf/GENERIC13
-rw-r--r--sys/riscv/riscv/elf_machdep.c367
-rw-r--r--sys/sys/aio.h3
-rw-r--r--sys/sys/cdefs.h3
-rw-r--r--sys/sys/elf_common.h10
-rw-r--r--sys/sys/kernel.h5
-rw-r--r--sys/sys/mbuf.h39
-rw-r--r--sys/sys/mutex.h6
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/protosw.h2
-rw-r--r--sys/sys/resource.h17
-rw-r--r--sys/sys/rwlock.h4
-rw-r--r--sys/sys/sched.h3
-rw-r--r--sys/sys/shm.h2
-rw-r--r--sys/sys/signal.h23
-rw-r--r--sys/sys/socket.h4
-rw-r--r--sys/sys/sx.h6
-rw-r--r--sys/sys/taskqueue.h16
-rw-r--r--sys/vm/uma_core.c10
-rw-r--r--sys/vm/uma_dbg.c29
-rw-r--r--sys/vm/vm_object.c1
-rw-r--r--sys/vm/vm_page.c45
-rw-r--r--sys/x86/include/_align.h4
-rw-r--r--sys/x86/include/_stdint.h6
-rw-r--r--sys/x86/include/_types.h2
-rw-r--r--sys/x86/include/apicvar.h1
-rw-r--r--sys/xen/error.h206
-rw-r--r--sys/xen/gnttab.h1
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc399
-rwxr-xr-xtools/tools/locale/tools/cldr2def.pl40
-rw-r--r--usr.bin/iscsictl/iscsi.conf.58
-rw-r--r--usr.bin/iscsictl/iscsictl.813
-rw-r--r--usr.bin/iscsictl/iscsictl.c107
-rw-r--r--usr.bin/iscsictl/iscsictl.h6
-rw-r--r--usr.bin/iscsictl/parse.y15
-rw-r--r--usr.bin/iscsictl/token.l1
-rw-r--r--usr.bin/mkimg/image.c3
-rw-r--r--usr.bin/sed/process.c11
-rw-r--r--usr.bin/sockstat/sockstat.c4
-rw-r--r--usr.bin/xlint/llib/Makefile11
-rw-r--r--usr.sbin/Makefile4
-rw-r--r--usr.sbin/blacklistctl/Makefile22
-rw-r--r--usr.sbin/blacklistd/Makefile22
-rw-r--r--usr.sbin/ctld/ctl.conf.52
-rw-r--r--usr.sbin/keyserv/crypt_server.c9
-rw-r--r--usr.sbin/rpc.statd/statd.c8
-rw-r--r--usr.sbin/rpcbind/check_bound.c3
-rw-r--r--usr.sbin/rpcbind/rpcbind.c14
-rw-r--r--usr.sbin/rpcbind/util.c14
-rw-r--r--usr.sbin/services_mkdb/services_mkdb.c5
-rw-r--r--usr.sbin/tzsetup/tzsetup.c5
552 files changed, 27281 insertions, 3094 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index e5e29e7..2503da3 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -527,7 +527,13 @@ TARGET_ABI= gnueabihf
TARGET_ABI= gnueabi
.endif
.endif
-.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == "clang"
+.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc
+# GCC requires -isystem and -L when using a cross-compiler.
+XCFLAGS+= -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
+# Force using libc++ for external GCC.
+XCXXFLAGS+= -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
+ -nostdinc++ -L${WORLDTMP}/../lib/libc++
+.else
TARGET_ABI?= unknown
TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd11.0
XCFLAGS+= -target ${TARGET_TRIPLE}
diff --git a/Makefile.libcompat b/Makefile.libcompat
index 08d684c..f7911c3 100644
--- a/Makefile.libcompat
+++ b/Makefile.libcompat
@@ -72,6 +72,13 @@ LIBCOMPATCFLAGS+= ${LIBCOMPATCPUFLAGS} \
# -B is needed to find /usr/lib32/crti.o for GCC and /usr/libsoft/crti.o for
# Clang/GCC.
LIBCOMPATCFLAGS+= -B${LIBCOMPATTMP}/usr/lib${libcompat}
+.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc
+# GCC requires -isystem when using a cross-compiler.
+LIBCOMPATCFLAGS+= -isystem ${LIBCOMPATTMP}/usr/include
+# Force using libc++ for external GCC.
+LIBCOMPATCXXFLAGS+= -isystem ${LIBCOMPATTMP}/usr/include/c++/v1 -std=c++11 \
+ -nostdinc++ -L${LIBCOMPAT_OBJTREE}${.CURDIR}/lib/libc++
+.endif
# Yes, the flags are redundant.
LIBCOMPATWMAKEENV+= MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} \
@@ -85,7 +92,7 @@ LIBCOMPATWMAKEENV+= MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} \
LIBCOMPATWMAKEENV+= BUILD_TOOLS_META=.NOMETA_CMP
.endif
LIBCOMPATWMAKEFLAGS+= CC="${XCC} ${LIBCOMPATCFLAGS}" \
- CXX="${XCXX} ${LIBCOMPATCFLAGS} ${LIBCOMPATCXXFLAGS}" \
+ CXX="${XCXX} ${LIBCOMPATCXXFLAGS} ${LIBCOMPATCFLAGS}" \
CPP="${XCPP} ${LIBCOMPATCFLAGS}" \
DESTDIR=${LIBCOMPATTMP} \
-DNO_CPU_CFLAGS \
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 873ef5e..ca7a40f 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,9 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20160523: remove extranous ALTQ files
+OLD_FILES+=usr/include/altq/altq_codel.h
+OLD_FILES+=usr/include/altq/altq_fairq.h
# 20160519: remove DTrace Toolkit from base
OLD_FILES+=usr/share/dtrace/toolkit/execsnoop
OLD_FILES+=usr/share/dtrace/toolkit/hotkernel
diff --git a/bin/ls/tests/ls_tests.sh b/bin/ls/tests/ls_tests.sh
index 3317876..2291bab 100755
--- a/bin/ls/tests/ls_tests.sh
+++ b/bin/ls/tests/ls_tests.sh
@@ -535,7 +535,7 @@ atf_test_case h_flag
h_flag_head()
{
atf_set "descr" "Verify that -h prints out the humanized units for file sizes with ls -l"
- atf_set "require.files" "/usr/bin/bc"
+ atf_set "require.progs" "bc"
}
h_flag_body()
diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c
index b802c37..2482490 100644
--- a/bin/ps/keyword.c
+++ b/bin/ps/keyword.c
@@ -95,7 +95,7 @@ static VAR var[] = {
{"etimes", "ELAPSED", NULL, "elapsed-times", USER, elapseds, 0, CHAR,
NULL, 0},
{"euid", "", "uid", NULL, 0, NULL, 0, CHAR, NULL, 0},
- {"f", "F", NULL, "flags", 0, kvar, KOFF(ki_flag), INT, "x", 0},
+ {"f", "F", NULL, "flags", 0, kvar, KOFF(ki_flag), LONG, "lx", 0},
{"f2", "F2", NULL, "flags2", 0, kvar, KOFF(ki_flag2), INT, "08x", 0},
{"fib", "FIB", NULL, "fib", 0, kvar, KOFF(ki_fibnum), INT, "d", 0},
{"flags", "", "f", NULL, 0, NULL, 0, CHAR, NULL, 0},
diff --git a/bin/ps/print.c b/bin/ps/print.c
index 91daa44..1cbcf62 100644
--- a/bin/ps/print.c
+++ b/bin/ps/print.c
@@ -211,7 +211,7 @@ logname(KINFO *k, VARENT *ve __unused)
char *
state(KINFO *k, VARENT *ve __unused)
{
- int flag, tdflags;
+ long flag, tdflags;
char *cp, *buf;
buf = malloc(16);
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index cc04a2a..1297748 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -2063,7 +2063,7 @@ getprompt(void *unused __unused)
*/
default:
ps[i] = '\\';
- if (i < PROMPTLEN - 1)
+ if (i < PROMPTLEN - 2)
ps[++i] = *fmt;
break;
}
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 1f3431c..20a9dbf 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd May 24, 2016
+.Dd May 30, 2016
.Dt SH 1
.Os
.Sh NAME
@@ -1403,9 +1403,9 @@ may include any of the following formatting sequences,
which are replaced by the given information:
.Bl -tag -width indent
.It Li \eH
-The fully-qualified hostname.
+This system's fully-qualified hostname (FQDN).
.It Li \eh
-The local hostname.
+This system's hostname.
.It Li \eW
The final component of the current working directory.
.It Li \ew
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8
index dedfc0a..2b74120 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8
@@ -31,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 24, 2015
+.Dd May 31, 2016
.Dt ZFS 8
.Os
.Sh NAME
@@ -940,7 +940,7 @@ command or unmounted by the
command.
.Pp
This property is not inherited.
-.It Sy checksum Ns = Ns Cm on | off | fletcher2 | fletcher4 | sha256 | noparity
+.It Sy checksum Ns = Ns Cm on | off | fletcher2 | fletcher4 | sha256 | noparity | sha512 | skein
Controls the checksum used to verify data integrity. The default value is
.Cm on ,
which automatically selects an appropriate algorithm (currently,
@@ -957,6 +957,16 @@ not be used by any other dataset.
Disabling checksums is
.Em NOT
a recommended practice.
+The
+.Sy sha512 ,
+and
+.Sy skein
+checksum algorithms require enabling the appropriate features on the pool.
+Please see
+.Xr zpool-features 7
+for more information on these algorithms.
+.Pp
+Changing this property affects only newly-written data.
.It Sy compression Ns = Ns Cm on | off | lzjb | gzip | gzip- Ns Ar N | Cm zle | Cm lz4
Controls the compression algorithm used for this dataset.
Setting compression to
@@ -1036,7 +1046,7 @@ Changing this property only affects newly-written data. Therefore, set this
property at file system creation time by using the
.Fl o Cm copies= Ns Ar N
option.
-.It Sy dedup Ns = Ns Cm on | off | verify | sha256 Ns Op Cm ,verify
+.It Sy dedup Ns = Ns Cm on | off | verify | sha256 Ns Oo Cm ,verify Oc | Sy sha512 Ns Oo Cm ,verify Oc | Sy skein Ns Oo Cm ,verify Oc
Configures deduplication for a dataset. The default value is
.Cm off .
The default deduplication checksum is
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 b/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
index 6c3b6f9..2b1d721 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
@@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 10, 2014
+.Dd May 31, 2016
.Dt ZPOOL-FEATURES 7
.Os
.Sh NAME
@@ -454,6 +454,97 @@ Please note that booting from datasets that have recordsize greater than
supported by the
.Fx
boot loader.
+.It Sy sha512
+.Bl -column "READ\-ONLY COMPATIBLE" "org.illumos:sha512"
+.It GUID Ta org.illumos:sha512
+.It READ\-ONLY COMPATIBLE Ta no
+.It DEPENDENCIES Ta none
+.El
+.Pp
+The
+.Sy sha512
+feature enables the use of the SHA-512/256 truncated hash algorithm
+.Pq FIPS 180-4
+for checksum and dedup.
+The native 64-bit arithmetic of SHA-512 provides an approximate 50%
+performance boost over SHA-256 on 64-bit hardware and is thus a good
+minimum-change replacement candidate for systems where hash performance is
+important, but these systems cannot for whatever reason utilize the faster
+.Sy skein
+algorithms.
+.Pp
+When the
+.Sy sha512
+feature is set to
+.Sy enabled ,
+the administrator can turn on the
+.Sy sha512
+checksum on any dataset using the
+.Dl # zfs set checksum=sha512 Ar dataset
+command.
+This feature becomes
+.Sy active
+once a
+.Sy checksum
+property has been set to
+.Sy sha512 ,
+and will return to being
+.Sy enabled
+once all filesystems that have ever had their checksum set to
+.Sy sha512
+are destroyed.
+.Pp
+Booting off of a pools utilizing SHA-512/256 is
+.Em NOT
+yet supported.
+.It Sy skein
+.Bl -column "READ\-ONLY COMPATIBLE" "org.illumos:skein"
+.It GUID Ta org.illumos:skein
+.It READ\-ONLY COMPATIBLE Ta no
+.It DEPENDENCIES Ta none
+.El
+.Pp
+The
+.Sy skein
+feature enables the use of the Skein hash algorithm for checksum and dedup.
+Skein is a high-performance secure hash algorithm that was a finalist in the
+NIST SHA-3 competition.
+It provides a very high security margin and high performance on 64-bit hardware
+.Pq 80% faster than SHA-256 .
+This implementation also utilizes the new salted checksumming functionality in
+ZFS, which means that the checksum is pre-seeded with a secret 256-bit random
+key
+.Pq stored on the pool
+before being fed the data block to be checksummed.
+Thus the produced checksums are unique to a given pool, preventing hash
+collision attacks on systems with dedup.
+.Pp
+When the
+.Sy skein
+feature is set to
+.Sy enabled ,
+the administrator can turn on the
+.Sy skein
+checksum on any dataset using the
+.Dl # zfs set checksum=skein Ar dataset
+command.
+This feature becomes
+.Sy active
+once a
+.Sy checksum
+property has been set to
+.Sy skein ,
+and will return to being
+.Sy enabled
+once all filesystems that have ever had their checksum set to
+.Sy skein
+are destroyed.
+.Pp
+Booting off of pools using
+.Sy skein
+is
+.Em NOT
+supported.
.El
.Sh SEE ALSO
.Xr zpool 8
diff --git a/cddl/usr.sbin/Makefile b/cddl/usr.sbin/Makefile
index ff96d85..8fb489a 100644
--- a/cddl/usr.sbin/Makefile
+++ b/cddl/usr.sbin/Makefile
@@ -7,6 +7,7 @@ SUBDIR= ${_dtrace} \
${_plockstat} \
${_tests} \
${_zdb} \
+ ${_zfsd} \
${_zhack}
.if ${MK_TESTS} != "no"
@@ -18,6 +19,9 @@ _tests= tests
_zdb= zdb
_zhack= zhack
.endif
+. if ${MK_CXX} != "no"
+_zfsd= zfsd
+. endif
.endif
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
diff --git a/cddl/usr.sbin/zfsd/Makefile b/cddl/usr.sbin/zfsd/Makefile
new file mode 100644
index 0000000..4f1a0c8
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+SRCDIR=${.CURDIR}/../../..
+.include "Makefile.common"
+
+PROG_CXX= zfsd
+MAN= zfsd.8
+
+.include <bsd.prog.mk>
+
+# The unittests require devel/googletest and devel/googlemock from ports.
+# Don't automatically build them.
+SUBDIR=
diff --git a/cddl/usr.sbin/zfsd/Makefile.common b/cddl/usr.sbin/zfsd/Makefile.common
new file mode 100644
index 0000000..aec0441
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/Makefile.common
@@ -0,0 +1,42 @@
+# $FreeBSD$
+
+SRCS= callout.cc \
+ case_file.cc \
+ zfsd_event.cc \
+ vdev.cc \
+ vdev_iterator.cc \
+ zfsd.cc \
+ zfsd_exception.cc \
+ zpool_list.cc \
+ zfsd_main.cc
+
+WARNS?= 3
+
+# Ignore warnings about Solaris specific pragmas.
+IGNORE_PRAGMA= YES
+
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libzpool/common
+INCFLAGS+= -I${SRCDIR}/cddl/compat/opensolaris/include
+INCFLAGS+= -I${SRCDIR}/cddl/compat/opensolaris/lib/libumem
+INCFLAGS+= -I${SRCDIR}/sys/cddl/compat/opensolaris
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/head
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libuutil/common
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libumem/common
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libzfs_core/common
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libzfs/common
+INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libnvpair
+INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/common/zfs
+INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/uts/common
+INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
+INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/uts/common/sys
+
+CFLAGS= -g -DNEED_SOLARIS_BOOLEAN ${INCFLAGS}
+
+DPADD= ${LIBDEVDCTL} ${LIBZFS} ${LIBZFS_CORE} ${LIBUTIL} ${LIBGEOM} \
+ ${LIBBSDXML} ${LIBSBUF} ${LIBNVPAIR} ${LIBUUTIL}
+LIBADD= devdctl zfs zfs_core util geom bsdxml sbuf nvpair uutil
+
+cscope:
+ find ${.CURDIR} -type f -a \( -name "*.[ch]" -o -name "*.cc" \) \
+ > ${.CURDIR}/cscope.files
+ cd ${.CURDIR} && cscope -buq ${INCFLAGS}
diff --git a/cddl/usr.sbin/zfsd/callout.cc b/cddl/usr.sbin/zfsd/callout.cc
new file mode 100644
index 0000000..2671c5d3
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/callout.cc
@@ -0,0 +1,219 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file callout.cc
+ *
+ * \brief Implementation of the Callout class - multi-client
+ * timer services built on top of the POSIX interval timer.
+ */
+
+#include <sys/time.h>
+
+#include <signal.h>
+#include <syslog.h>
+
+#include <climits>
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/consumer.h>
+#include <devdctl/exception.h>
+
+#include "callout.h"
+#include "vdev_iterator.h"
+#include "zfsd.h"
+#include "zfsd_exception.h"
+
+std::list<Callout *> Callout::s_activeCallouts;
+bool Callout::s_alarmFired(false);
+
+void
+Callout::Init()
+{
+ signal(SIGALRM, Callout::AlarmSignalHandler);
+}
+
+bool
+Callout::Stop()
+{
+ if (!IsPending())
+ return (false);
+
+ for (std::list<Callout *>::iterator it(s_activeCallouts.begin());
+ it != s_activeCallouts.end(); it++) {
+ if (*it != this)
+ continue;
+
+ it = s_activeCallouts.erase(it);
+ if (it != s_activeCallouts.end()) {
+
+ /*
+ * Maintain correct interval for the
+ * callouts that follow the just removed
+ * entry.
+ */
+ timeradd(&(*it)->m_interval, &m_interval,
+ &(*it)->m_interval);
+ }
+ break;
+ }
+ m_pending = false;
+ return (true);
+}
+
+bool
+Callout::Reset(const timeval &interval, CalloutFunc_t *func, void *arg)
+{
+ bool cancelled(false);
+
+ if (!timerisset(&interval))
+ throw ZfsdException("Callout::Reset: interval of 0");
+
+ cancelled = Stop();
+
+ m_interval = interval;
+ m_func = func;
+ m_arg = arg;
+ m_pending = true;
+
+ std::list<Callout *>::iterator it(s_activeCallouts.begin());
+ for (; it != s_activeCallouts.end(); it++) {
+
+ if (timercmp(&(*it)->m_interval, &m_interval, <=)) {
+ /*
+ * Decrease our interval by those that come
+ * before us.
+ */
+ timersub(&m_interval, &(*it)->m_interval, &m_interval);
+ } else {
+ /*
+ * Account for the time between the newly
+ * inserted event and those that follow.
+ */
+ timersub(&(*it)->m_interval, &m_interval,
+ &(*it)->m_interval);
+ break;
+ }
+ }
+ s_activeCallouts.insert(it, this);
+
+
+ if (s_activeCallouts.front() == this) {
+ itimerval timerval = { {0, 0}, m_interval };
+
+ setitimer(ITIMER_REAL, &timerval, NULL);
+ }
+
+ return (cancelled);
+}
+
+void
+Callout::AlarmSignalHandler(int)
+{
+ s_alarmFired = true;
+ ZfsDaemon::WakeEventLoop();
+}
+
+void
+Callout::ExpireCallouts()
+{
+ if (!s_alarmFired)
+ return;
+
+ s_alarmFired = false;
+ if (s_activeCallouts.empty()) {
+ /* Callout removal/SIGALRM race was lost. */
+ return;
+ }
+
+ /*
+ * Expire the first callout (the one we used to set the
+ * interval timer) as well as any callouts following that
+ * expire at the same time (have a zero interval from
+ * the callout before it).
+ */
+ do {
+ Callout *cur(s_activeCallouts.front());
+ s_activeCallouts.pop_front();
+ cur->m_pending = false;
+ cur->m_func(cur->m_arg);
+ } while (!s_activeCallouts.empty()
+ && timerisset(&s_activeCallouts.front()->m_interval) == 0);
+
+ if (!s_activeCallouts.empty()) {
+ Callout *next(s_activeCallouts.front());
+ itimerval timerval = { { 0, 0 }, next->m_interval };
+
+ setitimer(ITIMER_REAL, &timerval, NULL);
+ }
+}
+
+timeval
+Callout::TimeRemaining() const
+{
+ /*
+ * Outline: Add the m_interval for each callout in s_activeCallouts
+ * ahead of this, except for the first callout. Add to that the result
+ * of getitimer (That's because the first callout stores its original
+ * interval setting while the timer is ticking).
+ */
+ itimerval timervalToAlarm;
+ timeval timeToExpiry;
+ std::list<Callout *>::iterator it;
+
+ if (!IsPending()) {
+ timeToExpiry.tv_sec = INT_MAX;
+ timeToExpiry.tv_usec = 999999; /*maximum normalized value*/
+ return (timeToExpiry);
+ }
+
+ timerclear(&timeToExpiry);
+ getitimer(ITIMER_REAL, &timervalToAlarm);
+ timeval& timeToAlarm = timervalToAlarm.it_value;
+ timeradd(&timeToExpiry, &timeToAlarm, &timeToExpiry);
+
+ it =s_activeCallouts.begin();
+ it++; /*skip the first callout in the list*/
+ for (; it != s_activeCallouts.end(); it++) {
+ timeradd(&timeToExpiry, &(*it)->m_interval, &timeToExpiry);
+ if ((*it) == this)
+ break;
+ }
+ return (timeToExpiry);
+}
diff --git a/cddl/usr.sbin/zfsd/callout.h b/cddl/usr.sbin/zfsd/callout.h
new file mode 100644
index 0000000..d6b83bc
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/callout.h
@@ -0,0 +1,185 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file callout.h
+ *
+ * \brief Interface for timer based callback services.
+ *
+ * Header requirements:
+ *
+ * #include <sys/time.h>
+ *
+ * #include <list>
+ */
+
+#ifndef _CALLOUT_H_
+#define _CALLOUT_H_
+
+/**
+ * \brief Type of the function callback from a Callout.
+ */
+typedef void CalloutFunc_t(void *);
+
+/**
+ * \brief Interface to a schedulable one-shot timer with the granularity
+ * of the system clock (see setitimer(2)).
+ *
+ * Determination of callback expiration is triggered by the SIGALRM
+ * signal. Callout callbacks are always delivered from Zfsd's event
+ * processing loop.
+ *
+ * Periodic actions can be triggered via the Callout mechanisms by
+ * resetting the Callout from within its callback.
+ */
+class Callout
+{
+public:
+
+ /**
+ * Initialize the Callout subsystem.
+ */
+ static void Init();
+
+ /**
+ * Function called (via SIGALRM) when our interval
+ * timer expires.
+ */
+ static void AlarmSignalHandler(int);
+
+ /**
+ * Execute callbacks for all callouts that have the same
+ * expiration time as the first callout in the list.
+ */
+ static void ExpireCallouts();
+
+ /** Constructor. */
+ Callout();
+
+ /**
+ * Returns true if callout has not been stopped,
+ * or deactivated since the last time the callout was
+ * reset.
+ */
+ bool IsActive() const;
+
+ /**
+ * Returns true if callout is still waiting to expire.
+ */
+ bool IsPending() const;
+
+ /**
+ * Disestablish a callout.
+ */
+ bool Stop();
+
+ /**
+ * \brief Establish or change a timeout.
+ *
+ * \param interval Timeval indicating the time which must elapse
+ * before this callout fires.
+ * \param func Pointer to the callback function
+ * \param arg Argument pointer to pass to callback function
+ *
+ * \return Cancellation status.
+ * true: The previous callback was pending and therefore
+ * was cancelled.
+ * false: The callout was not pending at the time of this
+ * reset request.
+ * In all cases, a new callout is established.
+ */
+ bool Reset(const timeval &interval, CalloutFunc_t *func, void *arg);
+
+ /**
+ * \brief Calculate the remaining time until this Callout's timer
+ * expires.
+ *
+ * The return value will be slightly greater than the actual time to
+ * expiry.
+ *
+ * If the callout is not pending, returns INT_MAX.
+ */
+ timeval TimeRemaining() const;
+
+private:
+ /**
+ * All active callouts sorted by expiration time. The callout
+ * with the nearest expiration time is at the head of the list.
+ */
+ static std::list<Callout *> s_activeCallouts;
+
+ /**
+ * The interval timer has expired. This variable is set from
+ * signal handler context and tested from Zfsd::EventLoop()
+ * context via ExpireCallouts().
+ */
+ static bool s_alarmFired;
+
+ /**
+ * Time, relative to others in the active list, until
+ * this callout is fired.
+ */
+ timeval m_interval;
+
+ /** Callback function argument. */
+ void *m_arg;
+
+ /**
+ * The callback function associated with this timer
+ * entry.
+ */
+ CalloutFunc_t *m_func;
+
+ /** State of this callout. */
+ bool m_pending;
+};
+
+//- Callout public const methods ----------------------------------------------
+inline bool
+Callout::IsPending() const
+{
+ return (m_pending);
+}
+
+//- Callout public methods ----------------------------------------------------
+inline
+Callout::Callout()
+ : m_arg(0),
+ m_func(NULL),
+ m_pending(false)
+{
+ timerclear(&m_interval);
+}
+
+#endif /* CALLOUT_H_ */
diff --git a/cddl/usr.sbin/zfsd/case_file.cc b/cddl/usr.sbin/zfsd/case_file.cc
new file mode 100644
index 0000000..86c74b1
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/case_file.cc
@@ -0,0 +1,1103 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file case_file.cc
+ *
+ * We keep case files for any leaf vdev that is not in the optimal state.
+ * However, we only serialize to disk those events that need to be preserved
+ * across reboots. For now, this is just a log of soft errors which we
+ * accumulate in order to mark a device as degraded.
+ */
+#include <sys/cdefs.h>
+#include <sys/time.h>
+
+#include <sys/fs/zfs.h>
+
+#include <dirent.h>
+#include <iomanip>
+#include <fstream>
+#include <functional>
+#include <sstream>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <libzfs.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include "callout.h"
+#include "vdev_iterator.h"
+#include "zfsd_event.h"
+#include "case_file.h"
+#include "vdev.h"
+#include "zfsd.h"
+#include "zfsd_exception.h"
+#include "zpool_list.h"
+
+__FBSDID("$FreeBSD$");
+
+/*============================ Namespace Control =============================*/
+using std::auto_ptr;
+using std::hex;
+using std::ifstream;
+using std::stringstream;
+using std::setfill;
+using std::setw;
+
+using DevdCtl::Event;
+using DevdCtl::EventFactory;
+using DevdCtl::EventList;
+using DevdCtl::Guid;
+using DevdCtl::ParseException;
+
+/*--------------------------------- CaseFile ---------------------------------*/
+//- CaseFile Static Data -------------------------------------------------------
+
+CaseFileList CaseFile::s_activeCases;
+const string CaseFile::s_caseFilePath = "/var/db/zfsd/cases";
+const timeval CaseFile::s_removeGracePeriod = { 60 /*sec*/, 0 /*usec*/};
+
+//- CaseFile Static Public Methods ---------------------------------------------
+CaseFile *
+CaseFile::Find(Guid poolGUID, Guid vdevGUID)
+{
+ for (CaseFileList::iterator curCase = s_activeCases.begin();
+ curCase != s_activeCases.end(); curCase++) {
+
+ if ((*curCase)->PoolGUID() != poolGUID
+ || (*curCase)->VdevGUID() != vdevGUID)
+ continue;
+
+ /*
+ * We only carry one active case per-vdev.
+ */
+ return (*curCase);
+ }
+ return (NULL);
+}
+
+CaseFile *
+CaseFile::Find(const string &physPath)
+{
+ CaseFile *result = NULL;
+
+ for (CaseFileList::iterator curCase = s_activeCases.begin();
+ curCase != s_activeCases.end(); curCase++) {
+
+ if ((*curCase)->PhysicalPath() != physPath)
+ continue;
+
+ if (result != NULL) {
+ syslog(LOG_WARNING, "Multiple casefiles found for "
+ "physical path %s. "
+ "This is most likely a bug in zfsd",
+ physPath.c_str());
+ }
+ result = *curCase;
+ }
+ return (result);
+}
+
+
+void
+CaseFile::ReEvaluateByGuid(Guid poolGUID, const ZfsEvent &event)
+{
+ CaseFileList::iterator casefile;
+ for (casefile = s_activeCases.begin(); casefile != s_activeCases.end();){
+ CaseFileList::iterator next = casefile;
+ next++;
+ if (poolGUID == (*casefile)->PoolGUID())
+ (*casefile)->ReEvaluate(event);
+ casefile = next;
+ }
+}
+
+CaseFile &
+CaseFile::Create(Vdev &vdev)
+{
+ CaseFile *activeCase;
+
+ activeCase = Find(vdev.PoolGUID(), vdev.GUID());
+ if (activeCase == NULL)
+ activeCase = new CaseFile(vdev);
+
+ return (*activeCase);
+}
+
+void
+CaseFile::DeSerialize()
+{
+ struct dirent **caseFiles;
+
+ int numCaseFiles(scandir(s_caseFilePath.c_str(), &caseFiles,
+ DeSerializeSelector, /*compar*/NULL));
+
+ if (numCaseFiles == -1)
+ return;
+ if (numCaseFiles == 0) {
+ free(caseFiles);
+ return;
+ }
+
+ for (int i = 0; i < numCaseFiles; i++) {
+
+ DeSerializeFile(caseFiles[i]->d_name);
+ free(caseFiles[i]);
+ }
+ free(caseFiles);
+}
+
+void
+CaseFile::LogAll()
+{
+ for (CaseFileList::iterator curCase = s_activeCases.begin();
+ curCase != s_activeCases.end(); curCase++)
+ (*curCase)->Log();
+}
+
+void
+CaseFile::PurgeAll()
+{
+ /*
+ * Serialize casefiles before deleting them so that they can be reread
+ * and revalidated during BuildCaseFiles.
+ * CaseFiles remove themselves from this list on destruction.
+ */
+ while (s_activeCases.size() != 0) {
+ CaseFile *casefile = s_activeCases.front();
+ casefile->Serialize();
+ delete casefile;
+ }
+
+}
+
+//- CaseFile Public Methods ----------------------------------------------------
+bool
+CaseFile::RefreshVdevState()
+{
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+ zpool_handle_t *casePool(zpl.empty() ? NULL : zpl.front());
+ if (casePool == NULL)
+ return (false);
+
+ Vdev vd(casePool, CaseVdev(casePool));
+ if (vd.DoesNotExist())
+ return (false);
+
+ m_vdevState = vd.State();
+ m_vdevPhysPath = vd.PhysicalPath();
+ return (true);
+}
+
+bool
+CaseFile::ReEvaluate(const string &devPath, const string &physPath, Vdev *vdev)
+{
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+ zpool_handle_t *pool(zpl.empty() ? NULL : zpl.front());
+
+ if (pool == NULL || !RefreshVdevState()) {
+ /*
+ * The pool or vdev for this case file is no longer
+ * part of the configuration. This can happen
+ * if we process a device arrival notification
+ * before seeing the ZFS configuration change
+ * event.
+ */
+ syslog(LOG_INFO,
+ "CaseFile::ReEvaluate(%s,%s) Pool/Vdev unconfigured. "
+ "Closing\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str());
+ Close();
+
+ /*
+ * Since this event was not used to close this
+ * case, do not report it as consumed.
+ */
+ return (/*consumed*/false);
+ }
+
+ if (VdevState() > VDEV_STATE_CANT_OPEN) {
+ /*
+ * For now, newly discovered devices only help for
+ * devices that are missing. In the future, we might
+ * use a newly inserted spare to replace a degraded
+ * or faulted device.
+ */
+ syslog(LOG_INFO, "CaseFile::ReEvaluate(%s,%s): Pool/Vdev ignored",
+ PoolGUIDString().c_str(), VdevGUIDString().c_str());
+ return (/*consumed*/false);
+ }
+
+ if (vdev != NULL
+ && vdev->PoolGUID() == m_poolGUID
+ && vdev->GUID() == m_vdevGUID) {
+
+ zpool_vdev_online(pool, vdev->GUIDString().c_str(),
+ ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE,
+ &m_vdevState);
+ syslog(LOG_INFO, "Onlined vdev(%s/%s:%s). State now %s.\n",
+ zpool_get_name(pool), vdev->GUIDString().c_str(),
+ devPath.c_str(),
+ zpool_state_to_name(VdevState(), VDEV_AUX_NONE));
+
+ /*
+ * Check the vdev state post the online action to see
+ * if we can retire this case.
+ */
+ CloseIfSolved();
+
+ return (/*consumed*/true);
+ }
+
+ /*
+ * If the auto-replace policy is enabled, and we have physical
+ * path information, try a physical path replacement.
+ */
+ if (zpool_get_prop_int(pool, ZPOOL_PROP_AUTOREPLACE, NULL) == 0) {
+ syslog(LOG_INFO,
+ "CaseFile(%s:%s:%s): AutoReplace not set. "
+ "Ignoring device insertion.\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str(),
+ zpool_state_to_name(VdevState(), VDEV_AUX_NONE));
+ return (/*consumed*/false);
+ }
+
+ if (PhysicalPath().empty()) {
+ syslog(LOG_INFO,
+ "CaseFile(%s:%s:%s): No physical path information. "
+ "Ignoring device insertion.\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str(),
+ zpool_state_to_name(VdevState(), VDEV_AUX_NONE));
+ return (/*consumed*/false);
+ }
+
+ if (physPath != PhysicalPath()) {
+ syslog(LOG_INFO,
+ "CaseFile(%s:%s:%s): Physical path mismatch. "
+ "Ignoring device insertion.\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str(),
+ zpool_state_to_name(VdevState(), VDEV_AUX_NONE));
+ return (/*consumed*/false);
+ }
+
+ /* Write a label on the newly inserted disk. */
+ if (zpool_label_disk(g_zfsHandle, pool, devPath.c_str()) != 0) {
+ syslog(LOG_ERR,
+ "Replace vdev(%s/%s) by physical path (label): %s: %s\n",
+ zpool_get_name(pool), VdevGUIDString().c_str(),
+ libzfs_error_action(g_zfsHandle),
+ libzfs_error_description(g_zfsHandle));
+ return (/*consumed*/false);
+ }
+
+ syslog(LOG_INFO, "CaseFile::ReEvaluate(%s/%s): Replacing with %s",
+ PoolGUIDString().c_str(), VdevGUIDString().c_str(),
+ devPath.c_str());
+ return (Replace(VDEV_TYPE_DISK, devPath.c_str(), /*isspare*/false));
+}
+
+bool
+CaseFile::ReEvaluate(const ZfsEvent &event)
+{
+ bool consumed(false);
+
+ if (event.Value("type") == "misc.fs.zfs.vdev_remove") {
+ /*
+ * The Vdev we represent has been removed from the
+ * configuration. This case is no longer of value.
+ */
+ Close();
+
+ return (/*consumed*/true);
+ } else if (event.Value("type") == "misc.fs.zfs.pool_destroy") {
+ /* This Pool has been destroyed. Discard the case */
+ Close();
+
+ return (/*consumed*/true);
+ } else if (event.Value("type") == "misc.fs.zfs.config_sync") {
+ RefreshVdevState();
+ if (VdevState() < VDEV_STATE_HEALTHY)
+ consumed = ActivateSpare();
+ }
+
+
+ if (event.Value("class") == "resource.fs.zfs.removed") {
+ bool spare_activated;
+
+ if (!RefreshVdevState()) {
+ /*
+ * The pool or vdev for this case file is no longer
+ * part of the configuration. This can happen
+ * if we process a device arrival notification
+ * before seeing the ZFS configuration change
+ * event.
+ */
+ syslog(LOG_INFO,
+ "CaseFile::ReEvaluate(%s,%s) Pool/Vdev "
+ "unconfigured. Closing\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str());
+ /*
+ * Close the case now so we won't waste cycles in the
+ * system rescan
+ */
+ Close();
+
+ /*
+ * Since this event was not used to close this
+ * case, do not report it as consumed.
+ */
+ return (/*consumed*/false);
+ }
+
+ /*
+ * Discard any tentative I/O error events for
+ * this case. They were most likely caused by the
+ * hot-unplug of this device.
+ */
+ PurgeTentativeEvents();
+
+ /* Try to activate spares if they are available */
+ spare_activated = ActivateSpare();
+
+ /*
+ * Rescan the drives in the system to see if a recent
+ * drive arrival can be used to solve this case.
+ */
+ ZfsDaemon::RequestSystemRescan();
+
+ /*
+ * Consume the event if we successfully activated a spare.
+ * Otherwise, leave it in the unconsumed events list so that the
+ * future addition of a spare to this pool might be able to
+ * close the case
+ */
+ consumed = spare_activated;
+ } else if (event.Value("class") == "resource.fs.zfs.statechange") {
+ RefreshVdevState();
+ /*
+ * If this vdev is DEGRADED, FAULTED, or UNAVAIL, try to
+ * activate a hotspare. Otherwise, ignore the event
+ */
+ if (VdevState() == VDEV_STATE_FAULTED ||
+ VdevState() == VDEV_STATE_DEGRADED ||
+ VdevState() == VDEV_STATE_CANT_OPEN)
+ (void) ActivateSpare();
+ consumed = true;
+ }
+ else if (event.Value("class") == "ereport.fs.zfs.io" ||
+ event.Value("class") == "ereport.fs.zfs.checksum") {
+
+ m_tentativeEvents.push_front(event.DeepCopy());
+ RegisterCallout(event);
+ consumed = true;
+ }
+
+ bool closed(CloseIfSolved());
+
+ return (consumed || closed);
+}
+
+
+bool
+CaseFile::ActivateSpare() {
+ nvlist_t *config, *nvroot;
+ nvlist_t **spares;
+ char *devPath, *vdev_type;
+ const char *poolname;
+ u_int nspares, i;
+ int error;
+
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+ zpool_handle_t *zhp(zpl.empty() ? NULL : zpl.front());
+ if (zhp == NULL) {
+ syslog(LOG_ERR, "CaseFile::ActivateSpare: Could not find pool "
+ "for pool_guid %" PRIu64".", (uint64_t)m_poolGUID);
+ return (false);
+ }
+ poolname = zpool_get_name(zhp);
+ config = zpool_get_config(zhp, NULL);
+ if (config == NULL) {
+ syslog(LOG_ERR, "CaseFile::ActivateSpare: Could not find pool "
+ "config for pool %s", poolname);
+ return (false);
+ }
+ error = nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot);
+ if (error != 0){
+ syslog(LOG_ERR, "CaseFile::ActivateSpare: Could not find vdev "
+ "tree for pool %s", poolname);
+ return (false);
+ }
+ nspares = 0;
+ nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, &spares,
+ &nspares);
+ if (nspares == 0) {
+ /* The pool has no spares configured */
+ syslog(LOG_INFO, "CaseFile::ActivateSpare: "
+ "No spares available for pool %s", poolname);
+ return (false);
+ }
+ for (i = 0; i < nspares; i++) {
+ uint64_t *nvlist_array;
+ vdev_stat_t *vs;
+ uint_t nstats;
+
+ if (nvlist_lookup_uint64_array(spares[i],
+ ZPOOL_CONFIG_VDEV_STATS, &nvlist_array, &nstats) != 0) {
+ syslog(LOG_ERR, "CaseFile::ActivateSpare: Could not "
+ "find vdev stats for pool %s, spare %d",
+ poolname, i);
+ return (false);
+ }
+ vs = reinterpret_cast<vdev_stat_t *>(nvlist_array);
+
+ if ((vs->vs_aux != VDEV_AUX_SPARED)
+ && (vs->vs_state == VDEV_STATE_HEALTHY)) {
+ /* We found a usable spare */
+ break;
+ }
+ }
+
+ if (i == nspares) {
+ /* No available spares were found */
+ return (false);
+ }
+
+ error = nvlist_lookup_string(spares[i], ZPOOL_CONFIG_PATH, &devPath);
+ if (error != 0) {
+ syslog(LOG_ERR, "CaseFile::ActivateSpare: Cannot determine "
+ "the path of pool %s, spare %d. Error %d",
+ poolname, i, error);
+ return (false);
+ }
+
+ error = nvlist_lookup_string(spares[i], ZPOOL_CONFIG_TYPE, &vdev_type);
+ if (error != 0) {
+ syslog(LOG_ERR, "CaseFile::ActivateSpare: Cannot determine "
+ "the vdev type of pool %s, spare %d. Error %d",
+ poolname, i, error);
+ return (false);
+ }
+
+ return (Replace(vdev_type, devPath, /*isspare*/true));
+}
+
+void
+CaseFile::RegisterCallout(const Event &event)
+{
+ timeval now, countdown, elapsed, timestamp, zero, remaining;
+
+ gettimeofday(&now, 0);
+ timestamp = event.GetTimestamp();
+ timersub(&now, &timestamp, &elapsed);
+ timersub(&s_removeGracePeriod, &elapsed, &countdown);
+ /*
+ * If countdown is <= zero, Reset the timer to the
+ * smallest positive time value instead
+ */
+ timerclear(&zero);
+ if (timercmp(&countdown, &zero, <=)) {
+ timerclear(&countdown);
+ countdown.tv_usec = 1;
+ }
+
+ remaining = m_tentativeTimer.TimeRemaining();
+
+ if (!m_tentativeTimer.IsPending()
+ || timercmp(&countdown, &remaining, <))
+ m_tentativeTimer.Reset(countdown, OnGracePeriodEnded, this);
+}
+
+
+bool
+CaseFile::CloseIfSolved()
+{
+ if (m_events.empty()
+ && m_tentativeEvents.empty()) {
+
+ /*
+ * We currently do not track or take actions on
+ * devices in the degraded or faulted state.
+ * Once we have support for spare pools, we'll
+ * retain these cases so that any spares added in
+ * the future can be applied to them.
+ */
+ switch (VdevState()) {
+ case VDEV_STATE_HEALTHY:
+ /* No need to keep cases for healthy vdevs */
+ Close();
+ return (true);
+ case VDEV_STATE_REMOVED:
+ case VDEV_STATE_CANT_OPEN:
+ /*
+ * Keep open. We may solve it with a newly inserted
+ * device.
+ */
+ case VDEV_STATE_FAULTED:
+ case VDEV_STATE_DEGRADED:
+ /*
+ * Keep open. We may solve it with the future
+ * addition of a spare to the pool
+ */
+ case VDEV_STATE_UNKNOWN:
+ case VDEV_STATE_CLOSED:
+ case VDEV_STATE_OFFLINE:
+ /*
+ * Keep open? This may not be the correct behavior,
+ * but it's what we've always done
+ */
+ ;
+ }
+
+ /*
+ * Re-serialize the case in order to remove any
+ * previous event data.
+ */
+ Serialize();
+ }
+
+ return (false);
+}
+
+void
+CaseFile::Log()
+{
+ syslog(LOG_INFO, "CaseFile(%s,%s,%s)\n", PoolGUIDString().c_str(),
+ VdevGUIDString().c_str(), PhysicalPath().c_str());
+ syslog(LOG_INFO, "\tVdev State = %s\n",
+ zpool_state_to_name(VdevState(), VDEV_AUX_NONE));
+ if (m_tentativeEvents.size() != 0) {
+ syslog(LOG_INFO, "\t=== Tentative Events ===\n");
+ for (EventList::iterator event(m_tentativeEvents.begin());
+ event != m_tentativeEvents.end(); event++)
+ (*event)->Log(LOG_INFO);
+ }
+ if (m_events.size() != 0) {
+ syslog(LOG_INFO, "\t=== Events ===\n");
+ for (EventList::iterator event(m_events.begin());
+ event != m_events.end(); event++)
+ (*event)->Log(LOG_INFO);
+ }
+}
+
+//- CaseFile Static Protected Methods ------------------------------------------
+void
+CaseFile::OnGracePeriodEnded(void *arg)
+{
+ CaseFile &casefile(*static_cast<CaseFile *>(arg));
+
+ casefile.OnGracePeriodEnded();
+}
+
+int
+CaseFile::DeSerializeSelector(const struct dirent *dirEntry)
+{
+ uint64_t poolGUID;
+ uint64_t vdevGUID;
+
+ if (dirEntry->d_type == DT_REG
+ && sscanf(dirEntry->d_name, "pool_%" PRIu64 "_vdev_%" PRIu64 ".case",
+ &poolGUID, &vdevGUID) == 2)
+ return (1);
+ return (0);
+}
+
+void
+CaseFile::DeSerializeFile(const char *fileName)
+{
+ string fullName(s_caseFilePath + '/' + fileName);
+ CaseFile *existingCaseFile(NULL);
+ CaseFile *caseFile(NULL);
+
+ try {
+ uint64_t poolGUID;
+ uint64_t vdevGUID;
+ nvlist_t *vdevConf;
+
+ sscanf(fileName, "pool_%" PRIu64 "_vdev_%" PRIu64 ".case",
+ &poolGUID, &vdevGUID);
+ existingCaseFile = Find(Guid(poolGUID), Guid(vdevGUID));
+ if (existingCaseFile != NULL) {
+ /*
+ * If the vdev is already degraded or faulted,
+ * there's no point in keeping the state around
+ * that we use to put a drive into the degraded
+ * state. However, if the vdev is simply missing,
+ * preserve the case data in the hopes that it will
+ * return.
+ */
+ caseFile = existingCaseFile;
+ vdev_state curState(caseFile->VdevState());
+ if (curState > VDEV_STATE_CANT_OPEN
+ && curState < VDEV_STATE_HEALTHY) {
+ unlink(fileName);
+ return;
+ }
+ } else {
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &poolGUID);
+ if (zpl.empty()
+ || (vdevConf = VdevIterator(zpl.front())
+ .Find(vdevGUID)) == NULL) {
+ /*
+ * Either the pool no longer exists
+ * or this vdev is no longer a member of
+ * the pool.
+ */
+ unlink(fullName.c_str());
+ return;
+ }
+
+ /*
+ * Any vdev we find that does not have a case file
+ * must be in the healthy state and thus worthy of
+ * continued SERD data tracking.
+ */
+ caseFile = new CaseFile(Vdev(zpl.front(), vdevConf));
+ }
+
+ ifstream caseStream(fullName.c_str());
+ if (!caseStream)
+ throw ZfsdException("CaseFile::DeSerialize: Unable to "
+ "read %s.\n", fileName);
+
+ caseFile->DeSerialize(caseStream);
+ } catch (const ParseException &exp) {
+
+ exp.Log();
+ if (caseFile != existingCaseFile)
+ delete caseFile;
+
+ /*
+ * Since we can't parse the file, unlink it so we don't
+ * trip over it again.
+ */
+ unlink(fileName);
+ } catch (const ZfsdException &zfsException) {
+
+ zfsException.Log();
+ if (caseFile != existingCaseFile)
+ delete caseFile;
+ }
+}
+
+//- CaseFile Protected Methods -------------------------------------------------
+CaseFile::CaseFile(const Vdev &vdev)
+ : m_poolGUID(vdev.PoolGUID()),
+ m_vdevGUID(vdev.GUID()),
+ m_vdevState(vdev.State()),
+ m_vdevPhysPath(vdev.PhysicalPath())
+{
+ stringstream guidString;
+
+ guidString << m_vdevGUID;
+ m_vdevGUIDString = guidString.str();
+ guidString.str("");
+ guidString << m_poolGUID;
+ m_poolGUIDString = guidString.str();
+
+ s_activeCases.push_back(this);
+
+ syslog(LOG_INFO, "Creating new CaseFile:\n");
+ Log();
+}
+
+CaseFile::~CaseFile()
+{
+ PurgeEvents();
+ PurgeTentativeEvents();
+ m_tentativeTimer.Stop();
+ s_activeCases.remove(this);
+}
+
+void
+CaseFile::PurgeEvents()
+{
+ for (EventList::iterator event(m_events.begin());
+ event != m_events.end(); event++)
+ delete *event;
+
+ m_events.clear();
+}
+
+void
+CaseFile::PurgeTentativeEvents()
+{
+ for (EventList::iterator event(m_tentativeEvents.begin());
+ event != m_tentativeEvents.end(); event++)
+ delete *event;
+
+ m_tentativeEvents.clear();
+}
+
+void
+CaseFile::SerializeEvList(const EventList events, int fd,
+ const char* prefix) const
+{
+ if (events.empty())
+ return;
+ for (EventList::const_iterator curEvent = events.begin();
+ curEvent != events.end(); curEvent++) {
+ const string &eventString((*curEvent)->GetEventString());
+
+ // TODO: replace many write(2) calls with a single writev(2)
+ if (prefix)
+ write(fd, prefix, strlen(prefix));
+ write(fd, eventString.c_str(), eventString.length());
+ }
+}
+
+void
+CaseFile::Serialize()
+{
+ stringstream saveFile;
+
+ saveFile << setfill('0')
+ << s_caseFilePath << "/"
+ << "pool_" << PoolGUIDString()
+ << "_vdev_" << VdevGUIDString()
+ << ".case";
+
+ if (m_events.empty() && m_tentativeEvents.empty()) {
+ unlink(saveFile.str().c_str());
+ return;
+ }
+
+ int fd(open(saveFile.str().c_str(), O_CREAT|O_TRUNC|O_WRONLY, 0644));
+ if (fd == -1) {
+ syslog(LOG_ERR, "CaseFile::Serialize: Unable to open %s.\n",
+ saveFile.str().c_str());
+ return;
+ }
+ SerializeEvList(m_events, fd);
+ SerializeEvList(m_tentativeEvents, fd, "tentative ");
+ close(fd);
+}
+
+/*
+ * XXX: This method assumes that events may not contain embedded newlines. If
+ * ever events can contain embedded newlines, then CaseFile must switch
+ * serialization formats
+ */
+void
+CaseFile::DeSerialize(ifstream &caseStream)
+{
+ string evString;
+ const EventFactory &factory(ZfsDaemon::Get().GetFactory());
+
+ caseStream >> std::noskipws >> std::ws;
+ while (caseStream.good()) {
+ /*
+ * Outline:
+ * read the beginning of a line and check it for
+ * "tentative". If found, discard "tentative".
+ * Create a new event
+ * continue
+ */
+ EventList* destEvents;
+ const string tentFlag("tentative ");
+ string line;
+ std::stringbuf lineBuf;
+
+ caseStream.get(lineBuf);
+ caseStream.ignore(); /*discard the newline character*/
+ line = lineBuf.str();
+ if (line.compare(0, tentFlag.size(), tentFlag) == 0) {
+ /* Discard "tentative" */
+ line.erase(0, tentFlag.size());
+ destEvents = &m_tentativeEvents;
+ } else {
+ destEvents = &m_events;
+ }
+ Event *event(Event::CreateEvent(factory, line));
+ if (event != NULL) {
+ destEvents->push_back(event);
+ RegisterCallout(*event);
+ }
+ }
+}
+
+void
+CaseFile::Close()
+{
+ /*
+ * This case is no longer relevant. Clean up our
+ * serialization file, and delete the case.
+ */
+ syslog(LOG_INFO, "CaseFile(%s,%s) closed - State %s\n",
+ PoolGUIDString().c_str(), VdevGUIDString().c_str(),
+ zpool_state_to_name(VdevState(), VDEV_AUX_NONE));
+
+ /*
+ * Serialization of a Case with no event data, clears the
+ * Serialization data for that event.
+ */
+ PurgeEvents();
+ Serialize();
+
+ delete this;
+}
+
+void
+CaseFile::OnGracePeriodEnded()
+{
+ bool should_fault, should_degrade;
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+ zpool_handle_t *zhp(zpl.empty() ? NULL : zpl.front());
+
+ m_events.splice(m_events.begin(), m_tentativeEvents);
+ should_fault = ShouldFault();
+ should_degrade = ShouldDegrade();
+
+ if (should_fault || should_degrade) {
+ if (zhp == NULL
+ || (VdevIterator(zhp).Find(m_vdevGUID)) == NULL) {
+ /*
+ * Either the pool no longer exists
+ * or this vdev is no longer a member of
+ * the pool.
+ */
+ Close();
+ return;
+ }
+
+ }
+
+ /* A fault condition has priority over a degrade condition */
+ if (ShouldFault()) {
+ /* Fault the vdev and close the case. */
+ if (zpool_vdev_fault(zhp, (uint64_t)m_vdevGUID,
+ VDEV_AUX_ERR_EXCEEDED) == 0) {
+ syslog(LOG_INFO, "Faulting vdev(%s/%s)",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str());
+ Close();
+ return;
+ }
+ else {
+ syslog(LOG_ERR, "Fault vdev(%s/%s): %s: %s\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str(),
+ libzfs_error_action(g_zfsHandle),
+ libzfs_error_description(g_zfsHandle));
+ }
+ }
+ else if (ShouldDegrade()) {
+ /* Degrade the vdev and close the case. */
+ if (zpool_vdev_degrade(zhp, (uint64_t)m_vdevGUID,
+ VDEV_AUX_ERR_EXCEEDED) == 0) {
+ syslog(LOG_INFO, "Degrading vdev(%s/%s)",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str());
+ Close();
+ return;
+ }
+ else {
+ syslog(LOG_ERR, "Degrade vdev(%s/%s): %s: %s\n",
+ PoolGUIDString().c_str(),
+ VdevGUIDString().c_str(),
+ libzfs_error_action(g_zfsHandle),
+ libzfs_error_description(g_zfsHandle));
+ }
+ }
+ Serialize();
+}
+
+Vdev
+CaseFile::BeingReplacedBy(zpool_handle_t *zhp) {
+ Vdev vd(zhp, CaseVdev(zhp));
+ std::list<Vdev> children;
+ std::list<Vdev>::iterator children_it;
+
+ Vdev parent(vd.Parent());
+ Vdev replacing(NonexistentVdev);
+
+ /*
+ * To determine whether we are being replaced by another spare that
+ * is still working, then make sure that it is currently spared and
+ * that the spare is either resilvering or healthy. If any of these
+ * conditions fail, then we are not being replaced by a spare.
+ *
+ * If the spare is healthy, then the case file should be closed very
+ * soon after this check.
+ */
+ if (parent.DoesNotExist()
+ || parent.Name(zhp, /*verbose*/false) != "spare")
+ return (NonexistentVdev);
+
+ children = parent.Children();
+ children_it = children.begin();
+ for (;children_it != children.end(); children_it++) {
+ Vdev child = *children_it;
+
+ /* Skip our vdev. */
+ if (child.GUID() == VdevGUID())
+ continue;
+ /*
+ * Accept the first child that doesn't match our GUID, or
+ * any resilvering/healthy device if one exists.
+ */
+ if (replacing.DoesNotExist() || child.IsResilvering()
+ || child.State() == VDEV_STATE_HEALTHY)
+ replacing = child;
+ }
+
+ return (replacing);
+}
+
+bool
+CaseFile::Replace(const char* vdev_type, const char* path, bool isspare) {
+ nvlist_t *nvroot, *newvd;
+ const char *poolname;
+ string oldstr(VdevGUIDString());
+ bool retval = true;
+
+ /* Figure out what pool we're working on */
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &m_poolGUID);
+ zpool_handle_t *zhp(zpl.empty() ? NULL : zpl.front());
+ if (zhp == NULL) {
+ syslog(LOG_ERR, "CaseFile::Replace: could not find pool for "
+ "pool_guid %" PRIu64 ".", (uint64_t)m_poolGUID);
+ return (false);
+ }
+ poolname = zpool_get_name(zhp);
+ Vdev vd(zhp, CaseVdev(zhp));
+ Vdev replaced(BeingReplacedBy(zhp));
+
+ if (isspare && !vd.IsSpare() && !replaced.DoesNotExist()) {
+ /* If we are already being replaced by a working spare, pass. */
+ if (replaced.IsResilvering()
+ || replaced.State() == VDEV_STATE_HEALTHY) {
+ syslog(LOG_INFO, "CaseFile::Replace(%s->%s): already "
+ "replaced", VdevGUIDString().c_str(), path);
+ return (/*consumed*/false);
+ }
+ /*
+ * If we have already been replaced by a spare, but that spare
+ * is broken, we must spare the spare, not the original device.
+ */
+ oldstr = replaced.GUIDString();
+ syslog(LOG_INFO, "CaseFile::Replace(%s->%s): sparing "
+ "broken spare %s instead", VdevGUIDString().c_str(),
+ path, oldstr.c_str());
+ }
+
+ /*
+ * Build a root vdev/leaf vdev configuration suitable for
+ * zpool_vdev_attach. Only enough data for the kernel to find
+ * the device (i.e. type and disk device node path) are needed.
+ */
+ nvroot = NULL;
+ newvd = NULL;
+
+ if (nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) != 0
+ || nvlist_alloc(&newvd, NV_UNIQUE_NAME, 0) != 0) {
+ syslog(LOG_ERR, "Replace vdev(%s/%s): Unable to allocate "
+ "configuration data.", poolname, oldstr.c_str());
+ if (nvroot != NULL)
+ nvlist_free(nvroot);
+ return (false);
+ }
+ if (nvlist_add_string(newvd, ZPOOL_CONFIG_TYPE, vdev_type) != 0
+ || nvlist_add_string(newvd, ZPOOL_CONFIG_PATH, path) != 0
+ || nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) != 0
+ || nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
+ &newvd, 1) != 0) {
+ syslog(LOG_ERR, "Replace vdev(%s/%s): Unable to initialize "
+ "configuration data.", poolname, oldstr.c_str());
+ nvlist_free(newvd);
+ nvlist_free(nvroot);
+ return (true);
+ }
+
+ /* Data was copied when added to the root vdev. */
+ nvlist_free(newvd);
+
+ retval = (zpool_vdev_attach(zhp, oldstr.c_str(), path, nvroot,
+ /*replace*/B_TRUE) == 0);
+ if (retval)
+ syslog(LOG_INFO, "Replacing vdev(%s/%s) with %s\n",
+ poolname, oldstr.c_str(), path);
+ else
+ syslog(LOG_ERR, "Replace vdev(%s/%s): %s: %s\n",
+ poolname, oldstr.c_str(), libzfs_error_action(g_zfsHandle),
+ libzfs_error_description(g_zfsHandle));
+ nvlist_free(nvroot);
+
+ return (retval);
+}
+
+/* Does the argument event refer to a checksum error? */
+static bool
+IsChecksumEvent(const Event* const event)
+{
+ return ("ereport.fs.zfs.checksum" == event->Value("type"));
+}
+
+/* Does the argument event refer to an IO error? */
+static bool
+IsIOEvent(const Event* const event)
+{
+ return ("ereport.fs.zfs.io" == event->Value("type"));
+}
+
+bool
+CaseFile::ShouldDegrade() const
+{
+ return (std::count_if(m_events.begin(), m_events.end(),
+ IsChecksumEvent) > ZFS_DEGRADE_IO_COUNT);
+}
+
+bool
+CaseFile::ShouldFault() const
+{
+ return (std::count_if(m_events.begin(), m_events.end(),
+ IsIOEvent) > ZFS_DEGRADE_IO_COUNT);
+}
+
+nvlist_t *
+CaseFile::CaseVdev(zpool_handle_t *zhp) const
+{
+ return (VdevIterator(zhp).Find(VdevGUID()));
+}
diff --git a/cddl/usr.sbin/zfsd/case_file.h b/cddl/usr.sbin/zfsd/case_file.h
new file mode 100644
index 0000000..aa2a447
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/case_file.h
@@ -0,0 +1,426 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file case_file.h
+ *
+ * CaseFile objects aggregate vdev faults that may require ZFSD action
+ * in order to maintain the health of a ZFS pool.
+ *
+ * Header requirements:
+ *
+ * #include <list>
+ *
+ * #include "callout.h"
+ * #include "zfsd_event.h"
+ */
+#ifndef _CASE_FILE_H_
+#define _CASE_FILE_H_
+
+/*=========================== Forward Declarations ===========================*/
+class CaseFile;
+class Vdev;
+
+/*============================= Class Definitions ============================*/
+/*------------------------------- CaseFileList -------------------------------*/
+/**
+ * CaseFileList is a specialization of the standard list STL container.
+ */
+typedef std::list< CaseFile *> CaseFileList;
+
+/*--------------------------------- CaseFile ---------------------------------*/
+/**
+ * A CaseFile object is instantiated anytime a vdev for an active pool
+ * experiences an I/O error, is faulted by ZFS, or is determined to be
+ * missing/removed.
+ *
+ * A vdev may have at most one CaseFile.
+ *
+ * CaseFiles are retired when a vdev leaves an active pool configuration
+ * or an action is taken to resolve the issues recorded in the CaseFile.
+ *
+ * Logging a case against a vdev does not imply that an immediate action
+ * to resolve a fault is required or even desired. For example, a CaseFile
+ * must accumulate a number of I/O errors in order to flag a device as
+ * degraded.
+ *
+ * Vdev I/O errors are not recorded in ZFS label inforamation. For this
+ * reasons, CaseFile%%s with accumulated I/O error events are serialized
+ * to the file system so that they survive across boots. Currently all
+ * other fault types can be reconstructed from ZFS label information, so
+ * CaseFile%%s for missing, faulted, or degradded members are just recreated
+ * at ZFSD startup instead of being deserialized from the file system.
+ */
+class CaseFile
+{
+public:
+ /**
+ * \brief Find a CaseFile object by a vdev's pool/vdev GUID tuple.
+ *
+ * \param poolGUID Pool GUID for the vdev of the CaseFile to find.
+ * \param vdevGUID Vdev GUID for the vdev of the CaseFile to find.
+ *
+ * \return If found, a pointer to a valid CaseFile object.
+ * Otherwise NULL.
+ */
+ static CaseFile *Find(DevdCtl::Guid poolGUID, DevdCtl::Guid vdevGUID);
+
+ /**
+ * \brief Find a CaseFile object by a vdev's current/last known
+ * physical path.
+ *
+ * \param physPath Physical path of the vdev of the CaseFile to find.
+ *
+ * \return If found, a pointer to a valid CaseFile object.
+ * Otherwise NULL.
+ */
+ static CaseFile *Find(const string &physPath);
+
+ /**
+ * \brief ReEvaluate all open cases whose pool guid matches the argument
+ *
+ * \param poolGUID Only reevaluate cases for this pool
+ * \param event Try to consume this event with the casefile
+ */
+ static void ReEvaluateByGuid(DevdCtl::Guid poolGUID,
+ const ZfsEvent &event);
+
+ /**
+ * \brief Create or return an existing active CaseFile for the
+ * specified vdev.
+ *
+ * \param vdev The vdev object for which to find/create a CaseFile.
+ *
+ * \return A reference to a valid CaseFile object.
+ */
+ static CaseFile &Create(Vdev &vdev);
+
+ /**
+ * \brief Deserialize all serialized CaseFile objects found in
+ * the file system.
+ */
+ static void DeSerialize();
+
+ /**
+ * \brief Emit syslog data on all active CaseFile%%s in the system.
+ */
+ static void LogAll();
+
+ /**
+ * \brief Destroy the in-core cache of CaseFile data.
+ *
+ * This routine does not disturb the on disk, serialized, CaseFile
+ * data.
+ */
+ static void PurgeAll();
+
+ DevdCtl::Guid PoolGUID() const;
+ DevdCtl::Guid VdevGUID() const;
+ vdev_state VdevState() const;
+ const string &PoolGUIDString() const;
+ const string &VdevGUIDString() const;
+ const string &PhysicalPath() const;
+
+ /**
+ * \brief Attempt to resolve this CaseFile using the disk
+ * resource at the given device/physical path/vdev object
+ * tuple.
+ *
+ * \param devPath The devfs path for the disk resource.
+ * \param physPath The physical path information reported by
+ * the disk resource.
+ * \param vdev If the disk contains ZFS label information,
+ * a pointer to the disk label's vdev object
+ * data. Otherwise NULL.
+ *
+ * \return True if this event was consumed by this CaseFile.
+ */
+ bool ReEvaluate(const string &devPath, const string &physPath,
+ Vdev *vdev);
+
+ /**
+ * \brief Update this CaseFile in light of the provided ZfsEvent.
+ *
+ * Must be virtual so it can be overridden in the unit tests
+ *
+ * \param event The ZfsEvent to evaluate.
+ *
+ * \return True if this event was consumed by this CaseFile.
+ */
+ virtual bool ReEvaluate(const ZfsEvent &event);
+
+ /**
+ * \brief Register an itimer callout for the given event, if necessary
+ */
+ virtual void RegisterCallout(const DevdCtl::Event &event);
+
+ /**
+ * \brief Close a case if it is no longer relevant.
+ *
+ * This method deals with cases tracking soft errors. Soft errors
+ * will be discarded should a remove event occur within a short period
+ * of the soft errors being reported. We also discard the events
+ * if the vdev is marked degraded or failed.
+ *
+ * \return True if the case is closed. False otherwise.
+ */
+ bool CloseIfSolved();
+
+ /**
+ * \brief Emit data about this CaseFile via syslog(3).
+ */
+ void Log();
+
+ /**
+ * \brief Whether we should degrade this vdev
+ */
+ bool ShouldDegrade() const;
+
+ /**
+ * \brief Whether we should fault this vdev
+ */
+ bool ShouldFault() const;
+
+protected:
+ enum {
+ /**
+ * The number of soft errors on a vdev required
+ * to transition a vdev from healthy to degraded
+ * status.
+ */
+ ZFS_DEGRADE_IO_COUNT = 50
+ };
+
+ static CalloutFunc_t OnGracePeriodEnded;
+
+ /**
+ * \brief scandir(3) filter function used to find files containing
+ * serialized CaseFile data.
+ *
+ * \param dirEntry Directory entry for the file to filter.
+ *
+ * \return Non-zero for a file to include in the selection,
+ * otherwise 0.
+ */
+ static int DeSerializeSelector(const struct dirent *dirEntry);
+
+ /**
+ * \brief Given the name of a file containing serialized events from a
+ * CaseFile object, create/update an in-core CaseFile object
+ * representing the serialized data.
+ *
+ * \param fileName The name of a file containing serialized events
+ * from a CaseFile object.
+ */
+ static void DeSerializeFile(const char *fileName);
+
+ /** Constructor. */
+ CaseFile(const Vdev &vdev);
+
+ /**
+ * Destructor.
+ * Must be virtual so it can be subclassed in the unit tests
+ */
+ virtual ~CaseFile();
+
+ /**
+ * \brief Reload state for the vdev associated with this CaseFile.
+ *
+ * \return True if the refresh was successful. False if the system
+ * has no record of the pool or vdev for this CaseFile.
+ */
+ virtual bool RefreshVdevState();
+
+ /**
+ * \brief Free all events in the m_events list.
+ */
+ void PurgeEvents();
+
+ /**
+ * \brief Free all events in the m_tentativeEvents list.
+ */
+ void PurgeTentativeEvents();
+
+ /**
+ * \brief Commit to file system storage.
+ */
+ void Serialize();
+
+ /**
+ * \brief Retrieve event data from a serialization stream.
+ *
+ * \param caseStream The serializtion stream to parse.
+ */
+ void DeSerialize(std::ifstream &caseStream);
+
+ /**
+ * \brief Serializes the supplied event list and writes it to fd
+ *
+ * \param prefix If not NULL, this prefix will be prepended to
+ * every event in the file.
+ */
+ void SerializeEvList(const DevdCtl::EventList events, int fd,
+ const char* prefix=NULL) const;
+
+ /**
+ * \brief Unconditionally close a CaseFile.
+ */
+ virtual void Close();
+
+ /**
+ * \brief Callout callback invoked when the remove timer grace
+ * period expires.
+ *
+ * If no remove events are received prior to the grace period
+ * firing, then any tentative events are promoted and counted
+ * against the health of the vdev.
+ */
+ void OnGracePeriodEnded();
+
+ /**
+ * \brief Attempt to activate a spare on this case's pool.
+ *
+ * Call this whenever a pool becomes degraded. It will look for any
+ * spare devices and activate one to replace the casefile's vdev. It
+ * will _not_ close the casefile; that should only happen when the
+ * missing drive is replaced or the user promotes the spare.
+ *
+ * \return True if a spare was activated
+ */
+ bool ActivateSpare();
+
+ /**
+ * \brief replace a pool's vdev with another
+ *
+ * \param vdev_type The type of the new vdev. Usually either
+ * VDEV_TYPE_DISK or VDEV_TYPE_FILE
+ * \param path The file system path to the new vdev
+ * \param isspare Whether the new vdev is a spare
+ *
+ * \return true iff the replacement was successful
+ */
+ bool Replace(const char* vdev_type, const char* path, bool isspare);
+
+ /**
+ * \brief Which vdev, if any, is replacing ours.
+ *
+ * \param zhp Pool handle state from the caller context
+ *
+ * \return the vdev that is currently replacing ours,
+ * or NonexistentVdev if there isn't one.
+ */
+ Vdev BeingReplacedBy(zpool_handle_t *zhp);
+
+ /**
+ * \brief All CaseFiles being tracked by ZFSD.
+ */
+ static CaseFileList s_activeCases;
+
+ /**
+ * \brief The file system path to serialized CaseFile data.
+ */
+ static const string s_caseFilePath;
+
+ /**
+ * \brief The time ZFSD waits before promoting a tentative event
+ * into a permanent event.
+ */
+ static const timeval s_removeGracePeriod;
+
+ /**
+ * \brief A list of soft error events counted against the health of
+ * a vdev.
+ */
+ DevdCtl::EventList m_events;
+
+ /**
+ * \brief A list of soft error events waiting for a grace period
+ * expiration before being counted against the health of
+ * a vdev.
+ */
+ DevdCtl::EventList m_tentativeEvents;
+
+ DevdCtl::Guid m_poolGUID;
+ DevdCtl::Guid m_vdevGUID;
+ vdev_state m_vdevState;
+ string m_poolGUIDString;
+ string m_vdevGUIDString;
+ string m_vdevPhysPath;
+
+ /**
+ * \brief Callout activated when a grace period
+ */
+ Callout m_tentativeTimer;
+
+private:
+ nvlist_t *CaseVdev(zpool_handle_t *zhp) const;
+};
+
+inline DevdCtl::Guid
+CaseFile::PoolGUID() const
+{
+ return (m_poolGUID);
+}
+
+inline DevdCtl::Guid
+CaseFile::VdevGUID() const
+{
+ return (m_vdevGUID);
+}
+
+inline vdev_state
+CaseFile::VdevState() const
+{
+ return (m_vdevState);
+}
+
+inline const string &
+CaseFile::PoolGUIDString() const
+{
+ return (m_poolGUIDString);
+}
+
+inline const string &
+CaseFile::VdevGUIDString() const
+{
+ return (m_vdevGUIDString);
+}
+
+inline const string &
+CaseFile::PhysicalPath() const
+{
+ return (m_vdevPhysPath);
+}
+
+#endif /* _CASE_FILE_H_ */
diff --git a/cddl/usr.sbin/zfsd/tests/Makefile b/cddl/usr.sbin/zfsd/tests/Makefile
new file mode 100644
index 0000000..2a6ffb5
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/tests/Makefile
@@ -0,0 +1,45 @@
+# $FreeBSD$
+
+SRCDIR=${.CURDIR}/../../../..
+.include "${.CURDIR}/../Makefile.common"
+.PATH: ${.CURDIR}/..
+
+TESTSDIR?= ${TESTSBASE}/cddl/sbin/zfsd
+
+PLAIN_TESTS_CXX= zfsd_unittest
+SRCS.zfsd_unittest:= ${SRCS:Nzfsd_main.cc}
+SRCS.zfsd_unittest+= libmocks.c zfsd_unittest.cc
+SRCS=
+
+# Use #include <zfsd/xxx.h> in test programs.
+INCFLAGS+= -I${.CURDIR}/../..
+
+.if defined(DESTDIR)
+INCFLAGS+= -I${DESTDIR}/usr/include
+LIBRARY_PATH= ${DESTDIR}/lib:${DESTDIR}/usr/lib
+LDFLAGS.zfsd_unittest+= -L${DESTDIR}/lib -L${DESTDIR}/usr/lib
+.elif defined(WORLDTMP)
+INCFLAGS+= -I${WORLDTMP}/usr/include
+LIBRARY_PATH= ${WORLDTMP}/lib:${WORLDTMP}/usr/lib
+LDFLAGS.zfsd_unittest+= -L${WORLDTMP}/lib -L${WORLDTMP}/usr/lib
+.else
+LIBRARY_PATH=
+.endif
+
+# Googletest options
+LOCALBASE?= /usr/local
+INCFLAGS+= -I${LOCALBASE}/include -D_THREAD_SAFE -pthread
+LDFLAGS.zfsd_unittest+= -L${LOCALBASE}/lib -D_THREAD_SAFE -pthread
+LDADD.zfsd_unittest+= ${LOCALBASE}/lib/libgtest.a
+
+# GoogleMock options
+LDADD.zfsd_unittest+= ${LOCALBASE}/lib/libgmock.a ${LOCALBASE}/lib/libgmock_main.a
+
+# Googlemock fails if we don't have this line
+# https://groups.google.com/forum/#!msg/googletestframework/h8ixEPCFm0o/amwfu4xGJb0J
+CFLAGS.zfsd_unittest+= -DGTEST_HAS_PTHREAD
+
+# Install the tests
+TESTSBASE?= /usr/tests
+
+.include <bsd.test.mk>
diff --git a/cddl/usr.sbin/zfsd/tests/libmocks.c b/cddl/usr.sbin/zfsd/tests/libmocks.c
new file mode 100644
index 0000000..e3c90a4
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/tests/libmocks.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2012 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "libmocks.h"
+
+/*
+ * This file mocks shared library functions that are used by zfsd. Every
+ * function present will be used for all tests in all test suites instead of the
+ * normal function.
+ */
+
+int syslog_last_priority;
+char syslog_last_message[4096];
+void syslog(int priority, const char* message, ...) {
+ va_list ap;
+
+ syslog_last_priority = priority;
+ va_start(ap, message);
+ vsnprintf(syslog_last_message, 4096, message, ap);
+ va_end(ap);
+}
+
+int zpool_iter(libzfs_handle_t* handle, zpool_iter_f iter, void* arg) {
+ return (0);
+}
diff --git a/cddl/usr.sbin/zfsd/tests/libmocks.h b/cddl/usr.sbin/zfsd/tests/libmocks.h
new file mode 100644
index 0000000..130f438
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/tests/libmocks.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2012 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LIBMOCKS_H_
+#define _LIBMOCKS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct libzfs_handle;
+typedef struct libzfs_handle libzfs_handle_t;
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+typedef int (*zpool_iter_f)(zpool_handle_t *, void *);
+
+void syslog(int priority, const char* message, ...);
+int zpool_iter(libzfs_handle_t*, zpool_iter_f, void*);
+
+extern int syslog_last_priority;
+extern char syslog_last_message[4096];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc
new file mode 100644
index 0000000..9a2384a
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc
@@ -0,0 +1,771 @@
+/*-
+ * Copyright (c) 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ */
+#include <sys/cdefs.h>
+
+#include <stdarg.h>
+#include <syslog.h>
+
+#include <libnvpair.h>
+#include <libzfs.h>
+
+#include <list>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include <zfsd/callout.h>
+#include <zfsd/vdev_iterator.h>
+#include <zfsd/zfsd_event.h>
+#include <zfsd/case_file.h>
+#include <zfsd/vdev.h>
+#include <zfsd/zfsd.h>
+#include <zfsd/zfsd_exception.h>
+#include <zfsd/zpool_list.h>
+
+#include "libmocks.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+using std::string;
+using std::stringstream;
+
+using DevdCtl::Event;
+using DevdCtl::EventBuffer;
+using DevdCtl::EventFactory;
+using DevdCtl::EventList;
+using DevdCtl::Guid;
+using DevdCtl::NVPairMap;
+
+/* redefine zpool_handle here because libzfs_impl.h is not includable */
+struct zpool_handle
+{
+ libzfs_handle_t *zpool_hdl;
+ zpool_handle_t *zpool_next;
+ char zpool_name[ZPOOL_MAXNAMELEN];
+ int zpool_state;
+ size_t zpool_config_size;
+ nvlist_t *zpool_config;
+ nvlist_t *zpool_old_config;
+ nvlist_t *zpool_props;
+ diskaddr_t zpool_start_block;
+};
+
+class MockZfsEvent : public ZfsEvent
+{
+public:
+ MockZfsEvent(Event::Type, NVPairMap&, const string&);
+ virtual ~MockZfsEvent() {}
+
+ static BuildMethod MockZfsEventBuilder;
+
+ MOCK_CONST_METHOD0(ProcessPoolEvent, void());
+
+ static EventFactory::Record s_buildRecords[];
+};
+
+EventFactory::Record MockZfsEvent::s_buildRecords[] =
+{
+ { Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder }
+};
+
+MockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map,
+ const string& str)
+ : ZfsEvent(type, map, str)
+{
+}
+
+Event *
+MockZfsEvent::MockZfsEventBuilder(Event::Type type,
+ NVPairMap &nvpairs,
+ const string &eventString)
+{
+ return (new MockZfsEvent(type, nvpairs, eventString));
+}
+
+/*
+ * A dummy Vdev class used for testing other classes
+ */
+class MockVdev : public Vdev
+{
+public:
+ MockVdev(nvlist_t *vdevConfig);
+ virtual ~MockVdev() {}
+
+ MOCK_CONST_METHOD0(GUID, Guid());
+ MOCK_CONST_METHOD0(PoolGUID, Guid());
+ MOCK_CONST_METHOD0(State, vdev_state());
+ MOCK_CONST_METHOD0(PhysicalPath, string());
+};
+
+MockVdev::MockVdev(nvlist_t *vdevConfig)
+ : Vdev(vdevConfig)
+{
+}
+
+/*
+ * A CaseFile class with side effects removed, for testing
+ */
+class TestableCaseFile : public CaseFile
+{
+public:
+ static TestableCaseFile &Create(Vdev &vdev);
+ TestableCaseFile(Vdev &vdev);
+ virtual ~TestableCaseFile() {}
+
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD1(RegisterCallout, void(const Event &event));
+ MOCK_METHOD0(RefreshVdevState, bool());
+ MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event));
+
+ bool RealReEvaluate(const ZfsEvent &event)
+ {
+ return (CaseFile::ReEvaluate(event));
+ }
+
+ /*
+ * This splices the event lists, a procedure that would normally be done
+ * by OnGracePeriodEnded, but we don't necessarily call that in the
+ * unit tests
+ */
+ void SpliceEvents();
+
+ /*
+ * Used by some of our expectations. CaseFile does not publicize this
+ */
+ static int getActiveCases()
+ {
+ return (s_activeCases.size());
+ }
+};
+
+TestableCaseFile::TestableCaseFile(Vdev &vdev)
+ : CaseFile(vdev)
+{
+}
+
+TestableCaseFile &
+TestableCaseFile::Create(Vdev &vdev)
+{
+ TestableCaseFile *newCase;
+ newCase = new TestableCaseFile(vdev);
+ return (*newCase);
+}
+
+void
+TestableCaseFile::SpliceEvents()
+{
+ m_events.splice(m_events.begin(), m_tentativeEvents);
+}
+
+
+/*
+ * Test class ZfsdException
+ */
+class ZfsdExceptionTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_string(poolConfig,
+ ZPOOL_CONFIG_POOL_NAME, "unit_test_pool"));
+ ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
+ ZPOOL_CONFIG_POOL_GUID, 0x1234));
+
+ ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(vdevConfig,
+ ZPOOL_CONFIG_GUID, 0x5678));
+ bzero(&poolHandle, sizeof(poolHandle));
+ poolHandle.zpool_config = poolConfig;
+ }
+
+ virtual void TearDown()
+ {
+ nvlist_free(poolConfig);
+ nvlist_free(vdevConfig);
+ }
+
+ nvlist_t *poolConfig;
+ nvlist_t *vdevConfig;
+ zpool_handle_t poolHandle;
+};
+
+TEST_F(ZfsdExceptionTest, StringConstructorNull)
+{
+ ZfsdException ze("");
+ EXPECT_STREQ("", ze.GetString().c_str());
+}
+
+TEST_F(ZfsdExceptionTest, StringConstructorFormatted)
+{
+ ZfsdException ze(" %d %s", 55, "hello world");
+ EXPECT_STREQ(" 55 hello world", ze.GetString().c_str());
+}
+
+TEST_F(ZfsdExceptionTest, LogSimple)
+{
+ ZfsdException ze("unit test w/o vdev or pool");
+ ze.Log();
+ EXPECT_EQ(LOG_ERR, syslog_last_priority);
+ EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message);
+}
+
+TEST_F(ZfsdExceptionTest, Pool)
+{
+ const char msg[] = "Exception with pool name";
+ char expected[4096];
+ sprintf(expected, "Pool unit_test_pool: %s\n", msg);
+ ZfsdException ze(poolConfig, msg);
+ ze.Log();
+ EXPECT_STREQ(expected, syslog_last_message);
+}
+
+TEST_F(ZfsdExceptionTest, PoolHandle)
+{
+ const char msg[] = "Exception with pool handle";
+ char expected[4096];
+ sprintf(expected, "Pool unit_test_pool: %s\n", msg);
+ ZfsdException ze(&poolHandle, msg);
+ ze.Log();
+ EXPECT_STREQ(expected, syslog_last_message);
+}
+
+/*
+ * Test class Vdev
+ */
+class VdevTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig,
+ ZPOOL_CONFIG_POOL_GUID,
+ 0x1234));
+
+ ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID,
+ 0x5678));
+ }
+
+ virtual void TearDown()
+ {
+ nvlist_free(m_poolConfig);
+ nvlist_free(m_vdevConfig);
+ }
+
+ nvlist_t *m_poolConfig;
+ nvlist_t *m_vdevConfig;
+};
+
+
+TEST_F(VdevTest, StateFromConfig)
+{
+ vdev_stat_t vs;
+
+ vs.vs_state = VDEV_STATE_OFFLINE;
+
+ ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig,
+ ZPOOL_CONFIG_VDEV_STATS,
+ (uint64_t*)&vs,
+ sizeof(vs) / sizeof(uint64_t)));
+
+ Vdev vdev(m_poolConfig, m_vdevConfig);
+
+ EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State());
+}
+
+TEST_F(VdevTest, StateFaulted)
+{
+ ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1));
+
+ Vdev vdev(m_poolConfig, m_vdevConfig);
+
+ EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State());
+}
+
+/*
+ * Test that we can construct a Vdev from the label information that is stored
+ * on an available spare drive
+ */
+TEST_F(VdevTest, ConstructAvailSpare)
+{
+ nvlist_t *labelConfig;
+
+ ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
+ 1948339428197961030));
+ ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
+ POOL_STATE_SPARE));
+
+ EXPECT_NO_THROW(Vdev vdev(labelConfig));
+
+ nvlist_free(labelConfig);
+}
+
+/* Available spares will always show the HEALTHY state */
+TEST_F(VdevTest, AvailSpareState) {
+ nvlist_t *labelConfig;
+
+ ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
+ ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
+ 1948339428197961030));
+ ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
+ POOL_STATE_SPARE));
+
+ Vdev vdev(labelConfig);
+ EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State());
+
+ nvlist_free(labelConfig);
+}
+
+/* Test the Vdev::IsSpare method */
+TEST_F(VdevTest, IsSpare) {
+ Vdev notSpare(m_poolConfig, m_vdevConfig);
+ EXPECT_EQ(false, notSpare.IsSpare());
+
+ ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1));
+ Vdev isSpare(m_poolConfig, m_vdevConfig);
+ EXPECT_EQ(true, isSpare.IsSpare());
+}
+
+/*
+ * Test class ZFSEvent
+ */
+class ZfsEventTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ m_eventFactory = new EventFactory();
+ m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
+ NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
+
+ m_event = NULL;
+ }
+
+ virtual void TearDown()
+ {
+ delete m_eventFactory;
+ delete m_event;
+ }
+
+ EventFactory *m_eventFactory;
+ Event *m_event;
+};
+
+TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled)
+{
+ string evString("!system=ZFS "
+ "subsystem=ZFS "
+ "type=misc.fs.zfs.vdev_remove "
+ "pool_name=foo "
+ "pool_guid=9756779504028057996 "
+ "vdev_guid=1631193447431603339 "
+ "vdev_path=/dev/da1 "
+ "timestamp=1348871594");
+ m_event = Event::CreateEvent(*m_eventFactory, evString);
+ MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event);
+
+ EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1);
+ mock_event->Process();
+}
+
+/*
+ * Test class CaseFile
+ */
+
+class CaseFileTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ m_eventFactory = new EventFactory();
+ m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
+ NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
+
+ m_event = NULL;
+
+ nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
+ ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
+ ZPOOL_CONFIG_GUID, 0xbeef));
+ m_vdev = new MockVdev(m_vdevConfig);
+ ON_CALL(*m_vdev, GUID())
+ .WillByDefault(::testing::Return(Guid(123)));
+ ON_CALL(*m_vdev, PoolGUID())
+ .WillByDefault(::testing::Return(Guid(456)));
+ ON_CALL(*m_vdev, State())
+ .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
+ m_caseFile = &TestableCaseFile::Create(*m_vdev);
+ ON_CALL(*m_caseFile, ReEvaluate(::testing::_))
+ .WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate));
+ return;
+ }
+
+ virtual void TearDown()
+ {
+ delete m_caseFile;
+ nvlist_free(m_vdevConfig);
+ delete m_vdev;
+ delete m_event;
+ delete m_eventFactory;
+ }
+
+ nvlist_t *m_vdevConfig;
+ MockVdev *m_vdev;
+ TestableCaseFile *m_caseFile;
+ Event *m_event;
+ EventFactory *m_eventFactory;
+};
+
+/*
+ * A Vdev with no events should not be degraded or faulted
+ */
+TEST_F(CaseFileTest, HealthyVdev)
+{
+ EXPECT_FALSE(m_caseFile->ShouldDegrade());
+ EXPECT_FALSE(m_caseFile->ShouldFault());
+}
+
+/*
+ * A Vdev with only one event should not be degraded or faulted
+ * For performance reasons, RefreshVdevState should not be called.
+ */
+TEST_F(CaseFileTest, HealthyishVdev)
+{
+ string evString("!system=ZFS "
+ "class=ereport.fs.zfs.io "
+ "ena=12091638756982918145 "
+ "parent_guid=13237004955564865395 "
+ "parent_type=raidz "
+ "pool=testpool.4415 "
+ "pool_context=0 "
+ "pool_failmode=wait "
+ "pool_guid=456 "
+ "subsystem=ZFS "
+ "timestamp=1348867914 "
+ "type=ereport.fs.zfs.io "
+ "vdev_guid=123 "
+ "vdev_path=/dev/da400 "
+ "vdev_type=disk "
+ "zio_blkid=622 "
+ "zio_err=1 "
+ "zio_level=-2 "
+ "zio_object=0 "
+ "zio_objset=37 "
+ "zio_offset=25598976 "
+ "zio_size=1024");
+ m_event = Event::CreateEvent(*m_eventFactory, evString);
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
+
+ EXPECT_CALL(*m_caseFile, RefreshVdevState())
+ .Times(::testing::Exactly(0));
+ EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
+ EXPECT_FALSE(m_caseFile->ShouldDegrade());
+ EXPECT_FALSE(m_caseFile->ShouldFault());
+}
+
+/* The case file should be closed when its pool is destroyed */
+TEST_F(CaseFileTest, PoolDestroy)
+{
+ string evString("!system=ZFS "
+ "pool_name=testpool.4415 "
+ "pool_guid=456 "
+ "subsystem=ZFS "
+ "timestamp=1348867914 "
+ "type=misc.fs.zfs.pool_destroy ");
+ m_event = Event::CreateEvent(*m_eventFactory, evString);
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
+ EXPECT_CALL(*m_caseFile, Close());
+ EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
+}
+
+/*
+ * A Vdev with a very large number of IO errors should fault
+ * For performance reasons, RefreshVdevState should be called at most once
+ */
+TEST_F(CaseFileTest, VeryManyIOErrors)
+{
+ EXPECT_CALL(*m_caseFile, RefreshVdevState())
+ .Times(::testing::AtMost(1))
+ .WillRepeatedly(::testing::Return(true));
+
+ for(int i=0; i<100; i++) {
+ stringstream evStringStream;
+ evStringStream <<
+ "!system=ZFS "
+ "class=ereport.fs.zfs.io "
+ "ena=12091638756982918145 "
+ "parent_guid=13237004955564865395 "
+ "parent_type=raidz "
+ "pool=testpool.4415 "
+ "pool_context=0 "
+ "pool_failmode=wait "
+ "pool_guid=456 "
+ "subsystem=ZFS "
+ "timestamp=";
+ evStringStream << i << " ";
+ evStringStream <<
+ "type=ereport.fs.zfs.io "
+ "vdev_guid=123 "
+ "vdev_path=/dev/da400 "
+ "vdev_type=disk "
+ "zio_blkid=622 "
+ "zio_err=1 "
+ "zio_level=-2 "
+ "zio_object=0 "
+ "zio_objset=37 "
+ "zio_offset=25598976 "
+ "zio_size=1024";
+ Event *event(Event::CreateEvent(*m_eventFactory,
+ evStringStream.str()));
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
+ EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
+ delete event;
+ }
+
+ m_caseFile->SpliceEvents();
+ EXPECT_FALSE(m_caseFile->ShouldDegrade());
+ EXPECT_TRUE(m_caseFile->ShouldFault());
+}
+
+/*
+ * A Vdev with a very large number of checksum errors should degrade
+ * For performance reasons, RefreshVdevState should be called at most once
+ */
+TEST_F(CaseFileTest, VeryManyChecksumErrors)
+{
+ EXPECT_CALL(*m_caseFile, RefreshVdevState())
+ .Times(::testing::AtMost(1))
+ .WillRepeatedly(::testing::Return(true));
+
+ for(int i=0; i<100; i++) {
+ stringstream evStringStream;
+ evStringStream <<
+ "!system=ZFS "
+ "bad_cleared_bits=03000000000000803f50b00000000000 "
+ "bad_range_clears=0000000e "
+ "bad_range_sets=00000000 "
+ "bad_ranges=0000000000000010 "
+ "bad_ranges_min_gap=8 "
+ "bad_set_bits=00000000000000000000000000000000 "
+ "class=ereport.fs.zfs.checksum "
+ "ena=12272856582652437505 "
+ "parent_guid=5838204195352909894 "
+ "parent_type=raidz pool=testpool.7640 "
+ "pool_context=0 "
+ "pool_failmode=wait "
+ "pool_guid=456 "
+ "subsystem=ZFS timestamp=";
+ evStringStream << i << " ";
+ evStringStream <<
+ "type=ereport.fs.zfs.checksum "
+ "vdev_guid=123 "
+ "vdev_path=/mnt/tmp/file1.7702 "
+ "vdev_type=file "
+ "zio_blkid=0 "
+ "zio_err=0 "
+ "zio_level=0 "
+ "zio_object=3 "
+ "zio_objset=0 "
+ "zio_offset=16896 "
+ "zio_size=512";
+ Event *event(Event::CreateEvent(*m_eventFactory,
+ evStringStream.str()));
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
+ EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
+ delete event;
+ }
+
+ m_caseFile->SpliceEvents();
+ EXPECT_TRUE(m_caseFile->ShouldDegrade());
+ EXPECT_FALSE(m_caseFile->ShouldFault());
+}
+
+/*
+ * Test CaseFile::ReEvaluateByGuid
+ */
+class ReEvaluateByGuidTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ m_eventFactory = new EventFactory();
+ m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
+ NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
+ m_event = Event::CreateEvent(*m_eventFactory, s_evString);
+ nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
+ ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
+ ZPOOL_CONFIG_GUID, 0xbeef));
+ m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
+ m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
+ ON_CALL(*m_vdev456, GUID())
+ .WillByDefault(::testing::Return(Guid(123)));
+ ON_CALL(*m_vdev456, PoolGUID())
+ .WillByDefault(::testing::Return(Guid(456)));
+ ON_CALL(*m_vdev456, State())
+ .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
+ ON_CALL(*m_vdev789, GUID())
+ .WillByDefault(::testing::Return(Guid(123)));
+ ON_CALL(*m_vdev789, PoolGUID())
+ .WillByDefault(::testing::Return(Guid(789)));
+ ON_CALL(*m_vdev789, State())
+ .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
+ m_caseFile456 = NULL;
+ m_caseFile789 = NULL;
+ return;
+ }
+
+ virtual void TearDown()
+ {
+ delete m_caseFile456;
+ delete m_caseFile789;
+ nvlist_free(m_vdevConfig);
+ delete m_vdev456;
+ delete m_vdev789;
+ delete m_event;
+ delete m_eventFactory;
+ }
+
+ static string s_evString;
+ nvlist_t *m_vdevConfig;
+ ::testing::NiceMock<MockVdev> *m_vdev456;
+ ::testing::NiceMock<MockVdev> *m_vdev789;
+ TestableCaseFile *m_caseFile456;
+ TestableCaseFile *m_caseFile789;
+ Event *m_event;
+ EventFactory *m_eventFactory;
+};
+
+string ReEvaluateByGuidTest::s_evString(
+ "!system=ZFS "
+ "pool_guid=16271873792808333580 "
+ "pool_name=foo "
+ "subsystem=ZFS "
+ "timestamp=1360620391 "
+ "type=misc.fs.zfs.config_sync");
+
+
+/*
+ * Test the ReEvaluateByGuid method on an empty list of casefiles.
+ * We must create one event, even though it never gets used, because it will
+ * be passed by reference to ReEvaluateByGuid
+ */
+TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty)
+{
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
+
+ EXPECT_EQ(0, TestableCaseFile::getActiveCases());
+ CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
+ EXPECT_EQ(0, TestableCaseFile::getActiveCases());
+}
+
+/*
+ * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
+ * one CaseFile, which doesn't match the criteria
+ */
+TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse)
+{
+ m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
+
+ EXPECT_EQ(1, TestableCaseFile::getActiveCases());
+ EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(0));
+ CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event);
+ EXPECT_EQ(1, TestableCaseFile::getActiveCases());
+}
+
+/*
+ * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
+ * one CaseFile, which does match the criteria
+ */
+TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue)
+{
+ m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
+
+ EXPECT_EQ(1, TestableCaseFile::getActiveCases());
+ EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(1))
+ .WillRepeatedly(::testing::Return(false));
+ CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
+ EXPECT_EQ(1, TestableCaseFile::getActiveCases());
+}
+
+/*
+ * Test the ReEvaluateByGuid method on a long list of CaseFiles that contains a
+ * few cases which meet the criteria
+ */
+TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
+{
+ TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456);
+ TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789);
+ TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456);
+ TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789);
+ TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789);
+ ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
+
+ EXPECT_EQ(5, TestableCaseFile::getActiveCases());
+ EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(1))
+ .WillRepeatedly(::testing::Return(false));
+ EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(1))
+ .WillRepeatedly(::testing::Return(false));
+ EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(0));
+ EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(0));
+ EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_))
+ .Times(::testing::Exactly(0));
+ CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
+ EXPECT_EQ(5, TestableCaseFile::getActiveCases());
+ delete CaseFile1;
+ delete CaseFile2;
+ delete CaseFile3;
+ delete CaseFile4;
+ delete CaseFile5;
+}
diff --git a/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp
new file mode 100644
index 0000000..138ef69
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/tests/zfsd_unittest.supp
@@ -0,0 +1,138 @@
+#-
+# Copyright (c) 2012 Spectra Logic Corporation
+# 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,
+# without modification.
+# 2. Redistributions in binary form must reproduce at minimum a disclaimer
+# substantially similar to the "NO WARRANTY" disclaimer below
+# ("Disclaimer") and any redistribution must be conditioned upon
+# including a substantially similar Disclaimer requirement for further
+# binary redistribution.
+#
+# NO WARRANTY
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+#
+# Authors: Alan Somers (Spectra Logic Corporation)
+#
+# $FreeBSD$
+
+
+# This is a valgrind suppression file used for running zfsd_unittest with
+# valgrind. It suppress spurious errors generated by the googletest and
+# googlemock libraries.
+#
+# To use, do:
+# valgrind --suppressions=$PWD/zfsd_unittest.supp ./zfsd_unittest
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Free
+ fun:free
+ ...
+ fun:__cxa_finalize
+ fun:exit
+ fun:(below main)
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Free
+ fun:free
+ ...
+ fun:_ZN7testing8internal27PrettyUnitTestResultPrinter*
+ ...
+ ...
+ fun:main
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Free
+ fun:free
+ fun:_ZN7testing*
+ ...
+ fun:main
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Free
+ fun:free
+ ...
+ fun:_Z41__static_initialization_and_destruction_0ii
+ ...
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Free
+ fun:free
+ ...
+ fun:_ZN7testing8internal8MockSpec*
+ ...
+ fun:_ZN7testing4Test3RunEv
+ fun:_ZN7testing8internal12TestInfoImpl3RunEv
+ fun:_ZN7testing8TestCase3RunEv
+ fun:_ZN7testing8internal12UnitTestImpl11RunAllTestsEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Free
+ fun:free
+ ...
+ fun:_ZN7testing8internal14FunctionMocker*
+ ...
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Cond
+ obj:/lib/libc.so.7
+ obj:/lib/libc.so.7
+ fun:snprintf
+ fun:_ZN7testing45_GLOBAL__N_src_gmock_all.cc_00000000_917CAD5926PrintByteSegmentInObjectToEPKhmmPSo
+ fun:_ZN7testing9internal220PrintBytesInObjectToEPKhmPSo
+ fun:_ZN7testing9internal220TypeWithoutFormatterI8ZfsEventLb0EE10PrintValueERKS2_PSo
+ fun:_ZN7testing9internal2lsIcSt11char_traitsIcE8ZfsEventEERSt13basic_ostreamIT_T0_ES9_RKT1_
+ fun:_ZN16testing_internal26DefaultPrintNonContainerToI8ZfsEventEEvRKT_PSo
+ fun:_ZN7testing8internal14DefaultPrintToI8ZfsEventEEvcNS0_13bool_constantILb0EEERKT_PSo
+ fun:_ZN7testing8internal7PrintToI8ZfsEventEEvRKT_PSo
+ fun:_ZN7testing8internal16UniversalPrinterIK8ZfsEventE5PrintERS3_PSo
+ fun:_ZN7testing8internal16UniversalPrinterIRK8ZfsEventE5PrintES4_PSo
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Cond
+ ...
+ fun:snprintf
+ ...
+ fun:_ZN7testing9internal220PrintBytesInObjectToEPKhmPSo
+ ...
+}
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Value8
+ ...
+ fun:snprintf
+ ...
+ fun:_ZN7testing9internal220PrintBytesInObjectToEPKhmPSo
+ ...
+}
+
diff --git a/cddl/usr.sbin/zfsd/vdev.cc b/cddl/usr.sbin/zfsd/vdev.cc
new file mode 100644
index 0000000..687b064
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/vdev.cc
@@ -0,0 +1,357 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file vdev.cc
+ *
+ * Implementation of the Vdev class.
+ */
+#include <syslog.h>
+#include <sys/cdefs.h>
+#include <sys/fs/zfs.h>
+
+#include <libzfs.h>
+/*
+ * Undefine flush, defined by cpufunc.h on sparc64, because it conflicts with
+ * C++ flush methods
+ */
+#undef flush
+
+#include <list>
+#include <map>
+#include <string>
+#include <sstream>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include "vdev.h"
+#include "vdev_iterator.h"
+#include "zfsd.h"
+#include "zfsd_exception.h"
+#include "zpool_list.h"
+
+__FBSDID("$FreeBSD$");
+/*============================ Namespace Control =============================*/
+using std::string;
+using std::stringstream;
+
+//- Special objects -----------------------------------------------------------
+Vdev NonexistentVdev;
+
+//- Vdev Inline Public Methods ------------------------------------------------
+/*=========================== Class Implementations ==========================*/
+/*----------------------------------- Vdev -----------------------------------*/
+
+/* Special constructor for NonexistentVdev. */
+Vdev::Vdev()
+ : m_poolConfig(NULL),
+ m_config(NULL)
+{}
+
+bool
+Vdev::VdevLookupPoolGuid()
+{
+ uint64_t guid;
+ if (nvlist_lookup_uint64(m_poolConfig, ZPOOL_CONFIG_POOL_GUID, &guid))
+ return (false);
+ m_poolGUID = guid;
+ return (true);
+}
+
+void
+Vdev::VdevLookupGuid()
+{
+ uint64_t guid;
+ if (nvlist_lookup_uint64(m_config, ZPOOL_CONFIG_GUID, &guid) != 0)
+ throw ZfsdException("Unable to extract vdev GUID "
+ "from vdev config data.");
+ m_vdevGUID = guid;
+}
+
+Vdev::Vdev(zpool_handle_t *pool, nvlist_t *config)
+ : m_poolConfig(zpool_get_config(pool, NULL)),
+ m_config(config)
+{
+ if (!VdevLookupPoolGuid())
+ throw ZfsdException("Can't extract pool GUID from handle.");
+ VdevLookupGuid();
+}
+
+Vdev::Vdev(nvlist_t *poolConfig, nvlist_t *config)
+ : m_poolConfig(poolConfig),
+ m_config(config)
+{
+ if (!VdevLookupPoolGuid())
+ throw ZfsdException("Can't extract pool GUID from config.");
+ VdevLookupGuid();
+}
+
+Vdev::Vdev(nvlist_t *labelConfig)
+ : m_poolConfig(labelConfig),
+ m_config(labelConfig)
+{
+ /*
+ * Spares do not have a Pool GUID. Tolerate its absence.
+ * Code accessing this Vdev in a context where the Pool GUID is
+ * required will find it invalid (as it is upon Vdev construction)
+ * and act accordingly.
+ */
+ (void) VdevLookupPoolGuid();
+ VdevLookupGuid();
+
+ try {
+ m_config = VdevIterator(labelConfig).Find(m_vdevGUID);
+ } catch (const ZfsdException &exp) {
+ /*
+ * When reading a spare's label, it is normal not to find
+ * a list of vdevs
+ */
+ m_config = NULL;
+ }
+}
+
+bool
+Vdev::IsSpare() const
+{
+ uint64_t is_spare(0);
+
+ if (m_config == NULL)
+ return (false);
+
+ (void)nvlist_lookup_uint64(m_config, ZPOOL_CONFIG_IS_SPARE, &is_spare);
+ return (bool(is_spare));
+}
+
+vdev_state
+Vdev::State() const
+{
+ uint64_t *nvlist_array;
+ vdev_stat_t *vs;
+ uint_t vsc;
+
+ if (m_config == NULL) {
+ /*
+ * If we couldn't find the list of vdevs, that normally means
+ * that this is an available hotspare. In that case, we will
+ * presume it to be healthy. Even if this spare had formerly
+ * been in use, been degraded, and been replaced, the act of
+ * replacement wipes the degraded bit from the label. So we
+ * have no choice but to presume that it is healthy.
+ */
+ return (VDEV_STATE_HEALTHY);
+ }
+
+ if (nvlist_lookup_uint64_array(m_config, ZPOOL_CONFIG_VDEV_STATS,
+ &nvlist_array, &vsc) == 0) {
+ vs = reinterpret_cast<vdev_stat_t *>(nvlist_array);
+ return (static_cast<vdev_state>(vs->vs_state));
+ }
+
+ /*
+ * Stats are not available. This vdev was created from a label.
+ * Synthesize a state based on available data.
+ */
+ uint64_t faulted(0);
+ uint64_t degraded(0);
+ (void)nvlist_lookup_uint64(m_config, ZPOOL_CONFIG_FAULTED, &faulted);
+ (void)nvlist_lookup_uint64(m_config, ZPOOL_CONFIG_DEGRADED, &degraded);
+ if (faulted)
+ return (VDEV_STATE_FAULTED);
+ if (degraded)
+ return (VDEV_STATE_DEGRADED);
+ return (VDEV_STATE_HEALTHY);
+}
+
+std::list<Vdev>
+Vdev::Children()
+{
+ nvlist_t **vdevChildren;
+ int result;
+ u_int numChildren;
+ std::list<Vdev> children;
+
+ if (m_poolConfig == NULL || m_config == NULL)
+ return (children);
+
+ result = nvlist_lookup_nvlist_array(m_config,
+ ZPOOL_CONFIG_CHILDREN, &vdevChildren, &numChildren);
+ if (result != 0)
+ return (children);
+
+ for (u_int c = 0;c < numChildren; c++)
+ children.push_back(Vdev(m_poolConfig, vdevChildren[c]));
+
+ return (children);
+}
+
+Vdev
+Vdev::RootVdev()
+{
+ nvlist_t *rootVdev;
+
+ if (m_poolConfig == NULL)
+ return (NonexistentVdev);
+
+ if (nvlist_lookup_nvlist(m_poolConfig, ZPOOL_CONFIG_VDEV_TREE,
+ &rootVdev) != 0)
+ return (NonexistentVdev);
+ return (Vdev(m_poolConfig, rootVdev));
+}
+
+/*
+ * Find our parent. This requires doing a traversal of the config; we can't
+ * cache it as leaf vdevs may change their pool config location (spare,
+ * replacing, mirror, etc).
+ */
+Vdev
+Vdev::Parent()
+{
+ std::list<Vdev> to_examine;
+ std::list<Vdev> children;
+ std::list<Vdev>::iterator children_it;
+
+ to_examine.push_back(RootVdev());
+ for (;;) {
+ if (to_examine.empty())
+ return (NonexistentVdev);
+ Vdev vd = to_examine.front();
+ if (vd.DoesNotExist())
+ return (NonexistentVdev);
+ to_examine.pop_front();
+ children = vd.Children();
+ children_it = children.begin();
+ for (;children_it != children.end(); children_it++) {
+ Vdev child = *children_it;
+
+ if (child.GUID() == GUID())
+ return (vd);
+ to_examine.push_front(child);
+ }
+ }
+}
+
+bool
+Vdev::IsAvailableSpare() const
+{
+ /* If we have a pool guid, we cannot be an available spare. */
+ if (PoolGUID())
+ return (false);
+
+ return (true);
+}
+
+bool
+Vdev::IsSpare()
+{
+ uint64_t spare;
+ if (nvlist_lookup_uint64(m_config, ZPOOL_CONFIG_IS_SPARE, &spare) != 0)
+ return (false);
+ return (spare != 0);
+}
+
+bool
+Vdev::IsActiveSpare() const
+{
+ vdev_stat_t *vs;
+ uint_t c;
+
+ if (m_poolConfig == NULL)
+ return (false);
+
+ (void) nvlist_lookup_uint64_array(m_config, ZPOOL_CONFIG_VDEV_STATS,
+ reinterpret_cast<uint64_t **>(&vs), &c);
+ if (vs == NULL || vs->vs_aux != VDEV_AUX_SPARED)
+ return (false);
+ return (true);
+}
+
+bool
+Vdev::IsResilvering() const
+{
+ pool_scan_stat_t *ps = NULL;
+ uint_t c;
+
+ if (State() != VDEV_STATE_HEALTHY)
+ return (false);
+
+ (void) nvlist_lookup_uint64_array(m_config, ZPOOL_CONFIG_SCAN_STATS,
+ reinterpret_cast<uint64_t **>(&ps), &c);
+ if (ps == NULL || ps->pss_func != POOL_SCAN_RESILVER)
+ return (false);
+ return (true);
+}
+
+string
+Vdev::GUIDString() const
+{
+ stringstream vdevGUIDString;
+
+ vdevGUIDString << GUID();
+ return (vdevGUIDString.str());
+}
+
+string
+Vdev::Name(zpool_handle_t *zhp, bool verbose) const
+{
+ return (zpool_vdev_name(g_zfsHandle, zhp, m_config,
+ verbose ? B_TRUE : B_FALSE));
+}
+
+string
+Vdev::Path() const
+{
+ char *path(NULL);
+
+ if ((m_config != NULL)
+ && (nvlist_lookup_string(m_config, ZPOOL_CONFIG_PATH, &path) == 0))
+ return (path);
+
+ return ("");
+}
+
+string
+Vdev::PhysicalPath() const
+{
+ char *path(NULL);
+
+ if ((m_config != NULL) && (nvlist_lookup_string(m_config,
+ ZPOOL_CONFIG_PHYS_PATH, &path) == 0))
+ return (path);
+
+ return ("");
+}
diff --git a/cddl/usr.sbin/zfsd/vdev.h b/cddl/usr.sbin/zfsd/vdev.h
new file mode 100644
index 0000000..2fd4d4f
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/vdev.h
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file vdev.h
+ *
+ * Definition of the Vdev class.
+ *
+ * Header requirements:
+ *
+ * #include <string>
+ * #include <list>
+ *
+ * #include <devdctl/guid.h>
+ */
+#ifndef _VDEV_H_
+#define _VDEV_H_
+
+/*=========================== Forward Declarations ===========================*/
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+
+struct nvlist;
+typedef struct nvlist nvlist_t;
+
+/*============================= Class Definitions ============================*/
+/*----------------------------------- Vdev -----------------------------------*/
+/**
+ * \brief Wrapper class for a vdev's name/value configuration list
+ * simplifying access to commonly used vdev attributes.
+ */
+class Vdev
+{
+public:
+ /**
+ * \brief Instantiate a vdev object for a vdev that is a member
+ * of an imported pool.
+ *
+ * \param pool The pool object containing the vdev with
+ * configuration data provided in vdevConfig.
+ * \param vdevConfig Vdev configuration data.
+ *
+ * This method should be used whenever dealing with vdev's
+ * enumerated via the ZpoolList class. The in-core configuration
+ * data for a vdev does not contain all of the items found in
+ * the on-disk label. This requires the vdev class to augment
+ * the data in vdevConfig with data found in the pool object.
+ */
+ Vdev(zpool_handle_t *pool, nvlist_t *vdevConfig);
+
+ /**
+ * \brief Instantiate a vdev object for a vdev that is a member
+ * of a pool configuration.
+ *
+ * \param poolConfig The pool configuration containing the vdev
+ * configuration data provided in vdevConfig.
+ * \param vdevConfig Vdev configuration data.
+ *
+ * This method should be used whenever dealing with vdev's
+ * enumerated via the ZpoolList class. The in-core configuration
+ * data for a vdev does not contain all of the items found in
+ * the on-disk label. This requires the vdev class to augment
+ * the data in vdevConfig with data found in the pool object.
+ */
+ Vdev(nvlist_t *poolConfig, nvlist_t *vdevConfig);
+
+ /**
+ * \brief Instantiate a vdev object from a ZFS label stored on
+ * the device.
+ *
+ * \param vdevConfig The name/value list retrieved by reading
+ * the label information on a leaf vdev.
+ */
+ Vdev(nvlist_t *vdevConfig);
+
+ /**
+ * \brief No-op copy constructor for nonexistent vdevs.
+ */
+ Vdev();
+ bool DoesNotExist() const;
+
+ /**
+ * \brief Return a list of the vdev's children.
+ */
+ std::list<Vdev> Children();
+
+ virtual DevdCtl::Guid GUID() const;
+ bool IsSpare() const;
+ virtual DevdCtl::Guid PoolGUID() const;
+ virtual vdev_state State() const;
+ std::string Path() const;
+ virtual std::string PhysicalPath() const;
+ std::string GUIDString() const;
+ nvlist_t *PoolConfig() const;
+ nvlist_t *Config() const;
+ Vdev Parent();
+ Vdev RootVdev();
+ std::string Name(zpool_handle_t *, bool verbose) const;
+ bool IsSpare();
+ bool IsAvailableSpare() const;
+ bool IsActiveSpare() const;
+ bool IsResilvering() const;
+
+private:
+ void VdevLookupGuid();
+ bool VdevLookupPoolGuid();
+ DevdCtl::Guid m_poolGUID;
+ DevdCtl::Guid m_vdevGUID;
+ nvlist_t *m_poolConfig;
+ nvlist_t *m_config;
+};
+
+//- Special objects -----------------------------------------------------------
+extern Vdev NonexistentVdev;
+
+//- Vdev Inline Public Methods ------------------------------------------------
+inline DevdCtl::Guid
+Vdev::PoolGUID() const
+{
+ return (m_poolGUID);
+}
+
+inline DevdCtl::Guid
+Vdev::GUID() const
+{
+ return (m_vdevGUID);
+}
+
+inline nvlist_t *
+Vdev::PoolConfig() const
+{
+ return (m_poolConfig);
+}
+
+inline nvlist_t *
+Vdev::Config() const
+{
+ return (m_config);
+}
+
+inline bool
+Vdev::DoesNotExist() const
+{
+ return (m_config == NULL);
+}
+
+#endif /* _VDEV_H_ */
diff --git a/cddl/usr.sbin/zfsd/vdev_iterator.cc b/cddl/usr.sbin/zfsd/vdev_iterator.cc
new file mode 100644
index 0000000..07f19d2
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/vdev_iterator.cc
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file vdev_iterator.cc
+ *
+ * Implementation of the VdevIterator class.
+ */
+#include <sys/cdefs.h>
+#include <sys/fs/zfs.h>
+
+#include <stdint.h>
+#include <syslog.h>
+
+#include <libzfs.h>
+
+#include <list>
+#include <string>
+
+#include <devdctl/exception.h>
+#include <devdctl/guid.h>
+
+#include "vdev.h"
+#include "vdev_iterator.h"
+#include "zfsd_exception.h"
+
+/*============================ Namespace Control =============================*/
+using DevdCtl::Guid;
+
+/*=========================== Class Implementations ==========================*/
+/*------------------------------- VdevIterator -------------------------------*/
+VdevIterator::VdevIterator(zpool_handle_t *pool)
+ : m_poolConfig(zpool_get_config(pool, NULL))
+{
+ Reset();
+}
+
+VdevIterator::VdevIterator(nvlist_t *poolConfig)
+ : m_poolConfig(poolConfig)
+{
+ Reset();
+}
+
+void
+VdevIterator::Reset()
+{
+ nvlist_t *rootVdev;
+ int result;
+
+ result = nvlist_lookup_nvlist(m_poolConfig,
+ ZPOOL_CONFIG_VDEV_TREE,
+ &rootVdev);
+ if (result != 0)
+ throw ZfsdException(m_poolConfig, "Unable to extract "
+ "ZPOOL_CONFIG_VDEV_TREE from pool.");
+ m_vdevQueue.assign(1, rootVdev);
+}
+
+nvlist_t *
+VdevIterator::Next()
+{
+ nvlist_t *vdevConfig;
+
+ if (m_vdevQueue.empty())
+ return (NULL);
+
+ for (;;) {
+ nvlist_t **vdevChildren;
+ int result;
+ u_int numChildren;
+
+ vdevConfig = m_vdevQueue.front();
+ m_vdevQueue.pop_front();
+
+ /* Expand non-leaf vdevs. */
+ result = nvlist_lookup_nvlist_array(vdevConfig,
+ ZPOOL_CONFIG_CHILDREN,
+ &vdevChildren, &numChildren);
+ if (result != 0) {
+ /* leaf vdev */
+ break;
+ }
+
+ /*
+ * Insert children at the head of the queue to effect a
+ * depth first traversal of the tree.
+ */
+ m_vdevQueue.insert(m_vdevQueue.begin(), vdevChildren,
+ vdevChildren + numChildren);
+ }
+
+ return (vdevConfig);
+}
+
+void
+VdevIterator::Each(VdevCallback_t *callBack, void *callBackArg)
+{
+ nvlist_t *vdevConfig;
+
+ Reset();
+ while ((vdevConfig = Next()) != NULL) {
+ Vdev vdev(m_poolConfig, vdevConfig);
+
+ if (callBack(vdev, callBackArg))
+ break;
+ }
+}
+
+nvlist_t *
+VdevIterator::Find(Guid vdevGUID)
+{
+ nvlist_t *vdevConfig;
+
+ Reset();
+ while ((vdevConfig = Next()) != NULL) {
+ Vdev vdev(m_poolConfig, vdevConfig);
+
+ if (vdev.GUID() == vdevGUID)
+ return (vdevConfig);
+ }
+ return (NULL);
+}
diff --git a/cddl/usr.sbin/zfsd/vdev_iterator.h b/cddl/usr.sbin/zfsd/vdev_iterator.h
new file mode 100644
index 0000000..435582e
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/vdev_iterator.h
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file vdev_iterator.h
+ *
+ * VdevIterator class definition.
+ *
+ * Header requirements:
+ *
+ * #include <list>
+ */
+#ifndef _VDEV_ITERATOR_H_
+#define _VDEV_ITERATOR_H_
+
+/*=========================== Forward Declarations ===========================*/
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+
+struct nvlist;
+typedef struct nvlist nvlist_t;
+
+class Vdev;
+
+/*============================= Class Definitions ============================*/
+/*------------------------------- VdevIterator -------------------------------*/
+typedef bool VdevCallback_t(Vdev &vdev, void *cbArg);
+
+/**
+ * \brief VdevIterator provides mechanisms for traversing and searching
+ * the leaf vdevs contained in a ZFS pool configuration.
+ */
+class VdevIterator
+{
+public:
+ /**
+ * \brief Instantiate a VdevIterator for the given ZFS pool.
+ *
+ * \param pool The ZFS pool to traverse/search.
+ */
+ VdevIterator(zpool_handle_t *pool);
+
+ /**
+ * \brief Instantiate a VdevIterator for the given ZFS pool.
+ *
+ * \param poolConfig The configuration data for the ZFS pool
+ * to traverse/search.
+ */
+ VdevIterator(nvlist_t *poolConfig);
+
+ /**
+ * \brief Reset this iterator's cursor so that Next() will
+ * report the first member of the pool.
+ */
+ void Reset();
+
+ /**
+ * \brief Report the leaf vdev at this iterator's cursor and increment
+ * the cursor to the next leaf pool member.
+ */
+ nvlist_t *Next();
+
+ /**
+ * \brief Traverse the entire pool configuration starting its
+ * first member, returning a vdev object with the given
+ * vdev GUID if found.
+ *
+ * \param vdevGUID The vdev GUID of the vdev object to find.
+ *
+ * \return A Vdev object for the matching vdev if found. Otherwise
+ * NULL.
+ *
+ * Upon return, the VdevIterator's cursor points to the vdev just
+ * past the returned vdev or end() if no matching vdev is found.
+ */
+ nvlist_t *Find(DevdCtl::Guid vdevGUID);
+
+ /**
+ * \brief Perform the specified operation on each leaf member of
+ * a pool's vdev membership.
+ *
+ * \param cb Callback function to execute for each member.
+ * \param cbArg Argument to pass to cb.
+ */
+ void Each(VdevCallback_t *cb, void *cbArg);
+
+private:
+ nvlist_t *m_poolConfig;
+ std::list<nvlist_t *> m_vdevQueue;
+};
+
+#endif /* _VDEV_ITERATOR_H_ */
diff --git a/cddl/usr.sbin/zfsd/zfsd.8 b/cddl/usr.sbin/zfsd/zfsd.8
new file mode 100644
index 0000000..e4285da
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd.8
@@ -0,0 +1,157 @@
+.\"-
+.\" Copyright (c) 2016 Allan Jude
+.\" 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$
+.\"
+.Dd May 26, 2016
+.Dt ZFSD 8
+.Os
+.Sh NAME
+.Nm zfsd
+.Nd ZFS fault management daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Sh DESCRIPTION
+.Nm
+attempts to resolve ZFS faults that the kernel can't resolve by itself.
+It listens to
+.Xr devctl 4
+events, which are how the kernel notifies userland of events such as I/O
+errors and disk removals.
+.Nm
+attempts to resolve these faults by activating or deactivating hot spares
+and onlining offline vdevs.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl d
+Run in the foreground instead of daemonizing.
+.El
+.Pp
+System administrators never interact with
+.Nm
+directly.
+Instead, they control its behavior indirectly through zpool configuration.
+There are two ways to influence
+.Nm :
+assigning hotspares and setting pool properties.
+Currently, only the
+.Em autoreplace
+property has any effect.
+See
+.Xr zpool 8
+for details.
+.Pp
+.Nm
+will attempt to resolve the following types of fault:
+.Bl -tag -width a
+.It device removal
+When a leaf vdev disappears,
+.Nm
+will activate any available hotspare.
+.It device arrival
+When a new GEOM device appears,
+.Nm
+will attempt to read its ZFS label, if any.
+If it matches a previously removed vdev on an active pool,
+.Nm
+will online it.
+Once resilvering completes, any active hotspare will detach automatically.
+.Pp
+If the new device has no ZFS label but its physical path matches the
+physical path of a previously removed vdev on an active pool, and that
+pool has the autoreplace property set, then
+.Nm
+will replace the missing vdev with the newly arrived device.
+Once resilvering completes, any active hotspare will detach automatically.
+.It vdev degrade or fault events
+If a vdev becomes degraded or faulted,
+.Nm
+will activate any available hotspare.
+.It I/O errors
+If a leaf vdev generates more than 50 I/O errors in a 60 second period, then
+.Nm
+will mark that vdev as
+.Em FAULTED .
+.Xr zfs 4
+will no longer issue any I/Os to it.
+.Nm
+will activate a hotspare if one is available.
+.It Checksum errors
+If a leaf vdev generates more than 50 checksum errors in a 60 second
+period, then
+.Nm
+will mark that vdev as
+.Em DEGRADED .
+.Xr zfs 4
+will still use it, but zfsd will activate a spare anyway.
+.It Spare addition
+If the system administrator adds a hotspare to a pool that is already degraded,
+.Nm
+will activate the spare.
+.It Resilver complete
+.Nm
+will detach any hotspare once a permanent replacement finishes resilvering.
+.It Physical path change
+If the physical path of an existing disk changes,
+.Nm
+will attempt to replace any missing disk with the same physical path,
+if its pool's autoreplace property is set.
+.El
+.Pp
+.Nm
+will log interesting events and its actions to syslog with facility
+.Em daemon
+and identity
+.Op zfsd .
+.El
+.Sh FILES
+.Bl -tag -width a -compact
+.It Pa /var/db/zfsd/cases
+When
+.Nm
+exits, it serializes any unresolved casefiles here,
+then reads them back in when next it starts up.
+.El
+.Sh SEE ALSO
+.Xr devctl 4 ,
+.Xr zfs 4 ,
+.Xr zpool 8
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 11.0 .
+.Sh AUTHORS
+.Nm
+was originally written by
+.An Justin Gibbs Aq Mt gibbs@FreeBSD.org
+and
+.An Alan Somers Aq Mt asomers@FreeBSD.org
+.Sh TODO
+In the future,
+.Nm
+should be able to resume a pool that became suspended due to device
+removals, if enough missing devices have returned.
diff --git a/cddl/usr.sbin/zfsd/zfsd.cc b/cddl/usr.sbin/zfsd/zfsd.cc
new file mode 100644
index 0000000..e05c16d
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd.cc
@@ -0,0 +1,448 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file zfsd.cc
+ *
+ * The ZFS daemon consumes kernel devdctl(4) event data via devd(8)'s
+ * unix domain socket in order to react to system changes that impact
+ * the function of ZFS storage pools. The goal of this daemon is to
+ * provide similar functionality to the Solaris ZFS Diagnostic Engine
+ * (zfs-diagnosis), the Solaris ZFS fault handler (zfs-retire), and
+ * the Solaris ZFS vdev insertion agent (zfs-mod sysevent handler).
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/fs/zfs.h>
+
+#include <err.h>
+#include <libgeom.h>
+#include <libutil.h>
+#include <poll.h>
+#include <syslog.h>
+
+#include <libzfs.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include "callout.h"
+#include "vdev_iterator.h"
+#include "zfsd_event.h"
+#include "case_file.h"
+#include "vdev.h"
+#include "vdev_iterator.h"
+#include "zfsd.h"
+#include "zfsd_exception.h"
+#include "zpool_list.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+using DevdCtl::Event;
+using DevdCtl::EventFactory;
+using DevdCtl::EventList;
+
+/*================================ Global Data ===============================*/
+int g_debug = 0;
+libzfs_handle_t *g_zfsHandle;
+
+/*--------------------------------- ZfsDaemon --------------------------------*/
+//- ZfsDaemon Static Private Data ----------------------------------------------
+ZfsDaemon *ZfsDaemon::s_theZfsDaemon;
+bool ZfsDaemon::s_logCaseFiles;
+bool ZfsDaemon::s_terminateEventLoop;
+char ZfsDaemon::s_pidFilePath[] = "/var/run/zfsd.pid";
+pidfh *ZfsDaemon::s_pidFH;
+int ZfsDaemon::s_signalPipeFD[2];
+bool ZfsDaemon::s_systemRescanRequested(false);
+EventFactory::Record ZfsDaemon::s_registryEntries[] =
+{
+ { Event::NOTIFY, "DEVFS", &DevfsEvent::Builder },
+ { Event::NOTIFY, "GEOM", &GeomEvent::Builder },
+ { Event::NOTIFY, "ZFS", &ZfsEvent::Builder }
+};
+
+//- ZfsDaemon Static Public Methods --------------------------------------------
+ZfsDaemon &
+ZfsDaemon::Get()
+{
+ return (*s_theZfsDaemon);
+}
+
+void
+ZfsDaemon::WakeEventLoop()
+{
+ write(s_signalPipeFD[1], "+", 1);
+}
+
+void
+ZfsDaemon::RequestSystemRescan()
+{
+ s_systemRescanRequested = true;
+ ZfsDaemon::WakeEventLoop();
+}
+
+void
+ZfsDaemon::Run()
+{
+ ZfsDaemon daemon;
+
+ while (s_terminateEventLoop == false) {
+
+ try {
+ daemon.DisconnectFromDevd();
+
+ if (daemon.ConnectToDevd() == false) {
+ sleep(30);
+ continue;
+ }
+
+ daemon.DetectMissedEvents();
+
+ daemon.EventLoop();
+
+ } catch (const DevdCtl::Exception &exp) {
+ exp.Log();
+ }
+ }
+
+ daemon.DisconnectFromDevd();
+}
+
+//- ZfsDaemon Private Methods --------------------------------------------------
+ZfsDaemon::ZfsDaemon()
+ : Consumer(/*defBuilder*/NULL, s_registryEntries,
+ NUM_ELEMENTS(s_registryEntries))
+{
+ if (s_theZfsDaemon != NULL)
+ errx(1, "Multiple ZfsDaemon instances created. Exiting");
+
+ s_theZfsDaemon = this;
+
+ if (pipe(s_signalPipeFD) != 0)
+ errx(1, "Unable to allocate signal pipe. Exiting");
+
+ if (fcntl(s_signalPipeFD[0], F_SETFL, O_NONBLOCK) == -1)
+ errx(1, "Unable to set pipe as non-blocking. Exiting");
+
+ if (fcntl(s_signalPipeFD[1], F_SETFL, O_NONBLOCK) == -1)
+ errx(1, "Unable to set pipe as non-blocking. Exiting");
+
+ signal(SIGHUP, ZfsDaemon::RescanSignalHandler);
+ signal(SIGINFO, ZfsDaemon::InfoSignalHandler);
+ signal(SIGINT, ZfsDaemon::QuitSignalHandler);
+ signal(SIGTERM, ZfsDaemon::QuitSignalHandler);
+ signal(SIGUSR1, ZfsDaemon::RescanSignalHandler);
+
+ g_zfsHandle = libzfs_init();
+ if (g_zfsHandle == NULL)
+ errx(1, "Unable to initialize ZFS library. Exiting");
+
+ Callout::Init();
+ InitializeSyslog();
+ OpenPIDFile();
+
+ if (g_debug == 0)
+ daemon(0, 0);
+
+ UpdatePIDFile();
+}
+
+ZfsDaemon::~ZfsDaemon()
+{
+ PurgeCaseFiles();
+ ClosePIDFile();
+}
+
+void
+ZfsDaemon::PurgeCaseFiles()
+{
+ CaseFile::PurgeAll();
+}
+
+bool
+ZfsDaemon::VdevAddCaseFile(Vdev &vdev, void *cbArg)
+{
+ if (vdev.State() != VDEV_STATE_HEALTHY)
+ CaseFile::Create(vdev);
+
+ return (/*break early*/false);
+}
+
+void
+ZfsDaemon::BuildCaseFiles()
+{
+ ZpoolList zpl;
+ ZpoolList::iterator pool;
+
+ /* Add CaseFiles for vdevs with issues. */
+ for (pool = zpl.begin(); pool != zpl.end(); pool++)
+ VdevIterator(*pool).Each(VdevAddCaseFile, NULL);
+
+ /* De-serialize any saved cases. */
+ CaseFile::DeSerialize();
+
+ /* Simulate config_sync events to force CaseFile reevaluation */
+ for (pool = zpl.begin(); pool != zpl.end(); pool++) {
+ char evString[160];
+ Event *event;
+ nvlist_t *config;
+ uint64_t poolGUID;
+ const char *poolname;
+
+ poolname = zpool_get_name(*pool);
+ config = zpool_get_config(*pool, NULL);
+ if (config == NULL) {
+ syslog(LOG_ERR, "ZFSDaemon::BuildCaseFiles: Could not "
+ "find pool config for pool %s", poolname);
+ continue;
+ }
+ if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
+ &poolGUID) != 0) {
+ syslog(LOG_ERR, "ZFSDaemon::BuildCaseFiles: Could not "
+ "find pool guid for pool %s", poolname);
+ continue;
+ }
+
+
+ snprintf(evString, 160, "!system=ZFS subsystem=ZFS "
+ "type=misc.fs.zfs.config_sync sub_type=synthesized "
+ "pool_name=%s pool_guid=%" PRIu64 "\n", poolname, poolGUID);
+ event = Event::CreateEvent(GetFactory(), string(evString));
+ if (event != NULL) {
+ event->Process();
+ delete event;
+ }
+ }
+}
+
+void
+ZfsDaemon::RescanSystem()
+{
+ struct gmesh mesh;
+ struct gclass *mp;
+ struct ggeom *gp;
+ struct gprovider *pp;
+ int result;
+
+ /*
+ * The devdctl system doesn't replay events for new consumers
+ * of the interface. Emit manufactured DEVFS arrival events
+ * for any devices that already before we started or during
+ * periods where we've lost our connection to devd.
+ */
+ result = geom_gettree(&mesh);
+ if (result != 0) {
+ syslog(LOG_ERR, "ZfsDaemon::RescanSystem: "
+ "geom_gettree faild with error %d\n", result);
+ return;
+ }
+
+ const string evStart("!system=DEVFS subsystem=CDEV type=CREATE "
+ "sub_type=synthesized cdev=");
+ LIST_FOREACH(mp, &mesh.lg_class, lg_class) {
+ LIST_FOREACH(gp, &mp->lg_geom, lg_geom) {
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
+ Event *event;
+
+ string evString(evStart + pp->lg_name + "\n");
+ event = Event::CreateEvent(GetFactory(),
+ evString);
+ if (event != NULL) {
+ if (event->Process())
+ SaveEvent(*event);
+ delete event;
+ }
+ }
+ }
+ }
+ geom_deletetree(&mesh);
+}
+
+void
+ZfsDaemon::DetectMissedEvents()
+{
+ do {
+ PurgeCaseFiles();
+
+ /*
+ * Discard any events waiting for us. We don't know
+ * if they still apply to the current state of the
+ * system.
+ */
+ FlushEvents();
+
+ BuildCaseFiles();
+
+ /*
+ * If the system state has changed during our
+ * interrogation, start over.
+ */
+ } while (s_terminateEventLoop == false && EventsPending());
+
+ RescanSystem();
+}
+
+void
+ZfsDaemon::EventLoop()
+{
+ while (s_terminateEventLoop == false) {
+ struct pollfd fds[2];
+ int result;
+
+ if (s_logCaseFiles == true) {
+ EventList::iterator event(m_unconsumedEvents.begin());
+ s_logCaseFiles = false;
+ CaseFile::LogAll();
+ while (event != m_unconsumedEvents.end())
+ (*event++)->Log(LOG_INFO);
+ }
+
+ Callout::ExpireCallouts();
+
+ /* Wait for data. */
+ fds[0].fd = m_devdSockFD;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ fds[1].fd = s_signalPipeFD[0];
+ fds[1].events = POLLIN;
+ fds[1].revents = 0;
+ result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/INFTIM);
+ if (result == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ err(1, "Polling for devd events failed");
+ } else if (result == 0) {
+ errx(1, "Unexpected result of 0 from poll. Exiting");
+ }
+
+ if ((fds[0].revents & POLLIN) != 0)
+ ProcessEvents();
+
+ if ((fds[1].revents & POLLIN) != 0) {
+ static char discardBuf[128];
+
+ /*
+ * This pipe exists just to close the signal
+ * race. Its contents are of no interest to
+ * us, but we must ensure that future signals
+ * have space in the pipe to write.
+ */
+ while (read(s_signalPipeFD[0], discardBuf,
+ sizeof(discardBuf)) > 0)
+ ;
+ }
+
+ if (s_systemRescanRequested == true) {
+ s_systemRescanRequested = false;
+ syslog(LOG_INFO, "System Rescan request processed.");
+ RescanSystem();
+ }
+
+ if ((fds[0].revents & POLLERR) != 0) {
+ syslog(LOG_INFO, "POLLERROR detected on devd socket.");
+ break;
+ }
+
+ if ((fds[0].revents & POLLHUP) != 0) {
+ syslog(LOG_INFO, "POLLHUP detected on devd socket.");
+ break;
+ }
+ }
+}
+//- ZfsDaemon staic Private Methods --------------------------------------------
+void
+ZfsDaemon::InfoSignalHandler(int)
+{
+ s_logCaseFiles = true;
+ ZfsDaemon::WakeEventLoop();
+}
+
+void
+ZfsDaemon::RescanSignalHandler(int)
+{
+ RequestSystemRescan();
+}
+
+void
+ZfsDaemon::QuitSignalHandler(int)
+{
+ s_terminateEventLoop = true;
+ ZfsDaemon::WakeEventLoop();
+}
+
+void
+ZfsDaemon::OpenPIDFile()
+{
+ pid_t otherPID;
+
+ s_pidFH = pidfile_open(s_pidFilePath, 0600, &otherPID);
+ if (s_pidFH == NULL) {
+ if (errno == EEXIST)
+ errx(1, "already running as PID %d. Exiting", otherPID);
+ warn("cannot open PID file");
+ }
+}
+
+void
+ZfsDaemon::UpdatePIDFile()
+{
+ if (s_pidFH != NULL)
+ pidfile_write(s_pidFH);
+}
+
+void
+ZfsDaemon::ClosePIDFile()
+{
+ if (s_pidFH != NULL)
+ pidfile_close(s_pidFH);
+}
+
+void
+ZfsDaemon::InitializeSyslog()
+{
+ openlog("zfsd", LOG_NDELAY, LOG_DAEMON);
+}
+
diff --git a/cddl/usr.sbin/zfsd/zfsd.h b/cddl/usr.sbin/zfsd/zfsd.h
new file mode 100644
index 0000000..7b4019c
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd.h
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file zfsd.h
+ *
+ * Class definitions and supporting data strutures for the ZFS fault
+ * management daemon.
+ *
+ * Header requirements:
+ *
+ * #include <sys/fs/zfs.h>
+ *
+ * #include <libzfs.h>
+ *
+ * #include <list>
+ * #include <map>
+ * #include <string>
+ *
+ * #include <devdctl/guid.h>
+ * #include <devdctl/event.h>
+ * #include <devdctl/event_factory.h>
+ * #include <devdctl/consumer.h>
+ *
+ * #include "vdev_iterator.h"
+ */
+#ifndef _ZFSD_H_
+#define _ZFSD_H_
+
+/*=========================== Forward Declarations ===========================*/
+struct pidfh;
+
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+
+struct zfs_handle;
+typedef struct libzfs_handle libzfs_handle_t;
+
+struct nvlist;
+typedef struct nvlist nvlist_t;
+
+typedef int LeafIterFunc(zpool_handle_t *, nvlist_t *, void *);
+
+/*================================ Global Data ===============================*/
+extern int g_debug;
+extern libzfs_handle_t *g_zfsHandle;
+
+/*============================= Class Definitions ============================*/
+/*--------------------------------- ZfsDaemon --------------------------------*/
+/**
+ * Static singleton orchestrating the operations of the ZFS daemon program.
+ */
+class ZfsDaemon : public DevdCtl::Consumer
+{
+public:
+ /** Return the ZfsDaemon singleton. */
+ static ZfsDaemon &Get();
+
+ /**
+ * Used by signal handlers to ensure, in a race free way, that
+ * the event loop will perform at least one more full loop
+ * before sleeping again.
+ */
+ static void WakeEventLoop();
+
+ /**
+ * Schedules a rescan of devices in the system for potential
+ * candidates to replace a missing vdev. The scan is performed
+ * during the next run of the event loop.
+ */
+ static void RequestSystemRescan();
+
+ /** Daemonize and perform all functions of the ZFS daemon. */
+ static void Run();
+
+private:
+ ZfsDaemon();
+ ~ZfsDaemon();
+
+ static VdevCallback_t VdevAddCaseFile;
+
+ /** Purge our cache of outstanding ZFS issues in the system. */
+ void PurgeCaseFiles();
+
+ /** Build a cache of outstanding ZFS issues in the system. */
+ void BuildCaseFiles();
+
+ /**
+ * Iterate over all known issues and attempt to solve them
+ * given resources currently available in the system.
+ */
+ void RescanSystem();
+
+ /**
+ * Interrogate the system looking for previously unknown
+ * faults that occurred either before ZFSD was started,
+ * or during a period of lost communication with Devd.
+ */
+ void DetectMissedEvents();
+
+ /**
+ * Wait for and process event source activity.
+ */
+ void EventLoop();
+
+ /**
+ * Signal handler for which our response is to
+ * log the current state of the daemon.
+ *
+ * \param sigNum The signal caught.
+ */
+ static void InfoSignalHandler(int sigNum);
+
+ /**
+ * Signal handler for which our response is to
+ * request a case rescan.
+ *
+ * \param sigNum The signal caught.
+ */
+ static void RescanSignalHandler(int sigNum);
+
+ /**
+ * Signal handler for which our response is to
+ * gracefully terminate.
+ *
+ * \param sigNum The signal caught.
+ */
+ static void QuitSignalHandler(int sigNum);
+
+ /**
+ * Open and lock our PID file.
+ */
+ static void OpenPIDFile();
+
+ /**
+ * Update our PID file with our PID.
+ */
+ static void UpdatePIDFile();
+
+ /**
+ * Close and release the lock on our PID file.
+ */
+ static void ClosePIDFile();
+
+ /**
+ * Perform syslog configuration.
+ */
+ static void InitializeSyslog();
+
+ static ZfsDaemon *s_theZfsDaemon;
+
+ /**
+ * Set to true when our program is signaled to
+ * gracefully exit.
+ */
+ static bool s_logCaseFiles;
+
+ /**
+ * Set to true when our program is signaled to
+ * gracefully exit.
+ */
+ static bool s_terminateEventLoop;
+
+ /**
+ * The canonical path and file name of zfsd's PID file.
+ */
+ static char s_pidFilePath[];
+
+ /**
+ * Control structure for PIDFILE(3) API.
+ */
+ static pidfh *s_pidFH;
+
+ /**
+ * Pipe file descriptors used to close races with our
+ * signal handlers.
+ */
+ static int s_signalPipeFD[2];
+
+ /**
+ * Flag controlling a rescan from ZFSD's event loop of all
+ * GEOM providers in the system to find candidates for solving
+ * cases.
+ */
+ static bool s_systemRescanRequested;
+
+ /**
+ * Flag controlling whether events can be queued. This boolean
+ * is set during event replay to ensure that events for pools or
+ * devices no longer in the system are not retained forever.
+ */
+ static bool s_consumingEvents;
+
+ static DevdCtl::EventFactory::Record s_registryEntries[];
+};
+
+#endif /* _ZFSD_H_ */
diff --git a/cddl/usr.sbin/zfsd/zfsd_event.cc b/cddl/usr.sbin/zfsd/zfsd_event.cc
new file mode 100644
index 0000000..c10cc18
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd_event.cc
@@ -0,0 +1,535 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file zfsd_event.cc
+ */
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/fs/zfs.h>
+
+#include <syslog.h>
+
+#include <libzfs.h>
+/*
+ * Undefine flush, defined by cpufunc.h on sparc64, because it conflicts with
+ * C++ flush methods
+ */
+#undef flush
+
+#include <list>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include "callout.h"
+#include "vdev_iterator.h"
+#include "zfsd_event.h"
+#include "case_file.h"
+#include "vdev.h"
+#include "zfsd.h"
+#include "zfsd_exception.h"
+#include "zpool_list.h"
+
+__FBSDID("$FreeBSD$");
+/*============================ Namespace Control =============================*/
+using DevdCtl::Event;
+using DevdCtl::Guid;
+using DevdCtl::NVPairMap;
+using std::stringstream;
+
+/*=========================== Class Implementations ==========================*/
+
+/*-------------------------------- DevfsEvent --------------------------------*/
+
+//- DevfsEvent Static Public Methods -------------------------------------------
+Event *
+DevfsEvent::Builder(Event::Type type,
+ NVPairMap &nvPairs,
+ const string &eventString)
+{
+ return (new DevfsEvent(type, nvPairs, eventString));
+}
+
+//- DevfsEvent Static Protected Methods ----------------------------------------
+nvlist_t *
+DevfsEvent::ReadLabel(int devFd, bool &inUse, bool &degraded)
+{
+ pool_state_t poolState;
+ char *poolName;
+ boolean_t b_inuse;
+
+ inUse = false;
+ degraded = false;
+ poolName = NULL;
+ if (zpool_in_use(g_zfsHandle, devFd, &poolState,
+ &poolName, &b_inuse) == 0) {
+ nvlist_t *devLabel;
+
+ inUse = b_inuse == B_TRUE;
+ if (poolName != NULL)
+ free(poolName);
+
+ if (zpool_read_label(devFd, &devLabel) != 0
+ || devLabel == NULL)
+ return (NULL);
+
+ try {
+ Vdev vdev(devLabel);
+ degraded = vdev.State() != VDEV_STATE_HEALTHY;
+ return (devLabel);
+ } catch (ZfsdException &exp) {
+ string devName = fdevname(devFd);
+ string devPath = _PATH_DEV + devName;
+ string context("DevfsEvent::ReadLabel: "
+ + devPath + ": ");
+
+ exp.GetString().insert(0, context);
+ exp.Log();
+ }
+ }
+ return (NULL);
+}
+
+bool
+DevfsEvent::OnlineByLabel(const string &devPath, const string& physPath,
+ nvlist_t *devConfig)
+{
+ try {
+ /*
+ * A device with ZFS label information has been
+ * inserted. If it matches a device for which we
+ * have a case, see if we can solve that case.
+ */
+ syslog(LOG_INFO, "Interrogating VDEV label for %s\n",
+ devPath.c_str());
+ Vdev vdev(devConfig);
+ CaseFile *caseFile(CaseFile::Find(vdev.PoolGUID(),
+ vdev.GUID()));
+ if (caseFile != NULL)
+ return (caseFile->ReEvaluate(devPath, physPath, &vdev));
+
+ } catch (ZfsdException &exp) {
+ string context("DevfsEvent::OnlineByLabel: " + devPath + ": ");
+
+ exp.GetString().insert(0, context);
+ exp.Log();
+ }
+ return (false);
+}
+
+//- DevfsEvent Virtual Public Methods ------------------------------------------
+Event *
+DevfsEvent::DeepCopy() const
+{
+ return (new DevfsEvent(*this));
+}
+
+bool
+DevfsEvent::Process() const
+{
+ /*
+ * We are only concerned with newly discovered
+ * devices that can be ZFS vdevs.
+ */
+ if (Value("type") != "CREATE" || !IsDiskDev())
+ return (false);
+
+ /* Log the event since it is of interest. */
+ Log(LOG_INFO);
+
+ string devPath;
+ if (!DevPath(devPath))
+ return (false);
+
+ int devFd(open(devPath.c_str(), O_RDONLY));
+ if (devFd == -1)
+ return (false);
+
+ bool inUse;
+ bool degraded;
+ nvlist_t *devLabel(ReadLabel(devFd, inUse, degraded));
+
+ string physPath;
+ bool havePhysPath(PhysicalPath(physPath));
+
+ string devName;
+ DevName(devName);
+ close(devFd);
+
+ if (inUse && devLabel != NULL) {
+ OnlineByLabel(devPath, physPath, devLabel);
+ } else if (degraded) {
+ syslog(LOG_INFO, "%s is marked degraded. Ignoring "
+ "as a replace by physical path candidate.\n",
+ devName.c_str());
+ } else if (havePhysPath && IsWholeDev()) {
+ /*
+ * TODO: attempt to resolve events using every casefile
+ * that matches this physpath
+ */
+ CaseFile *caseFile(CaseFile::Find(physPath));
+ if (caseFile != NULL) {
+ syslog(LOG_INFO,
+ "Found CaseFile(%s:%s:%s) - ReEvaluating\n",
+ caseFile->PoolGUIDString().c_str(),
+ caseFile->VdevGUIDString().c_str(),
+ zpool_state_to_name(caseFile->VdevState(),
+ VDEV_AUX_NONE));
+ caseFile->ReEvaluate(devPath, physPath, /*vdev*/NULL);
+ }
+ }
+ if (devLabel != NULL)
+ nvlist_free(devLabel);
+ return (false);
+}
+
+//- DevfsEvent Protected Methods -----------------------------------------------
+DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : DevdCtl::DevfsEvent(type, nvpairs, eventString)
+{
+}
+
+DevfsEvent::DevfsEvent(const DevfsEvent &src)
+ : DevdCtl::DevfsEvent::DevfsEvent(src)
+{
+}
+
+/*-------------------------------- GeomEvent --------------------------------*/
+
+//- GeomEvent Static Public Methods -------------------------------------------
+Event *
+GeomEvent::Builder(Event::Type type,
+ NVPairMap &nvPairs,
+ const string &eventString)
+{
+ return (new GeomEvent(type, nvPairs, eventString));
+}
+
+//- GeomEvent Virtual Public Methods ------------------------------------------
+Event *
+GeomEvent::DeepCopy() const
+{
+ return (new GeomEvent(*this));
+}
+
+bool
+GeomEvent::Process() const
+{
+ /*
+ * We are only concerned with physical path changes, because those can
+ * be used to satisfy autoreplace operations
+ */
+ if (Value("type") != "GEOM::physpath" || !IsDiskDev())
+ return (false);
+
+ /* Log the event since it is of interest. */
+ Log(LOG_INFO);
+
+ string devPath;
+ if (!DevPath(devPath))
+ return (false);
+
+ string physPath;
+ bool havePhysPath(PhysicalPath(physPath));
+
+ string devName;
+ DevName(devName);
+
+ if (havePhysPath) {
+ /*
+ * TODO: attempt to resolve events using every casefile
+ * that matches this physpath
+ */
+ CaseFile *caseFile(CaseFile::Find(physPath));
+ if (caseFile != NULL) {
+ syslog(LOG_INFO,
+ "Found CaseFile(%s:%s:%s) - ReEvaluating\n",
+ caseFile->PoolGUIDString().c_str(),
+ caseFile->VdevGUIDString().c_str(),
+ zpool_state_to_name(caseFile->VdevState(),
+ VDEV_AUX_NONE));
+ caseFile->ReEvaluate(devPath, physPath, /*vdev*/NULL);
+ }
+ }
+ return (false);
+}
+
+//- GeomEvent Protected Methods -----------------------------------------------
+GeomEvent::GeomEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : DevdCtl::GeomEvent(type, nvpairs, eventString)
+{
+}
+
+GeomEvent::GeomEvent(const GeomEvent &src)
+ : DevdCtl::GeomEvent::GeomEvent(src)
+{
+}
+
+
+/*--------------------------------- ZfsEvent ---------------------------------*/
+//- ZfsEvent Static Public Methods ---------------------------------------------
+DevdCtl::Event *
+ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+{
+ return (new ZfsEvent(type, nvpairs, eventString));
+}
+
+//- ZfsEvent Virtual Public Methods --------------------------------------------
+Event *
+ZfsEvent::DeepCopy() const
+{
+ return (new ZfsEvent(*this));
+}
+
+bool
+ZfsEvent::Process() const
+{
+ string logstr("");
+
+ if (!Contains("class") && !Contains("type")) {
+ syslog(LOG_ERR,
+ "ZfsEvent::Process: Missing class or type data.");
+ return (false);
+ }
+
+ /* On config syncs, replay any queued events first. */
+ if (Value("type").find("misc.fs.zfs.config_sync") == 0) {
+ /*
+ * Even if saved events are unconsumed the second time
+ * around, drop them. Any events that still can't be
+ * consumed are probably referring to vdevs or pools that
+ * no longer exist.
+ */
+ ZfsDaemon::Get().ReplayUnconsumedEvents(/*discard*/true);
+ CaseFile::ReEvaluateByGuid(PoolGUID(), *this);
+ }
+
+ if (Value("type").find("misc.fs.zfs.") == 0) {
+ /* Configuration changes, resilver events, etc. */
+ ProcessPoolEvent();
+ return (false);
+ }
+
+ if (!Contains("pool_guid") || !Contains("vdev_guid")) {
+ /* Only currently interested in Vdev related events. */
+ return (false);
+ }
+
+ CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID()));
+ if (caseFile != NULL) {
+ Log(LOG_INFO);
+ syslog(LOG_INFO, "Evaluating existing case file\n");
+ caseFile->ReEvaluate(*this);
+ return (false);
+ }
+
+ /* Skip events that can't be handled. */
+ Guid poolGUID(PoolGUID());
+ /* If there are no replicas for a pool, then it's not manageable. */
+ if (Value("class").find("fs.zfs.vdev.no_replicas") == 0) {
+ stringstream msg;
+ msg << "No replicas available for pool " << poolGUID;
+ msg << ", ignoring";
+ Log(LOG_INFO);
+ syslog(LOG_INFO, "%s", msg.str().c_str());
+ return (false);
+ }
+
+ /*
+ * Create a case file for this vdev, and have it
+ * evaluate the event.
+ */
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &poolGUID);
+ if (zpl.empty()) {
+ stringstream msg;
+ int priority = LOG_INFO;
+ msg << "ZfsEvent::Process: Event for unknown pool ";
+ msg << poolGUID << " ";
+ msg << "queued";
+ Log(LOG_INFO);
+ syslog(priority, "%s", msg.str().c_str());
+ return (true);
+ }
+
+ nvlist_t *vdevConfig = VdevIterator(zpl.front()).Find(VdevGUID());
+ if (vdevConfig == NULL) {
+ stringstream msg;
+ int priority = LOG_INFO;
+ msg << "ZfsEvent::Process: Event for unknown vdev ";
+ msg << VdevGUID() << " ";
+ msg << "queued";
+ Log(LOG_INFO);
+ syslog(priority, "%s", msg.str().c_str());
+ return (true);
+ }
+
+ Vdev vdev(zpl.front(), vdevConfig);
+ caseFile = &CaseFile::Create(vdev);
+ if (caseFile->ReEvaluate(*this) == false) {
+ stringstream msg;
+ int priority = LOG_INFO;
+ msg << "ZfsEvent::Process: Unconsumed event for vdev(";
+ msg << zpool_get_name(zpl.front()) << ",";
+ msg << vdev.GUID() << ") ";
+ msg << "queued";
+ Log(LOG_INFO);
+ syslog(priority, "%s", msg.str().c_str());
+ return (true);
+ }
+ return (false);
+}
+
+//- ZfsEvent Protected Methods -------------------------------------------------
+ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : DevdCtl::ZfsEvent(type, nvpairs, eventString)
+{
+}
+
+ZfsEvent::ZfsEvent(const ZfsEvent &src)
+ : DevdCtl::ZfsEvent(src)
+{
+}
+
+/*
+ * Sometimes the kernel won't detach a spare when it is no longer needed. This
+ * can happen for example if a drive is removed, then either the pool is
+ * exported or the machine is powered off, then the drive is reinserted, then
+ * the machine is powered on or the pool is imported. ZFSD must detach these
+ * spares itself.
+ */
+void
+ZfsEvent::CleanupSpares() const
+{
+ Guid poolGUID(PoolGUID());
+ ZpoolList zpl(ZpoolList::ZpoolByGUID, &poolGUID);
+ if (!zpl.empty()) {
+ zpool_handle_t* hdl;
+
+ hdl = zpl.front();
+ VdevIterator(hdl).Each(TryDetach, (void*)hdl);
+ }
+}
+
+void
+ZfsEvent::ProcessPoolEvent() const
+{
+ bool degradedDevice(false);
+
+ /* The pool is destroyed. Discard any open cases */
+ if (Value("type") == "misc.fs.zfs.pool_destroy") {
+ Log(LOG_INFO);
+ CaseFile::ReEvaluateByGuid(PoolGUID(), *this);
+ return;
+ }
+
+ CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID()));
+ if (caseFile != NULL) {
+ if (caseFile->VdevState() != VDEV_STATE_UNKNOWN
+ && caseFile->VdevState() < VDEV_STATE_HEALTHY)
+ degradedDevice = true;
+
+ Log(LOG_INFO);
+ caseFile->ReEvaluate(*this);
+ }
+ else if (Value("type") == "misc.fs.zfs.resilver_finish")
+ {
+ /*
+ * It's possible to get a resilver_finish event with no
+ * corresponding casefile. For example, if a damaged pool were
+ * exported, repaired, then reimported.
+ */
+ Log(LOG_INFO);
+ CleanupSpares();
+ }
+
+ if (Value("type") == "misc.fs.zfs.vdev_remove"
+ && degradedDevice == false) {
+
+ /* See if any other cases can make use of this device. */
+ Log(LOG_INFO);
+ ZfsDaemon::RequestSystemRescan();
+ }
+}
+
+bool
+ZfsEvent::TryDetach(Vdev &vdev, void *cbArg)
+{
+ /*
+ * Outline:
+ * if this device is a spare, and its parent includes one healthy,
+ * non-spare child, then detach this device.
+ */
+ zpool_handle_t *hdl(static_cast<zpool_handle_t*>(cbArg));
+
+ if (vdev.IsSpare()) {
+ std::list<Vdev> siblings;
+ std::list<Vdev>::iterator siblings_it;
+ boolean_t cleanup = B_FALSE;
+
+ Vdev parent = vdev.Parent();
+ siblings = parent.Children();
+
+ /* Determine whether the parent should be cleaned up */
+ for (siblings_it = siblings.begin();
+ siblings_it != siblings.end();
+ siblings_it++) {
+ Vdev sibling = *siblings_it;
+
+ if (!sibling.IsSpare() &&
+ sibling.State() == VDEV_STATE_HEALTHY) {
+ cleanup = B_TRUE;
+ break;
+ }
+ }
+
+ if (cleanup) {
+ syslog(LOG_INFO, "Detaching spare vdev %s from pool %s",
+ vdev.Path().c_str(), zpool_get_name(hdl));
+ zpool_vdev_detach(hdl, vdev.Path().c_str());
+ }
+
+ }
+
+ /* Always return false, because there may be other spares to detach */
+ return (false);
+}
diff --git a/cddl/usr.sbin/zfsd/zfsd_event.h b/cddl/usr.sbin/zfsd/zfsd_event.h
new file mode 100644
index 0000000..c4ba422
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd_event.h
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file dev_ctl_event.h
+ *
+ * \brief Class hierarchy used to express events received via
+ * the devdctl API.
+ *
+ * Header requirements:
+ * #include <string>
+ * #include <list>
+ * #include <map>
+ *
+ * #include <devdctl/guid.h>
+ * #include <devdctl/event.h>
+ */
+
+#ifndef _ZFSD_EVENT_H_
+#define _ZFSD_EVENT_H_
+
+/*============================ Namespace Control =============================*/
+using std::string;
+
+/*=========================== Forward Declarations ===========================*/
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+
+struct nvlist;
+typedef struct nvlist nvlist_t;
+
+/*============================= Class Definitions ============================*/
+/*-------------------------------- DevfsEvent --------------------------------*/
+class DevfsEvent : public DevdCtl::DevfsEvent
+{
+public:
+ /** Specialized DevdCtlEvent object factory for Devfs events. */
+ static BuildMethod Builder;
+
+ virtual DevdCtl::Event *DeepCopy() const;
+
+ /**
+ * Interpret and perform any actions necessary to
+ * consume the event.
+ * \return True if this event should be queued for later reevaluation
+ */
+ virtual bool Process() const;
+
+protected:
+ /**
+ * \brief Read and return label information for a device.
+ *
+ * \param devFd The device from which to read ZFS label information.
+ * \param inUse The device is part of an active or potentially
+ * active configuration.
+ * \param degraded The device label indicates the vdev is not healthy.
+ *
+ * \return If label information is available, an nvlist describing
+ * the vdev configuraiton found on the device specified by
+ * devFd. Otherwise NULL.
+ */
+ static nvlist_t *ReadLabel(int devFd, bool &inUse, bool &degraded);
+
+ /**
+ * Attempt to match the ZFS labeled device at devPath with an active
+ * CaseFile for a missing vdev. If a CaseFile is found, attempt
+ * to re-integrate the device with its pool.
+ *
+ * \param devPath The devfs path to the potential leaf vdev.
+ * \param physPath The physical path string reported by the device
+ * at devPath.
+ * \param devConfig The ZFS label information found on the device
+ * at devPath.
+ *
+ * \return true if the event that caused the online action can
+ * be considered consumed.
+ */
+ static bool OnlineByLabel(const string &devPath,
+ const string& physPath,
+ nvlist_t *devConfig);
+
+ /** DeepCopy Constructor. */
+ DevfsEvent(const DevfsEvent &src);
+
+ /** Constructor */
+ DevfsEvent(Type, DevdCtl::NVPairMap &, const string &);
+};
+
+/*--------------------------------- ZfsEvent ---------------------------------*/
+class ZfsEvent : public DevdCtl::ZfsEvent
+{
+public:
+ /** Specialized DevdCtlEvent object factory for ZFS events. */
+ static BuildMethod Builder;
+
+ virtual DevdCtl::Event *DeepCopy() const;
+
+ /**
+ * Interpret and perform any actions necessary to
+ * consume the event.
+ * \return True if this event should be queued for later reevaluation
+ */
+ virtual bool Process() const;
+
+protected:
+ /** DeepCopy Constructor. */
+ ZfsEvent(const ZfsEvent &src);
+
+ /** Constructor */
+ ZfsEvent(Type, DevdCtl::NVPairMap &, const string &);
+
+ /**
+ * Detach any spares that are no longer needed, but were not
+ * automatically detached by the kernel
+ */
+ virtual void CleanupSpares() const;
+ virtual void ProcessPoolEvent() const;
+ static VdevCallback_t TryDetach;
+};
+
+class GeomEvent : public DevdCtl::GeomEvent
+{
+public:
+ static BuildMethod Builder;
+
+ virtual DevdCtl::Event *DeepCopy() const;
+
+ virtual bool Process() const;
+
+protected:
+ /** DeepCopy Constructor. */
+ GeomEvent(const GeomEvent &src);
+
+ /** Constructor */
+ GeomEvent(Type, DevdCtl::NVPairMap &, const string &);
+};
+#endif /*_ZFSD_EVENT_H_ */
diff --git a/cddl/usr.sbin/zfsd/zfsd_exception.cc b/cddl/usr.sbin/zfsd/zfsd_exception.cc
new file mode 100644
index 0000000..7859a65
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd_exception.cc
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file zfsd_exception
+ *
+ * Implementation of the ZfsdException class.
+ */
+#include <sys/cdefs.h>
+#include <sys/fs/zfs.h>
+
+#include <syslog.h>
+
+#include <string>
+#include <list>
+#include <sstream>
+
+#include <devdctl/exception.h>
+#include <devdctl/guid.h>
+
+#include <libzfs.h>
+
+#include "vdev.h"
+#include "zfsd_exception.h"
+
+__FBSDID("$FreeBSD$");
+/*============================ Namespace Control =============================*/
+using std::endl;
+using std::string;
+using std::stringstream;
+
+/*=========================== Class Implementations ==========================*/
+/*------------------------------- ZfsdException ------------------------------*/
+ZfsdException::ZfsdException(const char *fmt, ...)
+ : DevdCtl::Exception(),
+ m_poolConfig(NULL),
+ m_vdevConfig(NULL)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ FormatLog(fmt, ap);
+ va_end(ap);
+}
+
+ZfsdException::ZfsdException(zpool_handle_t *pool, const char *fmt, ...)
+ : DevdCtl::Exception(),
+ m_poolConfig(zpool_get_config(pool, NULL)),
+ m_vdevConfig(NULL)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ FormatLog(fmt, ap);
+ va_end(ap);
+}
+
+ZfsdException::ZfsdException(nvlist_t *poolConfig, const char *fmt, ...)
+ : DevdCtl::Exception(),
+ m_poolConfig(poolConfig),
+ m_vdevConfig(NULL)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ FormatLog(fmt, ap);
+ va_end(ap);
+}
+
+void
+ZfsdException::Log() const
+{
+ stringstream output;
+
+ if (m_poolConfig != NULL) {
+
+ output << "Pool ";
+
+ char *poolName;
+ if (nvlist_lookup_string(m_poolConfig, ZPOOL_CONFIG_POOL_NAME,
+ &poolName) == 0)
+ output << poolName;
+ else
+ output << "Unknown";
+ output << ": ";
+ }
+
+ if (m_vdevConfig != NULL) {
+
+ if (m_poolConfig != NULL) {
+ Vdev vdev(m_poolConfig, m_vdevConfig);
+
+ output << "Vdev " << vdev.GUID() << ": ";
+ } else {
+ Vdev vdev(m_vdevConfig);
+
+ output << "Pool " << vdev.PoolGUID() << ": ";
+ output << "Vdev " << vdev.GUID() << ": ";
+ }
+ }
+
+ output << m_log << endl;
+ syslog(LOG_ERR, "%s", output.str().c_str());
+}
+
diff --git a/cddl/usr.sbin/zfsd/zfsd_exception.h b/cddl/usr.sbin/zfsd/zfsd_exception.h
new file mode 100644
index 0000000..5170b2d
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd_exception.h
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file zfsd_exception.h
+ *
+ * Definition of the ZfsdException class hierarchy. All exceptions
+ * explicitly thrown by Zfsd are defined here.
+ *
+ * Header requirements:
+ * #include <string>
+ *
+ * #include <devdctl/exception.h>
+ */
+#ifndef _ZFSD_EXCEPTION_H_
+#define _ZFSD_EXCEPTION_H_
+
+/*=========================== Forward Declarations ===========================*/
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+
+struct nvlist;
+typedef struct nvlist nvlist_t;
+
+/*============================= Class Definitions ============================*/
+/*------------------------------- ZfsdException ------------------------------*/
+/**
+ * \brief Class allowing unified reporting/logging of exceptional events.
+ */
+class ZfsdException : public DevdCtl::Exception
+{
+public:
+ /**
+ * \brief ZfsdException constructor allowing arbitrary string
+ * data to be reported.
+ *
+ * \param fmt Printf-like string format specifier.
+ */
+ ZfsdException(const char *fmt, ...);
+
+ /**
+ * \brief ZfsdException constructor allowing arbitrary string
+ * data to be reported and associated with the configuration
+ * data for a ZFS pool.
+ *
+ * \param pool Pool handle describing the pool to which this
+ * exception is associated.
+ * \param fmt Printf-like string format specifier.
+ *
+ * Instantiation with this method is used to report global
+ * pool errors.
+ */
+ ZfsdException(zpool_handle_t *pool, const char *, ...);
+
+ /**
+ * \brief ZfsdException constructor allowing arbitrary string
+ * data to be reported and associated with the configuration
+ * data for a ZFS pool.
+ *
+ * \param poolConfig Pool configuration describing the pool to
+ * which this exception is associated.
+ * \param fmt Printf-like string format specifier.
+ *
+ * Instantiation with this method is used to report global
+ * pool errors.
+ */
+ ZfsdException(nvlist_t *poolConfig, const char *, ...);
+
+ /**
+ * \brief Emit exception data to syslog(3).
+ */
+ virtual void Log() const;
+private:
+ nvlist_t *m_poolConfig;
+ nvlist_t *m_vdevConfig;
+};
+
+#endif /* _ZFSD_EXCEPTION_H_ */
diff --git a/cddl/usr.sbin/zfsd/zfsd_main.cc b/cddl/usr.sbin/zfsd/zfsd_main.cc
new file mode 100644
index 0000000..f090631
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zfsd_main.cc
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ */
+
+/**
+ * \file zfsd_main.cc
+ *
+ * main function for the ZFS Daemon. Separated to facilitate testing.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <unistd.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include "vdev_iterator.h"
+#include "zfsd.h"
+
+__FBSDID("$FreeBSD$");
+
+/*=============================== Program Main ===============================*/
+static void
+usage()
+{
+ fprintf(stderr, "usage: %s [-d]\n", getprogname());
+ exit(1);
+}
+
+/**
+ * Program entry point.
+ */
+int
+main(int argc, char **argv)
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "d")) != -1) {
+ switch (ch) {
+ case 'd':
+ g_debug++;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ ZfsDaemon::Run();
+
+ return (0);
+}
diff --git a/cddl/usr.sbin/zfsd/zpool_list.cc b/cddl/usr.sbin/zfsd/zpool_list.cc
new file mode 100644
index 0000000..1d1540b
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zpool_list.cc
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file zpool_list.cc
+ *
+ * Implementation of the ZpoolList class.
+ */
+#include <sys/cdefs.h>
+#include <sys/fs/zfs.h>
+
+#include <stdint.h>
+
+#include <libzfs.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+#include <devdctl/exception.h>
+#include <devdctl/consumer.h>
+
+#include "vdev.h"
+#include "vdev_iterator.h"
+#include "zpool_list.h"
+#include "zfsd.h"
+
+/*============================ Namespace Control =============================*/
+using DevdCtl::Guid;
+
+/*=========================== Class Implementations ==========================*/
+/*--------------------------------- ZpoolList --------------------------------*/
+bool
+ZpoolList::ZpoolAll(zpool_handle_t *pool, nvlist_t *poolConfig, void *cbArg)
+{
+ return (true);
+}
+
+bool
+ZpoolList::ZpoolByGUID(zpool_handle_t *pool, nvlist_t *poolConfig,
+ void *cbArg)
+{
+ Guid *desiredPoolGUID(static_cast<Guid *>(cbArg));
+ uint64_t poolGUID;
+
+ /* We are only intested in the pool that matches our pool GUID. */
+ return (nvlist_lookup_uint64(poolConfig, ZPOOL_CONFIG_POOL_GUID,
+ &poolGUID) == 0
+ && poolGUID == (uint64_t)*desiredPoolGUID);
+}
+
+bool
+ZpoolList::ZpoolByName(zpool_handle_t *pool, nvlist_t *poolConfig, void *cbArg)
+{
+ const string &desiredPoolName(*static_cast<const string *>(cbArg));
+
+ /* We are only intested in the pool that matches our pool GUID. */
+ return (desiredPoolName == zpool_get_name(pool));
+}
+
+int
+ZpoolList::LoadIterator(zpool_handle_t *pool, void *data)
+{
+ ZpoolList *zpl(reinterpret_cast<ZpoolList *>(data));
+ nvlist_t *poolConfig(zpool_get_config(pool, NULL));
+
+ if (zpl->m_filter(pool, poolConfig, zpl->m_filterArg))
+ zpl->push_back(pool);
+ else
+ zpool_close(pool);
+ return (0);
+}
+
+ZpoolList::ZpoolList(PoolFilter_t *filter, void * filterArg)
+ : m_filter(filter),
+ m_filterArg(filterArg)
+{
+ zpool_iter(g_zfsHandle, LoadIterator, this);
+}
+
+ZpoolList::~ZpoolList()
+{
+ for (iterator it(begin()); it != end(); it++)
+ zpool_close(*it);
+
+ clear();
+}
diff --git a/cddl/usr.sbin/zfsd/zpool_list.h b/cddl/usr.sbin/zfsd/zpool_list.h
new file mode 100644
index 0000000..6ee3089
--- /dev/null
+++ b/cddl/usr.sbin/zfsd/zpool_list.h
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file zpool_list.h
+ *
+ * ZpoolList class definition. ZpoolList is a standard container
+ * allowing filtering and iteration of imported ZFS pool information.
+ *
+ * Header requirements:
+ *
+ * #include <list>
+ * #include <string>
+ */
+#ifndef _ZPOOL_LIST_H_
+#define _ZPOOL_LIST_H_
+
+/*============================ Namespace Control =============================*/
+using std::string;
+
+/*=========================== Forward Declarations ===========================*/
+struct zpool_handle;
+typedef struct zpool_handle zpool_handle_t;
+
+struct nvlist;
+typedef struct nvlist nvlist_t;
+
+class Vdev;
+
+/*============================= Class Definitions ============================*/
+/*--------------------------------- ZpoolList --------------------------------*/
+class ZpoolList;
+typedef bool PoolFilter_t(zpool_handle_t *pool, nvlist_t *poolConfig,
+ void *filterArg);
+
+/**
+ * \brief Container of imported ZFS pool data.
+ *
+ * ZpoolList is a convenience class that converts libzfs's ZFS
+ * pool methods into a standard list container.
+ */
+class ZpoolList : public std::list<zpool_handle_t *>
+{
+public:
+ /**
+ * \brief Utility ZpoolList construction filter that causes all
+ * pools known to the system to be included in the
+ * instantiated ZpoolList.
+ */
+ static PoolFilter_t ZpoolAll;
+
+ /**
+ * \brief Utility ZpoolList construction filter that causes only
+ * a pool known to the system and having the specified GUID
+ * to be included in the instantiated ZpoolList.
+ */
+ static PoolFilter_t ZpoolByGUID;
+
+ /**
+ * \brief Utility ZpoolList construction filter that causes only
+ * pools known to the system and having the specified name
+ * to be included in the instantiated ZpoolList.
+ */
+ static PoolFilter_t ZpoolByName;
+
+ /**
+ * \brief ZpoolList contructor
+ *
+ * \param filter The filter function to use when constructing
+ * the ZpoolList. This may be one of the static
+ * utility filters defined for ZpoolList or a
+ * user defined function.
+ * \param filterArg A single argument to pass into the filter function
+ * when it is invoked on each candidate pool.
+ */
+ ZpoolList(PoolFilter_t *filter = ZpoolAll, void *filterArg = NULL);
+ ~ZpoolList();
+
+private:
+ /**
+ * \brief Helper routine used to populate the internal
+ * data store of ZFS pool objects using libzfs's
+ * zpool_iter() function.
+ *
+ * \param pool The ZFS pool object to filter.
+ * \param data User argument passed through zpool_iter().
+ */
+ static int LoadIterator(zpool_handle_t *pool, void *data);
+
+ /**
+ * \brief The filter with which this ZpoolList was constructed.
+ */
+ PoolFilter_t *m_filter;
+
+ /**
+ * \brief The filter argument with which this ZpoolList was
+ * constructed.
+ */
+ void *m_filterArg;
+};
+
+#endif /* _ZPOOL_ITERATOR_H_ */
diff --git a/contrib/binutils/include/libiberty.h b/contrib/binutils/include/libiberty.h
index 4e69734..555f5c7 100644
--- a/contrib/binutils/include/libiberty.h
+++ b/contrib/binutils/include/libiberty.h
@@ -102,7 +102,7 @@ extern int writeargv PARAMS ((char **, FILE *));
is 1, we found it so don't provide any declaration at all. */
#if !HAVE_DECL_BASENAME
#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) || defined (HAVE_DECL_BASENAME)
-extern char *basename (const char *);
+#include <libgen.h>
#else
/* Do not allow basename to be used if there is no prototype seen. We
either need to use the above prototype or have one from
diff --git a/contrib/blacklist/Makefile b/contrib/blacklist/Makefile
new file mode 100644
index 0000000..da4411d
--- /dev/null
+++ b/contrib/blacklist/Makefile
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.2 2015/01/22 17:49:41 christos Exp $
+
+SUBDIR = lib .WAIT include bin etc libexec
+
+.include <bsd.subdir.mk>
diff --git a/contrib/blacklist/Makefile.inc b/contrib/blacklist/Makefile.inc
new file mode 100644
index 0000000..85c8278
--- /dev/null
+++ b/contrib/blacklist/Makefile.inc
@@ -0,0 +1,10 @@
+# $NetBSD: Makefile.inc,v 1.3 2015/01/23 03:57:22 christos Exp $
+
+WARNS=6
+.if !defined(LIB)
+LDADD+= -lblacklist
+DPADD+= ${LIBBLACKLIST}
+.endif
+CPPFLAGS+= -I${.CURDIR}/../include
+CPPFLAGS+=-DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_UTIL_H -DHAVE_DB_H
+
diff --git a/contrib/blacklist/README b/contrib/blacklist/README
new file mode 100644
index 0000000..44e1026
--- /dev/null
+++ b/contrib/blacklist/README
@@ -0,0 +1,103 @@
+# $NetBSD: README,v 1.7 2015/01/26 00:34:50 christos Exp $
+
+This package contains library that can be used by network daemons to
+communicate with a packet filter via a daemon to enforce opening and
+closing ports dynamically based on policy.
+
+The interface to the packet filter is in libexec/blacklistd-helper
+(this is currently designed for npf) and the configuration file
+(inspired from inetd.conf) is in etc/blacklistd.conf.
+
+On NetBSD you can find an example npf.conf and blacklistd.conf in
+/usr/share/examples/blacklistd; you need to adjust the interface
+in npf.conf and copy both files to /etc; then you just enable
+blacklistd=YES in /etc/rc.conf, start it up, and you are all set.
+
+There is also a startup file in etc/rc.d/blacklistd
+
+Patches to various daemons to add blacklisting capabilitiers are in the
+"diff" directory:
+ - OpenSSH: diff/ssh.diff [tcp socket example]
+ - Bind: diff/named.diff [both tcp and udp]
+ - ftpd: diff/ftpd.diff [tcp]
+
+These patches have been applied to NetBSD-current.
+
+The network daemon (for example sshd) communicates to blacklistd, via
+a unix socket like syslog. The library calls are simple and everything
+is handled by the library. In the simplest form the only thing the
+daemon needs to do is to call:
+
+ blacklist(action, acceptedfd, message);
+
+Where:
+ action = 0 -> successful login clear blacklist state
+ 1 -> failed login, add to the failed count
+ acceptedfd -> the file descriptor where the server is
+ connected to the remote client. It is used
+ to determine the listening socket, and the
+ remote address. This allows any program to
+ contact the blacklist daemon, since the verification
+ if the program has access to the listening
+ socket is done by virtue that the port
+ number is retrieved from the kernel.
+ message -> an optional string that is used in debugging logs.
+
+Unfortunately there is no way to get information about the "peer"
+from a udp socket, because there is no connection and that information
+is kept with the server. In that case the daemon can provide the
+peer information to blacklistd via:
+
+ blacklist_sa(action, acceptedfd, sockaddr, sockaddr_len, message);
+
+The configuration file contains entries of the form:
+
+# Blacklist rule
+# host/Port type protocol owner name nfail disable
+192.168.1.1:ssh stream tcp * -int 10 1m
+8.8.8.8:ssh stream tcp * -ext 6 60m
+ssh stream tcp6 * * 6 60m
+http stream tcp * * 6 60m
+
+Here note that owner is * because the connection is done from the
+child ssh socket which runs with user privs. We treat ipv4 connections
+differently by maintaining two different rules one for the external
+interface and one from the internal We also register for both tcp
+and tcp6 since those are different listening sockets and addresses;
+we don't bother with ipv6 and separate rules. We use nfail = 6,
+because ssh allows 3 password attempts per connection, and this
+will let us have 2 connections before blocking. Finally we block
+for an hour; we could block forever too by specifying * in the
+duration column.
+
+blacklistd and the library use syslog(3) to report errors. The
+blacklist filter state is persisted automatically in /var/db/blacklistd.db
+so that if the daemon is restarted, it remembers what connections
+is currently handling. To start from a fresh state (if you restart
+npf too for example), you can use -f. To watch the daemon at work,
+you can use -d.
+
+The current control file is designed for npf, and it uses the
+dynamic rule feature. You need to create a dynamic rule in your
+/etc/npf.conf on the group referring to the interface you want to block
+called blacklistd as follows:
+
+ext_if=bge0
+int_if=sk0
+
+group "external" on $ext_if {
+ ...
+ ruleset "blacklistd-ext"
+ ruleset "blacklistd"
+ ...
+}
+
+group "internal" on $int_if {
+ ...
+ ruleset "blacklistd-int"
+ ...
+}
+
+Enjoy,
+
+christos
diff --git a/contrib/blacklist/TODO b/contrib/blacklist/TODO
new file mode 100644
index 0000000..9925020
--- /dev/null
+++ b/contrib/blacklist/TODO
@@ -0,0 +1,21 @@
+# $NetBSD: TODO,v 1.7 2015/01/23 21:34:01 christos Exp $
+
+- don't poll periodically, find the next timeout
+- use the socket also for commands? Or separate socket?
+- add functionality to the control program. Should it change the database
+ directly, or talk to the daemon to have it do it?
+- perhaps handle interfaces too instead of addresses for dynamic ip?
+ <bge0/4>? What to do with multiple addresses?
+- perhaps rate limit against DoS
+- perhaps instead of scanning the list have a sparse map by port?
+- do we want to use libnpf directly for efficiency?
+- add more daemons ftpd?
+- do we care about the db state becoming too large?
+- instead of a yes = bump one, no = return to 0 interface, do we want
+ to have something more flexible like?
+ +n
+ -n
+ block
+ unblock
+- do we need an api in blacklistctl to perform maintenance
+- fix the blacklistctl output to be more user friendly
diff --git a/contrib/blacklist/bin/Makefile b/contrib/blacklist/bin/Makefile
new file mode 100644
index 0000000..280c72f
--- /dev/null
+++ b/contrib/blacklist/bin/Makefile
@@ -0,0 +1,15 @@
+# $NetBSD: Makefile,v 1.11 2015/01/27 19:40:36 christos Exp $
+
+BINDIR=/sbin
+
+PROGS=blacklistd blacklistctl
+MAN.blacklistd=blacklistd.8 blacklistd.conf.5
+MAN.blacklistctl=blacklistctl.8
+SRCS.blacklistd = blacklistd.c conf.c run.c state.c support.c internal.c
+SRCS.blacklistctl = blacklistctl.c conf.c state.c support.c internal.c
+DBG=-g
+
+LDADD+=-lutil
+DPADD+=${LIBUTIL}
+
+.include <bsd.prog.mk>
diff --git a/contrib/blacklist/bin/blacklistctl.8 b/contrib/blacklist/bin/blacklistctl.8
new file mode 100644
index 0000000..d8ed1f0
--- /dev/null
+++ b/contrib/blacklist/bin/blacklistctl.8
@@ -0,0 +1,81 @@
+.\" $NetBSD: blacklistctl.8,v 1.7 2015/04/30 06:20:43 riz Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Christos Zoulas.
+.\"
+.\" 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.
+.\"
+.Dd April 29, 2015
+.Dt BLACKLISTCTL 8
+.Os
+.Sh NAME
+.Nm blacklistctl
+.Nd display and change the state of blacklistd
+.Sh SYNOPSIS
+.Nm
+.Cm dump
+.Op Fl abdnrw
+.Sh DESCRIPTION
+.Nm
+is a program used to display the state of
+.Xr blacklistd 8
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+Show all database entries, by default it shows only the embryonic ones.
+.It Fl b
+Show only the blocked entries.
+.It Fl d
+Increase debugging level.
+.It Fl n
+Don't display a header.
+.It Fl r
+Show the remaining blocked time instead of the last activity time.
+.It Fl w
+Normally the width of addresses is good for IPv4, the
+.Fl w
+flag, makes the display wide enough for IPv6 addresses.
+.El
+.Sh SEE ALSO
+.Xr blacklistd 8
+.Sh NOTES
+Sometimes the reported number of failed attempts can exceed the number
+of attempts that
+.Xr blacklistd 8
+is configured to block.
+This can happen either because the rule has been removed manually, or
+because there were more attempts in flight while the rule block was being
+added.
+This condition is normal; in that case
+.Xr blacklistd 8
+will first attempt to remove the existing rule, and then it will re-add
+it to make sure that there is only one rule active.
+.Sh HISTORY
+.Nm
+appeared in
+.Nx 7 .
+.Sh AUTHORS
+.An Christos Zoulas
diff --git a/contrib/blacklist/bin/blacklistctl.c b/contrib/blacklist/bin/blacklistctl.c
new file mode 100644
index 0000000..d202fb1
--- /dev/null
+++ b/contrib/blacklist/bin/blacklistctl.c
@@ -0,0 +1,151 @@
+/* $NetBSD: blacklistctl.c,v 1.20 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: blacklistctl.c,v 1.20 2016/04/04 15:52:56 christos Exp $");
+
+#include <stdio.h>
+#include <time.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <fcntl.h>
+#include <string.h>
+#include <syslog.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "conf.h"
+#include "state.h"
+#include "internal.h"
+#include "support.h"
+
+static __dead void
+usage(int c)
+{
+ if (c == 0)
+ warnx("Missing/unknown command");
+ else
+ warnx("Unknown option `%c'", (char)c);
+ fprintf(stderr, "Usage: %s dump [-abdnrw]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *dbname = _PATH_BLSTATE;
+ DB *db;
+ struct conf c;
+ struct dbinfo dbi;
+ unsigned int i;
+ struct timespec ts;
+ int all, blocked, remain, wide, noheader;
+ int o;
+
+ noheader = wide = blocked = all = remain = 0;
+ lfun = dlog;
+
+ if (argc == 1 || strcmp(argv[1], "dump") != 0)
+ usage(0);
+
+ argc--;
+ argv++;
+
+ while ((o = getopt(argc, argv, "abD:dnrw")) != -1)
+ switch (o) {
+ case 'a':
+ all = 1;
+ blocked = 0;
+ break;
+ case 'b':
+ blocked = 1;
+ case 'D':
+ dbname = optarg;
+ break;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ noheader = 1;
+ break;
+ case 'r':
+ remain = 1;
+ break;
+ case 'w':
+ wide = 1;
+ break;
+ default:
+ usage(o);
+ break;
+ }
+
+ db = state_open(dbname, O_RDONLY, 0);
+ if (db == NULL)
+ err(EXIT_FAILURE, "Can't open `%s'", dbname);
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ wide = wide ? 8 * 4 + 7 : 4 * 3 + 3;
+ if (!noheader)
+ printf("%*.*s/ma:port\tid\tnfail\t%s\n", wide, wide,
+ "address", remain ? "remaining time" : "last access");
+ for (i = 1; state_iterate(db, &c, &dbi, i) != 0; i = 0) {
+ char buf[BUFSIZ];
+ if (!all) {
+ if (blocked) {
+ if (dbi.count < c.c_nfail)
+ continue;
+ } else {
+ if (dbi.count >= c.c_nfail)
+ continue;
+ }
+ }
+ sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&c.c_ss);
+ printf("%*.*s/%d:%d\t", wide, wide, buf, c.c_lmask, c.c_port);
+ if (remain)
+ fmtydhms(buf, sizeof(buf),
+ c.c_duration - (ts.tv_sec - dbi.last));
+ else
+ fmttime(buf, sizeof(buf), dbi.last);
+ printf("%s\t%d/%d\t%-s\n", dbi.id, dbi.count, c.c_nfail, buf);
+ }
+ state_close(db);
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/blacklist/bin/blacklistd.8 b/contrib/blacklist/bin/blacklistd.8
new file mode 100644
index 0000000..80a53da
--- /dev/null
+++ b/contrib/blacklist/bin/blacklistd.8
@@ -0,0 +1,222 @@
+.\" $NetBSD: blacklistd.8,v 1.15 2016/03/11 17:16:40 christos Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Christos Zoulas.
+.\"
+.\" 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.
+.\"
+.Dd June 4, 2015
+.Dt BLACKLISTD 8
+.Os
+.Sh NAME
+.Nm blacklistd
+.Nd block and release ports on demand to avoid DoS abuse
+.Sh SYNOPSIS
+.Nm
+.Op Fl dfrv
+.Op Fl C Ar controlprog
+.Op Fl c Ar configfile
+.Op Fl D Ar dbfile
+.Op Fl P Ar sockpathsfile
+.Op Fl R Ar rulename
+.Op Fl s Ar sockpath
+.Op Fl t Ar timeout
+.Sh DESCRIPTION
+.Nm
+is a daemon similar to
+.Xr syslogd 8
+that listens to a sockets at paths specified in the
+.Ar sockpathsfile
+for notifications from other daemons about successful or failed connection
+attempts.
+If no such file is specified, then it only listens to the socket path
+specified by
+.Ar sockspath
+or if that is not specified to
+.Pa /var/run/blacklistd.sock .
+Each notification contains an (action, port, protocol, address, owner) tuple
+that identifies the remote connection and the action.
+This tuple is consulted against entries in
+.Ar configfile
+with syntax specified in
+.Xr blacklistd.conf 5 .
+If an entry is matched, a state entry is created for that tuple.
+Each entry contains a number of tries limit and a duration.
+.Pp
+If the action is
+.Dq add
+and the number of tries limit is reached, then a
+control script
+.Ar controlprog
+is invoked with arguments:
+.Bd -literal -offset indent
+control add <rulename> <proto> <address> <mask> <port>
+.Ed
+.Pp
+and should invoke a packet filter command to block the connection
+specified by the arguments.
+The
+.Ar rulename
+argument can be set from the command line (default
+.Dv blacklistd ) .
+The script could print a numerical id to stdout as a handle for
+the rule that can be used later to remove that connection, but
+that is not required as all information to remove the rule is
+kept.
+.Pp
+If the action is
+.Dq remove
+Then the same control script is invoked as:
+.Bd -literal -offset indent
+control remove <rulename> <proto> <address> <mask> <port> <id>
+.Ed
+.Pp
+where
+.Ar id
+is the number returned from the
+.Dq add
+action.
+.Pp
+.Nm
+maintains a database of known connections in
+.Ar dbfile .
+On startup it reads entries from that file, and updates its internal state.
+.Pp
+.Nm
+checks the list of active entries every
+.Ar timeout
+seconds (default
+.Dv 15 )
+and removes entries and block rules using the control program as necessary.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl C Ar controlprog
+Use
+.Ar controlprog
+to communicate with the packet filter, usually
+.Pa /usr/libexec/blacklistd-helper .
+The following arguments are passed to the control program:
+.Bl -tag -width protocol
+.It action
+The action to perform:
+.Dv add ,
+.Dv rem ,
+or
+.Dv flush
+to add, remove or flush a firewall rule.
+.It name
+The rule name.
+.It protocol
+The optional protocol name (can be empty):
+.Dv tcp ,
+.Dv tcp6 ,
+.Dv udp ,
+.Dv udp6 .
+.It address
+The IPv4 or IPv6 numeric address to be blocked or released.
+.It mask
+The numeric mask to be applied to the blocked or released address
+.It port
+The optional numeric port to be blocked (can be empty).
+.It id
+For packet filters that support removal of rules by rule identifier, the
+identifier of the rule to be removed.
+The add command is expected to return the rule identifier string to stdout.
+.El
+.It Fl c Ar configuration
+The name of the configuration file to read, usually
+.Pa /etc/blacklistd.conf .
+.It Fl D Ar dbfile
+The Berkeley DB file where
+.Nm
+stores its state, usually
+.Pa /var/run/blacklistd.db .
+.It Fl d
+Normally,
+.Nm
+disassociates itself from the terminal unless the
+.Fl d
+flag is specified, in which case it stays in the foreground.
+.It Fl f
+Truncate the state database and flush all the rules named
+.Ar rulename
+are deleted by invoking the control script as:
+.Bd -literal -offset indent
+control flush <rulename>
+.Ed
+.It Fl P Ar sockspathsfile
+A file containing a list of pathnames, one per line that
+.Nm
+will create sockets to listen to.
+This is useful for chrooted environments.
+.It Fl R Ar rulename
+Specify the default rule name for the packet filter rules, usually
+.Dv blacklistd .
+.It Fl r
+Re-read the firewall rules from the internal database, then
+remove and re-add them.
+This helps for packet filters that don't retain state across reboots.
+.It Fl s Ar sockpath
+Add
+.Ar sockpath
+to the list of Unix sockets
+.Nm
+listens to.
+.It Fl t Ar timeout
+The interval in seconds
+.Nm
+polls the state file to update the rules.
+.It Fl v
+Cause
+.Nm
+to print
+diagnostic messages to
+.Dv stdout
+instead of
+.Xr syslogd 8 .
+.El
+.Sh FILES
+.Bl -tag -width /usr/libexec/blacklistd-helper -compact
+.It Pa /usr/libexec/blacklistd-helper
+Shell script invoked to interface with the packet filter.
+.It Pa /etc/blacklistd.conf
+Configuration file.
+.It Pa /var/db/blacklistd.db
+Database of current connection entries.
+.It Pa /var/run/blacklistd.sock
+Socket to receive connection notifications.
+.El
+.Sh SEE ALSO
+.Xr blacklistd.conf 5 ,
+.Xr blacklistctl 8 ,
+.Xr npfctl 8 ,
+.Xr syslogd 8
+.Sh HISTORY
+.Nm
+appeared in
+.Nx 7 .
+.Sh AUTHORS
+.An Christos Zoulas
diff --git a/contrib/blacklist/bin/blacklistd.c b/contrib/blacklist/bin/blacklistd.c
new file mode 100644
index 0000000..c16b18e
--- /dev/null
+++ b/contrib/blacklist/bin/blacklistd.c
@@ -0,0 +1,537 @@
+/* $NetBSD: blacklistd.c,v 1.34 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: blacklistd.c,v 1.34 2016/04/04 15:52:56 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <inttypes.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+
+#include "bl.h"
+#include "internal.h"
+#include "conf.h"
+#include "run.h"
+#include "state.h"
+#include "support.h"
+
+static const char *configfile = _PATH_BLCONF;
+static DB *state;
+static const char *dbfile = _PATH_BLSTATE;
+static sig_atomic_t readconf;
+static sig_atomic_t done;
+static int vflag;
+
+static void
+sigusr1(int n __unused)
+{
+ debug++;
+}
+
+static void
+sigusr2(int n __unused)
+{
+ debug--;
+}
+
+static void
+sighup(int n __unused)
+{
+ readconf++;
+}
+
+static void
+sigdone(int n __unused)
+{
+ done++;
+}
+
+static __dead void
+usage(int c)
+{
+ if (c)
+ warnx("Unknown option `%c'", (char)c);
+ fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] "
+ "[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] "
+ "[-s <sockpath>] [-t <timeout>]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static int
+getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl)
+{
+ *rsl = sizeof(*rss);
+ memset(rss, 0, *rsl);
+
+ if (getpeername(bi->bi_fd, (void *)rss, rsl) != -1)
+ return 0;
+
+ if (errno != ENOTCONN) {
+ (*lfun)(LOG_ERR, "getpeername failed (%m)");
+ return -1;
+ }
+
+ if (bi->bi_slen == 0) {
+ (*lfun)(LOG_ERR, "unconnected socket with no peer in message");
+ return -1;
+ }
+
+ switch (bi->bi_ss.ss_family) {
+ case AF_INET:
+ *rsl = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ *rsl = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ (*lfun)(LOG_ERR, "bad client passed socket family %u",
+ (unsigned)bi->bi_ss.ss_family);
+ return -1;
+ }
+
+ if (*rsl != bi->bi_slen) {
+ (*lfun)(LOG_ERR, "bad client passed socket length %u != %u",
+ (unsigned)*rsl, (unsigned)bi->bi_slen);
+ return -1;
+ }
+
+ memcpy(rss, &bi->bi_ss, *rsl);
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (*rsl != rss->ss_len) {
+ (*lfun)(LOG_ERR,
+ "bad client passed socket internal length %u != %u",
+ (unsigned)*rsl, (unsigned)rss->ss_len);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static void
+process(bl_t bl)
+{
+ struct sockaddr_storage rss;
+ socklen_t rsl;
+ char rbuf[BUFSIZ];
+ bl_info_t *bi;
+ struct conf c;
+ struct dbinfo dbi;
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
+ return;
+ }
+
+ if ((bi = bl_recv(bl)) == NULL) {
+ (*lfun)(LOG_ERR, "no message (%m)");
+ return;
+ }
+
+ if (getremoteaddress(bi, &rss, &rsl) == -1)
+ goto out;
+
+ if (debug) {
+ sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss);
+ (*lfun)(LOG_DEBUG, "processing type=%d fd=%d remote=%s msg=%s"
+ " uid=%lu gid=%lu", bi->bi_type, bi->bi_fd, rbuf,
+ bi->bi_msg, (unsigned long)bi->bi_uid,
+ (unsigned long)bi->bi_gid);
+ }
+
+ if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) {
+ (*lfun)(LOG_DEBUG, "no rule matched");
+ goto out;
+ }
+
+
+ if (state_get(state, &c, &dbi) == -1)
+ goto out;
+
+ if (debug) {
+ char b1[128], b2[128];
+ (*lfun)(LOG_DEBUG, "%s: db state info for %s: count=%d/%d "
+ "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail,
+ fmttime(b1, sizeof(b1), dbi.last),
+ fmttime(b2, sizeof(b2), ts.tv_sec));
+ }
+
+ switch (bi->bi_type) {
+ case BL_ADD:
+ dbi.count++;
+ dbi.last = ts.tv_sec;
+ if (dbi.id[0]) {
+ /*
+ * We should not be getting this since the rule
+ * should have blocked the address. A possible
+ * explanation is that someone removed that rule,
+ * and another would be that we got another attempt
+ * before we added the rule. In anycase, we remove
+ * and re-add the rule because we don't want to add
+ * it twice, because then we'd lose track of it.
+ */
+ (*lfun)(LOG_DEBUG, "rule exists %s", dbi.id);
+ (void)run_change("rem", &c, dbi.id, 0);
+ dbi.id[0] = '\0';
+ }
+ if (c.c_nfail != -1 && dbi.count >= c.c_nfail) {
+ int res = run_change("add", &c, dbi.id, sizeof(dbi.id));
+ if (res == -1)
+ goto out;
+ sockaddr_snprintf(rbuf, sizeof(rbuf), "%a",
+ (void *)&rss);
+ (*lfun)(LOG_INFO,
+ "blocked %s/%d:%d for %d seconds",
+ rbuf, c.c_lmask, c.c_port, c.c_duration);
+
+ }
+ break;
+ case BL_DELETE:
+ if (dbi.last == 0)
+ goto out;
+ dbi.last = 0;
+ break;
+ default:
+ (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type);
+ }
+ if (state_put(state, &c, &dbi) == -1)
+ goto out;
+out:
+ close(bi->bi_fd);
+}
+
+static void
+update_interfaces(void)
+{
+ struct ifaddrs *oifas, *nifas;
+
+ if (getifaddrs(&nifas) == -1)
+ return;
+
+ oifas = ifas;
+ ifas = nifas;
+
+ if (oifas)
+ freeifaddrs(oifas);
+}
+
+static void
+update(void)
+{
+ struct timespec ts;
+ struct conf c;
+ struct dbinfo dbi;
+ unsigned int f, n;
+ char buf[128];
+ void *ss = &c.c_ss;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
+ return;
+ }
+
+again:
+ for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1;
+ f = 0, n++)
+ {
+ time_t when = c.c_duration + dbi.last;
+ if (debug > 1) {
+ char b1[64], b2[64];
+ sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss);
+ (*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d "
+ "last=%s " "now=%s", __func__, n, buf, dbi.count,
+ c.c_duration, fmttime(b1, sizeof(b1), dbi.last),
+ fmttime(b2, sizeof(b2), ts.tv_sec));
+ }
+ if (c.c_duration == -1 || when >= ts.tv_sec)
+ continue;
+ if (dbi.id[0]) {
+ run_change("rem", &c, dbi.id, 0);
+ sockaddr_snprintf(buf, sizeof(buf), "%a", ss);
+ syslog(LOG_INFO, "released %s/%d:%d after %d seconds",
+ buf, c.c_lmask, c.c_port, c.c_duration);
+ }
+ state_del(state, &c);
+ goto again;
+ }
+}
+
+static void
+addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd,
+ const char *path)
+{
+ bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog);
+ if (bl == NULL || !bl_isconnected(bl))
+ exit(EXIT_FAILURE);
+ if (*nfd >= *maxfd) {
+ *maxfd += 10;
+ *blp = realloc(*blp, sizeof(**blp) * *maxfd);
+ if (*blp == NULL)
+ err(EXIT_FAILURE, "malloc");
+ *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd);
+ if (*pfdp == NULL)
+ err(EXIT_FAILURE, "malloc");
+ }
+
+ (*pfdp)[*nfd].fd = bl_getfd(bl);
+ (*pfdp)[*nfd].events = POLLIN;
+ (*blp)[*nfd] = bl;
+ *nfd += 1;
+}
+
+static void
+uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c)
+{
+ struct conf **list = *listp;
+
+ if (c->c_name[0] == '\0')
+ return;
+ for (size_t i = 0; i < *nlist; i++) {
+ if (strcmp(list[i]->c_name, c->c_name) == 0)
+ return;
+ }
+ if (*nlist == *mlist) {
+ *mlist += 10;
+ void *p = realloc(*listp, *mlist * sizeof(*list));
+ if (p == NULL)
+ err(EXIT_FAILURE, "Can't allocate for rule list");
+ list = *listp = p;
+ }
+ list[(*nlist)++] = c;
+}
+
+static void
+rules_flush(void)
+{
+ struct conf **list;
+ size_t nlist, mlist;
+
+ list = NULL;
+ mlist = nlist = 0;
+ for (size_t i = 0; i < rconf.cs_n; i++)
+ uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]);
+ for (size_t i = 0; i < lconf.cs_n; i++)
+ uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]);
+
+ for (size_t i = 0; i < nlist; i++)
+ run_flush(list[i]);
+ free(list);
+}
+
+static void
+rules_restore(void)
+{
+ struct conf c;
+ struct dbinfo dbi;
+ unsigned int f;
+
+ for (f = 1; state_iterate(state, &c, &dbi, f) == 1; f = 0) {
+ if (dbi.id[0] == '\0')
+ continue;
+ (void)run_change("rem", &c, dbi.id, 0);
+ (void)run_change("add", &c, dbi.id, sizeof(dbi.id));
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c, tout, flags, flush, restore;
+ const char *spath, *blsock;
+
+ setprogname(argv[0]);
+
+ spath = NULL;
+ blsock = _PATH_BLSOCK;
+ flush = 0;
+ restore = 0;
+ tout = 0;
+ flags = O_RDWR|O_EXCL|O_CLOEXEC;
+ while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) {
+ switch (c) {
+ case 'C':
+ controlprog = optarg;
+ break;
+ case 'c':
+ configfile = optarg;
+ break;
+ case 'D':
+ dbfile = optarg;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'f':
+ flush++;
+ break;
+ case 'P':
+ spath = optarg;
+ break;
+ case 'R':
+ rulename = optarg;
+ break;
+ case 'r':
+ restore++;
+ break;
+ case 's':
+ blsock = optarg;
+ break;
+ case 't':
+ tout = atoi(optarg) * 1000;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage(c);
+ }
+ }
+
+ argc -= optind;
+ if (argc)
+ usage(0);
+
+ signal(SIGHUP, sighup);
+ signal(SIGINT, sigdone);
+ signal(SIGQUIT, sigdone);
+ signal(SIGTERM, sigdone);
+ signal(SIGUSR1, sigusr1);
+ signal(SIGUSR2, sigusr2);
+
+ openlog(getprogname(), LOG_PID, LOG_DAEMON);
+
+ if (debug) {
+ lfun = dlog;
+ if (tout == 0)
+ tout = 5000;
+ } else {
+ if (tout == 0)
+ tout = 15000;
+ }
+
+ update_interfaces();
+ conf_parse(configfile);
+ if (flush) {
+ rules_flush();
+ flags |= O_TRUNC;
+ }
+
+ if (restore)
+ rules_restore();
+
+ struct pollfd *pfd = NULL;
+ bl_t *bl = NULL;
+ size_t nfd = 0;
+ size_t maxfd = 0;
+
+ if (spath == NULL)
+ addfd(&pfd, &bl, &nfd, &maxfd, blsock);
+ else {
+ FILE *fp = fopen(spath, "r");
+ char *line;
+ if (fp == NULL)
+ err(EXIT_FAILURE, "Can't open `%s'", spath);
+ for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL;
+ free(line))
+ addfd(&pfd, &bl, &nfd, &maxfd, line);
+ fclose(fp);
+ }
+
+ state = state_open(dbfile, flags, 0600);
+ if (state == NULL)
+ state = state_open(dbfile, flags | O_CREAT, 0600);
+ if (state == NULL)
+ return EXIT_FAILURE;
+
+ if (!debug) {
+ if (daemon(0, 0) == -1)
+ err(EXIT_FAILURE, "daemon failed");
+ if (pidfile(NULL) == -1)
+ err(EXIT_FAILURE, "Can't create pidfile");
+ }
+
+ for (size_t t = 0; !done; t++) {
+ if (readconf) {
+ readconf = 0;
+ conf_parse(configfile);
+ }
+ switch (poll(pfd, (nfds_t)nfd, tout)) {
+ case -1:
+ if (errno == EINTR)
+ continue;
+ (*lfun)(LOG_ERR, "poll (%m)");
+ return EXIT_FAILURE;
+ case 0:
+ state_sync(state);
+ break;
+ default:
+ for (size_t i = 0; i < nfd; i++)
+ if (pfd[i].revents & POLLIN)
+ process(bl[i]);
+ }
+ if (t % 100 == 0)
+ state_sync(state);
+ if (t % 10000 == 0)
+ update_interfaces();
+ update();
+ }
+ state_close(state);
+ return 0;
+}
diff --git a/contrib/blacklist/bin/blacklistd.conf.5 b/contrib/blacklist/bin/blacklistd.conf.5
new file mode 100644
index 0000000..40d507b
--- /dev/null
+++ b/contrib/blacklist/bin/blacklistd.conf.5
@@ -0,0 +1,222 @@
+.\" $NetBSD: blacklistd.conf.5,v 1.3 2015/04/30 06:20:43 riz Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Christos Zoulas.
+.\"
+.\" 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.
+.\"
+.Dd April 29, 2015
+.Dt BLACKLISTD.CONF 5
+.Os
+.Sh NAME
+.Nm blacklistd.conf
+.Nd configuration file format for blacklistd
+.Sh DESCRIPTION
+The
+.Nm
+files contains configuration lines for
+.Xr blacklistd 8 .
+It contains one entry per line, and is similar to
+.Xr inetd.conf 5 .
+There must be an entry for each field of the configuration file, with
+entries for each field separated by a tab or a space.
+Comments are denoted by a
+.Dq #
+at the beginning of a line.
+.Pp
+There are two kinds of configuration lines,
+.Va local
+and
+.Va remote .
+By default, configuration lines are
+.Va local ,
+i.e. the address specified refers to the addresses on the local machine.
+To switch to between
+.Va local
+and
+.Va remote
+configuration lines you can specify the stanzas:
+.Dq [local]
+and
+.Dq [remote] .
+.Pp
+On
+.Va local
+and
+.Va remote
+lines
+.Dq *
+means use the default, or wildcard match.
+In addition, for
+.Va remote
+lines
+.Dq =
+means use the values from the matched
+.Va local
+configuration line.
+.Pp
+The first four fields,
+.Va location ,
+.Va type ,
+.Va proto ,
+and
+.Va owner
+are used to match the
+.Va local
+or
+.Va remote
+addresses, whereas the last 3 fields
+.Va name ,
+.Va nfail ,
+and
+.Va disable
+are used to modify the filtering action.
+.Pp
+The first field denotes the
+.Va location
+as an address, mask, and port.
+The syntax for the
+.Va location
+is:
+.Bd -literal -offset indent
+ [<address>|<interface>][/<mask>][:<port>]
+.Ed
+.Pp
+The
+.Dv address
+can be an IPv4 address in numeric format, an IPv6 address
+in numeric format and enclosed by square brackets, or an interface name.
+Mask modifiers are not allowed on interfaces because interfaces
+have multiple address in different protocols where the mask has a different
+size.
+.Pp
+The
+.Dv mask
+is always numeric, but the
+.Dv port
+can be either numeric or symbolic.
+.Pp
+The second field is the socket
+.Va type :
+.Dv stream ,
+.Dv dgram ,
+or numeric.
+The third field is the
+.Va prococol :
+.Dv tcp ,
+.Dv udp ,
+.Dv tcp6 ,
+.Dv udp6 ,
+or numeric.
+The fourth file is the effective user
+.Va ( owner )
+of the daemon process reporting the event,
+either as a username or a userid.
+.Pp
+The rest of the fields are controlling the behavior of the filter.
+.Pp
+The
+.Va name
+field, is the name of the packet filter rule to be used.
+If the
+.Va name
+starts with a
+.Dq - ,
+then the default rulename is prepended to the given name.
+If the
+.Dv name
+contains a
+.Dq / ,
+the remaining portion of the name is interpreted as the mask to be
+applied to the address specified in the rule, so one can block whole
+subnets for a single rule violation.
+.Pp
+The
+.Va nfail
+field contains the number of failed attempts before access is blocked,
+defaulting to
+.Dq *
+meaning never, and the last field
+.Va disable
+specifies the amount of time since the last access that the blocking
+rule should be active, defaulting to
+.Dq *
+meaning forever.
+The default unit for
+.Va disable
+is seconds, but one can specify suffixes for different units, such as
+.Dq m
+for minutes
+.Dq h
+for hours and
+.Dq d
+for days.
+.Pp
+Matching is done first by checking the
+.Va local
+rules one by one, from the most specific to the least specific.
+If a match is found, then the
+.Va remote
+rules are applied, and if a match is found the
+.Va name ,
+.Va nfail ,
+and
+.Va disable
+fields can be altered by the
+.Va remote
+rule that matched.
+.Pp
+The
+.Va remote
+rules can be used for whitelisting specific addresses, changing the mask
+size, or the rule that the packet filter uses, the number of failed attempts,
+or the blocked duration.
+.Sh FILES
+.Bl -tag -width /etc/blacklistd.conf -compact
+.It Pa /etc/blacklistd.conf
+Configuration file.
+.El
+.Sh EXAMPLES
+.Bd -literal -offset
+# Block ssh, after 3 attempts for 6 hours on the bnx0 interface
+[local]
+# location type proto owner name nfail duration
+bnx0:ssh * * * * 3 6h
+[remote]
+# Never block 1.2.3.4
+1.2.3.4:ssh * * * * * *
+# For addresses coming from 8.8.0.0/16 block class C networks instead
+# individual hosts, but keep the rest of the blocking parameters the same.
+8.8.0.0/16:ssh * * * /24 = =
+.Ed
+.Sh SEE ALSO
+.Xr blacklistctl 8 ,
+.Xr blacklistd 8
+.Sh HISTORY
+.Nm
+appeared in
+.Nx 7 .
+.Sh AUTHORS
+.An Christos Zoulas
diff --git a/contrib/blacklist/bin/conf.c b/contrib/blacklist/bin/conf.c
new file mode 100644
index 0000000..3ec1e08
--- /dev/null
+++ b/contrib/blacklist/bin/conf.c
@@ -0,0 +1,1142 @@
+/* $NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $");
+
+#include <stdio.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/socket.h>
+
+#include "bl.h"
+#include "internal.h"
+#include "support.h"
+#include "conf.h"
+
+
+struct sockaddr_if {
+ uint8_t sif_len;
+ sa_family_t sif_family;
+ in_port_t sif_port;
+ char sif_name[16];
+};
+
+#define SIF_NAME(a) \
+ ((const struct sockaddr_if *)(const void *)(a))->sif_name
+
+static int conf_is_interface(const char *);
+
+#define FSTAR -1
+#define FEQUAL -2
+
+static void
+advance(char **p)
+{
+ char *ep = *p;
+ while (*ep && !isspace((unsigned char)*ep))
+ ep++;
+ while (*ep && isspace((unsigned char)*ep))
+ *ep++ = '\0';
+ *p = ep;
+}
+
+static int
+getnum(const char *f, size_t l, bool local, void *rp, const char *name,
+ const char *p)
+{
+ int e;
+ intmax_t im;
+ int *r = rp;
+
+ if (strcmp(p, "*") == 0) {
+ *r = FSTAR;
+ return 0;
+ }
+ if (strcmp(p, "=") == 0) {
+ if (local)
+ goto out;
+ *r = FEQUAL;
+ return 0;
+ }
+
+ im = strtoi(p, NULL, 0, 0, INT_MAX, &e);
+ if (e == 0) {
+ *r = (int)im;
+ return 0;
+ }
+
+ if (f == NULL)
+ return -1;
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Bad number for %s [%s]", __func__, f, l,
+ name, p);
+ return -1;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' for %s not allowed in local config",
+ __func__, f, l, name);
+ return -1;
+
+}
+
+static int
+getnfail(const char *f, size_t l, bool local, struct conf *c, const char *p)
+{
+ return getnum(f, l, local, &c->c_nfail, "nfail", p);
+}
+
+static int
+getsecs(const char *f, size_t l, bool local, struct conf *c, const char *p)
+{
+ int e;
+ char *ep;
+ intmax_t tot, im;
+
+ tot = 0;
+ if (strcmp(p, "*") == 0) {
+ c->c_duration = FSTAR;
+ return 0;
+ }
+ if (strcmp(p, "=") == 0) {
+ if (local)
+ goto out;
+ c->c_duration = FEQUAL;
+ return 0;
+ }
+again:
+ im = strtoi(p, &ep, 0, 0, INT_MAX, &e);
+
+ if (e == ENOTSUP) {
+ switch (*ep) {
+ case 'd':
+ im *= 24;
+ /*FALLTHROUGH*/
+ case 'h':
+ im *= 60;
+ /*FALLTHROUGH*/
+ case 'm':
+ im *= 60;
+ /*FALLTHROUGH*/
+ case 's':
+ e = 0;
+ tot += im;
+ if (ep[1] != '\0') {
+ p = ep + 2;
+ goto again;
+ }
+ break;
+ }
+ } else
+ tot = im;
+
+ if (e == 0) {
+ c->c_duration = (int)tot;
+ return 0;
+ }
+
+ if (f == NULL)
+ return -1;
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Bad number [%s]", __func__, f, l, p);
+ return -1;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' duration not allowed in local"
+ " config", __func__, f, l);
+ return -1;
+
+}
+
+static int
+getport(const char *f, size_t l, bool local, void *r, const char *p)
+{
+ struct servent *sv;
+
+ // XXX: Pass in the proto instead
+ if ((sv = getservbyname(p, "tcp")) != NULL) {
+ *(int *)r = ntohs(sv->s_port);
+ return 0;
+ }
+ if ((sv = getservbyname(p, "udp")) != NULL) {
+ *(int *)r = ntohs(sv->s_port);
+ return 0;
+ }
+
+ return getnum(f, l, local, r, "service", p);
+}
+
+static int
+getmask(const char *f, size_t l, bool local, const char **p, int *mask)
+{
+ char *d;
+ const char *s = *p;
+
+ if ((d = strchr(s, ':')) != NULL) {
+ *d++ = '\0';
+ *p = d;
+ }
+ if ((d = strchr(s, '/')) == NULL) {
+ *mask = FSTAR;
+ return 0;
+ }
+
+ *d++ = '\0';
+ return getnum(f, l, local, mask, "mask", d);
+}
+
+static int
+gethostport(const char *f, size_t l, bool local, struct conf *c, const char *p)
+{
+ char *d; // XXX: Ok to write to string.
+ in_port_t *port = NULL;
+ const char *pstr;
+
+ if (strcmp(p, "*") == 0) {
+ c->c_port = FSTAR;
+ c->c_lmask = FSTAR;
+ return 0;
+ }
+
+ if ((d = strchr(p, ']')) != NULL) {
+ *d++ = '\0';
+ pstr = d;
+ p++;
+ } else
+ pstr = p;
+
+ if (getmask(f, l, local, &pstr, &c->c_lmask) == -1)
+ goto out;
+
+ if (d) {
+ struct sockaddr_in6 *sin6 = (void *)&c->c_ss;
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: host6 %s", __func__, p);
+ if (strcmp(p, "*") != 0) {
+ if (inet_pton(AF_INET6, p, &sin6->sin6_addr) == -1)
+ goto out;
+ sin6->sin6_family = AF_INET6;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ sin6->sin6_len = sizeof(*sin6);
+#endif
+ port = &sin6->sin6_port;
+ }
+ } else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) {
+ if (pstr == p)
+ pstr = "*";
+ struct sockaddr_in *sin = (void *)&c->c_ss;
+ struct sockaddr_if *sif = (void *)&c->c_ss;
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: host4 %s", __func__, p);
+ if (strcmp(p, "*") != 0) {
+ if (conf_is_interface(p)) {
+ if (!local)
+ goto out2;
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: interface %s",
+ __func__, p);
+ if (c->c_lmask != FSTAR)
+ goto out1;
+ sif->sif_family = AF_MAX;
+ strlcpy(sif->sif_name, p,
+ sizeof(sif->sif_name));
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ sif->sif_len = sizeof(*sif);
+#endif
+ port = &sif->sif_port;
+ } else if (inet_pton(AF_INET, p, &sin->sin_addr) != -1)
+ {
+ sin->sin_family = AF_INET;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ sin->sin_len = sizeof(*sin);
+#endif
+ port = &sin->sin_port;
+ } else
+ goto out;
+ }
+ }
+
+ if (getport(f, l, local, &c->c_port, pstr) == -1)
+ return -1;
+
+ if (port && c->c_port != FSTAR && c->c_port != FEQUAL)
+ *port = htons((in_port_t)c->c_port);
+ return 0;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, pstr);
+ return -1;
+out1:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Can't specify mask %d with "
+ "interface [%s]", __func__, f, l, c->c_lmask, p);
+ return -1;
+out2:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Interface spec does not make sense "
+ "with remote config [%s]", __func__, f, l, p);
+ return -1;
+}
+
+static int
+getproto(const char *f, size_t l, bool local __unused, struct conf *c,
+ const char *p)
+{
+ if (strcmp(p, "stream") == 0) {
+ c->c_proto = IPPROTO_TCP;
+ return 0;
+ }
+ if (strcmp(p, "dgram") == 0) {
+ c->c_proto = IPPROTO_UDP;
+ return 0;
+ }
+ return getnum(f, l, local, &c->c_proto, "protocol", p);
+}
+
+static int
+getfamily(const char *f, size_t l, bool local __unused, struct conf *c,
+ const char *p)
+{
+ if (strncmp(p, "tcp", 3) == 0 || strncmp(p, "udp", 3) == 0) {
+ c->c_family = p[3] == '6' ? AF_INET6 : AF_INET;
+ return 0;
+ }
+ return getnum(f, l, local, &c->c_family, "family", p);
+}
+
+static int
+getuid(const char *f, size_t l, bool local __unused, struct conf *c,
+ const char *p)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwnam(p)) != NULL) {
+ c->c_uid = (int)pw->pw_uid;
+ return 0;
+ }
+
+ return getnum(f, l, local, &c->c_uid, "user", p);
+}
+
+
+static int
+getname(const char *f, size_t l, bool local, struct conf *c,
+ const char *p)
+{
+ if (getmask(f, l, local, &p, &c->c_rmask) == -1)
+ return -1;
+
+ if (strcmp(p, "*") == 0) {
+ strlcpy(c->c_name, rulename, CONFNAMESZ);
+ return 0;
+ }
+ if (strcmp(p, "=") == 0) {
+ if (local)
+ goto out;
+ c->c_name[0] = '\0';
+ return 0;
+ }
+
+ snprintf(c->c_name, CONFNAMESZ, "%s%s", *p == '-' ? rulename : "", p);
+ return 0;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' name not allowed in local"
+ " config", __func__, f, l);
+ return -1;
+}
+
+static int
+getvalue(const char *f, size_t l, bool local, void *r, char **p,
+ int (*fun)(const char *, size_t, bool, struct conf *, const char *))
+{
+ char *ep = *p;
+
+ advance(p);
+ return (*fun)(f, l, local, r, ep);
+}
+
+
+static int
+conf_parseline(const char *f, size_t l, char *p, struct conf *c, bool local)
+{
+ int e;
+
+ while (*p && isspace((unsigned char)*p))
+ p++;
+
+ memset(c, 0, sizeof(*c));
+ e = getvalue(f, l, local, c, &p, gethostport);
+ if (e) return -1;
+ e = getvalue(f, l, local, c, &p, getproto);
+ if (e) return -1;
+ e = getvalue(f, l, local, c, &p, getfamily);
+ if (e) return -1;
+ e = getvalue(f, l, local, c, &p, getuid);
+ if (e) return -1;
+ e = getvalue(f, l, local, c, &p, getname);
+ if (e) return -1;
+ e = getvalue(f, l, local, c, &p, getnfail);
+ if (e) return -1;
+ e = getvalue(f, l, local, c, &p, getsecs);
+ if (e) return -1;
+
+ return 0;
+}
+
+static int
+conf_sort(const void *v1, const void *v2)
+{
+ const struct conf *c1 = v1;
+ const struct conf *c2 = v2;
+
+#define CMP(a, b, f) \
+ if ((a)->f > (b)->f) return -1; \
+ else if ((a)->f < (b)->f) return 1
+
+ CMP(c1, c2, c_ss.ss_family);
+ CMP(c1, c2, c_lmask);
+ CMP(c1, c2, c_port);
+ CMP(c1, c2, c_proto);
+ CMP(c1, c2, c_family);
+ CMP(c1, c2, c_rmask);
+ CMP(c1, c2, c_uid);
+#undef CMP
+ return 0;
+}
+
+static int
+conf_is_interface(const char *name)
+{
+ const struct ifaddrs *ifa;
+
+ for (ifa = ifas; ifa; ifa = ifa->ifa_next)
+ if (strcmp(ifa->ifa_name, name) == 0)
+ return 1;
+ return 0;
+}
+
+#define MASK(m) ((uint32_t)~((1 << (32 - (m))) - 1))
+
+static int
+conf_amask_eq(const void *v1, const void *v2, size_t len, int mask)
+{
+ const uint32_t *a1 = v1;
+ const uint32_t *a2 = v2;
+ uint32_t m;
+ int omask = mask;
+
+ len >>= 2;
+ switch (mask) {
+ case FSTAR:
+ if (memcmp(v1, v2, len) == 0)
+ return 1;
+ goto out;
+ case FEQUAL:
+
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
+ mask);
+ abort();
+ default:
+ break;
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ if (mask > 32) {
+ m = htonl((uint32_t)~0);
+ mask -= 32;
+ } else if (mask) {
+ m = htonl(MASK(mask));
+ mask = 0;
+ } else
+ return 1;
+ if ((a1[i] & m) != (a2[i] & m))
+ goto out;
+ }
+ return 1;
+out:
+ if (debug > 1) {
+ char b1[256], b2[256];
+ len <<= 2;
+ blhexdump(b1, sizeof(b1), "a1", v1, len);
+ blhexdump(b2, sizeof(b2), "a2", v2, len);
+ (*lfun)(LOG_DEBUG, "%s: %s != %s [0x%x]", __func__,
+ b1, b2, omask);
+ }
+ return 0;
+}
+
+/*
+ * Apply the mask to the given address
+ */
+static void
+conf_apply_mask(void *v, size_t len, int mask)
+{
+ uint32_t *a = v;
+ uint32_t m;
+
+ switch (mask) {
+ case FSTAR:
+ return;
+ case FEQUAL:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
+ mask);
+ abort();
+ default:
+ break;
+ }
+ len >>= 2;
+
+ for (size_t i = 0; i < len; i++) {
+ if (mask > 32) {
+ m = htonl((uint32_t)~0);
+ mask -= 32;
+ } else if (mask) {
+ m = htonl(MASK(mask));
+ mask = 0;
+ } else
+ m = 0;
+ a[i] &= m;
+ }
+}
+
+/*
+ * apply the mask and the port to the address given
+ */
+static void
+conf_addr_set(struct conf *c, const struct sockaddr_storage *ss)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ in_port_t *port;
+ void *addr;
+ size_t alen;
+
+ c->c_lmask = c->c_rmask;
+ c->c_ss = *ss;
+
+ if (c->c_ss.ss_family != c->c_family) {
+ (*lfun)(LOG_CRIT, "%s: Internal error: mismatched family "
+ "%u != %u", __func__, c->c_ss.ss_family, c->c_family);
+ abort();
+ }
+
+ switch (c->c_ss.ss_family) {
+ case AF_INET:
+ sin = (void *)&c->c_ss;
+ port = &sin->sin_port;
+ addr = &sin->sin_addr;
+ alen = sizeof(sin->sin_addr);
+ break;
+ case AF_INET6:
+ sin6 = (void *)&c->c_ss;
+ port = &sin6->sin6_port;
+ addr = &sin6->sin6_addr;
+ alen = sizeof(sin6->sin6_addr);
+ break;
+ default:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
+ __func__, c->c_ss.ss_family);
+ abort();
+ }
+
+ *port = htons((in_port_t)c->c_port);
+ conf_apply_mask(addr, alen, c->c_lmask);
+ if (c->c_lmask == FSTAR)
+ c->c_lmask = (int)(alen * 8);
+ if (debug) {
+ char buf[128];
+ sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&c->c_ss);
+ (*lfun)(LOG_DEBUG, "Applied address %s", buf);
+ }
+}
+
+/*
+ * Compared two addresses for equality applying the mask
+ */
+static int
+conf_inet_eq(const void *v1, const void *v2, int mask)
+{
+ const struct sockaddr *sa1 = v1;
+ const struct sockaddr *sa2 = v2;
+ size_t size;
+
+ if (sa1->sa_family != sa2->sa_family)
+ return 0;
+
+ switch (sa1->sa_family) {
+ case AF_INET: {
+ const struct sockaddr_in *s1 = v1;
+ const struct sockaddr_in *s2 = v2;
+ size = sizeof(s1->sin_addr);
+ v1 = &s1->sin_addr;
+ v2 = &s2->sin_addr;
+ break;
+ }
+
+ case AF_INET6: {
+ const struct sockaddr_in6 *s1 = v1;
+ const struct sockaddr_in6 *s2 = v2;
+ size = sizeof(s1->sin6_addr);
+ v1 = &s1->sin6_addr;
+ v2 = &s2->sin6_addr;
+ break;
+ }
+
+ default:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
+ __func__, sa1->sa_family);
+ abort();
+ }
+
+ return conf_amask_eq(v1, v2, size, mask);
+}
+
+static int
+conf_addr_in_interface(const struct sockaddr_storage *s1,
+ const struct sockaddr_storage *s2, int mask)
+{
+ const char *name = SIF_NAME(s2);
+ const struct ifaddrs *ifa;
+
+ for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
+ if ((ifa->ifa_flags & IFF_UP) == 0)
+ continue;
+
+ if (strcmp(ifa->ifa_name, name) != 0)
+ continue;
+
+ if (s1->ss_family != ifa->ifa_addr->sa_family)
+ continue;
+
+ bool eq;
+ switch (s1->ss_family) {
+ case AF_INET:
+ case AF_INET6:
+ eq = conf_inet_eq(ifa->ifa_addr, s1, mask);
+ break;
+ default:
+ (*lfun)(LOG_ERR, "Bad family %u", s1->ss_family);
+ continue;
+ }
+ if (eq)
+ return 1;
+ }
+ return 0;
+}
+
+static int
+conf_addr_eq(const struct sockaddr_storage *s1,
+ const struct sockaddr_storage *s2, int mask)
+{
+ switch (s2->ss_family) {
+ case 0:
+ return 1;
+ case AF_MAX:
+ return conf_addr_in_interface(s1, s2, mask);
+ case AF_INET:
+ case AF_INET6:
+ return conf_inet_eq(s1, s2, mask);
+ default:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
+ __func__, s1->ss_family);
+ abort();
+ }
+}
+
+static int
+conf_eq(const struct conf *c1, const struct conf *c2)
+{
+
+ if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, c2->c_lmask))
+ return 0;
+
+#define CMP(a, b, f) \
+ if ((a)->f != (b)->f && (b)->f != FSTAR && (b)->f != FEQUAL) { \
+ if (debug > 1) \
+ (*lfun)(LOG_DEBUG, "%s: %s fail %d != %d", __func__, \
+ __STRING(f), (a)->f, (b)->f); \
+ return 0; \
+ }
+ CMP(c1, c2, c_port);
+ CMP(c1, c2, c_proto);
+ CMP(c1, c2, c_family);
+ CMP(c1, c2, c_uid);
+#undef CMP
+ return 1;
+}
+
+static const char *
+conf_num(char *b, size_t l, int n)
+{
+ switch (n) {
+ case FSTAR:
+ return "*";
+ case FEQUAL:
+ return "=";
+ default:
+ snprintf(b, l, "%d", n);
+ return b;
+ }
+}
+
+static const char *
+fmtname(const char *n) {
+ size_t l = strlen(rulename);
+ if (l == 0)
+ return "*";
+ if (strncmp(n, rulename, l) == 0) {
+ if (n[l] != '\0')
+ return n + l;
+ else
+ return "*";
+ } else if (!*n)
+ return "=";
+ else
+ return n;
+}
+
+static void
+fmtport(char *b, size_t l, int port)
+{
+ char buf[128];
+
+ if (port == FSTAR)
+ return;
+
+ if (b[0] == '\0' || strcmp(b, "*") == 0)
+ snprintf(b, l, "%d", port);
+ else {
+ snprintf(buf, sizeof(buf), ":%d", port);
+ strlcat(b, buf, l);
+ }
+}
+
+static const char *
+fmtmask(char *b, size_t l, int fam, int mask)
+{
+ char buf[128];
+
+ switch (mask) {
+ case FSTAR:
+ return "";
+ case FEQUAL:
+ if (strcmp(b, "=") == 0)
+ return "";
+ else {
+ strlcat(b, "/=", l);
+ return b;
+ }
+ default:
+ break;
+ }
+
+ switch (fam) {
+ case AF_INET:
+ if (mask == 32)
+ return "";
+ break;
+ case AF_INET6:
+ if (mask == 128)
+ return "";
+ break;
+ default:
+ break;
+ }
+
+ snprintf(buf, sizeof(buf), "/%d", mask);
+ strlcat(b, buf, l);
+ return b;
+}
+
+static const char *
+conf_namemask(char *b, size_t l, const struct conf *c)
+{
+ strlcpy(b, fmtname(c->c_name), l);
+ fmtmask(b, l, c->c_family, c->c_rmask);
+ return b;
+}
+
+const char *
+conf_print(char *buf, size_t len, const char *pref, const char *delim,
+ const struct conf *c)
+{
+ char ha[128], hb[32], b[5][64];
+ int sp;
+
+#define N(n, v) conf_num(b[n], sizeof(b[n]), (v))
+
+ switch (c->c_ss.ss_family) {
+ case 0:
+ snprintf(ha, sizeof(ha), "*");
+ break;
+ case AF_MAX:
+ snprintf(ha, sizeof(ha), "%s", SIF_NAME(&c->c_ss));
+ break;
+ default:
+ sockaddr_snprintf(ha, sizeof(ha), "%a", (const void *)&c->c_ss);
+ break;
+ }
+
+ fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask);
+ fmtport(ha, sizeof(ha), c->c_port);
+
+ sp = *delim == '\t' ? 20 : -1;
+ hb[0] = '\0';
+ if (*delim)
+ snprintf(buf, len, "%s%*.*s%s%s%s" "%s%s%s%s"
+ "%s%s" "%s%s%s",
+ pref, sp, sp, ha, delim, N(0, c->c_proto), delim,
+ N(1, c->c_family), delim, N(2, c->c_uid), delim,
+ conf_namemask(hb, sizeof(hb), c), delim,
+ N(3, c->c_nfail), delim, N(4, c->c_duration));
+ else
+ snprintf(buf, len, "%starget:%s, proto:%s, family:%s, "
+ "uid:%s, name:%s, nfail:%s, duration:%s", pref,
+ ha, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid),
+ conf_namemask(hb, sizeof(hb), c),
+ N(3, c->c_nfail), N(4, c->c_duration));
+ return buf;
+}
+
+/*
+ * Apply the local config match to the result
+ */
+static void
+conf_apply(struct conf *c, const struct conf *sc)
+{
+ char buf[BUFSIZ];
+
+ if (debug) {
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "merge:\t", "", sc));
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "to:\t", "", c));
+ }
+ memcpy(c->c_name, sc->c_name, CONFNAMESZ);
+ c->c_uid = sc->c_uid;
+ c->c_rmask = sc->c_rmask;
+ c->c_nfail = sc->c_nfail;
+ c->c_duration = sc->c_duration;
+
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "result:\t", "", c));
+}
+
+/*
+ * Merge a remote configuration to the result
+ */
+static void
+conf_merge(struct conf *c, const struct conf *sc)
+{
+ char buf[BUFSIZ];
+
+ if (debug) {
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "merge:\t", "", sc));
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "to:\t", "", c));
+ }
+
+ if (sc->c_name[0])
+ memcpy(c->c_name, sc->c_name, CONFNAMESZ);
+ if (sc->c_uid != FEQUAL)
+ c->c_uid = sc->c_uid;
+ if (sc->c_rmask != FEQUAL)
+ c->c_lmask = c->c_rmask = sc->c_rmask;
+ if (sc->c_nfail != FEQUAL)
+ c->c_nfail = sc->c_nfail;
+ if (sc->c_duration != FEQUAL)
+ c->c_duration = sc->c_duration;
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "result:\t", "", c));
+}
+
+static void
+confset_init(struct confset *cs)
+{
+ cs->cs_c = NULL;
+ cs->cs_n = 0;
+ cs->cs_m = 0;
+}
+
+static int
+confset_grow(struct confset *cs)
+{
+ void *tc;
+
+ cs->cs_m += 10;
+ tc = realloc(cs->cs_c, cs->cs_m * sizeof(*cs->cs_c));
+ if (tc == NULL) {
+ (*lfun)(LOG_ERR, "%s: Can't grow confset (%m)", __func__);
+ return -1;
+ }
+ cs->cs_c = tc;
+ return 0;
+}
+
+static struct conf *
+confset_get(struct confset *cs)
+{
+ return &cs->cs_c[cs->cs_n];
+}
+
+static bool
+confset_full(const struct confset *cs)
+{
+ return cs->cs_n == cs->cs_m;
+}
+
+static void
+confset_sort(struct confset *cs)
+{
+ qsort(cs->cs_c, cs->cs_n, sizeof(*cs->cs_c), conf_sort);
+}
+
+static void
+confset_add(struct confset *cs)
+{
+ cs->cs_n++;
+}
+
+static void
+confset_free(struct confset *cs)
+{
+ free(cs->cs_c);
+ confset_init(cs);
+}
+
+static void
+confset_replace(struct confset *dc, struct confset *sc)
+{
+ struct confset tc;
+ tc = *dc;
+ *dc = *sc;
+ confset_init(sc);
+ confset_free(&tc);
+}
+
+static void
+confset_list(const struct confset *cs, const char *msg, const char *where)
+{
+ char buf[BUFSIZ];
+
+ (*lfun)(LOG_DEBUG, "[%s]", msg);
+ (*lfun)(LOG_DEBUG, "%20.20s\ttype\tproto\towner\tname\tnfail\tduration",
+ where);
+ for (size_t i = 0; i < cs->cs_n; i++)
+ (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), "", "\t",
+ &cs->cs_c[i]));
+}
+
+/*
+ * Match a configuration against the given list and apply the function
+ * to it, returning the matched entry number.
+ */
+static size_t
+confset_match(const struct confset *cs, struct conf *c,
+ void (*fun)(struct conf *, const struct conf *))
+{
+ char buf[BUFSIZ];
+ size_t i;
+
+ for (i = 0; i < cs->cs_n; i++) {
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
+ "check:\t", "", &cs->cs_c[i]));
+ if (conf_eq(c, &cs->cs_c[i])) {
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s",
+ conf_print(buf, sizeof(buf),
+ "found:\t", "", &cs->cs_c[i]));
+ (*fun)(c, &cs->cs_c[i]);
+ break;
+ }
+ }
+ return i;
+}
+
+const struct conf *
+conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
+ struct conf *cr)
+{
+ int proto;
+ socklen_t slen;
+ struct sockaddr_storage lss;
+ size_t i;
+ char buf[BUFSIZ];
+
+ memset(cr, 0, sizeof(*cr));
+ slen = sizeof(lss);
+ memset(&lss, 0, slen);
+ if (getsockname(fd, (void *)&lss, &slen) == -1) {
+ (*lfun)(LOG_ERR, "getsockname failed (%m)");
+ return NULL;
+ }
+
+ slen = sizeof(proto);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) {
+ (*lfun)(LOG_ERR, "getsockopt failed (%m)");
+ return NULL;
+ }
+
+ if (debug) {
+ sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&lss);
+ (*lfun)(LOG_DEBUG, "listening socket: %s", buf);
+ }
+
+ switch (proto) {
+ case SOCK_STREAM:
+ cr->c_proto = IPPROTO_TCP;
+ break;
+ case SOCK_DGRAM:
+ cr->c_proto = IPPROTO_UDP;
+ break;
+ default:
+ (*lfun)(LOG_ERR, "unsupported protocol %d", proto);
+ return NULL;
+ }
+
+ switch (lss.ss_family) {
+ case AF_INET:
+ cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port);
+ break;
+ case AF_INET6:
+ cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port);
+ break;
+ default:
+ (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family);
+ return NULL;
+ }
+
+ cr->c_ss = lss;
+ cr->c_lmask = FSTAR;
+ cr->c_uid = (int)uid;
+ cr->c_family = lss.ss_family;
+ cr->c_name[0] = '\0';
+ cr->c_rmask = FSTAR;
+ cr->c_nfail = FSTAR;
+ cr->c_duration = FSTAR;
+
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
+ "look:\t", "", cr));
+
+ /* match the local config */
+ i = confset_match(&lconf, cr, conf_apply);
+ if (i == lconf.cs_n) {
+ if (debug)
+ (*lfun)(LOG_DEBUG, "not found");
+ return NULL;
+ }
+
+ conf_addr_set(cr, rss);
+ /* match the remote config */
+ confset_match(&rconf, cr, conf_merge);
+ /* to apply the mask */
+ conf_addr_set(cr, &cr->c_ss);
+
+ return cr;
+}
+
+
+void
+conf_parse(const char *f)
+{
+ FILE *fp;
+ char *line;
+ size_t lineno, len;
+ struct confset lc, rc, *cs;
+
+ if ((fp = fopen(f, "r")) == NULL) {
+ (*lfun)(LOG_ERR, "%s: Cannot open `%s' (%m)", __func__, f);
+ return;
+ }
+
+ lineno = 1;
+
+ confset_init(&rc);
+ confset_init(&lc);
+ cs = &lc;
+ for (; (line = fparseln(fp, &len, &lineno, NULL, 0)) != NULL;
+ free(line))
+ {
+ if (!*line)
+ continue;
+ if (strcmp(line, "[local]") == 0) {
+ cs = &lc;
+ continue;
+ }
+ if (strcmp(line, "[remote]") == 0) {
+ cs = &rc;
+ continue;
+ }
+
+ if (confset_full(cs)) {
+ if (confset_grow(cs) == -1) {
+ confset_free(&lc);
+ confset_free(&rc);
+ fclose(fp);
+ return;
+ }
+ }
+ if (conf_parseline(f, lineno, line, confset_get(cs),
+ cs == &lc) == -1)
+ continue;
+ confset_add(cs);
+ }
+
+ fclose(fp);
+ confset_sort(&lc);
+ confset_sort(&rc);
+
+ confset_replace(&rconf, &rc);
+ confset_replace(&lconf, &lc);
+
+ if (debug) {
+ confset_list(&lconf, "local", "target");
+ confset_list(&rconf, "remote", "source");
+ }
+}
diff --git a/contrib/blacklist/bin/conf.h b/contrib/blacklist/bin/conf.h
new file mode 100644
index 0000000..03f1942
--- /dev/null
+++ b/contrib/blacklist/bin/conf.h
@@ -0,0 +1,65 @@
+/* $NetBSD: conf.h,v 1.6 2015/01/27 19:40:36 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _CONF_H
+#define _CONF_H
+
+#include <sys/socket.h>
+
+struct conf {
+ struct sockaddr_storage c_ss;
+ int c_lmask;
+ int c_port;
+ int c_proto;
+ int c_family;
+ int c_uid;
+ int c_nfail;
+ char c_name[128];
+ int c_rmask;
+ int c_duration;
+};
+
+struct confset {
+ struct conf *cs_c;
+ size_t cs_n;
+ size_t cs_m;
+};
+
+#define CONFNAMESZ sizeof(((struct conf *)0)->c_name)
+
+__BEGIN_DECLS
+const char *conf_print(char *, size_t, const char *, const char *,
+ const struct conf *);
+void conf_parse(const char *);
+const struct conf *conf_find(int, uid_t, const struct sockaddr_storage *,
+ struct conf *);
+__END_DECLS
+
+#endif /* _CONF_H */
diff --git a/contrib/blacklist/bin/internal.c b/contrib/blacklist/bin/internal.c
new file mode 100644
index 0000000..5c039e4
--- /dev/null
+++ b/contrib/blacklist/bin/internal.c
@@ -0,0 +1,48 @@
+/* $NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $");
+
+#include <stdio.h>
+#include <syslog.h>
+#include "conf.h"
+#include "internal.h"
+
+int debug;
+const char *rulename = "blacklistd";
+const char *controlprog = _PATH_BLCONTROL;
+struct confset lconf, rconf;
+struct ifaddrs *ifas;
+void (*lfun)(int, const char *, ...) = syslog;
diff --git a/contrib/blacklist/bin/internal.h b/contrib/blacklist/bin/internal.h
new file mode 100644
index 0000000..5a40e49
--- /dev/null
+++ b/contrib/blacklist/bin/internal.h
@@ -0,0 +1,57 @@
+/* $NetBSD: internal.h,v 1.14 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _INTERNAL_H
+#define _INTERNAL_H
+
+#ifndef _PATH_BLCONF
+#define _PATH_BLCONF "/etc/blacklistd.conf"
+#endif
+#ifndef _PATH_BLCONTROL
+#define _PATH_BLCONTROL "/libexec/blacklistd-helper"
+#endif
+#ifndef _PATH_BLSTATE
+#define _PATH_BLSTATE "/var/db/blacklistd.db"
+#endif
+
+extern struct confset rconf, lconf;
+extern int debug;
+extern const char *rulename;
+extern const char *controlprog;
+extern struct ifaddrs *ifas;
+
+#if !defined(__syslog_attribute__) && !defined(__syslog__)
+#define __syslog__ __printf__
+#endif
+
+extern void (*lfun)(int, const char *, ...)
+ __attribute__((__format__(__syslog__, 2, 3)));
+
+#endif /* _INTERNAL_H */
diff --git a/contrib/blacklist/bin/run.c b/contrib/blacklist/bin/run.c
new file mode 100644
index 0000000..8499edd
--- /dev/null
+++ b/contrib/blacklist/bin/run.c
@@ -0,0 +1,156 @@
+/* $NetBSD: run.c,v 1.14 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: run.c,v 1.14 2016/04/04 15:52:56 christos Exp $");
+
+#include <stdio.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <stdarg.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <syslog.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include "run.h"
+#include "conf.h"
+#include "internal.h"
+#include "support.h"
+
+extern char **environ;
+
+static char *
+run(const char *cmd, const char *name, ...)
+{
+ const char *argv[20];
+ size_t i;
+ va_list ap;
+ FILE *fp;
+ char buf[10240], *res;
+
+ argv[0] = "control";
+ argv[1] = cmd;
+ argv[2] = name;
+ va_start(ap, name);
+ for (i = 3; i < __arraycount(argv) &&
+ (argv[i] = va_arg(ap, char *)) != NULL; i++)
+ continue;
+ va_end(ap);
+
+ if (debug) {
+ size_t z;
+ int r;
+
+ r = snprintf(buf, sizeof(buf), "run %s [", controlprog);
+ if (r == -1 || (z = (size_t)r) >= sizeof(buf))
+ z = sizeof(buf);
+ for (i = 0; argv[i]; i++) {
+ r = snprintf(buf + z, sizeof(buf) - z, "%s%s",
+ argv[i], argv[i + 1] ? " " : "");
+ if (r == -1 || (z += (size_t)r) >= sizeof(buf))
+ z = sizeof(buf);
+ }
+ (*lfun)(LOG_DEBUG, "%s]", buf);
+ }
+
+ fp = popenve(controlprog, __UNCONST(argv), environ, "r");
+ if (fp == NULL) {
+ (*lfun)(LOG_ERR, "popen %s failed (%m)", controlprog);
+ return NULL;
+ }
+ if (fgets(buf, sizeof(buf), fp) != NULL)
+ res = strdup(buf);
+ else
+ res = NULL;
+ pclose(fp);
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s returns %s", cmd, res);
+ return res;
+}
+
+void
+run_flush(const struct conf *c)
+{
+ free(run("flush", c->c_name, NULL));
+}
+
+int
+run_change(const char *how, const struct conf *c, char *id, size_t len)
+{
+ const char *prname;
+ char poname[64], adname[128], maskname[32], *rv;
+ size_t off;
+
+ switch (c->c_proto) {
+ case -1:
+ prname = "";
+ break;
+ case IPPROTO_TCP:
+ prname = "tcp";
+ break;
+ case IPPROTO_UDP:
+ prname = "udp";
+ break;
+ default:
+ (*lfun)(LOG_ERR, "%s: bad protocol %d", __func__, c->c_proto);
+ return -1;
+ }
+
+ if (c->c_port != -1)
+ snprintf(poname, sizeof(poname), "%d", c->c_port);
+ else
+ poname[0] = '\0';
+
+ snprintf(maskname, sizeof(maskname), "%d", c->c_lmask);
+ sockaddr_snprintf(adname, sizeof(adname), "%a", (const void *)&c->c_ss);
+
+ rv = run(how, c->c_name, prname, adname, maskname, poname, id, NULL);
+ if (rv == NULL)
+ return -1;
+ if (len != 0) {
+ rv[strcspn(rv, "\n")] = '\0';
+ off = strncmp(rv, "OK ", 3) == 0 ? 3 : 0;
+ strlcpy(id, rv + off, len);
+ }
+ free(rv);
+ return 0;
+}
diff --git a/contrib/blacklist/bin/run.h b/contrib/blacklist/bin/run.h
new file mode 100644
index 0000000..bafc3e5
--- /dev/null
+++ b/contrib/blacklist/bin/run.h
@@ -0,0 +1,41 @@
+/* $NetBSD: run.h,v 1.5 2015/01/27 19:40:37 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _RUN_H
+#define _RUN_H
+
+__BEGIN_DECLS
+struct conf;
+void run_flush(const struct conf *);
+struct sockaddr_storage;
+int run_change(const char *, const struct conf *, char *, size_t);
+__END_DECLS
+
+#endif /* _RUN_H */
diff --git a/contrib/blacklist/bin/state.c b/contrib/blacklist/bin/state.c
new file mode 100644
index 0000000..eb97e97
--- /dev/null
+++ b/contrib/blacklist/bin/state.c
@@ -0,0 +1,233 @@
+/* $NetBSD: state.c,v 1.18 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: state.c,v 1.18 2016/04/04 15:52:56 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <netinet/in.h>
+
+#include "bl.h"
+#include "internal.h"
+#include "conf.h"
+#include "support.h"
+#include "state.h"
+
+static HASHINFO openinfo = {
+ 4096, /* bsize */
+ 32, /* ffactor */
+ 256, /* nelem */
+ 8 * 1024 * 1024,/* cachesize */
+ NULL, /* hash() */
+ 0 /* lorder */
+};
+
+int
+state_close(DB *db)
+{
+ if (db == NULL)
+ return -1;
+ if ((*db->close)(db) == -1) {
+ (*lfun)(LOG_ERR, "%s: can't close db (%m)", __func__);
+ return -1;
+ }
+ return 0;
+}
+
+DB *
+state_open(const char *dbname, int flags, mode_t perm)
+{
+ DB *db;
+
+#ifdef __APPLE__
+ flags &= O_CREAT|O_EXCL|O_EXLOCK|O_NONBLOCK|O_RDONLY|
+ O_RDWR|O_SHLOCK|O_TRUNC;
+#endif
+ db = dbopen(dbname, flags, perm, DB_HASH, &openinfo);
+ if (db == NULL) {
+ if (errno == ENOENT && (flags & O_CREAT) == 0)
+ return NULL;
+ (*lfun)(LOG_ERR, "%s: can't open `%s' (%m)", __func__, dbname);
+ }
+ return db;
+}
+
+static int
+state_sizecheck(const DBT *t)
+{
+ if (sizeof(struct conf) == t->size)
+ return 0;
+ (*lfun)(LOG_ERR, "Key size mismatch %zu != %zu", sizeof(struct conf),
+ t->size);
+ return -1;
+}
+
+static void
+dumpkey(const struct conf *k)
+{
+ char buf[10240];
+ blhexdump(buf, sizeof(buf), __func__, k, sizeof(*k));
+ (*lfun)(LOG_DEBUG, "%s", buf);
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "", "", k));
+
+}
+
+int
+state_del(DB *db, const struct conf *c)
+{
+ int rv;
+ DBT k;
+
+ if (db == NULL)
+ return -1;
+
+ k.data = __UNCONST(c);
+ k.size = sizeof(*c);
+
+ switch (rv = (*db->del)(db, &k, 0)) {
+ case 0:
+ case 1:
+ if (debug > 1) {
+ (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
+ (*db->sync)(db, 0);
+ }
+ return 0;
+ default:
+ (*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
+ return -1;
+ }
+}
+
+int
+state_get(DB *db, const struct conf *c, struct dbinfo *dbi)
+{
+ int rv;
+ DBT k, v;
+
+ if (db == NULL)
+ return -1;
+
+ k.data = __UNCONST(c);
+ k.size = sizeof(*c);
+
+ switch (rv = (*db->get)(db, &k, &v, 0)) {
+ case 0:
+ case 1:
+ if (rv)
+ memset(dbi, 0, sizeof(*dbi));
+ else
+ memcpy(dbi, v.data, sizeof(*dbi));
+ if (debug > 1)
+ (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
+ return 0;
+ default:
+ (*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
+ return -1;
+ }
+}
+
+int
+state_put(DB *db, const struct conf *c, const struct dbinfo *dbi)
+{
+ int rv;
+ DBT k, v;
+
+ if (db == NULL)
+ return -1;
+
+ k.data = __UNCONST(c);
+ k.size = sizeof(*c);
+ v.data = __UNCONST(dbi);
+ v.size = sizeof(*dbi);
+
+ switch (rv = (*db->put)(db, &k, &v, 0)) {
+ case 0:
+ if (debug > 1) {
+ (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
+ (*db->sync)(db, 0);
+ }
+ return 0;
+ case 1:
+ errno = EEXIST;
+ /*FALLTHROUGH*/
+ default:
+ (*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
+ return -1;
+ }
+}
+
+int
+state_iterate(DB *db, struct conf *c, struct dbinfo *dbi, unsigned int first)
+{
+ int rv;
+ DBT k, v;
+
+ if (db == NULL)
+ return -1;
+
+ first = first ? R_FIRST : R_NEXT;
+
+ switch (rv = (*db->seq)(db, &k, &v, first)) {
+ case 0:
+ if (state_sizecheck(&k) == -1)
+ return -1;
+ memcpy(c, k.data, sizeof(*c));
+ if (debug > 2)
+ dumpkey(c);
+ memcpy(dbi, v.data, sizeof(*dbi));
+ if (debug > 1)
+ (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
+ return 1;
+ case 1:
+ if (debug > 1)
+ (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
+ return 0;
+ default:
+ (*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
+ return -1;
+ }
+}
+
+int
+state_sync(DB *db)
+{
+ return (*db->sync)(db, 0);
+}
diff --git a/contrib/blacklist/bin/state.h b/contrib/blacklist/bin/state.h
new file mode 100644
index 0000000..2e92570
--- /dev/null
+++ b/contrib/blacklist/bin/state.h
@@ -0,0 +1,62 @@
+/* $NetBSD: state.h,v 1.5 2015/01/27 19:40:37 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _STATE_H
+#define _STATE_H
+
+#ifdef HAVE_DB_185_H
+#include <db_185.h>
+#elif HAVE_DB_H
+#include <db.h>
+#else
+#error "no db.h"
+#endif
+#include <time.h>
+
+struct dbinfo {
+ int count;
+ time_t last;
+ char id[64];
+};
+
+__BEGIN_DECLS
+struct sockaddr_storage;
+struct conf;
+
+DB *state_open(const char *, int, mode_t);
+int state_close(DB *);
+int state_get(DB *, const struct conf *, struct dbinfo *);
+int state_put(DB *, const struct conf *, const struct dbinfo *);
+int state_del(DB *, const struct conf *);
+int state_iterate(DB *, struct conf *, struct dbinfo *, unsigned int);
+int state_sync(DB *);
+__END_DECLS
+
+#endif /* _STATE_H */
diff --git a/contrib/blacklist/bin/support.c b/contrib/blacklist/bin/support.c
new file mode 100644
index 0000000..0dac499ac
--- /dev/null
+++ b/contrib/blacklist/bin/support.c
@@ -0,0 +1,157 @@
+/* $NetBSD: support.c,v 1.8 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: support.c,v 1.8 2016/04/04 15:52:56 christos Exp $");
+
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "support.h"
+
+static __attribute__((__format_arg__(3))) const char *
+expandm(char *buf, size_t len, const char *fmt)
+{
+ char *p;
+ size_t r;
+
+ if ((p = strstr(fmt, "%m")) == NULL)
+ return fmt;
+
+ r = (size_t)(p - fmt);
+ if (r >= len)
+ return fmt;
+
+ strlcpy(buf, fmt, r + 1);
+ strlcat(buf, strerror(errno), len);
+ strlcat(buf, fmt + r + 2, len);
+
+ return buf;
+}
+
+void
+vdlog(int level __unused, const char *fmt, va_list ap)
+{
+ char buf[BUFSIZ];
+
+// fprintf(stderr, "%s: ", getprogname());
+ vfprintf(stderr, expandm(buf, sizeof(buf), fmt), ap);
+ fprintf(stderr, "\n");
+}
+
+void
+dlog(int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vdlog(level, fmt, ap);
+ va_end(ap);
+}
+
+const char *
+fmttime(char *b, size_t l, time_t t)
+{
+ struct tm tm;
+ if (localtime_r(&t, &tm) == NULL)
+ snprintf(b, l, "*%jd*", (intmax_t)t);
+ else
+ strftime(b, l, "%Y/%m/%d %H:%M:%S", &tm);
+ return b;
+}
+
+const char *
+fmtydhms(char *b, size_t l, time_t t)
+{
+ time_t s, m, h, d, y;
+ int z;
+ size_t o;
+
+ s = t % 60;
+ t /= 60;
+ m = t % 60;
+ t /= 60;
+ h = t % 60;
+ t /= 24;
+ d = t % 24;
+ t /= 356;
+ y = t;
+
+ z = 0;
+ o = 0;
+#define APPEND(a) \
+ if (a) { \
+ z = snprintf(b + o, l - o, "%jd%s", (intmax_t)a, __STRING(a)); \
+ if (z == -1) \
+ return b; \
+ o += (size_t)z; \
+ if (o >= l) \
+ return b; \
+ }
+ APPEND(y)
+ APPEND(d)
+ APPEND(h)
+ APPEND(m)
+ APPEND(s)
+ return b;
+}
+
+ssize_t
+blhexdump(char *buf, size_t len, const char *str, const void *b, size_t l)
+{
+ size_t z, cz;
+ int r;
+ const unsigned char *p = b;
+ const unsigned char *e = p + l;
+
+ r = snprintf(buf, len, "%s: ", str);
+ if (r == -1)
+ return -1;
+ if ((cz = z = (size_t)r) >= len)
+ cz = len;
+
+ while (p < e) {
+ r = snprintf(buf + cz, len - cz, "%.2x", *p++);
+ if (r == -1)
+ return -1;
+ if ((cz = (z += (size_t)r)) >= len)
+ cz = len;
+ }
+ return (ssize_t)z;
+}
diff --git a/contrib/blacklist/bin/support.h b/contrib/blacklist/bin/support.h
new file mode 100644
index 0000000..899649c
--- /dev/null
+++ b/contrib/blacklist/bin/support.h
@@ -0,0 +1,44 @@
+/* $NetBSD: support.h,v 1.7 2016/04/04 15:52:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _SUPPORT_H
+#define _SUPPORT_H
+
+__BEGIN_DECLS
+const char *fmttime(char *, size_t, time_t);
+const char *fmtydhms(char *, size_t, time_t);
+void vdlog(int, const char *, va_list)
+ __attribute__((__format__(__printf__, 2, 0)));
+void dlog(int, const char *, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+ssize_t blhexdump(char *, size_t, const char *, const void *, size_t);
+__END_DECLS
+
+#endif /* _SUPPORT_H */
diff --git a/contrib/blacklist/diff/ftpd.diff b/contrib/blacklist/diff/ftpd.diff
new file mode 100644
index 0000000..d28577f
--- /dev/null
+++ b/contrib/blacklist/diff/ftpd.diff
@@ -0,0 +1,91 @@
+--- /dev/null 2015-01-23 17:30:40.000000000 -0500
++++ pfilter.c 2015-01-23 17:12:02.000000000 -0500
+@@ -0,0 +1,24 @@
++#include <stdio.h>
++#include <blacklist.h>
++
++#include "pfilter.h"
++
++static struct blacklist *blstate;
++
++void
++pfilter_open(void)
++{
++ if (blstate == NULL)
++ blstate = blacklist_open();
++}
++
++void
++pfilter_notify(int what, const char *msg)
++{
++ pfilter_open();
++
++ if (blstate == NULL)
++ return;
++
++ blacklist_r(blstate, what, 0, msg);
++}
+--- /dev/null 2015-01-23 17:30:40.000000000 -0500
++++ pfilter.h 2015-01-23 17:07:25.000000000 -0500
+@@ -0,0 +1,2 @@
++void pfilter_open(void);
++void pfilter_notify(int, const char *);
+Index: Makefile
+===================================================================
+RCS file: /cvsroot/src/libexec/ftpd/Makefile,v
+retrieving revision 1.63
+diff -u -p -u -r1.63 Makefile
+--- Makefile 14 Aug 2011 11:46:28 -0000 1.63
++++ Makefile 23 Jan 2015 22:32:20 -0000
+@@ -11,6 +11,10 @@ LDADD+= -lcrypt -lutil
+ MAN= ftpd.conf.5 ftpusers.5 ftpd.8
+ MLINKS= ftpusers.5 ftpchroot.5
+
++SRCS+= pfilter.c
++LDADD+= -lblacklist
++DPADD+= ${LIBBLACKLIST}
++
+ .if defined(NO_INTERNAL_LS)
+ CPPFLAGS+=-DNO_INTERNAL_LS
+ .else
+Index: ftpd.c
+===================================================================
+RCS file: /cvsroot/src/libexec/ftpd/ftpd.c,v
+retrieving revision 1.200
+diff -u -p -u -r1.200 ftpd.c
+--- ftpd.c 31 Jul 2013 19:50:47 -0000 1.200
++++ ftpd.c 23 Jan 2015 22:32:20 -0000
+@@ -165,6 +165,8 @@ __RCSID("$NetBSD: ftpd.c,v 1.200 2013/07
+ #include <security/pam_appl.h>
+ #endif
+
++#include "pfilter.h"
++
+ #define GLOBAL
+ #include "extern.h"
+ #include "pathnames.h"
+@@ -471,6 +473,8 @@ main(int argc, char *argv[])
+ if (EMPTYSTR(confdir))
+ confdir = _DEFAULT_CONFDIR;
+
++ pfilter_open();
++
+ if (dowtmp) {
+ #ifdef SUPPORT_UTMPX
+ ftpd_initwtmpx();
+@@ -1401,6 +1405,7 @@ do_pass(int pass_checked, int pass_rval,
+ if (rval) {
+ reply(530, "%s", rval == 2 ? "Password expired." :
+ "Login incorrect.");
++ pfilter_notify(1, rval == 2 ? "exppass" : "badpass");
+ if (logging) {
+ syslog(LOG_NOTICE,
+ "FTP LOGIN FAILED FROM %s", remoteloghost);
+@@ -1444,6 +1449,7 @@ do_pass(int pass_checked, int pass_rval,
+ *remote_ip = 0;
+ remote_ip[sizeof(remote_ip) - 1] = 0;
+ if (!auth_hostok(lc, remotehost, remote_ip)) {
++ pfilter_notify(1, "bannedhost");
+ syslog(LOG_INFO|LOG_AUTH,
+ "FTP LOGIN FAILED (HOST) as %s: permission denied.",
+ pw->pw_name);
diff --git a/contrib/blacklist/diff/named.diff b/contrib/blacklist/diff/named.diff
new file mode 100644
index 0000000..fcd97ba
--- /dev/null
+++ b/contrib/blacklist/diff/named.diff
@@ -0,0 +1,216 @@
+--- /dev/null 2015-01-22 01:48:00.000000000 -0500
++++ dist/bin/named/pfilter.c 2015-01-22 01:35:16.000000000 -0500
+@@ -0,0 +1,42 @@
++#include <config.h>
++
++#include <isc/platform.h>
++#include <isc/util.h>
++#include <named/types.h>
++#include <named/client.h>
++
++#include <blacklist.h>
++
++#include "pfilter.h"
++
++static struct blacklist *blstate;
++
++void
++pfilter_open(void)
++{
++ if (blstate == NULL)
++ blstate = blacklist_open();
++}
++
++#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
++
++void
++pfilter_notify(isc_result_t res, ns_client_t *client, const char *msg)
++{
++ isc_socket_t *socket;
++
++ pfilter_open();
++
++ if (TCP_CLIENT(client))
++ socket = client->tcpsocket;
++ else {
++ socket = client->udpsocket;
++ if (!client->peeraddr_valid)
++ return;
++ }
++ if (socket == NULL)
++ return;
++ blacklist_sa_r(blstate,
++ res != ISC_R_SUCCESS, isc_socket_getfd(socket),
++ &client->peeraddr.type.sa, client->peeraddr.length, msg);
++}
+--- /dev/null 2015-01-22 01:48:00.000000000 -0500
++++ dist/bin/named/pfilter.h 2015-01-22 01:16:56.000000000 -0500
+@@ -0,0 +1,2 @@
++void pfilter_open(void);
++void pfilter_notify(isc_result_t, ns_client_t *, const char *);
+Index: bin/named/Makefile
+===================================================================
+RCS file: /cvsroot/src/external/bsd/bind/bin/named/Makefile,v
+retrieving revision 1.8
+diff -u -u -r1.8 Makefile
+--- bin/named/Makefile 31 Dec 2013 20:23:12 -0000 1.8
++++ bin/named/Makefile 23 Jan 2015 21:37:09 -0000
+@@ -33,7 +33,9 @@
+ lwaddr.c lwdclient.c lwderror.c \
+ lwdgabn.c lwdgnba.c lwdgrbn.c lwdnoop.c lwresd.c lwsearch.c \
+ main.c notify.c query.c server.c sortlist.c statschannel.c \
+- tkeyconf.c tsigconf.c \
++ pfilter.c tkeyconf.c tsigconf.c \
+ update.c xfrout.c zoneconf.c ${SRCS_UNIX}
+
++LDADD+=-lblacklist
++DPADD+=${LIBBLACKLIST}
+ .include <bsd.prog.mk>
+Index: dist/bin/named/client.c
+===================================================================
+RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/client.c,v
+retrieving revision 1.11
+diff -u -u -r1.11 client.c
+--- dist/bin/named/client.c 10 Dec 2014 04:37:51 -0000 1.11
++++ dist/bin/named/client.c 23 Jan 2015 21:37:09 -0000
+@@ -65,6 +65,8 @@
+ #include <named/server.h>
+ #include <named/update.h>
+
++#include "pfilter.h"
++
+ /***
+ *** Client
+ ***/
+@@ -3101,6 +3103,7 @@
+ result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
+ acl, default_allow);
+
++ pfilter_notify(result, client, opname);
+ if (result == ISC_R_SUCCESS)
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+Index: dist/bin/named/main.c
+===================================================================
+RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/main.c,v
+retrieving revision 1.15
+diff -u -u -r1.15 main.c
+--- dist/bin/named/main.c 10 Dec 2014 04:37:51 -0000 1.15
++++ dist/bin/named/main.c 23 Jan 2015 21:37:09 -0000
+@@ -83,6 +83,9 @@
+ #ifdef HAVE_LIBXML2
+ #include <libxml/xmlversion.h>
+ #endif
++
++#include "pfilter.h"
++
+ /*
+ * Include header files for database drivers here.
+ */
+@@ -1206,6 +1209,8 @@
+
+ parse_command_line(argc, argv);
+
++ pfilter_open();
++
+ /*
+ * Warn about common configuration error.
+ */
+Index: dist/bin/named/query.c
+===================================================================
+RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/query.c,v
+retrieving revision 1.17
+diff -u -u -r1.17 query.c
+--- dist/bin/named/query.c 10 Dec 2014 04:37:52 -0000 1.17
++++ dist/bin/named/query.c 23 Jan 2015 21:37:09 -0000
+@@ -65,6 +65,8 @@
+ #include <named/sortlist.h>
+ #include <named/xfrout.h>
+
++#include "pfilter.h"
++
+ #if 0
+ /*
+ * It has been recommended that DNS64 be changed to return excluded
+@@ -762,6 +764,8 @@
+ }
+
+ result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
++ if (result != ISC_R_SUCCESS)
++ pfilter_notify(result, client, "validatezonedb");
+ if ((options & DNS_GETDB_NOLOG) == 0) {
+ char msg[NS_CLIENT_ACLMSGSIZE("query")];
+ if (result == ISC_R_SUCCESS) {
+@@ -1026,6 +1030,8 @@
+ result = ns_client_checkaclsilent(client, NULL,
+ client->view->cacheacl,
+ ISC_TRUE);
++ if (result == ISC_R_SUCCESS)
++ pfilter_notify(result, client, "cachedb");
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We were allowed by the "allow-query-cache" ACL.
+Index: dist/bin/named/update.c
+===================================================================
+RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/update.c,v
+retrieving revision 1.9
+diff -u -u -r1.9 update.c
+--- dist/bin/named/update.c 10 Dec 2014 04:37:52 -0000 1.9
++++ dist/bin/named/update.c 23 Jan 2015 21:37:09 -0000
+@@ -59,6 +59,8 @@
+ #include <named/server.h>
+ #include <named/update.h>
+
++#include "pfilter.h"
++
+ /*! \file
+ * \brief
+ * This module implements dynamic update as in RFC2136.
+@@ -307,6 +309,7 @@
+
+ result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
++ pfilter_notify(result, client, "queryacl");
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+@@ -324,6 +327,7 @@
+ sizeof(classbuf));
+
+ result = DNS_R_REFUSED;
++ pfilter_notify(result, client, "updateacl");
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
+ "update '%s/%s' denied", namebuf, classbuf);
+@@ -362,6 +366,7 @@
+ msg = "disabled";
+ } else {
+ result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE);
++ pfilter_notify(result, client, "updateacl");
+ if (result == ISC_R_SUCCESS) {
+ level = ISC_LOG_DEBUG(3);
+ msg = "approved";
+Index: dist/bin/named/xfrout.c
+===================================================================
+RCS file: /cvsroot/src/external/bsd/bind/dist/bin/named/xfrout.c,v
+retrieving revision 1.7
+diff -u -u -r1.7 xfrout.c
+--- dist/bin/named/xfrout.c 10 Dec 2014 04:37:52 -0000 1.7
++++ dist/bin/named/xfrout.c 23 Jan 2015 21:37:09 -0000
+@@ -54,6 +54,8 @@
+ #include <named/server.h>
+ #include <named/xfrout.h>
+
++#include "pfilter.h"
++
+ /*! \file
+ * \brief
+ * Outgoing AXFR and IXFR.
+@@ -822,6 +824,7 @@
+ &client->peeraddr,
+ &db);
+
++ pfilter_notify(result, client, "zonexfr");
+ if (result == ISC_R_NOPERM) {
+ char _buf1[DNS_NAME_FORMATSIZE];
+ char _buf2[DNS_RDATACLASS_FORMATSIZE];
diff --git a/contrib/blacklist/diff/proftpd.diff b/contrib/blacklist/diff/proftpd.diff
new file mode 100644
index 0000000..c811c9c
--- /dev/null
+++ b/contrib/blacklist/diff/proftpd.diff
@@ -0,0 +1,124 @@
+--- Make.rules.in.orig 2015-05-27 20:25:54.000000000 -0400
++++ Make.rules.in 2016-01-25 21:48:47.000000000 -0500
+@@ -110,3 +110,8 @@
+
+ FTPWHO_OBJS=ftpwho.o scoreboard.o misc.o
+ BUILD_FTPWHO_OBJS=utils/ftpwho.o utils/scoreboard.o utils/misc.o
++
++CPPFLAGS+=-DHAVE_BLACKLIST
++LIBS+=-lblacklist
++OBJS+= pfilter.o
++BUILD_OBJS+= src/pfilter.o
+--- /dev/null 2016-01-22 17:30:55.000000000 -0500
++++ include/pfilter.h 2016-01-22 16:18:33.000000000 -0500
+@@ -0,0 +1,3 @@
++
++void pfilter_notify(int);
++void pfilter_init(void);
+--- modules/mod_auth.c.orig 2015-05-27 20:25:54.000000000 -0400
++++ modules/mod_auth.c 2016-01-22 16:21:06.000000000 -0500
+@@ -30,6 +30,7 @@
+
+ #include "conf.h"
+ #include "privs.h"
++#include "pfilter.h"
+
+ extern pid_t mpid;
+
+@@ -84,6 +85,8 @@
+ _("Login timeout (%d %s): closing control connection"), TimeoutLogin,
+ TimeoutLogin != 1 ? "seconds" : "second");
+
++ pfilter_notify(1);
++
+ /* It's possible that any listeners of this event might terminate the
+ * session process themselves (e.g. mod_ban). So write out that the
+ * TimeoutLogin has been exceeded to the log here, in addition to the
+@@ -913,6 +916,7 @@
+ pr_memscrub(pass, strlen(pass));
+ }
+
++ pfilter_notify(1);
+ pr_log_auth(PR_LOG_NOTICE, "SECURITY VIOLATION: Root login attempted");
+ return 0;
+ }
+@@ -1726,6 +1730,7 @@
+ return 1;
+
+ auth_failure:
++ pfilter_notify(1);
+ if (pass)
+ pr_memscrub(pass, strlen(pass));
+ session.user = session.group = NULL;
+--- src/main.c.orig 2016-01-22 17:36:43.000000000 -0500
++++ src/main.c 2016-01-22 17:37:58.000000000 -0500
+@@ -49,6 +49,7 @@
+ #endif
+
+ #include "privs.h"
++#include "pfilter.h"
+
+ int (*cmd_auth_chk)(cmd_rec *);
+ void (*cmd_handler)(server_rec *, conn_t *);
+@@ -1050,6 +1051,7 @@
+ pid_t pid;
+ sigset_t sig_set;
+
++ pfilter_init();
+ if (!nofork) {
+
+ /* A race condition exists on heavily loaded servers where the parent
+@@ -1169,7 +1171,8 @@
+
+ /* Reseed pseudo-randoms */
+ srand((unsigned int) (time(NULL) * getpid()));
+-
++#else
++ pfilter_init();
+ #endif /* PR_DEVEL_NO_FORK */
+
+ /* Child is running here */
+--- /dev/null 2016-01-22 17:30:55.000000000 -0500
++++ src/pfilter.c 2016-01-22 16:37:55.000000000 -0500
+@@ -0,0 +1,41 @@
++#include "pfilter.h"
++#include "conf.h"
++#include "privs.h"
++#ifdef HAVE_BLACKLIST
++#include <blacklist.h>
++#endif
++
++static struct blacklist *blstate;
++
++void
++pfilter_init(void)
++{
++#ifdef HAVE_BLACKLIST
++ if (blstate == NULL)
++ blstate = blacklist_open();
++#endif
++}
++
++void
++pfilter_notify(int a)
++{
++#ifdef HAVE_BLACKLIST
++ conn_t *c = session.c;
++ int fd;
++
++ if (c == NULL)
++ return;
++ if (c->rfd != -1)
++ fd = c->rfd;
++ else if (c->wfd != -1)
++ fd = c->wfd;
++ else
++ return;
++
++ if (blstate == NULL)
++ pfilter_init();
++ if (blstate == NULL)
++ return;
++ (void)blacklist_r(blstate, a, fd, "proftpd");
++#endif
++}
diff --git a/contrib/blacklist/diff/ssh.diff b/contrib/blacklist/diff/ssh.diff
new file mode 100644
index 0000000..bc0b75c
--- /dev/null
+++ b/contrib/blacklist/diff/ssh.diff
@@ -0,0 +1,231 @@
+--- /dev/null 2015-01-22 23:10:33.000000000 -0500
++++ dist/pfilter.c 2015-01-22 23:46:03.000000000 -0500
+@@ -0,0 +1,28 @@
++#include "namespace.h"
++#include "includes.h"
++#include "ssh.h"
++#include "packet.h"
++#include "log.h"
++#include "pfilter.h"
++#include <blacklist.h>
++
++static struct blacklist *blstate;
++
++void
++pfilter_init(void)
++{
++ blstate = blacklist_open();
++}
++
++void
++pfilter_notify(int a)
++{
++ int fd;
++ if (blstate == NULL)
++ pfilter_init();
++ if (blstate == NULL)
++ return;
++ // XXX: 3?
++ fd = packet_connection_is_on_socket() ? packet_get_connection_in() : 3;
++ (void)blacklist_r(blstate, a, fd, "ssh");
++}
+--- /dev/null 2015-01-20 21:14:44.000000000 -0500
++++ dist/pfilter.h 2015-01-20 20:16:20.000000000 -0500
+@@ -0,0 +1,3 @@
++
++void pfilter_notify(int);
++void pfilter_init(void);
+Index: bin/sshd/Makefile
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/bin/sshd/Makefile,v
+retrieving revision 1.10
+diff -u -u -r1.10 Makefile
+--- bin/sshd/Makefile 19 Oct 2014 16:30:58 -0000 1.10
++++ bin/sshd/Makefile 22 Jan 2015 21:39:21 -0000
+@@ -15,7 +15,7 @@
+ auth2-none.c auth2-passwd.c auth2-pubkey.c \
+ monitor_mm.c monitor.c monitor_wrap.c \
+ kexdhs.c kexgexs.c kexecdhs.c sftp-server.c sftp-common.c \
+- roaming_common.c roaming_serv.c sandbox-rlimit.c
++ roaming_common.c roaming_serv.c sandbox-rlimit.c pfilter.c
+
+ COPTS.auth-options.c= -Wno-pointer-sign
+ COPTS.ldapauth.c= -Wno-format-nonliteral # XXX: should fix
+@@ -68,3 +68,6 @@
+
+ LDADD+= -lwrap
+ DPADD+= ${LIBWRAP}
++
++LDADD+= -lblacklist
++DPADD+= ${LIBBLACKLIST}
+Index: dist/auth.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth.c,v
+retrieving revision 1.10
+diff -u -u -r1.10 auth.c
+--- dist/auth.c 19 Oct 2014 16:30:58 -0000 1.10
++++ dist/auth.c 22 Jan 2015 21:39:22 -0000
+@@ -62,6 +62,7 @@
+ #include "monitor_wrap.h"
+ #include "krl.h"
+ #include "compat.h"
++#include "pfilter.h"
+
+ #ifdef HAVE_LOGIN_CAP
+ #include <login_cap.h>
+@@ -362,6 +363,8 @@
+ compat20 ? "ssh2" : "ssh1",
+ authctxt->info != NULL ? ": " : "",
+ authctxt->info != NULL ? authctxt->info : "");
++ if (!authctxt->postponed)
++ pfilter_notify(!authenticated);
+ free(authctxt->info);
+ authctxt->info = NULL;
+ }
+Index: dist/sshd.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/sshd.c,v
+retrieving revision 1.15
+diff -u -u -r1.15 sshd.c
+--- dist/sshd.c 28 Oct 2014 21:36:16 -0000 1.15
++++ dist/sshd.c 22 Jan 2015 21:39:22 -0000
+@@ -109,6 +109,7 @@
+ #include "roaming.h"
+ #include "ssh-sandbox.h"
+ #include "version.h"
++#include "pfilter.h"
+
+ #ifdef LIBWRAP
+ #include <tcpd.h>
+@@ -364,6 +365,7 @@
+ killpg(0, SIGTERM);
+ }
+
++ pfilter_notify(1);
+ /* Log error and exit. */
+ sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+ }
+@@ -1160,6 +1162,7 @@
+ for (i = 0; i < options.max_startups; i++)
+ startup_pipes[i] = -1;
+
++ pfilter_init();
+ /*
+ * Stay listening for connections until the system crashes or
+ * the daemon is killed with a signal.
+Index: auth1.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth1.c,v
+retrieving revision 1.9
+diff -u -u -r1.9 auth1.c
+--- auth1.c 19 Oct 2014 16:30:58 -0000 1.9
++++ auth1.c 14 Feb 2015 15:40:51 -0000
+@@ -41,6 +41,7 @@
+ #endif
+ #include "monitor_wrap.h"
+ #include "buffer.h"
++#include "pfilter.h"
+
+ /* import */
+ extern ServerOptions options;
+@@ -445,6 +446,7 @@
+ else {
+ debug("do_authentication: invalid user %s", user);
+ authctxt->pw = fakepw();
++ pfilter_notify(1);
+ }
+
+ /* Configuration may have changed as a result of Match */
+Index: auth2.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth2.c,v
+retrieving revision 1.9
+diff -u -u -r1.9 auth2.c
+--- auth2.c 19 Oct 2014 16:30:58 -0000 1.9
++++ auth2.c 14 Feb 2015 15:40:51 -0000
+@@ -52,6 +52,7 @@
+ #include "pathnames.h"
+ #include "buffer.h"
+ #include "canohost.h"
++#include "pfilter.h"
+
+ #ifdef GSSAPI
+ #include "ssh-gss.h"
+@@ -256,6 +257,7 @@
+ } else {
+ logit("input_userauth_request: invalid user %s", user);
+ authctxt->pw = fakepw();
++ pfilter_notify(1);
+ }
+ #ifdef USE_PAM
+ if (options.use_pam)
+Index: sshd.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/sshd.c,v
+retrieving revision 1.16
+diff -u -r1.16 sshd.c
+--- sshd.c 25 Jan 2015 15:52:44 -0000 1.16
++++ sshd.c 14 Feb 2015 09:55:06 -0000
+@@ -628,6 +628,8 @@
+ explicit_bzero(pw->pw_passwd, strlen(pw->pw_passwd));
+ endpwent();
+
++ pfilter_init();
++
+ /* Change our root directory */
+ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+ fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+
+Index: auth-pam.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth-pam.c,v
+retrieving revision 1.7
+diff -u -u -r1.7 auth-pam.c
+--- auth-pam.c 3 Jul 2015 00:59:59 -0000 1.7
++++ auth-pam.c 23 Jan 2016 00:01:16 -0000
+@@ -114,6 +114,7 @@
+ #include "ssh-gss.h"
+ #endif
+ #include "monitor_wrap.h"
++#include "pfilter.h"
+
+ extern ServerOptions options;
+ extern Buffer loginmsg;
+@@ -809,6 +810,7 @@
+ free(msg);
+ return (0);
+ }
++ pfilter_notify(1);
+ error("PAM: %s for %s%.100s from %.100s", msg,
+ sshpam_authctxt->valid ? "" : "illegal user ",
+ sshpam_authctxt->user,
+Index: auth.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth.c,v
+retrieving revision 1.15
+diff -u -u -r1.15 auth.c
+--- auth.c 21 Aug 2015 08:20:59 -0000 1.15
++++ auth.c 23 Jan 2016 00:01:16 -0000
+@@ -656,6 +656,7 @@
+
+ pw = getpwnam(user);
+ if (pw == NULL) {
++ pfilter_notify(1);
+ logit("Invalid user %.100s from %.100s",
+ user, get_remote_ipaddr());
+ return (NULL);
+Index: auth1.c
+===================================================================
+RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/auth1.c,v
+retrieving revision 1.12
+diff -u -u -r1.12 auth1.c
+--- auth1.c 3 Jul 2015 00:59:59 -0000 1.12
++++ auth1.c 23 Jan 2016 00:01:16 -0000
+@@ -376,6 +376,7 @@
+ char *msg;
+ size_t len;
+
++ pfilter_notify(1);
+ error("Access denied for user %s by PAM account "
+ "configuration", authctxt->user);
+ len = buffer_len(&loginmsg);
diff --git a/contrib/blacklist/etc/Makefile b/contrib/blacklist/etc/Makefile
new file mode 100644
index 0000000..669528d
--- /dev/null
+++ b/contrib/blacklist/etc/Makefile
@@ -0,0 +1,10 @@
+# $NetBSD: Makefile,v 1.3 2015/01/26 00:18:40 christos Exp $
+
+SUBDIR=rc.d
+
+FILESDIR= /usr/share/examples/blacklist
+FILESMODE= 644
+FILES= blacklistd.conf npf.conf
+
+.include <bsd.files.mk>
+.include <bsd.subdir.mk>
diff --git a/contrib/blacklist/etc/blacklistd.conf b/contrib/blacklist/etc/blacklistd.conf
new file mode 100644
index 0000000..f061b00
--- /dev/null
+++ b/contrib/blacklist/etc/blacklistd.conf
@@ -0,0 +1,14 @@
+# Blacklist rule
+# adr/mask:port type proto owner name nfail disable
+[local]
+ssh stream * * * 3 6h
+ftp stream * * * 3 6h
+domain * * named * 3 12h
+#6161 stream tcp6 christos * 2 10m
+* * * * * 3 60
+
+# adr/mask:port type proto owner name nfail disable
+[remote]
+#129.168.0.0/16 * * * = * *
+#6161 = = = =/24 = =
+#* stream tcp * = = =
diff --git a/contrib/blacklist/etc/npf.conf b/contrib/blacklist/etc/npf.conf
new file mode 100644
index 0000000..42d5604
--- /dev/null
+++ b/contrib/blacklist/etc/npf.conf
@@ -0,0 +1,15 @@
+# Transparent firewall example for blacklistd
+
+$ext_if = "bnx0"
+
+set bpf.jit on;
+alg "icmp"
+
+group "external" on $ext_if {
+ ruleset "blacklistd"
+ pass final all
+}
+
+group default {
+ pass final all
+}
diff --git a/contrib/blacklist/etc/rc.d/Makefile b/contrib/blacklist/etc/rc.d/Makefile
new file mode 100644
index 0000000..e863d08
--- /dev/null
+++ b/contrib/blacklist/etc/rc.d/Makefile
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $
+
+SCRIPTS=blacklistd
+SCRIPTSDIR=/etc/rc.d
+
+.include <bsd.prog.mk>
diff --git a/contrib/blacklist/etc/rc.d/blacklistd b/contrib/blacklist/etc/rc.d/blacklistd
new file mode 100644
index 0000000..2e46f51
--- /dev/null
+++ b/contrib/blacklist/etc/rc.d/blacklistd
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# $NetBSD: blacklistd,v 1.1 2015/01/22 17:49:41 christos Exp $
+#
+
+# PROVIDE: blacklistd
+# REQUIRE: npf
+# BEFORE: SERVERS
+
+$_rc_subr_loaded . /etc/rc.subr
+
+name="blacklistd"
+rcvar=$name
+command="/sbin/${name}"
+pidfile="/var/run/${name}.pid"
+required_files="/etc/${name}.conf"
+start_precmd="${name}_precmd"
+extra_commands="reload"
+
+_sockfile="/var/run/${name}.sockets"
+_sockname="blsock"
+
+blacklistd_precmd()
+{
+ # Create default list of blacklistd sockets to watch
+ #
+ ( umask 022 ; > $_sockfile )
+
+ # Find /etc/rc.d scripts with "chrootdir" rcorder(8) keyword,
+ # and if $${app}_chrootdir is a directory, add appropriate
+ # blacklistd socket to list of sockets to watch.
+ #
+ for _lr in $(rcorder -k chrootdir /etc/rc.d/*); do
+ (
+ _l=${_lr##*/}
+ load_rc_config ${_l}
+ eval _ldir=\$${_l}_chrootdir
+ if checkyesno $_l && [ -n "$_ldir" ]; then
+ echo "${_ldir}/var/run/${_sockname}" >> $_sockfile
+ fi
+ )
+ done
+
+ # If other sockets have been provided, change run_rc_command()'s
+ # internal copy of $blacklistd_flags to force use of specific
+ # blacklistd sockets.
+ #
+ if [ -s $_sockfile ]; then
+ echo "/var/run/${_sockname}" >> $_sockfile
+ rc_flags="-P $_sockfile $rc_flags"
+ fi
+
+ return 0
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/contrib/blacklist/include/Makefile b/contrib/blacklist/include/Makefile
new file mode 100644
index 0000000..6854907
--- /dev/null
+++ b/contrib/blacklist/include/Makefile
@@ -0,0 +1,10 @@
+# $NetBSD: Makefile,v 1.1 2015/01/21 16:16:00 christos Exp $
+
+# Doing a make includes builds /usr/include
+
+NOOBJ= # defined
+
+INCS= blacklist.h
+INCSDIR= /usr/include
+
+.include <bsd.prog.mk>
diff --git a/contrib/blacklist/include/bl.h b/contrib/blacklist/include/bl.h
new file mode 100644
index 0000000..68249cd
--- /dev/null
+++ b/contrib/blacklist/include/bl.h
@@ -0,0 +1,76 @@
+/* $NetBSD: bl.h,v 1.13 2016/03/11 17:16:40 christos Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _BL_H
+#define _BL_H
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include "blacklist.h"
+
+typedef enum {
+ BL_INVALID,
+ BL_ADD,
+ BL_DELETE
+} bl_type_t;
+
+typedef struct {
+ bl_type_t bi_type;
+ int bi_fd;
+ uid_t bi_uid;
+ gid_t bi_gid;
+ socklen_t bi_slen;
+ struct sockaddr_storage bi_ss;
+ char bi_msg[1024];
+} bl_info_t;
+
+#define bi_cred bi_u._bi_cred
+
+#ifndef _PATH_BLSOCK
+#define _PATH_BLSOCK "/var/run/blacklistd.sock"
+#endif
+
+__BEGIN_DECLS
+
+typedef struct blacklist *bl_t;
+
+bl_t bl_create(bool, const char *, void (*)(int, const char *, va_list));
+void bl_destroy(bl_t);
+int bl_send(bl_t, bl_type_t, int, const struct sockaddr *, socklen_t,
+ const char *);
+int bl_getfd(bl_t);
+bl_info_t *bl_recv(bl_t);
+bool bl_isconnected(bl_t);
+
+__END_DECLS
+
+#endif /* _BL_H */
diff --git a/contrib/blacklist/include/blacklist.h b/contrib/blacklist/include/blacklist.h
new file mode 100644
index 0000000..9ebe11b
--- /dev/null
+++ b/contrib/blacklist/include/blacklist.h
@@ -0,0 +1,46 @@
+/* $NetBSD: blacklist.h,v 1.3 2015/01/23 18:48:56 christos Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _BLACKLIST_H
+#define _BLACKLIST_H
+
+#include <sys/socket.h>
+
+__BEGIN_DECLS
+struct blacklist *blacklist_open(void);
+void blacklist_close(struct blacklist *);
+int blacklist(int, int, const char *);
+int blacklist_r(struct blacklist *, int, int, const char *);
+int blacklist_sa(int, int, const struct sockaddr *, socklen_t, const char *);
+int blacklist_sa_r(struct blacklist *, int, int,
+ const struct sockaddr *, socklen_t, const char *);
+__END_DECLS
+
+#endif /* _BLACKLIST_H */
diff --git a/contrib/blacklist/lib/Makefile b/contrib/blacklist/lib/Makefile
new file mode 100644
index 0000000..aea01ca
--- /dev/null
+++ b/contrib/blacklist/lib/Makefile
@@ -0,0 +1,19 @@
+# $NetBSD: Makefile,v 1.6 2016/01/05 13:07:46 christos Exp $
+
+.include <bsd.own.mk>
+
+USE_SHLIBDIR= yes
+
+CPPFLAGS+=-D_REENTRANT
+LIBDPLIBS+=pthread ${NETBSDSRCDIR}/lib/libpthread
+LIB=blacklist
+SRCS=bl.c blacklist.c
+MAN=libblacklist.3
+MLINKS+=libblacklist.3 blacklist_open.3
+MLINKS+=libblacklist.3 blacklist_close.3
+MLINKS+=libblacklist.3 blacklist.3
+MLINKS+=libblacklist.3 blacklist_r.3
+MLINKS+=libblacklist.3 blacklist_sa.3
+MLINKS+=libblacklist.3 blacklist_sa_r.3
+
+.include <bsd.lib.mk>
diff --git a/contrib/blacklist/lib/bl.c b/contrib/blacklist/lib/bl.c
new file mode 100644
index 0000000..bca52cf
--- /dev/null
+++ b/contrib/blacklist/lib/bl.c
@@ -0,0 +1,524 @@
+/* $NetBSD: bl.c,v 1.27 2015/12/30 16:42:48 christos Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: bl.c,v 1.27 2015/12/30 16:42:48 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <netinet/in.h>
+#ifdef _REENTRANT
+#include <pthread.h>
+#endif
+
+#include "bl.h"
+
+typedef struct {
+ uint32_t bl_len;
+ uint32_t bl_version;
+ uint32_t bl_type;
+ uint32_t bl_salen;
+ struct sockaddr_storage bl_ss;
+ char bl_data[];
+} bl_message_t;
+
+struct blacklist {
+#ifdef _REENTRANT
+ pthread_mutex_t b_mutex;
+# define BL_INIT(b) pthread_mutex_init(&b->b_mutex, NULL)
+# define BL_LOCK(b) pthread_mutex_lock(&b->b_mutex)
+# define BL_UNLOCK(b) pthread_mutex_unlock(&b->b_mutex)
+#else
+# define BL_INIT(b) do {} while(/*CONSTCOND*/0)
+# define BL_LOCK(b) BL_INIT(b)
+# define BL_UNLOCK(b) BL_INIT(b)
+#endif
+ int b_fd;
+ int b_connected;
+ struct sockaddr_un b_sun;
+ void (*b_fun)(int, const char *, va_list);
+ bl_info_t b_info;
+};
+
+#define BL_VERSION 1
+
+bool
+bl_isconnected(bl_t b)
+{
+ return b->b_connected == 0;
+}
+
+int
+bl_getfd(bl_t b)
+{
+ return b->b_fd;
+}
+
+static void
+bl_reset(bl_t b, bool locked)
+{
+ int serrno = errno;
+ if (!locked)
+ BL_LOCK(b);
+ close(b->b_fd);
+ errno = serrno;
+ b->b_fd = -1;
+ b->b_connected = -1;
+ if (!locked)
+ BL_UNLOCK(b);
+}
+
+static void
+bl_log(void (*fun)(int, const char *, va_list), int level,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int serrno = errno;
+
+ va_start(ap, fmt);
+ (*fun)(level, fmt, ap);
+ va_end(ap);
+ errno = serrno;
+}
+
+static int
+bl_init(bl_t b, bool srv)
+{
+ static int one = 1;
+ /* AF_UNIX address of local logger */
+ mode_t om;
+ int rv, serrno;
+ struct sockaddr_un *sun = &b->b_sun;
+
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK 0
+#endif
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC 0
+#endif
+#ifndef SOCK_NOSIGPIPE
+#define SOCK_NOSIGPIPE 0
+#endif
+
+ BL_LOCK(b);
+
+ if (b->b_fd == -1) {
+ b->b_fd = socket(PF_LOCAL,
+ SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NOSIGPIPE, 0);
+ if (b->b_fd == -1) {
+ bl_log(b->b_fun, LOG_ERR, "%s: socket failed (%m)",
+ __func__);
+ BL_UNLOCK(b);
+ return -1;
+ }
+#if SOCK_CLOEXEC == 0
+ fcntl(b->b_fd, F_SETFD, FD_CLOEXEC);
+#endif
+#if SOCK_NONBLOCK == 0
+ fcntl(b->b_fd, F_SETFL, fcntl(b->b_fd, F_GETFL) | O_NONBLOCK);
+#endif
+#if SOCK_NOSIGPIPE == 0
+#ifdef SO_NOSIGPIPE
+ int o = 1;
+ setsockopt(b->b_fd, SOL_SOCKET, SO_NOSIGPIPE, &o, sizeof(o));
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif
+#endif
+ }
+
+ if (bl_isconnected(b)) {
+ BL_UNLOCK(b);
+ return 0;
+ }
+
+ /*
+ * We try to connect anyway even when we are a server to verify
+ * that no other server is listening to the socket. If we succeed
+ * to connect and we are a server, someone else owns it.
+ */
+ rv = connect(b->b_fd, (const void *)sun, (socklen_t)sizeof(*sun));
+ if (rv == 0) {
+ if (srv) {
+ bl_log(b->b_fun, LOG_ERR,
+ "%s: another daemon is handling `%s'",
+ __func__, sun->sun_path);
+ goto out;
+ }
+ } else {
+ if (!srv) {
+ /*
+ * If the daemon is not running, we just try a
+ * connect, so leave the socket alone until it does
+ * and only log once.
+ */
+ if (b->b_connected != 1) {
+ bl_log(b->b_fun, LOG_DEBUG,
+ "%s: connect failed for `%s' (%m)",
+ __func__, sun->sun_path);
+ b->b_connected = 1;
+ }
+ BL_UNLOCK(b);
+ return -1;
+ }
+ bl_log(b->b_fun, LOG_DEBUG, "Connected to blacklist server",
+ __func__);
+ }
+
+ if (srv) {
+ (void)unlink(sun->sun_path);
+ om = umask(0);
+ rv = bind(b->b_fd, (const void *)sun, (socklen_t)sizeof(*sun));
+ serrno = errno;
+ (void)umask(om);
+ errno = serrno;
+ if (rv == -1) {
+ bl_log(b->b_fun, LOG_ERR,
+ "%s: bind failed for `%s' (%m)",
+ __func__, sun->sun_path);
+ goto out;
+ }
+ }
+
+ b->b_connected = 0;
+#define GOT_FD 1
+#if defined(LOCAL_CREDS)
+#define CRED_LEVEL 0
+#define CRED_NAME LOCAL_CREDS
+#define CRED_SC_UID sc_euid
+#define CRED_SC_GID sc_egid
+#define CRED_MESSAGE SCM_CREDS
+#define CRED_SIZE SOCKCREDSIZE(NGROUPS_MAX)
+#define CRED_TYPE struct sockcred
+#define GOT_CRED 2
+#elif defined(SO_PASSCRED)
+#define CRED_LEVEL SOL_SOCKET
+#define CRED_NAME SO_PASSCRED
+#define CRED_SC_UID uid
+#define CRED_SC_GID gid
+#define CRED_MESSAGE SCM_CREDENTIALS
+#define CRED_SIZE sizeof(struct ucred)
+#define CRED_TYPE struct ucred
+#define GOT_CRED 2
+#else
+#define GOT_CRED 0
+/*
+ * getpeereid() and LOCAL_PEERCRED don't help here
+ * because we are not a stream socket!
+ */
+#define CRED_SIZE 0
+#define CRED_TYPE void * __unused
+#endif
+
+#ifdef CRED_LEVEL
+ if (setsockopt(b->b_fd, CRED_LEVEL, CRED_NAME,
+ &one, (socklen_t)sizeof(one)) == -1) {
+ bl_log(b->b_fun, LOG_ERR, "%s: setsockopt %s "
+ "failed (%m)", __func__, __STRING(CRED_NAME));
+ goto out;
+ }
+#endif
+
+ BL_UNLOCK(b);
+ return 0;
+out:
+ bl_reset(b, true);
+ BL_UNLOCK(b);
+ return -1;
+}
+
+bl_t
+bl_create(bool srv, const char *path, void (*fun)(int, const char *, va_list))
+{
+ bl_t b = calloc(1, sizeof(*b));
+ if (b == NULL)
+ goto out;
+ b->b_fun = fun == NULL ? vsyslog : fun;
+ b->b_fd = -1;
+ b->b_connected = -1;
+ BL_INIT(b);
+
+ memset(&b->b_sun, 0, sizeof(b->b_sun));
+ b->b_sun.sun_family = AF_LOCAL;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ b->b_sun.sun_len = sizeof(b->b_sun);
+#endif
+ strlcpy(b->b_sun.sun_path,
+ path ? path : _PATH_BLSOCK, sizeof(b->b_sun.sun_path));
+
+ bl_init(b, srv);
+ return b;
+out:
+ free(b);
+ bl_log(fun, LOG_ERR, "%s: malloc failed (%m)", __func__);
+ return NULL;
+}
+
+void
+bl_destroy(bl_t b)
+{
+ bl_reset(b, false);
+ free(b);
+}
+
+static int
+bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa,
+ socklen_t slen, const char *ctx)
+{
+ uint8_t family;
+
+ memset(ss, 0, sizeof(*ss));
+
+ switch (slen) {
+ case 0:
+ return 0;
+ case sizeof(struct sockaddr_in):
+ family = AF_INET;
+ break;
+ case sizeof(struct sockaddr_in6):
+ family = AF_INET6;
+ break;
+ default:
+ bl_log(b->b_fun, LOG_ERR, "%s: invalid socket len %u (%s)",
+ __func__, (unsigned)slen, ctx);
+ errno = EINVAL;
+ return -1;
+ }
+
+ memcpy(ss, sa, slen);
+
+ if (ss->ss_family != family) {
+ bl_log(b->b_fun, LOG_INFO,
+ "%s: correcting socket family %d to %d (%s)",
+ __func__, ss->ss_family, family, ctx);
+ ss->ss_family = family;
+ }
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (ss->ss_len != slen) {
+ bl_log(b->b_fun, LOG_INFO,
+ "%s: correcting socket len %u to %u (%s)",
+ __func__, ss->ss_len, (unsigned)slen, ctx);
+ ss->ss_len = (uint8_t)slen;
+ }
+#endif
+ return 0;
+}
+
+int
+bl_send(bl_t b, bl_type_t e, int pfd, const struct sockaddr *sa,
+ socklen_t slen, const char *ctx)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ char ctrl[CMSG_SPACE(sizeof(int))];
+ uint32_t fd;
+ } ua;
+ struct cmsghdr *cmsg;
+ union {
+ bl_message_t bl;
+ char buf[512];
+ } ub;
+ size_t ctxlen, tried;
+#define NTRIES 5
+
+ ctxlen = strlen(ctx);
+ if (ctxlen > 128)
+ ctxlen = 128;
+
+ iov.iov_base = ub.buf;
+ iov.iov_len = sizeof(bl_message_t) + ctxlen;
+ ub.bl.bl_len = (uint32_t)iov.iov_len;
+ ub.bl.bl_version = BL_VERSION;
+ ub.bl.bl_type = (uint32_t)e;
+
+ if (bl_getsock(b, &ub.bl.bl_ss, sa, slen, ctx) == -1)
+ return -1;
+
+
+ ub.bl.bl_salen = slen;
+ memcpy(ub.bl.bl_data, ctx, ctxlen);
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+ msg.msg_control = ua.ctrl;
+ msg.msg_controllen = sizeof(ua.ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ memcpy(CMSG_DATA(cmsg), &pfd, sizeof(pfd));
+
+ tried = 0;
+again:
+ if (bl_init(b, false) == -1)
+ return -1;
+
+ if ((sendmsg(b->b_fd, &msg, 0) == -1) && tried++ < NTRIES) {
+ bl_reset(b, false);
+ goto again;
+ }
+ return tried >= NTRIES ? -1 : 0;
+}
+
+bl_info_t *
+bl_recv(bl_t b)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ char ctrl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(CRED_SIZE)];
+ uint32_t fd;
+ CRED_TYPE sc;
+ } ua;
+ struct cmsghdr *cmsg;
+ CRED_TYPE *sc;
+ union {
+ bl_message_t bl;
+ char buf[512];
+ } ub;
+ int got;
+ ssize_t rlen;
+ bl_info_t *bi = &b->b_info;
+
+ got = 0;
+ memset(bi, 0, sizeof(*bi));
+
+ iov.iov_base = ub.buf;
+ iov.iov_len = sizeof(ub);
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+ msg.msg_control = ua.ctrl;
+ msg.msg_controllen = sizeof(ua.ctrl) + 100;
+
+ rlen = recvmsg(b->b_fd, &msg, 0);
+ if (rlen == -1) {
+ bl_log(b->b_fun, LOG_ERR, "%s: recvmsg failed (%m)", __func__);
+ return NULL;
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level != SOL_SOCKET) {
+ bl_log(b->b_fun, LOG_ERR,
+ "%s: unexpected cmsg_level %d",
+ __func__, cmsg->cmsg_level);
+ continue;
+ }
+ switch (cmsg->cmsg_type) {
+ case SCM_RIGHTS:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+ bl_log(b->b_fun, LOG_ERR,
+ "%s: unexpected cmsg_len %d != %zu",
+ __func__, cmsg->cmsg_len,
+ CMSG_LEN(2 * sizeof(int)));
+ continue;
+ }
+ memcpy(&bi->bi_fd, CMSG_DATA(cmsg), sizeof(bi->bi_fd));
+ got |= GOT_FD;
+ break;
+#ifdef CRED_MESSAGE
+ case CRED_MESSAGE:
+ sc = (void *)CMSG_DATA(cmsg);
+ bi->bi_uid = sc->CRED_SC_UID;
+ bi->bi_gid = sc->CRED_SC_GID;
+ got |= GOT_CRED;
+ break;
+#endif
+ default:
+ bl_log(b->b_fun, LOG_ERR,
+ "%s: unexpected cmsg_type %d",
+ __func__, cmsg->cmsg_type);
+ continue;
+ }
+
+ }
+
+ if (got != (GOT_CRED|GOT_FD)) {
+ bl_log(b->b_fun, LOG_ERR, "message missing %s %s",
+#if GOT_CRED != 0
+ (got & GOT_CRED) == 0 ? "cred" :
+#endif
+ "", (got & GOT_FD) == 0 ? "fd" : "");
+
+ return NULL;
+ }
+
+ if ((size_t)rlen <= sizeof(ub.bl)) {
+ bl_log(b->b_fun, LOG_ERR, "message too short %zd", rlen);
+ return NULL;
+ }
+
+ if (ub.bl.bl_version != BL_VERSION) {
+ bl_log(b->b_fun, LOG_ERR, "bad version %d", ub.bl.bl_version);
+ return NULL;
+ }
+
+ bi->bi_type = ub.bl.bl_type;
+ bi->bi_slen = ub.bl.bl_salen;
+ bi->bi_ss = ub.bl.bl_ss;
+#ifndef CRED_MESSAGE
+ bi->bi_uid = -1;
+ bi->bi_gid = -1;
+#endif
+ strlcpy(bi->bi_msg, ub.bl.bl_data, MIN(sizeof(bi->bi_msg),
+ ((size_t)rlen - sizeof(ub.bl) + 1)));
+ return bi;
+}
diff --git a/contrib/blacklist/lib/blacklist.c b/contrib/blacklist/lib/blacklist.c
new file mode 100644
index 0000000..b8a524c
--- /dev/null
+++ b/contrib/blacklist/lib/blacklist.c
@@ -0,0 +1,88 @@
+/* $NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $");
+
+#include <stdio.h>
+#include <bl.h>
+
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+int
+blacklist_sa(int action, int rfd, const struct sockaddr *sa, socklen_t salen,
+ const char *msg)
+{
+ struct blacklist *bl;
+ int rv;
+ if ((bl = blacklist_open()) == NULL)
+ return -1;
+ rv = blacklist_sa_r(bl, action, rfd, sa, salen, msg);
+ blacklist_close(bl);
+ return rv;
+}
+
+int
+blacklist_sa_r(struct blacklist *bl, int action, int rfd,
+ const struct sockaddr *sa, socklen_t slen, const char *msg)
+{
+ return bl_send(bl, action ? BL_ADD : BL_DELETE, rfd, sa, slen, msg);
+}
+
+int
+blacklist(int action, int rfd, const char *msg)
+{
+ return blacklist_sa(action, rfd, NULL, 0, msg);
+}
+
+int
+blacklist_r(struct blacklist *bl, int action, int rfd, const char *msg)
+{
+ return blacklist_sa_r(bl, action, rfd, NULL, 0, msg);
+}
+
+struct blacklist *
+blacklist_open(void) {
+ return bl_create(false, NULL, vsyslog);
+}
+
+void
+blacklist_close(struct blacklist *bl)
+{
+ bl_destroy(bl);
+}
diff --git a/contrib/blacklist/lib/libblacklist.3 b/contrib/blacklist/lib/libblacklist.3
new file mode 100644
index 0000000..e136820
--- /dev/null
+++ b/contrib/blacklist/lib/libblacklist.3
@@ -0,0 +1,125 @@
+.\" $NetBSD: libblacklist.3,v 1.3 2015/01/25 23:09:28 wiz Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Christos Zoulas.
+.\"
+.\" 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.
+.\"
+.Dd January 22, 2015
+.Dt LIBBLACKLIST 3
+.Os
+.Sh NAME
+.Nm blacklist_open ,
+.Nm blacklist_close ,
+.Nm blacklist_r ,
+.Nm blacklist ,
+.Nm blacklist_sa
+.Nm blacklist_sa_r ,
+.Nd Blacklistd notification library
+.Sh LIBRARY
+.Lb libblacklist
+.Sh SYNOPSIS
+.In blacklist.h
+.Ft struct blacklist *
+.Fn blacklist_open "void"
+.Ft void
+.Fn blacklist_close "struct blacklist *cookie"
+.Ft int
+.Fn blacklist "int action" "int fd" "const char *msg"
+.Ft int
+.Fn blacklist_r "struct blacklist *cookie" "int action" "int fd" "const char *msg"
+.Ft int
+.Fn blacklist_sa "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg"
+.Ft int
+.Fn blacklist_sa_r "struct blacklist *cookie" "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg"
+.Sh DESCRIPTION
+These functions can be used by daemons to notify
+.Xr blacklistd 8
+about successful and failed remote connections so that blacklistd can
+block or release port access to prevent Denial of Service attacks.
+.Pp
+The function
+.Fn blacklist_open
+creates a the necessary state to communicate with
+.Xr blacklistd 8
+and returns a pointer to it, or
+.Dv NULL
+on failure.
+.Pp
+The
+.Fn blacklist_close
+function frees all memory and resources used.
+.Pp
+The
+.Fn blacklist
+function sends a message to
+.Xr blacklistd 8 ,
+with an
+.Ar action
+argument specifying
+.Dv 1
+for a failed connection or
+.Dv 0
+for a successful connection,
+a file descriptor
+.Ar fd
+specifying the accepted file descriptor connected to the client,
+and an optional message in the
+.Ar msg
+argument.
+.Pp
+The
+.Fn blacklist_r
+function is more efficient because it keeps the blacklist state around.
+.Pp
+The
+.Fn blacklist_sa
+and
+.Fn blacklist_sa_r
+functions can be used with unconnected sockets, where
+.Xr getpeername 2
+will not work, the server will pass the peer name in the message.
+.Pp
+All functions log errors to
+.Xr syslogd 8 .
+.Sh RETURN VALUES
+The function
+.Fn bl_open
+returns a cookie on success and
+.Dv NULL
+on failure setting errno to an appropriate value.
+.Pp
+The
+.Fn bl_send
+function returns
+.Dv 0
+on success and
+.Dv -1
+on failure setting errno to an appropriate value.
+.Sh SEE ALSO
+.Xr blacklistd.conf 5 ,
+.Xr blacklistd 8
+.Sh AUTHORS
+.An Christos Zoulas
diff --git a/contrib/blacklist/lib/shlib_version b/contrib/blacklist/lib/shlib_version
new file mode 100644
index 0000000..97c9f92
--- /dev/null
+++ b/contrib/blacklist/lib/shlib_version
@@ -0,0 +1,2 @@
+major=0
+minor=0
diff --git a/contrib/blacklist/libexec/Makefile b/contrib/blacklist/libexec/Makefile
new file mode 100644
index 0000000..6537080
--- /dev/null
+++ b/contrib/blacklist/libexec/Makefile
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.1 2015/01/22 17:49:41 christos Exp $
+
+SCRIPTS= blacklistd-helper
+SCRIPTSDIR= /libexec
+
+.include <bsd.prog.mk>
diff --git a/contrib/blacklist/libexec/blacklistd-helper b/contrib/blacklist/libexec/blacklistd-helper
new file mode 100644
index 0000000..743ccf5
--- /dev/null
+++ b/contrib/blacklist/libexec/blacklistd-helper
@@ -0,0 +1,82 @@
+#!/bin/sh
+#echo "run $@" 1>&2
+#set -x
+# $1 command
+# $2 rulename
+# $3 protocol
+# $4 address
+# $5 mask
+# $6 port
+# $7 id
+
+pf=
+for f in npf pf; do
+ if [ -f "/etc/$f.conf" ]; then
+ pf="$f"
+ break
+ fi
+done
+
+if [ -z "$pf" ]; then
+ echo "$0: Unsupported packet filter" 1>&2
+ exit 1
+fi
+
+if [ -n "$3" ]; then
+ proto="proto $3"
+fi
+
+if [ -n "$6" ]; then
+ port="port $6"
+fi
+
+addr="$4"
+mask="$5"
+case "$4" in
+::ffff:*.*.*.*)
+ if [ "$5" = 128 ]; then
+ mask=32
+ addr=${4#::ffff:}
+ fi;;
+esac
+
+case "$1" in
+add)
+ case "$pf" in
+ npf)
+ /sbin/npfctl rule "$2" add block in final $proto from \
+ "$addr/$mask" to any $port
+ ;;
+ pf)
+ # insert $ip/$mask into per-protocol anchored table
+ /sbin/pfctl -a "$2" -t "port$6" -T add "$addr/$mask"
+ echo "block in quick $proto from <port$6> to any $port" | \
+ /sbin/pfctl -a "$2" -f -
+ ;;
+ esac
+ ;;
+rem)
+ case "$pf" in
+ npf)
+ /sbin/npfctl rule "$2" rem-id "$7"
+ ;;
+ pf)
+ /sbin/pfctl -a "$2" -t "port$6" -T delete "$addr/$mask"
+ ;;
+ esac
+ ;;
+flush)
+ case "$pf" in
+ npf)
+ /sbin/npfctl rule "$2" flush
+ ;;
+ pf)
+ /sbin/pfctl -a "$2" -t "port$6" -T flush
+ ;;
+ esac
+ ;;
+*)
+ echo "$0: Unknown command '$1'" 1>&2
+ exit 1
+ ;;
+esac
diff --git a/contrib/blacklist/port/Makefile.am b/contrib/blacklist/port/Makefile.am
new file mode 100644
index 0000000..f1b36ca
--- /dev/null
+++ b/contrib/blacklist/port/Makefile.am
@@ -0,0 +1,25 @@
+#
+ACLOCAL_AMFLAGS = -I m4
+lib_LTLIBRARIES = libblacklist.la
+include_HEADERS = blacklist.h
+
+bin_PROGRAMS = blacklistd blacklistctl srvtest cltest
+
+VPATH = ../bin:../lib:../test
+
+AM_CPPFLAGS = -I../include -DDOT="."
+AM_CFLAGS = @WARNINGS@
+
+libblacklist_la_SOURCES = bl.c blacklist.c
+libblacklist_la_LDFLAGS = -no-undefined -version-info 0:0:0
+libblacklist_la_LIBADD = $(LTLIBOBJS)
+
+SRCS = internal.c support.c run.c conf.c state.c
+blacklistd_SOURCES = blacklistd.c ${SRCS}
+blacklistd_LDADD = libblacklist.la
+blacklistctl_SOURCES = blacklistctl.c ${SRCS}
+blacklistctl_LDADD = libblacklist.la
+srvtest_SOURCES = srvtest.c ${SRCS}
+srvtest_LDADD = libblacklist.la
+cltest_SOURCES = cltest.c ${SRCS}
+cltest_LDADD = libblacklist.la
diff --git a/contrib/blacklist/port/_strtoi.h b/contrib/blacklist/port/_strtoi.h
new file mode 100644
index 0000000..4b2b4e8
--- /dev/null
+++ b/contrib/blacklist/port/_strtoi.h
@@ -0,0 +1,93 @@
+/* $NetBSD: _strtoi.h,v 1.1 2015/01/22 02:15:59 christos Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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.
+ *
+ * Original version ID:
+ * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp
+ *
+ * Created by Kamil Rytarowski, based on ID:
+ * NetBSD: src/common/lib/libc/stdlib/_strtoul.h,v 1.7 2013/05/17 12:55:56 joerg Exp
+ */
+
+/*
+ * function template for strtoi and strtou
+ *
+ * parameters:
+ * _FUNCNAME : function name
+ * __TYPE : return and range limits type
+ * __WRAPPED : wrapped function, strtoimax or strtoumax
+ */
+
+__TYPE
+_FUNCNAME(const char * __restrict nptr, char ** __restrict endptr, int base,
+ __TYPE lo, __TYPE hi, int * rstatus)
+{
+ int serrno;
+ __TYPE im;
+ char *ep;
+ int rep;
+
+ /* endptr may be NULL */
+
+ if (endptr == NULL)
+ endptr = &ep;
+
+ if (rstatus == NULL)
+ rstatus = &rep;
+
+ serrno = errno;
+ errno = 0;
+
+ im = __WRAPPED(nptr, endptr, base);
+
+ *rstatus = errno;
+ errno = serrno;
+
+ if (*rstatus == 0) {
+ /* No digits were found */
+ if (nptr == *endptr)
+ *rstatus = ECANCELED;
+ /* There are further characters after number */
+ else if (**endptr != '\0')
+ *rstatus = ENOTSUP;
+ }
+
+ if (im < lo) {
+ if (*rstatus == 0)
+ *rstatus = ERANGE;
+ return lo;
+ }
+ if (im > hi) {
+ if (*rstatus == 0)
+ *rstatus = ERANGE;
+ return hi;
+ }
+
+ return im;
+}
diff --git a/contrib/blacklist/port/clock_gettime.c b/contrib/blacklist/port/clock_gettime.c
new file mode 100644
index 0000000..284bd81
--- /dev/null
+++ b/contrib/blacklist/port/clock_gettime.c
@@ -0,0 +1,17 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <sys/time.h>
+
+int
+clock_gettime(int clock __unused, struct timespec *ts)
+{
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL) == -1)
+ return -1;
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+ return 0;
+}
diff --git a/contrib/blacklist/port/config.h b/contrib/blacklist/port/config.h
new file mode 100644
index 0000000..27f3263
--- /dev/null
+++ b/contrib/blacklist/port/config.h
@@ -0,0 +1,3 @@
+#if defined(__FreeBSD__)
+#include "port.h"
+#endif
diff --git a/contrib/blacklist/port/configure.ac b/contrib/blacklist/port/configure.ac
new file mode 100644
index 0000000..eef8065
--- /dev/null
+++ b/contrib/blacklist/port/configure.ac
@@ -0,0 +1,91 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT([blacklistd],[0.1],[christos@netbsd.com])
+AM_INIT_AUTOMAKE([subdir-objects foreign])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_SUBST(WARNINGS)
+
+dnl Checks for programs.
+AC_PROG_CC_STDC
+AC_USE_SYSTEM_EXTENSIONS
+AM_PROG_CC_C_O
+AC_C_BIGENDIAN
+AC_PROG_INSTALL
+AC_PROG_LN_S
+LT_INIT([disable-static pic-only])
+gl_VISIBILITY
+dnl Checks for headers
+AC_HEADER_STDC
+AC_HEADER_MAJOR
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(stdint.h fcntl.h stdint.h inttypes.h unistd.h)
+AC_CHECK_HEADERS(sys/un.h sys/socket.h limits.h)
+AC_CHECK_HEADERS(arpa/inet.h getopt.h err.h)
+AC_CHECK_HEADERS(sys/types.h util.h sys/time.h time.h)
+AC_CHECK_HEADERS(netatalk/at.h net/if_dl.h db.h db_185.h)
+AC_CHECK_LIB(rt, clock_gettime)
+AC_CHECK_LIB(db, __db185_open)
+AC_CHECK_LIB(util, pidfile)
+AC_CHECK_LIB(util, sockaddr_snprintf)
+
+AH_BOTTOM([
+#ifndef __NetBSD__
+#include "port.h"
+#endif
+])
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+AC_SYS_LARGEFILE
+AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [#include <sys/socket.h>])
+
+AC_TYPE_PID_T
+AC_TYPE_UINT8_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_INT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_INT64_T
+AC_TYPE_INTPTR_T
+AC_TYPE_UINTPTR_T
+
+AC_MSG_CHECKING(for gcc compiler warnings)
+AC_ARG_ENABLE(warnings,
+[ --disable-warnings disable compiler warnings],
+[if test "${enableval}" = no -o "$GCC" = no; then
+ AC_MSG_RESULT(no)
+ WARNINGS=
+else
+ AC_MSG_RESULT(yes)
+ WARNINGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \
+ -Wmissing-declarations -Wredundant-decls -Wnested-externs \
+ -Wsign-compare -Wreturn-type -Wswitch -Wshadow \
+ -Wcast-qual -Wwrite-strings -Wextra -Wunused-parameter -Wformat=2"
+fi], [
+if test "$GCC" = yes; then
+ AC_MSG_RESULT(yes)
+ WARNINGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \
+ -Wmissing-declarations -Wredundant-decls -Wnested-externs \
+ -Wsign-compare -Wreturn-type -Wswitch -Wshadow \
+ -Wcast-qual -Wwrite-strings -Wextra -Wunused-parameter -Wformat=2"
+else
+ WARNINGS=
+ AC_MSG_RESULT(no)
+fi])
+
+dnl Checks for functions
+AC_CHECK_FUNCS(strerror)
+
+dnl Provide implementation of some required functions if necessary
+AC_REPLACE_FUNCS(strtoi sockaddr_snprintf popenve clock_gettime strlcpy strlcat getprogname fparseln fgetln pidfile)
+
+dnl See if we are cross-compiling
+AM_CONDITIONAL(IS_CROSS_COMPILE, test "$cross_compiling" = yes)
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/contrib/blacklist/port/fgetln.c b/contrib/blacklist/port/fgetln.c
new file mode 100644
index 0000000..a41a383
--- /dev/null
+++ b/contrib/blacklist/port/fgetln.c
@@ -0,0 +1,106 @@
+/* $NetBSD: fgetln.c,v 1.1 2015/01/22 03:48:07 christos Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if !HAVE_FGETLN
+#include <stdlib.h>
+#ifndef HAVE_NBTOOL_CONFIG_H
+/* These headers are required, but included from nbtool_config.h */
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#endif
+
+char *
+fgetln(FILE *fp, size_t *len)
+{
+ static char *buf = NULL;
+ static size_t bufsiz = 0;
+ char *ptr;
+
+
+ if (buf == NULL) {
+ bufsiz = BUFSIZ;
+ if ((buf = malloc(bufsiz)) == NULL)
+ return NULL;
+ }
+
+ if (fgets(buf, bufsiz, fp) == NULL)
+ return NULL;
+
+ *len = 0;
+ while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
+ size_t nbufsiz = bufsiz + BUFSIZ;
+ char *nbuf = realloc(buf, nbufsiz);
+
+ if (nbuf == NULL) {
+ int oerrno = errno;
+ free(buf);
+ errno = oerrno;
+ buf = NULL;
+ return NULL;
+ } else
+ buf = nbuf;
+
+ if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) {
+ buf[bufsiz] = '\0';
+ *len = strlen(buf);
+ return buf;
+ }
+
+ *len = bufsiz;
+ bufsiz = nbufsiz;
+ }
+
+ *len = (ptr - buf) + 1;
+ return buf;
+}
+
+#endif
+
+#ifdef TEST
+int
+main(int argc, char *argv[])
+{
+ char *p;
+ size_t len;
+
+ while ((p = fgetln(stdin, &len)) != NULL) {
+ (void)printf("%zu %s", len, p);
+ free(p);
+ }
+ return 0;
+}
+#endif
diff --git a/contrib/blacklist/port/fparseln.c b/contrib/blacklist/port/fparseln.c
new file mode 100644
index 0000000..5bfae54b
--- /dev/null
+++ b/contrib/blacklist/port/fparseln.c
@@ -0,0 +1,236 @@
+/* $NetBSD: fparseln.c,v 1.1 2015/01/22 03:48:07 christos Exp $ */
+
+/*
+ * Copyright (c) 1997 Christos Zoulas. 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 ``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 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fparseln.c,v 1.1 2015/01/22 03:48:07 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if ! HAVE_FPARSELN || BROKEN_FPARSELN
+
+#define FLOCKFILE(fp)
+#define FUNLOCKFILE(fp)
+
+#if defined(_REENTRANT) && !HAVE_NBTOOL_CONFIG_H
+#define __fgetln(f, l) __fgetstr(f, l, '\n')
+#else
+#define __fgetln(f, l) fgetln(f, l)
+#endif
+
+static int isescaped(const char *, const char *, int);
+
+/* isescaped():
+ * Return true if the character in *p that belongs to a string
+ * that starts in *sp, is escaped by the escape character esc.
+ */
+static int
+isescaped(const char *sp, const char *p, int esc)
+{
+ const char *cp;
+ size_t ne;
+
+ /* No escape character */
+ if (esc == '\0')
+ return 0;
+
+ /* Count the number of escape characters that precede ours */
+ for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
+ continue;
+
+ /* Return true if odd number of escape characters */
+ return (ne & 1) != 0;
+}
+
+
+/* fparseln():
+ * Read a line from a file parsing continuations ending in \
+ * and eliminating trailing newlines, or comments starting with
+ * the comment char.
+ */
+char *
+fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
+{
+ static const char dstr[3] = { '\\', '\\', '#' };
+
+ size_t s, len;
+ char *buf;
+ char *ptr, *cp;
+ int cnt;
+ char esc, con, nl, com;
+
+ len = 0;
+ buf = NULL;
+ cnt = 1;
+
+ if (str == NULL)
+ str = dstr;
+
+ esc = str[0];
+ con = str[1];
+ com = str[2];
+ /*
+ * XXX: it would be cool to be able to specify the newline character,
+ * but unfortunately, fgetln does not let us
+ */
+ nl = '\n';
+
+ FLOCKFILE(fp);
+
+ while (cnt) {
+ cnt = 0;
+
+ if (lineno)
+ (*lineno)++;
+
+ if ((ptr = __fgetln(fp, &s)) == NULL)
+ break;
+
+ if (s && com) { /* Check and eliminate comments */
+ for (cp = ptr; cp < ptr + s; cp++)
+ if (*cp == com && !isescaped(ptr, cp, esc)) {
+ s = cp - ptr;
+ cnt = s == 0 && buf == NULL;
+ break;
+ }
+ }
+
+ if (s && nl) { /* Check and eliminate newlines */
+ cp = &ptr[s - 1];
+
+ if (*cp == nl)
+ s--; /* forget newline */
+ }
+
+ if (s && con) { /* Check and eliminate continuations */
+ cp = &ptr[s - 1];
+
+ if (*cp == con && !isescaped(ptr, cp, esc)) {
+ s--; /* forget continuation char */
+ cnt = 1;
+ }
+ }
+
+ if (s == 0) {
+ /*
+ * nothing to add, skip realloc except in case
+ * we need a minimal buf to return an empty line
+ */
+ if (cnt || buf != NULL)
+ continue;
+ }
+
+ if ((cp = realloc(buf, len + s + 1)) == NULL) {
+ FUNLOCKFILE(fp);
+ free(buf);
+ return NULL;
+ }
+ buf = cp;
+
+ (void) memcpy(buf + len, ptr, s);
+ len += s;
+ buf[len] = '\0';
+ }
+
+ FUNLOCKFILE(fp);
+
+ if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
+ strchr(buf, esc) != NULL) {
+ ptr = cp = buf;
+ while (cp[0] != '\0') {
+ int skipesc;
+
+ while (cp[0] != '\0' && cp[0] != esc)
+ *ptr++ = *cp++;
+ if (cp[0] == '\0' || cp[1] == '\0')
+ break;
+
+ skipesc = 0;
+ if (cp[1] == com)
+ skipesc += (flags & FPARSELN_UNESCCOMM);
+ if (cp[1] == con)
+ skipesc += (flags & FPARSELN_UNESCCONT);
+ if (cp[1] == esc)
+ skipesc += (flags & FPARSELN_UNESCESC);
+ if (cp[1] != com && cp[1] != con && cp[1] != esc)
+ skipesc = (flags & FPARSELN_UNESCREST);
+
+ if (skipesc)
+ cp++;
+ else
+ *ptr++ = *cp++;
+ *ptr++ = *cp++;
+ }
+ *ptr = '\0';
+ len = strlen(buf);
+ }
+
+ if (size)
+ *size = len;
+ return buf;
+}
+
+#ifdef TEST
+
+int main(int, char **);
+
+int
+main(int argc, char **argv)
+{
+ char *ptr;
+ size_t size, line;
+
+ line = 0;
+ while ((ptr = fparseln(stdin, &size, &line, NULL,
+ FPARSELN_UNESCALL)) != NULL)
+ printf("line %d (%d) |%s|\n", line, size, ptr);
+ return 0;
+}
+
+/*
+
+# This is a test
+line 1
+line 2 \
+line 3 # Comment
+line 4 \# Not comment \\\\
+
+# And a comment \
+line 5 \\\
+line 6
+
+*/
+
+#endif /* TEST */
+#endif /* ! HAVE_FPARSELN || BROKEN_FPARSELN */
diff --git a/contrib/blacklist/port/getprogname.c b/contrib/blacklist/port/getprogname.c
new file mode 100644
index 0000000..983d674
--- /dev/null
+++ b/contrib/blacklist/port/getprogname.c
@@ -0,0 +1,24 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+
+extern char *__progname;
+
+const char *
+getprogname(void)
+{
+ return __progname;
+}
+
+void
+setprogname(char *p)
+{
+ char *q;
+ if (p == NULL)
+ return;
+ if ((q = strrchr(p, '/')) != NULL)
+ __progname = ++q;
+ else
+ __progname = p;
+}
diff --git a/contrib/blacklist/port/m4/.cvsignore b/contrib/blacklist/port/m4/.cvsignore
new file mode 100644
index 0000000..0f4126c
--- /dev/null
+++ b/contrib/blacklist/port/m4/.cvsignore
@@ -0,0 +1 @@
+*.m4
diff --git a/contrib/blacklist/port/pidfile.c b/contrib/blacklist/port/pidfile.c
new file mode 100644
index 0000000..4deb234
--- /dev/null
+++ b/contrib/blacklist/port/pidfile.c
@@ -0,0 +1,183 @@
+/* $NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe, Matthias Scheler and Julio Merino.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: pidfile.c,v 1.2 2016/04/05 12:28:57 christos Exp $");
+#endif
+
+#include <sys/param.h>
+
+#include <paths.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+static pid_t pidfile_pid;
+static char *pidfile_path;
+
+/* Deletes an existent pidfile iff it was created by this process. */
+static void
+pidfile_cleanup(void)
+{
+
+ if ((pidfile_path != NULL) && (pidfile_pid == getpid()))
+ (void) unlink(pidfile_path);
+}
+
+/* Registers an atexit(3) handler to delete the pidfile we have generated.
+ * We only register the handler when we create a pidfile, so we can assume
+ * that the pidfile exists.
+ *
+ * Returns 0 on success or -1 if the handler could not be registered. */
+static int
+register_atexit_handler(void)
+{
+ static bool done = false;
+
+ if (!done) {
+ if (atexit(pidfile_cleanup) < 0)
+ return -1;
+ done = true;
+ }
+
+ return 0;
+}
+
+/* Given a new pidfile name in 'path', deletes any previously-created pidfile
+ * if the previous file differs to the new one.
+ *
+ * If a previous file is deleted, returns 1, which means that a new pidfile
+ * must be created. Otherwise, this returns 0, which means that the existing
+ * file does not need to be touched. */
+static int
+cleanup_old_pidfile(const char* path)
+{
+ if (pidfile_path != NULL) {
+ if (strcmp(pidfile_path, path) != 0) {
+ pidfile_cleanup();
+
+ free(pidfile_path);
+ pidfile_path = NULL;
+
+ return 1;
+ } else
+ return 0;
+ } else
+ return 1;
+}
+
+/* Constructs a name for a pidfile in the default location (/var/run). If
+ * 'basename' is NULL, uses the name of the current program for the name of
+ * the pidfile.
+ *
+ * Returns a pointer to a dynamically-allocatd string containing the absolute
+ * path to the pidfile; NULL on failure. */
+static char *
+generate_varrun_path(const char *bname)
+{
+ char *path;
+
+ if (bname == NULL)
+ bname = getprogname();
+
+ /* _PATH_VARRUN includes trailing / */
+ if (asprintf(&path, "%s%s.pid", _PATH_VARRUN, bname) == -1)
+ return NULL;
+ return path;
+}
+
+/* Creates a pidfile with the provided name. The new pidfile is "registered"
+ * in the global variables pidfile_path and pidfile_pid so that any further
+ * call to pidfile(3) can check if we are recreating the same file or a new
+ * one.
+ *
+ * Returns 0 on success or -1 if there is any error. */
+static int
+create_pidfile(const char* path)
+{
+ FILE *f;
+
+ if (register_atexit_handler() == -1)
+ return -1;
+
+ if (cleanup_old_pidfile(path) == 0)
+ return 0;
+
+ pidfile_path = strdup(path);
+ if (pidfile_path == NULL)
+ return -1;
+
+ if ((f = fopen(path, "w")) == NULL) {
+ free(pidfile_path);
+ pidfile_path = NULL;
+ return -1;
+ }
+
+ pidfile_pid = getpid();
+
+ (void) fprintf(f, "%d\n", pidfile_pid);
+ (void) fclose(f);
+
+ return 0;
+}
+
+int
+pidfile(const char *path)
+{
+
+ if (path == NULL || strchr(path, '/') == NULL) {
+ char *default_path;
+
+ if ((default_path = generate_varrun_path(path)) == NULL)
+ return -1;
+
+ if (create_pidfile(default_path) == -1) {
+ free(default_path);
+ return -1;
+ }
+
+ free(default_path);
+ return 0;
+ } else
+ return create_pidfile(path);
+}
diff --git a/contrib/blacklist/port/popenve.c b/contrib/blacklist/port/popenve.c
new file mode 100644
index 0000000..20f6b5b
--- /dev/null
+++ b/contrib/blacklist/port/popenve.c
@@ -0,0 +1,274 @@
+/* $NetBSD: popenve.c,v 1.2 2015/01/22 03:10:50 christos Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * 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 University 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 REGENTS 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 REGENTS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
+#else
+__RCSID("$NetBSD: popenve.c,v 1.2 2015/01/22 03:10:50 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef __weak_alias
+__weak_alias(popen,_popen)
+__weak_alias(pclose,_pclose)
+#endif
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+#ifdef _REENTRANT
+ int fd;
+#endif
+ pid_t pid;
+} *pidlist;
+
+#ifdef _REENTRANT
+static rwlock_t pidlist_lock = RWLOCK_INITIALIZER;
+#endif
+
+static struct pid *
+pdes_get(int *pdes, const char **type)
+{
+ struct pid *cur;
+ int flags = strchr(*type, 'e') ? O_CLOEXEC : 0;
+ int serrno;
+
+ if (strchr(*type, '+')) {
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC 0
+#endif
+ int stype = flags ? (SOCK_STREAM | SOCK_CLOEXEC) : SOCK_STREAM;
+ *type = "r+";
+ if (socketpair(AF_LOCAL, stype, 0, pdes) < 0)
+ return NULL;
+#if SOCK_CLOEXEC == 0
+ fcntl(pdes[0], F_SETFD, FD_CLOEXEC);
+ fcntl(pdes[1], F_SETFD, FD_CLOEXEC);
+#endif
+ } else {
+ *type = strrchr(*type, 'r') ? "r" : "w";
+#if SOCK_CLOEXEC != 0
+ if (pipe2(pdes, flags) == -1)
+ return NULL;
+#else
+ if (pipe(pdes) == -1)
+ return NULL;
+ fcntl(pdes[0], F_SETFL, fcntl(pdes[0], F_GETFL) | flags);
+ fcntl(pdes[1], F_SETFL, fcntl(pdes[1], F_GETFL) | flags);
+#endif
+ }
+
+ if ((cur = malloc(sizeof(*cur))) != NULL)
+ return cur;
+ serrno = errno;
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
+ errno = serrno;
+ return NULL;
+}
+
+static void
+pdes_child(int *pdes, const char *type)
+{
+ struct pid *old;
+
+ /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
+ from previous popen() calls that remain open in the
+ parent process are closed in the new child process. */
+ for (old = pidlist; old; old = old->next)
+#ifdef _REENTRANT
+ (void)close(old->fd); /* don't allow a flush */
+#else
+ (void)close(fileno(old->fp)); /* don't allow a flush */
+#endif
+
+ if (type[0] == 'r') {
+ (void)close(pdes[0]);
+ if (pdes[1] != STDOUT_FILENO) {
+ (void)dup2(pdes[1], STDOUT_FILENO);
+ (void)close(pdes[1]);
+ }
+ if (type[1] == '+')
+ (void)dup2(STDOUT_FILENO, STDIN_FILENO);
+ } else {
+ (void)close(pdes[1]);
+ if (pdes[0] != STDIN_FILENO) {
+ (void)dup2(pdes[0], STDIN_FILENO);
+ (void)close(pdes[0]);
+ }
+ }
+}
+
+static void
+pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type)
+{
+ FILE *iop;
+
+ /* Parent; assume fdopen can't fail. */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+#ifdef _REENTRANT
+ cur->fd = pdes[0];
+#endif
+ (void)close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+#ifdef _REENTRANT
+ cur->fd = pdes[1];
+#endif
+ (void)close(pdes[0]);
+ }
+
+ /* Link into list of file descriptors. */
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+}
+
+static void
+pdes_error(int *pdes, struct pid *cur)
+{
+ free(cur);
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
+}
+
+FILE *
+popenve(const char *cmd, char *const *argv, char *const *envp, const char *type)
+{
+ struct pid *cur;
+ int pdes[2], serrno;
+ pid_t pid;
+
+ if ((cur = pdes_get(pdes, &type)) == NULL)
+ return NULL;
+
+#ifdef _REENTRANT
+ (void)rwlock_rdlock(&pidlist_lock);
+#endif
+ switch (pid = vfork()) {
+ case -1: /* Error. */
+ serrno = errno;
+#ifdef _REENTRANT
+ (void)rwlock_unlock(&pidlist_lock);
+#endif
+ pdes_error(pdes, cur);
+ errno = serrno;
+ return NULL;
+ /* NOTREACHED */
+ case 0: /* Child. */
+ pdes_child(pdes, type);
+ execve(cmd, argv, envp);
+ _exit(127);
+ /* NOTREACHED */
+ }
+
+ pdes_parent(pdes, cur, pid, type);
+
+#ifdef _REENTRANT
+ (void)rwlock_unlock(&pidlist_lock);
+#endif
+
+ return cur->fp;
+}
+
+/*
+ * pclose --
+ * Pclose returns -1 if stream is not associated with a `popened' command,
+ * if already `pclosed', or waitpid returns an error.
+ */
+int
+pcloseve(FILE *iop)
+{
+ struct pid *cur, *last;
+ int pstat;
+ pid_t pid;
+
+#ifdef _REENTRANT
+ rwlock_wrlock(&pidlist_lock);
+#endif
+
+ /* Find the appropriate file pointer. */
+ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ if (cur->fp == iop)
+ break;
+ if (cur == NULL) {
+#ifdef _REENTRANT
+ (void)rwlock_unlock(&pidlist_lock);
+#endif
+ errno = ESRCH;
+ return -1;
+ }
+
+ (void)fclose(iop);
+
+ /* Remove the entry from the linked list. */
+ if (last == NULL)
+ pidlist = cur->next;
+ else
+ last->next = cur->next;
+
+#ifdef _REENTRANT
+ (void)rwlock_unlock(&pidlist_lock);
+#endif
+
+ do {
+ pid = waitpid(cur->pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+
+ free(cur);
+
+ return pid == -1 ? -1 : pstat;
+}
diff --git a/contrib/blacklist/port/port.h b/contrib/blacklist/port/port.h
new file mode 100644
index 0000000..f82fb34
--- /dev/null
+++ b/contrib/blacklist/port/port.h
@@ -0,0 +1,86 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <inttypes.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <netdb.h>
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef __dead
+#define __dead __attribute__((__noreturn__))
+#endif
+
+#ifndef __RCSID
+#define __RCSID(a)
+#endif
+
+#ifndef __UNCONST
+#define __UNCONST(a) ((void *)(intptr_t)(a))
+#endif
+
+#ifndef __arraycount
+#define __arraycount(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_POPENVE
+FILE *popenve(const char *, char *const *, char *const *, const char *);
+int pcloseve(FILE *);
+#define pclose(a) pcloseve(a);
+#endif
+
+#ifndef HAVE_SOCKADDR_SNPRINTF
+struct sockaddr;
+int sockaddr_snprintf(char *, size_t, const char *, const struct sockaddr *);
+#endif
+
+#ifndef HAVE_STRTOI
+intmax_t strtoi(const char *, char **, int, intmax_t, intmax_t, int *);
+#endif
+
+#ifndef HAVE_GETPROGNAME
+const char *getprogname(void);
+void setprogname(char *);
+#endif
+
+#ifndef HAVE_PIDFILE
+int pidfile(const char *);
+#endif
+
+#ifndef HAVE_FPARSELN
+#define FPARSELN_UNESCALL 0xf
+#define FPARSELN_UNESCCOMM 0x1
+#define FPARSELN_UNESCCONT 0x2
+#define FPARSELN_UNESCESC 0x4
+#define FPARSELN_UNESCREST 0x8
+char *fparseln(FILE *, size_t *, size_t *, const char delim[3], int);
+#endif
+
+#ifndef HAVE_FGETLN
+char *fgetln(FILE *, size_t *);
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+struct timespec;
+int clock_gettime(int, struct timespec *);
+#define CLOCK_REALTIME 0
+#endif
+
+#if !defined(__FreeBSD__)
+#define _PATH_BLCONF "conf"
+#define _PATH_BLCONTROL "control"
+#define _PATH_BLSOCK "blacklistd.sock"
+#define _PATH_BLSTATE "blacklistd.db"
+#endif
diff --git a/contrib/blacklist/port/sockaddr_snprintf.c b/contrib/blacklist/port/sockaddr_snprintf.c
new file mode 100644
index 0000000..41e5e0c
--- /dev/null
+++ b/contrib/blacklist/port/sockaddr_snprintf.c
@@ -0,0 +1,383 @@
+/* $NetBSD: sockaddr_snprintf.c,v 1.10 2016/04/05 12:28:57 christos Exp $ */
+
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.10 2016/04/05 12:28:57 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#ifdef __linux__
+#undef HAVE_NETATALK_AT_H
+#endif
+#ifdef HAVE_NETATALK_AT_H
+#include <netatalk/at.h>
+#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <netdb.h>
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+#define SLEN(a) (a)->a ## _len
+#else
+static socklen_t
+socklen(u_int af)
+{
+ switch (af) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ case AF_LOCAL:
+ return sizeof(struct sockaddr_un);
+#ifdef HAVE_NET_IF_DL_H
+ case AF_LINK:
+ return sizeof(struct sockaddr_dl);
+#endif
+#ifdef HAVE_NETATALK_AT_H
+ case AF_APPLETALK:
+ return sizeof(struct sockaddr_at);
+#endif
+ default:
+ return sizeof(struct sockaddr_storage);
+ }
+}
+
+#define SLEN(a) socklen((a)->a ## _family)
+#endif
+
+#ifdef HAVE_NETATALK_AT_H
+static int
+debug_at(char *str, size_t len, const struct sockaddr_at *sat)
+{
+ return snprintf(str, len, "sat_len=%u, sat_family=%u, sat_port=%u, "
+ "sat_addr.s_net=%u, sat_addr.s_node=%u, "
+ "sat_range.r_netrange.nr_phase=%u, "
+ "sat_range.r_netrange.nr_firstnet=%u, "
+ "sat_range.r_netrange.nr_lastnet=%u",
+ SLEN(sat), sat->sat_family, sat->sat_port,
+ sat->sat_addr.s_net, sat->sat_addr.s_node,
+ sat->sat_range.r_netrange.nr_phase,
+ sat->sat_range.r_netrange.nr_firstnet,
+ sat->sat_range.r_netrange.nr_lastnet);
+}
+#endif
+
+static int
+debug_in(char *str, size_t len, const struct sockaddr_in *sin)
+{
+ return snprintf(str, len, "sin_len=%u, sin_family=%u, sin_port=%u, "
+ "sin_addr.s_addr=%08x",
+ SLEN(sin), sin->sin_family, sin->sin_port,
+ sin->sin_addr.s_addr);
+}
+
+static int
+debug_in6(char *str, size_t len, const struct sockaddr_in6 *sin6)
+{
+ const uint8_t *s = sin6->sin6_addr.s6_addr;
+
+ return snprintf(str, len, "sin6_len=%u, sin6_family=%u, sin6_port=%u, "
+ "sin6_flowinfo=%u, "
+ "sin6_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
+ "%02x:%02x:%02x:%02x:%02x:%02x, sin6_scope_id=%u",
+ SLEN(sin6), sin6->sin6_family, sin6->sin6_port,
+ sin6->sin6_flowinfo, s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5],
+ s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb], s[0xc], s[0xd],
+ s[0xe], s[0xf], sin6->sin6_scope_id);
+}
+
+static int
+debug_un(char *str, size_t len, const struct sockaddr_un *sun)
+{
+ return snprintf(str, len, "sun_len=%u, sun_family=%u, sun_path=%*s",
+ SLEN(sun), sun->sun_family, (int)sizeof(sun->sun_path),
+ sun->sun_path);
+}
+
+#ifdef HAVE_NET_IF_DL_H
+static int
+debug_dl(char *str, size_t len, const struct sockaddr_dl *sdl)
+{
+ const uint8_t *s = (const void *)sdl->sdl_data;
+
+ return snprintf(str, len, "sdl_len=%u, sdl_family=%u, sdl_index=%u, "
+ "sdl_type=%u, sdl_nlen=%u, sdl_alen=%u, sdl_slen=%u, sdl_data="
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+ SLEN(sdl), sdl->sdl_family, sdl->sdl_index,
+ sdl->sdl_type, sdl->sdl_nlen, sdl->sdl_alen, sdl->sdl_slen,
+ s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5],
+ s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb]);
+}
+#endif
+
+int
+sockaddr_snprintf(char * const sbuf, const size_t len, const char * const fmt,
+ const struct sockaddr * const sa)
+{
+ const void *a = NULL;
+ char abuf[1024], nbuf[1024], *addr = NULL;
+
+ char Abuf[1024], pbuf[32], *name = NULL, *port = NULL;
+ char *ebuf = &sbuf[len - 1], *buf = sbuf;
+ const char *ptr, *s;
+ int p = -1;
+#ifdef HAVE_NETATALK_AT_H
+ const struct sockaddr_at *sat = NULL;
+#endif
+ const struct sockaddr_in *sin4 = NULL;
+ const struct sockaddr_in6 *sin6 = NULL;
+ const struct sockaddr_un *sun = NULL;
+#ifdef HAVE_NET_IF_DL_H
+ const struct sockaddr_dl *sdl = NULL;
+ char *w = NULL;
+#endif
+ int na = 1;
+
+#define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
+ while (/*CONSTCOND*/0)
+#define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
+ while (/*CONSTCOND*/0)
+#define ADDNA() do { if (na) ADDS("N/A"); } \
+ while (/*CONSTCOND*/0)
+
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ goto done;
+#ifdef HAVE_NETATALK_AT_H
+ case AF_APPLETALK:
+ sat = ((const struct sockaddr_at *)(const void *)sa);
+ p = ntohs(sat->sat_port);
+ (void)snprintf(addr = abuf, sizeof(abuf), "%u.%u",
+ ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
+ (void)snprintf(port = pbuf, sizeof(pbuf), "%d", p);
+ break;
+#endif
+ case AF_LOCAL:
+ sun = ((const struct sockaddr_un *)(const void *)sa);
+ (void)strlcpy(addr = abuf, sun->sun_path, sizeof(abuf));
+ break;
+ case AF_INET:
+ sin4 = ((const struct sockaddr_in *)(const void *)sa);
+ p = ntohs(sin4->sin_port);
+ a = &sin4->sin_addr;
+ break;
+ case AF_INET6:
+ sin6 = ((const struct sockaddr_in6 *)(const void *)sa);
+ p = ntohs(sin6->sin6_port);
+ a = &sin6->sin6_addr;
+ break;
+#ifdef HAVE_NET_IF_DL_H
+ case AF_LINK:
+ sdl = ((const struct sockaddr_dl *)(const void *)sa);
+ (void)strlcpy(addr = abuf, link_ntoa(sdl), sizeof(abuf));
+ if ((w = strchr(addr, ':')) != 0) {
+ *w++ = '\0';
+ addr = w;
+ }
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (addr == abuf)
+ name = addr;
+
+ if (a && getnameinfo(sa, (socklen_t)SLEN(sa), addr = abuf,
+ (unsigned int)sizeof(abuf), NULL, 0,
+ NI_NUMERICHOST|NI_NUMERICSERV) != 0)
+ return -1;
+
+ for (ptr = fmt; *ptr; ptr++) {
+ if (*ptr != '%') {
+ ADDC(*ptr);
+ continue;
+ }
+ next_char:
+ switch (*++ptr) {
+ case '?':
+ na = 0;
+ goto next_char;
+ case 'a':
+ ADDS(addr);
+ break;
+ case 'p':
+ if (p != -1) {
+ (void)snprintf(nbuf, sizeof(nbuf), "%d", p);
+ ADDS(nbuf);
+ } else
+ ADDNA();
+ break;
+ case 'f':
+ (void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family);
+ ADDS(nbuf);
+ break;
+ case 'l':
+ (void)snprintf(nbuf, sizeof(nbuf), "%d", SLEN(sa));
+ ADDS(nbuf);
+ break;
+ case 'A':
+ if (name)
+ ADDS(name);
+ else if (!a)
+ ADDNA();
+ else {
+ getnameinfo(sa, (socklen_t)SLEN(sa),
+ name = Abuf,
+ (unsigned int)sizeof(nbuf), NULL, 0, 0);
+ ADDS(name);
+ }
+ break;
+ case 'P':
+ if (port)
+ ADDS(port);
+ else if (p == -1)
+ ADDNA();
+ else {
+ getnameinfo(sa, (socklen_t)SLEN(sa), NULL, 0,
+ port = pbuf,
+ (unsigned int)sizeof(pbuf), 0);
+ ADDS(port);
+ }
+ break;
+ case 'I':
+#ifdef HAVE_NET_IF_DL_H
+ if (sdl && addr != abuf) {
+ ADDS(abuf);
+ } else
+#endif
+ {
+ ADDNA();
+ }
+ break;
+ case 'F':
+ if (sin6) {
+ (void)snprintf(nbuf, sizeof(nbuf), "%d",
+ sin6->sin6_flowinfo);
+ ADDS(nbuf);
+ break;
+ } else {
+ ADDNA();
+ }
+ break;
+ case 'S':
+ if (sin6) {
+ (void)snprintf(nbuf, sizeof(nbuf), "%d",
+ sin6->sin6_scope_id);
+ ADDS(nbuf);
+ break;
+ } else {
+ ADDNA();
+ }
+ break;
+ case 'R':
+#ifdef HAVE_NETATALK_AT_H
+ if (sat) {
+ const struct netrange *n =
+ &sat->sat_range.r_netrange;
+ (void)snprintf(nbuf, sizeof(nbuf),
+ "%d:[%d,%d]", n->nr_phase , n->nr_firstnet,
+ n->nr_lastnet);
+ ADDS(nbuf);
+ } else
+#endif
+ {
+ ADDNA();
+ }
+ break;
+ case 'D':
+ switch (sa->sa_family) {
+#ifdef HAVE_NETATALK_AT_H
+ case AF_APPLETALK:
+ debug_at(nbuf, sizeof(nbuf), sat);
+ break;
+#endif
+ case AF_LOCAL:
+ debug_un(nbuf, sizeof(nbuf), sun);
+ break;
+ case AF_INET:
+ debug_in(nbuf, sizeof(nbuf), sin4);
+ break;
+ case AF_INET6:
+ debug_in6(nbuf, sizeof(nbuf), sin6);
+ break;
+#ifdef HAVE_NET_IF_DL_H
+ case AF_LINK:
+ debug_dl(nbuf, sizeof(nbuf), sdl);
+ break;
+#endif
+ default:
+ abort();
+ }
+ ADDS(nbuf);
+ break;
+ default:
+ ADDC('%');
+ if (na == 0)
+ ADDC('?');
+ if (*ptr == '\0')
+ goto done;
+ /*FALLTHROUGH*/
+ case '%':
+ ADDC(*ptr);
+ break;
+ }
+ na = 1;
+ }
+done:
+ if (buf < ebuf)
+ *buf = '\0';
+ else if (len != 0)
+ sbuf[len - 1] = '\0';
+ return (int)(buf - sbuf);
+}
diff --git a/contrib/blacklist/port/strlcat.c b/contrib/blacklist/port/strlcat.c
new file mode 100644
index 0000000..d3c69b5
--- /dev/null
+++ b/contrib/blacklist/port/strlcat.c
@@ -0,0 +1,96 @@
+/* $NetBSD: strlcat.c,v 1.2 2015/01/22 03:48:07 christos Exp $ */
+/* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strlcat.c,v 1.2 2015/01/22 03:48:07 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _LIBC
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strlcat, _strlcat)
+# endif
+#endif
+
+#else
+#include <lib/libkern/libkern.h>
+#endif /* !_KERNEL && !_STANDALONE */
+
+#if !HAVE_STRLCAT
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+#if 1
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+#else
+
+ /*
+ * Find length of string in dst (maxing out at siz).
+ */
+ size_t dlen = strnlen(dst, siz);
+
+ /*
+ * Copy src into any remaining space in dst (truncating if needed).
+ * Note strlcpy(dst, src, 0) returns strlen(src).
+ */
+ return dlen + strlcpy(dst + dlen, src, siz - dlen);
+#endif
+}
+#endif
diff --git a/contrib/blacklist/port/strlcpy.c b/contrib/blacklist/port/strlcpy.c
new file mode 100644
index 0000000..6646e1c
--- /dev/null
+++ b/contrib/blacklist/port/strlcpy.c
@@ -0,0 +1,78 @@
+/* $NetBSD: strlcpy.c,v 1.2 2015/01/22 03:48:07 christos Exp $ */
+/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strlcpy.c,v 1.2 2015/01/22 03:48:07 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _LIBC
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strlcpy, _strlcpy)
+# endif
+#endif
+#else
+#include <lib/libkern/libkern.h>
+#endif /* !_KERNEL && !_STANDALONE */
+
+
+#if !HAVE_STRLCPY
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
+#endif
diff --git a/contrib/blacklist/port/strtoi.c b/contrib/blacklist/port/strtoi.c
new file mode 100644
index 0000000..5514f1a
--- /dev/null
+++ b/contrib/blacklist/port/strtoi.c
@@ -0,0 +1,61 @@
+/* $NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $ */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project. All rights reserved.
+ * Copyright (c) 2003 Citrus 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.
+ *
+ * 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.
+ *
+ * Created by Kamil Rytarowski, based on ID:
+ * NetBSD: src/common/lib/libc/stdlib/strtoul.c,v 1.3 2008/08/20 19:58:34 oster Exp
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: strtoi.c,v 1.3 2015/01/22 03:10:50 christos Exp $");
+
+#if defined(_KERNEL)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <lib/libkern/libkern.h>
+#elif defined(_STANDALONE)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+#else
+#include <stddef.h>
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#endif
+
+#define _FUNCNAME strtoi
+#define __TYPE intmax_t
+#define __WRAPPED strtoimax
+
+#if !HAVE_STRTOI
+#include "_strtoi.h"
+#endif
diff --git a/contrib/blacklist/test/Makefile b/contrib/blacklist/test/Makefile
new file mode 100644
index 0000000..a451274
--- /dev/null
+++ b/contrib/blacklist/test/Makefile
@@ -0,0 +1,12 @@
+# $NetBSD: Makefile,v 1.3 2015/05/30 22:40:38 christos Exp $
+
+MKMAN=no
+
+PROGS=srvtest cltest
+SRCS.srvtest = srvtest.c
+SRCS.cltest = cltest.c
+CPPFLAGS+=-DBLDEBUG
+LDADD+=-lutil
+DPADD+=${LIBUTIL}
+
+.include <bsd.prog.mk>
diff --git a/contrib/blacklist/test/cltest.c b/contrib/blacklist/test/cltest.c
new file mode 100644
index 0000000..6671429
--- /dev/null
+++ b/contrib/blacklist/test/cltest.c
@@ -0,0 +1,136 @@
+/* $NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: cltest.c,v 1.6 2015/01/22 05:44:28 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+static __dead void
+usage(int c)
+{
+ warnx("Unknown option `%c'", (char)c);
+ fprintf(stderr, "Usage: %s [-u] [-a <addr>] [-m <msg>] [-p <port>]\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static void
+getaddr(const char *a, in_port_t p, struct sockaddr_storage *ss,
+ socklen_t *slen)
+{
+ int c;
+
+ memset(ss, 0, sizeof(*ss));
+ p = htons(p);
+
+ if (strchr(a, ':')) {
+ struct sockaddr_in6 *s6 = (void *)ss;
+ c = inet_pton(AF_INET6, a, &s6->sin6_addr);
+ s6->sin6_family = AF_INET6;
+ *slen = sizeof(*s6);
+ s6->sin6_port = p;
+ } else {
+ struct sockaddr_in *s = (void *)ss;
+ c = inet_pton(AF_INET, a, &s->sin_addr);
+ s->sin_family = AF_INET;
+ *slen = sizeof(*s);
+ s->sin_port = p;
+ }
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ ss->ss_len = (uint8_t)*slen;
+#endif
+ if (c == -1)
+ err(EXIT_FAILURE, "Invalid address `%s'", a);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int sfd;
+ int c;
+ struct sockaddr_storage ss;
+ const char *msg = "hello";
+ const char *addr = "127.0.0.1";
+ int type = SOCK_STREAM;
+ in_port_t port = 6161;
+ socklen_t slen;
+ char buf[128];
+
+ while ((c = getopt(argc, argv, "a:m:p:u")) != -1) {
+ switch (c) {
+ case 'a':
+ addr = optarg;
+ break;
+ case 'm':
+ msg = optarg;
+ break;
+ case 'p':
+ port = (in_port_t)atoi(optarg);
+ break;
+ case 'u':
+ type = SOCK_DGRAM;
+ break;
+ default:
+ usage(c);
+ }
+ }
+
+ getaddr(addr, port, &ss, &slen);
+
+ if ((sfd = socket(AF_INET, type, 0)) == -1)
+ err(EXIT_FAILURE, "socket");
+
+ sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (const void *)&ss);
+ printf("connecting to: %s\n", buf);
+ if (connect(sfd, (const void *)&ss, slen) == -1)
+ err(EXIT_FAILURE, "connect");
+
+ size_t len = strlen(msg) + 1;
+ if (write(sfd, msg, len) != (ssize_t)len)
+ err(EXIT_FAILURE, "write");
+ return 0;
+}
diff --git a/contrib/blacklist/test/srvtest.c b/contrib/blacklist/test/srvtest.c
new file mode 100644
index 0000000..03a762a
--- /dev/null
+++ b/contrib/blacklist/test/srvtest.c
@@ -0,0 +1,220 @@
+/* $NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: srvtest.c,v 1.10 2015/05/30 22:40:38 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <err.h>
+
+#include "blacklist.h"
+#ifdef BLDEBUG
+#include "bl.h"
+static void *b;
+#endif
+
+#ifndef INFTIM
+#define INFTIM -1
+#endif
+
+static void
+process_tcp(int afd)
+{
+ ssize_t n;
+ char buffer[256];
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((n = read(afd, buffer, sizeof(buffer))) == -1)
+ err(1, "read");
+ buffer[sizeof(buffer) - 1] = '\0';
+ printf("%s: sending %d %s\n", getprogname(), afd, buffer);
+#ifdef BLDEBUG
+ blacklist_r(b, 1, afd, buffer);
+#else
+ blacklist(1, afd, buffer);
+#endif
+ exit(0);
+}
+
+static void
+process_udp(int afd)
+{
+ ssize_t n;
+ char buffer[256];
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ slen = (socklen_t)sizeof(ss);
+ memset(&ss, 0, sizeof(ss));
+ if ((n = recvfrom(afd, buffer, sizeof(buffer), 0, (void *)&ss,
+ &slen)) == -1)
+ err(1, "recvfrom");
+ buffer[sizeof(buffer) - 1] = '\0';
+ printf("%s: sending %d %s\n", getprogname(), afd, buffer);
+ blacklist_sa(1, afd, (void *)&ss, slen, buffer);
+ exit(0);
+}
+static int
+cr(int af, int type, in_port_t p)
+{
+ int sfd;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+ sfd = socket(af == AF_INET ? PF_INET : PF_INET6, type, 0);
+ if (sfd == -1)
+ err(1, "socket");
+
+ p = htons(p);
+ memset(&ss, 0, sizeof(ss));
+ if (af == AF_INET) {
+ struct sockaddr_in *s = (void *)&ss;
+ s->sin_family = AF_INET;
+ slen = sizeof(*s);
+ s->sin_port = p;
+ } else {
+ struct sockaddr_in6 *s6 = (void *)&ss;
+ s6->sin6_family = AF_INET6;
+ slen = sizeof(*s6);
+ s6->sin6_port = p;
+ }
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ ss.ss_len = (uint8_t)slen;
+#endif
+
+ if (bind(sfd, (const void *)&ss, slen) == -1)
+ err(1, "bind");
+
+ if (type != SOCK_DGRAM)
+ if (listen(sfd, 5) == -1)
+ err(1, "listen");
+ return sfd;
+}
+
+static void
+handle(int type, int sfd)
+{
+ struct sockaddr_storage ss;
+ socklen_t alen = sizeof(ss);
+ int afd;
+
+ if (type != SOCK_DGRAM) {
+ if ((afd = accept(sfd, (void *)&ss, &alen)) == -1)
+ err(1, "accept");
+ } else
+ afd = sfd;
+
+ /* Create child process */
+ switch (fork()) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ if (type == SOCK_DGRAM)
+ process_udp(afd);
+ else
+ process_tcp(afd);
+ break;
+ default:
+ close(afd);
+ break;
+ }
+}
+
+static __dead void
+usage(int c)
+{
+ warnx("Unknown option `%c'", (char)c);
+ fprintf(stderr, "Usage: %s [-u] [-p <num>]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+#ifdef __linux__
+#define NUMFD 1
+#else
+#define NUMFD 2
+#endif
+ struct pollfd pfd[NUMFD];
+ int type = SOCK_STREAM, c;
+ in_port_t port = 6161;
+
+ signal(SIGCHLD, SIG_IGN);
+
+#ifdef BLDEBUG
+ b = bl_create(false, "blsock", vsyslog);
+#endif
+
+ while ((c = getopt(argc, argv, "up:")) != -1)
+ switch (c) {
+ case 'u':
+ type = SOCK_DGRAM;
+ break;
+ case 'p':
+ port = (in_port_t)atoi(optarg);
+ break;
+ default:
+ usage(c);
+ }
+
+ pfd[0].fd = cr(AF_INET, type, port);
+ pfd[0].events = POLLIN;
+#if NUMFD > 1
+ pfd[1].fd = cr(AF_INET6, type, port);
+ pfd[1].events = POLLIN;
+#endif
+
+ for (;;) {
+ if (poll(pfd, __arraycount(pfd), INFTIM) == -1)
+ err(1, "poll");
+ for (size_t i = 0; i < __arraycount(pfd); i++) {
+ if ((pfd[i].revents & POLLIN) == 0)
+ continue;
+ handle(type, pfd[i].fd);
+ }
+ }
+}
diff --git a/contrib/libxo/configure.ac b/contrib/libxo/configure.ac
index d1db438..0ff0a64 100644
--- a/contrib/libxo/configure.ac
+++ b/contrib/libxo/configure.ac
@@ -12,7 +12,7 @@
#
AC_PREREQ(2.2)
-AC_INIT([libxo], [0.6.1], [phil@juniper.net])
+AC_INIT([libxo], [0.6.2], [phil@juniper.net])
AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
# Support silent build rules. Requires at least automake-1.11.
diff --git a/contrib/libxo/doc/libxo-manual.html b/contrib/libxo/doc/libxo-manual.html
index 4db374b..0c042a4 100644
--- a/contrib/libxo/doc/libxo-manual.html
+++ b/contrib/libxo/doc/libxo-manual.html
@@ -515,7 +515,7 @@ li.indline1 {
}
@top-right {
- content: "April 2016";
+ content: "May 2016";
}
@top-center {
@@ -22009,7 +22009,7 @@ jQuery(function ($) {
</tr>
<tr>
<td class="header left"></td>
-<td class="header right">April 15, 2016</td>
+<td class="header right">May 28, 2016</td>
</tr>
</table></div>
<p id="title" class="title">libxo: The Easy Way to Generate text, XML, JSON, and HTML output<br><span class="filename">libxo-manual</span></p>
@@ -22739,7 +22739,7 @@ jQuery(function ($) {
make
make test
sudo make install
- </pre> <p id="doc_section_1_1_2_p_4">The following sections will walk thru each of these steps with additional details and options, but the above directions should be all that's needed.</p>
+ </pre> <p id="doc_section_1_1_2_p_4">The following sections will walk through each of these steps with additional details and options, but the above directions should be all that's needed.</p>
<p id="doc_section_1_1_2_p_5">Section Contents: </p>
<ul>
<li><a href="#setting-up-the-build" title="Setting up the build">Section1.1.2.1</a></li>
@@ -23087,7 +23087,7 @@ jQuery(function ($) {
xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\n",
free_blocks);
</pre> <p id="doc_section_2_2_1_p_3">When a role is not provided, the "value" role is used as the default.</p>
-<p id="doc_section_2_2_1_p_4">Roles and modifiers can also use more verbose names, when preceeded by a comma:</p>
+<p id="doc_section_2_2_1_p_4">Roles and modifiers can also use more verbose names, when preceded by a comma:</p>
<div id="doc_figure_u.27"></div> <pre>
EXAMPLE:
xo_emit("{,label:Free}{,decoration::}{,padding: }"
@@ -23444,7 +23444,7 @@ jQuery(function ($) {
</tr>
</tbody>
</table></div>
-<p id="doc_section_2_2_2_p_2">Roles and modifiers can also use more verbose names, when preceeded by a comma. For example, the modifier string "Lwc" (or "L,white,colon") means the field has a label role (text that describes the next field) and should be followed by a colon ('c') and a space ('w'). The modifier string "Vkq" (or ":key,quote") means the field has a value role (the default role), that it is a key for the current instance, and that the value should be quoted when encoded for JSON.</p>
+<p id="doc_section_2_2_2_p_2">Roles and modifiers can also use more verbose names, when preceded by a comma. For example, the modifier string "Lwc" (or "L,white,colon") means the field has a label role (text that describes the next field) and should be followed by a colon ('c') and a space ('w'). The modifier string "Vkq" (or ":key,quote") means the field has a value role (the default role), that it is a key for the current instance, and that the value should be quoted when encoded for JSON.</p>
<p id="doc_section_2_2_2_p_3">Section Contents: </p>
<ul>
<li><a href="#the-argument-modifier-a" title="The Argument Modifier ({a:})">Section2.2.2.1</a></li>
@@ -23688,7 +23688,7 @@ jQuery(function ($) {
<li>a '#' character, indicating the output value should be prefixed with '0x', typically to indicate a base 16 (hex) value.</li>
<li>a minus sign ('&#8209;'), indicating the output value should be padded on the right instead of the left.</li>
<li>a leading zero ('0') indicating the output value should be padded on the left with zeroes instead of spaces (' ').</li>
-<li>one or more digits ('0' - '9') indicating the minimum width of the argument. If the width in columns of the output value is less that the minumum width, the value will be padded to reach the minimum.</li>
+<li>one or more digits ('0' - '9') indicating the minimum width of the argument. If the width in columns of the output value is less than the minimum width, the value will be padded to reach the minimum.</li>
<li>a period followed by one or more digits indicating the maximum number of bytes which will be examined for a string argument, or the maximum width for a non-string argument. When handling ASCII strings this functions as the field width but for multi-byte characters, a single character may be composed of multiple bytes. xo_emit will never dereference memory beyond the given number of bytes.</li>
<li>a second period followed by one or more digits indicating the maximum width for a string argument. This modifier cannot be given for non-string arguments.</li>
<li>one or more 'h' characters, indicating shorter input data.</li>
diff --git a/contrib/libxo/doc/libxo.txt b/contrib/libxo/doc/libxo.txt
index ba63702..4cd51cc 100644
--- a/contrib/libxo/doc/libxo.txt
+++ b/contrib/libxo/doc/libxo.txt
@@ -155,7 +155,7 @@ explained in detail in the rest of this section.
make test
sudo make install
-The following sections will walk thru each of these steps with
+The following sections will walk through each of these steps with
additional details and options, but the above directions should be all
that's needed.
@@ -469,7 +469,7 @@ content. The roles are listed below; only one role is permitted:
When a role is not provided, the "value" role is used as the default.
-Roles and modifiers can also use more verbose names, when preceeded by
+Roles and modifiers can also use more verbose names, when preceded by
a comma:
EXAMPLE:
@@ -720,7 +720,7 @@ particular output styles:
| w | white | A blank (" ") is appended after the label |
|---+---------------+--------------------------------------------------|
-Roles and modifiers can also use more verbose names, when preceeded by
+Roles and modifiers can also use more verbose names, when preceded by
a comma. For example, the modifier string "Lwc" (or "L,white,colon")
means the field has a label role (text that describes the next field)
and should be followed by a colon ('c') and a space ('w'). The
@@ -986,8 +986,8 @@ the right instead of the left.
- a leading zero ('0') indicating the output value should be padded on the
left with zeroes instead of spaces (' ').
- one or more digits ('0' - '9') indicating the minimum width of the
-argument. If the width in columns of the output value is less that
-the minumum width, the value will be padded to reach the minimum.
+argument. If the width in columns of the output value is less than
+the minimum width, the value will be padded to reach the minimum.
- a period followed by one or more digits indicating the maximum
number of bytes which will be examined for a string argument, or the maximum
width for a non-string argument. When handling ASCII strings this
diff --git a/contrib/libxo/libxo/libxo.c b/contrib/libxo/libxo/libxo.c
index 194a096..7a714b1 100644
--- a/contrib/libxo/libxo/libxo.c
+++ b/contrib/libxo/libxo/libxo.c
@@ -56,7 +56,7 @@
* (end of word, middle of word, etc) and many that affect characters
* previously emitted. Without content, it can't hope to tell us.
* But it's the only standard tool we've got, so we use it. We would
- * use wcswidth() but it typically just loops thru adding the results
+ * use wcswidth() but it typically just loops through adding the results
* of wcwidth() calls in an entirely unhelpful way.
*
* Even then, there are many poor implementations (macosx), so we have
@@ -97,7 +97,7 @@
/*
* Three styles of specifying thread-local variables are supported.
- * configure.ac has the brains to run each possibility thru the
+ * configure.ac has the brains to run each possibility through the
* compiler and see what works; we are left to define the THREAD_LOCAL
* macro to the right value. Most toolchains (clang, gcc) use
* "before", but some (borland) use "after" and I've heard of some
@@ -988,7 +988,7 @@ xo_vsnprintf (xo_handle_t *xop, xo_buffer_t *xbp, const char *fmt, va_list vap)
}
/*
- * Print some data thru the handle.
+ * Print some data through the handle.
*/
static int
xo_printf_v (xo_handle_t *xop, const char *fmt, va_list vap)
@@ -1251,7 +1251,7 @@ xo_buf_append_locale (xo_handle_t *xop, xo_buffer_t *xbp,
cols += xo_buf_append_locale_from_utf8(xop, xbp, cp, slen);
- /* Next time thru, we'll start at the next character */
+ /* Next time through, we'll start at the next character */
cp += slen - 1;
sp = cp + 1;
}
@@ -2816,7 +2816,7 @@ xo_format_string (xo_handle_t *xop, xo_buffer_t *xbp, xo_xff_flags_t flags,
* but if we did the work ourselves, then we need to do it.
*/
int delta = xfp->xf_width[XF_WIDTH_MIN] - cols;
- if (!xo_buf_has_room(xbp, delta))
+ if (!xo_buf_has_room(xbp, xfp->xf_width[XF_WIDTH_MIN]))
goto bail;
/*
@@ -3328,7 +3328,7 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp,
case XO_STYLE_XML:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
- /* fall thru */
+ /* FALLTHRU */
case XO_STYLE_HTML:
rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR));
break;
@@ -3687,7 +3687,7 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
if (flags & XFF_ENCODE_ONLY) {
/*
- * Even if this is encode-only, we need to go thru the
+ * Even if this is encode-only, we need to go through the
* work of formatting it to make sure the args are cleared
* from xo_vap.
*/
@@ -5342,7 +5342,7 @@ xo_gettext_finish_numbering_fields (xo_handle_t *xop UNUSED,
}
/*
- * The format string uses field numbers, so we need to whiffle thru it
+ * The format string uses field numbers, so we need to whiffle through it
* and make sure everything's sane and lovely.
*/
static int
@@ -6128,6 +6128,12 @@ xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields,
XOIF_CLEAR(xop, XOIF_REORDER);
+ /*
+ * If we've got enough data, flush it.
+ */
+ if (xo_buf_offset(&xop->xo_data) > XO_BUF_HIGH_WATER)
+ flush = 1;
+
/* If we don't have an anchor, write the text out */
if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) {
if (xo_write(xop) < 0)
@@ -6988,7 +6994,7 @@ xo_do_close_leaf_list (xo_handle_t *xop, const char *name)
case XO_STYLE_ENCODER:
rc = xo_encoder_handle(xop, XO_OP_CLOSE_LEAF_LIST, name, NULL);
- /*fallthru*/
+ /* FALLTHRU */
default:
xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LEAF_LIST, XSF_LIST);
@@ -7780,9 +7786,9 @@ xo_parse_args (int argc, char **argv)
}
cp = argv[i] + sizeof(libxo_opt) - 1;
- if (*cp == 0) {
+ if (*cp == '\0') {
cp = argv[++i];
- if (cp == 0) {
+ if (cp == NULL) {
xo_warnx("missing libxo option");
return -1;
}
@@ -7879,7 +7885,7 @@ xo_set_version_h (xo_handle_t *xop, const char *version)
}
/*
- * Set the version number for the API content being carried thru
+ * Set the version number for the API content being carried through
* the xo handle.
*/
void
diff --git a/contrib/libxo/libxo/xo_buf.h b/contrib/libxo/libxo/xo_buf.h
index 349e9ad..01eb397 100644
--- a/contrib/libxo/libxo/xo_buf.h
+++ b/contrib/libxo/libxo/xo_buf.h
@@ -19,8 +19,8 @@
#ifndef XO_BUF_H
#define XO_BUF_H
-#define XO_BUFSIZ (8*1024) /* Initial buffer size */
-
+#define XO_BUFSIZ (8*1024) /* Initial buffer size */
+#define XO_BUF_HIGH_WATER (XO_BUFSIZ - 512) /* When to auto-flush */
/*
* xo_buffer_t: a memory buffer that can be grown as needed. We
* use them for building format strings and output data.
diff --git a/contrib/libxo/libxo/xo_encoder.c b/contrib/libxo/libxo/xo_encoder.c
index 70195ec..eb2960b 100644
--- a/contrib/libxo/libxo/xo_encoder.c
+++ b/contrib/libxo/libxo/xo_encoder.c
@@ -313,7 +313,7 @@ xo_encoder_init (xo_handle_t *xop, const char *name)
/*
* A couple of function varieties here, to allow for multiple
- * use cases. This varient is for when the main program knows
+ * use cases. This variant is for when the main program knows
* its own encoder needs.
*/
xo_handle_t *
diff --git a/contrib/libxo/libxo/xo_format.5 b/contrib/libxo/libxo/xo_format.5
index 79af3fa..abd1b6f 100644
--- a/contrib/libxo/libxo/xo_format.5
+++ b/contrib/libxo/libxo/xo_format.5
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd November 6, 2015
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -116,7 +116,7 @@ The roles are listed below; only one role is permitted:
.Pp
When a role is not provided, the "value" role is used as the default.
.Pp
-Roles and modifiers can also use more verbose names, when preceeded by
+Roles and modifiers can also use more verbose names, when preceded by
a comma:
.Bd -literal -offset indent
EXAMPLE:
@@ -380,7 +380,7 @@ The modifier string "Vkq" means the
field has a value role, that it is a key for the current instance, and
that the value should be quoted when encoded for JSON.
.Pp
-Roles and modifiers can also use more verbose names, when preceeded by
+Roles and modifiers can also use more verbose names, when preceded by
a comma.
For example, the modifier string "Lwc" (or "L,white,colon")
means the field has a label role (text that describes the next field)
diff --git a/contrib/libxo/libxo/xo_syslog.c b/contrib/libxo/libxo/xo_syslog.c
index da53e0c..c7d67f3 100644
--- a/contrib/libxo/libxo/xo_syslog.c
+++ b/contrib/libxo/libxo/xo_syslog.c
@@ -91,7 +91,7 @@
#elif defined(__macosx__)
#define XO_DEFAULT_EID 63
#else
-#define XO_DEFAULT_EID 32473 /* Bail; use "example" number */
+#define XO_DEFAULT_EID 32473 /* Fallback to the "example" number */
#endif
#ifdef _SC_HOST_NAME_MAX
diff --git a/contrib/libxo/tests/core/saved/test_03.E.out b/contrib/libxo/tests/core/saved/test_03.E.out
index 3965783..c68081f 100644
--- a/contrib/libxo/tests/core/saved/test_03.E.out
+++ b/contrib/libxo/tests/core/saved/test_03.E.out
@@ -1,6 +1,18 @@
op create: [] []
op open_container: [employees] []
op open_list: [employee] []
+op close_list: [employee] []
+op string: [extra] []
+op open_list: [memory] []
+op open_instance: [memory] []
+op string: [type] [name]
+op content: [in-use] [12345]
+op content: [memory-use] [54321]
+op string: [high-use] [-]
+op content: [requests] [32145]
+op close_instance: [memory] []
+op close_list: [memory] []
+op open_list: [employee] []
op open_instance: [employee] []
op string: [first-name] [Terry]
op string: [last-name] [Jones]
diff --git a/contrib/libxo/tests/core/saved/test_03.H.out b/contrib/libxo/tests/core/saved/test_03.H.out
index 6b9ccc4..ff61897 100644
--- a/contrib/libxo/tests/core/saved/test_03.H.out
+++ b/contrib/libxo/tests/core/saved/test_03.H.out
@@ -1 +1 @@
-<div class="line"><div class="data" data-tag="first-name">Terry</div><div class="text"> </div><div class="data" data-tag="last-name">Jones</div><div class="text"> works in dept #</div><div class="data" data-tag="department">660</div></div><div class="line"><div class="data" data-tag="first-name">Leslie</div><div class="text"> </div><div class="data" data-tag="last-name">Patterson</div><div class="text"> works in dept #</div><div class="data" data-tag="department">341</div></div><div class="line"><div class="data" data-tag="first-name">Ashley</div><div class="text"> </div><div class="data" data-tag="last-name">Smith</div><div class="text"> works in dept #</div><div class="data" data-tag="department">1440</div></div> \ No newline at end of file
+<div class="line"><div class="text">[</div><div class="data" data-tag="extra"></div><div class="text">]</div></div><div class="line"><div class="title"> Type</div><div class="text"> </div><div class="title">InUse</div><div class="text"> </div><div class="title">MemUse</div><div class="text"> </div><div class="title">HighUse</div><div class="text"> </div><div class="title">Requests</div><div class="text"> </div><div class="title">Size(s)</div></div><div class="line"><div class="data" data-tag="type"> name</div><div class="text"> </div><div class="data" data-tag="in-use">12345</div><div class="text"> </div><div class="data" data-tag="memory-use">54321</div><div class="units">K</div><div class="text"> </div><div class="data" data-tag="high-use"> -</div><div class="text"> </div><div class="data" data-tag="requests"> 32145</div><div class="text"> </div></div><div class="line"><div class="data" data-tag="first-name">Terry</div><div class="text"> </div><div class="data" data-tag="last-name">Jones</div><div class="text"> works in dept #</div><div class="data" data-tag="department">660</div></div><div class="line"><div class="data" data-tag="first-name">Leslie</div><div class="text"> </div><div class="data" data-tag="last-name">Patterson</div><div class="text"> works in dept #</div><div class="data" data-tag="department">341</div></div><div class="line"><div class="data" data-tag="first-name">Ashley</div><div class="text"> </div><div class="data" data-tag="last-name">Smith</div><div class="text"> works in dept #</div><div class="data" data-tag="department">1440</div></div><div class="line"><div class="text">done</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_03.HIPx.out b/contrib/libxo/tests/core/saved/test_03.HIPx.out
index bfae221..aaf867b 100644
--- a/contrib/libxo/tests/core/saved/test_03.HIPx.out
+++ b/contrib/libxo/tests/core/saved/test_03.HIPx.out
@@ -1,4 +1,35 @@
<div class="line">
+ <div class="text">[</div>
+ <div class="data" data-tag="extra" data-xpath="/employees/extra"></div>
+ <div class="text">]</div>
+</div>
+<div class="line">
+ <div class="title"> Type</div>
+ <div class="text"> </div>
+ <div class="title">InUse</div>
+ <div class="text"> </div>
+ <div class="title">MemUse</div>
+ <div class="text"> </div>
+ <div class="title">HighUse</div>
+ <div class="text"> </div>
+ <div class="title">Requests</div>
+ <div class="text"> </div>
+ <div class="title">Size(s)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="type" data-xpath="/employees/memory/type"> name</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="in-use" data-xpath="/employees/memory[type = 'name']/in-use">12345</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="memory-use" data-xpath="/employees/memory[type = 'name']/memory-use">54321</div>
+ <div class="units">K</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="high-use" data-xpath="/employees/memory[type = 'name']/high-use"> -</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="requests" data-xpath="/employees/memory[type = 'name']/requests"> 32145</div>
+ <div class="text"> </div>
+</div>
+<div class="line">
<div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Terry</div>
<div class="text"> </div>
<div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Jones</div>
@@ -19,3 +50,6 @@
<div class="text"> works in dept #</div>
<div class="data" data-tag="department" data-xpath="/employees/employee/department">1440</div>
</div>
+<div class="line">
+ <div class="text">done</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_03.HP.out b/contrib/libxo/tests/core/saved/test_03.HP.out
index f8b072a..2e476fb 100644
--- a/contrib/libxo/tests/core/saved/test_03.HP.out
+++ b/contrib/libxo/tests/core/saved/test_03.HP.out
@@ -1,4 +1,35 @@
<div class="line">
+ <div class="text">[</div>
+ <div class="data" data-tag="extra"></div>
+ <div class="text">]</div>
+</div>
+<div class="line">
+ <div class="title"> Type</div>
+ <div class="text"> </div>
+ <div class="title">InUse</div>
+ <div class="text"> </div>
+ <div class="title">MemUse</div>
+ <div class="text"> </div>
+ <div class="title">HighUse</div>
+ <div class="text"> </div>
+ <div class="title">Requests</div>
+ <div class="text"> </div>
+ <div class="title">Size(s)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="type"> name</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="in-use">12345</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="memory-use">54321</div>
+ <div class="units">K</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="high-use"> -</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="requests"> 32145</div>
+ <div class="text"> </div>
+</div>
+<div class="line">
<div class="data" data-tag="first-name">Terry</div>
<div class="text"> </div>
<div class="data" data-tag="last-name">Jones</div>
@@ -19,3 +50,6 @@
<div class="text"> works in dept #</div>
<div class="data" data-tag="department">1440</div>
</div>
+<div class="line">
+ <div class="text">done</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_03.J.out b/contrib/libxo/tests/core/saved/test_03.J.out
index 4ba1fb1..00a5301 100644
--- a/contrib/libxo/tests/core/saved/test_03.J.out
+++ b/contrib/libxo/tests/core/saved/test_03.J.out
@@ -1,2 +1,2 @@
-{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
+{"employees": {"employee": [],"extra":"", "memory": [{"type":"name","in-use":12345,"memory-use":54321,"high-use":"-","requests":32145}], "employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
}
diff --git a/contrib/libxo/tests/core/saved/test_03.JP.out b/contrib/libxo/tests/core/saved/test_03.JP.out
index ff2d5b0..a62f47e 100644
--- a/contrib/libxo/tests/core/saved/test_03.JP.out
+++ b/contrib/libxo/tests/core/saved/test_03.JP.out
@@ -1,6 +1,18 @@
{
"employees": {
"employee": [
+ ],
+ "extra": "",
+ "memory": [
+ {
+ "type": "name",
+ "in-use": 12345,
+ "memory-use": 54321,
+ "high-use": "-",
+ "requests": 32145
+ }
+ ],
+ "employee": [
{
"first-name": "Terry",
"last-name": "Jones",
diff --git a/contrib/libxo/tests/core/saved/test_03.T.out b/contrib/libxo/tests/core/saved/test_03.T.out
index da60fb7..90486fb 100644
--- a/contrib/libxo/tests/core/saved/test_03.T.out
+++ b/contrib/libxo/tests/core/saved/test_03.T.out
@@ -1,3 +1,7 @@
+[]
+ Type InUse MemUse HighUse Requests Size(s)
+ name 12345 54321K - 32145
Terry Jones works in dept #660
Leslie Patterson works in dept #341
Ashley Smith works in dept #1440
+done
diff --git a/contrib/libxo/tests/core/saved/test_03.X.out b/contrib/libxo/tests/core/saved/test_03.X.out
index a626fb6..279e359 100644
--- a/contrib/libxo/tests/core/saved/test_03.X.out
+++ b/contrib/libxo/tests/core/saved/test_03.X.out
@@ -1 +1 @@
-<employees><employee><first-name>Terry</first-name><last-name>Jones</last-name><department>660</department></employee><employee><first-name>Leslie</first-name><last-name>Patterson</last-name><department>341</department></employee><employee><first-name>Ashley</first-name><last-name>Smith</last-name><department>1440</department></employee></employees> \ No newline at end of file
+<employees><extra></extra><memory><type>name</type><in-use>12345</in-use><memory-use>54321</memory-use><high-use>-</high-use><requests>32145</requests></memory><employee><first-name>Terry</first-name><last-name>Jones</last-name><department>660</department></employee><employee><first-name>Leslie</first-name><last-name>Patterson</last-name><department>341</department></employee><employee><first-name>Ashley</first-name><last-name>Smith</last-name><department>1440</department></employee></employees> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_03.XP.out b/contrib/libxo/tests/core/saved/test_03.XP.out
index b6e7641..751bbfc 100644
--- a/contrib/libxo/tests/core/saved/test_03.XP.out
+++ b/contrib/libxo/tests/core/saved/test_03.XP.out
@@ -1,4 +1,12 @@
<employees>
+ <extra></extra>
+ <memory>
+ <type>name</type>
+ <in-use>12345</in-use>
+ <memory-use>54321</memory-use>
+ <high-use>-</high-use>
+ <requests>32145</requests>
+ </memory>
<employee>
<first-name>Terry</first-name>
<last-name>Jones</last-name>
diff --git a/contrib/libxo/tests/core/test_03.c b/contrib/libxo/tests/core/test_03.c
index 0ab9699..af65ddd 100644
--- a/contrib/libxo/tests/core/test_03.c
+++ b/contrib/libxo/tests/core/test_03.c
@@ -25,6 +25,9 @@ int info_count = (sizeof(info) / sizeof(info[0]));
int
main (int argc, char **argv)
{
+ unsigned opt_count = 1;
+ unsigned opt_extra = 0;
+
struct employee {
const char *e_first;
const char *e_last;
@@ -34,24 +37,68 @@ main (int argc, char **argv)
{ "Leslie", "Patterson", 341 },
{ "Ashley", "Smith", 1440 },
{ NULL, NULL }
- }, *ep = employees;
+ }, *ep;
argc = xo_parse_args(argc, argv);
if (argc < 0)
return 1;
+ for (argc = 1; argv[argc]; argc++) {
+ if (strcmp(argv[argc], "count") == 0) {
+ if (argv[argc + 1])
+ opt_count = atoi(argv[++argc]);
+ } else if (strcmp(argv[argc], "extra") == 0) {
+ if (argv[argc + 1])
+ opt_extra = atoi(argv[++argc]);
+ }
+ }
+
xo_set_info(NULL, info, info_count);
xo_open_container("employees");
xo_open_list("employee");
- for ( ; ep->e_first; ep++) {
- xo_open_instance("employee");
- xo_emit("{:first-name} {:last-name} works in dept #{:department/%u}\n",
- ep->e_first, ep->e_last, ep->e_dept);
- xo_close_instance("employee");
+ xo_emit("[{:extra/%*s}]\n", opt_extra, "");
+
+ xo_emit("{T:/%13s} {T:/%5s} {T:/%6s} {T:/%7s} {T:/%8s} {T:Size(s)}\n",
+ "Type", "InUse", "MemUse", "HighUse", "Requests");
+ xo_open_list("memory");
+ xo_open_instance("memory");
+
+#define PRIu64 "llu"
+#define TO_ULL(_x) ((unsigned long long) _x)
+ xo_emit("{k:type/%13s} {:in-use/%5" PRIu64 "} "
+ "{:memory-use/%5" PRIu64 "}{U:K} {:high-use/%7s} "
+ "{:requests/%8" PRIu64 "} ",
+ "name", TO_ULL(12345), TO_ULL(54321), "-", TO_ULL(32145));
+
+ int first = 1, i;
+#if 0
+ xo_open_list("size");
+ for (i = 0; i < 32; i++) {
+ if (!first)
+ xo_emit(",");
+ xo_emit("{l:size/%d}", 1 << (i + 4));
+ first = 0;
+ }
+ xo_close_list("size");
+#endif
+ xo_close_instance("memory");
+ xo_emit("\n");
+ xo_close_list("memory");
+
+ while (opt_count-- != 0) {
+ for (ep = employees; ep->e_first; ep++) {
+ xo_open_instance("employee");
+ xo_emit("{:first-name} {:last-name} works in "
+ "dept #{:department/%u}\n",
+ ep->e_first, ep->e_last, ep->e_dept);
+ xo_close_instance("employee");
+ }
}
+ xo_emit("done\n");
+
xo_close_list("employee");
xo_close_container("employees");
diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
index 25288a7..66b12d3 100644
--- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -26159,6 +26159,8 @@ static SDValue detectAVGPattern(SDValue In, EVT VT, SelectionDAG &DAG,
if (InScalarVT.getSizeInBits() <= ScalarVT.getSizeInBits())
return SDValue();
+ if (!Subtarget->hasSSE2())
+ return SDValue();
if (Subtarget->hasAVX512()) {
if (VT.getSizeInBits() > 512)
return SDValue();
diff --git a/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 17c25df..2935460 100644
--- a/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -3161,10 +3161,11 @@ void InnerLoopVectorizer::truncateToMinimalBitwidths() {
// truncated version of `I` and reextend its result. InstCombine runs
// later and will remove any ext/trunc pairs.
//
+ SmallPtrSet<Value *, 4> Erased;
for (auto &KV : MinBWs) {
VectorParts &Parts = WidenMap.get(KV.first);
for (Value *&I : Parts) {
- if (I->use_empty())
+ if (Erased.count(I) || I->use_empty())
continue;
Type *OriginalTy = I->getType();
Type *ScalarTruncatedTy = IntegerType::get(OriginalTy->getContext(),
@@ -3238,6 +3239,7 @@ void InnerLoopVectorizer::truncateToMinimalBitwidths() {
Value *Res = B.CreateZExtOrTrunc(NewI, OriginalTy);
I->replaceAllUsesWith(Res);
cast<Instruction>(I)->eraseFromParent();
+ Erased.insert(I);
I = Res;
}
}
diff --git a/etc/Makefile b/etc/Makefile
index 94c4473..99d905a 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -86,6 +86,10 @@ BIN1+= apmd.conf
BIN1+= auto_master
.endif
+.if ${MK_BLACKLIST_SUPPORT} != "no"
+BIN1+= blacklistd.conf
+.endif
+
.if ${MK_FREEBSD_UPDATE} != "no"
BIN1+= freebsd-update.conf
.endif
diff --git a/etc/blacklistd.conf b/etc/blacklistd.conf
new file mode 100644
index 0000000..2b1cf87
--- /dev/null
+++ b/etc/blacklistd.conf
@@ -0,0 +1,17 @@
+# $FreeBSD$
+#
+# Blacklist rule
+# adr/mask:port type proto owner name nfail disable
+[local]
+ssh stream * * * 3 24h
+ftp stream * * * 3 24h
+smtp stream * * * 3 24h
+submission stream * * * 3 24h
+#6161 stream tcp6 christos * 2 10m
+* * * * * 3 60
+
+# adr/mask:port type proto owner name nfail disable
+[remote]
+#129.168.0.0/16 * * * = * *
+#6161 = = = =/24 = =
+#* stream tcp * = = =
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 74125d1..8a5c07e 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -60,6 +60,10 @@ rc_conf_files="/etc/rc.conf /etc/rc.conf.local"
# ZFS support
zfs_enable="NO" # Set to YES to automatically mount ZFS file systems
+# ZFSD support
+zfsd_enable="NO" # Set to YES to automatically start the ZFS fault
+ # management daemon.
+
gptboot_enable="YES" # GPT boot success/failure reporting.
# Experimental - test before enabling
@@ -266,6 +270,8 @@ hastd_program="/sbin/hastd" # path to hastd, if you want a different one.
hastd_flags="" # Optional flags to hastd.
ctld_enable="NO" # CAM Target Layer / iSCSI target daemon.
local_unbound_enable="NO" # local caching resolver
+blacklistd_enable="YES" # Run blacklistd daemon (YES/NO).
+blacklistd_flags="" # Optional flags for blacklistd(8).
#
# kerberos. Do not run the admin daemons on slave servers
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index a9baa7e..42980d0 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -155,6 +155,8 @@
wi
..
..
+ devdctl
+ ..
edit
readline
..
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index f18091d..ae17129 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -215,6 +215,8 @@
..
..
..
+ zfsd
+ ..
..
..
etc
@@ -308,6 +310,8 @@
..
libcrypt
..
+ libdevdctl
+ ..
libmp
..
libnv
diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist
index 46b8dcd..e6dfa50 100644
--- a/etc/mtree/BSD.var.dist
+++ b/etc/mtree/BSD.var.dist
@@ -54,6 +54,10 @@
..
portsnap
..
+ zfsd
+ cases
+ ..
+ ..
..
empty mode=0555 flags=schg
..
diff --git a/etc/periodic/daily/480.leapfile-ntpd b/etc/periodic/daily/480.leapfile-ntpd
index 8429824..5a3ccce 100755
--- a/etc/periodic/daily/480.leapfile-ntpd
+++ b/etc/periodic/daily/480.leapfile-ntpd
@@ -16,10 +16,10 @@ case "$daily_ntpd_leapfile_enable" in
case "$daily_ntpd_avoid_congestion" in
[Yy][Ee][Ss])
# Avoid dogpiling
- (sleep $(jot -r 1 0 86400); service ntpd fetch) &
+ (sleep $(jot -r 1 0 86400); service ntpd onefetch) &
;;
*)
- service ntpd fetch
+ service ntpd onefetch
;;
esac
;;
diff --git a/etc/periodic/security/520.pfdenied b/etc/periodic/security/520.pfdenied
index f2f9e8a..850c10d 100755
--- a/etc/periodic/security/520.pfdenied
+++ b/etc/periodic/security/520.pfdenied
@@ -44,8 +44,14 @@ rc=0
if check_yesno_period security_status_pfdenied_enable
then
TMP=`mktemp -t security`
- if pfctl -sr -v -z 2>/dev/null | nawk '{if (/^block/) {buf=$0; getline; gsub(" +"," ",$0); if ($5 > 0) print buf$0;} }' > ${TMP}; then
- check_diff new_only pf ${TMP} "${host} pf denied packets:"
+ touch ${TMP}
+ for _a in "" blacklistd
+ do
+ pfctl -a ${_a} -sr -v -z 2>/dev/null | \
+ nawk '{if (/^block/) {buf=$0; getline; gsub(" +"," ",$0); if ($5 > 0) print buf$0;} }' >> ${TMP}
+ done
+ if [ -s ${TMP} ]; then
+ check_diff new_only pf ${TMP} "${host} pf denied packets:"
fi
rc=$?
rm -f ${TMP}
diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile
index 89d2baf..2d195f1 100644
--- a/etc/rc.d/Makefile
+++ b/etc/rc.d/Makefile
@@ -17,6 +17,7 @@ FILES= DAEMON \
auditd \
auditdistd \
bgfsck \
+ ${_blacklistd} \
${_bluetooth} \
bridge \
${_bthidd} \
@@ -123,7 +124,7 @@ FILES= DAEMON \
ypserv \
ypset \
ypupdated \
- ypxfrd \
+ ypxfrd
.if ${MK_ACCT} != "no"
FILESGROUPS+= ACCT
@@ -168,6 +169,10 @@ FILES+= automountd
FILES+= autounmountd
.endif
+.if ${MK_BLACKLIST_SUPPORT} != "no"
+_blacklistd+= blacklistd
+.endif
+
.if ${MK_BLUETOOTH} != "no"
_bluetooth= bluetooth
_bthidd= bthidd
@@ -308,6 +313,7 @@ FILES+= wpa_supplicant
.if ${MK_ZFS} != "no"
FILESGROUPS+= ZFS
ZFS+= zfs
+ZFS+= zfsd
ZFS+= zvol
ZFSPACKAGE= zfs
.endif
diff --git a/etc/rc.d/blacklistd b/etc/rc.d/blacklistd
new file mode 100644
index 0000000..8e79250
--- /dev/null
+++ b/etc/rc.d/blacklistd
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 The FreeBSD Foundation
+# All rights reserved.
+#
+# This software was developed by Kurt Lidl under sponsorship from the
+# FreeBSD Foundation.
+#
+# 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$
+#
+
+# PROVIDE: blacklistd
+# REQUIRE: netif pf
+
+. /etc/rc.subr
+
+name="blacklistd"
+desc="System blacklist daemon"
+rcvar="blacklistd_enable"
+command="/usr/sbin/${name}"
+required_files="/etc/blacklistd.conf"
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/etc/rc.d/dhclient b/etc/rc.d/dhclient
index 332be4c..f2d17c5 100755
--- a/etc/rc.d/dhclient
+++ b/etc/rc.d/dhclient
@@ -30,7 +30,7 @@ dhclient_pre_check()
else
debug "$msg"
fi
- exit 1
+ exit 1
fi
}
diff --git a/etc/rc.d/ldconfig b/etc/rc.d/ldconfig
index 9ecb172..a657a01 100755
--- a/etc/rc.d/ldconfig
+++ b/etc/rc.d/ldconfig
@@ -4,7 +4,7 @@
#
# PROVIDE: ldconfig
-# REQUIRE: mountcritremote FILESYSTEMS
+# REQUIRE: FILESYSTEMS
# BEFORE: DAEMON
. /etc/rc.subr
diff --git a/etc/rc.d/mountcritremote b/etc/rc.d/mountcritremote
index 2af48b6..dede14f 100755
--- a/etc/rc.d/mountcritremote
+++ b/etc/rc.d/mountcritremote
@@ -35,12 +35,15 @@ mountcritremote_precmd()
mountcritremote_start()
{
+ local mounted_remote_filesystem=false
+
# Mount nfs filesystems.
#
case "`/sbin/mount -d -a -t nfs`" in
'')
;;
*)
+ mounted_remote_filesystem=true
echo -n 'Mounting NFS filesystems:'
mount -a -t nfs
echo '.'
@@ -64,6 +67,7 @@ mountcritremote_start()
case "`mount -d -a -t ${fstype}`" in
*mount_${fstype}*)
+ mounted_remote_filesystem=true
echo -n "Mounting ${fsdecr} filesystems:"
mount -a -t ${fstype}
echo '.'
@@ -71,9 +75,15 @@ mountcritremote_start()
esac
done
- # Cleanup /var again just in case it's a network mount.
- /etc/rc.d/cleanvar quietreload
- rm -f /var/run/clean_var /var/spool/lock/clean_var
+ if $mounted_remote_filesystem; then
+ # Cleanup /var again just in case it's a network mount.
+ /etc/rc.d/cleanvar quietreload
+ rm -f /var/run/clean_var /var/spool/lock/clean_var
+
+ # Regenerate the ldconfig hints in case there are additional
+ # library paths on remote file systems
+ /etc/rc.d/ldconfig quietstart
+ fi
}
load_rc_config $name
diff --git a/etc/rc.d/netif b/etc/rc.d/netif
index e2b1825..a1543e6 100755
--- a/etc/rc.d/netif
+++ b/etc/rc.d/netif
@@ -27,7 +27,7 @@
# PROVIDE: netif
# REQUIRE: FILESYSTEMS iovctl serial sppp sysctl
-# REQUIRE: ipfilter ipfs
+# REQUIRE: hostid ipfilter ipfs
# KEYWORD: nojailvnet
. /etc/rc.subr
diff --git a/etc/rc.d/random b/etc/rc.d/random
index 179ccc7..1e4e5b2 100755
--- a/etc/rc.d/random
+++ b/etc/rc.d/random
@@ -44,12 +44,12 @@ random_start()
{
if [ ${harvest_mask} -gt 0 ]; then
- echo -n 'Setting up harvesting:'
+ echo -n 'Setting up harvesting: '
${SYSCTL} kern.random.harvest.mask=${harvest_mask} > /dev/null
${SYSCTL_N} kern.random.harvest.mask_symbolic
fi
- echo -n 'Feeding entropy:'
+ echo -n 'Feeding entropy: '
if [ ! -w /dev/random ] ; then
warn "/dev/random is not writeable"
diff --git a/etc/rc.d/routing b/etc/rc.d/routing
index 3d3f5a5..2a57fa3 100755
--- a/etc/rc.d/routing
+++ b/etc/rc.d/routing
@@ -90,18 +90,23 @@ routing_stop()
setroutes()
{
+ local _ret
+ _ret=0
case $1 in
static)
static_$2 add $3
+ _ret=$?
;;
options)
options_$2
;;
doall)
static_$2 add $3
+ _ret=$?
options_$2
;;
esac
+ return $_ret
}
routing_stop_inet()
diff --git a/etc/rc.d/zfsd b/etc/rc.d/zfsd
new file mode 100644
index 0000000..edf259b
--- /dev/null
+++ b/etc/rc.d/zfsd
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# PROVIDE: zfsd
+# REQUIRE: devd zfs
+# KEYWORD: nojail shutdown
+
+. /etc/rc.subr
+
+name="zfsd"
+rcvar="zfsd_enable"
+command="/usr/sbin/${name}"
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/include/dirent.h b/include/dirent.h
index b894bb8..1ab949c 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -38,15 +38,23 @@
* the getdirentries(2) system call.
*/
#include <sys/cdefs.h>
+#include <sys/_types.h>
#include <sys/dirent.h>
#if __XSI_VISIBLE
+
+#ifndef _INO_T_DECLARED
+typedef __ino_t ino_t;
+#define _INO_T_DECLARED
+#endif
+
/*
* XXX this is probably illegal in the __XSI_VISIBLE case, but brings us closer
* to the specification.
*/
#define d_ino d_fileno /* backward and XSI compatibility */
-#endif
+
+#endif /* __XSI_VISIBLE */
#if __BSD_VISIBLE
diff --git a/include/libgen.h b/include/libgen.h
index 0d4472f..28c0067 100644
--- a/include/libgen.h
+++ b/include/libgen.h
@@ -29,22 +29,14 @@
*/
#ifndef _LIBGEN_H_
-#define _LIBGEN_H_
+#define _LIBGEN_H_
#include <sys/cdefs.h>
__BEGIN_DECLS
-
char *basename(const char *);
char *basename_r(const char *, char *);
char *dirname(const char *);
-#if 0
-char *regcmp(const char *, ...);
-char *regex(const char *, const char *, ...);
-
-extern char *__loc1;
-#endif
-
__END_DECLS
-#endif /* _LIBGEN_H_ */
+#endif /* !_LIBGEN_H_ */
diff --git a/include/monetary.h b/include/monetary.h
index 93f82c1..bca607a 100644
--- a/include/monetary.h
+++ b/include/monetary.h
@@ -43,7 +43,7 @@ typedef __ssize_t ssize_t;
#endif
__BEGIN_DECLS
-#ifdef _XLOCALE_H_
+#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
#include <xlocale/_monetary.h>
#endif
ssize_t strfmon(char * __restrict, size_t, const char * __restrict, ...);
diff --git a/include/ndbm.h b/include/ndbm.h
index 0acb6a6..db83803 100644
--- a/include/ndbm.h
+++ b/include/ndbm.h
@@ -52,7 +52,7 @@
#define DBM_SUFFIX ".db"
typedef struct {
- char *dptr;
+ void *dptr;
int dsize;
} datum;
@@ -70,7 +70,7 @@ datum dbm_firstkey(DBM *);
long dbm_forder(DBM *, datum);
#endif
datum dbm_nextkey(DBM *);
-DBM *dbm_open(const char *, int, int);
+DBM *dbm_open(const char *, int, mode_t);
int dbm_store(DBM *, datum, datum, int);
#if __BSD_VISIBLE
int dbm_dirfno(DBM *);
diff --git a/include/netdb.h b/include/netdb.h
index a73d2af..3fa5ff3 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -60,6 +60,16 @@
#include <sys/cdefs.h>
#include <sys/_types.h>
+#ifndef _IN_ADDR_T_DECLARED
+typedef __uint32_t in_addr_t;
+#define _IN_ADDR_T_DECLARED
+#endif
+
+#ifndef _IN_PORT_T_DECLARED
+typedef __uint16_t in_port_t;
+#define _IN_PORT_T_DECLARED
+#endif
+
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
@@ -131,6 +141,8 @@ struct addrinfo {
struct addrinfo *ai_next; /* next structure in linked list */
};
+#define IPPORT_RESERVED 1024
+
/*
* Error return codes from gethostbyname() and gethostbyaddr()
* (left in h_errno).
diff --git a/include/signal.h b/include/signal.h
index 217fadd..9f33fb6 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -113,7 +113,7 @@ int siginterrupt(int, int);
#endif
#if __POSIX_VISIBLE >= 200809
-void psignal(unsigned int, const char *);
+void psignal(int, const char *);
#endif
#if __BSD_VISIBLE
diff --git a/include/wchar.h b/include/wchar.h
index 84a4a97..26d257a 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -76,6 +76,13 @@ typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
+#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE
+#ifndef _VA_LIST_DECLARED
+typedef __va_list va_list;
+#define _VA_LIST_DECLARED
+#endif
+#endif
+
#ifndef __cplusplus
#ifndef _WCHAR_T_DECLARED
typedef ___wchar_t wchar_t;
diff --git a/lib/Makefile b/lib/Makefile
index 0c8120c..d475c6c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -28,6 +28,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libatm} \
libauditd \
libbegemot \
+ ${_libblacklist} \
libblocksruntime \
${_libbluetooth} \
${_libbsnmp} \
@@ -41,6 +42,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
libcompat \
libcrypt \
libdevctl \
+ libdevdctl \
libdevinfo \
libdevstat \
libdpv \
@@ -148,7 +150,6 @@ SUBDIR_DEPEND_libpjdlog= libutil
SUBDIR_DEPEND_libprocstat= libkvm libutil
SUBDIR_DEPEND_libradius= libmd
SUBDIR_DEPEND_libsmb= libkiconv
-SUBDIR_DEPEND_libstdc++:= msun
SUBDIR_DEPEND_libtacplus= libmd
SUBDIR_DEPEND_libulog= libmd
SUBDIR_DEPEND_libunbound= ${_libldns}
@@ -160,6 +161,10 @@ SUBDIR_DEPEND_liblzma= ${_libthr}
_libngatm= libngatm
.endif
+.if ${MK_BLACKLIST_SUPPORT} != "no"
+_libblacklist= libblacklist
+.endif
+
.if ${MK_BLUETOOTH} != "no"
_libbluetooth= libbluetooth
_libsdp= libsdp
diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc
index c143edd..72c5bed 100644
--- a/lib/clang/include/clang/Basic/Version.inc
+++ b/lib/clang/include/clang/Basic/Version.inc
@@ -9,4 +9,4 @@
#define SVN_REVISION "262564"
-#define FREEBSD_CC_VERSION 1100002U
+#define FREEBSD_CC_VERSION 1100004U
diff --git a/lib/libblacklist/Makefile b/lib/libblacklist/Makefile
new file mode 100644
index 0000000..8187479
--- /dev/null
+++ b/lib/libblacklist/Makefile
@@ -0,0 +1,30 @@
+# $FreeBSD$
+
+BLACKLIST_DIR=${SRCTOP}/contrib/blacklist
+
+.PATH: ${BLACKLIST_DIR}/lib ${BLACKLIST_DIR}/include
+
+LIB= blacklist
+SHLIB_MAJOR= 0
+
+LIBADD+= pthread
+
+CFLAGS.clang+=-Wno-thread-safety-analysis
+
+CFLAGS+=-I${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \
+ -D_REENTRANT -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \
+ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_GETPROGNAME \
+ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN
+
+SRCS= bl.c blacklist.c
+INCS= blacklist.h
+MAN= libblacklist.3
+
+MLINKS= libblacklist.3 blacklist_open.3 \
+ libblacklist.3 blacklist_close.3 \
+ libblacklist.3 blacklist.3 \
+ libblacklist.3 blacklist_r.3 \
+ libblacklist.3 blacklist_sa.3 \
+ libblacklist.3 blacklist_sa_r.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libc++/Makefile b/lib/libc++/Makefile
index 984e70b..6e70cf1 100644
--- a/lib/libc++/Makefile
+++ b/lib/libc++/Makefile
@@ -63,7 +63,7 @@ cxxrt_${_S}: ${_LIBCXXRTDIR}/${_S} .NOMETA
.endfor
WARNS= 0
-CFLAGS+= -I${HDRDIR} -I${_LIBCXXRTDIR} -nostdinc++ -nostdlib -DLIBCXXRT
+CFLAGS+= -isystem ${HDRDIR} -isystem ${_LIBCXXRTDIR} -nostdinc++ -nostdlib -DLIBCXXRT
.if empty(CXXFLAGS:M-std=*)
CXXFLAGS+= -std=c++11
.endif
@@ -187,7 +187,7 @@ RT_HEADERS= cxxabi.h\
.for hdr in ${STD_HEADERS}
STD+= ${HDRDIR}/${hdr}
-INCSLINKS+= ${CXXINCLUDEDIR}/${hdr} ${CXXINCLUDEDIR}/tr1/${hdr}
+INCSLINKS+= ../${hdr} ${CXXINCLUDEDIR}/tr1/${hdr}
.endfor
.for hdr in ${RT_HEADERS}
STD+= ${_LIBCXXRTDIR}/${hdr}
diff --git a/lib/libc/db/hash/ndbm.c b/lib/libc/db/hash/ndbm.c
index 37adaf6..1a02d00 100644
--- a/lib/libc/db/hash/ndbm.c
+++ b/lib/libc/db/hash/ndbm.c
@@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
* NULL on failure
*/
extern DBM *
-dbm_open(const char *file, int flags, int mode)
+dbm_open(const char *file, int flags, mode_t mode)
{
HASHINFO info;
char path[MAXPATHLEN];
diff --git a/lib/libc/db/man/dbm.3 b/lib/libc/db/man/dbm.3
index eedf804..4fe5d82 100644
--- a/lib/libc/db/man/dbm.3
+++ b/lib/libc/db/man/dbm.3
@@ -15,7 +15,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 19, 2015
+.Dd May 30, 2016
.Dt DBM 3
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.In fcntl.h
.In ndbm.h
.Ft DBM *
-.Fn dbm_open "const char *base" "int flags" "int mode"
+.Fn dbm_open "const char *base" "int flags" "mode_t mode"
.Ft void
.Fn dbm_close "DBM *db"
.Ft int
@@ -66,7 +66,7 @@ is declared in
.In ndbm.h :
.Bd -literal
typedef struct {
- char *dptr;
+ void *dptr;
int dsize;
} datum;
.Ed
diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3
index 231acfa..ed7023b 100644
--- a/lib/libc/gen/psignal.3
+++ b/lib/libc/gen/psignal.3
@@ -28,7 +28,7 @@
.\" @(#)psignal.3 8.2 (Berkeley) 2/27/95
.\" $FreeBSD$
.\"
-.Dd February 4, 2011
+.Dd May 30, 2016
.Dt PSIGNAL 3
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Sh SYNOPSIS
.In signal.h
.Ft void
-.Fn psignal "unsigned sig" "const char *s"
+.Fn psignal "int sig" "const char *s"
.Vt extern const char * const sys_siglist[] ;
.Vt extern const char * const sys_signame[] ;
.In string.h
diff --git a/lib/libc/gen/psignal.c b/lib/libc/gen/psignal.c
index 5c5aada..d1c70c6 100644
--- a/lib/libc/gen/psignal.c
+++ b/lib/libc/gen/psignal.c
@@ -44,11 +44,11 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
void
-psignal(unsigned int sig, const char *s)
+psignal(int sig, const char *s)
{
const char *c;
- if (sig < NSIG)
+ if (sig >= 0 && sig < NSIG)
c = sys_siglist[sig];
else
c = "Unknown signal";
diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c
index ed404a6..299dd5f 100644
--- a/lib/libc/iconv/citrus_esdb.c
+++ b/lib/libc/iconv/citrus_esdb.c
@@ -291,18 +291,12 @@ _citrus_esdb_get_list(char ***rlist, size_t *rnum, bool sorted)
/* get alias entries */
while ((ret = _lookup_seq_next(cla, &key, &data)) == 0) {
- if (sorted)
- snprintf(buf, sizeof(buf), "%.*s/%.*s",
- (int)_region_size(&data),
- (const char *)_region_head(&data),
- (int)_region_size(&key),
- (const char *)_region_head(&key));
- else
- snprintf(buf, sizeof(buf), "%.*s/%.*s",
- (int)_region_size(&data),
- (const char *)_region_head(&data),
- (int)_region_size(&key),
- (const char *)_region_head(&key));
+ /* XXX: sorted? */
+ snprintf(buf, sizeof(buf), "%.*s/%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data),
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
_bcs_convert_to_upper(buf);
list[num] = strdup(buf);
if (list[num] == NULL) {
diff --git a/lib/libc/locale/ascii.c b/lib/libc/locale/ascii.c
index 784814d..a70d71a 100644
--- a/lib/libc/locale/ascii.c
+++ b/lib/libc/locale/ascii.c
@@ -143,6 +143,7 @@ _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
nchr = 0;
while (len-- > 0 && nms-- > 0) {
if (*s & 0x80) {
+ *src = s;
errno = EILSEQ;
return ((size_t)-1);
}
@@ -177,6 +178,7 @@ _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
nchr = 0;
while (len-- > 0 && nwc-- > 0) {
if (*s < 0 || *s > 127) {
+ *src = s;
errno = EILSEQ;
return ((size_t)-1);
}
diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c
index c4695fd..4e5a61d 100644
--- a/lib/libc/locale/none.c
+++ b/lib/libc/locale/none.c
@@ -174,6 +174,7 @@ _none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
nchr = 0;
while (len-- > 0 && nwc-- > 0) {
if (*s < 0 || *s > UCHAR_MAX) {
+ *src = s;
errno = EILSEQ;
return ((size_t)-1);
}
diff --git a/lib/libc/stdlib/div.c b/lib/libc/stdlib/div.c
index 7dfe553..0bafbe6 100644
--- a/lib/libc/stdlib/div.c
+++ b/lib/libc/stdlib/div.c
@@ -46,6 +46,7 @@ div(num, denom)
r.quot = num / denom;
r.rem = num % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
/*
* The ANSI standard says that |r.quot| <= |n/d|, where
* n/d is to be computed in infinite precision. In other
@@ -73,5 +74,6 @@ div(num, denom)
r.quot++;
r.rem -= denom;
}
+#endif
return (r);
}
diff --git a/lib/libc/stdlib/imaxdiv.c b/lib/libc/stdlib/imaxdiv.c
index 7dae467..adcab0b 100644
--- a/lib/libc/stdlib/imaxdiv.c
+++ b/lib/libc/stdlib/imaxdiv.c
@@ -37,9 +37,11 @@ imaxdiv(intmax_t numer, intmax_t denom)
retval.quot = numer / denom;
retval.rem = numer % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
if (numer >= 0 && retval.rem < 0) {
retval.quot++;
retval.rem -= denom;
}
+#endif
return (retval);
}
diff --git a/lib/libc/stdlib/ldiv.c b/lib/libc/stdlib/ldiv.c
index 0ec98e6..745c566 100644
--- a/lib/libc/stdlib/ldiv.c
+++ b/lib/libc/stdlib/ldiv.c
@@ -48,9 +48,11 @@ ldiv(num, denom)
r.quot = num / denom;
r.rem = num % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
if (num >= 0 && r.rem < 0) {
r.quot++;
r.rem -= denom;
}
+#endif
return (r);
}
diff --git a/lib/libc/stdlib/lldiv.c b/lib/libc/stdlib/lldiv.c
index b34b65e..197b48f 100644
--- a/lib/libc/stdlib/lldiv.c
+++ b/lib/libc/stdlib/lldiv.c
@@ -37,9 +37,11 @@ lldiv(long long numer, long long denom)
retval.quot = numer / denom;
retval.rem = numer % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
if (numer >= 0 && retval.rem < 0) {
retval.quot++;
retval.rem -= denom;
}
+#endif
return (retval);
}
diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c
index eb3c10a..2e0456a 100644
--- a/lib/libc/stdlib/rand.c
+++ b/lib/libc/stdlib/rand.c
@@ -48,14 +48,6 @@ __FBSDID("$FreeBSD$");
static int
do_rand(unsigned long *ctx)
{
-#ifdef USE_WEAK_SEEDING
-/*
- * Historic implementation compatibility.
- * The random sequences do not vary much with the seed,
- * even with overflowing.
- */
- return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
-#else /* !USE_WEAK_SEEDING */
/*
* Compute x = (7^5 * x) mod (2^31 - 1)
* without overflowing 31 bits:
@@ -66,48 +58,34 @@ do_rand(unsigned long *ctx)
*/
long hi, lo, x;
- /* Must be in [1, 0x7ffffffe] range at this point. */
- hi = *ctx / 127773;
- lo = *ctx % 127773;
+ /* Transform to [1, 0x7ffffffe] range. */
+ x = (*ctx % 0x7ffffffe) + 1;
+ hi = x / 127773;
+ lo = x % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
- *ctx = x;
/* Transform to [0, 0x7ffffffd] range. */
- return (x - 1);
-#endif /* !USE_WEAK_SEEDING */
+ x--;
+ *ctx = x;
+ return (x);
}
int
-rand_r(unsigned int *ctx)
+rand_r(unsigned *ctx)
{
u_long val;
int r;
-#ifdef USE_WEAK_SEEDING
val = *ctx;
-#else
- /* Transform to [1, 0x7ffffffe] range. */
- val = (*ctx % 0x7ffffffe) + 1;
-#endif
r = do_rand(&val);
-
-#ifdef USE_WEAK_SEEDING
- *ctx = (unsigned int)val;
-#else
- *ctx = (unsigned int)(val - 1);
-#endif
+ *ctx = (unsigned)val;
return (r);
}
-static u_long next =
-#ifdef USE_WEAK_SEEDING
- 1;
-#else
- 2;
-#endif
+static u_long next = 1;
int
rand(void)
@@ -116,13 +94,9 @@ rand(void)
}
void
-srand(u_int seed)
+srand(unsigned seed)
{
next = seed;
-#ifndef USE_WEAK_SEEDING
- /* Transform to [1, 0x7ffffffe] range. */
- next = (next % 0x7ffffffe) + 1;
-#endif
}
@@ -144,10 +118,6 @@ sranddev(void)
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
sysctl(mib, 2, (void *)&next, &len, NULL, 0);
-#ifndef USE_WEAK_SEEDING
- /* Transform to [1, 0x7ffffffe] range. */
- next = (next % 0x7ffffffe) + 1;
-#endif
}
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
index f7b745e..fe8fc86 100644
--- a/lib/libc/stdlib/random.c
+++ b/lib/libc/stdlib/random.c
@@ -137,11 +137,7 @@ __FBSDID("$FreeBSD$");
*/
#define MAX_TYPES 5 /* max number of types above */
-#ifdef USE_WEAK_SEEDING
-#define NSHUFF 0
-#else /* !USE_WEAK_SEEDING */
#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
-#endif /* !USE_WEAK_SEEDING */
static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
@@ -162,23 +158,12 @@ static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
static uint32_t randtbl[DEG_3 + 1] = {
TYPE_3,
-#ifdef USE_WEAK_SEEDING
-/* Historic implementation compatibility */
-/* The random sequences do not vary much with the seed */
- 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
- 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
- 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
- 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
- 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
- 0x27fb47b9,
-#else /* !USE_WEAK_SEEDING */
- 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
- 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
- 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
- 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
- 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
- 0xf3bec5da
-#endif /* !USE_WEAK_SEEDING */
+ 0x2cf41758, 0x27bb3711, 0x4916d4d1, 0x7b02f59f, 0x9b8e28eb, 0xc0e80269,
+ 0x696f5c16, 0x878f1ff5, 0x52d9c07f, 0x916a06cd, 0xb50b3a20, 0x2776970a,
+ 0xee4eb2a6, 0xe94640ec, 0xb1d65612, 0x9d1ed968, 0x1043f6b7, 0xa3432a76,
+ 0x17eacbb9, 0x3c09e2eb, 0x4f8c2b3, 0x708a1f57, 0xee341814, 0x95d0e4d2,
+ 0xb06f216c, 0x8bd2e72e, 0x8f7c38d7, 0xcfc6a8fc, 0x2a59495, 0xa20d2a69,
+ 0xe29d12d1
};
/*
@@ -215,16 +200,8 @@ static int rand_sep = SEP_3;
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
static inline uint32_t
-good_rand(int32_t x)
+good_rand(uint32_t ctx)
{
-#ifdef USE_WEAK_SEEDING
-/*
- * Historic implementation compatibility.
- * The random sequences do not vary much with the seed,
- * even with overflowing.
- */
- return (1103515245 * x + 12345);
-#else /* !USE_WEAK_SEEDING */
/*
* Compute x = (7^5 * x) mod (2^31 - 1)
* wihout overflowing 31 bits:
@@ -233,18 +210,17 @@ good_rand(int32_t x)
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
*/
- int32_t hi, lo;
+ int32_t hi, lo, x;
- /* Can't be initialized with 0, so use another value. */
- if (x == 0)
- x = 123459876;
+ /* Transform to [1, 0x7ffffffe] range. */
+ x = (ctx % 0x7ffffffe) + 1;
hi = x / 127773;
lo = x % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
- return (x);
-#endif /* !USE_WEAK_SEEDING */
+ /* Transform to [0, 0x7ffffffd] range. */
+ return (x - 1);
}
/*
@@ -404,16 +380,8 @@ setstate(char *arg_state)
uint32_t rear = new_state[0] / MAX_TYPES;
char *ostate = (char *)(&state[-1]);
- switch(type) {
- case TYPE_0:
- case TYPE_1:
- case TYPE_2:
- case TYPE_3:
- case TYPE_4:
- break;
- default:
+ if (type != TYPE_0 && rear >= degrees[type])
return (NULL);
- }
if (rand_type == TYPE_0)
state[-1] = rand_type;
else
@@ -455,14 +423,14 @@ random(void)
if (rand_type == TYPE_0) {
i = state[0];
- state[0] = i = (good_rand(i)) & 0x7fffffff;
+ state[0] = i = good_rand(i);
} else {
/*
* Use local variables rather than static variables for speed.
*/
f = fptr; r = rptr;
*f += *r;
- i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ i = *f >> 1; /* chucking least random bit */
if (++f >= end_ptr) {
f = state;
++r;
diff --git a/lib/libc/sys/_umtx_op.2 b/lib/libc/sys/_umtx_op.2
index e2ce109..bd4ad3b 100644
--- a/lib/libc/sys/_umtx_op.2
+++ b/lib/libc/sys/_umtx_op.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 17, 2016
+.Dd May 29, 2016
.Dt _UMTX_OP 2
.Os
.Sh NAME
@@ -257,7 +257,7 @@ are defined, in addition to the common flags:
.It Dv URWLOCK_PREFER_READER
If specified, immediately grant read lock requests when
.Dv urwlock
-is already read-locked, even in presence of the unsatisfied write
+is already read-locked, even in presence of unsatisfied write
lock requests.
By default, if there is a write lock waiter, further read requests are
not granted, to prevent unfair write lock waiter starvation.
@@ -387,7 +387,7 @@ variant which returns an error rather than sleeping if the lock cannot
be obtained.
Also,
.Fn _umtx_op
-provides requests which explicitely put the thread to sleep.
+provides requests which explicitly put the thread to sleep.
.Pp
Wakes need to know which threads to make runnable, so sleeping threads
are grouped into containers called
@@ -399,12 +399,12 @@ Note that the
.Em physical
address is used, which means that same variable mapped multiple
times will give one key value.
-This mechanism enables the construction of the
+This mechanism enables the construction of
.Em process-shared
locks.
.Pp
A related attribute of the key is shareability.
-Some requests always interpet keys as private for the current process,
+Some requests always interpret keys as private for the current process,
creating sleep queues with the scope of the current process even if
the memory is shared.
Others either select the shareability automatically from the
@@ -435,7 +435,8 @@ the queue are selected.
The
.Em robust umutexes
are provided as a substrate for a userspace library to implement
-POSIX robust mutexes.
+.Tn POSIX
+robust mutexes.
A robust umutex must have the
.Dv UMUTEX_ROBUST
flag set.
@@ -524,13 +525,13 @@ argument is compared with the
If they are equal, the requesting thread is put to interruptible sleep
until woken up or the optionally specified timeout expires.
.Pp
-The comparision and sleep are atomic.
+The comparison and sleep are atomic.
In other words, if another thread writes a new value to
.Dv *obj
and then issues
.Dv UMTX_OP_WAKE ,
the request is guaranteed to not miss the wakeup,
-which might otherwise happen between comparision and blocking.
+which might otherwise happen between comparison and blocking.
.Pp
The physical address of memory where the
.Fa *obj
@@ -599,7 +600,7 @@ contention indicator, and provides the acquire barrier for
lock entrance semantic.
.Pp
If the lock cannot be obtained immediately because another thread owns
-the lock, the current thread is put into sleep, with
+the lock, the current thread is put to sleep, with
.Dv UMUTEX_CONTESTED
bit set before.
Upon wake up, the lock conditions are re-tested.
@@ -668,7 +669,9 @@ New ceiling value.
.It Fa uaddr
Address of a variable of type
.Vt uint32_t .
-If not NULL, after the successful update the previous ceiling value is
+If not
+.Dv NULL
+and the update was successful, the previous ceiling value is
written to the location pointed to by
.Fa uaddr .
.El
@@ -685,7 +688,9 @@ member of the
after which the umutex is unlocked.
.Pp
The locking does not adhere to the priority protect protocol,
-to confirm with the POSIX requirements for the
+to conform to the
+.Tn POSIX
+requirements for the
.Xr pthread_mutex_setprioceiling 3
interface.
.It Dv UMTX_OP_CV_WAIT
@@ -769,7 +774,8 @@ If the
flag is supplied, the timeout specifies absolute time value, otherwise
it denotes a relative time interval.
.Pp
-The request is not restartable. An unblocked signal delivered during
+The request is not restartable.
+An unblocked signal delivered during
the wait always results in sleep interruption and
.Er EINTR
error.
@@ -845,7 +851,7 @@ If the
.Dv URWLOCK_WRITE_OWNER
bit is set in the word
.Dv rw_state ,
-the lock was granted to a writer which has not yet relinguished
+the lock was granted to a writer which has not yet relinquished
its ownership.
In this case the current thread is put to sleep until it makes sense to
retry.
@@ -959,7 +965,7 @@ Same as
.Dv UMTX_OP_WAKE ,
but unconditionally select the process-private sleep queue.
.It Dv UMTX_OP_MUTEX_WAIT
-Wait for the mutex availability.
+Wait for mutex availability.
The arguments to the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -986,12 +992,12 @@ priority inherited protocol mutexes.
Optionally, a timeout for the request may be specified.
.Pp
.Pp
-The request with a timeout specified is not restartable.
+A request with a timeout specified is not restartable.
An unblocked signal delivered during the wait always results in sleep
interruption and
.Er EINTR
error.
-The request without a timeout automatically restarts if the signal disposition
+A request without a timeout automatically restarts if the signal disposition
requested restart via the
.Dv SA_RESTART
flag in
@@ -999,7 +1005,7 @@ flag in
member
.Dv sa_flags .
.It Dv UMTX_OP_NWAKE_PRIVATE
-Wake up a batch of sleeping thread.
+Wake up a batch of sleeping threads.
The arguments to the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1016,7 +1022,7 @@ wakes up all threads waiting on the
sleep queue with the key
being the byte addressed by the array element.
.It Dv UMTX_OP_MUTEX_WAKE
-Check if the normal umutex is unlocked and wake up a waiter.
+Check if a normal umutex is unlocked and wake up a waiter.
The arguments for the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1035,8 +1041,22 @@ with the byte addressed by the
if any.
Only normal mutexes are supported by the request.
The sleep queue is always one for a normal mutex type.
+.Pp
+This request is deprecated in favor of
+.Dv UMTX_OP_MUTEX_WAKE2
+since mutexes using it cannot synchronize their own destruction.
+That is, the
+.Dv m_owner
+word has already been set to
+.Dv UMUTEX_UNOWNED
+when this request is made,
+so that another thread can lock, unlock and destroy the mutex
+(if no other thread uses the mutex afterwards).
+Clearing the
+.Dv UMUTEX_CONTESTED
+bit may then modify freed memory.
.It Dv UMTX_OP_MUTEX_WAKE2
-Check if the umutex is unlocked and wake up a waiter.
+Check if a umutex is unlocked and wake up a waiter.
The arguments for the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1048,7 +1068,7 @@ The umutex flags.
The request does not read the
.Dv m_flags
member of the
-.Vt struct umutex ,
+.Vt struct umutex ;
instead, the
.Fa val
argument supplies flag information, in particular, to determine the
@@ -1064,8 +1084,7 @@ one waiter but the mutex is owned by a thread, the
bit is set in the
.Dv m_owner
word of the
-.Vt struct umutex
-the request operates upon.
+.Vt struct umutex .
.It Dv UMTX_OP_SEM2_WAIT
Wait until semaphore is available.
The arguments to the request are:
@@ -1076,12 +1095,12 @@ Pointer to the semaphore (of type
.El
Put the requesting thread onto a sleep queue if the semaphore counter
is zero.
-If thread is put to sleep, the
+If the thread is put to sleep, the
.Dv USEM_HAS_WAITERS
bit is set in the
.Dv _count
word to indicate waiters.
-Function returns either due to
+The function returns either due to
.Dv _count
indicating the semaphore is available (non-zero count due to post),
or due to a wakeup.
@@ -1096,7 +1115,7 @@ interruption and
.Er EINTR
error.
.It Dv UMTX_OP_SEM2_WAKE
-Wake up waiters on the semaphore lock.
+Wake up waiters on semaphore lock.
The arguments to the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1112,7 +1131,9 @@ bit was set in the
.Dv _count
word, and the last sleeping thread was woken up, the bit is cleared.
.It Dv UMTX_OP_SHM
-Manage the anonymous POSIX shared objects (see
+Manage anonymous
+.Tn POSIX
+shared memory objects (see
.Xr shm_open 2 ) ,
which can be attached to a byte of physical memory, mapped into the
process address space.
@@ -1126,7 +1147,7 @@ argument specifies the sub-request of the
request:
.Bl -tag -width "Dv UMTX_SHM_DESTROY"
.It Dv UMTX_SHM_CREAT
-Creates the POSIX anonymous memory shared object, which can be looked up
+Creates the anonymous shared memory object, which can be looked up
with the specified key
.Fa uaddr.
If the object associated with the
@@ -1143,7 +1164,7 @@ Same as
request, but if there is no shared memory object associated with
the specified key
.Fa uaddr ,
-an error is returned, and new object is not created.
+an error is returned, and no new object is created.
.It Dv UMTX_SHM_DESTROY
De-associate the shared object with the specified key
.Fa uaddr.
@@ -1158,7 +1179,7 @@ This request is an optimization of the
.Dv UMTX_SHM_LOOKUP
request.
It is cheaper when only the liveness of the associated object is asked
-for, since the file descriptor is not installed in the process fd table
+for, since no file descriptor is installed in the process fd table
on success.
.El
.Pp
@@ -1212,7 +1233,7 @@ The kernel inspects the
in addition to walking the shared and private lists.
Also, the mutex pointed to by
.Dv robust_inact_offset
-is handled more loosly at the thread termination time,
+is handled more loosely at the thread termination time,
than other mutexes on the list.
That mutex is allowed to be not owned by the current thread,
in which case list processing is continued.
@@ -1233,7 +1254,7 @@ The
.Dv UMTX_SHM_CREAT
and
.Dv UMTX_SHM_LOOKUP
-return a POSIX shared memory file descriptor on success.
+return a shared memory file descriptor on success.
On error \-1 is returned, and the
.Va errno
variable is set to indicate the error.
@@ -1326,15 +1347,15 @@ and
.Dv UMTX_SHM_ALIVE
sub-requests of the
.Dv UMTX_OP_SHM
-request, there is no shared object associated with the provided key.
+request, there is no shared memory object associated with the provided key.
.It Bq Er ENOMEM
The
.Dv UMTX_SHM_CREAT
sub-request of the
.Dv UMTX_OP_SHM
-request cannot be satisfied, because allocation of the shared object
+request cannot be satisfied, because allocation of the shared memory object
would exceed the
-.Dv RLIMIT_UMXP
+.Dv RLIMIT_UMTXP
resource limit, see
.Xr setrlimit 2 .
.It Bq Er EAGAIN
@@ -1358,7 +1379,7 @@ specified in absolute time may be restartable.
.It Bq Er ERESTART
A signal was delivered during wait, for a restartable operation.
Mutex lock requests without timeout specified are restartable.
-The error is typically not returned to userspace code, restart
+The error is not returned to userspace code since restart
is handled by usual adjustment of the instruction counter.
.El
.Sh BUGS
@@ -1374,7 +1395,7 @@ implementation is only vulnerable to this race when operating on
a shared mutex.
A possible fix for the current implementation is to strengthen the checks
for shared mutexes before terminating them, in particular, verifying
-that the mutex memory is mapped from the POSIX shared object, allocated
+that the mutex memory is mapped from a shared memory object allocated
by the
.Dv UMTX_OP_SHM
request.
@@ -1402,5 +1423,5 @@ system call is non-standard and is used by the
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2
index 8b6add9..2e13a6c 100644
--- a/lib/libc/sys/jail.2
+++ b/lib/libc/sys/jail.2
@@ -106,7 +106,7 @@ pointers can be set to an arrays of IPv4 and IPv6 addresses to be assigned to
the prison, or NULL if none.
IPv4 addresses must be in network byte order.
.Pp
-This is equivalent to the
+This is equivalent to, and deprecated in favor of, the
.Fn jail_set
system call (see below), with the parameters
.Va path ,
diff --git a/lib/libc/sys/thr_exit.2 b/lib/libc/sys/thr_exit.2
index 0804219..781b07f 100644
--- a/lib/libc/sys/thr_exit.2
+++ b/lib/libc/sys/thr_exit.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_EXIT 2
.Os
.Sh NAME
@@ -41,24 +41,33 @@
.Ft void
.Fn thr_exit "long *state"
.Sh DESCRIPTION
+.Bf -symbolic
+This function is intended for implementing threading.
+Normal applications should call
+.Xr pthread_exit 3
+instead.
+.Ef
+.Pp
The
.Fn thr_exit
system call terminates the current kernel-scheduled thread.
.Pp
If the
.Fa state
-argument is not NULL, the location pointed to by the argument is
-updated with an arbitrary non-zero value, and
+argument is not
+.Dv NULL ,
+the location pointed to by the argument is
+updated with an arbitrary non-zero value, and an
.Xr _umtx_op 2
.Dv UMTX_OP_WAKE
operation is consequently performed on the location.
.Pp
-Attempts to terminate last thread in the process are silently ignored.
+Attempts to terminate the last thread in the process are silently ignored.
Use
.Xr _exit 2
syscall to terminate the process.
.Sh RETURN VALUES
-The function does not return any values.
+The function does not return a value.
A return from the function indicates that the calling thread was the
last one in the process.
.Sh SEE ALSO
@@ -68,13 +77,14 @@ last one in the process.
.Xr thr_new 2 ,
.Xr thr_self 2 ,
.Xr thr_set_name 2 ,
-.Xr _umtx_op 2
+.Xr _umtx_op 2 ,
+.Xr pthread_exit 3
.Sh STANDARDS
The
.Fn thr_exit
-system call is non-standard and is used by the
+system call is non-standard and is used by
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_kill.2 b/lib/libc/sys/thr_kill.2
index 8c12ef7..04293aa 100644
--- a/lib/libc/sys/thr_kill.2
+++ b/lib/libc/sys/thr_kill.2
@@ -28,12 +28,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_kill 2
.Os
.Sh NAME
.Nm thr_kill
-.Nd send signal to the thread
+.Nd send signal to thread
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -72,7 +72,7 @@ The
.Fa sig
argument defines the delivered signal.
It must be a valid signal number or zero.
-In the later case no signal is actually send, and the call is used to
+In the latter case no signal is actually sent, and the call is used to
verify the liveness of the thread.
.Pp
The signal is delivered with
@@ -112,11 +112,13 @@ The current process does not have sufficient privilege to check existence or
send a signal to the specified process.
.El
.Sh SEE ALSO
+.Xr kill 2 ,
.Xr thr_exit 2 ,
.Xr thr_new 2 ,
.Xr thr_self 2 ,
.Xr thr_set_name 2 ,
.Xr _umtx_op 2 ,
+.Xr pthread_kill 3 ,
.Xr signal 3
.Sh STANDARDS
The
@@ -127,5 +129,5 @@ system calls are non-standard and are used by the
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_new.2 b/lib/libc/sys/thr_new.2
index 44c468d..1de5f92 100644
--- a/lib/libc/sys/thr_new.2
+++ b/lib/libc/sys/thr_new.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_NEW 2
.Os
.Sh NAME
@@ -41,6 +41,13 @@
.Ft int
.Fn thr_new "struct thr_param *param" "int param_size"
.Sh DESCRIPTION
+.Bf -symbolic
+This function is intended for implementing threading.
+Normal applications should call
+.Xr pthread_create 3
+instead.
+.Ef
+.Pp
The
.Fn thr_new
system call creates a new kernel-scheduled thread of execution in the context
@@ -52,7 +59,7 @@ The machine context for the new thread is copied from the creating thread's
context, including coprocessor state.
FPU state and specific machine registers are excluded from the copy.
These are set according to ABI requirements and syscall parameters.
-The FPU state for new thread is reinitialized to clean.
+The FPU state for the new thread is reinitialized to clean.
.Pp
The
.Fa param
@@ -77,22 +84,22 @@ struct thr_param {
and contains the following fields:
.Bl -tag -width ".Va parent_tid"
.It Va start_func
-The pointer to the thread entry function.
-Kernel arranges for the new thread to start executing the function
+Pointer to the thread entry function.
+The kernel arranges for the new thread to start executing the function
upon the first return to userspace.
.It Va arg
Opaque argument supplied to the entry function.
.It Va stack_base
Stack base address.
The stack must be allocated by the caller.
-On some architectures, the ABI might require that system put information
+On some architectures, the ABI might require that the system put information
on the stack to ensure the execution environment for
.Va start_func .
.It Va stack_size
Stack size.
.It Va tls_base
TLS base address.
-The value of TLS base is loaded to the ABI-defined machine register
+The value of TLS base is loaded into the ABI-defined machine register
in the new thread context.
.It Va tls_size
TLS size.
@@ -113,9 +120,9 @@ issuing the
syscall, while
.Va parent_tid
is used by the thread creator.
-The later is separate from the
+The latter is separate from
.Va child_tid
-because new thread might exit and free its thread data before parent
+because the new thread might exit and free its thread data before the parent
has a chance to execute far enough to access it.
.It Va flags
Thread creation flags.
@@ -132,7 +139,9 @@ The flag is not currently implemented.
.El
.It Va rtp
Real-time scheduling priority for the new thread.
-May be NULL if thread should inherit the priority from the
+May be
+.Dv NULL
+to inherit the priority from the
creating thread.
.El
.Pp
@@ -184,14 +193,16 @@ initial data on the stack.
.It Bq Er EINVAL
The
.Fa param_size
-argument specifies negative value, or its value is greater than the
+argument specifies a negative value, or the value is greater than the
largest
.Fa struct param
size the kernel can interpret.
.It Bq Er EINVAL
The
.Fa rtp
-member is not NULL, but specifies invalid scheduling parameters.
+member is not
+.Dv NULL
+and specifies invalid scheduling parameters.
.It Bq Er EINVAL
The specified TLS base is invalid.
.It Bq Er EPROCLIM
@@ -216,7 +227,8 @@ No kernel memory to allocate for the new thread structures.
.Xr thr_kill2 2 ,
.Xr thr_self 2 ,
.Xr thr_set_name 2 ,
-.Xr _umtx_op 2
+.Xr _umtx_op 2 ,
+.Xr pthread_create 3
.Sh STANDARDS
The
.Fn thr_new
@@ -224,5 +236,5 @@ system call is non-standard and is used by the
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_self.2 b/lib/libc/sys/thr_self.2
index d90b863..949b600 100644
--- a/lib/libc/sys/thr_self.2
+++ b/lib/libc/sys/thr_self.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_SELF 2
.Os
.Sh NAME
@@ -76,13 +76,15 @@ argument is not valid.
.Xr thr_kill2 2 ,
.Xr thr_new 2 ,
.Xr thr_set_name 2 ,
-.Xr _umtx_op 2
+.Xr _umtx_op 2 ,
+.Xr pthread_getthreadid_np 3 ,
+.Xr pthread_self 3
.Sh STANDARDS
The
.Fn thr_self
-system call is non-standard and is used by the
+system call is non-standard and is used by
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_set_name.2 b/lib/libc/sys/thr_set_name.2
index 681e94b..d2549e4 100644
--- a/lib/libc/sys/thr_set_name.2
+++ b/lib/libc/sys/thr_set_name.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_SET_NAME 2
.Os
.Sh NAME
@@ -45,7 +45,7 @@ The
.Fn thr_set_name
sets the user-visible name for the kernel thread with the identifier
.Va id
-in the current process, to the NULL-terminated string
+in the current process, to the NUL-terminated string
.Va name .
The thread name can be seen in the output of the
.Xr ps 1
@@ -87,10 +87,11 @@ does not exist in the current process.
.Xr thr_new 2 ,
.Xr thr_self 2 ,
.Xr _umtx_op 2 ,
+.Xr pthread_set_name_np 3 ,
.Xr ddb 4 ,
.Xr ktr 9
.Sh STANDARDS
The
.Fn thr_new
-system call is non-standard and is used by the
+system call is non-standard and is used by
.Lb libthr .
diff --git a/lib/libc/sys/wait.2 b/lib/libc/sys/wait.2
index 687bc18..38b7bb7 100644
--- a/lib/libc/sys/wait.2
+++ b/lib/libc/sys/wait.2
@@ -28,7 +28,7 @@
.\" @(#)wait.2 8.2 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd December 3, 2013
+.Dd June 1, 2016
.Dt WAIT 2
.Os
.Sh NAME
@@ -596,6 +596,14 @@ and
fields of
.Fa infop
must be checked against zero to determine if a process reported status.
+.Pp
+.Fn wait
+called with -1 to wait for any child process will ignore a child that is
+referenced by a process descriptor (see
+.Xr pdfork 2 ) .
+Specific processes can still be waited on by specifying the process ID
+or descriptor (see
+.Xr pdwait 4 ) .
.Sh ERRORS
The
.Fn wait
diff --git a/lib/libcasper/services/cap_grp/cap_grp.c b/lib/libcasper/services/cap_grp/cap_grp.c
index d358cea..54a022f 100644
--- a/lib/libcasper/services/cap_grp/cap_grp.c
+++ b/lib/libcasper/services/cap_grp/cap_grp.c
@@ -703,7 +703,9 @@ grp_setgrent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused,
nvlist_t *nvlout __unused)
{
- return (setgrent() == 0 ? EFAULT : 0);
+ setgrent();
+
+ return (0);
}
static int
diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile
index c1f8542..3b982a3 100644
--- a/lib/libcrypt/Makefile
+++ b/lib/libcrypt/Makefile
@@ -31,6 +31,8 @@ CFLAGS+= -I${.CURDIR} -DHAS_DES -DHAS_BLOWFISH
.for sym in MD4Init MD4Final MD4Update MD4Pad \
MD5Init MD5Final MD5Update MD5Pad \
SHA256_Init SHA256_Final SHA256_Update \
+ SHA512_224_Init SHA512_224_Final SHA512_224_Update \
+ SHA512_256_Init SHA512_256_Final SHA512_256_Update \
SHA384_Init SHA384_Final SHA384_Update \
SHA512_Init SHA512_Final SHA512_Update
CFLAGS+= -D${sym}=__${sym}
diff --git a/lib/libcxxrt/Makefile b/lib/libcxxrt/Makefile
index 15420a6..f2efe8d 100644
--- a/lib/libcxxrt/Makefile
+++ b/lib/libcxxrt/Makefile
@@ -21,7 +21,7 @@ SRCS+= libelftc_dem_gnu3.c\
guard.cc
WARNS= 0
-CFLAGS+= -I${SRCDIR} -nostdinc++
+CFLAGS+= -isystem ${SRCDIR} -nostdinc++
.if empty(CXXFLAGS:M-std=*)
CXXFLAGS+= -std=c++11
.endif
diff --git a/lib/libdevdctl/Makefile b/lib/libdevdctl/Makefile
new file mode 100644
index 0000000..5a18a14
--- /dev/null
+++ b/lib/libdevdctl/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+LIB_CXX= devdctl
+INCS= consumer.h \
+ event.h \
+ event_factory.h \
+ exception.h \
+ guid.h
+SRCS= consumer.cc \
+ event.cc \
+ event_factory.cc \
+ exception.cc \
+ guid.cc
+
+INCSDIR= ${INCLUDEDIR}/devdctl
+
+WARNS?= 3
+PRIVATELIB= true
+SHLIB_MAJOR= 0
+
+.include <bsd.lib.mk>
diff --git a/lib/libdevdctl/consumer.cc b/lib/libdevdctl/consumer.cc
new file mode 100644
index 0000000..e769894
--- /dev/null
+++ b/lib/libdevdctl/consumer.cc
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file consumer.cc
+ */
+
+#include <sys/cdefs.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <cstdarg>
+#include <cstring>
+#include <list>
+#include <map>
+#include <string>
+
+#include "guid.h"
+#include "event.h"
+#include "event_factory.h"
+#include "exception.h"
+
+#include "consumer.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+using std::string;
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+/*----------------------------- DevdCtl::Consumer ----------------------------*/
+//- Consumer Static Private Data -----------------------------------------------
+const char Consumer::s_devdSockPath[] = "/var/run/devd.seqpacket.pipe";
+
+//- Consumer Public Methods ----------------------------------------------------
+Consumer::Consumer(Event::BuildMethod *defBuilder,
+ EventFactory::Record *regEntries,
+ size_t numEntries)
+ : m_devdSockFD(-1),
+ m_eventFactory(defBuilder),
+ m_replayingEvents(false)
+{
+ m_eventFactory.UpdateRegistry(regEntries, numEntries);
+}
+
+Consumer::~Consumer()
+{
+ DisconnectFromDevd();
+}
+
+bool
+Consumer::ConnectToDevd()
+{
+ struct sockaddr_un devdAddr;
+ int sLen;
+ int result;
+
+ if (m_devdSockFD != -1) {
+ /* Already connected. */
+ syslog(LOG_DEBUG, "%s: Already connected.", __func__);
+ return (true);
+ }
+ syslog(LOG_INFO, "%s: Connecting to devd.", __func__);
+
+ memset(&devdAddr, 0, sizeof(devdAddr));
+ devdAddr.sun_family= AF_UNIX;
+ strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path));
+ sLen = SUN_LEN(&devdAddr);
+
+ m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ if (m_devdSockFD == -1)
+ err(1, "Unable to create socket");
+ if (fcntl(m_devdSockFD, F_SETFL, O_NONBLOCK) < 0)
+ err(1, "fcntl");
+ result = connect(m_devdSockFD,
+ reinterpret_cast<sockaddr *>(&devdAddr),
+ sLen);
+ if (result == -1) {
+ syslog(LOG_INFO, "Unable to connect to devd");
+ DisconnectFromDevd();
+ return (false);
+ }
+
+ syslog(LOG_INFO, "Connection to devd successful");
+ return (true);
+}
+
+void
+Consumer::DisconnectFromDevd()
+{
+ if (m_devdSockFD != -1) {
+ syslog(LOG_INFO, "Disconnecting from devd.");
+ close(m_devdSockFD);
+ }
+ m_devdSockFD = -1;
+}
+
+std::string
+Consumer::ReadEvent()
+{
+ char buf[MAX_EVENT_SIZE + 1];
+ ssize_t len;
+
+ len = ::recv(m_devdSockFD, buf, MAX_EVENT_SIZE, MSG_WAITALL);
+ if (len == -1)
+ return (std::string(""));
+ else {
+ /* NULL-terminate the result */
+ buf[len] = '\0';
+ return (std::string(buf));
+ }
+}
+
+void
+Consumer::ReplayUnconsumedEvents(bool discardUnconsumed)
+{
+ EventList::iterator event(m_unconsumedEvents.begin());
+ bool replayed_any = (event != m_unconsumedEvents.end());
+
+ m_replayingEvents = true;
+ if (replayed_any)
+ syslog(LOG_INFO, "Started replaying unconsumed events");
+ while (event != m_unconsumedEvents.end()) {
+ bool consumed((*event)->Process());
+ if (consumed || discardUnconsumed) {
+ delete *event;
+ event = m_unconsumedEvents.erase(event);
+ } else {
+ event++;
+ }
+ }
+ if (replayed_any)
+ syslog(LOG_INFO, "Finished replaying unconsumed events");
+ m_replayingEvents = false;
+}
+
+bool
+Consumer::SaveEvent(const Event &event)
+{
+ if (m_replayingEvents)
+ return (false);
+ m_unconsumedEvents.push_back(event.DeepCopy());
+ return (true);
+}
+
+Event *
+Consumer::NextEvent()
+{
+ if (!Connected())
+ return(NULL);
+
+ Event *event(NULL);
+ try {
+ string evString;
+
+ evString = ReadEvent();
+ if (! evString.empty()) {
+ Event::TimestampEventString(evString);
+ event = Event::CreateEvent(m_eventFactory, evString);
+ }
+ } catch (const Exception &exp) {
+ exp.Log();
+ DisconnectFromDevd();
+ }
+ return (event);
+}
+
+/* Capture and process buffered events. */
+void
+Consumer::ProcessEvents()
+{
+ Event *event;
+ while ((event = NextEvent()) != NULL) {
+ if (event->Process())
+ SaveEvent(*event);
+ delete event;
+ }
+}
+
+void
+Consumer::FlushEvents()
+{
+ std::string s;
+
+ do
+ s = ReadEvent();
+ while (! s.empty()) ;
+}
+
+bool
+Consumer::EventsPending()
+{
+ struct pollfd fds[1];
+ int result;
+
+ do {
+ fds->fd = m_devdSockFD;
+ fds->events = POLLIN;
+ fds->revents = 0;
+ result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/0);
+ } while (result == -1 && errno == EINTR);
+
+ if (result == -1)
+ err(1, "Polling for devd events failed");
+
+ if ((fds->revents & POLLERR) != 0)
+ throw Exception("Consumer::EventsPending(): "
+ "POLLERR detected on devd socket.");
+
+ if ((fds->revents & POLLHUP) != 0)
+ throw Exception("Consumer::EventsPending(): "
+ "POLLHUP detected on devd socket.");
+
+ return ((fds->revents & POLLIN) != 0);
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/consumer.h b/lib/libdevdctl/consumer.h
new file mode 100644
index 0000000..0f15b79
--- /dev/null
+++ b/lib/libdevdctl/consumer.h
@@ -0,0 +1,174 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_consumer.h
+ */
+#ifndef _DEVDCTL_CONSUMER_H_
+#define _DEVDCTL_CONSUMER_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*=========================== Forward Declarations ===========================*/
+class Event;
+
+/*============================ Class Declarations ============================*/
+/*----------------------------- DevdCtl::Consumer ----------------------------*/
+
+/**
+ */
+class Consumer
+{
+public:
+ Consumer(Event::BuildMethod *defBuilder = NULL,
+ EventFactory::Record *regEntries = NULL,
+ size_t numEntries = 0);
+ virtual ~Consumer();
+
+ bool Connected() const;
+
+ /**
+ * Return file descriptor useful for client's wishing to poll(2)
+ * for new events.
+ */
+ int GetPollFd();
+
+ /**
+ * Queue an event for deferred processing or replay.
+ */
+ bool SaveEvent(const Event &event);
+
+ /**
+ * Reprocess any events saved via the SaveEvent() facility.
+ *
+ * \param discardUnconsumed If true, events that are not consumed
+ * during replay are discarded.
+ */
+ void ReplayUnconsumedEvents(bool discardUnconsumed);
+
+ /** Return an event, if one is available. */
+ Event *NextEvent();
+
+ /**
+ * Extract events and invoke each event's Process method.
+ */
+ void ProcessEvents();
+
+ /** Discard all data pending in m_devdSockFD. */
+ void FlushEvents();
+
+ /**
+ * Test for data pending in m_devdSockFD
+ *
+ * \return True if data is pending. Otherwise false.
+ */
+ bool EventsPending();
+
+ /**
+ * Open a connection to devd's unix domain socket.
+ *
+ * \return True if the connection attempt is successsful. Otherwise
+ * false.
+ */
+ bool ConnectToDevd();
+
+ /**
+ * Close a connection (if any) to devd's unix domain socket.
+ */
+ void DisconnectFromDevd();
+
+ EventFactory GetFactory();
+
+protected:
+ /**
+ * \brief Reads the most recent record
+ *
+ * On error, "" is returned, and errno will be set by the OS
+ *
+ * \returns A string containing the record
+ */
+ std::string ReadEvent();
+
+ enum {
+ /*
+ * The maximum event size supported by libdevdctl.
+ */
+ MAX_EVENT_SIZE = 8192,
+ };
+
+ static const char s_devdSockPath[];
+
+ /**
+ * File descriptor representing the unix domain socket
+ * connection with devd.
+ */
+ int m_devdSockFD;
+
+ EventFactory m_eventFactory;
+
+ /** Queued events for replay. */
+ EventList m_unconsumedEvents;
+
+ /**
+ * Flag controlling whether events can be queued. This boolean
+ * is set during event replay to ensure that previosuly deferred
+ * events are not requeued and thus retained forever.
+ */
+ bool m_replayingEvents;
+};
+
+//- Consumer Const Public Inline Methods ---------------------------------------
+inline bool
+Consumer::Connected() const
+{
+ return (m_devdSockFD != -1);
+}
+
+//- Consumer Public Inline Methods ---------------------------------------------
+inline int
+Consumer::GetPollFd()
+{
+ return (m_devdSockFD);
+}
+
+inline EventFactory
+Consumer::GetFactory()
+{
+ return (m_eventFactory);
+}
+
+} // namespace DevdCtl
+#endif /* _DEVDCTL_CONSUMER_H_ */
diff --git a/lib/libdevdctl/event.cc b/lib/libdevdctl/event.cc
new file mode 100644
index 0000000..d63e8e2
--- /dev/null
+++ b/lib/libdevdctl/event.cc
@@ -0,0 +1,602 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file event.cc
+ *
+ * Implementation of the class hierarchy used to express events
+ * received via the devdctl API.
+ */
+#include <sys/cdefs.h>
+#include <sys/disk.h>
+#include <sys/filio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <cstdarg>
+#include <cstring>
+#include <iostream>
+#include <list>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "guid.h"
+#include "event.h"
+#include "event_factory.h"
+#include "exception.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+using std::cout;
+using std::endl;
+using std::string;
+using std::stringstream;
+
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*----------------------------------- Event ----------------------------------*/
+//- Event Static Protected Data ------------------------------------------------
+const string Event::s_theEmptyString;
+
+Event::EventTypeRecord Event::s_typeTable[] =
+{
+ { Event::NOTIFY, "Notify" },
+ { Event::NOMATCH, "No Driver Match" },
+ { Event::ATTACH, "Attach" },
+ { Event::DETACH, "Detach" }
+};
+
+//- Event Static Public Methods ------------------------------------------------
+Event *
+Event::Builder(Event::Type type, NVPairMap &nvPairs,
+ const string &eventString)
+{
+ return (new Event(type, nvPairs, eventString));
+}
+
+Event *
+Event::CreateEvent(const EventFactory &factory, const string &eventString)
+{
+ NVPairMap &nvpairs(*new NVPairMap);
+ Type type(static_cast<Event::Type>(eventString[0]));
+
+ try {
+ ParseEventString(type, eventString, nvpairs);
+ } catch (const ParseException &exp) {
+ if (exp.GetType() == ParseException::INVALID_FORMAT)
+ exp.Log();
+ return (NULL);
+ }
+
+ /*
+ * Allow entries in our table for events with no system specified.
+ * These entries should specify the string "none".
+ */
+ NVPairMap::iterator system_item(nvpairs.find("system"));
+ if (system_item == nvpairs.end())
+ nvpairs["system"] = "none";
+
+ return (factory.Build(type, nvpairs, eventString));
+}
+
+bool
+Event::DevName(std::string &name) const
+{
+ return (false);
+}
+
+/* TODO: simplify this function with C++-11 <regex> methods */
+bool
+Event::IsDiskDev() const
+{
+ const int numDrivers = 2;
+ static const char *diskDevNames[numDrivers] =
+ {
+ "da",
+ "ada"
+ };
+ const char **dName;
+ string devName;
+
+ if (! DevName(devName))
+ return false;
+
+ size_t find_start = devName.rfind('/');
+ if (find_start == string::npos) {
+ find_start = 0;
+ } else {
+ /* Just after the last '/'. */
+ find_start++;
+ }
+
+ for (dName = &diskDevNames[0];
+ dName <= &diskDevNames[numDrivers - 1]; dName++) {
+
+ size_t loc(devName.find(*dName, find_start));
+ if (loc == find_start) {
+ size_t prefixLen(strlen(*dName));
+
+ if (devName.length() - find_start >= prefixLen
+ && isdigit(devName[find_start + prefixLen]))
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+const char *
+Event::TypeToString(Event::Type type)
+{
+ EventTypeRecord *rec(s_typeTable);
+ EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1);
+
+ for (; rec <= lastRec; rec++) {
+ if (rec->m_type == type)
+ return (rec->m_typeName);
+ }
+ return ("Unknown");
+}
+
+//- Event Public Methods -------------------------------------------------------
+const string &
+Event::Value(const string &varName) const
+{
+ NVPairMap::const_iterator item(m_nvPairs.find(varName));
+ if (item == m_nvPairs.end())
+ return (s_theEmptyString);
+
+ return (item->second);
+}
+
+bool
+Event::Contains(const string &varName) const
+{
+ return (m_nvPairs.find(varName) != m_nvPairs.end());
+}
+
+string
+Event::ToString() const
+{
+ stringstream result;
+
+ NVPairMap::const_iterator devName(m_nvPairs.find("device-name"));
+ if (devName != m_nvPairs.end())
+ result << devName->second << ": ";
+
+ NVPairMap::const_iterator systemName(m_nvPairs.find("system"));
+ if (systemName != m_nvPairs.end()
+ && systemName->second != "none")
+ result << systemName->second << ": ";
+
+ result << TypeToString(GetType()) << ' ';
+
+ for (NVPairMap::const_iterator curVar = m_nvPairs.begin();
+ curVar != m_nvPairs.end(); curVar++) {
+ if (curVar == devName || curVar == systemName)
+ continue;
+
+ result << ' '
+ << curVar->first << "=" << curVar->second;
+ }
+ result << endl;
+
+ return (result.str());
+}
+
+void
+Event::Print() const
+{
+ cout << ToString() << std::flush;
+}
+
+void
+Event::Log(int priority) const
+{
+ syslog(priority, "%s", ToString().c_str());
+}
+
+//- Event Virtual Public Methods -----------------------------------------------
+Event::~Event()
+{
+ delete &m_nvPairs;
+}
+
+Event *
+Event::DeepCopy() const
+{
+ return (new Event(*this));
+}
+
+bool
+Event::Process() const
+{
+ return (false);
+}
+
+timeval
+Event::GetTimestamp() const
+{
+ timeval tv_timestamp;
+ struct tm tm_timestamp;
+
+ if (!Contains("timestamp")) {
+ throw Exception("Event contains no timestamp: %s",
+ m_eventString.c_str());
+ }
+ strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp);
+ tv_timestamp.tv_sec = mktime(&tm_timestamp);
+ tv_timestamp.tv_usec = 0;
+ return (tv_timestamp);
+}
+
+bool
+Event::DevPath(std::string &path) const
+{
+ string devName;
+
+ if (!DevName(devName))
+ return (false);
+
+ string devPath(_PATH_DEV + devName);
+ int devFd(open(devPath.c_str(), O_RDONLY));
+ if (devFd == -1)
+ return (false);
+
+ /* Normalize the device name in case the DEVFS event is for a link. */
+ devName = fdevname(devFd);
+ path = _PATH_DEV + devName;
+
+ close(devFd);
+
+ return (true);
+}
+
+bool
+Event::PhysicalPath(std::string &path) const
+{
+ string devPath;
+
+ if (!DevPath(devPath))
+ return (false);
+
+ int devFd(open(devPath.c_str(), O_RDONLY));
+ if (devFd == -1)
+ return (false);
+
+ char physPath[MAXPATHLEN];
+ physPath[0] = '\0';
+ bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0);
+ close(devFd);
+ if (result)
+ path = physPath;
+ return (result);
+}
+
+//- Event Protected Methods ----------------------------------------------------
+Event::Event(Type type, NVPairMap &map, const string &eventString)
+ : m_type(type),
+ m_nvPairs(map),
+ m_eventString(eventString)
+{
+}
+
+Event::Event(const Event &src)
+ : m_type(src.m_type),
+ m_nvPairs(*new NVPairMap(src.m_nvPairs)),
+ m_eventString(src.m_eventString)
+{
+}
+
+void
+Event::ParseEventString(Event::Type type,
+ const string &eventString,
+ NVPairMap& nvpairs)
+{
+ size_t start;
+ size_t end;
+
+ switch (type) {
+ case ATTACH:
+ case DETACH:
+
+ /*
+ * <type><device-name><unit> <pnpvars> \
+ * at <location vars> <pnpvars> \
+ * on <parent>
+ *
+ * Handle all data that doesn't conform to the
+ * "name=value" format, and let the generic parser
+ * below handle the rest.
+ *
+ * Type is a single char. Skip it.
+ */
+ start = 1;
+ end = eventString.find_first_of(" \t\n", start);
+ if (end == string::npos)
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, start);
+
+ nvpairs["device-name"] = eventString.substr(start, end - start);
+
+ start = eventString.find(" on ", end);
+ if (end == string::npos)
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, start);
+ start += 4;
+ end = eventString.find_first_of(" \t\n", start);
+ nvpairs["parent"] = eventString.substr(start, end);
+ break;
+ case NOTIFY:
+ break;
+ case NOMATCH:
+ throw ParseException(ParseException::DISCARDED_EVENT_TYPE,
+ eventString);
+ default:
+ throw ParseException(ParseException::UNKNOWN_EVENT_TYPE,
+ eventString);
+ }
+
+ /* Process common "key=value" format. */
+ for (start = 1; start < eventString.length(); start = end + 1) {
+
+ /* Find the '=' in the middle of the key/value pair. */
+ end = eventString.find('=', start);
+ if (end == string::npos)
+ break;
+
+ /*
+ * Find the start of the key by backing up until
+ * we hit whitespace or '!' (event type "notice").
+ * Due to the devdctl format, all key/value pair must
+ * start with one of these two characters.
+ */
+ start = eventString.find_last_of("! \t\n", end);
+ if (start == string::npos)
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, end);
+ start++;
+ string key(eventString.substr(start, end - start));
+
+ /*
+ * Walk forward from the '=' until either we exhaust
+ * the buffer or we hit whitespace.
+ */
+ start = end + 1;
+ if (start >= eventString.length())
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, end);
+ end = eventString.find_first_of(" \t\n", start);
+ if (end == string::npos)
+ end = eventString.length() - 1;
+ string value(eventString.substr(start, end - start));
+
+ nvpairs[key] = value;
+ }
+}
+
+void
+Event::TimestampEventString(std::string &eventString)
+{
+ if (eventString.size() > 0) {
+ /*
+ * Add a timestamp as the final field of the event if it is
+ * not already present.
+ */
+ if (eventString.find("timestamp=") == string::npos) {
+ const size_t bufsize = 32; // Long enough for a 64-bit int
+ timeval now;
+ char timebuf[bufsize];
+
+ size_t eventEnd(eventString.find_last_not_of('\n') + 1);
+ if (gettimeofday(&now, NULL) != 0)
+ err(1, "gettimeofday");
+ snprintf(timebuf, bufsize, " timestamp=%" PRId64,
+ (int64_t) now.tv_sec);
+ eventString.insert(eventEnd, timebuf);
+ }
+ }
+}
+
+/*-------------------------------- DevfsEvent --------------------------------*/
+//- DevfsEvent Static Public Methods -------------------------------------------
+Event *
+DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs,
+ const string &eventString)
+{
+ return (new DevfsEvent(type, nvPairs, eventString));
+}
+
+//- DevfsEvent Static Protected Methods ----------------------------------------
+bool
+DevfsEvent::IsWholeDev(const string &devName)
+{
+ string::const_iterator i(devName.begin());
+
+ size_t start = devName.rfind('/');
+ if (start == string::npos) {
+ start = 0;
+ } else {
+ /* Just after the last '/'. */
+ start++;
+ }
+ i += start;
+
+ /* alpha prefix followed only by digits. */
+ for (; i < devName.end() && !isdigit(*i); i++)
+ ;
+
+ if (i == devName.end())
+ return (false);
+
+ for (; i < devName.end() && isdigit(*i); i++)
+ ;
+
+ return (i == devName.end());
+}
+
+//- DevfsEvent Virtual Public Methods ------------------------------------------
+Event *
+DevfsEvent::DeepCopy() const
+{
+ return (new DevfsEvent(*this));
+}
+
+bool
+DevfsEvent::Process() const
+{
+ return (true);
+}
+
+//- DevfsEvent Public Methods --------------------------------------------------
+bool
+DevfsEvent::IsWholeDev() const
+{
+ string devName;
+
+ return (DevName(devName) && IsDiskDev() && IsWholeDev(devName));
+}
+
+bool
+DevfsEvent::DevName(std::string &name) const
+{
+ if (Value("subsystem") != "CDEV")
+ return (false);
+
+ name = Value("cdev");
+ return (!name.empty());
+}
+
+//- DevfsEvent Protected Methods -----------------------------------------------
+DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : Event(type, nvpairs, eventString)
+{
+}
+
+DevfsEvent::DevfsEvent(const DevfsEvent &src)
+ : Event(src)
+{
+}
+
+/*--------------------------------- GeomEvent --------------------------------*/
+//- GeomEvent Static Public Methods --------------------------------------------
+Event *
+GeomEvent::Builder(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+{
+ return (new GeomEvent(type, nvpairs, eventString));
+}
+
+//- GeomEvent Virtual Public Methods -------------------------------------------
+Event *
+GeomEvent::DeepCopy() const
+{
+ return (new GeomEvent(*this));
+}
+
+bool
+GeomEvent::DevName(std::string &name) const
+{
+ name = Value("devname");
+ return (!name.empty());
+}
+
+
+//- GeomEvent Protected Methods ------------------------------------------------
+GeomEvent::GeomEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : Event(type, nvpairs, eventString),
+ m_devname(Value("devname"))
+{
+}
+
+GeomEvent::GeomEvent(const GeomEvent &src)
+ : Event(src),
+ m_devname(src.m_devname)
+{
+}
+
+/*--------------------------------- ZfsEvent ---------------------------------*/
+//- ZfsEvent Static Public Methods ---------------------------------------------
+Event *
+ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+{
+ return (new ZfsEvent(type, nvpairs, eventString));
+}
+
+//- ZfsEvent Virtual Public Methods --------------------------------------------
+Event *
+ZfsEvent::DeepCopy() const
+{
+ return (new ZfsEvent(*this));
+}
+
+bool
+ZfsEvent::DevName(std::string &name) const
+{
+ return (false);
+}
+
+//- ZfsEvent Protected Methods -------------------------------------------------
+ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : Event(type, nvpairs, eventString),
+ m_poolGUID(Guid(Value("pool_guid"))),
+ m_vdevGUID(Guid(Value("vdev_guid")))
+{
+}
+
+ZfsEvent::ZfsEvent(const ZfsEvent &src)
+ : Event(src),
+ m_poolGUID(src.m_poolGUID),
+ m_vdevGUID(src.m_vdevGUID)
+{
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/event.h b/lib/libdevdctl/event.h
new file mode 100644
index 0000000..74ee3f7
--- /dev/null
+++ b/lib/libdevdctl/event.h
@@ -0,0 +1,423 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_event.h
+ *
+ * \brief Class hierarchy used to express events received via
+ * the devdctl API.
+ */
+
+#ifndef _DEVDCTL_EVENT_H_
+#define _DEVDCTL_EVENT_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*=========================== Forward Declarations ===========================*/
+class EventFactory;
+
+/*============================= Class Definitions ============================*/
+/*-------------------------------- NVPairMap ---------------------------------*/
+/**
+ * NVPairMap is a specialization of the standard map STL container.
+ */
+typedef std::map<std::string, std::string> NVPairMap;
+
+/*----------------------------------- Event ----------------------------------*/
+/**
+ * \brief Container for the name => value pairs that comprise the content of
+ * a device control event.
+ *
+ * All name => value data for events can be accessed via the Contains()
+ * and Value() methods. name => value pairs for data not explicitly
+ * received as a name => value pair are synthesized during parsing. For
+ * example, ATTACH and DETACH events have "device-name" and "parent"
+ * name => value pairs added.
+ */
+class Event
+{
+ friend class EventFactory;
+
+public:
+ /** Event type */
+ enum Type {
+ /** Generic event notification. */
+ NOTIFY = '!',
+
+ /** A driver was not found for this device. */
+ NOMATCH = '?',
+
+ /** A bus device instance has been added. */
+ ATTACH = '+',
+
+ /** A bus device instance has been removed. */
+ DETACH = '-'
+ };
+
+ /**
+ * Factory method type to construct an Event given
+ * the type of event and an NVPairMap populated from
+ * the event string received from devd.
+ */
+ typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &);
+
+ /** Generic Event object factory. */
+ static BuildMethod Builder;
+
+ static Event *CreateEvent(const EventFactory &factory,
+ const std::string &eventString);
+
+ /**
+ * Returns the devname, if any, associated with the event
+ *
+ * \param name Devname, returned by reference
+ * \return True iff the event contained a devname
+ */
+ virtual bool DevName(std::string &name) const;
+
+ /**
+ * Returns the absolute pathname of the device associated with this
+ * event.
+ *
+ * \param name Devname, returned by reference
+ * \return True iff the event contained a devname
+ */
+ bool DevPath(std::string &path) const;
+
+ /**
+ * Returns true iff this event refers to a disk device
+ */
+ bool IsDiskDev() const;
+
+ /** Returns the physical path of the device, if any
+ *
+ * \param path Physical path, returned by reference
+ * \return True iff the event contains a device with a physical
+ * path
+ */
+ bool PhysicalPath(std::string &path) const;
+
+ /**
+ * Provide a user friendly string representation of an
+ * event type.
+ *
+ * \param type The type of event to map to a string.
+ *
+ * \return A user friendly string representing the input type.
+ */
+ static const char *TypeToString(Type type);
+
+ /**
+ * Determine the availability of a name => value pair by name.
+ *
+ * \param name The key name to search for in this event instance.
+ *
+ * \return true if the specified key is available in this
+ * event, otherwise false.
+ */
+ bool Contains(const std::string &name) const;
+
+ /**
+ * \param key The name of the key for which to retrieve its
+ * associated value.
+ *
+ * \return A const reference to the string representing the
+ * value associated with key.
+ *
+ * \note For key's with no registered value, the empty string
+ * is returned.
+ */
+ const std::string &Value(const std::string &key) const;
+
+ /**
+ * Get the type of this event instance.
+ *
+ * \return The type of this event instance.
+ */
+ Type GetType() const;
+
+ /**
+ * Get the original DevdCtl event string for this event.
+ *
+ * \return The DevdCtl event string.
+ */
+ const std::string &GetEventString() const;
+
+ /**
+ * Convert the event instance into a string suitable for
+ * printing to the console or emitting to syslog.
+ *
+ * \return A string of formatted event data.
+ */
+ std::string ToString() const;
+
+ /**
+ * Pretty-print this event instance to cout.
+ */
+ void Print() const;
+
+ /**
+ * Pretty-print this event instance to syslog.
+ *
+ * \param priority The logging priority/facility.
+ * See syslog(3).
+ */
+ void Log(int priority) const;
+
+ /**
+ * Create and return a fully independent clone
+ * of this event.
+ */
+ virtual Event *DeepCopy() const;
+
+ /** Destructor */
+ virtual ~Event();
+
+ /**
+ * Interpret and perform any actions necessary to
+ * consume the event.
+ *
+ * \return True if this event should be queued for later reevaluation
+ */
+ virtual bool Process() const;
+
+ /**
+ * Get the time that the event was created
+ */
+ timeval GetTimestamp() const;
+
+ /**
+ * Add a timestamp to the event string, if one does not already exist
+ * TODO: make this an instance method that operates on the std::map
+ * instead of the string. We must fix zfsd's CaseFile serialization
+ * routines first, so that they don't need the raw event string.
+ *
+ * \param[in,out] eventString The devd event string to modify
+ */
+ static void TimestampEventString(std::string &eventString);
+
+ /**
+ * Access all parsed key => value pairs.
+ */
+ const NVPairMap &GetMap() const;
+
+protected:
+ /** Table entries used to map a type to a user friendly string. */
+ struct EventTypeRecord
+ {
+ Type m_type;
+ const char *m_typeName;
+ };
+
+ /**
+ * Constructor
+ *
+ * \param type The type of event to create.
+ */
+ Event(Type type, NVPairMap &map, const std::string &eventString);
+
+ /** Deep copy constructor. */
+ Event(const Event &src);
+
+ /** Always empty string returned when NVPairMap lookups fail. */
+ static const std::string s_theEmptyString;
+
+ /** Unsorted table of event types. */
+ static EventTypeRecord s_typeTable[];
+
+ /** The type of this event. */
+ const Type m_type;
+
+ /**
+ * Event attribute storage.
+ *
+ * \note Although stored by reference (since m_nvPairs can
+ * never be NULL), the NVPairMap referenced by this field
+ * is dynamically allocated and owned by this event object.
+ * m_nvPairs must be deleted at event destruction.
+ */
+ NVPairMap &m_nvPairs;
+
+ /**
+ * The unaltered event string, as received from devd, used to
+ * create this event object.
+ */
+ std::string m_eventString;
+
+private:
+ /**
+ * Ingest event data from the supplied string.
+ *
+ * \param[in] eventString The string of devd event data to parse.
+ * \param[out] nvpairs Returns the parsed data
+ */
+ static void ParseEventString(Type type, const std::string &eventString,
+ NVPairMap &nvpairs);
+};
+
+inline Event::Type
+Event::GetType() const
+{
+ return (m_type);
+}
+
+inline const std::string &
+Event::GetEventString() const
+{
+ return (m_eventString);
+}
+
+inline const NVPairMap &
+Event::GetMap() const
+{
+ return (m_nvPairs);
+}
+
+/*--------------------------------- EventList --------------------------------*/
+/**
+ * EventList is a specialization of the standard list STL container.
+ */
+typedef std::list<Event *> EventList;
+
+/*-------------------------------- DevfsEvent --------------------------------*/
+class DevfsEvent : public Event
+{
+public:
+ /** Specialized Event object factory for Devfs events. */
+ static BuildMethod Builder;
+
+ virtual Event *DeepCopy() const;
+
+ /**
+ * Interpret and perform any actions necessary to
+ * consume the event.
+ * \return True if this event should be queued for later reevaluation
+ */
+ virtual bool Process() const;
+
+ bool IsWholeDev() const;
+ virtual bool DevName(std::string &name) const;
+
+protected:
+ /**
+ * Given the device name of a disk, determine if the device
+ * represents the whole device, not just a partition.
+ *
+ * \param devName Device name of disk device to test.
+ *
+ * \return True if the device name represents the whole device.
+ * Otherwise false.
+ */
+ static bool IsWholeDev(const std::string &devName);
+
+ /** DeepCopy Constructor. */
+ DevfsEvent(const DevfsEvent &src);
+
+ /** Constructor */
+ DevfsEvent(Type, NVPairMap &, const std::string &);
+};
+
+/*--------------------------------- GeomEvent --------------------------------*/
+class GeomEvent : public Event
+{
+public:
+ /** Specialized Event object factory for GEOM events. */
+ static BuildMethod Builder;
+
+ virtual Event *DeepCopy() const;
+
+ virtual bool DevName(std::string &name) const;
+
+ const std::string &DeviceName() const;
+
+protected:
+ /** Constructor */
+ GeomEvent(Type, NVPairMap &, const std::string &);
+
+ /** Deep copy constructor. */
+ GeomEvent(const GeomEvent &src);
+
+ std::string m_devname;
+};
+
+/*--------------------------------- ZfsEvent ---------------------------------*/
+class ZfsEvent : public Event
+{
+public:
+ /** Specialized Event object factory for ZFS events. */
+ static BuildMethod Builder;
+
+ virtual Event *DeepCopy() const;
+
+ virtual bool DevName(std::string &name) const;
+
+ const std::string &PoolName() const;
+ Guid PoolGUID() const;
+ Guid VdevGUID() const;
+
+protected:
+ /** Constructor */
+ ZfsEvent(Type, NVPairMap &, const std::string &);
+
+ /** Deep copy constructor. */
+ ZfsEvent(const ZfsEvent &src);
+
+ Guid m_poolGUID;
+ Guid m_vdevGUID;
+};
+
+//- ZfsEvent Inline Public Methods --------------------------------------------
+inline const std::string&
+ZfsEvent::PoolName() const
+{
+ /* The pool name is reported as the subsystem of ZFS events. */
+ return (Value("subsystem"));
+}
+
+inline Guid
+ZfsEvent::PoolGUID() const
+{
+ return (m_poolGUID);
+}
+
+inline Guid
+ZfsEvent::VdevGUID() const
+{
+ return (m_vdevGUID);
+}
+
+} // namespace DevdCtl
+#endif /*_DEVDCTL_EVENT_H_ */
diff --git a/lib/libdevdctl/event_factory.cc b/lib/libdevdctl/event_factory.cc
new file mode 100644
index 0000000..3901fd5
--- /dev/null
+++ b/lib/libdevdctl/event_factory.cc
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file event_factory.cc
+ */
+#include <sys/cdefs.h>
+#include <sys/time.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include "guid.h"
+#include "event.h"
+#include "event_factory.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*------------------------------- EventFactory -------------------------------*/
+//- Event Public Methods -------------------------------------------------------
+EventFactory::EventFactory(Event::BuildMethod *defaultBuildMethod)
+ : m_defaultBuildMethod(defaultBuildMethod)
+{
+}
+
+void
+EventFactory::UpdateRegistry(Record regEntries[], size_t numEntries)
+{
+ EventFactory::Record *rec(regEntries);
+ EventFactory::Record *lastRec(rec + numEntries - 1);
+
+ for (; rec <= lastRec; rec++) {
+ Key key(rec->m_type, rec->m_subsystem);
+
+ if (rec->m_buildMethod == NULL)
+ m_registry.erase(key);
+ else
+ m_registry[key] = rec->m_buildMethod;
+ }
+}
+
+Event *
+EventFactory::Build(Event::Type type, NVPairMap &nvpairs,
+ const std::string eventString) const
+{
+ Key key(type, nvpairs["system"]);
+ Event::BuildMethod *buildMethod(m_defaultBuildMethod);
+
+ Registry::const_iterator foundMethod(m_registry.find(key));
+ if (foundMethod != m_registry.end())
+ buildMethod = foundMethod->second;
+
+ if (buildMethod == NULL) {
+ delete &nvpairs;
+ return (NULL);
+ }
+
+ return (buildMethod(type, nvpairs, eventString));
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/event_factory.h b/lib/libdevdctl/event_factory.h
new file mode 100644
index 0000000..e23332c
--- /dev/null
+++ b/lib/libdevdctl/event_factory.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_event_factory.h
+ */
+
+#ifndef _DEVDCTL_EVENT_FACTORY_H_
+#define _DEVDCTL_EVENT_FACTORY_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+/*------------------------------- EventFactory -------------------------------*/
+/**
+ * \brief Container for "event type" => "event object" creation methods.
+ */
+class EventFactory
+{
+public:
+ /**
+ * Event creation handlers are matched by event type and a
+ * string representing the system emitting the event.
+ */
+ typedef std::pair<Event::Type, std::string> Key;
+
+ /** Map type for Factory method lookups. */
+ typedef std::map<Key, Event::BuildMethod *> Registry;
+
+ /** Table record of factory methods to add to our registry. */
+ struct Record
+ {
+ Event::Type m_type;
+ const char *m_subsystem;
+ Event::BuildMethod *m_buildMethod;
+ };
+
+ const Registry &GetRegistry() const;
+ Event *Build(Event::Type type, NVPairMap &nvpairs,
+ const std::string eventString) const;
+
+ EventFactory(Event::BuildMethod *defaultBuildMethod = NULL);
+
+ void UpdateRegistry(Record regEntries[], size_t numEntries);
+
+
+protected:
+ /** Registry of event factory methods providing O(log(n)) lookup. */
+ Registry m_registry;
+
+ Event::BuildMethod *m_defaultBuildMethod;
+};
+
+inline const EventFactory::Registry &
+EventFactory::GetRegistry() const
+{
+ return (m_registry);
+}
+
+} // namespace DevdCtl
+#endif /*_DEVDCTL_EVENT_FACTORY_H_ */
diff --git a/lib/libdevdctl/exception.cc b/lib/libdevdctl/exception.cc
new file mode 100644
index 0000000..4dc8cf5
--- /dev/null
+++ b/lib/libdevdctl/exception.cc
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file exception.cc
+ */
+#include <sys/cdefs.h>
+
+#include <syslog.h>
+
+#include <cstdio>
+#include <cstdarg>
+#include <sstream>
+#include <string>
+
+#include "exception.h"
+
+__FBSDID("$FreeBSD$");
+
+/*============================ Namespace Control =============================*/
+using std::string;
+using std::stringstream;
+using std::endl;
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*--------------------------------- Exception --------------------------------*/
+void
+Exception::FormatLog(const char *fmt, va_list ap)
+{
+ char buf[256];
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ m_log = buf;
+}
+
+Exception::Exception(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ FormatLog(fmt, ap);
+ va_end(ap);
+}
+
+Exception::Exception()
+{
+}
+
+void
+Exception::Log() const
+{
+ syslog(LOG_ERR, "%s", m_log.c_str());
+}
+
+/*------------------------------ ParseException ------------------------------*/
+//- ParseException Inline Public Methods ---------------------------------------
+ParseException::ParseException(Type type, const std::string &parsedBuffer,
+ size_t offset)
+ : Exception(),
+ m_type(type),
+ m_parsedBuffer(parsedBuffer),
+ m_offset(offset)
+{
+ stringstream logstream;
+
+ logstream << "Parsing ";
+
+ switch (Type()) {
+ case INVALID_FORMAT:
+ logstream << "invalid format ";
+ break;
+ case DISCARDED_EVENT_TYPE:
+ logstream << "discarded event ";
+ break;
+ case UNKNOWN_EVENT_TYPE:
+ logstream << "unknown event ";
+ break;
+ default:
+ break;
+ }
+ logstream << "exception on buffer: \'";
+ if (GetOffset() == 0) {
+ logstream << m_parsedBuffer << '\'' << endl;
+ } else {
+ string markedBuffer(m_parsedBuffer);
+
+ markedBuffer.insert(GetOffset(), "<HERE-->");
+ logstream << markedBuffer << '\'' << endl;
+ }
+
+ GetString() = logstream.str();
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/exception.h b/lib/libdevdctl/exception.h
new file mode 100644
index 0000000..9f4403c
--- /dev/null
+++ b/lib/libdevdctl/exception.h
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file zfsd_exception.h
+ *
+ * Definition of the ZfsdException class hierarchy. All exceptions
+ * explicitly thrown by Zfsd are defined here.
+ */
+#ifndef _DEVDCTL_EXCEPTION_H_
+#define _DEVDCTL_EXCEPTION_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+
+/*--------------------------------- Exception --------------------------------*/
+/**
+ * \brief Class allowing unified reporting/logging of exceptional events.
+ */
+class Exception
+{
+public:
+ /**
+ * \brief Exception constructor allowing arbitrary string
+ * data to be reported.
+ *
+ * \param fmt Printf-like string format specifier.
+ */
+ Exception(const char *fmt, ...);
+
+ /**
+ * \brief Augment/Modify a Exception's string data.
+ */
+ std::string& GetString();
+
+ /**
+ * \brief Emit exception data to syslog(3).
+ */
+ virtual void Log() const;
+
+protected:
+ Exception();
+
+ /**
+ * \brief Convert exception string format and arguments provided
+ * in event constructors into a linear string.
+ */
+ void FormatLog(const char *fmt, va_list ap);
+
+ std::string m_log;
+};
+
+inline std::string &
+Exception::GetString()
+{
+ return (m_log);
+}
+
+/*------------------------------ ParseException ------------------------------*/
+/**
+ * Exception thrown when an event string is not converted to an actionable
+ * Event object.
+ */
+class ParseException : public Exception
+{
+public:
+ enum Type
+ {
+ /** Improperly formatted event string encountered. */
+ INVALID_FORMAT,
+
+ /** No handlers for this event type. */
+ DISCARDED_EVENT_TYPE,
+
+ /** Unhandled event type. */
+ UNKNOWN_EVENT_TYPE
+ };
+
+ /**
+ * Constructor
+ *
+ * \param type The type of this exception.
+ * \param parsedBuffer The parsing buffer active at the time of
+ * the exception.
+ * \param offset The location in the parse buffer where this
+ * exception occurred.
+ */
+ ParseException(Type type, const std::string &parsedBuffer,
+ size_t offset = 0);
+
+ /**
+ * Accessor
+ *
+ * \return The classification for this exception.
+ */
+ Type GetType() const;
+
+ /**
+ * Accessor
+ *
+ * \return The offset into the event string where this exception
+ * occurred.
+ */
+ size_t GetOffset() const;
+
+private:
+ /** The type of this exception. */
+ Type m_type;
+
+ /** The parsing buffer that was active at the time of the exception. */
+ const std::string m_parsedBuffer;
+
+ /**
+ * The offset into the event string buffer from where this
+ * exception was triggered.
+ */
+ size_t m_offset;
+};
+
+//- ParseException Inline Const Public Methods ---------------------------------
+inline ParseException::Type
+ParseException::GetType() const
+{
+ return (m_type);
+}
+
+inline size_t
+ParseException::GetOffset() const
+{
+ return (m_offset);
+}
+
+} // namespace DevdCtl
+#endif /* _DEVDCTL_EXCEPTION_H_ */
diff --git a/lib/libdevdctl/guid.cc b/lib/libdevdctl/guid.cc
new file mode 100644
index 0000000..42d326f
--- /dev/null
+++ b/lib/libdevdctl/guid.cc
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file guid.cc
+ *
+ * Implementation of the Guid class.
+ */
+#include <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
+
+#include <iostream>
+#include <string>
+
+#include "guid.h"
+
+__FBSDID("$FreeBSD$");
+/*============================ Namespace Control =============================*/
+using std::string;
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*----------------------------------- Guid -----------------------------------*/
+Guid::Guid(const string &guidString)
+{
+ if (guidString.empty()) {
+ m_GUID = INVALID_GUID;
+ } else {
+ /*
+ * strtoumax() returns zero on conversion failure
+ * which nicely matches our choice for INVALID_GUID.
+ */
+ m_GUID = (uint64_t)strtoumax(guidString.c_str(), NULL, 0);
+ }
+}
+
+std::ostream&
+operator<< (std::ostream& out, Guid g)
+{
+ if (g.IsValid())
+ out << (uint64_t)g;
+ else
+ out << "None";
+ return (out);
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/guid.h b/lib/libdevdctl/guid.h
new file mode 100644
index 0000000..ede414b
--- /dev/null
+++ b/lib/libdevdctl/guid.h
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_guid.h
+ *
+ * Definition of the Guid class.
+ */
+#ifndef _DEVDCTL_GUID_H_
+#define _DEVDCTL_GUID_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+/*----------------------------------- Guid -----------------------------------*/
+/**
+ * \brief Object that represents guids.
+ *
+ * It can generally be manipulated as a uint64_t, but with a special
+ * value INVALID_GUID that does not equal any valid guid.
+ *
+ * As of this writing, this class is only used to represent ZFS
+ * guids in events and spa_generate_guid() in spa_misc.c explicitly
+ * refuses to return a guid of 0. So this class uses 0 as the value
+ * for INVALID_GUID. In the future, if 0 is allowed to be a valid
+ * guid, the implementation of this class must change.
+ */
+class Guid
+{
+public:
+ /* Constructors */
+ Guid();
+ Guid(uint64_t guid);
+ Guid(const std::string &guid);
+
+ /* Assignment */
+ Guid& operator=(const Guid& rhs);
+
+ /* Test the validity of this guid. */
+ bool IsValid() const;
+
+ /* Comparison to other Guid operators */
+ bool operator==(const Guid& rhs) const;
+ bool operator!=(const Guid& rhs) const;
+
+ /* Integer conversion operators */
+ operator uint64_t() const;
+ operator bool() const;
+
+ static const uint64_t INVALID_GUID = 0;
+protected:
+ /* The integer value of the GUID. */
+ uint64_t m_GUID;
+};
+
+//- Guid Inline Public Methods ------------------------------------------------
+inline
+Guid::Guid()
+ : m_GUID(INVALID_GUID)
+{
+}
+
+inline
+Guid::Guid(uint64_t guid)
+ : m_GUID(guid)
+{
+}
+
+inline Guid&
+Guid::operator=(const Guid &rhs)
+{
+ m_GUID = rhs.m_GUID;
+ return (*this);
+}
+
+inline bool
+Guid::IsValid() const
+{
+ return (m_GUID != INVALID_GUID);
+}
+
+inline bool
+Guid::operator==(const Guid& rhs) const
+{
+ return (m_GUID == rhs.m_GUID);
+}
+
+inline bool
+Guid::operator!=(const Guid& rhs) const
+{
+ return (m_GUID != rhs.m_GUID);
+}
+
+inline
+Guid::operator uint64_t() const
+{
+ return (m_GUID);
+}
+
+inline
+Guid::operator bool() const
+{
+ return (m_GUID != INVALID_GUID);
+}
+
+/** Convert the GUID into its string representation */
+std::ostream& operator<< (std::ostream& out, Guid g);
+
+} // namespace DevdCtl
+#endif /* _DEVDCTL_GUID_H_ */
diff --git a/lib/libdevdctl/tests/Makefile b/lib/libdevdctl/tests/Makefile
new file mode 100644
index 0000000..3bbbd0d
--- /dev/null
+++ b/lib/libdevdctl/tests/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/lib/libdevdctl
+
+.PATH: ${.CURDIR}/..
+
+PLAIN_TESTS_CXX= libdevdctl_unittest
+
+SRCS.libdevdctl_unittest+= event_factory.cc \
+ libdevdctl_unittest.cc \
+ event.cc exception.cc \
+ guid.cc
+CFLAGS.libdevdctl_unittest+= -I ${LOCALBASE}/include -D_THREAD_SAFE -pthread
+DPADD.libdevdctl_unittest+= ${LIBDEVDCTL}
+LDADD.libdevdctl_unittest+= -L ${LOCALBASE}/lib -D_THREAD_SAFE -pthread -lgtest -lgtest_main
+
+# Googletest options
+LOCALBASE?= /usr/local
+
+WARNS?= 3
+.include <bsd.test.mk>
diff --git a/lib/libdevdctl/tests/libdevdctl_unittest.cc b/lib/libdevdctl/tests/libdevdctl_unittest.cc
new file mode 100644
index 0000000..4f69cb6
--- /dev/null
+++ b/lib/libdevdctl/tests/libdevdctl_unittest.cc
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+#include <gtest/gtest.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+
+using namespace DevdCtl;
+using namespace std;
+using namespace testing;
+
+#define REGISTRY_SIZE 2
+
+struct DevNameTestParams
+{
+ const char* evs;
+ bool is_disk;
+ const char* devname;
+};
+
+class DevNameTest : public TestWithParam<DevNameTestParams>{
+protected:
+ virtual void SetUp()
+ {
+ m_factory = new EventFactory();
+ m_factory->UpdateRegistry(s_registry, REGISTRY_SIZE);
+ }
+
+ virtual void TearDown()
+ {
+ if (m_ev) delete m_ev;
+ if (m_factory) delete m_factory;
+ }
+
+ EventFactory *m_factory;
+ Event *m_ev;
+ static EventFactory::Record s_registry[REGISTRY_SIZE];
+};
+
+DevdCtl::EventFactory::Record DevNameTest::s_registry[REGISTRY_SIZE] = {
+ { Event::NOTIFY, "DEVFS", &DevfsEvent::Builder },
+ { Event::NOTIFY, "GEOM", &GeomEvent::Builder }
+};
+
+TEST_P(DevNameTest, TestDevname) {
+ std::string devname;
+ DevNameTestParams param = GetParam();
+
+ string evString(param.evs);
+ m_ev = Event::CreateEvent(*m_factory, evString);
+ m_ev->DevName(devname);
+ EXPECT_STREQ(param.devname, devname.c_str());
+}
+
+TEST_P(DevNameTest, TestIsDiskDev) {
+ DevNameTestParams param = GetParam();
+
+ string evString(param.evs);
+ m_ev = Event::CreateEvent(*m_factory, evString);
+ EXPECT_EQ(param.is_disk, m_ev->IsDiskDev());
+}
+
+/* TODO: clean this up using C++-11 uniform initializers */
+INSTANTIATE_TEST_CASE_P(IsDiskDevTestInstantiation, DevNameTest, Values(
+ (DevNameTestParams){
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=da6\n",
+ .is_disk = true, .devname = "da6"},
+ (DevNameTestParams){.is_disk = false, .devname = "cuau0",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=cuau0\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "ada6",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=ada6\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "da6p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=da6p1\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "ada6p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=ada6p1\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "da6s0p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=da6s0p1\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "ada6s0p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=ada6s0p1\n"},
+ /*
+ * Test physical path nodes. These are currently all set to false since
+ * physical path nodes are implemented with symlinks, and most CAM and
+ * ZFS operations can't use symlinked device nodes
+ */
+ /* A SpectraBSD-style physical path node*/
+ (DevNameTestParams){.is_disk = false, .devname = "enc@50030480019f53fd/elmtype@array_device/slot@18/da",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@50030480019f53fd/elmtype@array_device/slot@18/da\n"},
+ (DevNameTestParams){.is_disk = false, .devname = "enc@50030480019f53fd/elmtype@array_device/slot@18/pass",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@50030480019f53fd/elmtype@array_device/slot@18/pass\n"},
+ /* A FreeBSD-style physical path node */
+ (DevNameTestParams){.is_disk = true, .devname = "enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/da6",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/da6\n"},
+ (DevNameTestParams){.is_disk = false, .devname = "enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/pass6",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/pass6\n"},
+
+ /*
+ * Test some GEOM events
+ */
+ (DevNameTestParams){.is_disk = true, .devname = "da5",
+ .evs = "!system=GEOM subsystem=disk type=GEOM::physpath devname=da5\n"})
+);
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index f80404d..0c575d0 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -114,6 +114,7 @@ __FBSDID("$FreeBSD$");
#define HTTP_REDIRECT(xyz) ((xyz) == HTTP_MOVED_PERM \
|| (xyz) == HTTP_MOVED_TEMP \
|| (xyz) == HTTP_TEMP_REDIRECT \
+ || (xyz) == HTTP_PERM_REDIRECT \
|| (xyz) == HTTP_USE_PROXY \
|| (xyz) == HTTP_SEE_OTHER)
@@ -1767,6 +1768,8 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
break;
case HTTP_MOVED_PERM:
case HTTP_MOVED_TEMP:
+ case HTTP_TEMP_REDIRECT:
+ case HTTP_PERM_REDIRECT:
case HTTP_SEE_OTHER:
case HTTP_USE_PROXY:
/*
diff --git a/lib/libmd/Makefile b/lib/libmd/Makefile
index bde4fb5..bb50623 100644
--- a/lib/libmd/Makefile
+++ b/lib/libmd/Makefile
@@ -9,12 +9,15 @@ SRCS= md4c.c md5c.c md4hl.c md5hl.c \
sha0c.c sha0hl.c sha1c.c sha1hl.c \
sha256c.c sha256hl.c \
sha384hl.c \
- sha512c.c sha512hl.c
-INCS= md4.h md5.h ripemd.h sha.h sha256.h sha384.h sha512.h
+ sha512c.c sha512hl.c sha512thl.c \
+ skein.c skein_block.c \
+ skein256hl.c skein512hl.c skein1024hl.c
+INCS= md4.h md5.h ripemd.h sha.h sha256.h sha384.h sha512.h sha512t.h \
+ skein.h skein_port.h skein_freebsd.h skein_iv.h
WARNS?= 0
-MAN+= md4.3 md5.3 ripemd.3 sha.3 sha256.3 sha512.3
+MAN+= md4.3 md5.3 ripemd.3 sha.3 sha256.3 sha512.3 skein.3
MLINKS+=md4.3 MD4Init.3 md4.3 MD4Update.3 md4.3 MD4Final.3
MLINKS+=md4.3 MD4End.3 md4.3 MD4File.3 md4.3 MD4FileChunk.3
MLINKS+=md4.3 MD4Data.3
@@ -43,11 +46,31 @@ MLINKS+=sha512.3 SHA512_Init.3 sha512.3 SHA512_Update.3
MLINKS+=sha512.3 SHA512_Final.3 sha512.3 SHA512_End.3
MLINKS+=sha512.3 SHA512_File.3 sha512.3 SHA512_FileChunk.3
MLINKS+=sha512.3 SHA512_Data.3
+MLINKS+=sha512.3 SHA512_256_Init.3 sha512.3 SHA512_256_Update.3
+MLINKS+=sha512.3 SHA512_256_Final.3 sha512.3 SHA512_256_End.3
+MLINKS+=sha512.3 SHA512_256_File.3 sha512.3 SHA512_256_FileChunk.3
+MLINKS+=sha512.3 SHA512_256_Data.3
+MLINKS+=skein.3 SKEIN256_Init.3 skein.3 SKEIN256_Update.3
+MLINKS+=skein.3 SKEIN256_Final.3 skein.3 SKEIN256_End.3
+MLINKS+=skein.3 SKEIN256_File.3 skein.3 SKEIN256_FileChunk.3
+MLINKS+=skein.3 SKEIN256_Data.3 skein.3 skein256.3
+MLINKS+=skein.3 SKEIN512_Init.3 skein.3 SKEIN512_Update.3
+MLINKS+=skein.3 SKEIN512_Final.3 skein.3 SKEIN512_End.3
+MLINKS+=skein.3 SKEIN512_File.3 skein.3 SKEIN512_FileChunk.3
+MLINKS+=skein.3 SKEIN512_Data.3 skein.3 skein512.3
+MLINKS+=skein.3 SKEIN1024_Init.3 skein.3 SKEIN1024_Update.3
+MLINKS+=skein.3 SKEIN1024_Final.3 skein.3 SKEIN1024_End.3
+MLINKS+=skein.3 SKEIN1024_File.3 skein.3 SKEIN1024_FileChunk.3
+MLINKS+=skein.3 SKEIN1024_Data.3 skein.3 skein1024.3
+
CLEANFILES+= md[245]hl.c md[245].ref md[245].3 mddriver \
rmd160.ref rmd160hl.c rmddriver \
sha0.ref sha0hl.c sha1.ref sha1hl.c shadriver \
sha256.ref sha256hl.c sha384hl.c sha384.ref \
- sha512.ref sha512hl.c
+ sha512.ref sha512hl.c sha512t256.ref sha512thl.c \
+ skein256hl.c skein512hl.c skein1024hl.c \
+ skein256.ref skein512.ref skein1024.ref \
+ skeindriver
# Define WEAK_REFS to provide weak aliases for libmd symbols
#
@@ -56,8 +79,10 @@ CLEANFILES+= md[245]hl.c md[245].ref md[245].3 mddriver \
# * macros are used to rename symbols to libcrypt internal names
# * no weak aliases are generated
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys/crypto/sha2
+CFLAGS+= -I${.CURDIR}/../../sys/crypto/skein
CFLAGS+= -DWEAK_REFS
.PATH: ${.CURDIR}/${MACHINE_ARCH} ${.CURDIR}/../../sys/crypto/sha2
+.PATH: ${.CURDIR}/../../sys/crypto/skein ${.CURDIR}/../../sys/crypto/skein/${MACHINE_ARCH}
.if exists(${MACHINE_ARCH}/sha.S)
SRCS+= sha.S
@@ -67,7 +92,11 @@ CFLAGS+= -DSHA1_ASM
SRCS+= rmd160.S
CFLAGS+= -DRMD160_ASM
.endif
-.if exists(${MACHINE_ARCH}/sha.S) || exists(${MACHINE_ARCH}/rmd160.S)
+.if exists(${MACHINE_ARCH}/skein_block_asm.s)
+SRCS+= skein_block_asm.s
+CFLAGS+= -DSKEIN_ASM -DSKEIN_USE_ASM=1792 # list of block functions to replace with assembly: 256+512+1024 = 1792
+.endif
+.if exists(${MACHINE_ARCH}/sha.S) || exists(${MACHINE_ARCH}/rmd160.S) || exists(${MACHINE_ARCH}/skein_block_asm.s)
ACFLAGS+= -DELF -Wa,--noexecstack
.endif
@@ -107,12 +136,38 @@ sha512hl.c: mdXhl.c
-e 's/SHA512__/SHA512_/g' \
${.ALLSRC}) > ${.TARGET}
+sha512thl.c: mdXhl.c
+ (echo '#define LENGTH 32'; \
+ sed -e 's/mdX/sha512t/g' -e 's/MDX/SHA512_256_/g' \
+ -e 's/SHA512_256__/SHA512_256_/g' \
+ -e 's/SHA512_256_CTX/SHA512_CTX/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
rmd160hl.c: mdXhl.c
(echo '#define LENGTH 20'; \
sed -e 's/mdX/ripemd/g' -e 's/MDX/RIPEMD160_/g' \
-e 's/RIPEMD160__/RIPEMD160_/g' \
${.ALLSRC}) > ${.TARGET}
+skein256hl.c: mdXhl.c
+ (echo '#define LENGTH 32'; \
+ sed -e 's/mdX/skein/g' -e 's/MDX/SKEIN256_/g' \
+ -e 's/SKEIN256__/SKEIN256_/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
+skein512hl.c: mdXhl.c
+ (echo '#define LENGTH 64'; \
+ sed -e 's/mdX/skein/g' -e 's/MDX/SKEIN512_/g' \
+ -e 's/SKEIN512__/SKEIN512_/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
+skein1024hl.c: mdXhl.c
+ (echo '#define LENGTH 128'; \
+ sed -e 's/mdX/skein/g' -e 's/MDX/SKEIN1024_/g' \
+ -e 's/SKEIN1024__/SKEIN1024_/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
+
.for i in 2 4 5
md${i}.3: ${.CURDIR}/mdX.3
sed -e "s/mdX/md${i}/g" -e "s/MDX/MD${i}/g" ${.ALLSRC} > ${.TARGET}
@@ -211,6 +266,21 @@ sha512.ref:
@echo 'SHA-512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
'72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843' >> ${.TARGET}
+sha512t256.ref:
+ echo 'SHA-512256 test suite:' > ${.TARGET}
+ @echo 'SHA-512256 ("") =' \
+ 'c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a' >> ${.TARGET}
+ @echo 'SHA-512256 ("abc") =' \
+ '53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23' >> ${.TARGET}
+ @echo 'SHA-512256 ("message digest") =' \
+ '0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb' >> ${.TARGET}
+ @echo 'SHA-512256 ("abcdefghijklmnopqrstuvwxyz") =' \
+ 'fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26' >> ${.TARGET}
+ @echo 'SHA-512256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ 'cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8' >> ${.TARGET}
+ @echo 'SHA-512256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ '2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148' >> ${.TARGET}
+
rmd160.ref:
echo 'RIPEMD160 test suite:' > ${.TARGET}
@echo 'RIPEMD160 ("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31' >> ${.TARGET}
@@ -224,8 +294,51 @@ rmd160.ref:
@echo 'RIPEMD160 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
'9b752e45573d4b39f4dbd3323cab82bf63326bfb' >> ${.TARGET}
+skein256.ref:
+ echo 'SKEIN256 test suite:' > ${.TARGET}
+ @echo 'SKEIN256 ("") = c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba' >> ${.TARGET}
+ @echo 'SKEIN256 ("abc") = 258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870' >> ${.TARGET}
+ @echo 'SKEIN256 ("message digest") =' \
+ '4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488' >> ${.TARGET}
+ @echo 'SKEIN256 ("abcdefghijklmnopqrstuvwxyz") =' \
+ '46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82' >> ${.TARGET}
+ @echo 'SKEIN256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ '7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2' >> ${.TARGET}
+ @echo 'SKEIN256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ '4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d' >> ${.TARGET}
+
+skein512.ref:
+ echo 'SKEIN512 test suite:' > ${.TARGET}
+ @echo 'SKEIN512 ("") =' \
+ 'bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a' >> ${.TARGET}
+ @echo 'SKEIN512 ("abc") =' \
+ '8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75' >> ${.TARGET}
+ @echo 'SKEIN512 ("message digest") =' \
+ '15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc' >> ${.TARGET}
+ @echo 'SKEIN512 ("abcdefghijklmnopqrstuvwxyz") =' \
+ '23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c' >> ${.TARGET}
+ @echo 'SKEIN512 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ '0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c' >> ${.TARGET}
+ @echo 'SKEIN512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ '2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce' >> ${.TARGET}
+
+skein1024.ref:
+ echo 'SKEIN1024 test suite:' > ${.TARGET}
+ @echo 'SKEIN1024 ("") =' \
+ '0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6' >> ${.TARGET}
+ @echo 'SKEIN1024 ("abc") =' \
+ '35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f' >> ${.TARGET}
+ @echo 'SKEIN1024 ("message digest") =' \
+ 'ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458' >> ${.TARGET}
+ @echo 'SKEIN1024 ("abcdefghijklmnopqrstuvwxyz") =' \
+ 'f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f' >> ${.TARGET}
+ @echo 'SKEIN1024 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ 'cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469' >> ${.TARGET}
+ @echo 'SKEIN1024 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ 'cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a' >> ${.TARGET}
+
test: md4.ref md5.ref sha0.ref rmd160.ref sha1.ref sha256.ref sha384.ref \
- sha512.ref
+ sha512.ref sha512t256.ref skein256.ref skein512.ref skein1024.ref
@${ECHO} if any of these test fail, the code produces wrong results
@${ECHO} and should NOT be used.
${CC} ${CFLAGS} ${LDFLAGS} -DMD=4 -o mddriver ${.CURDIR}/mddriver.c libmd.a
@@ -254,6 +367,19 @@ test: md4.ref md5.ref sha0.ref rmd160.ref sha1.ref sha256.ref sha384.ref \
${CC} ${CFLAGS} ${LDFLAGS} -DSHA=512 -o shadriver ${.CURDIR}/shadriver.c libmd.a
./shadriver | cmp sha512.ref -
@${ECHO} SHA-512 passed test
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSHA=512256 -o shadriver ${.CURDIR}/shadriver.c libmd.a
+ ./shadriver | cmp sha512t256.ref -
+ @${ECHO} SHA-512t256 passed test
-rm -f shadriver
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSKEIN=256 -o skeindriver ${.CURDIR}/skeindriver.c libmd.a
+ ./skeindriver | cmp skein256.ref -
+ @${ECHO} SKEIN256 passed test
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSKEIN=512 -o skeindriver ${.CURDIR}/skeindriver.c libmd.a
+ ./skeindriver | cmp skein512.ref -
+ @${ECHO} SKEIN512 passed test
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSKEIN=1024 -o skeindriver ${.CURDIR}/skeindriver.c libmd.a
+ ./skeindriver | cmp skein1024.ref -
+ @${ECHO} SKEIN1024 passed test
+ -rm -f skeindriver
.include <bsd.lib.mk>
diff --git a/lib/libmd/mdX.3 b/lib/libmd/mdX.3
index 4cc321f..daa5c36 100644
--- a/lib/libmd/mdX.3
+++ b/lib/libmd/mdX.3
@@ -8,7 +8,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 11, 1999
+.Dd April 26, 2016
.Dt MDX 3
.Os
.Sh NAME
@@ -145,7 +145,11 @@ argument is non-null it must point to at least 33 characters of buffer space.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
-.Xr sha 3
+.Xr ripemd 3 ,
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Rs
.%A R. Rivest
.%T The MD4 Message-Digest Algorithm
diff --git a/lib/libmd/ripemd.3 b/lib/libmd/ripemd.3
index 2c9d2d3..8e868b8 100644
--- a/lib/libmd/ripemd.3
+++ b/lib/libmd/ripemd.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd March 28, 2014
+.Dd April 26, 2016
.Dt RIPEMD 3
.Os
.Sh NAME
@@ -125,7 +125,10 @@ argument is non-null it must point to at least 41 characters of buffer space.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
-.Xr sha 3
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 4.0 .
diff --git a/lib/libmd/sha.3 b/lib/libmd/sha.3
index fe5c339..95c0603 100644
--- a/lib/libmd/sha.3
+++ b/lib/libmd/sha.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd March 28, 2014
+.Dd April 26, 2016
.Dt SHA 3
.Os
.Sh NAME
@@ -157,7 +157,9 @@ argument is non-null it must point to at least 41 characters of buffer space.
.Xr md4 3 ,
.Xr md5 3 ,
.Xr ripemd 3 ,
-.Xr sha256 3
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 4.0 .
diff --git a/lib/libmd/sha256.3 b/lib/libmd/sha256.3
index 6117e70..530c644 100644
--- a/lib/libmd/sha256.3
+++ b/lib/libmd/sha256.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd March 28, 2014
+.Dd April 26, 2016
.Dt SHA256 3
.Os
.Sh NAME
@@ -123,7 +123,10 @@ argument is non-null it must point to at least 65 characters of buffer space.
.Xr md4 3 ,
.Xr md5 3 ,
.Xr ripemd 3 ,
-.Xr sha 3
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 6.0 .
diff --git a/lib/libmd/sha512.3 b/lib/libmd/sha512.3
index d6b3aaf..d718ada 100644
--- a/lib/libmd/sha512.3
+++ b/lib/libmd/sha512.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd October 17, 2015
+.Dd April 22, 2016
.Dt SHA512 3
.Os
.Sh NAME
@@ -26,7 +26,14 @@
.Nm SHA384_End ,
.Nm SHA384_File ,
.Nm SHA384_FileChunk ,
-.Nm SHA384_Data
+.Nm SHA384_Data,
+.Nm SHA512_256_Init ,
+.Nm SHA512_256_Update ,
+.Nm SHA512_256_Final ,
+.Nm SHA512_256_End ,
+.Nm SHA512_256_File ,
+.Nm SHA512_256_FileChunk ,
+.Nm SHA512_256_Data
.Nd calculate the FIPS 180-4 ``SHA-512'' family of message digests
.Sh LIBRARY
.Lb libmd
@@ -47,6 +54,7 @@
.Fn SHA512_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *"
.Fn SHA512_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.In sha384.h
.Ft void
.Fn SHA384_Init "SHA384_CTX *context"
.Ft void
@@ -61,6 +69,21 @@
.Fn SHA384_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *"
.Fn SHA384_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.In sha512t.h
+.Ft void
+.Fn SHA512_256_Init "SHA512_CTX *context"
+.Ft void
+.Fn SHA512_256_Update "SHA512_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SHA512_256_Final "unsigned char digest[32]" "SHA512_CTX *context"
+.Ft "char *"
+.Fn SHA512_256_End "SHA512_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA512_256_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA512_256_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SHA512_256_Data "const unsigned char *data" "unsigned int len" "char *buf"
.Sh DESCRIPTION
The
.Li SHA512_
@@ -92,7 +115,7 @@ and finally extract the result using
.Fn SHA512_End
is a wrapper for
.Fn SHA512_Final
-which converts the return value to a 65-character
+which converts the return value to a 129-character
(including the terminating '\e0')
.Tn ASCII
string which represents the 512 bits in hexadecimal.
@@ -139,27 +162,40 @@ and subsequently must be explicitly deallocated using
after use.
If the
.Fa buf
-argument is non-null it must point to at least 65 characters of buffer space.
+argument is non-null it must point to at least 129 characters of buffer space.
.Pp
The
.Li SHA384_
+and
+.Li SHA512_256_
functions are identical to the
.Li SHA512_
functions except they use a different initial hash value and the output is
-truncated to 384 bits.
+truncated to 384 bits and 256 bits respectively.
.Pp
.Fn SHA384_End
is a wrapper for
.Fn SHA384_Final
-which converts the return value to a 49-character
+which converts the return value to a 97-character
(including the terminating '\e0')
.Tn ASCII
string which represents the 384 bits in hexadecimal.
+.Pp
+.Fn SHA512_256_End
+is a wrapper for
+.Fn SHA512_Final
+which converts the return value to a 65-character
+(including the terminating '\e0')
+.Tn ASCII
+string which represents the 256 bits in hexadecimal.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
.Xr ripemd 3 ,
-.Xr sha 3
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 9.0 .
diff --git a/lib/libmd/shadriver.c b/lib/libmd/shadriver.c
index e7e7b5d..b643f96 100644
--- a/lib/libmd/shadriver.c
+++ b/lib/libmd/shadriver.c
@@ -24,6 +24,7 @@ __FBSDID("$FreeBSD$");
#include "sha256.h"
#include "sha384.h"
#include "sha512.h"
+#include "sha512t.h"
/* The following makes SHA default to SHA-1 if it has not already been
* defined with C compiler flags. */
@@ -43,6 +44,9 @@ __FBSDID("$FreeBSD$");
#elif SHA == 512
#undef SHA_Data
#define SHA_Data SHA512_Data
+#elif SHA == 512256
+#undef SHA_Data
+#define SHA_Data SHA512_256_Data
#endif
/* Digests a string and prints the result. */
diff --git a/lib/libmd/skein.3 b/lib/libmd/skein.3
new file mode 100644
index 0000000..11c78a7
--- /dev/null
+++ b/lib/libmd/skein.3
@@ -0,0 +1,214 @@
+.\"-
+.\" Copyright (c) 2016 Allan Jude
+.\" 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$
+.\"
+.Dd May 28, 2016
+.Dt SKEIN 3
+.Os
+.Sh NAME
+.Nm SKEIN256_Init ,
+.Nm SKEIN256_Update ,
+.Nm SKEIN256_Final ,
+.Nm SKEIN256_End ,
+.Nm SKEIN256_File ,
+.Nm SKEIN256_FileChunk ,
+.Nm SKEIN256_Data ,
+.Nm SKEIN512_Init ,
+.Nm SKEIN512_Update ,
+.Nm SKEIN512_Final ,
+.Nm SKEIN512_End ,
+.Nm SKEIN512_File ,
+.Nm SKEIN512_FileChunk ,
+.Nm SKEIN512_Data ,
+.Nm SKEIN1024_Init ,
+.Nm SKEIN1024_Update ,
+.Nm SKEIN1024_Final ,
+.Nm SKEIN1024_End ,
+.Nm SKEIN1024_File ,
+.Nm SKEIN1024_FileChunk ,
+.Nm SKEIN1024_Data
+.Nd calculate the ``SKEIN'' family of message digests
+.Sh LIBRARY
+.Lb libmd
+.Sh SYNOPSIS
+.In sys/types.h
+.In skein.h
+.Ft void
+.Fn SKEIN256_Init "SKEIN256_CTX *context"
+.Ft void
+.Fn SKEIN256_Update "SKEIN256_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SKEIN256_Final "unsigned char digest[32]" "SKEIN256_CTX *context"
+.Ft "char *"
+.Fn SKEIN256_End "SKEIN256_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SKEIN256_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SKEIN256_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SKEIN256_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.Ft void
+.Fn SKEIN512_Init "SKEIN512_CTX *context"
+.Ft void
+.Fn SKEIN512_Update "SKEIN512_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SKEIN512_Final "unsigned char digest[64]" "SKEIN512_CTX *context"
+.Ft "char *"
+.Fn SKEIN512_End "SKEIN512_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SKEIN512_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SKEIN512_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SKEIN512_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.Ft void
+.Fn SKEIN1024_Init "SKEIN1024_CTX *context"
+.Ft void
+.Fn SKEIN1024_Update "SKEIN1024_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SKEIN1024_Final "unsigned char digest[128]" "SKEIN1024_CTX *context"
+.Ft "char *"
+.Fn SKEIN1024_End "SKEIN1024_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SKEIN1024_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SKEIN1024_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SKEIN1024_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.Sh DESCRIPTION
+.Li Skein
+is a new family of cryptographic hash functions based on the
+.Li Threefish
+large-block cipher.
+Its design combines speed, security, simplicity, and a great deal of
+flexibility in a modular package that is easy to analyze.
+.Li Skein
+is defined for three different internal state sizes\(em256 bits, 512 bits, and
+1024 bits\(emand any output size.
+This allows Skein to be a drop-in replacement for the entire SHA family
+of hash functions.
+.Pp
+The
+.Fn SKEIN256_Init ,
+.Fn SKEIN256_Update ,
+and
+.Fn SKEIN256_Final
+functions are the core functions.
+Allocate an
+.Vt SKEIN256_CTX ,
+initialize it with
+.Fn SKEIN256_Init ,
+run over the data with
+.Fn SKEIN256_Update ,
+and finally extract the result using
+.Fn SKEIN256_Final .
+.Pp
+.Fn SKEIN256_End
+is a wrapper for
+.Fn SKEIN256_Final
+which converts the return value to a 33-character
+(including the terminating '\e0')
+.Tn ASCII
+string which represents the 256 bits in hexadecimal.
+.Pp
+.Fn SKEIN256_File
+calculates the digest of a file, and uses
+.Fn SKEIN256_End
+to return the result.
+If the file cannot be opened, a null pointer is returned.
+.Fn SKEIN256_FileChunk
+is similar to
+.Fn SKEIN256_File ,
+but it only calculates the digest over a byte-range of the file specified,
+starting at
+.Fa offset
+and spanning
+.Fa length
+bytes.
+If the
+.Fa length
+parameter is specified as 0, or more than the length of the remaining part
+of the file,
+.Fn SKEIN256_FileChunk
+calculates the digest from
+.Fa offset
+to the end of file.
+.Fn SKEIN256_Data
+calculates the digest of a chunk of data in memory, and uses
+.Fn SKEIN256_End
+to return the result.
+.Pp
+When using
+.Fn SKEIN256_End ,
+.Fn SKEIN256_File ,
+or
+.Fn SKEIN256_Data ,
+the
+.Fa buf
+argument can be a null pointer, in which case the returned string
+is allocated with
+.Xr malloc 3
+and subsequently must be explicitly deallocated using
+.Xr free 3
+after use.
+If the
+.Fa buf
+argument is non-null it must point to at least 33 characters of buffer space.
+.Pp
+The
+.Li SKEIN512_
+and
+.Li SKEIN1024_
+functions are similar to the
+.Li SKEIN256_
+functions except they produce a 512-bit, 65 character,
+or 1024-bit, 129 character, output.
+.Sh SEE ALSO
+.Xr md4 3 ,
+.Xr md5 3 ,
+.Xr ripemd 3 ,
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3
+.Sh HISTORY
+These functions appeared in
+.Fx 11.0 .
+.Sh AUTHORS
+.An -nosplit
+The core hash routines were imported from version 1.3 of the optimized
+Skein reference implementation written by
+.An Doug Whiting
+as submitted to the NSA SHA-3 contest.
+The algorithms were developed by
+.An Niels Ferguson ,
+.An Stefan Lucks ,
+.An Bruce Schneier ,
+.An Doug Whiting ,
+.An Mihir Bellare ,
+.An Tadayoshi Kohno ,
+.An Jon Callas,
+and
+.An Jesse Walker .
diff --git a/lib/libmd/skeindriver.c b/lib/libmd/skeindriver.c
new file mode 100644
index 0000000..5960457
--- /dev/null
+++ b/lib/libmd/skeindriver.c
@@ -0,0 +1,68 @@
+/* SKEINDRIVER.C - test driver for SKEIN */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights
+ * reserved.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software. */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+#include "skein.h"
+
+/* The following makes SKEIN default to SKEIN512 if it has not already been
+ * defined with C compiler flags. */
+#ifndef SKEIN
+#define SKEIN 512
+#endif
+
+#if SKEIN == 256
+#undef SKEIN_Data
+#define SKEIN_Data SKEIN256_Data
+#elif SKEIN == 512
+#undef SKEIN_Data
+#define SKEIN_Data SKEIN512_Data
+#elif SKEIN == 1024
+#undef SKEIN_Data
+#define SKEIN_Data SKEIN1024_Data
+#endif
+
+/* Digests a string and prints the result. */
+static void
+SKEINString(char *string)
+{
+ char buf[2*128 + 1];
+
+ printf("SKEIN%d (\"%s\") = %s\n",
+ SKEIN, string, SKEIN_Data(string, strlen(string), buf));
+}
+
+/* Digests a reference suite of strings and prints the results. */
+int
+main(void)
+{
+ printf("SKEIN%d test suite:\n", SKEIN);
+
+ SKEINString("");
+ SKEINString("abc");
+ SKEINString("message digest");
+ SKEINString("abcdefghijklmnopqrstuvwxyz");
+ SKEINString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz0123456789");
+ SKEINString("1234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890");
+
+ return 0;
+}
diff --git a/lib/libthr/libthr.3 b/lib/libthr/libthr.3
index 2b79e95..8b3f9cc 100644
--- a/lib/libthr/libthr.3
+++ b/lib/libthr/libthr.3
@@ -47,9 +47,7 @@ library provides a 1:1 implementation of the
library interfaces for application threading.
It
has been optimized for use by applications expecting system scope thread
-semantics, and can provide significant performance improvements
-compared to
-.Lb libkse .
+semantics.
.Pp
The library is tightly integrated with the run-time link editor
.Xr ld-elf.so.1 1
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c
index 4d9356a..506b8ec 100644
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -69,18 +69,18 @@ __weak_reference(_pthread_cond_destroy, pthread_cond_destroy);
__weak_reference(_pthread_cond_signal, pthread_cond_signal);
__weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast);
-#define CV_PSHARED(cvp) (((cvp)->__flags & USYNC_PROCESS_SHARED) != 0)
+#define CV_PSHARED(cvp) (((cvp)->kcond.c_flags & USYNC_PROCESS_SHARED) != 0)
static void
cond_init_body(struct pthread_cond *cvp, const struct pthread_cond_attr *cattr)
{
if (cattr == NULL) {
- cvp->__clock_id = CLOCK_REALTIME;
+ cvp->kcond.c_clockid = CLOCK_REALTIME;
} else {
if (cattr->c_pshared)
- cvp->__flags |= USYNC_PROCESS_SHARED;
- cvp->__clock_id = cattr->c_clockid;
+ cvp->kcond.c_flags |= USYNC_PROCESS_SHARED;
+ cvp->kcond.c_clockid = cattr->c_clockid;
}
}
@@ -205,9 +205,8 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
if (cancel)
_thr_cancel_enter2(curthread, 0);
- error = _thr_ucond_wait((struct ucond *)&cvp->__has_kern_waiters,
- (struct umutex *)&mp->m_lock, abstime, CVWAIT_ABSTIME |
- CVWAIT_CLOCKID);
+ error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
+ CVWAIT_ABSTIME | CVWAIT_CLOCKID);
if (cancel)
_thr_cancel_leave(curthread, 0);
@@ -259,7 +258,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
curthread = _get_curthread();
if (curthread->wchan != NULL)
- PANIC("thread was already on queue.");
+ PANIC("thread %p was already on queue.", curthread);
if (cancel)
_thr_testcancel(curthread);
@@ -292,7 +291,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
if (cancel)
_thr_cancel_enter2(curthread, 0);
- error = _thr_sleep(curthread, cvp->__clock_id, abstime);
+ error = _thr_sleep(curthread, cvp->kcond.c_clockid, abstime);
if (cancel)
_thr_cancel_leave(curthread, 0);
@@ -349,8 +348,7 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
if (curthread->attr.sched_policy != SCHED_OTHER ||
(mp->m_lock.m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT |
- USYNC_PROCESS_SHARED)) != 0 ||
- (cvp->__flags & USYNC_PROCESS_SHARED) != 0)
+ USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp))
return (cond_wait_kernel(cvp, mp, abstime, cancel));
else
return (cond_wait_user(cvp, mp, abstime, cancel));
@@ -413,7 +411,7 @@ cond_signal_common(pthread_cond_t *cond)
pshared = CV_PSHARED(cvp);
- _thr_ucond_signal((struct ucond *)&cvp->__has_kern_waiters);
+ _thr_ucond_signal(&cvp->kcond);
if (pshared || cvp->__has_user_waiters == 0)
return (0);
@@ -496,7 +494,7 @@ cond_broadcast_common(pthread_cond_t *cond)
pshared = CV_PSHARED(cvp);
- _thr_ucond_broadcast((struct ucond *)&cvp->__has_kern_waiters);
+ _thr_ucond_broadcast(&cvp->kcond);
if (pshared || cvp->__has_user_waiters == 0)
return (0);
diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c
index e76623c..3ead7ff 100644
--- a/lib/libthr/thread/thr_exit.c
+++ b/lib/libthr/thread/thr_exit.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#ifdef _PTHREAD_FORCED_UNWIND
#include <dlfcn.h>
#endif
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
@@ -172,18 +173,31 @@ thread_unwind(void)
#endif
void
-_thread_exit(const char *fname, int lineno, const char *msg)
+_thread_exitf(const char *fname, int lineno, const char *fmt, ...)
{
+ va_list ap;
/* Write an error message to the standard error file descriptor: */
- _thread_printf(2,
- "Fatal error '%s' at line %d in file %s (errno = %d)\n",
- msg, lineno, fname, errno);
+ _thread_printf(STDERR_FILENO, "Fatal error '");
+
+ va_start(ap, fmt);
+ _thread_vprintf(STDERR_FILENO, fmt, ap);
+ va_end(ap);
+
+ _thread_printf(STDERR_FILENO, "' at line %d in file %s (errno = %d)\n",
+ lineno, fname, errno);
abort();
}
void
+_thread_exit(const char *fname, int lineno, const char *msg)
+{
+
+ _thread_exitf(fname, lineno, "%s", msg);
+}
+
+void
_pthread_exit(void *status)
{
_pthread_exit_mask(status, NULL);
@@ -195,13 +209,10 @@ _pthread_exit_mask(void *status, sigset_t *mask)
struct pthread *curthread = _get_curthread();
/* Check if this thread is already in the process of exiting: */
- if (curthread->cancelling) {
- char msg[128];
- snprintf(msg, sizeof(msg), "Thread %p has called "
+ if (curthread->cancelling)
+ PANIC("Thread %p has called "
"pthread_exit() from a destructor. POSIX 1003.1 "
"1996 s16.2.5.2 does not allow this!", curthread);
- PANIC(msg);
- }
/* Flag this thread as exiting. */
curthread->cancelling = 1;
@@ -298,7 +309,7 @@ exit_thread(void)
#if defined(_PTHREADS_INVARIANTS)
if (THR_IN_CRITICAL(curthread))
- PANIC("thread exits with resources held!");
+ PANIC("thread %p exits with resources held!", curthread);
#endif
/*
* Kernel will do wakeup at the address, so joiner thread
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
index 2d507e7..5a99605 100644
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -135,13 +135,9 @@ mutex_assert_is_owned(struct pthread_mutex *m __unused)
{
#if defined(_PTHREADS_INVARIANTS)
- if (__predict_false(m->m_qe.tqe_prev == NULL)) {
- char msg[128];
- snprintf(msg, sizeof(msg),
- "mutex %p own %#x is not on list %p %p",
+ if (__predict_false(m->m_qe.tqe_prev == NULL))
+ PANIC("mutex %p own %#x is not on list %p %p",
m, m->m_lock.m_owner, m->m_qe.tqe_prev, m->m_qe.tqe_next);
- PANIC(msg);
- }
#endif
}
@@ -152,27 +148,20 @@ mutex_assert_not_owned(struct pthread *curthread __unused,
#if defined(_PTHREADS_INVARIANTS)
if (__predict_false(m->m_qe.tqe_prev != NULL ||
- m->m_qe.tqe_next != NULL)) {
- char msg[128];
- snprintf(msg, sizeof(msg),
- "mutex %p own %#x is on list %p %p",
+ m->m_qe.tqe_next != NULL))
+ PANIC("mutex %p own %#x is on list %p %p",
m, m->m_lock.m_owner, m->m_qe.tqe_prev, m->m_qe.tqe_next);
- PANIC(msg);
- }
if (__predict_false(is_robust_mutex(m) &&
(m->m_lock.m_rb_lnk != 0 || m->m_rb_prev != NULL ||
(is_pshared_mutex(m) && curthread->robust_list ==
(uintptr_t)&m->m_lock) ||
(!is_pshared_mutex(m) && curthread->priv_robust_list ==
- (uintptr_t)&m->m_lock)))) {
- char msg[128];
- snprintf(msg, sizeof(msg),
+ (uintptr_t)&m->m_lock))))
+ PANIC(
"mutex %p own %#x is on robust linkage %p %p head %p phead %p",
m, m->m_lock.m_owner, (void *)m->m_lock.m_rb_lnk,
m->m_rb_prev, (void *)curthread->robust_list,
(void *)curthread->priv_robust_list);
- PANIC(msg);
- }
#endif
}
diff --git a/lib/libthr/thread/thr_printf.c b/lib/libthr/thread/thr_printf.c
index ed94287..d38ee18 100644
--- a/lib/libthr/thread/thr_printf.c
+++ b/lib/libthr/thread/thr_printf.c
@@ -52,23 +52,35 @@ static void pstr(int fd, const char *s);
void
_thread_printf(int fd, const char *fmt, ...)
{
+ va_list ap;
+
+ va_start(ap, fmt);
+ _thread_vprintf(fd, fmt, ap);
+ va_end(ap);
+}
+
+void
+_thread_vprintf(int fd, const char *fmt, va_list ap)
+{
static const char digits[16] = "0123456789abcdef";
- va_list ap;
char buf[20];
char *s;
unsigned long r, u;
int c;
long d;
- int islong;
+ int islong, isalt;
- va_start(ap, fmt);
while ((c = *fmt++)) {
+ isalt = 0;
islong = 0;
if (c == '%') {
next: c = *fmt++;
if (c == '\0')
- goto out;
+ return;
switch (c) {
+ case '#':
+ isalt = 1;
+ goto next;
case 'c':
pchar(fd, va_arg(ap, int));
continue;
@@ -79,10 +91,13 @@ next: c = *fmt++;
islong = 1;
goto next;
case 'p':
+ pstr(fd, "0x");
islong = 1;
case 'd':
case 'u':
case 'x':
+ if (c == 'x' && isalt)
+ pstr(fd, "0x");
r = ((c == 'u') || (c == 'd')) ? 10 : 16;
if (c == 'd') {
if (islong)
@@ -111,8 +126,6 @@ next: c = *fmt++;
}
pchar(fd, c);
}
-out:
- va_end(ap);
}
/*
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 21399f3..02b575d 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -86,7 +86,7 @@ TAILQ_HEAD(mutex_queue, pthread_mutex);
/*
* Kernel fatal error handler macro.
*/
-#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
+#define PANIC(args...) _thread_exitf(__FILE__, __LINE__, ##args)
/* Output debug messages like this: */
#define stdout_debug(args...) _thread_printf(STDOUT_FILENO, ##args)
@@ -190,9 +190,7 @@ struct pthread_mutex_attr {
struct pthread_cond {
__uint32_t __has_user_waiters;
- __uint32_t __has_kern_waiters;
- __uint32_t __flags;
- __uint32_t __clock_id;
+ struct ucond kcond;
};
struct pthread_cond_attr {
@@ -780,6 +778,8 @@ void _mutex_leave_robust(struct pthread *curthread, struct pthread_mutex *m)
void _libpthread_init(struct pthread *) __hidden;
struct pthread *_thr_alloc(struct pthread *) __hidden;
void _thread_exit(const char *, int, const char *) __hidden __dead2;
+void _thread_exitf(const char *, int, const char *, ...) __hidden __dead2
+ __printflike(3, 4);
int _thr_ref_add(struct pthread *, struct pthread *, int) __hidden;
void _thr_ref_delete(struct pthread *, struct pthread *) __hidden;
void _thr_ref_delete_unlocked(struct pthread *, struct pthread *) __hidden;
@@ -791,7 +791,8 @@ void _thr_stack_free(struct pthread_attr *) __hidden;
void _thr_free(struct pthread *, struct pthread *) __hidden;
void _thr_gc(struct pthread *) __hidden;
void _thread_cleanupspecific(void) __hidden;
-void _thread_printf(int, const char *, ...) __hidden;
+void _thread_printf(int, const char *, ...) __hidden __printflike(2, 3);
+void _thread_vprintf(int, const char *, va_list) __hidden;
void _thr_spinlock_init(void) __hidden;
void _thr_cancel_enter(struct pthread *) __hidden;
void _thr_cancel_enter2(struct pthread *, int) __hidden;
diff --git a/lib/libxo/add.man b/lib/libxo/add.man
index d314685..ee79bf3 100644
--- a/lib/libxo/add.man
+++ b/lib/libxo/add.man
@@ -3,10 +3,10 @@
.Fx
uses
.Nm libxo
-version 0.6.1.
+version 0.6.2.
Complete documentation can be found on github:
.Bd -literal -offset indent
-http://juniper.github.io/libxo/0.6.1/libxo\-manual.html
+http://juniper.github.io/libxo/0.6.2/libxo\-manual.html
.Ed
.Pp
.Nm libxo
diff --git a/lib/libxo/xo_config.h b/lib/libxo/xo_config.h
index b26fded..9020b8c 100644
--- a/lib/libxo/xo_config.h
+++ b/lib/libxo/xo_config.h
@@ -183,16 +183,16 @@
/* #undef LIBXO_TEXT_ONLY */
/* Version number as dotted value */
-#define LIBXO_VERSION "0.6.1"
+#define LIBXO_VERSION "0.6.2"
/* Version number extra information */
#define LIBXO_VERSION_EXTRA ""
/* Version number as a number */
-#define LIBXO_VERSION_NUMBER 6001
+#define LIBXO_VERSION_NUMBER 6002
/* Version number as string */
-#define LIBXO_VERSION_STRING "6001"
+#define LIBXO_VERSION_STRING "6002"
/* Enable local wcwidth implementation */
#define LIBXO_WCWIDTH 1
@@ -210,7 +210,7 @@
#define PACKAGE_NAME "libxo"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libxo 0.6.1"
+#define PACKAGE_STRING "libxo 0.6.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libxo"
@@ -219,7 +219,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.6.1"
+#define PACKAGE_VERSION "0.6.2"
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -233,7 +233,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "0.6.1"
+#define VERSION "0.6.2"
/* Retain hash bucket size */
/* #undef XO_RETAIN_SIZE */
diff --git a/libexec/Makefile b/libexec/Makefile
index b60cc34..fdcc49a 100644
--- a/libexec/Makefile
+++ b/libexec/Makefile
@@ -5,6 +5,7 @@
SUBDIR= ${_atf} \
${_atrun} \
+ ${_blacklistd-helper} \
${_comsat} \
${_dma} \
getty \
@@ -33,6 +34,10 @@ SUBDIR= ${_atf} \
_atrun= atrun
.endif
+.if ${MK_BLACKLIST_SUPPORT} != "no"
+_blacklistd-helper+= blacklistd-helper
+.endif
+
.if ${MK_BOOTPD} != "no"
SUBDIR+= bootpd
.endif
diff --git a/libexec/blacklistd-helper/Makefile b/libexec/blacklistd-helper/Makefile
new file mode 100644
index 0000000..649c619
--- /dev/null
+++ b/libexec/blacklistd-helper/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+BLACKLIST_DIR=${SRCTOP}/contrib/blacklist
+
+SCRIPTS= ${BLACKLIST_DIR}/libexec/blacklistd-helper
+
+.include <bsd.prog.mk>
diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml
index 2a61808..cececb9 100644
--- a/release/doc/en_US.ISO8859-1/relnotes/article.xml
+++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml
@@ -1554,6 +1554,11 @@
code has been updated to take <literal>ashift</literal> into
account when gathering buffers to be written to the
<literal>l2arc</literal> device.</para>
+
+ <para revision="300906" contrib="sponsor"
+ sponsor="&ix;, &spectralogic;">The zfsd daemon has been added,
+ which manages hotspares and replements in drive slots that publish
+ physical paths.</para>
</sect2>
<sect2 xml:id="storage-geom">
@@ -1729,6 +1734,43 @@
<para revision="287798" contrib="sponsor" sponsor="&dell;">The
network stack has been updated to fix handling of
<acronym>IPv6</acronym> On-Link redirects.</para>
+
+ <para revision="300240">The net.inet.tcp.ecn.enable sysctl mib has been
+ changed from a binary off/on control to a three way setting.</para>
+
+ <informaltable frame="none" pgwide="0">
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><literal>0</literal></entry>
+ <entry>Totally disable ECN.</entry>
+ </row>
+
+ <row>
+ <entry><literal>1</literal></entry>
+ <entry>Enable ECN if incoming connections request it. Outgoing
+ connections will request ECN.</entry>
+ </row>
+
+ <row>
+ <entry><literal>2</literal></entry>
+ <entry>Enable ECN if incoming connections request it. Outgoing
+ conections will not request ECN.</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </informaltable>
+
</sect2>
</sect1>
diff --git a/release/tools/arm.subr b/release/tools/arm.subr
index 2adadd2..edce8ba 100644
--- a/release/tools/arm.subr
+++ b/release/tools/arm.subr
@@ -72,7 +72,6 @@ arm_create_disk() {
chroot ${CHROOTDIR} gpart create -s bsd ${mddev}s2
chroot ${CHROOTDIR} gpart add -t freebsd-ufs -a 64k /dev/${mddev}s2
chroot ${CHROOTDIR} newfs -U -L rootfs /dev/${mddev}s2a
- chroot ${CHROOTDIR} tunefs -N enable /dev/${mddev}s2a
return 0
}
diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index 0a6dd0f..a386741 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -54,11 +54,14 @@ static const char rcsid[] =
static struct in_aliasreq in_addreq;
static struct ifreq in_ridreq;
+static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/
+extern char *f_inet, *f_addr;
static void
in_status(int s __unused, const struct ifaddrs *ifa)
{
struct sockaddr_in *sin, null_sin;
+ int error, n_flags;
memset(&null_sin, 0, sizeof(null_sin));
@@ -66,19 +69,47 @@ in_status(int s __unused, const struct ifaddrs *ifa)
if (sin == NULL)
return;
- printf("\tinet %s ", inet_ntoa(sin->sin_addr));
+ if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
+ n_flags = 0;
+ else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
+ n_flags = NI_NOFQDN;
+ else
+ n_flags = NI_NUMERICHOST;
+
+ error = getnameinfo((struct sockaddr *)sin, sin->sin_len, addr_buf,
+ sizeof(addr_buf), NULL, 0, n_flags);
+
+ if (error)
+ inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf));
+
+ printf("\tinet %s", addr_buf);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
if (sin == NULL)
sin = &null_sin;
- printf("--> %s ", inet_ntoa(sin->sin_addr));
+ printf(" --> %s ", inet_ntoa(sin->sin_addr));
}
sin = (struct sockaddr_in *)ifa->ifa_netmask;
if (sin == NULL)
sin = &null_sin;
- printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
+ if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) {
+ int cidr = 32;
+ unsigned long smask;
+
+ smask = ntohl(sin->sin_addr.s_addr);
+ while ((smask & 1) == 0) {
+ smask = smask >> 1;
+ cidr--;
+ if (cidr == 0)
+ break;
+ }
+ printf("/%d ", cidr);
+ } else if (f_inet != NULL && strcmp(f_inet, "dotted") == 0)
+ printf(" netmask %s ", inet_ntoa(sin->sin_addr));
+ else
+ printf(" netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
if (ifa->ifa_flags & IFF_BROADCAST) {
sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index 6a24125..3ddf303 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -65,12 +65,13 @@ static int ip6lifetime;
static int prefix(void *, int);
static char *sec2str(time_t);
static int explicit_prefix = 0;
+extern char *f_inet6, *f_addr;
extern void setnd6flags(const char *, int, int, const struct afswtch *);
extern void setnd6defif(const char *, int, int, const struct afswtch *);
extern void nd6_status(int);
-static char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/
+static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/
static void
setifprefixlen(const char *addr, int dummy __unused, int s,
@@ -174,7 +175,7 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
u_int32_t flags6;
struct in6_addrlifetime lifetime;
struct timespec now;
- int error;
+ int error, n_flags;
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
@@ -206,12 +207,19 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
lifetime = ifr6.ifr_ifru.ifru_lifetime;
close(s6);
- error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf,
- sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
+ if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
+ n_flags = 0;
+ else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
+ n_flags = NI_NOFQDN;
+ else
+ n_flags = NI_NUMERICHOST;
+ error = getnameinfo((struct sockaddr *)sin, sin->sin6_len,
+ addr_buf, sizeof(addr_buf), NULL, 0,
+ n_flags);
if (error != 0)
inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
sizeof(addr_buf));
- printf("\tinet6 %s ", addr_buf);
+ printf("\tinet6 %s", addr_buf);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
@@ -229,15 +237,19 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
if (error != 0)
inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
sizeof(addr_buf));
- printf("--> %s ", addr_buf);
+ printf(" --> %s ", addr_buf);
}
}
sin = (struct sockaddr_in6 *)ifa->ifa_netmask;
if (sin == NULL)
sin = &null_sin;
- printf("prefixlen %d ", prefix(&sin->sin6_addr,
- sizeof(struct in6_addr)));
+ if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0)
+ printf("/%d ", prefix(&sin->sin6_addr,
+ sizeof(struct in6_addr)));
+ else
+ printf(" prefixlen %d ", prefix(&sin->sin6_addr,
+ sizeof(struct in6_addr)));
if ((flags6 & IN6_IFF_ANYCAST) != 0)
printf("anycast ");
diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c
index 4a4b661..c96cbd2 100644
--- a/sbin/ifconfig/af_link.c
+++ b/sbin/ifconfig/af_link.c
@@ -51,20 +51,29 @@ static const char rcsid[] =
static struct ifreq link_ridreq;
+extern char *f_ether;
+
static void
link_status(int s __unused, const struct ifaddrs *ifa)
{
/* XXX no const 'cuz LLADDR is defined wrong */
struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr;
+ char *ether_format, *format_char;
if (sdl != NULL && sdl->sdl_alen > 0) {
if ((sdl->sdl_type == IFT_ETHER ||
sdl->sdl_type == IFT_L2VLAN ||
sdl->sdl_type == IFT_BRIDGE) &&
- sdl->sdl_alen == ETHER_ADDR_LEN)
- printf("\tether %s\n",
- ether_ntoa((struct ether_addr *)LLADDR(sdl)));
- else {
+ sdl->sdl_alen == ETHER_ADDR_LEN) {
+ ether_format = ether_ntoa((struct ether_addr *)LLADDR(sdl));
+ if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
+ for (format_char = strchr(ether_format, ':');
+ format_char != NULL;
+ format_char = strchr(ether_format, ':'))
+ *format_char = '-';
+ }
+ printf("\tether %s\n", ether_format);
+ } else {
int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
printf("\tlladdr %s\n", link_ntoa(sdl) + n);
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index a5d7380..ef9bc2b 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
-.Dd November 6, 2015
+.Dd May 29, 2016
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -36,6 +36,7 @@
.Nd configure network interface parameters
.Sh SYNOPSIS
.Nm
+.Op Fl f Ar type:format Ns Op Ar ,type:format
.Op Fl L
.Op Fl k
.Op Fl m
@@ -194,6 +195,86 @@ for example,
List the interfaces in the given group.
.El
.Pp
+The output format of
+.Nm
+can be controlled using the
+.Fl f
+flag or the
+.Ev IFCONFIG_FORMAT
+environment variable.
+The format is specified as a comma separated list of
+.Sy type:format
+pairs.
+See the
+.Sx EXAMPLES
+section for more information.
+The
+.Sy types
+and their associated
+.Sy format
+strings are:
+.Bl -tag -width ether
+.It Sy addr
+Adjust the display of inet and inet6 addresses
+.Bl -tag -width default
+.It Sy default
+Display inet and inet6 addresses in the default format,
+.Sy numeric
+.It Sy fqdn
+Display inet and inet6 addresses as fully qualified domain names
+.Pq FQDN
+.It Sy host
+Display inet and inet6 addresses as unqualified hostnames
+.It Sy numeric
+Display inet and inet6 addresses in numeric format
+.El
+.It Sy ether
+Adjust the display of link-level ethernet (MAC) addresses
+.Bl -tag -width default
+.It Sy colon
+Separate address segments with a colon
+.It Sy dash
+Separate address segments with a dash
+.It Sy default
+Display ethernet addresses in the default format,
+.Sy colon
+.El
+.It Sy inet
+Adjust the display of inet address subnet masks:
+.Bl -tag -width default
+.It Sy cidr
+Display subnet masks in CIDR notation, for example:
+.br
+10.0.0.0/8 or 203.0.113.224/26
+.It Sy default
+Display subnet masks in the default format,
+.Sy hex
+.It Sy dotted
+Display subnet masks in dotted quad notation, for example:
+.br
+255.255.0.0 or 255.255.255.192
+.It Sy hex
+Display subnet masks in hexidecimal, for example:
+.br
+0xffff0000 or 0xffffffc0
+.El
+.It Sy inet6
+Adjust the display of inet6 address prefixes (subnet masks):
+.Bl -tag -width default
+.It Sy cidr
+Display subnet prefix in CIDR notation, for example:
+.br
+::1/128 or fe80::1%lo0/64
+.It Sy default
+Display subnet prefix in the default format
+.Sy numeric
+.It Sy numeric
+Display subnet prefix in integer format, for example:
+.br
+prefixlen 64
+.El
+.El
+.Pp
The following parameters may be set with
.Nm :
.Bl -tag -width indent
@@ -635,6 +716,10 @@ controls whether this flag is set by default or not.
.It Cm -accept_rtadv
Clear a flag
.Cm accept_rtadv .
+.It Cm autoconf
+Set a flag to accept router advertisements on an interface.
+.It Fl autoconf
+Disable autoconfiguration.
.It Cm no_radr
Set a flag to control whether routers from which the system accepts
Router Advertisement messages will be added to the Default Router List
@@ -707,12 +792,20 @@ Note that the address family keyword
.Dq Li inet6
is needed for them:
.Bl -tag -width indent
+.It Cm deprecated
+Set the IPv6 deprecated address bit.
+.It Fl deprecated
+Clear the IPv6 deprecated address bit.
+.It Cm pltime Ar n
+Set preferred lifetime for the address.
.It Cm prefer_source
Set a flag to prefer address as a candidate of the source address for
outgoing packets.
.It Cm -prefer_source
Clear a flag
.Cm prefer_source .
+.It Cm vltime Ar n
+Set valid lifetime for the address.
.El
.Pp
The following parameters are specific to cloning
@@ -2843,6 +2936,9 @@ Destroy the software network interface
Display available wireless networks using
.Li wlan0 :
.Dl # ifconfig wlan0 list scan
+.Pp
+Display inet and inet6 address subnet masks in CIDR notation
+.Dl # ifconfig -f inet:cidr,inet6:cidr
.Sh DIAGNOSTICS
Messages indicating the specified interface does not exist, the
requested address is unknown, or the user is not privileged and
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 001850f..cd61166 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -98,6 +98,9 @@ int printifname = 0;
int supmedia = 0;
int printkeys = 0; /* Print keying material for interfaces. */
+/* Formatter Strings */
+char *f_inet, *f_inet6, *f_ether, *f_addr;
+
static int ifconfig(int argc, char *const *argv, int iscreate,
const struct afswtch *afp);
static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
@@ -143,8 +146,8 @@ usage(void)
}
fprintf(stderr,
- "usage: ifconfig %sinterface address_family [address [dest_address]]\n"
- " [parameters]\n"
+ "usage: ifconfig [-f type:format] %sinterface address_family\n"
+ " [address [dest_address]] [parameters]\n"
" ifconfig interface create\n"
" ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
" ifconfig -l [-d] [-u] [address_family]\n"
@@ -243,6 +246,48 @@ cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q)
return (0);
}
+static void freeformat(void)
+{
+
+ if (f_inet != NULL)
+ free(f_inet);
+ if (f_inet6 != NULL)
+ free(f_inet6);
+ if (f_ether != NULL)
+ free(f_ether);
+ if (f_addr != NULL)
+ free(f_addr);
+}
+
+static void setformat(char *input)
+{
+ char *formatstr, *category, *modifier;
+
+ formatstr = strdup(input);
+ while ((category = strsep(&formatstr, ",")) != NULL) {
+ modifier = strchr(category, ':');
+ if (modifier == NULL || modifier[1] == '\0') {
+ warnx("Skipping invalid format specification: %s\n",
+ category);
+ continue;
+ }
+
+ /* Split the string on the separator, then seek past it */
+ modifier[0] = '\0';
+ modifier++;
+
+ if (strcmp(category, "addr") == 0)
+ f_addr = strdup(modifier);
+ else if (strcmp(category, "ether") == 0)
+ f_ether = strdup(modifier);
+ else if (strcmp(category, "inet") == 0)
+ f_inet = strdup(modifier);
+ else if (strcmp(category, "inet6") == 0)
+ f_inet6 = strdup(modifier);
+ }
+ free(formatstr);
+}
+
#undef ORDERS_SIZE
static struct ifaddrs *
@@ -315,7 +360,7 @@ main(int argc, char *argv[])
struct ifaddrs *ifap, *sifap, *ifa;
struct ifreq paifr;
const struct sockaddr_dl *sdl;
- char options[1024], *cp, *namecp = NULL;
+ char options[1024], *cp, *envformat, *namecp = NULL;
struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
struct ifa_order_elt *cur, *tmp;
const char *ifname;
@@ -323,7 +368,12 @@ main(int argc, char *argv[])
size_t iflen;
all = downonly = uponly = namesonly = noload = verbose = 0;
-
+ f_inet = f_inet6 = f_ether = f_addr = NULL;
+
+ envformat = getenv("IFCONFIG_FORMAT");
+ if (envformat != NULL)
+ setformat(envformat);
+
/*
* Ensure we print interface name when expected to,
* even if we terminate early due to error.
@@ -331,7 +381,7 @@ main(int argc, char *argv[])
atexit(printifnamemaybe);
/* Parse leading line options */
- strlcpy(options, "adklmnuv", sizeof(options));
+ strlcpy(options, "f:adklmnuv", sizeof(options));
for (p = opts; p != NULL; p = p->next)
strlcat(options, p->opt, sizeof(options));
while ((c = getopt(argc, argv, options)) != -1) {
@@ -342,6 +392,11 @@ main(int argc, char *argv[])
case 'd': /* restrict scan to "down" interfaces */
downonly++;
break;
+ case 'f':
+ if (optarg == NULL)
+ usage();
+ setformat(optarg);
+ break;
case 'k':
printkeys++;
break;
@@ -539,6 +594,7 @@ main(int argc, char *argv[])
printf("\n");
freeifaddrs(ifap);
+ freeformat();
exit(0);
}
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 63f04cf..ce8823f 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 13, 2015
+.Dd May 26, 2016
.Dt IPFW 8
.Os
.Sh NAME
diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile
index 6b65172..cb643ea 100644
--- a/sbin/md5/Makefile
+++ b/sbin/md5/Makefile
@@ -8,13 +8,21 @@ LINKS= ${BINDIR}/md5 ${BINDIR}/rmd160 \
${BINDIR}/md5 ${BINDIR}/sha1 \
${BINDIR}/md5 ${BINDIR}/sha256 \
${BINDIR}/md5 ${BINDIR}/sha384 \
- ${BINDIR}/md5 ${BINDIR}/sha512
+ ${BINDIR}/md5 ${BINDIR}/sha512 \
+ ${BINDIR}/md5 ${BINDIR}/sha512t256 \
+ ${BINDIR}/md5 ${BINDIR}/skein256 \
+ ${BINDIR}/md5 ${BINDIR}/skein512 \
+ ${BINDIR}/md5 ${BINDIR}/skein1024
MLINKS= md5.1 rmd160.1 \
md5.1 sha1.1 \
md5.1 sha256.1 \
md5.1 sha384.1 \
- md5.1 sha512.1
+ md5.1 sha512.1 \
+ md5.1 sha512t256.1 \
+ md5.1 skein256.1 \
+ md5.1 skein512.1 \
+ md5.1 skein1024.1
LIBADD= md
diff --git a/sbin/md5/md5.1 b/sbin/md5/md5.1
index 94cdf84..6fa0393 100644
--- a/sbin/md5/md5.1
+++ b/sbin/md5/md5.1
@@ -1,9 +1,9 @@
.\" $FreeBSD$
-.Dd October 17, 2015
+.Dd April 22, 2016
.Dt MD5 1
.Os
.Sh NAME
-.Nm md5 , sha1 , sha256 , sha384 , sha512, rmd160
+.Nm md5 , sha1 , sha256 , sha384 , sha512, sha512t256, rmd160
.Nd calculate a message-digest fingerprint (checksum) for a file
.Sh SYNOPSIS
.Nm md5
@@ -31,6 +31,11 @@
.Op Fl c Ar string
.Op Fl s Ar string
.Op Ar
+.Nm sha512t256
+.Op Fl pqrtx
+.Op Fl c Ar string
+.Op Fl s Ar string
+.Op Ar
.Nm rmd160
.Op Fl pqrtx
.Op Fl c Ar string
@@ -38,7 +43,7 @@
.Op Ar
.Sh DESCRIPTION
The
-.Nm md5 , sha1 , sha256 , sha384 , sha512
+.Nm md5 , sha1 , sha256 , sha384 , sha512, sha512t256
and
.Nm rmd160
utilities take as input a message of arbitrary length and produce as
@@ -78,8 +83,17 @@ found which is faster than a brute-force search, placing the security of
.Tn SHA-1
in doubt.
.Pp
-It is recommended that all new applications use
+.Tn SHA-512t256
+is a version of
+.Tn SHA-512
+truncated to only 256 bits.
+On 64-bit hardware, this algorithm is approximately 50% faster than
.Tn SHA-256
+but with the same level of security.
+The hashes are not interchangeable.
+.Pp
+It is recommended that all new applications use
+.Tn SHA-512
instead of one of the other hash functions.
.Pp
The following options may be used in any combination and must
@@ -114,7 +128,7 @@ Run a built-in test script.
.El
.Sh EXIT STATUS
The
-.Nm md5 , sha1 , sha256 , sha512
+.Nm md5 , sha1 , sha256 , sha512, sha512t256
and
.Nm rmd160
utilities exit 0 on success,
diff --git a/sbin/md5/md5.c b/sbin/md5/md5.c
index 1172f25..ddf3a3c 100644
--- a/sbin/md5/md5.c
+++ b/sbin/md5/md5.c
@@ -30,6 +30,8 @@ __FBSDID("$FreeBSD$");
#include <sha256.h>
#include <sha384.h>
#include <sha512.h>
+#include <sha512t.h>
+#include <skein.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -58,7 +60,11 @@ extern const char *SHA1_TestOutput[MDTESTCOUNT];
extern const char *SHA256_TestOutput[MDTESTCOUNT];
extern const char *SHA384_TestOutput[MDTESTCOUNT];
extern const char *SHA512_TestOutput[MDTESTCOUNT];
+extern const char *SHA512t256_TestOutput[MDTESTCOUNT];
extern const char *RIPEMD160_TestOutput[MDTESTCOUNT];
+extern const char *SKEIN256_TestOutput[MDTESTCOUNT];
+extern const char *SKEIN512_TestOutput[MDTESTCOUNT];
+extern const char *SKEIN1024_TestOutput[MDTESTCOUNT];
typedef struct Algorithm_t {
const char *progname;
@@ -85,12 +91,15 @@ typedef union {
SHA384_CTX sha384;
SHA512_CTX sha512;
RIPEMD160_CTX ripemd160;
+ SKEIN256_CTX skein256;
+ SKEIN512_CTX skein512;
+ SKEIN1024_CTX skein1024;
} DIGEST_CTX;
/* max(MD5_DIGEST_LENGTH, SHA_DIGEST_LENGTH,
SHA256_DIGEST_LENGTH, SHA512_DIGEST_LENGTH,
- RIPEMD160_DIGEST_LENGTH)*2+1 */
-#define HEX_DIGEST_LENGTH 129
+ RIPEMD160_DIGEST_LENGTH, SKEIN1024_DIGEST_LENGTH)*2+1 */
+#define HEX_DIGEST_LENGTH 257
/* algorithm function table */
@@ -110,9 +119,21 @@ static const struct Algorithm_t Algorithm[] = {
{ "sha512", "SHA512", &SHA512_TestOutput, (DIGEST_Init*)&SHA512_Init,
(DIGEST_Update*)&SHA512_Update, (DIGEST_End*)&SHA512_End,
&SHA512_Data, &SHA512_File },
+ { "sha512t256", "SHA512t256", &SHA512t256_TestOutput, (DIGEST_Init*)&SHA512_256_Init,
+ (DIGEST_Update*)&SHA512_256_Update, (DIGEST_End*)&SHA512_256_End,
+ &SHA512_256_Data, &SHA512_256_File },
{ "rmd160", "RMD160", &RIPEMD160_TestOutput,
(DIGEST_Init*)&RIPEMD160_Init, (DIGEST_Update*)&RIPEMD160_Update,
- (DIGEST_End*)&RIPEMD160_End, &RIPEMD160_Data, &RIPEMD160_File }
+ (DIGEST_End*)&RIPEMD160_End, &RIPEMD160_Data, &RIPEMD160_File },
+ { "skein256", "Skein256", &SKEIN256_TestOutput,
+ (DIGEST_Init*)&SKEIN256_Init, (DIGEST_Update*)&SKEIN256_Update,
+ (DIGEST_End*)&SKEIN256_End, &SKEIN256_Data, &SKEIN256_File },
+ { "skein512", "Skein512", &SKEIN512_TestOutput,
+ (DIGEST_Init*)&SKEIN512_Init, (DIGEST_Update*)&SKEIN512_Update,
+ (DIGEST_End*)&SKEIN512_End, &SKEIN512_Data, &SKEIN512_File },
+ { "skein1024", "Skein1024", &SKEIN1024_TestOutput,
+ (DIGEST_Init*)&SKEIN1024_Init, (DIGEST_Update*)&SKEIN1024_Update,
+ (DIGEST_End*)&SKEIN1024_End, &SKEIN1024_Data, &SKEIN1024_File }
};
static void
@@ -281,8 +302,8 @@ MDTimeTrial(const Algorithm_t *alg)
printf(" done\n");
printf("Digest = %s", p);
printf("\nTime = %f seconds\n", seconds);
- printf("Speed = %f bytes/second\n",
- (float) TEST_BLOCK_LEN * (float) TEST_BLOCK_COUNT / seconds);
+ printf("Speed = %f MiB/second\n", (float) TEST_BLOCK_LEN *
+ (float) TEST_BLOCK_COUNT / seconds / (1 << 20));
}
/*
* Digests a reference suite of strings and prints the results.
@@ -355,6 +376,17 @@ const char *SHA512_TestOutput[MDTESTCOUNT] = {
"e8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3"
};
+const char *SHA512t256_TestOutput[MDTESTCOUNT] = {
+ "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",
+ "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8",
+ "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23",
+ "0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb",
+ "fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26",
+ "cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8",
+ "2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148",
+ "dd095fc859b336c30a52548b3dc59fcc0d1be8616ebcf3368fad23107db2d736"
+};
+
const char *RIPEMD160_TestOutput[MDTESTCOUNT] = {
"9c1185a5c5e9fc54612808977ee8f548b2258d31",
"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
@@ -366,6 +398,39 @@ const char *RIPEMD160_TestOutput[MDTESTCOUNT] = {
"5feb69c6bf7c29d95715ad55f57d8ac5b2b7dd32"
};
+const char *SKEIN256_TestOutput[MDTESTCOUNT] = {
+ "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba",
+ "7fba44ff1a31d71a0c1f82e6e82fb5e9ac6c92a39c9185b9951fed82d82fe635",
+ "258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870",
+ "4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488",
+ "46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82",
+ "7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2",
+ "4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d",
+ "d9c017dbe355f318d036469eb9b5fbe129fc2b5786a9dc6746a516eab6fe0126"
+};
+
+const char *SKEIN512_TestOutput[MDTESTCOUNT] = {
+ "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a",
+ "b1cd8d33f61b3737adfd59bb13ad82f4a9548e92f22956a8976cca3fdb7fee4fe91698146c4197cec85d38b83c5d93bdba92c01fd9a53870d0c7f967bc62bdce",
+ "8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75",
+ "15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc",
+ "23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c",
+ "0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c",
+ "2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce",
+ "1131f2aaa0e97126c9314f9f968cc827259bbfabced2943bb8c9274448998fb3b78738b4580dd500c76105fd3c03e465e1414f2c29664286b1f79d3e51128125"
+};
+
+const char *SKEIN1024_TestOutput[MDTESTCOUNT] = {
+ "0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6",
+ "6ab4c4ba9814a3d976ec8bffa7fcc638ceba0544a97b3c98411323ffd2dc936315d13dc93c13c4e88cda6f5bac6f2558b2d8694d3b6143e40d644ae43ca940685cb37f809d3d0550c56cba8036dee729a4f8fb960732e59e64d57f7f7710f8670963cdcdc95b41daab4855fcf8b6762a64b173ee61343a2c7689af1d293eba97",
+ "35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f",
+ "ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458",
+ "f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f",
+ "cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469",
+ "cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a",
+ "e6799b78db54085a2be7ff4c8007f147fa88d326abab30be0560b953396d8802feee9a15419b48a467574e9283be15685ca8a079ee52b27166b64dd70b124b1d4e4f6aca37224c3f2685e67e67baef9f94b905698adc794a09672aba977a61b20966912acdb08c21a2c37001785355dc884751a21f848ab36e590331ff938138"
+};
+
static void
MDTestSuite(const Algorithm_t *alg)
{
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index 0c534ad..e34cfcf 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -216,7 +216,7 @@ main(int argc, char **argv)
static const char *
swap_on_off(const char *name, int doingall, char *mntops)
{
- char base[PATH_MAX];
+ char *base, *basebuf;
/* Swap on vnode-backed md(4) device. */
if (mntops != NULL &&
@@ -227,17 +227,23 @@ swap_on_off(const char *name, int doingall, char *mntops)
strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0))
return (swap_on_off_md(name, mntops, doingall));
- basename_r(name, base);
+ basebuf = strdup(name);
+ base = basename(basebuf);
/* Swap on encrypted device by GEOM_BDE. */
- if (fnmatch("*.bde", base, 0) == 0)
+ if (fnmatch("*.bde", base, 0) == 0) {
+ free(basebuf);
return (swap_on_off_gbde(name, doingall));
+ }
/* Swap on encrypted device by GEOM_ELI. */
- if (fnmatch("*.eli", base, 0) == 0)
+ if (fnmatch("*.eli", base, 0) == 0) {
+ free(basebuf);
return (swap_on_off_geli(name, mntops, doingall));
+ }
/* Swap on special file. */
+ free(basebuf);
return (swap_on_off_sfile(name, doingall));
}
diff --git a/share/man/man3/pthread_attr_get_np.3 b/share/man/man3/pthread_attr_get_np.3
index e43bcf3..a23cac6 100644
--- a/share/man/man3/pthread_attr_get_np.3
+++ b/share/man/man3/pthread_attr_get_np.3
@@ -93,7 +93,7 @@ function will fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
Invalid value for one of given parameters.
-.It Bq Er ESRC
+.It Bq Er ESRCH
No thread could be found corresponding to that specified by the given
thread ID.
.El
diff --git a/share/man/man3/pthread_barrier_destroy.3 b/share/man/man3/pthread_barrier_destroy.3
index 34be9d0..1b150a5 100644
--- a/share/man/man3/pthread_barrier_destroy.3
+++ b/share/man/man3/pthread_barrier_destroy.3
@@ -75,9 +75,7 @@ argument to
.Fn pthread_barrier_init .
Once the threads have been released the barrier will be reset.
.Sh IMPLEMENTATION NOTES
-In both
-.Lb libkse
-and
+In
.Lb libthr
the
.Dv PTHREAD_BARRIER_SERIAL_THREAD
diff --git a/share/man/man3/pthread_barrierattr.3 b/share/man/man3/pthread_barrierattr.3
index e314a0e..bbf37d9 100644
--- a/share/man/man3/pthread_barrierattr.3
+++ b/share/man/man3/pthread_barrierattr.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 19, 2004
+.Dd May 31, 2016
.Dt PTHREAD_BARRIERATTR 3
.Os
.Sh NAME
@@ -131,18 +131,5 @@ and in
.Lb libthr
in
.Fx 5.3 .
-.Sh BUGS
-The implementation of
-barriers
-does not fully conform to
-.St -p1003.2
-because the process-shared attribute is ignored in
-.Lb libthr ,
-and in
-.Lb libkse ;
-if any value other than
-.Dv PTHREAD_PROCESSES_PRIVATE
-is specified in a call to
-.Fn pthread_barrierattr_setpshared ,
-it will return
-.Er EINVAL .
+Support for process-shared barriers appeared in
+.Fx 11.0 .
diff --git a/share/man/man3/pthread_condattr.3 b/share/man/man3/pthread_condattr.3
index d7f8f6b..f72fd25 100644
--- a/share/man/man3/pthread_condattr.3
+++ b/share/man/man3/pthread_condattr.3
@@ -26,7 +26,7 @@
.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd May 9, 2010
+.Dd May 31, 2016
.Dt PTHREAD_CONDATTR 3
.Os
.Sh NAME
@@ -160,15 +160,3 @@ and
.Fn pthread_condattr_destroy
functions conform to
.St -p1003.1-96
-.Sh BUGS
-The implementation of
-condition variables
-does not fully conform to
-.St -p1003.2
-because the process-shared attribute is ignored;
-if any value other than
-.Dv PTHREAD_PROCESSES_PRIVATE
-is specified in a call to
-.Fn pthread_condattr_setpshared ,
-it will return
-.Er EINVAL .
diff --git a/share/man/man3/pthread_resume_np.3 b/share/man/man3/pthread_resume_np.3
index eba7568..898dbf9 100644
--- a/share/man/man3/pthread_resume_np.3
+++ b/share/man/man3/pthread_resume_np.3
@@ -57,7 +57,7 @@ function will fail if:
The value specified by the
.Fa tid
argument is invalid.
-.It Bq Er ESRC
+.It Bq Er ESRCH
No thread could be found corresponding to the thread ID specified by the
.Fa tid
argument.
diff --git a/share/man/man3/pthread_rwlock_init.3 b/share/man/man3/pthread_rwlock_init.3
index 2617c43..1b0023c 100644
--- a/share/man/man3/pthread_rwlock_init.3
+++ b/share/man/man3/pthread_rwlock_init.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 4, 1998
+.Dd May 31, 2016
.Dt PTHREAD_RWLOCK_INIT 3
.Os
.Sh NAME
@@ -98,5 +98,3 @@ The
.Fn pthread_rwlock_init
function first appeared in
.Fx 3.0 .
-.Sh BUGS
-The PTHREAD_PROCESS_SHARED attribute is not supported.
diff --git a/share/man/man3/pthread_rwlockattr_setpshared.3 b/share/man/man3/pthread_rwlockattr_setpshared.3
index ccfe886..bf2ddac 100644
--- a/share/man/man3/pthread_rwlockattr_setpshared.3
+++ b/share/man/man3/pthread_rwlockattr_setpshared.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 4, 1998
+.Dd May 31, 2016
.Dt PTHREAD_RWLOCKATTR_SETPSHARED 3
.Os
.Sh NAME
@@ -88,7 +88,5 @@ The
.Fn pthread_rwlockattr_setpshared
function first appeared in
.Fx 3.0 .
-.Sh BUGS
-The
-.Dv PTHREAD_PROCESS_SHARED
-attribute is not supported.
+Support for process-shared read/write locks appeared in
+.Fx 11.0 .
diff --git a/share/man/man3/pthread_spin_init.3 b/share/man/man3/pthread_spin_init.3
index 1f76de1..3ef67ad 100644
--- a/share/man/man3/pthread_spin_init.3
+++ b/share/man/man3/pthread_spin_init.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 22, 2004
+.Dd May 31, 2016
.Dt PTHREAD_SPIN_INIT 3
.Os
.Sh NAME
@@ -121,18 +121,5 @@ and in
.Lb libthr
in
.Fx 5.3 .
-.Sh BUGS
-The implementation of
-.Fn pthread_spin_init
-does not fully conform to
-.St -p1003.2
-because the
-.Fa pshared
-argument is ignored in
-.Lb libthr ,
-and in
-.Lb libkse
-if any value other than
-.Dv PTHREAD_PROCESSES_PRIVATE
-is specified, it returns
-.Er EINVAL .
+Support for process-shared spinlocks appeared in
+.Fx 11.0 .
diff --git a/share/man/man3/pthread_suspend_np.3 b/share/man/man3/pthread_suspend_np.3
index e68b317..ca8c72a 100644
--- a/share/man/man3/pthread_suspend_np.3
+++ b/share/man/man3/pthread_suspend_np.3
@@ -63,7 +63,7 @@ An attempt was made to suspend the current thread.
The value specified by the
.Fa tid
argument is invalid.
-.It Bq Er ESRC
+.It Bq Er ESRCH
No thread could be found corresponding to the thread ID specified by the
.Fa tid
argument.
diff --git a/share/man/man9/domain.9 b/share/man/man9/domain.9
index 464274b..e205b38 100644
--- a/share/man/man9/domain.9
+++ b/share/man/man9/domain.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 6, 2014
+.Dd June 1, 2016
.Dt DOMAIN 9
.Os
.Sh NAME
@@ -105,7 +105,6 @@ struct protosw {
pr_ctloutput_t *pr_ctloutput; /* control output (from above) */
/* utility hooks */
pr_init_t *pr_init;
- pr_destroy_t *pr_destroy;
pr_fasttimo_t *pr_fasttimo; /* fast timeout (200ms) */
pr_slowtimo_t *pr_slowtimo; /* slow timeout (500ms) */
pr_drain_t *pr_drain; /* flush any excess space possible */
diff --git a/share/man/man9/memguard.9 b/share/man/man9/memguard.9
index 42678c0..ed0773e 100644
--- a/share/man/man9/memguard.9
+++ b/share/man/man9/memguard.9
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 21, 2014
+.Dd June 1, 2016
.Dt MEMGUARD 9
.Os
.Sh NAME
@@ -204,17 +204,3 @@ Additions have been made by
and
.An Gleb Smirnoff Aq Mt glebius@FreeBSD.org
to both the implementation and the documentation.
-.Sh BUGS
-It is not possible to guard allocations that really expect themselves to be
-allocated from
-.Xr uma 9 ,
-utilizing additional interfaces apart from
-.Fn uma_zalloc
-and
-.Fn uma_free ,
-for example
-.Fn uma_find_refcnt .
-For the moment of writing only
-.Xr mbuf 9
-cluster zones belong to that kind of allocations.
-Attempt to guard them would lead to kernel panic.
diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot
index 29997f5..1656e80 100644
--- a/share/misc/committers-src.dot
+++ b/share/misc/committers-src.dot
@@ -218,6 +218,7 @@ kevlo [label="Kevin Lo\nkevlo@FreeBSD.org\n2006/07/23"]
kib [label="Konstantin Belousov\nkib@FreeBSD.org\n2006/06/03"]
kmacy [label="Kip Macy\nkmacy@FreeBSD.org\n2005/06/01"]
kp [label="Kristof Provost\nkp@FreeBSD.org\n2015/03/22"]
+landonf [label="Landon Fuller\nlandonf@FreeBSD.org\n2016/05/31"]
le [label="Lukas Ertl\nle@FreeBSD.org\n2004/02/02"]
lidl [label="Kurt Lidl\nlidl@FreeBSD.org\n2015/10/21"]
loos [label="Luiz Otavio O Souza\nloos@FreeBSD.org\n2013/07/03"]
@@ -346,6 +347,7 @@ day1 -> dg
adrian -> avos
adrian -> jmcneill
+adrian -> landonf
adrian -> lidl
adrian -> loos
adrian -> monthadar
diff --git a/share/misc/organization.dot b/share/misc/organization.dot
index b442d6c..0a03d78 100644
--- a/share/misc/organization.dot
+++ b/share/misc/organization.dot
@@ -31,9 +31,9 @@ doccommitters [label="Doc/www Committers\ndoc-committers@FreeBSD.org"]
doceng [label="Documentation Engineering Team\ndoceng@FreeBSD.org\ngjb, blackend,\ngabor, hrs"]
portscommitters [label="Ports Committers\nports-committers@FreeBSD.org"]
portmgr [label="Port Management Team\nportmgr@FreeBSD.org\nantoine, bapt, bdrewery,\nerwin, mat, swills,\nmiwi"]
-portmgrsecretary [label="Port Management Team Secretary\nportmgr-secretary@FreeBSD.org\nculot"]
+portmgrsecretary [label="Port Management Team Secretary\nportmgr-secretary@FreeBSD.org\nrene"]
re [label="Primary Release Engineering Team\nre@FreeBSD.org\nkib, blackend, jpaetzel, hrs, kensmith"]
-secteam [label="Security Team\nsecteam@FreeBSD.org\nsimon, qingli, delphij,\nremko, philip, stas, cperciva,\ncsjp, rwatson, miwi, bz"]
+secteam [label="Security Team\nsecteam@FreeBSD.org\ndelphij,\ndes, gavin, gjb,\nglebius, remko"]
portssecteam [label="Ports Security Team\nports-secteam@FreeBSD.org\ndelphij, eadler, feld, jgh, junovitch, miwi, rea, sbz, simon, swills, zi"]
secteamsecretary [label="Security Team Secretary\nsecteam-secretary@FreeBSD.org\nremko"]
securityofficer [label="Security Officer Team\nsecurity-officer@FreeBSD.org\ncperciva, simon, nectar"]
diff --git a/share/mk/bsd.dep.mk b/share/mk/bsd.dep.mk
index 92487ea..24651cc 100644
--- a/share/mk/bsd.dep.mk
+++ b/share/mk/bsd.dep.mk
@@ -92,7 +92,7 @@ OBJS_DEPEND_GUESS.${_S:R}.o= ${_S}
# Lexical analyzers
.for _LSRC in ${SRCS:M*.l:N*/*}
.for _LC in ${_LSRC:R}.c
-${_LC}: ${_LSRC}
+${_LC}: ${_LSRC} ${OP_META}
${LEX} ${LFLAGS} -o${.TARGET} ${.ALLSRC}
OBJS_DEPEND_GUESS.${_LC:R}.o= ${_LC}
SRCS:= ${SRCS:S/${_LSRC}/${_LC}/}
@@ -107,6 +107,7 @@ SRCS:= ${SRCS:S/${_YSRC}/${_YC}/}
CLEANFILES+= ${_YC}
.if !empty(YFLAGS:M-d) && !empty(SRCS:My.tab.h)
.ORDER: ${_YC} y.tab.h
+${_YC}: ${OP_META}
${_YC} y.tab.h: ${_YSRC}
${YACC} ${YFLAGS} ${.ALLSRC}
cp y.tab.c ${_YC}
@@ -114,13 +115,14 @@ CLEANFILES+= y.tab.c y.tab.h
.elif !empty(YFLAGS:M-d)
.for _YH in ${_YC:R}.h
.ORDER: ${_YC} ${_YH}
+${_YC}: ${OP_META}
${_YC} ${_YH}: ${_YSRC}
${YACC} ${YFLAGS} -o ${_YC} ${.ALLSRC}
SRCS+= ${_YH}
CLEANFILES+= ${_YH}
.endfor
.else
-${_YC}: ${_YSRC}
+${_YC}: ${_YSRC} ${OP_META}
${YACC} ${YFLAGS} -o ${_YC} ${.ALLSRC}
.endif
OBJS_DEPEND_GUESS.${_YC:R}.o= ${_YC}
@@ -134,20 +136,20 @@ CFLAGS+= -I${.OBJDIR}
.for _DSRC in ${SRCS:M*.d:N*/*}
.for _D in ${_DSRC:R}
SRCS+= ${_D}.h
-${_D}.h: ${_DSRC}
+${_D}.h: ${_DSRC} ${OP_META}
${DTRACE} ${DTRACEFLAGS} -h -s ${.ALLSRC}
SRCS:= ${SRCS:S/^${_DSRC}$//}
OBJS+= ${_D}.o
CLEANFILES+= ${_D}.h ${_D}.o
-${_D}.o: ${_DSRC} ${OBJS:S/^${_D}.o$//}
+${_D}.o: ${_DSRC} ${OBJS:S/^${_D}.o$//} ${OP_META}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
.if defined(LIB)
CLEANFILES+= ${_D}.So ${_D}.po
-${_D}.So: ${_DSRC} ${SOBJS:S/^${_D}.So$//}
+${_D}.So: ${_DSRC} ${SOBJS:S/^${_D}.So$//} ${OP_META}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
-${_D}.po: ${_DSRC} ${POBJS:S/^${_D}.po$//}
+${_D}.po: ${_DSRC} ${POBJS:S/^${_D}.po$//} ${OP_META}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
.endif
@@ -243,7 +245,7 @@ DPSRCS+= ${SRCS}
# A .depend file will only be generated if there are commands in
# beforedepend/_EXTRADEPEND/afterdepend. The target is kept
# to allow 'make depend' to generate files.
-${DEPENDFILE}: ${DPSRCS}
+${DEPENDFILE}: ${DPSRCS} ${OP_META}
.if !empty(.MAKE.MODE:Mmeta) || exists(${.OBJDIR}/${DEPENDFILE})
rm -f ${DEPENDFILE}
.endif
diff --git a/share/mk/bsd.info.mk b/share/mk/bsd.info.mk
index eeb0da3..832f59f 100644
--- a/share/mk/bsd.info.mk
+++ b/share/mk/bsd.info.mk
@@ -86,18 +86,18 @@ DVIPS2ASCII?= dvips2ascii
.SUFFIXES: ${ICOMPRESS_EXT} .info .texi .texinfo .dvi .ps .latin1 .html
-.texi.info .texinfo.info:
+.texi.info .texinfo.info: ${OP_META}
${MAKEINFO} ${MAKEINFOFLAGS} -I ${.CURDIR} -I ${SRCDIR} ${.IMPSRC} \
-o ${.TARGET}
-.texi.dvi .texinfo.dvi:
+.texi.dvi .texinfo.dvi: ${OP_META}
TEXINPUTS=${.CURDIR}:${SRCDIR}:$$TEXINPUTS \
${TEX} ${.IMPSRC} </dev/null
# Run again to resolve cross references.
TEXINPUTS=${.CURDIR}:${SRCDIR}:$$TEXINPUTS \
${TEX} ${.IMPSRC} </dev/null
-.texinfo.latin1 .texi.latin1:
+.texinfo.latin1 .texi.latin1: ${OP_META}
perl -npe 's/(^\s*\\input\s+texinfo\s+)/$$1\n@tex\n\\global\\hsize=120mm\n@end tex\n\n/' ${.IMPSRC} >> ${.IMPSRC:T:R}-la.texi
TEXINPUTS=${.CURDIR}:${SRCDIR}:$$TEXINPUTS \
${TEX} ${.IMPSRC:T:R}-la.texi </dev/null
@@ -108,10 +108,10 @@ DVIPS2ASCII?= dvips2ascii
${DVIPS2ASCII} > ${.TARGET}.new
mv -f ${.TARGET}.new ${.TARGET}
-.dvi.ps:
+.dvi.ps: ${OP_META}
${DVIPS} -o ${.TARGET} ${.IMPSRC}
-.info.html:
+.info.html: ${OP_META}
${INFO2HTML} ${.IMPSRC}
${INSTALL_LINK} ${.TARGET:R}.info.Top.html ${.TARGET}
@@ -133,7 +133,7 @@ all: ${IFILES}
.endif
.for x in ${IFILENS}
-${x:S/$/${ICOMPRESS_EXT}/}: ${x}
+${x:S/$/${ICOMPRESS_EXT}/}: ${x} ${OP_META}
${ICOMPRESS_CMD} ${.ALLSRC} > ${.TARGET}
.endfor
@@ -158,7 +158,7 @@ ${x:S/$/-install/}:
.if defined(SRCS)
CLEANFILES+= ${INFO}.texi
-${INFO}.texi: ${SRCS}
+${INFO}.texi: ${SRCS} ${OP_META}
cat ${.ALLSRC} > ${.TARGET}
.endif
diff --git a/share/mk/bsd.kmod.mk b/share/mk/bsd.kmod.mk
index 09ac8e3..d0ac48b 100644
--- a/share/mk/bsd.kmod.mk
+++ b/share/mk/bsd.kmod.mk
@@ -4,7 +4,7 @@
.for _dir in ${.CURDIR}/../.. ${.CURDIR}/../../.. ${.CURDIR}/../../../.. \
${.CURDIR}/../../../../.. /sys /usr/src/sys
.if !defined(SYSDIR) && exists(${_dir}/kern/) && exists(${_dir}/conf/kmod.mk)
-SYSDIR= ${_dir}
+SYSDIR= ${_dir:tA}
.endif
.endfor
.if !defined(SYSDIR) || !exists(${SYSDIR}/kern/) || \
diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk
index 971577c..97d703c 100644
--- a/share/mk/bsd.lib.mk
+++ b/share/mk/bsd.lib.mk
@@ -91,55 +91,55 @@ PICFLAG=-fpic
PO_FLAG=-pg
-.c.o:
+.c.o: ${OP_META}
${CC} ${STATIC_CFLAGS} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.c.po:
+.c.po: ${OP_META}
${CC} ${PO_FLAG} ${STATIC_CFLAGS} ${PO_CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.c.So:
+.c.So: ${OP_META}
${CC} ${PICFLAG} -DPIC ${SHARED_CFLAGS} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.cc.o .C.o .cpp.o .cxx.o:
+.cc.o .C.o .cpp.o .cxx.o: ${OP_META}
${CXX} ${STATIC_CXXFLAGS} ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
-.cc.po .C.po .cpp.po .cxx.po:
+.cc.po .C.po .cpp.po .cxx.po: ${OP_META}
${CXX} ${PO_FLAG} ${STATIC_CXXFLAGS} ${PO_CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
-.cc.So .C.So .cpp.So .cxx.So:
+.cc.So .C.So .cpp.So .cxx.So: ${OP_META}
${CXX} ${PICFLAG} -DPIC ${SHARED_CXXFLAGS} ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
-.f.po:
+.f.po: ${OP_META}
${FC} -pg ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC}
${CTFCONVERT_CMD}
-.f.So:
+.f.So: ${OP_META}
${FC} ${PICFLAG} -DPIC ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC}
${CTFCONVERT_CMD}
-.s.po .s.So:
+.s.po .s.So: ${OP_META}
${AS} ${AFLAGS} -o ${.TARGET} ${.IMPSRC}
${CTFCONVERT_CMD}
-.asm.po:
+.asm.po: ${OP_META}
${CC:N${CCACHE_BIN}} -x assembler-with-cpp -DPROF ${PO_CFLAGS} \
${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.asm.So:
+.asm.So: ${OP_META}
${CC:N${CCACHE_BIN}} -x assembler-with-cpp ${PICFLAG} -DPIC \
${CFLAGS} ${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.S.po:
+.S.po: ${OP_META}
${CC:N${CCACHE_BIN}} -DPROF ${PO_CFLAGS} ${ACFLAGS} -c ${.IMPSRC} \
-o ${.TARGET}
${CTFCONVERT_CMD}
-.S.So:
+.S.So: ${OP_META}
${CC:N${CCACHE_BIN}} ${PICFLAG} -DPIC ${CFLAGS} ${ACFLAGS} \
-c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
@@ -183,7 +183,7 @@ CLEANFILES+= ${OBJS} ${STATICOBJS}
.if defined(LIB) && !empty(LIB)
_LIBS= lib${LIB_PRIVATE}${LIB}.a
-lib${LIB_PRIVATE}${LIB}.a: ${OBJS} ${STATICOBJS}
+lib${LIB_PRIVATE}${LIB}.a: ${OBJS} ${STATICOBJS} ${OP_META}
@${ECHO} building static ${LIB} library
@rm -f ${.TARGET}
${AR} ${ARFLAGS} ${.TARGET} `NM='${NM}' NMFLAGS='${NMFLAGS}' lorder ${OBJS} ${STATICOBJS} | tsort -q` ${ARADD}
@@ -198,7 +198,7 @@ POBJS+= ${OBJS:.o=.po} ${STATICOBJS:.o=.po}
DEPENDOBJS+= ${POBJS}
CLEANFILES+= ${POBJS}
-lib${LIB_PRIVATE}${LIB}_p.a: ${POBJS}
+lib${LIB_PRIVATE}${LIB}_p.a: ${POBJS} ${OP_META}
@${ECHO} building profiled ${LIB} library
@rm -f ${.TARGET}
${AR} ${ARFLAGS} ${.TARGET} `NM='${NM}' NMFLAGS='${NMFLAGS}' lorder ${POBJS} | tsort -q` ${ARADD}
@@ -230,7 +230,7 @@ ${SHLIB_NAME_FULL}: beforelinking
.if defined(SHLIB_LINK)
.if defined(SHLIB_LDSCRIPT) && !empty(SHLIB_LDSCRIPT) && exists(${.CURDIR}/${SHLIB_LDSCRIPT})
-${SHLIB_LINK:R}.ld: ${.CURDIR}/${SHLIB_LDSCRIPT}
+${SHLIB_LINK:R}.ld: ${.CURDIR}/${SHLIB_LDSCRIPT} ${OP_META}
sed -e 's,@@SHLIB@@,${_SHLIBDIR}/${SHLIB_NAME},g' \
-e 's,@@LIBDIR@@,${_LIBDIR},g' \
${.ALLSRC} > ${.TARGET}
@@ -241,7 +241,7 @@ CLEANFILES+= ${SHLIB_LINK:R}.ld
CLEANFILES+= ${SHLIB_LINK}
.endif
-${SHLIB_NAME_FULL}: ${SOBJS}
+${SHLIB_NAME_FULL}: ${SOBJS} ${OP_META}
@${ECHO} building shared library ${SHLIB_NAME}
@rm -f ${SHLIB_NAME} ${SHLIB_LINK}
.if defined(SHLIB_LINK) && !commands(${SHLIB_LINK:R}.ld)
@@ -256,11 +256,11 @@ ${SHLIB_NAME_FULL}: ${SOBJS}
.if ${MK_DEBUG_FILES} != "no"
CLEANFILES+= ${SHLIB_NAME_FULL} ${SHLIB_NAME}.debug
-${SHLIB_NAME}: ${SHLIB_NAME_FULL} ${SHLIB_NAME}.debug
+${SHLIB_NAME}: ${SHLIB_NAME_FULL} ${SHLIB_NAME}.debug ${OP_META}
${OBJCOPY} --strip-debug --add-gnu-debuglink=${SHLIB_NAME}.debug \
${SHLIB_NAME_FULL} ${.TARGET}
-${SHLIB_NAME}.debug: ${SHLIB_NAME_FULL}
+${SHLIB_NAME}.debug: ${SHLIB_NAME_FULL} ${OP_META}
${OBJCOPY} --only-keep-debug ${SHLIB_NAME_FULL} ${.TARGET}
.endif
.endif #defined(SHLIB_NAME)
@@ -268,7 +268,7 @@ ${SHLIB_NAME}.debug: ${SHLIB_NAME_FULL}
.if defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB) && ${MK_TOOLCHAIN} != "no"
_LIBS+= lib${LIB_PRIVATE}${LIB}_pic.a
-lib${LIB_PRIVATE}${LIB}_pic.a: ${SOBJS}
+lib${LIB_PRIVATE}${LIB}_pic.a: ${SOBJS} ${OP_META}
@${ECHO} building special pic ${LIB} library
@rm -f ${.TARGET}
${AR} ${ARFLAGS} ${.TARGET} ${SOBJS} ${ARADD}
@@ -281,7 +281,7 @@ _LIBS+= ${LINTLIB}
LINTOBJS+= ${SRCS:M*.c:.c=.ln}
CLEANFILES+= ${LINTOBJS}
-${LINTLIB}: ${LINTOBJS}
+${LINTLIB}: ${LINTOBJS} ${OP_META}
@${ECHO} building lint library ${.TARGET}
@rm -f ${.TARGET}
${LINT} ${LINTLIBFLAGS} ${CFLAGS:M-[DIU]*} ${.ALLSRC}
diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk
index d7e00e6..e290624 100644
--- a/share/mk/bsd.libnames.mk
+++ b/share/mk/bsd.libnames.mk
@@ -22,6 +22,7 @@ LIBATM?= ${DESTDIR}${LIBDIR}/libatm.a
LIBAUDITD?= ${DESTDIR}${LIBDIR}/libauditd.a
LIBAVL?= ${DESTDIR}${LIBDIR}/libavl.a
LIBBEGEMOT?= ${DESTDIR}${LIBDIR}/libbegemot.a
+LIBBLACKLIST?= ${DESTDIR}${LIBDIR}/libblacklist.a
LIBBLUETOOTH?= ${DESTDIR}${LIBDIR}/libbluetooth.a
LIBBSDXML?= ${DESTDIR}${LIBDIR}/libbsdxml.a
LIBBSM?= ${DESTDIR}${LIBDIR}/libbsm.a
@@ -49,6 +50,7 @@ LIBCXGB4?= ${DESTDIR}${LIBDIR}/libcxgb4.a
LIBCXXRT?= ${DESTDIR}${LIBDIR}/libcxxrt.a
LIBC_PIC?= ${DESTDIR}${LIBDIR}/libc_pic.a
LIBDEVCTL?= ${DESTDIR}${LIBDIR}/libdevctl.a
+LIBDEVDCTL?= ${DESTDIR}${LIBDIR}/libdevdctl.a
LIBDEVINFO?= ${DESTDIR}${LIBDIR}/libdevinfo.a
LIBDEVSTAT?= ${DESTDIR}${LIBDIR}/libdevstat.a
LIBDIALOG?= ${DESTDIR}${LIBDIR}/libdialog.a
diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk
index eca0139..d96269c 100644
--- a/share/mk/bsd.man.mk
+++ b/share/mk/bsd.man.mk
@@ -99,7 +99,7 @@ ${__target}: ${__page}
.if defined(MANBUILDCAT) && !empty(MANBUILDCAT)
.for __target in ${__page:T:S/$/${CATEXT}${FILTEXTENSION}/g}
all-man: ${__target}
-${__target}: ${__page}
+${__target}: ${__page} ${OP_META}
${MANFILTER} < ${.ALLSRC} | ${MANDOC_CMD} > ${.TARGET}
.endfor
.endif
@@ -112,7 +112,7 @@ CLEANFILES+= ${MAN:T:S/$/${CATEXT}/g}
.for __page in ${MAN}
.for __target in ${__page:T:S/$/${CATEXT}/g}
all-man: ${__target}
-${__target}: ${__page}
+${__target}: ${__page} ${OP_META}
${MANDOC_CMD} ${.ALLSRC} > ${.TARGET}
.endfor
.endfor
@@ -148,7 +148,7 @@ CLEANFILES+= ${MAN:T:S/$/${CATEXT}${MCOMPRESS_EXT}/g}
.for __page in ${MAN}
.for __target in ${__page:T:S/$/${MCOMPRESS_EXT}/}
all-man: ${__target}
-${__target}: ${__page}
+${__target}: ${__page} ${OP_META}
.if defined(MANFILTER)
${MANFILTER} < ${.ALLSRC} | ${MCOMPRESS_CMD} > ${.TARGET}
.else
@@ -158,7 +158,7 @@ ${__target}: ${__page}
.if defined(MANBUILDCAT) && !empty(MANBUILDCAT)
.for __target in ${__page:T:S/$/${CATEXT}${MCOMPRESS_EXT}/}
all-man: ${__target}
-${__target}: ${__page}
+${__target}: ${__page} ${OP_META}
.if defined(MANFILTER)
${MANFILTER} < ${.ALLSRC} | ${MANDOC_CMD} | ${MCOMPRESS_CMD} > ${.TARGET}
.else
diff --git a/share/mk/bsd.nls.mk b/share/mk/bsd.nls.mk
index d160a2b..980ba95 100644
--- a/share/mk/bsd.nls.mk
+++ b/share/mk/bsd.nls.mk
@@ -42,7 +42,7 @@ NLSSRCFILES_${file}?= ${NLSSRCFILES}
.endif
.if defined(NLSSRCFILES_${file})
NLSSRCDIR_${file}?= ${NLSSRCDIR}
-${file}.msg: ${NLSSRCFILES_${file}:S/^/${NLSSRCDIR_${file}}\//}
+${file}.msg: ${NLSSRCFILES_${file}:S/^/${NLSSRCDIR_${file}}\//} ${OP_META}
@rm -f ${.TARGET}
cat ${.ALLSRC} > ${.TARGET}
CLEANFILES+= ${file}.msg
diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk
index 742eba9..3307dba 100644
--- a/share/mk/bsd.prog.mk
+++ b/share/mk/bsd.prog.mk
@@ -90,7 +90,7 @@ OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
beforelinking: ${OBJS}
${PROG_FULL}: beforelinking
.endif
-${PROG_FULL}: ${OBJS}
+${PROG_FULL}: ${OBJS} ${OP_META}
.if defined(PROG_CXX)
${CXX:N${CCACHE_BIN}} ${CXXFLAGS:N-M*} ${LDFLAGS} -o ${.TARGET} \
${OBJS} ${LDADD}
@@ -122,7 +122,7 @@ OBJS+= ${PROG}.o
beforelinking: ${OBJS}
${PROG_FULL}: beforelinking
.endif
-${PROG_FULL}: ${OBJS}
+${PROG_FULL}: ${OBJS} ${OP_META}
.if defined(PROG_CXX)
${CXX:N${CCACHE_BIN}} ${CXXFLAGS:N-M*} ${LDFLAGS} -o ${.TARGET} \
${OBJS} ${LDADD}
@@ -138,11 +138,11 @@ ${PROG_FULL}: ${OBJS}
.endif # !defined(SRCS)
.if ${MK_DEBUG_FILES} != "no"
-${PROG}: ${PROG_FULL} ${PROGNAME}.debug
+${PROG}: ${PROG_FULL} ${PROGNAME}.debug ${OP_META}
${OBJCOPY} --strip-debug --add-gnu-debuglink=${PROGNAME}.debug \
${PROG_FULL} ${.TARGET}
-${PROGNAME}.debug: ${PROG_FULL}
+${PROGNAME}.debug: ${PROG_FULL} ${OP_META}
${OBJCOPY} --only-keep-debug ${PROG_FULL} ${.TARGET}
.endif
diff --git a/share/mk/bsd.subdir.mk b/share/mk/bsd.subdir.mk
index ba31e82..f1b0970 100644
--- a/share/mk/bsd.subdir.mk
+++ b/share/mk/bsd.subdir.mk
@@ -72,10 +72,9 @@ DISTRIBUTION?= base
distribute: .MAKE
.for dist in ${DISTRIBUTION}
${_+_}cd ${.CURDIR}; \
- ${MAKE} install -DNO_SUBDIR DESTDIR=${DISTDIR}/${dist} SHARED=copies
+ ${MAKE} install installconfig -DNO_SUBDIR DESTDIR=${DISTDIR}/${dist} SHARED=copies
.endfor
.endif
-
# Convenience targets to run 'build${target}' and 'install${target}' when
# calling 'make ${target}'.
.for __target in files includes
diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk
index 7f74de1..4f157be 100644
--- a/share/mk/bsd.sys.mk
+++ b/share/mk/bsd.sys.mk
@@ -178,32 +178,6 @@ ACFLAGS+= ${ACFLAGS.${.IMPSRC:T}}
CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
CXXFLAGS+= ${CXXFLAGS.${.IMPSRC:T}}
-# Special handling for external GCC.
-.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == "gcc"
-# GCC's --sysroot support for a cross-compiler without a default
-# TARGET_SYSTEM_ROOT does not add sysroot/usr/include in or the C++
-# include path of sysroot/usr/include/c++/v1. They need to be added in
-# when not using -nostdinc/-nostdinc++. This is not a problem with a
-# non-cross-compiler external GCC or the in-tree cross-compiler GCC which
-# has a default TARGET_SYSTEM_ROOT.
-.if ${CC:M--sysroot=*} || ${CFLAGS:M--sysroot=*}
-.if ${CFLAGS:M-nostdinc} == ""
-CFLAGS+= -isystem =/usr/include
-.endif
-# Add in sysroot/usr/lib to ensure that it comes before /usr/local/lib
-# from ports compilers.
-LDFLAGS+= -L=/usr/lib
-# We want to force building the system with our in-tree libc++. Note that
-# this also requires a symlink in OBJDIR/lib/libc++/libstdc++.so to
-# sysroot/usr/lib/libc++.so.
-.if ${CXXFLAGS:M-nostdinc++} == "" && ${CXXFLAGS:M-nostdlib} == ""
-CXXFLAGS+= -std=c++11 \
- -nostdinc++ -isystem =/usr/include/c++/v1
-LDFLAGS+= -L${OBJTOP}/lib/libc++
-.endif
-.endif # --sysroot
-.endif # X_COMPILER_TYPE == gcc
-
.if defined(SRCTOP)
# Prevent rebuilding during install to support read-only objdirs.
.if !make(all) && make(install) && empty(.MAKE.MODE:Mmeta)
diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk
index ad61787..30fab90 100644
--- a/share/mk/src.libnames.mk
+++ b/share/mk/src.libnames.mk
@@ -16,6 +16,7 @@ _PRIVATELIBS= \
atf_c \
atf_cxx \
bsdstat \
+ devdctl \
event \
heimipcc \
heimipcs \
@@ -82,6 +83,7 @@ _LIBRARIES= \
cuse \
cxxrt \
devctl \
+ devdctl \
devinfo \
devstat \
dialog \
@@ -176,6 +178,12 @@ _LIBRARIES= \
zfs \
zpool \
+.if ${MK_BLACKLIST} != "no"
+_LIBRARIES+= \
+ blacklist \
+
+.endif
+
.if ${MK_OFED} != "no"
_LIBRARIES+= \
cxgb4 \
@@ -198,6 +206,9 @@ _LIBRARIES+= \
# 2nd+ order consumers. Auto-generating this would be better.
_DP_80211= sbuf bsdxml
_DP_archive= z bz2 lzma bsdxml
+.if ${MK_BLACKLIST} != "no"
+_DP_blacklist+= pthread
+.endif
.if ${MK_OPENSSL} != "no"
_DP_archive+= crypto
.else
@@ -500,9 +511,10 @@ LIBWINDDIR= ${OBJTOP}/kerberos5/lib/libwind
LIBATF_CDIR= ${OBJTOP}/lib/atf/libatf-c
LIBATF_CXXDIR= ${OBJTOP}/lib/atf/libatf-c++
LIBALIASDIR= ${OBJTOP}/lib/libalias/libalias
+LIBBLACKLISTDIR= ${OBJTOP}/lib/libblacklist
LIBBLOCKSRUNTIMEDIR= ${OBJTOP}/lib/libblocksruntime
LIBBSNMPDIR= ${OBJTOP}/lib/libbsnmp/libbsnmp
-LIBCAP_CASPERDIR= ${OBJTOP}/lib/libcasper/libcasper
+LIBCASPERDIR= ${OBJTOP}/lib/libcasper/libcasper
LIBCAP_DNSDIR= ${OBJTOP}/lib/libcasper/services/cap_dns
LIBCAP_GRPDIR= ${OBJTOP}/lib/libcasper/services/cap_grp
LIBCAP_PWDDIR= ${OBJTOP}/lib/libcasper/services/cap_pwd
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index 27444d7..30fe118 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -56,6 +56,7 @@ __DEFAULT_YES_OPTIONS = \
BHYVE \
BINUTILS \
BINUTILS_BOOTSTRAP \
+ BLACKLIST \
BLUETOOTH \
BOOT \
BOOTPARAMD \
@@ -374,6 +375,7 @@ MK_CLANG_FULL:= no
# MK_* variable is set to "no".
#
.for var in \
+ BLACKLIST \
BZIP2 \
GNU \
INET \
diff --git a/share/mk/sys.mk b/share/mk/sys.mk
index bdf604b..bea1c71 100644
--- a/share/mk/sys.mk
+++ b/share/mk/sys.mk
@@ -52,12 +52,18 @@ META_MODE+= meta verbose
META_MODE+= silent=yes
.endif
.if !exists(/dev/filemon)
+.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !defined(NO_FILEMON)
+.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded.
+.endif
META_MODE+= nofilemon
.endif
.endif
META_MODE?= normal
.export META_MODE
.MAKE.MODE?= ${META_MODE}
+.if ${.MAKE.MODE:Mmeta*} != ""
+OP_META= .META
+.endif
.if ${MK_AUTO_OBJ} == "yes"
# This needs to be done early - before .PATH is computed
@@ -286,99 +292,99 @@ YFLAGS ?= -d
# non-Posix rule set
-.sh:
+.sh: ${OP_META}
cp -f ${.IMPSRC} ${.TARGET}
chmod a+x ${.TARGET}
-.c.ln:
+.c.ln: ${OP_META}
${LINT} ${LINTOBJFLAGS} ${CFLAGS:M-[DIU]*} ${.IMPSRC} || \
touch ${.TARGET}
-.cc.ln .C.ln .cpp.ln .cxx.ln:
+.cc.ln .C.ln .cpp.ln .cxx.ln: ${OP_META}
${LINT} ${LINTOBJFLAGS} ${CXXFLAGS:M-[DIU]*} ${.IMPSRC} || \
touch ${.TARGET}
-.c:
+.c: ${OP_META}
${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
${CTFCONVERT_CMD}
-.c.o:
+.c.o: ${OP_META}
${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.cc .cpp .cxx .C:
+.cc .cpp .cxx .C: ${OP_META}
${CXX} ${CXXFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
-.cc.o .cpp.o .cxx.o .C.o:
+.cc.o .cpp.o .cxx.o .C.o: ${OP_META}
${CXX} ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
-.m.o:
+.m.o: ${OP_META}
${OBJC} ${OBJCFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.p.o:
+.p.o: ${OP_META}
${PC} ${PFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.e .r .F .f:
+.e .r .F .f: ${OP_META}
${FC} ${RFLAGS} ${EFLAGS} ${FFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} \
-o ${.TARGET}
-.e.o .r.o .F.o .f.o:
+.e.o .r.o .F.o .f.o: ${OP_META}
${FC} ${RFLAGS} ${EFLAGS} ${FFLAGS} -c ${.IMPSRC} -o ${.TARGET}
-.S.o:
+.S.o: ${OP_META}
${CC:N${CCACHE_BIN}} ${CFLAGS} ${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
-.asm.o:
+.asm.o: ${OP_META}
${CC:N${CCACHE_BIN}} -x assembler-with-cpp ${CFLAGS} ${ACFLAGS} -c ${.IMPSRC} \
-o ${.TARGET}
${CTFCONVERT_CMD}
-.s.o:
+.s.o: ${OP_META}
${AS} ${AFLAGS} -o ${.TARGET} ${.IMPSRC}
${CTFCONVERT_CMD}
# XXX not -j safe
-.y.o:
+.y.o: ${OP_META}
${YACC} ${YFLAGS} ${.IMPSRC}
${CC} ${CFLAGS} -c y.tab.c -o ${.TARGET}
rm -f y.tab.c
${CTFCONVERT_CMD}
-.l.o:
+.l.o: ${OP_META}
${LEX} -t ${LFLAGS} ${.IMPSRC} > ${.PREFIX}.tmp.c
${CC} ${CFLAGS} -c ${.PREFIX}.tmp.c -o ${.TARGET}
rm -f ${.PREFIX}.tmp.c
${CTFCONVERT_CMD}
# XXX not -j safe
-.y.c:
+.y.c: ${OP_META}
${YACC} ${YFLAGS} ${.IMPSRC}
mv y.tab.c ${.TARGET}
-.l.c:
+.l.c: ${OP_META}
${LEX} -t ${LFLAGS} ${.IMPSRC} > ${.TARGET}
-.s.out .c.out .o.out:
+.s.out .c.out .o.out: ${OP_META}
${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
${CTFCONVERT_CMD}
-.f.out .F.out .r.out .e.out:
+.f.out .F.out .r.out .e.out: ${OP_META}
${FC} ${EFLAGS} ${RFLAGS} ${FFLAGS} ${LDFLAGS} ${.IMPSRC} \
${LDLIBS} -o ${.TARGET}
rm -f ${.PREFIX}.o
${CTFCONVERT_CMD}
# XXX not -j safe
-.y.out:
+.y.out: ${OP_META}
${YACC} ${YFLAGS} ${.IMPSRC}
${CC} ${CFLAGS} ${LDFLAGS} y.tab.c ${LDLIBS} -ly -o ${.TARGET}
rm -f y.tab.c
${CTFCONVERT_CMD}
-.l.out:
+.l.out: ${OP_META}
${LEX} -t ${LFLAGS} ${.IMPSRC} > ${.PREFIX}.tmp.c
${CC} ${CFLAGS} ${LDFLAGS} ${.PREFIX}.tmp.c ${LDLIBS} -ll -o ${.TARGET}
rm -f ${.PREFIX}.tmp.c
diff --git a/share/timedef/am_ET.UTF-8.src b/share/timedef/am_ET.UTF-8.src
index 1665ccf..c69c0ff 100644
--- a/share/timedef/am_ET.UTF-8.src
+++ b/share/timedef/am_ET.UTF-8.src
@@ -56,14 +56,14 @@
%d/%m/%Y
#
# c_fmt
-%e %B %Y %I:%M:%S %p
+%A %e %B %Y %I:%M:%S %p
#
# AM/PM
ጥዋት
ከሰዓት
#
# date_fmt
-%e %B %Y %I:%M:%S %p %Z
+%A %e %B %Y %I:%M:%S %p %Z
#
# Long month names (without case ending)
ጃንዩወሪ
diff --git a/share/timedef/be_BY.CP1131.src b/share/timedef/be_BY.CP1131.src
index a422d40..1430d69 100644
--- a/share/timedef/be_BY.CP1131.src
+++ b/share/timedef/be_BY.CP1131.src
@@ -56,14 +56,14 @@
%e.%m.%y
#
# c_fmt
-%e %B %Y %H.%M.%S
+%A %e %B %Y %H.%M.%S
#
# AM/PM
#
# date_fmt
-%e %B %Y %H.%M.%S %Z
+%A %e %B %Y %H.%M.%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/be_BY.CP1251.src b/share/timedef/be_BY.CP1251.src
index 8340484..3782989 100644
--- a/share/timedef/be_BY.CP1251.src
+++ b/share/timedef/be_BY.CP1251.src
@@ -56,14 +56,14 @@
%e.%m.%y
#
# c_fmt
-%e %B %Y %H.%M.%S
+%A %e %B %Y %H.%M.%S
#
# AM/PM
#
# date_fmt
-%e %B %Y %H.%M.%S %Z
+%A %e %B %Y %H.%M.%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/be_BY.ISO8859-5.src b/share/timedef/be_BY.ISO8859-5.src
index 369eddd..3d8037d 100644
--- a/share/timedef/be_BY.ISO8859-5.src
+++ b/share/timedef/be_BY.ISO8859-5.src
@@ -56,14 +56,14 @@
%e.%m.%y
#
# c_fmt
-%e %B %Y %H.%M.%S
+%A %e %B %Y %H.%M.%S
#
# AM/PM
#
# date_fmt
-%e %B %Y %H.%M.%S %Z
+%A %e %B %Y %H.%M.%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/be_BY.UTF-8.src b/share/timedef/be_BY.UTF-8.src
index 4a4e39d..ee0552f 100644
--- a/share/timedef/be_BY.UTF-8.src
+++ b/share/timedef/be_BY.UTF-8.src
@@ -56,14 +56,14 @@
%e.%m.%y
#
# c_fmt
-%e %B %Y %H.%M.%S
+%A %e %B %Y %H.%M.%S
#
# AM/PM
да палудня
пасля палудня
#
# date_fmt
-%e %B %Y %H.%M.%S %Z
+%A %e %B %Y %H.%M.%S %Z
#
# Long month names (without case ending)
студзень
diff --git a/share/timedef/bg_BG.CP1251.src b/share/timedef/bg_BG.CP1251.src
index 6001e49..1cef479 100644
--- a/share/timedef/bg_BG.CP1251.src
+++ b/share/timedef/bg_BG.CP1251.src
@@ -56,14 +56,14 @@
%e.%m.%y г.
#
# c_fmt
-%e %B %Y ., %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
..
..
#
# date_fmt
-%e %B %Y ., %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/bg_BG.UTF-8.src b/share/timedef/bg_BG.UTF-8.src
index a874d4d..e80a7fb 100644
--- a/share/timedef/bg_BG.UTF-8.src
+++ b/share/timedef/bg_BG.UTF-8.src
@@ -56,14 +56,14 @@
%e.%m.%y г.
#
# c_fmt
-%e %B %Y г., %H:%M:%S
+%A %e %B %Y г. %H:%M:%S
#
# AM/PM
пр.об.
сл.об.
#
# date_fmt
-%e %B %Y г., %H:%M:%S %Z
+%A %e %B %Y г. %H:%M:%S %Z
#
# Long month names (without case ending)
януари
diff --git a/share/timedef/ca_IT.ISO8859-15.src b/share/timedef/ca_IT.ISO8859-15.src
index ab8c50e..fdfb05e 100644
--- a/share/timedef/ca_IT.ISO8859-15.src
+++ b/share/timedef/ca_IT.ISO8859-15.src
@@ -56,14 +56,14 @@ dissabte
%e/%m/%y
#
# c_fmt
-%e %B de %Y, %H:%M:%S
+%A %e %B de %Y, %H:%M:%S
#
# AM/PM
a. m.
p. m.
#
# date_fmt
-%e %B de %Y, %H:%M:%S %Z
+%A %e %B de %Y, %H:%M:%S %Z
#
# Long month names (without case ending)
de gener
diff --git a/share/timedef/ca_IT.UTF-8.src b/share/timedef/ca_IT.UTF-8.src
index 14ecf9d..4d98358 100644
--- a/share/timedef/ca_IT.UTF-8.src
+++ b/share/timedef/ca_IT.UTF-8.src
@@ -56,14 +56,14 @@ dissabte
%e/%m/%y
#
# c_fmt
-%e %B de %Y, %H:%M:%S
+%A %e %B de %Y, %H:%M:%S
#
# AM/PM
a. m.
p. m.
#
# date_fmt
-%e %B de %Y, %H:%M:%S %Z
+%A %e %B de %Y, %H:%M:%S %Z
#
# Long month names (without case ending)
de gener
diff --git a/share/timedef/el_GR.ISO8859-7.src b/share/timedef/el_GR.ISO8859-7.src
index 8ca153f..13b25ee 100644
--- a/share/timedef/el_GR.ISO8859-7.src
+++ b/share/timedef/el_GR.ISO8859-7.src
@@ -56,14 +56,14 @@
%e/%m/%y
#
# c_fmt
-%e %B %Y - %I:%M:%S %p
+%A %e %B %Y - %I:%M:%S %p
#
# AM/PM
..
..
#
# date_fmt
-%e %B %Y - %I:%M:%S %p %Z
+%A %e %B %Y - %I:%M:%S %p %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/el_GR.UTF-8.src b/share/timedef/el_GR.UTF-8.src
index b40ec69..13f217b 100644
--- a/share/timedef/el_GR.UTF-8.src
+++ b/share/timedef/el_GR.UTF-8.src
@@ -56,14 +56,14 @@
%e/%m/%y
#
# c_fmt
-%e %B %Y - %I:%M:%S %p
+%A %e %B %Y - %I:%M:%S %p
#
# AM/PM
π.μ.
μ.μ.
#
# date_fmt
-%e %B %Y - %I:%M:%S %p %Z
+%A %e %B %Y - %I:%M:%S %p %Z
#
# Long month names (without case ending)
Ιανουάριος
diff --git a/share/timedef/en_CA.UTF-8.src b/share/timedef/en_CA.UTF-8.src
index e0fafe5..181f0aa 100644
--- a/share/timedef/en_CA.UTF-8.src
+++ b/share/timedef/en_CA.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%Y-%m-%d
#
# c_fmt
-%B %e, %Y at %I:%M:%S %p
+%A, %B %e, %Y at %I:%M:%S %p
#
# AM/PM
AM
PM
#
# date_fmt
-%B %e, %Y at %I:%M:%S %p %Z
+%A, %B %e, %Y at %I:%M:%S %p %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/en_GB.UTF-8.src b/share/timedef/en_GB.UTF-8.src
index fbbb1ac..5479d5b 100644
--- a/share/timedef/en_GB.UTF-8.src
+++ b/share/timedef/en_GB.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%d/%m/%Y
#
# c_fmt
-%e %B %Y at %H:%M:%S
+%A %e %B %Y at %H:%M:%S
#
# AM/PM
a.m.
p.m.
#
# date_fmt
-%e %B %Y at %H:%M:%S %Z
+%A %e %B %Y at %H:%M:%S %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/en_HK.UTF-8.src b/share/timedef/en_HK.UTF-8.src
index ba093ad..f7fd696 100644
--- a/share/timedef/en_HK.UTF-8.src
+++ b/share/timedef/en_HK.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%e/%m/%Y
#
# c_fmt
-%e %B %Y at %I:%M:%S %p
+%A %e %B %Y at %I:%M:%S %p
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y at %I:%M:%S %p %Z
+%A %e %B %Y at %I:%M:%S %p %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/en_IE.UTF-8.src b/share/timedef/en_IE.UTF-8.src
index b27f9c9..a4eeab9 100644
--- a/share/timedef/en_IE.UTF-8.src
+++ b/share/timedef/en_IE.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%d/%m/%Y
#
# c_fmt
-%e %B %Y at %I:%M:%S %p
+%A %e %B %Y at %I:%M:%S %p
#
# AM/PM
a.m.
p.m.
#
# date_fmt
-%e %B %Y at %I:%M:%S %p %Z
+%A %e %B %Y at %I:%M:%S %p %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/en_PH.UTF-8.src b/share/timedef/en_PH.UTF-8.src
index 17faae6..788c0f5 100644
--- a/share/timedef/en_PH.UTF-8.src
+++ b/share/timedef/en_PH.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%d/%m/%Y
#
# c_fmt
-%e %B %Y at %I:%M:%S %p
+%A %e %B %Y at %I:%M:%S %p
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y at %I:%M:%S %p %Z
+%A %e %B %Y at %I:%M:%S %p %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/en_SG.UTF-8.src b/share/timedef/en_SG.UTF-8.src
index 8c44f5c..3fde7c6 100644
--- a/share/timedef/en_SG.UTF-8.src
+++ b/share/timedef/en_SG.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%e/%m/%y
#
# c_fmt
-%e %B %Y at %I:%M:%S %p
+%A %e %B %Y at %I:%M:%S %p
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y at %I:%M:%S %p %Z
+%A %e %B %Y at %I:%M:%S %p %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/en_US.UTF-8.src b/share/timedef/en_US.UTF-8.src
index b3a5717..a956cb3 100644
--- a/share/timedef/en_US.UTF-8.src
+++ b/share/timedef/en_US.UTF-8.src
@@ -56,14 +56,14 @@ Saturday
%m/%e/%y
#
# c_fmt
-%B %e, %Y at %I:%M:%S %p
+%A, %B %e, %Y at %I:%M:%S %p
#
# AM/PM
AM
PM
#
# date_fmt
-%B %e, %Y at %I:%M:%S %p %Z
+%A, %B %e, %Y at %I:%M:%S %p %Z
#
# Long month names (without case ending)
January
diff --git a/share/timedef/fr_BE.ISO8859-15.src b/share/timedef/fr_BE.ISO8859-15.src
index 4569555..7e976a4 100644
--- a/share/timedef/fr_BE.ISO8859-15.src
+++ b/share/timedef/fr_BE.ISO8859-15.src
@@ -56,14 +56,14 @@ samedi
%e/%m/%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_BE.UTF-8.src b/share/timedef/fr_BE.UTF-8.src
index 7544e20..c1d393d 100644
--- a/share/timedef/fr_BE.UTF-8.src
+++ b/share/timedef/fr_BE.UTF-8.src
@@ -56,14 +56,14 @@ samedi
%e/%m/%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_CA.ISO8859-15.src b/share/timedef/fr_CA.ISO8859-15.src
index 1fb71de..a45b7df 100644
--- a/share/timedef/fr_CA.ISO8859-15.src
+++ b/share/timedef/fr_CA.ISO8859-15.src
@@ -56,14 +56,14 @@ samedi
%y-%m-%d
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_CA.UTF-8.src b/share/timedef/fr_CA.UTF-8.src
index 1713fa7..b2a4fa0 100644
--- a/share/timedef/fr_CA.UTF-8.src
+++ b/share/timedef/fr_CA.UTF-8.src
@@ -56,14 +56,14 @@ samedi
%y-%m-%d
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_CH.ISO8859-15.src b/share/timedef/fr_CH.ISO8859-15.src
index 9af7c08..48773b7 100644
--- a/share/timedef/fr_CH.ISO8859-15.src
+++ b/share/timedef/fr_CH.ISO8859-15.src
@@ -56,14 +56,14 @@ samedi
%d.%m.%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_CH.UTF-8.src b/share/timedef/fr_CH.UTF-8.src
index de803ca..cf2fce6 100644
--- a/share/timedef/fr_CH.UTF-8.src
+++ b/share/timedef/fr_CH.UTF-8.src
@@ -56,14 +56,14 @@ samedi
%d.%m.%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_FR.ISO8859-15.src b/share/timedef/fr_FR.ISO8859-15.src
index df80d44..6fe84b6 100644
--- a/share/timedef/fr_FR.ISO8859-15.src
+++ b/share/timedef/fr_FR.ISO8859-15.src
@@ -56,14 +56,14 @@ samedi
%d/%m/%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/fr_FR.UTF-8.src b/share/timedef/fr_FR.UTF-8.src
index 15610aa..c98f4b6 100644
--- a/share/timedef/fr_FR.UTF-8.src
+++ b/share/timedef/fr_FR.UTF-8.src
@@ -56,14 +56,14 @@ samedi
%d/%m/%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
janvier
diff --git a/share/timedef/hi_IN.ISCII-DEV.src b/share/timedef/hi_IN.ISCII-DEV.src
index 766284e..6da687f 100644
--- a/share/timedef/hi_IN.ISCII-DEV.src
+++ b/share/timedef/hi_IN.ISCII-DEV.src
@@ -56,14 +56,14 @@
%e/%m/%y
#
# c_fmt
-%e %B %Y %I:%M:%S %p
+%A %e %B %Y %I:%M:%S %p
#
# AM/PM
#
# date_fmt
-%e %B %Y %I:%M:%S %p %Z
+%A %e %B %Y %I:%M:%S %p %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/hi_IN.UTF-8.src b/share/timedef/hi_IN.UTF-8.src
index 0329369..f7c17d2 100644
--- a/share/timedef/hi_IN.UTF-8.src
+++ b/share/timedef/hi_IN.UTF-8.src
@@ -56,14 +56,14 @@
%e/%m/%y
#
# c_fmt
-%e %B %Y को %I:%M:%S %p
+%A %e %B %Y को %I:%M:%S %p
#
# AM/PM
पूर्वाह्न
अपराह्न
#
# date_fmt
-%e %B %Y को %I:%M:%S %p %Z
+%A %e %B %Y को %I:%M:%S %p %Z
#
# Long month names (without case ending)
जनवरी
diff --git a/share/timedef/hy_AM.ARMSCII-8.src b/share/timedef/hy_AM.ARMSCII-8.src
index 98fa59e..4054f00 100644
--- a/share/timedef/hy_AM.ARMSCII-8.src
+++ b/share/timedef/hy_AM.ARMSCII-8.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%d %B, %Y., %H:%M:%S,
+%d %B, %Y. %H:%M:%S,
#
# AM/PM
ϻ
ϻ ѻ
#
# date_fmt
-%d %B, %Y., %H:%M:%S, %Z
+%d %B, %Y. %H:%M:%S, %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/hy_AM.UTF-8.src b/share/timedef/hy_AM.UTF-8.src
index 4dff9be..5f918bf 100644
--- a/share/timedef/hy_AM.UTF-8.src
+++ b/share/timedef/hy_AM.UTF-8.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%d %B, %Yթ., %H:%M:%S,
+%d %B, %Yթ. %H:%M:%S,
#
# AM/PM
կեսօրից առաջ
կեսօրից հետո
#
# date_fmt
-%d %B, %Yթ., %H:%M:%S, %Z
+%d %B, %Yթ. %H:%M:%S, %Z
#
# Long month names (without case ending)
հունվարի
diff --git a/share/timedef/it_CH.ISO8859-15.src b/share/timedef/it_CH.ISO8859-15.src
index 23ce1ff..c5fc2be 100644
--- a/share/timedef/it_CH.ISO8859-15.src
+++ b/share/timedef/it_CH.ISO8859-15.src
@@ -56,14 +56,14 @@ sabato
%d.%m.%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
gennaio
diff --git a/share/timedef/it_CH.UTF-8.src b/share/timedef/it_CH.UTF-8.src
index 03a25d1..305876f 100644
--- a/share/timedef/it_CH.UTF-8.src
+++ b/share/timedef/it_CH.UTF-8.src
@@ -56,14 +56,14 @@ sabato
%d.%m.%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
gennaio
diff --git a/share/timedef/it_IT.ISO8859-15.src b/share/timedef/it_IT.ISO8859-15.src
index 7554109..3d9df30 100644
--- a/share/timedef/it_IT.ISO8859-15.src
+++ b/share/timedef/it_IT.ISO8859-15.src
@@ -56,14 +56,14 @@ sabato
%d/%m/%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
gennaio
diff --git a/share/timedef/it_IT.UTF-8.src b/share/timedef/it_IT.UTF-8.src
index f166427..470fd10 100644
--- a/share/timedef/it_IT.UTF-8.src
+++ b/share/timedef/it_IT.UTF-8.src
@@ -56,14 +56,14 @@ sabato
%d/%m/%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
gennaio
diff --git a/share/timedef/kk_Cyrl_KZ.UTF-8.src b/share/timedef/kk_Cyrl_KZ.UTF-8.src
index 58cb53c..822b115 100644
--- a/share/timedef/kk_Cyrl_KZ.UTF-8.src
+++ b/share/timedef/kk_Cyrl_KZ.UTF-8.src
@@ -56,14 +56,14 @@
%d/%m/%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
таңертеңгі
түстен кейінгі
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
қантар
diff --git a/share/timedef/nl_BE.UTF-8.src b/share/timedef/nl_BE.UTF-8.src
index f437ce9..09ca522 100644
--- a/share/timedef/nl_BE.UTF-8.src
+++ b/share/timedef/nl_BE.UTF-8.src
@@ -56,14 +56,14 @@ zaterdag
%e/%m/%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
a.m.
p.m.
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
januari
diff --git a/share/timedef/nl_NL.UTF-8.src b/share/timedef/nl_NL.UTF-8.src
index 17a545b..c91f0fe 100644
--- a/share/timedef/nl_NL.UTF-8.src
+++ b/share/timedef/nl_NL.UTF-8.src
@@ -56,14 +56,14 @@ zaterdag
%d-%m-%y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
a.m.
p.m.
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
januari
diff --git a/share/timedef/pl_PL.ISO8859-2.src b/share/timedef/pl_PL.ISO8859-2.src
index 338a195..2b8f2fb 100644
--- a/share/timedef/pl_PL.ISO8859-2.src
+++ b/share/timedef/pl_PL.ISO8859-2.src
@@ -56,14 +56,14 @@ sobota
%d.%m.%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
stycze
diff --git a/share/timedef/pl_PL.UTF-8.src b/share/timedef/pl_PL.UTF-8.src
index d91c8a4..f878e7d 100644
--- a/share/timedef/pl_PL.UTF-8.src
+++ b/share/timedef/pl_PL.UTF-8.src
@@ -56,14 +56,14 @@ sobota
%d.%m.%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
AM
PM
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
styczeń
diff --git a/share/timedef/ro_RO.ISO8859-2.src b/share/timedef/ro_RO.ISO8859-2.src
index 21d730c..083b842 100644
--- a/share/timedef/ro_RO.ISO8859-2.src
+++ b/share/timedef/ro_RO.ISO8859-2.src
@@ -56,14 +56,14 @@ smbt
%d.%m.%Y
#
# c_fmt
-%e %B %Y, %H:%M:%S
+%A %e %B %Y, %H:%M:%S
#
# AM/PM
a.m.
p.m.
#
# date_fmt
-%e %B %Y, %H:%M:%S %Z
+%A %e %B %Y, %H:%M:%S %Z
#
# Long month names (without case ending)
ianuarie
diff --git a/share/timedef/ro_RO.UTF-8.src b/share/timedef/ro_RO.UTF-8.src
index 0f73f60..a9f4c34 100644
--- a/share/timedef/ro_RO.UTF-8.src
+++ b/share/timedef/ro_RO.UTF-8.src
@@ -56,14 +56,14 @@ sâmbătă
%d.%m.%Y
#
# c_fmt
-%e %B %Y, %H:%M:%S
+%A %e %B %Y, %H:%M:%S
#
# AM/PM
a.m.
p.m.
#
# date_fmt
-%e %B %Y, %H:%M:%S %Z
+%A %e %B %Y, %H:%M:%S %Z
#
# Long month names (without case ending)
ianuarie
diff --git a/share/timedef/ru_RU.CP1251.src b/share/timedef/ru_RU.CP1251.src
index b8ae9a8..b7a757a 100644
--- a/share/timedef/ru_RU.CP1251.src
+++ b/share/timedef/ru_RU.CP1251.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y ., %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
-AM
-PM
+
+
#
# date_fmt
-%e %B %Y ., %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/ru_RU.CP866.src b/share/timedef/ru_RU.CP866.src
index 639e5fe..4c59eb3 100644
--- a/share/timedef/ru_RU.CP866.src
+++ b/share/timedef/ru_RU.CP866.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y ., %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
-AM
-PM
+
+
#
# date_fmt
-%e %B %Y ., %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/ru_RU.ISO8859-5.src b/share/timedef/ru_RU.ISO8859-5.src
index f631f7e..e063042 100644
--- a/share/timedef/ru_RU.ISO8859-5.src
+++ b/share/timedef/ru_RU.ISO8859-5.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y ., %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
-AM
-PM
+
+
#
# date_fmt
-%e %B %Y ., %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/ru_RU.KOI8-R.src b/share/timedef/ru_RU.KOI8-R.src
index 7e67935..86b0086 100644
--- a/share/timedef/ru_RU.KOI8-R.src
+++ b/share/timedef/ru_RU.KOI8-R.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y ., %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
-AM
-PM
+
+
#
# date_fmt
-%e %B %Y ., %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/ru_RU.UTF-8.src b/share/timedef/ru_RU.UTF-8.src
index c9a43f5..1633d8a 100644
--- a/share/timedef/ru_RU.UTF-8.src
+++ b/share/timedef/ru_RU.UTF-8.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y г., %H:%M:%S
+%A %e %B %Y г. %H:%M:%S
#
# AM/PM
-AM
-PM
+дп
+пп
#
# date_fmt
-%e %B %Y г., %H:%M:%S %Z
+%A %e %B %Y г. %H:%M:%S %Z
#
# Long month names (without case ending)
январь
diff --git a/share/timedef/sv_FI.ISO8859-15.src b/share/timedef/sv_FI.ISO8859-15.src
index f017498..d83ffea 100644
--- a/share/timedef/sv_FI.ISO8859-15.src
+++ b/share/timedef/sv_FI.ISO8859-15.src
@@ -56,14 +56,14 @@ lrdag
%d-%m-%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
fm
em
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
januari
diff --git a/share/timedef/sv_FI.UTF-8.src b/share/timedef/sv_FI.UTF-8.src
index 68abdda..6023345 100644
--- a/share/timedef/sv_FI.UTF-8.src
+++ b/share/timedef/sv_FI.UTF-8.src
@@ -56,14 +56,14 @@ lördag
%d-%m-%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
fm
em
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
januari
diff --git a/share/timedef/sv_SE.ISO8859-15.src b/share/timedef/sv_SE.ISO8859-15.src
index 85bfded..46cca36 100644
--- a/share/timedef/sv_SE.ISO8859-15.src
+++ b/share/timedef/sv_SE.ISO8859-15.src
@@ -56,14 +56,14 @@ lrdag
%Y-%m-%d
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
fm
em
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
januari
diff --git a/share/timedef/sv_SE.UTF-8.src b/share/timedef/sv_SE.UTF-8.src
index c67ea8e..321579b 100644
--- a/share/timedef/sv_SE.UTF-8.src
+++ b/share/timedef/sv_SE.UTF-8.src
@@ -56,14 +56,14 @@ lördag
%Y-%m-%d
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
fm
em
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
januari
diff --git a/share/timedef/tr_TR.ISO8859-9.src b/share/timedef/tr_TR.ISO8859-9.src
index 13358f2..603f133 100644
--- a/share/timedef/tr_TR.ISO8859-9.src
+++ b/share/timedef/tr_TR.ISO8859-9.src
@@ -56,14 +56,14 @@ Cumartesi
%e.%m.%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
S
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
Ocak
diff --git a/share/timedef/tr_TR.UTF-8.src b/share/timedef/tr_TR.UTF-8.src
index 2162756..ce70fcf 100644
--- a/share/timedef/tr_TR.UTF-8.src
+++ b/share/timedef/tr_TR.UTF-8.src
@@ -56,14 +56,14 @@ Cumartesi
%e.%m.%Y
#
# c_fmt
-%e %B %Y %H:%M:%S
+%A %e %B %Y %H:%M:%S
#
# AM/PM
ÖÖ
ÖS
#
# date_fmt
-%e %B %Y %H:%M:%S %Z
+%A %e %B %Y %H:%M:%S %Z
#
# Long month names (without case ending)
Ocak
diff --git a/share/timedef/uk_UA.CP1251.src b/share/timedef/uk_UA.CP1251.src
index 0620499..60bc5e0 100644
--- a/share/timedef/uk_UA.CP1251.src
+++ b/share/timedef/uk_UA.CP1251.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y . %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
#
# date_fmt
-%e %B %Y . %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/uk_UA.ISO8859-5.src b/share/timedef/uk_UA.ISO8859-5.src
index 3c12346..b02c1f3 100644
--- a/share/timedef/uk_UA.ISO8859-5.src
+++ b/share/timedef/uk_UA.ISO8859-5.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y . %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
#
# date_fmt
-%e %B %Y . %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
diff --git a/share/timedef/uk_UA.KOI8-U.src b/share/timedef/uk_UA.KOI8-U.src
index b376eef..59cc654 100644
--- a/share/timedef/uk_UA.KOI8-U.src
+++ b/share/timedef/uk_UA.KOI8-U.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y . %H:%M:%S
+%A %e %B %Y . %H:%M:%S
#
# AM/PM
#
# date_fmt
-%e %B %Y . %H:%M:%S %Z
+%A %e %B %Y . %H:%M:%S %Z
#
# Long month names (without case ending)
Ӧ
diff --git a/share/timedef/uk_UA.UTF-8.src b/share/timedef/uk_UA.UTF-8.src
index fb39a6e..d5e6a94 100644
--- a/share/timedef/uk_UA.UTF-8.src
+++ b/share/timedef/uk_UA.UTF-8.src
@@ -56,14 +56,14 @@
%d.%m.%y
#
# c_fmt
-%e %B %Y р. %H:%M:%S
+%A %e %B %Y р. %H:%M:%S
#
# AM/PM
дп
пп
#
# date_fmt
-%e %B %Y р. %H:%M:%S %Z
+%A %e %B %Y р. %H:%M:%S %Z
#
# Long month names (without case ending)
січень
diff --git a/sys/arm/allwinner/aw_ccu.c b/sys/arm/allwinner/aw_ccu.c
index 0b1830b..acbd894 100644
--- a/sys/arm/allwinner/aw_ccu.c
+++ b/sys/arm/allwinner/aw_ccu.c
@@ -192,7 +192,7 @@ aw_ccu_search_compatible(void)
phandle_t root;
root = OF_finddevice("/");
- for (compat = compat_data; compat_data->ocd_str != NULL; compat++)
+ for (compat = compat_data; compat->ocd_str != NULL; compat++)
if (fdt_is_compatible(root, compat->ocd_str))
break;
diff --git a/sys/arm/arm/debug_monitor.c b/sys/arm/arm/debug_monitor.c
index ab9b46b..284d077 100644
--- a/sys/arm/arm/debug_monitor.c
+++ b/sys/arm/arm/debug_monitor.c
@@ -72,9 +72,8 @@ static boolean_t dbg_check_slot_free(enum dbg_t, u_int);
static int dbg_remove_xpoint(struct dbg_wb_conf *);
static int dbg_setup_xpoint(struct dbg_wb_conf *);
-static boolean_t dbg_capable; /* Indicates that machine is capable of using
+static int dbg_capable_var; /* Indicates that machine is capable of using
HW watchpoints/breakpoints */
-static boolean_t dbg_ready[MAXCPU]; /* Debug arch. reset performed on this CPU */
static uint32_t dbg_model; /* Debug Arch. Model */
static boolean_t dbg_ossr; /* OS Save and Restore implemented */
@@ -82,8 +81,6 @@ static boolean_t dbg_ossr; /* OS Save and Restore implemented */
static uint32_t dbg_watchpoint_num;
static uint32_t dbg_breakpoint_num;
-static int dbg_ref_count_mme; /* Times monitor mode was enabled */
-
/* ID_DFR0 - Debug Feature Register 0 */
#define ID_DFR0_CP_DEBUG_M_SHIFT 0
#define ID_DFR0_CP_DEBUG_M_MASK (0xF << ID_DFR0_CP_DEBUG_M_SHIFT)
@@ -247,9 +244,23 @@ dbg_wb_write_reg(int reg, int n, uint32_t val)
isb();
}
+static __inline boolean_t
+dbg_capable(void)
+{
+
+ return (atomic_cmpset_int(&dbg_capable_var, 0, 0) == 0);
+}
+
boolean_t
kdb_cpu_pc_is_singlestep(db_addr_t pc)
{
+ /*
+ * XXX: If the platform fails to enable its debug arch.
+ * there will be no stepping capabilities
+ * (SOFTWARE_SSTEP is not defined for __ARM_ARCH >= 6).
+ */
+ if (!dbg_capable())
+ return (FALSE);
if (dbg_find_slot(DBG_TYPE_BREAKPOINT, pc) != ~0U)
return (TRUE);
@@ -265,6 +276,9 @@ kdb_cpu_set_singlestep(void)
uint32_t wcr;
u_int i;
+ if (!dbg_capable())
+ return;
+
/*
* Disable watchpoints, e.g. stepping over watched instruction will
* trigger break exception instead of single-step exception and locks
@@ -295,6 +309,9 @@ kdb_cpu_clear_singlestep(void)
uint32_t wvr, wcr;
u_int i;
+ if (!dbg_capable())
+ return;
+
dbg_remove_breakpoint(DBG_BKPT_BT_SLOT);
dbg_remove_breakpoint(DBG_BKPT_BNT_SLOT);
@@ -412,7 +429,7 @@ dbg_show_watchpoint(void)
boolean_t is_enabled;
int i;
- if (!dbg_capable) {
+ if (!dbg_capable()) {
db_printf("Architecture does not support HW "
"breakpoints/watchpoints\n");
return;
@@ -572,34 +589,6 @@ dbg_enable_monitor(void)
}
static int
-dbg_disable_monitor(void)
-{
- uint32_t dbg_dscr;
-
- if (!dbg_monitor_is_enabled())
- return (0);
-
- dbg_dscr = cp14_dbgdscrint_get();
- switch (dbg_model) {
- case ID_DFR0_CP_DEBUG_M_V6:
- case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
- dbg_dscr &= ~DBGSCR_MDBG_EN;
- cp14_dbgdscr_v6_set(dbg_dscr);
- break;
- case ID_DFR0_CP_DEBUG_M_V7: /* fall through */
- case ID_DFR0_CP_DEBUG_M_V7_1:
- dbg_dscr &= ~DBGSCR_MDBG_EN;
- cp14_dbgdscr_v7_set(dbg_dscr);
- break;
- default:
- return (ENXIO);
- }
- isb();
-
- return (0);
-}
-
-static int
dbg_setup_xpoint(struct dbg_wb_conf *conf)
{
struct pcpu *pcpu;
@@ -608,24 +597,15 @@ dbg_setup_xpoint(struct dbg_wb_conf *conf)
uint32_t cr_size, cr_priv, cr_access;
uint32_t reg_ctrl, reg_addr, ctrl, addr;
boolean_t is_bkpt;
- u_int cpuid, cpu;
+ u_int cpu;
u_int i;
- int err;
- if (!dbg_capable)
+ if (!dbg_capable())
return (ENXIO);
is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
typestr = is_bkpt ? "breakpoint" : "watchpoint";
- cpuid = PCPU_GET(cpuid);
- if (!dbg_ready[cpuid]) {
- err = dbg_reset_state();
- if (err != 0)
- return (err);
- dbg_ready[cpuid] = TRUE;
- }
-
if (is_bkpt) {
if (dbg_breakpoint_num == 0) {
db_printf("Breakpoints not supported on this architecture\n");
@@ -702,13 +682,6 @@ dbg_setup_xpoint(struct dbg_wb_conf *conf)
dbg_wb_write_reg(reg_addr, i, addr);
dbg_wb_write_reg(reg_ctrl, i, ctrl);
- err = dbg_enable_monitor();
- if (err != 0)
- return (err);
-
- /* Increment monitor enable counter */
- dbg_ref_count_mme++;
-
/*
* Save watchpoint settings for all CPUs.
* We don't need to do the same with breakpoints since HW breakpoints
@@ -722,7 +695,7 @@ dbg_setup_xpoint(struct dbg_wb_conf *conf)
d->dbg_wvr[i] = addr;
d->dbg_wcr[i] = ctrl;
/* Skip update command for the current CPU */
- if (cpu != cpuid)
+ if (cpu != PCPU_GET(cpuid))
pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
}
}
@@ -739,23 +712,13 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf)
struct dbreg *d;
uint32_t reg_ctrl, reg_addr, addr;
boolean_t is_bkpt;
- u_int cpuid, cpu;
+ u_int cpu;
u_int i;
- int err;
- if (!dbg_capable)
+ if (!dbg_capable())
return (ENXIO);
is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
-
- cpuid = PCPU_GET(cpuid);
- if (!dbg_ready[cpuid]) {
- err = dbg_reset_state();
- if (err != 0)
- return (err);
- dbg_ready[cpuid] = TRUE;
- }
-
addr = conf->address;
if (is_bkpt) {
@@ -775,19 +738,6 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf)
dbg_wb_write_reg(reg_ctrl, i, 0);
dbg_wb_write_reg(reg_addr, i, 0);
- /* Decrement monitor enable counter */
- dbg_ref_count_mme--;
- if (dbg_ref_count_mme < 0)
- dbg_ref_count_mme = 0;
-
- atomic_thread_fence_rel();
-
- if (dbg_ref_count_mme == 0) {
- err = dbg_disable_monitor();
- if (err != 0)
- return (err);
- }
-
/*
* Save watchpoint settings for all CPUs.
* We don't need to do the same with breakpoints since HW breakpoints
@@ -801,7 +751,7 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf)
d->dbg_wvr[i] = 0;
d->dbg_wcr[i] = 0;
/* Skip update command for the current CPU */
- if (cpu != cpuid)
+ if (cpu != PCPU_GET(cpuid))
pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
}
/* Ensure all data is written before waking other CPUs */
@@ -827,7 +777,7 @@ dbg_get_ossr(void)
{
switch (dbg_model) {
- case ID_DFR0_CP_DEBUG_M_V6_1:
+ case ID_DFR0_CP_DEBUG_M_V7:
if ((cp14_dbgoslsr_get() & DBGOSLSR_OSLM0) != 0)
return (TRUE);
@@ -844,10 +794,8 @@ dbg_arch_supported(void)
{
switch (dbg_model) {
-#ifdef not_yet
case ID_DFR0_CP_DEBUG_M_V6:
case ID_DFR0_CP_DEBUG_M_V6_1:
-#endif
case ID_DFR0_CP_DEBUG_M_V7:
case ID_DFR0_CP_DEBUG_M_V7_1: /* fall through */
return (TRUE);
@@ -889,9 +837,16 @@ dbg_reset_state(void)
switch (dbg_model) {
case ID_DFR0_CP_DEBUG_M_V6:
- /* v6 Debug logic reset upon power-up */
- return (0);
- case ID_DFR0_CP_DEBUG_M_V6_1:
+ case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
+ /*
+ * Arch needs monitor mode selected and enabled
+ * to be able to access breakpoint/watchpoint registers.
+ */
+ err = dbg_enable_monitor();
+ if (err != 0)
+ return (err);
+ goto vectr_clr;
+ case ID_DFR0_CP_DEBUG_M_V7:
/* Is core power domain powered up? */
if ((cp14_dbgprsr_get() & DBGPRSR_PU) == 0)
err = ENXIO;
@@ -902,8 +857,6 @@ dbg_reset_state(void)
if (dbg_ossr)
goto vectr_clr;
break;
- case ID_DFR0_CP_DEBUG_M_V7:
- break;
case ID_DFR0_CP_DEBUG_M_V7_1:
/* Is double lock set? */
if ((cp14_dbgosdlr_get() & DBGPRSR_DLK) != 0)
@@ -998,8 +951,11 @@ dbg_monitor_init(void)
err = dbg_reset_state();
if (err == 0) {
- dbg_capable = TRUE;
- return;
+ err = dbg_enable_monitor();
+ if (err == 0) {
+ atomic_set_int(&dbg_capable_var, 1);
+ return;
+ }
}
db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n",
@@ -1009,18 +965,50 @@ dbg_monitor_init(void)
CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
void
+dbg_monitor_init_secondary(void)
+{
+ u_int cpuid;
+ int err;
+ /*
+ * This flag is set on the primary CPU
+ * and its meaning is valid for other CPUs too.
+ */
+ if (!dbg_capable())
+ return;
+
+ cpuid = PCPU_GET(cpuid);
+
+ err = dbg_reset_state();
+ if (err != 0) {
+ /*
+ * Something is very wrong.
+ * WPs/BPs will not work correctly on this CPU.
+ */
+ KASSERT(0, ("%s: Failed to reset Debug Architecture "
+ "state on CPU%d", __func__, cpuid));
+ /* Disable HW debug capabilities for all CPUs */
+ atomic_set_int(&dbg_capable_var, 0);
+ return;
+ }
+ err = dbg_enable_monitor();
+ if (err != 0) {
+ KASSERT(0, ("%s: Failed to enable Debug Monitor"
+ " on CPU%d", __func__, cpuid));
+ atomic_set_int(&dbg_capable_var, 0);
+ }
+}
+
+void
dbg_resume_dbreg(void)
{
struct dbreg *d;
- u_int cpuid;
u_int i;
- int err;
/*
* This flag is set on the primary CPU
* and its meaning is valid for other CPUs too.
*/
- if (!dbg_capable)
+ if (!dbg_capable())
return;
atomic_thread_fence_acq();
@@ -1028,21 +1016,6 @@ dbg_resume_dbreg(void)
switch (PCPU_GET(dbreg_cmd)) {
case PC_DBREG_CMD_LOAD:
d = (struct dbreg *)PCPU_PTR(dbreg);
- cpuid = PCPU_GET(cpuid);
-
- /* Reset Debug Architecture State if not done earlier */
- if (!dbg_ready[cpuid]) {
- err = dbg_reset_state();
- if (err != 0) {
- /*
- * Something is very wrong.
- * WPs/BPs will not work correctly in this CPU.
- */
- panic("%s: Failed to reset Debug Architecture "
- "state on CPU%d", __func__, cpuid);
- }
- dbg_ready[cpuid] = TRUE;
- }
/* Restore watchpoints */
for (i = 0; i < dbg_watchpoint_num; i++) {
@@ -1050,21 +1023,6 @@ dbg_resume_dbreg(void)
dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]);
}
- if ((dbg_ref_count_mme > 0) && !dbg_monitor_is_enabled()) {
- err = dbg_enable_monitor();
- if (err != 0) {
- panic("%s: Failed to enable Debug Monitor "
- "on CPU%d", __func__, cpuid);
- }
- }
- if ((dbg_ref_count_mme == 0) && dbg_monitor_is_enabled()) {
- err = dbg_disable_monitor();
- if (err != 0) {
- panic("%s: Failed to disable Debug Monitor "
- "on CPU%d", __func__, cpuid);
- }
- }
-
PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
break;
}
diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c
index cd5e6d7..6505b09 100644
--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -968,7 +968,7 @@ gic_bind(struct arm_gic_softc *sc, u_int irq, cpuset_t *cpus)
for (mask = 0, cpu = 0; cpu < end; cpu++)
if (CPU_ISSET(cpu, cpus))
- mask |= 1 << cpu;
+ mask |= arm_gic_map[cpu];
gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask);
return (0);
@@ -1128,8 +1128,11 @@ arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
if (gi->gi_irq != irq)
return (EINVAL);
- } else
- return (ENOTSUP);
+ } else {
+ irq = gi->gi_irq;
+ pol = INTR_POLARITY_CONFORM;
+ trig = INTR_TRIGGER_CONFORM;
+ }
/* Compare config if this is not first setup. */
if (isrc->isrc_handlers != 0) {
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index bb3c570..24b5679 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -23,6 +23,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+#include "opt_ddb.h"
+#include "opt_smp.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
@@ -60,8 +63,6 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#endif
-#include "opt_smp.h"
-
extern struct pcpu __pcpu[];
/* used to hold the AP's until we are ready to release them */
struct mtx ap_boot_mtx;
@@ -176,6 +177,9 @@ init_secondary(int cpu)
pcpu_init(pc, cpu, sizeof(struct pcpu));
dpcpu_init(dpcpu[cpu - 1], cpu);
+#if __ARM_ARCH >= 6 && defined(DDB)
+ dbg_monitor_init_secondary();
+#endif
/* Signal our startup to BSP */
atomic_add_rel_32(&mp_naps, 1);
diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X
index 1903e62..519127b 100644
--- a/sys/arm/conf/ARMADA38X
+++ b/sys/arm/conf/ARMADA38X
@@ -81,6 +81,11 @@ device iic
device iicbus
device twsi
+# CESA
+device cesa
+device crypto
+device cryptodev
+
#FDT
options FDT
options FDT_DTB_STATIC
diff --git a/sys/arm/include/debug_monitor.h b/sys/arm/include/debug_monitor.h
index 776d344..3656e9a 100644
--- a/sys/arm/include/debug_monitor.h
+++ b/sys/arm/include/debug_monitor.h
@@ -45,6 +45,7 @@ enum dbg_access_t {
#if __ARM_ARCH >= 6
void dbg_monitor_init(void);
+void dbg_monitor_init_secondary(void);
void dbg_show_watchpoint(void);
int dbg_setup_watchpoint(db_expr_t, db_expr_t, enum dbg_access_t);
int dbg_remove_watchpoint(db_expr_t, db_expr_t);
@@ -69,7 +70,10 @@ static __inline void
dbg_monitor_init(void)
{
}
-
+static __inline void
+dbg_monitor_init_secondary(void)
+{
+}
static __inline void
dbg_resume_dbreg(void)
{
diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c
index 55e3cd1..e24612c 100644
--- a/sys/arm/mv/mv_common.c
+++ b/sys/arm/mv/mv_common.c
@@ -2107,6 +2107,37 @@ moveon:
return (EINVAL);
cpu_win_tbl[t].target = MV_WIN_CESA_TARGET;
+#ifdef SOC_MV_ARMADA38X
+ cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR(0);
+#else
+ cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR(1);
+#endif
+ cpu_win_tbl[t].base = sram_base;
+ cpu_win_tbl[t].size = sram_size;
+ cpu_win_tbl[t].remap = ~0;
+ cpu_wins_no++;
+ debugf("sram: base = 0x%0lx size = 0x%0lx\n", sram_base, sram_size);
+
+ /* Check if there is a second CESA node */
+ while ((node = OF_peer(node)) != 0) {
+ if (fdt_is_compatible(node, "mrvl,cesa-sram")) {
+ if (fdt_regsize(node, &sram_base, &sram_size) != 0)
+ return (EINVAL);
+ break;
+ }
+ }
+
+ if (node == 0)
+ return (0);
+
+ t++;
+ if (t >= ((sizeof(cpu_win_tbl))/(sizeof(cpu_win_tbl[0])))) {
+ debugf("cannot fit CESA tuple into cpu_win_tbl\n");
+ return (ENOMEM);
+ }
+
+ /* Configure window for CESA1 */
+ cpu_win_tbl[t].target = MV_WIN_CESA_TARGET;
cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR(1);
cpu_win_tbl[t].base = sram_base;
cpu_win_tbl[t].size = sram_size;
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index 73972c3..a1d7d49 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -283,7 +283,7 @@ static struct devmap_entry fdt_devmap[FDT_DEVMAP_MAX] = {
static int
platform_sram_devmap(struct devmap_entry *map)
{
-#if !defined(SOC_MV_ARMADAXP)
+#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X)
phandle_t child, root;
u_long base, size;
/*
diff --git a/sys/arm/mv/mvwin.h b/sys/arm/mv/mvwin.h
index a9c2b8c..7e773a9 100644
--- a/sys/arm/mv/mvwin.h
+++ b/sys/arm/mv/mvwin.h
@@ -233,6 +233,19 @@
* 2: engine0
*/
#define MV_WIN_CESA_ATTR(eng_sel) (1 | ((eng_sel) << 2))
+#elif defined(SOC_MV_ARMADA38X)
+#define MV_WIN_CESA_TARGET 9
+/*
+ * Bits [1:0] = Data swapping
+ * 0x0 = Byte swap
+ * 0x1 = No swap
+ * 0x2 = Byte and word swap
+ * 0x3 = Word swap
+ * Bits [4:2] = CESA select:
+ * 0x6 = CESA0
+ * 0x5 = CESA1
+ */
+#define MV_WIN_CESA_ATTR(eng_sel) (0x11 | (1 << (3 - (eng_sel))))
#else
#define MV_WIN_CESA_TARGET 3
#define MV_WIN_CESA_ATTR(eng_sel) 0
diff --git a/sys/arm64/arm64/busdma_bounce.c b/sys/arm64/arm64/busdma_bounce.c
index 7166ebf..7039153 100644
--- a/sys/arm64/arm64/busdma_bounce.c
+++ b/sys/arm64/arm64/busdma_bounce.c
@@ -184,10 +184,8 @@ bounce_bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
newtag->map_count = 0;
newtag->segments = NULL;
-#ifdef notyet
if ((flags & BUS_DMA_COHERENT) != 0)
newtag->bounce_flags |= BF_COHERENT;
-#endif
if (parent != NULL) {
if ((newtag->common.filter != NULL ||
diff --git a/sys/arm64/arm64/gic_v3_fdt.c b/sys/arm64/arm64/gic_v3_fdt.c
index 5466900..d5106ee 100644
--- a/sys/arm64/arm64/gic_v3_fdt.c
+++ b/sys/arm64/arm64/gic_v3_fdt.c
@@ -141,11 +141,13 @@ gic_v3_fdt_attach(device_t dev)
xref = OF_xref_from_node(ofw_bus_get_node(dev));
if (intr_pic_register(dev, xref) == NULL) {
device_printf(dev, "could not register PIC\n");
+ err = ENXIO;
goto error;
}
if (intr_pic_claim_root(dev, xref, arm_gic_v3_intr, sc,
GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
+ err = ENXIO;
goto error;
}
#endif
@@ -172,7 +174,7 @@ error:
/* Failure so free resources */
gic_v3_detach(dev);
- return (ENXIO);
+ return (err);
}
/* OFW bus interface */
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index c90d59a..ee05244 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -119,6 +119,13 @@ static uint32_t cpu_reg[MAXCPU][2];
#endif
static device_t cpu_list[MAXCPU];
+/*
+ * Not all systems boot from the first CPU in the device tree. To work around
+ * this we need to find which CPU we have booted from so when we later
+ * enable the secondary CPUs we skip this one.
+ */
+static int cpu0 = -1;
+
void mpentry(unsigned long cpuid);
void init_secondary(uint64_t);
@@ -486,6 +493,7 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
uint64_t target_cpu;
struct pcpu *pcpup;
vm_paddr_t pa;
+ u_int cpuid;
int err;
/* Check we are able to start this cpu */
@@ -502,16 +510,19 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
#endif
/* We are already running on cpu 0 */
- if (id == 0)
+ if (id == cpu0)
return (1);
+ cpuid = id;
+ if (cpuid < cpu0)
+ cpuid++;
- pcpup = &__pcpu[id];
- pcpu_init(pcpup, id, sizeof(struct pcpu));
+ pcpup = &__pcpu[cpuid];
+ pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
- dpcpu[id - 1] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
+ dpcpu[cpuid - 1] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
M_WAITOK | M_ZERO);
- dpcpu_init(dpcpu[id - 1], id);
+ dpcpu_init(dpcpu[cpuid - 1], cpuid);
target_cpu = reg[0];
if (addr_size == 2) {
@@ -519,21 +530,23 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
target_cpu |= reg[1];
}
- printf("Starting CPU %u (%lx)\n", id, target_cpu);
+ printf("Starting CPU %u (%lx)\n", cpuid, target_cpu);
pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry);
- err = psci_cpu_on(target_cpu, pa, id);
+ err = psci_cpu_on(target_cpu, pa, cpuid);
if (err != PSCI_RETVAL_SUCCESS) {
/* Panic here if INVARIANTS are enabled */
- KASSERT(0, ("Failed to start CPU %u (%lx)\n", id, target_cpu));
+ KASSERT(0, ("Failed to start CPU %u (%lx)\n", id,
+ target_cpu));
pcpu_destroy(pcpup);
- kmem_free(kernel_arena, (vm_offset_t)dpcpu[id - 1], DPCPU_SIZE);
- dpcpu[id - 1] = NULL;
+ kmem_free(kernel_arena, (vm_offset_t)dpcpu[cpuid - 1],
+ DPCPU_SIZE);
+ dpcpu[cpuid - 1] = NULL;
/* Notify the user that the CPU failed to start */
printf("Failed to start CPU %u (%lx)\n", id, target_cpu);
} else
- CPU_SET(id, &all_cpus);
+ CPU_SET(cpuid, &all_cpus);
return (1);
}
@@ -551,6 +564,7 @@ cpu_mp_start(void)
switch(cpu_enum_method) {
#ifdef FDT
case CPUS_FDT:
+ KASSERT(cpu0 >= 0, ("Current CPU was not found"));
ofw_cpu_early_foreach(cpu_init_fdt, true);
break;
#endif
@@ -565,13 +579,34 @@ cpu_mp_announce(void)
{
}
+static boolean_t
+cpu_find_cpu0_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
+{
+ uint64_t mpidr_fdt, mpidr_reg;
+
+ if (cpu0 < 0) {
+ mpidr_fdt = reg[0];
+ if (addr_size == 2) {
+ mpidr_fdt <<= 32;
+ mpidr_fdt |= reg[1];
+ }
+
+ mpidr_reg = READ_SPECIALREG(mpidr_el1);
+
+ if ((mpidr_reg & 0xff00fffffful) == mpidr_fdt)
+ cpu0 = id;
+ }
+
+ return (TRUE);
+}
+
void
cpu_mp_setmaxid(void)
{
#ifdef FDT
int cores;
- cores = ofw_cpu_early_foreach(NULL, false);
+ cores = ofw_cpu_early_foreach(cpu_find_cpu0_fdt, false);
if (cores > 0) {
cores = MIN(cores, MAXCPU);
if (bootverbose)
diff --git a/sys/arm64/cavium/thunder_pcie_fdt.c b/sys/arm64/cavium/thunder_pcie_fdt.c
index e25d4a8..e55e6ed 100644
--- a/sys/arm64/cavium/thunder_pcie_fdt.c
+++ b/sys/arm64/cavium/thunder_pcie_fdt.c
@@ -119,6 +119,7 @@ thunder_pcie_fdt_attach(device_t dev)
sc = device_get_softc(dev);
thunder_pcie_identify_ecam(dev, &sc->ecam);
+ sc->coherent = 1;
return (pci_host_generic_attach(dev));
}
diff --git a/sys/arm64/cavium/thunder_pcie_pem.c b/sys/arm64/cavium/thunder_pcie_pem.c
index a8f2f43..79bb1ee 100644
--- a/sys/arm64/cavium/thunder_pcie_pem.c
+++ b/sys/arm64/cavium/thunder_pcie_pem.c
@@ -137,6 +137,7 @@ static int thunder_pem_get_id(device_t, device_t, enum pci_id_type,
static int thunder_pem_attach(device_t);
static int thunder_pem_deactivate_resource(device_t, device_t, int, int,
struct resource *);
+static bus_dma_tag_t thunder_pem_get_dma_tag(device_t, device_t);
static int thunder_pem_detach(device_t);
static uint64_t thunder_pem_config_reg_read(struct thunder_pem_softc *, int);
static int thunder_pem_link_init(struct thunder_pem_softc *);
@@ -176,6 +177,8 @@ static device_method_t thunder_pem_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_get_dma_tag, thunder_pem_get_dma_tag),
+
/* pcib interface */
DEVMETHOD(pcib_maxslots, thunder_pem_maxslots),
DEVMETHOD(pcib_read_config, thunder_pem_read_config),
@@ -331,6 +334,15 @@ thunder_pem_adjust_resource(device_t dev, device_t child, int type,
return (rman_adjust_resource(res, start, end));
}
+static bus_dma_tag_t
+thunder_pem_get_dma_tag(device_t dev, device_t child)
+{
+ struct thunder_pem_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (sc->dmat);
+}
+
static int
thunder_pem_alloc_msi(device_t pci, device_t child, int count, int maxcount,
int *irqs)
@@ -766,6 +778,21 @@ thunder_pem_attach(device_t dev)
sc->reg_bst = rman_get_bustag(sc->reg);
sc->reg_bsh = rman_get_bushandle(sc->reg);
+ /* Create the parent DMA tag to pass down the coherent flag */
+ error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
+ 1, 0, /* alignment, bounds */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE, /* maxsize */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
+ BUS_SPACE_MAXSIZE, /* maxsegsize */
+ BUS_DMA_COHERENT, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->dmat);
+ if (error != 0)
+ return (error);
+
/* Map SLI, do it only once */
if (!sli0_s2m_regx_base) {
bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC,
diff --git a/sys/arm64/cavium/thunder_pcie_pem.h b/sys/arm64/cavium/thunder_pcie_pem.h
index 755dc8d..2fc8df1 100644
--- a/sys/arm64/cavium/thunder_pcie_pem.h
+++ b/sys/arm64/cavium/thunder_pcie_pem.h
@@ -39,6 +39,7 @@ struct thunder_pem_softc {
struct resource *reg;
bus_space_tag_t reg_bst;
bus_space_handle_t reg_bsh;
+ bus_dma_tag_t dmat;
struct pcie_range ranges[MAX_RANGES_TUPLES];
struct rman mem_rman;
struct rman io_rman;
diff --git a/sys/boot/fdt/dts/arm/armada-388-gp.dts b/sys/boot/fdt/dts/arm/armada-388-gp.dts
index 8a211f6..44ff1cc 100644
--- a/sys/boot/fdt/dts/arm/armada-388-gp.dts
+++ b/sys/boot/fdt/dts/arm/armada-388-gp.dts
@@ -59,9 +59,16 @@
};
soc {
- ranges = <0 0 0xf1000000 0x100000>;
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
internal-regs {
+ crypto@90000 {
+ status = "okay";
+ };
+ crypto@92000 {
+ status = "okay";
+ };
+
spi@10600 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
diff --git a/sys/boot/fdt/dts/arm/armada-38x.dtsi b/sys/boot/fdt/dts/arm/armada-38x.dtsi
index d93dab2..736d41a 100644
--- a/sys/boot/fdt/dts/arm/armada-38x.dtsi
+++ b/sys/boot/fdt/dts/arm/armada-38x.dtsi
@@ -63,6 +63,8 @@
gpio1 = &gpio1;
serial0 = &uart0;
serial1 = &uart1;
+ sram0 = &SRAM0;
+ sram1 = &SRAM1;
};
pmu {
@@ -70,6 +72,16 @@
interrupts-extended = <&mpic 3>;
};
+ SRAM0: sram@f1100000 {
+ compatible = "mrvl,cesa-sram";
+ reg = <0xf1100000 0x0010000>;
+ };
+
+ SRAM1: sram@f1110000 {
+ compatible = "mrvl,cesa-sram";
+ reg = <0xf1110000 0x0010000>;
+ };
+
soc {
compatible = "marvell,armada380-mbus", "simple-bus";
#address-cells = <2>;
@@ -140,6 +152,25 @@
#size-cells = <1>;
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+ crypto@90000 {
+ compatible = "mrvl,cesa";
+ reg = <0x90000 0x10000>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ sram-handle = <&SRAM0>;
+ status = "disabled";
+ };
+
+ crypto@92000 {
+ compatible = "mrvl,cesa";
+ reg = <0x92000 0x1000 /* tdma base reg chan 1 */
+ 0x9F000 0x1000>; /* cesa base reg chan 1 */
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ sram-handle = <&SRAM1>;
+ status = "disabled";
+ };
+
L2: cache-controller@8000 {
compatible = "arm,pl310-cache";
reg = <0x8000 0x1000>;
diff --git a/sys/boot/fdt/dts/arm/db78100.dts b/sys/boot/fdt/dts/arm/db78100.dts
index 8a9e91c..d890db0 100644
--- a/sys/boot/fdt/dts/arm/db78100.dts
+++ b/sys/boot/fdt/dts/arm/db78100.dts
@@ -283,7 +283,8 @@
crypto@90000 {
compatible = "mrvl,cesa";
- reg = <0x90000 0x10000>;
+ reg = <0x90000 0x1000 /* tdma base reg chan 0 */
+ 0x9D000 0x1000>; /* cesa base reg chan 0 */
interrupts = <19>;
interrupt-parent = <&PIC>;
};
diff --git a/sys/boot/fdt/dts/arm/db88f6281.dts b/sys/boot/fdt/dts/arm/db88f6281.dts
index 55a27fc..f50eb65 100644
--- a/sys/boot/fdt/dts/arm/db88f6281.dts
+++ b/sys/boot/fdt/dts/arm/db88f6281.dts
@@ -221,7 +221,8 @@
crypto@30000 {
compatible = "mrvl,cesa";
- reg = <0x30000 0x10000>;
+ reg = <0x30000 0x1000 /* tdma base reg chan 0 */
+ 0x3D000 0x1000>; /* cesa base reg chan 0 */
interrupts = <22>;
interrupt-parent = <&PIC>;
diff --git a/sys/boot/fdt/dts/arm/dockstar.dts b/sys/boot/fdt/dts/arm/dockstar.dts
index 595894a..b805342 100644
--- a/sys/boot/fdt/dts/arm/dockstar.dts
+++ b/sys/boot/fdt/dts/arm/dockstar.dts
@@ -206,7 +206,8 @@
crypto@30000 {
compatible = "mrvl,cesa";
- reg = <0x30000 0x10000>;
+ reg = <0x30000 0x1000 /* tdma base reg chan 0 */
+ 0x3D000 0x1000>; /* cesa base reg chan 0 */
interrupts = <22>;
interrupt-parent = <&PIC>;
diff --git a/sys/boot/fdt/dts/arm/dreamplug-1001.dts b/sys/boot/fdt/dts/arm/dreamplug-1001.dts
index 92ca1b0..7b3998d 100644
--- a/sys/boot/fdt/dts/arm/dreamplug-1001.dts
+++ b/sys/boot/fdt/dts/arm/dreamplug-1001.dts
@@ -270,7 +270,8 @@
crypto@30000 {
compatible = "mrvl,cesa";
- reg = <0x30000 0x10000>;
+ reg = <0x30000 0x1000 /* tdma base reg chan 0 */
+ 0x3D000 0x1000>; /* cesa base reg chan 0 */
interrupts = <22>;
interrupt-parent = <&PIC>;
diff --git a/sys/boot/fdt/dts/arm/dreamplug-1001N.dts b/sys/boot/fdt/dts/arm/dreamplug-1001N.dts
index 230a65f..d233bca 100644
--- a/sys/boot/fdt/dts/arm/dreamplug-1001N.dts
+++ b/sys/boot/fdt/dts/arm/dreamplug-1001N.dts
@@ -291,7 +291,8 @@
crypto@30000 {
compatible = "mrvl,cesa";
- reg = <0x30000 0x10000>;
+ reg = <0x30000 0x1000 /* tdma base reg chan 0 */
+ 0x3D000 0x1000>; /* cesa base reg chan 0 */
interrupts = <22>;
interrupt-parent = <&PIC>;
diff --git a/sys/boot/fdt/dts/arm/sheevaplug.dts b/sys/boot/fdt/dts/arm/sheevaplug.dts
index 3d347da..fb0270a 100644
--- a/sys/boot/fdt/dts/arm/sheevaplug.dts
+++ b/sys/boot/fdt/dts/arm/sheevaplug.dts
@@ -218,7 +218,8 @@
crypto@30000 {
compatible = "mrvl,cesa";
- reg = <0x30000 0x10000>;
+ reg = <0x30000 0x1000 /* tdma base reg chan 0 */
+ 0x3D000 0x1000>; /* cesa base reg chan 0 */
interrupts = <22>;
interrupt-parent = <&PIC>;
diff --git a/sys/boot/geli/geliboot_crypto.c b/sys/boot/geli/geliboot_crypto.c
index 1596236..23d58ff 100644
--- a/sys/boot/geli/geliboot_crypto.c
+++ b/sys/boot/geli/geliboot_crypto.c
@@ -27,6 +27,10 @@
* $FreeBSD$
*/
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
#include "geliboot.h"
int
diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c b/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
index 57e5f5e..8736424 100644
--- a/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
+++ b/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
@@ -232,8 +232,6 @@ zpool_feature_init(void)
"org.open-zfs:large_blocks", "large_blocks",
"Support for blocks larger than 128KB.",
ZFEATURE_FLAG_PER_DATASET, large_blocks_deps);
-
-#ifdef illumos
zfeature_register(SPA_FEATURE_SHA512,
"org.illumos:sha512", "sha512",
"SHA-512/256 hash algorithm.",
@@ -242,6 +240,8 @@ zpool_feature_init(void)
"org.illumos:skein", "skein",
"Skein hash algorithm.",
ZFEATURE_FLAG_PER_DATASET, NULL);
+
+#ifdef illumos
zfeature_register(SPA_FEATURE_EDONR,
"org.illumos:edonr", "edonr",
"Edon-R hash algorithm.",
diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h b/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
index eea60f3..fa7e936 100644
--- a/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
+++ b/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
@@ -52,9 +52,9 @@ typedef enum spa_feature {
SPA_FEATURE_BOOKMARKS,
SPA_FEATURE_FS_SS_LIMIT,
SPA_FEATURE_LARGE_BLOCKS,
-#ifdef illumos
SPA_FEATURE_SHA512,
SPA_FEATURE_SKEIN,
+#ifdef illumos
SPA_FEATURE_EDONR,
#endif
SPA_FEATURES
diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c b/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
index c310a67b..079d860 100644
--- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
+++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
@@ -72,9 +72,9 @@ zfs_prop_init(void)
{ "fletcher4", ZIO_CHECKSUM_FLETCHER_4 },
{ "sha256", ZIO_CHECKSUM_SHA256 },
{ "noparity", ZIO_CHECKSUM_NOPARITY },
-#ifdef illumos
{ "sha512", ZIO_CHECKSUM_SHA512 },
{ "skein", ZIO_CHECKSUM_SKEIN },
+#ifdef illumos
{ "edonr", ZIO_CHECKSUM_EDONR },
#endif
{ NULL }
@@ -87,13 +87,13 @@ zfs_prop_init(void)
{ "sha256", ZIO_CHECKSUM_SHA256 },
{ "sha256,verify",
ZIO_CHECKSUM_SHA256 | ZIO_CHECKSUM_VERIFY },
-#ifdef illumos
{ "sha512", ZIO_CHECKSUM_SHA512 },
{ "sha512,verify",
ZIO_CHECKSUM_SHA512 | ZIO_CHECKSUM_VERIFY },
{ "skein", ZIO_CHECKSUM_SKEIN },
{ "skein,verify",
ZIO_CHECKSUM_SKEIN | ZIO_CHECKSUM_VERIFY },
+#ifdef illumos
{ "edonr,verify",
ZIO_CHECKSUM_EDONR | ZIO_CHECKSUM_VERIFY },
#endif
diff --git a/sys/cddl/contrib/opensolaris/uts/common/Makefile.files b/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
index 77c7b1d..086dd05 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
+++ b/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
@@ -74,6 +74,7 @@ ZFS_COMMON_OBJS += \
rrwlock.o \
sa.o \
sha256.o \
+ skein_zfs.o \
spa.o \
spa_config.o \
spa_errlog.o \
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
index e684b21..f3630a3 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
@@ -29,8 +29,10 @@
#include <sys/zio.h>
#ifdef _KERNEL
#include <crypto/sha2/sha256.h>
+#include <crypto/sha2/sha512t.h>
#else
#include <sha256.h>
+#include <sha512t.h>
#endif
/*ARGSUSED*/
@@ -58,17 +60,16 @@ zio_checksum_SHA256(const void *buf, uint64_t size,
zcp->zc_word[3] = BE_64(tmp.zc_word[3]);
}
-#ifdef illumos
/*ARGSUSED*/
void
zio_checksum_SHA512_native(const void *buf, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
- SHA2_CTX ctx;
+ SHA512_CTX ctx;
- SHA2Init(SHA512_256, &ctx);
- SHA2Update(&ctx, buf, size);
- SHA2Final(zcp, &ctx);
+ SHA512_256_Init(&ctx);
+ SHA512_256_Update(&ctx, buf, size);
+ SHA512_256_Final((unsigned char *)zcp, &ctx);
}
/*ARGSUSED*/
@@ -84,4 +85,3 @@ zio_checksum_SHA512_byteswap(const void *buf, uint64_t size,
zcp->zc_word[2] = BSWAP_64(tmp.zc_word[2]);
zcp->zc_word[3] = BSWAP_64(tmp.zc_word[3]);
}
-#endif
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c
index 6592340..f8d1cf9 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c
@@ -23,7 +23,11 @@
*/
#include <sys/zfs_context.h>
#include <sys/zio.h>
-#include <sys/skein.h>
+#ifdef _KERNEL
+#include <crypto/skein/skein.h>
+#else
+#include <skein.h>
+#endif
/*
* Computes a native 256-bit skein MAC checksum. Please note that this
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
index 56c821a..bda9afa 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
@@ -82,9 +82,9 @@ enum zio_checksum {
ZIO_CHECKSUM_SHA256,
ZIO_CHECKSUM_ZILOG2,
ZIO_CHECKSUM_NOPARITY,
-#ifdef illumos
ZIO_CHECKSUM_SHA512,
ZIO_CHECKSUM_SKEIN,
+#ifdef illumos
ZIO_CHECKSUM_EDONR,
#endif
ZIO_CHECKSUM_FUNCTIONS
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h
index 0a9d772..6cba764 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_checksum.h
@@ -82,7 +82,6 @@ extern zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS];
* Checksum routines.
*/
extern zio_checksum_t zio_checksum_SHA256;
-#ifdef illumos
extern zio_checksum_t zio_checksum_SHA512_native;
extern zio_checksum_t zio_checksum_SHA512_byteswap;
@@ -92,6 +91,7 @@ extern zio_checksum_t zio_checksum_skein_byteswap;
extern zio_checksum_tmpl_init_t zio_checksum_skein_tmpl_init;
extern zio_checksum_tmpl_free_t zio_checksum_skein_tmpl_free;
+#ifdef illumos
/* Edon-R */
extern zio_checksum_t zio_checksum_edonr_native;
extern zio_checksum_t zio_checksum_edonr_byteswap;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
index 9b08e35..17e2f02 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
@@ -3366,19 +3366,6 @@ vdev_set_state(vdev_t *vd, boolean_t isopen, vdev_state_t state, vdev_aux_t aux)
vd->vdev_ops->vdev_op_leaf)
vd->vdev_ops->vdev_op_close(vd);
- /*
- * If we have brought this vdev back into service, we need
- * to notify fmd so that it can gracefully repair any outstanding
- * cases due to a missing device. We do this in all cases, even those
- * that probably don't correlate to a repaired fault. This is sure to
- * catch all cases, and we let the zfs-retire agent sort it out. If
- * this is a transient state it's OK, as the retire agent will
- * double-check the state of the vdev before repairing it.
- */
- if (state == VDEV_STATE_HEALTHY && vd->vdev_ops->vdev_op_leaf &&
- vd->vdev_prevstate != state)
- zfs_post_state_change(spa, vd);
-
if (vd->vdev_removed &&
state == VDEV_STATE_CANT_OPEN &&
(aux == VDEV_AUX_OPEN_FAILED || vd->vdev_checkremove)) {
@@ -3459,6 +3446,16 @@ vdev_set_state(vdev_t *vd, boolean_t isopen, vdev_state_t state, vdev_aux_t aux)
vd->vdev_removed = B_FALSE;
}
+ /*
+ * Notify the fmd of the state change. Be verbose and post
+ * notifications even for stuff that's not important; the fmd agent can
+ * sort it out. Don't emit state change events for non-leaf vdevs since
+ * they can't change state on their own. The FMD can check their state
+ * if it wants to when it sees that a leaf vdev had a state change.
+ */
+ if (vd->vdev_ops->vdev_op_leaf)
+ zfs_post_state_change(spa, vd);
+
if (!isopen && vd->vdev_parent)
vdev_propagate_state(vd->vdev_parent);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c
index dac118a..997e313 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c
@@ -123,7 +123,6 @@ zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
NULL, NULL, ZCHECKSUM_FLAG_EMBEDDED, "zilog2"},
{{zio_checksum_off, zio_checksum_off},
NULL, NULL, 0, "noparity"},
-#ifdef illumos
{{zio_checksum_SHA512_native, zio_checksum_SHA512_byteswap},
NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP |
ZCHECKSUM_FLAG_NOPWRITE, "sha512"},
@@ -131,6 +130,7 @@ zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
zio_checksum_skein_tmpl_init, zio_checksum_skein_tmpl_free,
ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP |
ZCHECKSUM_FLAG_SALTED | ZCHECKSUM_FLAG_NOPWRITE, "skein"},
+#ifdef illumos
{{zio_checksum_edonr_native, zio_checksum_edonr_byteswap},
zio_checksum_edonr_tmpl_init, zio_checksum_edonr_tmpl_free,
ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_SALTED |
@@ -145,7 +145,6 @@ zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
spa_feature_t
zio_checksum_to_feature(enum zio_checksum cksum)
{
-#ifdef illumos
VERIFY((cksum & ~ZIO_CHECKSUM_MASK) == 0);
switch (cksum) {
@@ -153,10 +152,11 @@ zio_checksum_to_feature(enum zio_checksum cksum)
return (SPA_FEATURE_SHA512);
case ZIO_CHECKSUM_SKEIN:
return (SPA_FEATURE_SKEIN);
+#ifdef illumos
case ZIO_CHECKSUM_EDONR:
return (SPA_FEATURE_EDONR);
- }
#endif
+ }
return (SPA_FEATURE_NONE);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/acl.h b/sys/cddl/contrib/opensolaris/uts/common/sys/acl.h
index dbf128d..83c85ba 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/acl.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/acl.h
@@ -35,8 +35,8 @@
#if defined(_KERNEL)
/*
- * When compiling OpenSolaris kernel code, this file is getting
- * included instead of FreeBSD one. Pull the original sys/acl.h as well.
+ * When compiling OpenSolaris kernel code, this file is included instead of the
+ * FreeBSD one. Include the original sys/acl.h as well.
*/
#undef _SYS_ACL_H
#include_next <sys/acl.h>
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent.h b/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent.h
index 777d748..9a25982 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/sysevent.h
@@ -76,8 +76,8 @@ extern "C" {
#define SUNW_VENDOR "SUNW"
#define SE_USR_PUB "usr:"
#define SE_KERN_PUB "kern:"
-#define SUNW_KERN_PUB SUNW_VENDOR":"SE_KERN_PUB
-#define SUNW_USR_PUB SUNW_VENDOR":"SE_USR_PUB
+#define SUNW_KERN_PUB SUNW_VENDOR ":" SE_KERN_PUB
+#define SUNW_USR_PUB SUNW_VENDOR ":" SE_USR_PUB
/*
* Event header and attribute value limits
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c b/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c
index 442367f..80f9b1e 100644
--- a/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c
@@ -119,7 +119,7 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
volatile uint16_t *flags =
(volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
int ret = 0;
- uintptr_t oldfp;
+ uintptr_t oldfp = fp;
ASSERT(pcstack == NULL || pcstack_limit > 0);
@@ -168,6 +168,8 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
*flags &= ~CPU_DTRACE_FAULT;
break;
}
+
+ oldfp = fp;
}
return (ret);
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 09c0720..824bcf0 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -916,6 +916,8 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
case LINUX_TIOCGSERIAL: {
struct linux_serial_struct lss;
+
+ bzero(&lss, sizeof(lss));
lss.type = LINUX_PORT_16550A;
lss.flags = 0;
lss.close_delay = 0;
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index bd3d6aa..01fd25a 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -149,6 +149,7 @@ linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
int i, j;
struct timespec ts;
+ bzero(&sysinfo, sizeof(sysinfo));
getnanouptime(&ts);
if (ts.tv_nsec != 0)
ts.tv_sec++;
diff --git a/sys/conf/dtb.mk b/sys/conf/dtb.mk
index df6af54..f32b020 100644
--- a/sys/conf/dtb.mk
+++ b/sys/conf/dtb.mk
@@ -34,7 +34,7 @@
# Search for kernel source tree in standard places.
.for _dir in ${.CURDIR}/../.. ${.CURDIR}/../../.. /sys /usr/src/sys
.if !defined(SYSDIR) && exists(${_dir}/kern/)
-SYSDIR= ${_dir}
+SYSDIR= ${_dir:tA}
.endif
.endfor
.if !defined(SYSDIR) || !exists(${SYSDIR}/kern/)
@@ -51,7 +51,7 @@ all: ${DTB}
.if defined(DTS)
.for _dts in ${DTS}
-${_dts:R:S/$/.dtb/}: ${_dts}
+${_dts:R:S/$/.dtb/}: ${_dts} ${OP_META}
@echo Generating ${.TARGET} from ${_dts}
@${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${_dts} ${.OBJDIR}
CLEANFILES+=${_dts:R:S/$/.dtb/}
diff --git a/sys/conf/files b/sys/conf/files
index d274faa..4bfdffe 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -197,6 +197,7 @@ cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c optional zfs compile-wit
cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c optional zfs compile-with "${ZFS_C}"
cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c optional zfs compile-with "${ZFS_C}"
cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c optional zfs compile-with "${ZFS_C}"
+cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c optional zfs compile-with "${ZFS_C}"
cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c optional zfs compile-with "${ZFS_C}"
cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c optional zfs compile-with "${ZFS_C}"
cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c optional zfs compile-with "${ZFS_C}"
@@ -577,6 +578,8 @@ crypto/sha1.c optional carp | crypto | ipsec | \
crypto/sha2/sha256c.c optional crypto | geom_bde | ipsec | random !random_loadable | \
sctp | zfs
crypto/sha2/sha512c.c optional crypto | geom_bde | ipsec | zfs
+crypto/skein/skein.c optional crypto | zfs
+crypto/skein/skein_block.c optional crypto | zfs
crypto/siphash/siphash.c optional inet | inet6
crypto/siphash/siphash_test.c optional inet | inet6
ddb/db_access.c optional ddb
@@ -762,6 +765,8 @@ dev/ath/if_ath_beacon.c optional ath \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/if_ath_btcoex.c optional ath \
compile-with "${NORMAL_C} -I$S/dev/ath"
+dev/ath/if_ath_btcoex_mci.c optional ath \
+ compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/if_ath_debug.c optional ath \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/if_ath_descdma.c optional ath \
@@ -1699,6 +1704,7 @@ iwi_monitor.fw optional iwimonitorfw | iwifw \
clean "iwi_monitor.fw"
dev/iwm/if_iwm.c optional iwm
dev/iwm/if_iwm_binding.c optional iwm
+dev/iwm/if_iwm_led.c optional iwm
dev/iwm/if_iwm_mac_ctxt.c optional iwm
dev/iwm/if_iwm_pcie_trans.c optional iwm
dev/iwm/if_iwm_phy_ctxt.c optional iwm
@@ -3824,9 +3830,11 @@ netnatm/natm.c optional natm
netnatm/natm_pcb.c optional natm
netnatm/natm_proto.c optional natm
netpfil/ipfw/dn_aqm_codel.c optional inet dummynet
+netpfil/ipfw/dn_aqm_pie.c optional inet dummynet
netpfil/ipfw/dn_heap.c optional inet dummynet
netpfil/ipfw/dn_sched_fifo.c optional inet dummynet
netpfil/ipfw/dn_sched_fq_codel.c optional inet dummynet
+netpfil/ipfw/dn_sched_fq_pie.c optional inet dummynet
netpfil/ipfw/dn_sched_prio.c optional inet dummynet
netpfil/ipfw/dn_sched_qfq.c optional inet dummynet
netpfil/ipfw/dn_sched_rr.c optional inet dummynet
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index ef356ea..8f0670b 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -273,12 +273,12 @@ dev/hyperv/utilities/hv_util.c optional hyperv
dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
-dev/hyperv/vmbus/hv_hv.c optional hyperv
-dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
-dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
+dev/hyperv/vmbus/hyperv.c optional hyperv
dev/hyperv/vmbus/hyperv_busdma.c optional hyperv
-dev/hyperv/vmbus/amd64/hv_vector.S optional hyperv
+dev/hyperv/vmbus/vmbus.c optional hyperv
+dev/hyperv/vmbus/vmbus_et.c optional hyperv
+dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv
dev/nfe/if_nfe.c optional nfe pci
dev/ntb/if_ntb/if_ntb.c optional if_ntb
dev/ntb/ntb_hw/ntb_hw.c optional if_ntb | ntb_hw
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index d0cf1ed..ea33934 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -74,6 +74,8 @@ dev/psci/psci_arm64.S optional psci
dev/uart/uart_cpu_fdt.c optional uart fdt
dev/uart/uart_dev_pl011.c optional uart pl011
dev/usb/controller/dwc_otg_hisi.c optional dwcotg soc_hisi_hi6220
+dev/usb/controller/generic_ohci.c optional ohci fdt
+dev/usb/controller/generic_usb_if.m optional ohci fdt
dev/vnic/mrml_bridge.c optional vnic fdt
dev/vnic/nic_main.c optional vnic pci
dev/vnic/nicvf_main.c optional vnic pci pci_iov
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index a64a916..ed89ef3 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -248,12 +248,12 @@ dev/hyperv/utilities/hv_util.c optional hyperv
dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
-dev/hyperv/vmbus/hv_hv.c optional hyperv
-dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
-dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
+dev/hyperv/vmbus/hyperv.c optional hyperv
dev/hyperv/vmbus/hyperv_busdma.c optional hyperv
-dev/hyperv/vmbus/i386/hv_vector.S optional hyperv
+dev/hyperv/vmbus/vmbus.c optional hyperv
+dev/hyperv/vmbus/vmbus_et.c optional hyperv
+dev/hyperv/vmbus/i386/vmbus_vector.S optional hyperv
dev/ichwd/ichwd.c optional ichwd
dev/if_ndis/if_ndis.c optional ndis
dev/if_ndis/if_ndis_pccard.c optional ndis pccard
diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk
index ace1346..fef3959 100644
--- a/sys/conf/kern.post.mk
+++ b/sys/conf/kern.post.mk
@@ -12,7 +12,7 @@
.if defined(DESTDIR)
MKMODULESENV+= DESTDIR="${DESTDIR}"
.endif
-SYSDIR?= ${S:C;^[^/];${.CURDIR}/&;}
+SYSDIR?= ${S:C;^[^/];${.CURDIR}/&;:tA}
MKMODULESENV+= KERNBUILDDIR="${.CURDIR}" SYSDIR="${SYSDIR}"
.if defined(CONF_CFLAGS)
@@ -108,10 +108,10 @@ modules-all modules-depend: modules-obj
FULLKERNEL= ${KERNEL_KO}
.else
FULLKERNEL= ${KERNEL_KO}.full
-${KERNEL_KO}: ${FULLKERNEL} ${KERNEL_KO}.debug
+${KERNEL_KO}: ${FULLKERNEL} ${KERNEL_KO}.debug ${OP_META}
${OBJCOPY} --strip-debug --add-gnu-debuglink=${KERNEL_KO}.debug \
${FULLKERNEL} ${.TARGET}
-${KERNEL_KO}.debug: ${FULLKERNEL}
+${KERNEL_KO}.debug: ${FULLKERNEL} ${OP_META}
${OBJCOPY} --only-keep-debug ${FULLKERNEL} ${.TARGET}
install.debug reinstall.debug: gdbinit
cd ${.CURDIR}; ${MAKE} ${.TARGET:R}
@@ -127,7 +127,7 @@ gdbinit:
.endif
.endif
-${FULLKERNEL}: ${SYSTEM_DEP} vers.o
+${FULLKERNEL}: ${SYSTEM_DEP} vers.o ${OP_META}
@rm -f ${.TARGET}
@echo linking ${.TARGET}
${SYSTEM_LD}
@@ -150,9 +150,9 @@ LNFILES= ${CFILES:T:S/.c$/.ln/}
.for mfile in ${MFILES}
# XXX the low quality .m.o rules gnerated by config are normally used
# instead of the .m.c rules here.
-${mfile:T:S/.m$/.c/}: ${mfile}
+${mfile:T:S/.m$/.c/}: ${mfile} ${OP_META}
${AWK} -f $S/tools/makeobjops.awk ${mfile} -c
-${mfile:T:S/.m$/.h/}: ${mfile}
+${mfile:T:S/.m$/.h/}: ${mfile} ${OP_META}
${AWK} -f $S/tools/makeobjops.awk ${mfile} -h
.endfor
@@ -172,18 +172,18 @@ lint: ${LNFILES}
# dynamic references. We could probably do a '-Bforcedynamic' mode like
# in the a.out ld. For now, this works.
HACK_EXTRA_FLAGS?= -shared
-hack.So: Makefile
+hack.So: Makefile ${OP_META}
:> hack.c
${CC} ${HACK_EXTRA_FLAGS} -nostdlib hack.c -o hack.So
rm -f hack.c
-assym.s: $S/kern/genassym.sh genassym.o
+assym.s: $S/kern/genassym.sh genassym.o ${OP_META}
NM='${NM}' NMFLAGS='${NMFLAGS}' sh $S/kern/genassym.sh genassym.o > ${.TARGET}
-genassym.o: $S/$M/$M/genassym.c
+genassym.o: $S/$M/$M/genassym.c ${OP_META}
${CC} -c ${CFLAGS:N-fno-common} $S/$M/$M/genassym.c
-${SYSTEM_OBJS} genassym.o vers.o: opt_global.h
+${SYSTEM_OBJS} genassym.o vers.o: opt_global.h ${OP_META}
# Skip reading .depend when not needed to speed up tree-walks
# and simple lookups.
@@ -260,7 +260,7 @@ ${__obj}: ${OBJS_DEPEND_GUESS.${__obj}:N*.h}
.NOPATH: .depend ${DEPENDFILES_OBJS}
-.depend: .PRECIOUS ${SRCS}
+.depend: .PRECIOUS ${SRCS} ${OP_META}
_ILINKS= machine
.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64"
@@ -285,7 +285,7 @@ ${_ILINKS}:
path=${S}/${.TARGET}/include ;; \
esac ; \
${ECHO} ${.TARGET} "->" $$path ; \
- ln -s $$path ${.TARGET}
+ ln -fhs $$path ${.TARGET}
# .depend needs include links so we remove them only together.
kernel-cleandepend: .PHONY
@@ -339,26 +339,26 @@ kernel-reinstall:
${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO}.debug ${DESTDIR}${KERN_DEBUGDIR}${KODIR}/
.endif
-config.o env.o hints.o vers.o vnode_if.o:
+config.o env.o hints.o vers.o vnode_if.o: ${OP_META}
${NORMAL_C}
${NORMAL_CTFCONVERT}
-config.ln env.ln hints.ln vers.ln vnode_if.ln:
+config.ln env.ln hints.ln vers.ln vnode_if.ln: ${OP_META}
${NORMAL_LINT}
-vers.c: $S/conf/newvers.sh $S/sys/param.h ${SYSTEM_DEP}
+vers.c: $S/conf/newvers.sh $S/sys/param.h ${SYSTEM_DEP} ${OP_META}
MAKE=${MAKE} sh $S/conf/newvers.sh ${KERN_IDENT}
-vnode_if.c: $S/tools/vnode_if.awk $S/kern/vnode_if.src
+vnode_if.c: $S/tools/vnode_if.awk $S/kern/vnode_if.src ${OP_META}
${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -c
vnode_if.h vnode_if_newproto.h vnode_if_typedef.h: $S/tools/vnode_if.awk \
- $S/kern/vnode_if.src
-vnode_if.h: vnode_if_newproto.h vnode_if_typedef.h
+ $S/kern/vnode_if.src ${OP_META}
+vnode_if.h: vnode_if_newproto.h vnode_if_typedef.h ${OP_META}
${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -h
-vnode_if_newproto.h:
+vnode_if_newproto.h: ${OP_META}
${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -p
-vnode_if_typedef.h:
+vnode_if_typedef.h: ${OP_META}
${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -q
.if ${MFS_IMAGE:Uno} != "no"
@@ -367,7 +367,7 @@ vnode_if_typedef.h:
# via linking. Make sure the contents are in the mfs section and rename the
# start/end/size variables to __start_mfs, __stop_mfs, and mfs_size,
# respectively.
-embedfs_${MFS_IMAGE:T:R}.o: ${MFS_IMAGE}
+embedfs_${MFS_IMAGE:T:R}.o: ${MFS_IMAGE} ${OP_META}
${OBJCOPY} --input-target binary \
--output-target ${EMBEDFS_FORMAT.${MACHINE_ARCH}} \
--binary-architecture ${EMBEDFS_ARCH.${MACHINE_ARCH}} \
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index d5781db..e5cb093 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -22,6 +22,7 @@ _srcconf_included_:
# The kernel build always occurs in the object directory which is .CURDIR.
.if ${.MAKE.MODE:Unormal:Mmeta}
.MAKE.MODE+= curdirOk=yes
+OP_META= .META
.endif
# Can be overridden by makeoptions or /etc/make.conf
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index 817ecec..25de248 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -76,6 +76,16 @@ OBJCOPY?= objcopy
.include <bsd.compiler.mk>
.include "config.mk"
+# Search for kernel source tree in standard places.
+.for _dir in ${.CURDIR}/../.. ${.CURDIR}/../../.. /sys /usr/src/sys
+.if !defined(SYSDIR) && exists(${_dir}/kern/)
+SYSDIR= ${_dir:tA}
+.endif
+.endfor
+.if !defined(SYSDIR) || !exists(${SYSDIR}/kern/)
+.error "can't find kernel source tree"
+.endif
+
.SUFFIXES: .out .o .c .cc .cxx .C .y .l .s .S .m
# amd64 and mips use direct linking for kmod, all others use shared binaries
@@ -120,7 +130,7 @@ CFLAGS+= ${DEBUG_FLAGS}
CFLAGS+= -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
.endif
-.if ${MACHINE_CPUARCH} == "aarch64"
+.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv"
CFLAGS+= -fPIC
.endif
@@ -149,7 +159,7 @@ CTFFLAGS+= -g
.endif
.if defined(FIRMWS)
-${KMOD:S/$/.c/}: ${SYSDIR}/tools/fw_stub.awk
+${KMOD:S/$/.c/}: ${SYSDIR}/tools/fw_stub.awk ${OP_META}
${AWK} -f ${SYSDIR}/tools/fw_stub.awk ${FIRMWS} -m${KMOD} -c${KMOD:S/$/.c/g} \
${FIRMWARE_LICENSE:C/.+/-l/}${FIRMWARE_LICENSE}
@@ -157,7 +167,7 @@ SRCS+= ${KMOD:S/$/.c/}
CLEANFILES+= ${KMOD:S/$/.c/}
.for _firmw in ${FIRMWS}
-${_firmw:C/\:.*$/.fwo/:T}: ${_firmw:C/\:.*$//}
+${_firmw:C/\:.*$/.fwo/:T}: ${_firmw:C/\:.*$//} ${OP_META}
@${ECHO} ${_firmw:C/\:.*$//} ${.ALLSRC:M*${_firmw:C/\:.*$//}}
@if [ -e ${_firmw:C/\:.*$//} ]; then \
${LD} -b binary --no-warn-mismatch ${_LDFLAGS} \
@@ -188,15 +198,15 @@ PROG= ${KMOD}.ko
FULLPROG= ${PROG}
.else
FULLPROG= ${PROG}.full
-${PROG}: ${FULLPROG} ${PROG}.debug
+${PROG}: ${FULLPROG} ${PROG}.debug ${OP_META}
${OBJCOPY} --strip-debug --add-gnu-debuglink=${PROG}.debug \
${FULLPROG} ${.TARGET}
-${PROG}.debug: ${FULLPROG}
+${PROG}.debug: ${FULLPROG} ${OP_META}
${OBJCOPY} --only-keep-debug ${FULLPROG} ${.TARGET}
.endif
.if ${__KLD_SHARED} == yes
-${FULLPROG}: ${KMOD}.kld
+${FULLPROG}: ${KMOD}.kld ${OP_META}
.if ${MACHINE_CPUARCH} != "aarch64"
${LD} -Bshareable ${_LDFLAGS} -o ${.TARGET} ${KMOD}.kld
.else
@@ -219,9 +229,9 @@ CLEANFILES+= export_syms
.endif
.if ${__KLD_SHARED} == yes
-${KMOD}.kld: ${OBJS}
+${KMOD}.kld: ${OBJS} ${OP_META}
.else
-${FULLPROG}: ${OBJS}
+${FULLPROG}: ${OBJS} ${OP_META}
.endif
${LD} ${_LDFLAGS} -r -d -o ${.TARGET} ${OBJS}
.if ${MK_CTF} != "no"
@@ -266,16 +276,6 @@ ${OBJS}: ${_link}
.endif
.endfor
-# Search for kernel source tree in standard places.
-.for _dir in ${.CURDIR}/../.. ${.CURDIR}/../../.. /sys /usr/src/sys
-.if !defined(SYSDIR) && exists(${_dir}/kern/)
-SYSDIR= ${_dir}
-.endif
-.endfor
-.if !defined(SYSDIR) || !exists(${SYSDIR}/kern/)
-.error "can't find kernel source tree"
-.endif
-
.NOPATH: ${_ILINKS}
${_ILINKS}:
@@ -287,7 +287,7 @@ ${_ILINKS}:
esac ; \
path=`(cd $$path && /bin/pwd)` ; \
${ECHO} ${.TARGET:T} "->" $$path ; \
- ln -sf $$path ${.TARGET:T}
+ ln -fhs $$path ${.TARGET:T}
CLEANFILES+= ${PROG} ${KMOD}.kld ${OBJS}
@@ -397,16 +397,16 @@ _MATCHES=${_MFILES:${_MATCH}}
CLEANFILES+= ${_i}
.endif
.endfor # _i
-.m.c: ${SYSDIR}/tools/makeobjops.awk
+.m.c: ${SYSDIR}/tools/makeobjops.awk ${OP_META}
${AWK} -f ${SYSDIR}/tools/makeobjops.awk ${.IMPSRC} -c
-.m.h: ${SYSDIR}/tools/makeobjops.awk
+.m.h: ${SYSDIR}/tools/makeobjops.awk ${OP_META}
${AWK} -f ${SYSDIR}/tools/makeobjops.awk ${.IMPSRC} -h
.for _i in mii pccard
.if !empty(SRCS:M${_i}devs.h)
CLEANFILES+= ${_i}devs.h
-${_i}devs.h: ${SYSDIR}/tools/${_i}devs2h.awk ${SYSDIR}/dev/${_i}/${_i}devs
+${_i}devs.h: ${SYSDIR}/tools/${_i}devs2h.awk ${SYSDIR}/dev/${_i}/${_i}devs ${OP_META}
${AWK} -f ${SYSDIR}/tools/${_i}devs2h.awk ${SYSDIR}/dev/${_i}/${_i}devs
.endif
.endfor # _i
@@ -415,8 +415,9 @@ ${_i}devs.h: ${SYSDIR}/tools/${_i}devs2h.awk ${SYSDIR}/dev/${_i}/${_i}devs
CLEANFILES+= bhnd_nvram_map.h
bhnd_nvram_map.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \
${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
- ${SYSDIR}/dev/bhnd/nvram/nvram_map
-bhnd_nvram_map.h:
+ ${SYSDIR}/dev/bhnd/nvram/nvram_map \
+ ${OP_META}
+bhnd_nvram_map.h: ${OP_META}
sh ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
${SYSDIR}/dev/bhnd/nvram/nvram_map -h
.endif
@@ -425,27 +426,28 @@ bhnd_nvram_map.h:
CLEANFILES+= bhnd_nvram_map_data.h
bhnd_nvram_map_data.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \
${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
- ${SYSDIR}/dev/bhnd/nvram/nvram_map
-bhnd_nvram_map_data.h:
+ ${SYSDIR}/dev/bhnd/nvram/nvram_map \
+ ${OP_META}
+bhnd_nvram_map_data.h: ${OP_META}
sh ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
${SYSDIR}/dev/bhnd/nvram/nvram_map -d
.endif
.if !empty(SRCS:Musbdevs.h)
CLEANFILES+= usbdevs.h
-usbdevs.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs
+usbdevs.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs ${OP_META}
${AWK} -f ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs -h
.endif
.if !empty(SRCS:Musbdevs_data.h)
CLEANFILES+= usbdevs_data.h
-usbdevs_data.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs
+usbdevs_data.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs ${OP_META}
${AWK} -f ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs -d
.endif
.if !empty(SRCS:Macpi_quirks.h)
CLEANFILES+= acpi_quirks.h
-acpi_quirks.h: ${SYSDIR}/tools/acpi_quirks2h.awk ${SYSDIR}/dev/acpica/acpi_quirks
+acpi_quirks.h: ${SYSDIR}/tools/acpi_quirks2h.awk ${SYSDIR}/dev/acpica/acpi_quirks ${OP_META}
${AWK} -f ${SYSDIR}/tools/acpi_quirks2h.awk ${SYSDIR}/dev/acpica/acpi_quirks
.endif
@@ -455,10 +457,10 @@ assym.s: genassym.o
.if defined(KERNBUILDDIR)
genassym.o: opt_global.h
.endif
-assym.s: ${SYSDIR}/kern/genassym.sh
+assym.s: ${SYSDIR}/kern/genassym.sh ${OP_META}
sh ${SYSDIR}/kern/genassym.sh genassym.o > ${.TARGET}
genassym.o: ${SYSDIR}/${MACHINE}/${MACHINE}/genassym.c
-genassym.o: ${SRCS:Mopt_*.h}
+genassym.o: ${SRCS:Mopt_*.h} ${OP_META}
${CC} -c ${CFLAGS:N-fno-common} \
${SYSDIR}/${MACHINE}/${MACHINE}/genassym.c
.endif
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
index f7f3ed7..96b5fd8 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
@@ -723,10 +723,10 @@ ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st,
#if ATH_SUPPORT_MCI
if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
-#if 0
- ah->ah_bt_coex_set_weights = ar9300_mci_bt_coex_set_weights;
- ah->ah_bt_coex_disable = ar9300_mci_bt_coex_disable;
- ah->ah_bt_coex_enable = ar9300_mci_bt_coex_enable;
+#if 1
+ ah->ah_btCoexSetWeights = ar9300_mci_bt_coex_set_weights;
+ ah->ah_btCoexDisable = ar9300_mci_bt_coex_disable;
+ ah->ah_btCoexEnable = ar9300_mci_bt_coex_enable;
#endif
ahp->ah_mci_ready = AH_FALSE;
ahp->ah_mci_bt_state = MCI_BT_SLEEP;
@@ -3033,7 +3033,7 @@ ar9300_fill_capability_info(struct ath_hal *ah)
/* XXX is this a flag, or a chainmask number? */
p_cap->halApmEnable = !! ar9300_eeprom_get(ahp, EEP_CHAIN_MASK_REDUCE);
#if ATH_ANT_DIV_COMB
- if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
if (ahp->ah_diversity_control == HAL_ANT_VARIABLE) {
u_int8_t ant_div_control1 =
ar9300_eeprom_get(ahp, EEP_ANTDIV_control);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
index f1ae989..5e4a0a1 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
@@ -1643,6 +1643,10 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
u_int32_t xlan_gpio_cfg;
u_int8_t i;
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: use_bt_ant_enable=%d\n",
+ __func__, ahp->ah_lna_div_use_bt_ant_enable);
+
+ /* XXX TODO: only if rx_gain_idx == 0 */
if (AR_SREV_POSEIDON(ah)) {
xlan_gpio_cfg = ah->ah_config.ath_hal_ext_lna_ctl_gpio;
if (xlan_gpio_cfg) {
@@ -1733,7 +1737,7 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
}
}
- if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) {
+ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control);
/* main_lnaconf, alt_lnaconf, main_tb, alt_tb */
regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
@@ -1747,6 +1751,29 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
regval |= ANT_DIV_ENABLE;
}
+ if (AR_SREV_APHRODITE(ah)) {
+ if (ahp->ah_lna_div_use_bt_ant_enable) {
+ regval |= (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT);
+
+ OS_REG_SET_BIT(ah, AR_PHY_RESTART,
+ RESTART__ENABLE_ANT_FAST_DIV_M2FLAG__MASK);
+
+ /* Force WLAN LNA diversity ON */
+ OS_REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
+ AR_BTCOEX_WL_LNADIV_FORCE_ON);
+ } else {
+ regval &= ~(1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT);
+ regval &= ~(1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT);
+
+ OS_REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
+ (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT));
+
+ /* Force WLAN LNA diversity OFF */
+ OS_REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
+ AR_BTCOEX_WL_LNADIV_FORCE_ON);
+ }
+ }
+
#endif /* ATH_ANT_DIV_COMB */
OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
@@ -1756,7 +1783,8 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
regval |= ((value >> 7) & 0x1) <<
BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT;
#if ATH_ANT_DIV_COMB
- if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
+ if ((AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah))
+ && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
regval |= FAST_DIV_ENABLE;
}
#endif /* ATH_ANT_DIV_COMB */
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
index d00f7c8..e914057 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
@@ -303,6 +303,15 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
/* MCI bluetooth functions */
if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
+ /*
+ * Note: these are done in attach too for now, because
+ * at this point we haven't yet setup the mac/bb revision
+ * values, so this code is effectively NULL.
+ * However, I'm leaving this here so people digging
+ * into the code (a) see the MCI bits here, and (b)
+ * are now told they should look elsewhere for
+ * these methods.
+ */
ah->ah_btCoexSetWeights = ar9300_mci_bt_coex_set_weights;
ah->ah_btCoexDisable = ar9300_mci_bt_coex_disable;
ah->ah_btCoexEnable = ar9300_mci_bt_coex_enable;
@@ -310,7 +319,7 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
ah->ah_btMciSetup = ar9300_mci_setup;
ah->ah_btMciSendMessage = ar9300_mci_send_message;
ah->ah_btMciGetInterrupt = ar9300_mci_get_interrupt;
- ah->ah_btMciGetState = ar9300_mci_state;
+ ah->ah_btMciState = ar9300_mci_state;
ah->ah_btMciDetach = ar9300_mci_detach;
/* LNA diversity functions */
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
index 1ad0a44..71a3388 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
@@ -161,23 +161,6 @@ struct dfs_bin5pulse {
u_int32_t b5_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dB */
};
-#if 0
-/* SPECTRAL SCAN defines begin */
-typedef struct {
- u_int16_t ss_fft_period; /* Skip interval for FFT reports */
- u_int16_t ss_period; /* Spectral scan period */
- u_int16_t ss_count; /* # of reports to return from ss_active */
- u_int16_t ss_short_report;/* Set to report ony 1 set of FFT results */
- u_int8_t radar_bin_thresh_sel;
- u_int16_t ss_spectral_pri; /* are we doing a noise power cal ? */
- int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */
- int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */
- int32_t ss_nf_temp_data; /* temperature data taken during nf scan */
-} HAL_SPECTRAL_PARAM;
-#define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF
-#define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */
-#endif
-
/*
* Noise power data definitions
* units are: 4 x dBm - NOISE_PWR_DATA_OFFSET (e.g. -25 = (-25/4 - 90) = -96.25 dBm)
@@ -199,13 +182,6 @@ typedef struct halvowstats {
u_int32_t ext_cycle_count;
} HAL_VOWSTATS;
-#define HAL_BT_COEX_FLAG_LOW_ACK_PWR 0x00000001
-#define HAL_BT_COEX_FLAG_LOWER_TX_PWR 0x00000002
-#define HAL_BT_COEX_FLAG_ANT_DIV_ALLOW 0x00000004 /* Check Rx Diversity is allowed */
-#define HAL_BT_COEX_FLAG_ANT_DIV_ENABLE 0x00000008 /* Check Diversity is on or off */
-#define HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR 0x00000010
-#define HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX 0x00000020
-
/*
* Weight table configurations.
*/
@@ -260,339 +236,6 @@ typedef struct halvowstats {
#define HAL_MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */
-typedef enum mci_message_header {
- MCI_LNA_CTRL = 0x10, /* len = 0 */
- MCI_CONT_NACK = 0x20, /* len = 0 */
- MCI_CONT_INFO = 0x30, /* len = 4 */
- MCI_CONT_RST = 0x40, /* len = 0 */
- MCI_SCHD_INFO = 0x50, /* len = 16 */
- MCI_CPU_INT = 0x60, /* len = 4 */
- MCI_SYS_WAKING = 0x70, /* len = 0 */
- MCI_GPM = 0x80, /* len = 16 */
- MCI_LNA_INFO = 0x90, /* len = 1 */
- MCI_LNA_STATE = 0x94,
- MCI_LNA_TAKE = 0x98,
- MCI_LNA_TRANS = 0x9c,
- MCI_SYS_SLEEPING = 0xa0, /* len = 0 */
- MCI_REQ_WAKE = 0xc0, /* len = 0 */
- MCI_DEBUG_16 = 0xfe, /* len = 2 */
- MCI_REMOTE_RESET = 0xff /* len = 16 */
-} MCI_MESSAGE_HEADER;
-
-/* Default remote BT device MCI COEX version */
-#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3
-#define MCI_GPM_COEX_MINOR_VERSION_DEFAULT 0
-/* Local WLAN MCI COEX version */
-#define MCI_GPM_COEX_MAJOR_VERSION_WLAN 3
-#define MCI_GPM_COEX_MINOR_VERSION_WLAN 0
-
-typedef enum mci_gpm_subtype {
- MCI_GPM_BT_CAL_REQ = 0,
- MCI_GPM_BT_CAL_GRANT = 1,
- MCI_GPM_BT_CAL_DONE = 2,
- MCI_GPM_WLAN_CAL_REQ = 3,
- MCI_GPM_WLAN_CAL_GRANT = 4,
- MCI_GPM_WLAN_CAL_DONE = 5,
- MCI_GPM_COEX_AGENT = 0x0C,
- MCI_GPM_RSVD_PATTERN = 0xFE,
- MCI_GPM_RSVD_PATTERN32 = 0xFEFEFEFE,
- MCI_GPM_BT_DEBUG = 0xFF
-} MCI_GPM_SUBTYPE_T;
-
-typedef enum mci_gpm_coex_opcode {
- MCI_GPM_COEX_VERSION_QUERY = 0,
- MCI_GPM_COEX_VERSION_RESPONSE = 1,
- MCI_GPM_COEX_STATUS_QUERY = 2,
- MCI_GPM_COEX_HALT_BT_GPM = 3,
- MCI_GPM_COEX_WLAN_CHANNELS = 4,
- MCI_GPM_COEX_BT_PROFILE_INFO = 5,
- MCI_GPM_COEX_BT_STATUS_UPDATE = 6,
- MCI_GPM_COEX_BT_UPDATE_FLAGS = 7
-} MCI_GPM_COEX_OPCODE_T;
-
-typedef enum mci_gpm_coex_query_type {
- /* WLAN information */
- MCI_GPM_COEX_QUERY_WLAN_ALL_INFO = 0x01,
- /* BT information */
- MCI_GPM_COEX_QUERY_BT_ALL_INFO = 0x01,
- MCI_GPM_COEX_QUERY_BT_TOPOLOGY = 0x02,
- MCI_GPM_COEX_QUERY_BT_DEBUG = 0x04
-} MCI_GPM_COEX_QUERY_TYPE_T;
-
-typedef enum mci_gpm_coex_halt_bt_gpm {
- MCI_GPM_COEX_BT_GPM_UNHALT = 0,
- MCI_GPM_COEX_BT_GPM_HALT = 1
-} MCI_GPM_COEX_HALT_BT_GPM_T;
-
-typedef enum mci_gpm_coex_profile_type {
- MCI_GPM_COEX_PROFILE_UNKNOWN = 0,
- MCI_GPM_COEX_PROFILE_RFCOMM = 1,
- MCI_GPM_COEX_PROFILE_A2DP = 2,
- MCI_GPM_COEX_PROFILE_HID = 3,
- MCI_GPM_COEX_PROFILE_BNEP = 4,
- MCI_GPM_COEX_PROFILE_VOICE = 5,
- MCI_GPM_COEX_PROFILE_MAX
-} MCI_GPM_COEX_PROFILE_TYPE_T;
-
-typedef enum mci_gpm_coex_profile_state {
- MCI_GPM_COEX_PROFILE_STATE_END = 0,
- MCI_GPM_COEX_PROFILE_STATE_START = 1
-} MCI_GPM_COEX_PROFILE_STATE_T;
-
-typedef enum mci_gpm_coex_profile_role {
- MCI_GPM_COEX_PROFILE_SLAVE = 0,
- MCI_GPM_COEX_PROFILE_MASTER = 1
-} MCI_GPM_COEX_PROFILE_ROLE_T;
-
-typedef enum mci_gpm_coex_bt_status_type {
- MCI_GPM_COEX_BT_NONLINK_STATUS = 0,
- MCI_GPM_COEX_BT_LINK_STATUS = 1
-} MCI_GPM_COEX_BT_STATUS_TYPE_T;
-
-typedef enum mci_gpm_coex_bt_status_state {
- MCI_GPM_COEX_BT_NORMAL_STATUS = 0,
- MCI_GPM_COEX_BT_CRITICAL_STATUS = 1
-} MCI_GPM_COEX_BT_STATUS_STATE_T;
-
-#define MCI_GPM_INVALID_PROFILE_HANDLE 0xff
-
-typedef enum mci_gpm_coex_bt_updata_flags_op {
- MCI_GPM_COEX_BT_FLAGS_READ = 0x00,
- MCI_GPM_COEX_BT_FLAGS_SET = 0x01,
- MCI_GPM_COEX_BT_FLAGS_CLEAR = 0x02
-} MCI_GPM_COEX_BT_FLAGS_OP_T;
-
-/* MCI GPM/Coex opcode/type definitions */
-enum {
- MCI_GPM_COEX_W_GPM_PAYLOAD = 1,
- MCI_GPM_COEX_B_GPM_TYPE = 4,
- MCI_GPM_COEX_B_GPM_OPCODE = 5,
- /* MCI_GPM_WLAN_CAL_REQ, MCI_GPM_WLAN_CAL_DONE */
- MCI_GPM_WLAN_CAL_W_SEQUENCE = 2,
- /* MCI_GPM_COEX_VERSION_QUERY */
- /* MCI_GPM_COEX_VERSION_RESPONSE */
- MCI_GPM_COEX_B_MAJOR_VERSION = 6,
- MCI_GPM_COEX_B_MINOR_VERSION = 7,
- /* MCI_GPM_COEX_STATUS_QUERY */
- MCI_GPM_COEX_B_BT_BITMAP = 6,
- MCI_GPM_COEX_B_WLAN_BITMAP = 7,
- /* MCI_GPM_COEX_HALT_BT_GPM */
- MCI_GPM_COEX_B_HALT_STATE = 6,
- /* MCI_GPM_COEX_WLAN_CHANNELS */
- MCI_GPM_COEX_B_CHANNEL_MAP = 6,
- /* MCI_GPM_COEX_BT_PROFILE_INFO */
- MCI_GPM_COEX_B_PROFILE_TYPE = 6,
- MCI_GPM_COEX_B_PROFILE_LINKID = 7,
- MCI_GPM_COEX_B_PROFILE_STATE = 8,
- MCI_GPM_COEX_B_PROFILE_ROLE = 9,
- MCI_GPM_COEX_B_PROFILE_RATE = 10,
- MCI_GPM_COEX_B_PROFILE_VOTYPE = 11,
- MCI_GPM_COEX_H_PROFILE_T = 12,
- MCI_GPM_COEX_B_PROFILE_W = 14,
- MCI_GPM_COEX_B_PROFILE_A = 15,
- /* MCI_GPM_COEX_BT_STATUS_UPDATE */
- MCI_GPM_COEX_B_STATUS_TYPE = 6,
- MCI_GPM_COEX_B_STATUS_LINKID = 7,
- MCI_GPM_COEX_B_STATUS_STATE = 8,
- /* MCI_GPM_COEX_BT_UPDATE_FLAGS */
- MCI_GPM_COEX_B_BT_FLAGS_OP = 10,
- MCI_GPM_COEX_W_BT_FLAGS = 6
-};
-
-#define MCI_GPM_RECYCLE(_p_gpm) \
- { \
- *(((u_int32_t *)(_p_gpm)) + MCI_GPM_COEX_W_GPM_PAYLOAD) = MCI_GPM_RSVD_PATTERN32; \
- }
-#define MCI_GPM_TYPE(_p_gpm) \
- (*(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) & 0xff)
-#define MCI_GPM_OPCODE(_p_gpm) \
- (*(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) & 0xff)
-
-#define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type) \
- { \
- *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_cal_type) & 0xff; \
- }
-#define MCI_GPM_SET_TYPE_OPCODE(_p_gpm, _type, _opcode) \
- { \
- *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_type) & 0xff; \
- *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) = (_opcode) & 0xff; \
- }
-#define MCI_GPM_IS_CAL_TYPE(_type) ((_type) <= MCI_GPM_WLAN_CAL_DONE)
-
-#define MCI_NUM_BT_CHANNELS 79
-
-#define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \
- { \
- if (_bt_chan < MCI_NUM_BT_CHANNELS) { \
- *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
- (_bt_chan / 8)) |= 1 << (_bt_chan & 7); \
- } \
- }
-
-#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \
- { \
- if (_bt_chan < MCI_NUM_BT_CHANNELS) { \
- *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
- (_bt_chan / 8)) &= ~(1 << (_bt_chan & 7)); \
- } \
- }
-
-#define HAL_MCI_INTERRUPT_SW_MSG_DONE 0x00000001
-#define HAL_MCI_INTERRUPT_CPU_INT_MSG 0x00000002
-#define HAL_MCI_INTERRUPT_RX_CHKSUM_FAIL 0x00000004
-#define HAL_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008
-#define HAL_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010
-#define HAL_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020
-#define HAL_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080
-#define HAL_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100
-#define HAL_MCI_INTERRUPT_RX_MSG 0x00000200
-#define HAL_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400
-#define HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000
-#define HAL_MCI_INTERRUPT_MSG_FAIL_MASK ( HAL_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
- HAL_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
- HAL_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
- HAL_MCI_INTERRUPT_TX_SW_MSG_FAIL )
-
-#define HAL_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
-#define HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
-#define HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
-#define HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
-#define HAL_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
-#define HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
-#define HAL_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
-#define HAL_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
-#define HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
-#define HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
-#define HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
-#define HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
-#define HAL_MCI_INTERRUPT_RX_MSG_MONITOR (HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \
- HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
- HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
- HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
- HAL_MCI_INTERRUPT_RX_MSG_CONT_RST)
-
-typedef enum mci_bt_state {
- MCI_BT_SLEEP,
- MCI_BT_AWAKE,
- MCI_BT_CAL_START,
- MCI_BT_CAL
-} MCI_BT_STATE_T;
-
-/* Type of state query */
-typedef enum mci_state_type {
- HAL_MCI_STATE_ENABLE,
- HAL_MCI_STATE_INIT_GPM_OFFSET,
- HAL_MCI_STATE_NEXT_GPM_OFFSET,
- HAL_MCI_STATE_LAST_GPM_OFFSET,
- HAL_MCI_STATE_BT,
- HAL_MCI_STATE_SET_BT_SLEEP,
- HAL_MCI_STATE_SET_BT_AWAKE,
- HAL_MCI_STATE_SET_BT_CAL_START,
- HAL_MCI_STATE_SET_BT_CAL,
- HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET,
- HAL_MCI_STATE_REMOTE_SLEEP,
- HAL_MCI_STATE_CONT_RSSI_POWER,
- HAL_MCI_STATE_CONT_PRIORITY,
- HAL_MCI_STATE_CONT_TXRX,
- HAL_MCI_STATE_RESET_REQ_WAKE,
- HAL_MCI_STATE_SEND_WLAN_COEX_VERSION,
- HAL_MCI_STATE_SET_BT_COEX_VERSION,
- HAL_MCI_STATE_SEND_WLAN_CHANNELS,
- HAL_MCI_STATE_SEND_VERSION_QUERY,
- HAL_MCI_STATE_SEND_STATUS_QUERY,
- HAL_MCI_STATE_NEED_FLUSH_BT_INFO,
- HAL_MCI_STATE_SET_CONCUR_TX_PRI,
- HAL_MCI_STATE_RECOVER_RX,
- HAL_MCI_STATE_NEED_FTP_STOMP,
- HAL_MCI_STATE_NEED_TUNING,
- HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX,
- HAL_MCI_STATE_DEBUG,
- HAL_MCI_STATE_MAX
-} HAL_MCI_STATE_TYPE;
-
-#define HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG 1
-
-#define HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR 0x00000002
-#define HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR 0x00000004
-#define HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD 0x00000008
-#define HAL_MCI_BT_MCI_FLAGS_LNA_CTRL 0x00000010
-#define HAL_MCI_BT_MCI_FLAGS_DEBUG 0x00000020
-#define HAL_MCI_BT_MCI_FLAGS_SCHED_MSG 0x00000040
-#define HAL_MCI_BT_MCI_FLAGS_CONT_MSG 0x00000080
-#define HAL_MCI_BT_MCI_FLAGS_COEX_GPM 0x00000100
-#define HAL_MCI_BT_MCI_FLAGS_CPU_INT_MSG 0x00000200
-#define HAL_MCI_BT_MCI_FLAGS_MCI_MODE 0x00000400
-#define HAL_MCI_BT_MCI_FLAGS_EGRET_MODE 0x00000800
-#define HAL_MCI_BT_MCI_FLAGS_JUPITER_MODE 0x00001000
-#define HAL_MCI_BT_MCI_FLAGS_OTHER 0x00010000
-
-#define HAL_MCI_DEFAULT_BT_MCI_FLAGS 0x00011dde
-/*
- HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR = 1
- HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR = 1
- HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD = 1
- HAL_MCI_BT_MCI_FLAGS_LNA_CTRL = 1
- HAL_MCI_BT_MCI_FLAGS_DEBUG = 0
- HAL_MCI_BT_MCI_FLAGS_SCHED_MSG = 1
- HAL_MCI_BT_MCI_FLAGS_CONT_MSG = 1
- HAL_MCI_BT_MCI_FLAGS_COEX_GPM = 1
- HAL_MCI_BT_MCI_FLAGS_CPU_INT_MSG = 0
- HAL_MCI_BT_MCI_FLAGS_MCI_MODE = 1
- HAL_MCI_BT_MCI_FLAGS_EGRET_MODE = 1
- HAL_MCI_BT_MCI_FLAGS_JUPITER_MODE = 1
- HAL_MCI_BT_MCI_FLAGS_OTHER = 1
-*/
-
-#define HAL_MCI_TOGGLE_BT_MCI_FLAGS \
- ( HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR | \
- HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR | \
- HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD | \
- HAL_MCI_BT_MCI_FLAGS_MCI_MODE )
-
-#define HAL_MCI_2G_FLAGS_CLEAR_MASK 0x00000000
-#define HAL_MCI_2G_FLAGS_SET_MASK HAL_MCI_TOGGLE_BT_MCI_FLAGS
-#define HAL_MCI_2G_FLAGS HAL_MCI_DEFAULT_BT_MCI_FLAGS
-
-#define HAL_MCI_5G_FLAGS_CLEAR_MASK HAL_MCI_TOGGLE_BT_MCI_FLAGS
-#define HAL_MCI_5G_FLAGS_SET_MASK 0x00000000
-#define HAL_MCI_5G_FLAGS (HAL_MCI_DEFAULT_BT_MCI_FLAGS & \
- ~HAL_MCI_TOGGLE_BT_MCI_FLAGS)
-
-#define HAL_MCI_GPM_NOMORE 0
-#define HAL_MCI_GPM_MORE 1
-#define HAL_MCI_GPM_INVALID 0xffffffff
-
-#define ATH_AIC_MAX_BT_CHANNEL 79
-
-/*
- * Default value for Jupiter is 0x00002201
- * Default value for Aphrodite is 0x00002282
- */
-#define ATH_MCI_CONFIG_CONCUR_TX 0x00000003
-#define ATH_MCI_CONFIG_MCI_OBS_MCI 0x00000004
-#define ATH_MCI_CONFIG_MCI_OBS_TXRX 0x00000008
-#define ATH_MCI_CONFIG_MCI_OBS_BT 0x00000010
-#define ATH_MCI_CONFIG_DISABLE_MCI_CAL 0x00000020
-#define ATH_MCI_CONFIG_DISABLE_OSLA 0x00000040
-#define ATH_MCI_CONFIG_DISABLE_FTP_STOMP 0x00000080
-#define ATH_MCI_CONFIG_AGGR_THRESH 0x00000700
-#define ATH_MCI_CONFIG_AGGR_THRESH_S 8
-#define ATH_MCI_CONFIG_DISABLE_AGGR_THRESH 0x00000800
-#define ATH_MCI_CONFIG_CLK_DIV 0x00003000
-#define ATH_MCI_CONFIG_CLK_DIV_S 12
-#define ATH_MCI_CONFIG_DISABLE_TUNING 0x00004000
-#define ATH_MCI_CONFIG_MCI_WEIGHT_DBG 0x40000000
-#define ATH_MCI_CONFIG_DISABLE_MCI 0x80000000
-
-#define ATH_MCI_CONFIG_MCI_OBS_MASK ( ATH_MCI_CONFIG_MCI_OBS_MCI | \
- ATH_MCI_CONFIG_MCI_OBS_TXRX | \
- ATH_MCI_CONFIG_MCI_OBS_BT )
-#define ATH_MCI_CONFIG_MCI_OBS_GPIO 0x0000002F
-
-#define ATH_MCI_CONCUR_TX_SHARED_CHN 0x01
-#define ATH_MCI_CONCUR_TX_UNSHARED_CHN 0x02
-#define ATH_MCI_CONCUR_TX_DEBUG 0x03
-
/*
* The values below come from the system team test result.
* For Jupiter, BT tx power level is from 0(-20dBm) to 6(4dBm).
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
index acc14b3..b57b2b6 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
@@ -389,6 +389,8 @@ ar9300_get_pending_interrupts(
if (int_rx_msg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
ahp->ah_mci_cont_status =
OS_REG_READ(ah, AR_MCI_CONT_STATUS);
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(MCI) cont_status=0x%08x\n", ahp->ah_mci_cont_status);
}
OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
int_rx_msg);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c
index 26a0700..502746e 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c
@@ -73,6 +73,10 @@ void ar9300_mci_osla_setup(struct ath_hal *ah, HAL_BOOL enable)
if (!(ah->ah_config.ath_hal_mci_config &
ATH_MCI_CONFIG_DISABLE_AGGR_THRESH))
{
+
+ if (AR_SREV_APHRODITE(ah))
+ OS_REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);
+
thresh = MS(ah->ah_config.ath_hal_mci_config,
ATH_MCI_CONFIG_AGGR_THRESH);
OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
@@ -147,11 +151,11 @@ static int32_t ar9300_mci_wait_for_interrupt(struct ath_hal *ah,
}
if (time_out <= 0) {
- HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
"(MCI) %s: Wait for Reg0x%08x = 0x%08x timeout.\n",
__func__, address, bit_position);
HALDEBUG(ah, HAL_DEBUG_BT_COEX,
- "(MCI) INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x",
+ "(MCI) INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n",
OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW),
OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
time_out = 0;
@@ -450,6 +454,9 @@ void ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done)
void ar9300_mci_mute_bt(struct ath_hal *ah)
{
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
+
/* disable all MCI messages */
OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xFFFF0000);
OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xFFFFFFFF);
@@ -465,9 +472,11 @@ void ar9300_mci_mute_bt(struct ath_hal *ah)
* 1. reset not after resuming from full sleep
* 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
*/
- HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
- ar9300_mci_send_lna_take(ah, AH_TRUE);
- OS_DELAY(5);
+ if (MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config)) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
+ ar9300_mci_send_lna_take(ah, AH_TRUE);
+ OS_DELAY(5);
+ }
HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send sys sleeping\n");
ar9300_mci_send_sys_sleeping(ah, AH_TRUE);
}
@@ -488,10 +497,13 @@ static void ar9300_mci_observation_set_up(struct ath_hal *ah)
OS_REG_WRITE(ah, AR_PHY_TEST, 0x00080000); // a360
OS_REG_WRITE(ah, AR_PHY_TEST_CTL_STATUS, 0xe0000000); // a364
*/
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called; config=0x%08x\n",
+ __func__, ah->ah_config.ath_hal_mci_config);
- if (ah->ah_config.ath_hal_mci_config &
+ if (ah->ah_config.ath_hal_mci_config &
ATH_MCI_CONFIG_MCI_OBS_MCI)
{
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: CONFIG_MCI_OBS_MCI\n", __func__);
ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
@@ -500,6 +512,7 @@ static void ar9300_mci_observation_set_up(struct ath_hal *ah)
else if (ah->ah_config.ath_hal_mci_config &
ATH_MCI_CONFIG_MCI_OBS_TXRX)
{
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: CONFIG_MCI_OBS_TXRX\n", __func__);
ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
@@ -509,6 +522,7 @@ static void ar9300_mci_observation_set_up(struct ath_hal *ah)
else if (ah->ah_config.ath_hal_mci_config &
ATH_MCI_CONFIG_MCI_OBS_BT)
{
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: CONFIG_MCI_OBS_BT\n", __func__);
ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
@@ -834,7 +848,9 @@ static void ar9300_mci_prep_interface(struct ath_hal *ah)
AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
- if (AR_SREV_JUPITER_10(ah) || ahp->ah_mci_coex_is_2g) {
+ if (AR_SREV_JUPITER_10(ah) ||
+ (ahp->ah_mci_coex_is_2g &&
+ MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config))) {
/* Send LNA_TRANS */
HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send LNA_TRANS to BT\n",
__func__);
@@ -844,8 +860,8 @@ static void ar9300_mci_prep_interface(struct ath_hal *ah)
}
if (AR_SREV_JUPITER_10(ah) ||
- (ahp->ah_mci_coex_is_2g && !ahp->ah_mci_coex_2g5g_update))
- {
+ (ahp->ah_mci_coex_is_2g && !ahp->ah_mci_coex_2g5g_update &&
+ MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config))) {
if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) {
HALDEBUG(ah, HAL_DEBUG_BT_COEX,
@@ -913,6 +929,68 @@ void ar9300_mci_enable_interrupt(struct ath_hal *ah)
AR_MCI_INTERRUPT_RX_MSG_DEFAULT);
}
+static void ar9300_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hal *ah)
+{
+ uint32_t regval;
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
+ regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
+ SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+ SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
+ SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
+ SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+ SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+ OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
+ OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+}
+
+static void ar9300_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hal *ah)
+{
+ uint32_t regval;
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
+ regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
+ SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+ SM(0, AR_BTCOEX_CTRL_PA_SHARED) |
+ SM(0, AR_BTCOEX_CTRL_LNA_SHARED) |
+ SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+ SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+ OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0);
+ OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+}
+
+static void ar9300_mci_set_btcoex_ctrl_9462(struct ath_hal *ah)
+{
+ uint32_t regval;
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
+ regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
+ SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
+ SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
+ SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
+ SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
+ SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
+ SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+
+ if (AR_SREV_JUPITER_10(ah)) {
+ regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10);
+ }
+
+ OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
+}
+
void ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
HAL_BOOL is_full_sleep)
{
@@ -945,21 +1023,17 @@ void ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
* To avoid MCI state machine be affected by incoming remote MCI messages,
* MCI mode will be enabled later, right before reset the MCI TX and RX.
*/
- regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
- SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
- SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
- SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
- SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
- SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
- SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
- SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
- SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
-
- if (AR_SREV_JUPITER_10(ah)) {
- regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10);
+ if (AR_SREV_APHRODITE(ah)) {
+ uint8_t ant = MS(ah->ah_config.ath_hal_mci_config,
+ ATH_MCI_CONFIG_ANT_ARCH);
+ if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED)
+ ar9300_mci_set_btcoex_ctrl_9565_1ANT(ah);
+ else
+ ar9300_mci_set_btcoex_ctrl_9565_2ANT(ah);
+ } else {
+ ar9300_mci_set_btcoex_ctrl_9462(ah);
}
- OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
if (is_2g && (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) &&
!(ah->ah_config.ath_hal_mci_config &
@@ -982,6 +1056,9 @@ void ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
+ /* Set the time out to 3.125ms (5 BT slots) */
+ OS_REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);
+
if (ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_CONCUR_TX) {
u_int8_t i;
u_int32_t const *pmax_tx_pwr;
@@ -1080,7 +1157,11 @@ void ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
(SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
- OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+ if (MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config)) {
+ OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+ } else {
+ OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+ }
if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
ar9300_mci_observation_set_up(ah);
@@ -1342,8 +1423,8 @@ ar9300_mci_state(struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data)
if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) {
value = OS_REG_READ(ah, AR_BTCOEX_CTRL);
if ((value == 0xdeadbeef) || (value == 0xffffffff)) {
- // HALDEBUG(ah, HAL_DEBUG_BT_COEX,
- // "(MCI) BTCOEX_CTRL = 0xdeadbeef\n");
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(MCI) BTCOEX_CTRL = 0xdeadbeef\n");
value = 0;
}
}
@@ -1745,6 +1826,8 @@ void ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type)
// struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
u_int32_t tx_priority = 0;
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: stomp_type=%d\n", __func__, stomp_type);
+
switch (stomp_type) {
case HAL_BT_COEX_STOMP_ALL:
ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_WLAN_WGHT0;
@@ -1828,16 +1911,16 @@ void ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type)
ahp->ah_bt_coex_wlan_weight[3] |=
SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK2);
}
- if (ah->ah_config.ath_hal_mci_config &
- ATH_MCI_CONFIG_MCI_WEIGHT_DBG)
- {
+// if (ah->ah_config.ath_hal_mci_config &
+// ATH_MCI_CONFIG_MCI_WEIGHT_DBG)
+// {
HALDEBUG(ah, HAL_DEBUG_BT_COEX,
"(MCI) Set weights: 0x%08x 0x%08x 0x%08x 0x%08x\n",
ahp->ah_bt_coex_wlan_weight[0],
ahp->ah_bt_coex_wlan_weight[1],
ahp->ah_bt_coex_wlan_weight[2],
ahp->ah_bt_coex_wlan_weight[3]);
- }
+// }
}
void ar9300_mci_bt_coex_disable(struct ath_hal *ah)
@@ -1865,6 +1948,16 @@ int ar9300_mci_bt_coex_enable(struct ath_hal *ah)
{
struct ath_hal_9300 *ahp = AH9300(ah);
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: called\n", __func__);
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(MCI) Write weights: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ahp->ah_bt_coex_wlan_weight[0],
+ ahp->ah_bt_coex_wlan_weight[1],
+ ahp->ah_bt_coex_wlan_weight[2],
+ ahp->ah_bt_coex_wlan_weight[3]);
+
+
/* Mainly change the WLAN weight table */
OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
index 6972200..d320df1 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
@@ -2457,11 +2457,13 @@ static void
ar9300_bt_coex_antenna_diversity(struct ath_hal *ah, u_int32_t value)
{
struct ath_hal_9300 *ahp = AH9300(ah);
-#if ATH_ANT_DIV_COMB
+#if ATH_ANT_DIV_COMB
//struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
#endif
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called, value=%d\n", __func__, value);
+
if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW)
{
if (ahp->ah_diversity_control == HAL_ANT_VARIABLE)
@@ -2494,7 +2496,7 @@ ar9300_bt_coex_set_parameter(struct ath_hal *ah, u_int32_t type,
break;
case HAL_BT_COEX_ANTENNA_DIVERSITY:
- if (AR_SREV_POSEIDON(ah)) {
+ if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW;
if (value) {
ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_ANT_DIV_ENABLE;
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
index 3a95c35..ee16ca0 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
@@ -5340,6 +5340,9 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
ar9300_set_smart_antenna(ah, ahp->ah_smartantenna_enable);
+ if (AR_SREV_APHRODITE(ah) && ahp->ah_lna_div_use_bt_ant_enable)
+ OS_REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+
if (ahp->ah_skip_rx_iq_cal && !is_scan) {
/* restore RX Cal result if existing */
ar9300_rx_iq_cal_restore(ah);
@@ -6385,6 +6388,9 @@ ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal *ah, HAL_BOOL enable, cons
struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
HAL_CAPABILITIES *pcap = &ahpriv->ah_caps;
+ HALDEBUG(ah, HAL_DEBUG_RESET | HAL_DEBUG_BT_COEX,
+ "%s: called; enable=%d\n", __func__, enable);
+
if (AR_SREV_POSEIDON(ah)) {
// Make sure this scheme is only used for WB225(Astra)
ahp->ah_lna_div_use_bt_ant_enable = enable;
@@ -6454,10 +6460,35 @@ ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal *ah, HAL_BOOL enable, cons
}
return AH_TRUE;
- } else {
+ } else if (AR_SREV_APHRODITE(ah)) {
+ ahp->ah_lna_div_use_bt_ant_enable = enable;
+ if (enable) {
+ OS_REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, ANT_DIV_ENABLE);
+ OS_REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT));
+ OS_REG_SET_BIT(ah, AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+ OS_REG_SET_BIT(ah, AR_PHY_RESTART, RESTART__ENABLE_ANT_FAST_DIV_M2FLAG__MASK);
+ OS_REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+ } else {
+ OS_REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, ANT_DIV_ENABLE);
+ OS_REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT));
+ OS_REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+ OS_REG_CLR_BIT(ah, AR_PHY_RESTART, RESTART__ENABLE_ANT_FAST_DIV_M2FLAG__MASK);
+ OS_REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+
+ regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK |
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK |
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK |
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK));
+ regval |= (HAL_ANT_DIV_COMB_LNA1 <<
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT);
+ regval |= (HAL_ANT_DIV_COMB_LNA2 <<
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT);
+
+ OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+ }
return AH_TRUE;
}
-
- /* XXX TODO: Add AR9565 support? */
+ return AH_TRUE;
}
#endif /* ATH_ANT_DIV_COMB */
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
index 72ed110..ee6bb0f 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
@@ -614,6 +614,7 @@ ar9300_set_11n_tx_desc(
(key_ix != HAL_TXKEYIX_INVALID ? SM(key_ix, AR_dest_idx) : 0)
| SM(type, AR_frame_type)
| (flags & HAL_TXDESC_NOACK ? AR_no_ack : 0)
+ | (flags & HAL_TXDESC_HWTS ? AR_insert_ts : 0)
| (flags & HAL_TXDESC_EXT_ONLY ? AR_ext_only : 0)
| (flags & HAL_TXDESC_EXT_AND_CTL ? AR_ext_and_ctl : 0);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h
index 0d072e3..a5e0f79 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h
@@ -2855,6 +2855,9 @@ enum {
#define AR_BTCOEX_WL_WEIGHTS3 AR_WLAN_COEX_OFFSET(BTCOEX_WL_WEIGHTS3)
#define AR_BTCOEX_MAX_TXPWR(_x) (AR_WLAN_COEX_OFFSET(BTCOEX_MAX_TXPWR) + ((_x) << 2))
#define AR_BTCOEX_WL_LNA AR_WLAN_COEX_OFFSET(BTCOEX_WL_LNA)
+#define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF
+#define AR_BTCOEX_WL_LNA_TIMEOUT_S 0
+
#define AR_BTCOEX_RFGAIN_CTRL AR_WLAN_COEX_OFFSET(BTCOEX_RFGAIN_CTRL)
#define AR_BTCOEX_CTRL2 AR_WLAN_COEX_OFFSET(BTCOEX_CTRL2)
@@ -2887,6 +2890,32 @@ enum {
#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000FFF
#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0
+/* QCA9565 */
+
+#define AR_BTCOEX_WL_LNADIV 0x1a64
+#define AR_BTCOEX_WL_LNADIV_PREDICTED_PERIOD 0x00003FFF
+#define AR_BTCOEX_WL_LNADIV_PREDICTED_PERIOD_S 0
+#define AR_BTCOEX_WL_LNADIV_DPDT_IGNORE_PRIORITY 0x00004000
+#define AR_BTCOEX_WL_LNADIV_DPDT_IGNORE_PRIORITY_S 14
+#define AR_BTCOEX_WL_LNADIV_FORCE_ON 0x00008000
+#define AR_BTCOEX_WL_LNADIV_FORCE_ON_S 15
+#define AR_BTCOEX_WL_LNADIV_MODE_OPTION 0x00030000
+#define AR_BTCOEX_WL_LNADIV_MODE_OPTION_S 16
+#define AR_BTCOEX_WL_LNADIV_MODE 0x007c0000
+#define AR_BTCOEX_WL_LNADIV_MODE_S 18
+#define AR_BTCOEX_WL_LNADIV_ALLOWED_TX_ANTDIV_WL_TX_REQ 0x00800000
+#define AR_BTCOEX_WL_LNADIV_ALLOWED_TX_ANTDIV_WL_TX_REQ_S 23
+#define AR_BTCOEX_WL_LNADIV_DISABLE_TX_ANTDIV_ENABLE 0x01000000
+#define AR_BTCOEX_WL_LNADIV_DISABLE_TX_ANTDIV_ENABLE_S 24
+#define AR_BTCOEX_WL_LNADIV_CONTINUOUS_BT_ACTIVE_PROTECT 0x02000000
+#define AR_BTCOEX_WL_LNADIV_CONTINUOUS_BT_ACTIVE_PROTECT_S 25
+#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD 0xFC000000
+#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD_S 26
+
+#define AR_MCI_MISC 0x1a74
+#define AR_MCI_MISC_HW_FIX_EN 0x00000001
+#define AR_MCI_MISC_HW_FIX_EN_S 0
+
/******************************************************************************
* WLAN BT Global Register Map
******************************************************************************/
diff --git a/sys/crypto/sha2/sha256c.c b/sys/crypto/sha2/sha256c.c
index 79ed61d..a08b08f 100644
--- a/sys/crypto/sha2/sha256c.c
+++ b/sys/crypto/sha2/sha256c.c
@@ -78,6 +78,26 @@ be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
#endif /* BYTE_ORDER != BIG_ENDIAN */
+/* SHA256 round constants. */
+static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
/* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
@@ -90,18 +110,21 @@ be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
/* SHA256 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
- t0 = h + S1(e) + Ch(e, f, g) + k; \
- t1 = S0(a) + Maj(a, b, c); \
- d += t0; \
- h = t0 + t1;
+ h += S1(e) + Ch(e, f, g) + k; \
+ d += h; \
+ h += S0(a) + Maj(a, b, c);
/* Adjusted round function for rotating state */
-#define RNDr(S, W, i, k) \
+#define RNDr(S, W, i, ii) \
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
S[(66 - i) % 8], S[(67 - i) % 8], \
S[(68 - i) % 8], S[(69 - i) % 8], \
S[(70 - i) % 8], S[(71 - i) % 8], \
- W[i] + k)
+ W[i + ii] + K[i + ii])
+
+/* Message schedule computation */
+#define MSCH(W, ii, i) \
+ W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
/*
* SHA256 block compression function. The 256-bit state is transformed via
@@ -112,82 +135,52 @@ SHA256_Transform(uint32_t * state, const unsigned char block[64])
{
uint32_t W[64];
uint32_t S[8];
- uint32_t t0, t1;
int i;
- /* 1. Prepare message schedule W. */
+ /* 1. Prepare the first part of the message schedule W. */
be32dec_vect(W, block, 64);
- for (i = 16; i < 64; i++)
- W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 32);
/* 3. Mix. */
- RNDr(S, W, 0, 0x428a2f98);
- RNDr(S, W, 1, 0x71374491);
- RNDr(S, W, 2, 0xb5c0fbcf);
- RNDr(S, W, 3, 0xe9b5dba5);
- RNDr(S, W, 4, 0x3956c25b);
- RNDr(S, W, 5, 0x59f111f1);
- RNDr(S, W, 6, 0x923f82a4);
- RNDr(S, W, 7, 0xab1c5ed5);
- RNDr(S, W, 8, 0xd807aa98);
- RNDr(S, W, 9, 0x12835b01);
- RNDr(S, W, 10, 0x243185be);
- RNDr(S, W, 11, 0x550c7dc3);
- RNDr(S, W, 12, 0x72be5d74);
- RNDr(S, W, 13, 0x80deb1fe);
- RNDr(S, W, 14, 0x9bdc06a7);
- RNDr(S, W, 15, 0xc19bf174);
- RNDr(S, W, 16, 0xe49b69c1);
- RNDr(S, W, 17, 0xefbe4786);
- RNDr(S, W, 18, 0x0fc19dc6);
- RNDr(S, W, 19, 0x240ca1cc);
- RNDr(S, W, 20, 0x2de92c6f);
- RNDr(S, W, 21, 0x4a7484aa);
- RNDr(S, W, 22, 0x5cb0a9dc);
- RNDr(S, W, 23, 0x76f988da);
- RNDr(S, W, 24, 0x983e5152);
- RNDr(S, W, 25, 0xa831c66d);
- RNDr(S, W, 26, 0xb00327c8);
- RNDr(S, W, 27, 0xbf597fc7);
- RNDr(S, W, 28, 0xc6e00bf3);
- RNDr(S, W, 29, 0xd5a79147);
- RNDr(S, W, 30, 0x06ca6351);
- RNDr(S, W, 31, 0x14292967);
- RNDr(S, W, 32, 0x27b70a85);
- RNDr(S, W, 33, 0x2e1b2138);
- RNDr(S, W, 34, 0x4d2c6dfc);
- RNDr(S, W, 35, 0x53380d13);
- RNDr(S, W, 36, 0x650a7354);
- RNDr(S, W, 37, 0x766a0abb);
- RNDr(S, W, 38, 0x81c2c92e);
- RNDr(S, W, 39, 0x92722c85);
- RNDr(S, W, 40, 0xa2bfe8a1);
- RNDr(S, W, 41, 0xa81a664b);
- RNDr(S, W, 42, 0xc24b8b70);
- RNDr(S, W, 43, 0xc76c51a3);
- RNDr(S, W, 44, 0xd192e819);
- RNDr(S, W, 45, 0xd6990624);
- RNDr(S, W, 46, 0xf40e3585);
- RNDr(S, W, 47, 0x106aa070);
- RNDr(S, W, 48, 0x19a4c116);
- RNDr(S, W, 49, 0x1e376c08);
- RNDr(S, W, 50, 0x2748774c);
- RNDr(S, W, 51, 0x34b0bcb5);
- RNDr(S, W, 52, 0x391c0cb3);
- RNDr(S, W, 53, 0x4ed8aa4a);
- RNDr(S, W, 54, 0x5b9cca4f);
- RNDr(S, W, 55, 0x682e6ff3);
- RNDr(S, W, 56, 0x748f82ee);
- RNDr(S, W, 57, 0x78a5636f);
- RNDr(S, W, 58, 0x84c87814);
- RNDr(S, W, 59, 0x8cc70208);
- RNDr(S, W, 60, 0x90befffa);
- RNDr(S, W, 61, 0xa4506ceb);
- RNDr(S, W, 62, 0xbef9a3f7);
- RNDr(S, W, 63, 0xc67178f2);
+ for (i = 0; i < 64; i += 16) {
+ RNDr(S, W, 0, i);
+ RNDr(S, W, 1, i);
+ RNDr(S, W, 2, i);
+ RNDr(S, W, 3, i);
+ RNDr(S, W, 4, i);
+ RNDr(S, W, 5, i);
+ RNDr(S, W, 6, i);
+ RNDr(S, W, 7, i);
+ RNDr(S, W, 8, i);
+ RNDr(S, W, 9, i);
+ RNDr(S, W, 10, i);
+ RNDr(S, W, 11, i);
+ RNDr(S, W, 12, i);
+ RNDr(S, W, 13, i);
+ RNDr(S, W, 14, i);
+ RNDr(S, W, 15, i);
+
+ if (i == 48)
+ break;
+ MSCH(W, 0, i);
+ MSCH(W, 1, i);
+ MSCH(W, 2, i);
+ MSCH(W, 3, i);
+ MSCH(W, 4, i);
+ MSCH(W, 5, i);
+ MSCH(W, 6, i);
+ MSCH(W, 7, i);
+ MSCH(W, 8, i);
+ MSCH(W, 9, i);
+ MSCH(W, 10, i);
+ MSCH(W, 11, i);
+ MSCH(W, 12, i);
+ MSCH(W, 13, i);
+ MSCH(W, 14, i);
+ MSCH(W, 15, i);
+ }
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
@@ -205,22 +198,29 @@ static unsigned char PAD[64] = {
static void
SHA256_Pad(SHA256_CTX * ctx)
{
- unsigned char len[8];
- uint32_t r, plen;
-
- /*
- * Convert length to a vector of bytes -- we do this now rather
- * than later because the length will change after we pad.
- */
- be64enc(len, ctx->count);
+ size_t r;
- /* Add 1--64 bytes so that the resulting length is 56 mod 64 */
+ /* Figure out how many bytes we have buffered. */
r = (ctx->count >> 3) & 0x3f;
- plen = (r < 56) ? (56 - r) : (120 - r);
- SHA256_Update(ctx, PAD, (size_t)plen);
- /* Add the terminating bit-count */
- SHA256_Update(ctx, len, 8);
+ /* Pad to 56 mod 64, transforming if we finish a block en route. */
+ if (r < 56) {
+ /* Pad to 56 mod 64. */
+ memcpy(&ctx->buf[r], PAD, 56 - r);
+ } else {
+ /* Finish the current block and mix. */
+ memcpy(&ctx->buf[r], PAD, 64 - r);
+ SHA256_Transform(ctx->state, ctx->buf);
+
+ /* The start of the final block is all zeroes. */
+ memset(&ctx->buf[0], 0, 56);
+ }
+
+ /* Add the terminating bit-count. */
+ be64enc(&ctx->buf[56], ctx->count);
+
+ /* Mix in the final block. */
+ SHA256_Transform(ctx->state, ctx->buf);
}
/* SHA-256 initialization. Begins a SHA-256 operation. */
diff --git a/sys/crypto/sha2/sha512c.c b/sys/crypto/sha2/sha512c.c
index 5c107ea..21c7efa 100644
--- a/sys/crypto/sha2/sha512c.c
+++ b/sys/crypto/sha2/sha512c.c
@@ -1,5 +1,6 @@
/*-
* Copyright 2005 Colin Percival
+ * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +38,7 @@ __FBSDID("$FreeBSD$");
#endif
#include "sha512.h"
+#include "sha512t.h"
#include "sha384.h"
#if BYTE_ORDER == BIG_ENDIAN
@@ -79,6 +81,50 @@ be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
#endif /* BYTE_ORDER != BIG_ENDIAN */
+/* SHA512 round constants. */
+static const uint64_t K[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
/* Elementary functions used by SHA512 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
@@ -91,18 +137,21 @@ be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
/* SHA512 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
- t0 = h + S1(e) + Ch(e, f, g) + k; \
- t1 = S0(a) + Maj(a, b, c); \
- d += t0; \
- h = t0 + t1;
+ h += S1(e) + Ch(e, f, g) + k; \
+ d += h; \
+ h += S0(a) + Maj(a, b, c);
/* Adjusted round function for rotating state */
-#define RNDr(S, W, i, k) \
+#define RNDr(S, W, i, ii) \
RND(S[(80 - i) % 8], S[(81 - i) % 8], \
S[(82 - i) % 8], S[(83 - i) % 8], \
S[(84 - i) % 8], S[(85 - i) % 8], \
S[(86 - i) % 8], S[(87 - i) % 8], \
- W[i] + k)
+ W[i + ii] + K[i + ii])
+
+/* Message schedule computation */
+#define MSCH(W, ii, i) \
+ W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
/*
* SHA512 block compression function. The 512-bit state is transformed via
@@ -113,98 +162,52 @@ SHA512_Transform(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH
{
uint64_t W[80];
uint64_t S[8];
- uint64_t t0, t1;
int i;
- /* 1. Prepare message schedule W. */
+ /* 1. Prepare the first part of the message schedule W. */
be64dec_vect(W, block, SHA512_BLOCK_LENGTH);
- for (i = 16; i < 80; i++)
- W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, SHA512_DIGEST_LENGTH);
/* 3. Mix. */
- RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
- RNDr(S, W, 1, 0x7137449123ef65cdULL);
- RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
- RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
- RNDr(S, W, 4, 0x3956c25bf348b538ULL);
- RNDr(S, W, 5, 0x59f111f1b605d019ULL);
- RNDr(S, W, 6, 0x923f82a4af194f9bULL);
- RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
- RNDr(S, W, 8, 0xd807aa98a3030242ULL);
- RNDr(S, W, 9, 0x12835b0145706fbeULL);
- RNDr(S, W, 10, 0x243185be4ee4b28cULL);
- RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
- RNDr(S, W, 12, 0x72be5d74f27b896fULL);
- RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
- RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
- RNDr(S, W, 15, 0xc19bf174cf692694ULL);
- RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
- RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
- RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
- RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
- RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
- RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
- RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
- RNDr(S, W, 23, 0x76f988da831153b5ULL);
- RNDr(S, W, 24, 0x983e5152ee66dfabULL);
- RNDr(S, W, 25, 0xa831c66d2db43210ULL);
- RNDr(S, W, 26, 0xb00327c898fb213fULL);
- RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
- RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
- RNDr(S, W, 29, 0xd5a79147930aa725ULL);
- RNDr(S, W, 30, 0x06ca6351e003826fULL);
- RNDr(S, W, 31, 0x142929670a0e6e70ULL);
- RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
- RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
- RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
- RNDr(S, W, 35, 0x53380d139d95b3dfULL);
- RNDr(S, W, 36, 0x650a73548baf63deULL);
- RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
- RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
- RNDr(S, W, 39, 0x92722c851482353bULL);
- RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
- RNDr(S, W, 41, 0xa81a664bbc423001ULL);
- RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
- RNDr(S, W, 43, 0xc76c51a30654be30ULL);
- RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
- RNDr(S, W, 45, 0xd69906245565a910ULL);
- RNDr(S, W, 46, 0xf40e35855771202aULL);
- RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
- RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
- RNDr(S, W, 49, 0x1e376c085141ab53ULL);
- RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
- RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
- RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
- RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
- RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
- RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
- RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
- RNDr(S, W, 57, 0x78a5636f43172f60ULL);
- RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
- RNDr(S, W, 59, 0x8cc702081a6439ecULL);
- RNDr(S, W, 60, 0x90befffa23631e28ULL);
- RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
- RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
- RNDr(S, W, 63, 0xc67178f2e372532bULL);
- RNDr(S, W, 64, 0xca273eceea26619cULL);
- RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
- RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
- RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
- RNDr(S, W, 68, 0x06f067aa72176fbaULL);
- RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
- RNDr(S, W, 70, 0x113f9804bef90daeULL);
- RNDr(S, W, 71, 0x1b710b35131c471bULL);
- RNDr(S, W, 72, 0x28db77f523047d84ULL);
- RNDr(S, W, 73, 0x32caab7b40c72493ULL);
- RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
- RNDr(S, W, 75, 0x431d67c49c100d4cULL);
- RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
- RNDr(S, W, 77, 0x597f299cfc657e2aULL);
- RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
- RNDr(S, W, 79, 0x6c44198c4a475817ULL);
+ for (i = 0; i < 80; i += 16) {
+ RNDr(S, W, 0, i);
+ RNDr(S, W, 1, i);
+ RNDr(S, W, 2, i);
+ RNDr(S, W, 3, i);
+ RNDr(S, W, 4, i);
+ RNDr(S, W, 5, i);
+ RNDr(S, W, 6, i);
+ RNDr(S, W, 7, i);
+ RNDr(S, W, 8, i);
+ RNDr(S, W, 9, i);
+ RNDr(S, W, 10, i);
+ RNDr(S, W, 11, i);
+ RNDr(S, W, 12, i);
+ RNDr(S, W, 13, i);
+ RNDr(S, W, 14, i);
+ RNDr(S, W, 15, i);
+
+ if (i == 64)
+ break;
+ MSCH(W, 0, i);
+ MSCH(W, 1, i);
+ MSCH(W, 2, i);
+ MSCH(W, 3, i);
+ MSCH(W, 4, i);
+ MSCH(W, 5, i);
+ MSCH(W, 6, i);
+ MSCH(W, 7, i);
+ MSCH(W, 8, i);
+ MSCH(W, 9, i);
+ MSCH(W, 10, i);
+ MSCH(W, 11, i);
+ MSCH(W, 12, i);
+ MSCH(W, 13, i);
+ MSCH(W, 14, i);
+ MSCH(W, 15, i);
+ }
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
@@ -226,22 +229,29 @@ static unsigned char PAD[SHA512_BLOCK_LENGTH] = {
static void
SHA512_Pad(SHA512_CTX * ctx)
{
- unsigned char len[16];
- uint64_t r, plen;
+ size_t r;
- /*
- * Convert length to a vector of bytes -- we do this now rather
- * than later because the length will change after we pad.
- */
- be64enc_vect(len, ctx->count, 16);
-
- /* Add 1--128 bytes so that the resulting length is 112 mod 128 */
+ /* Figure out how many bytes we have buffered. */
r = (ctx->count[1] >> 3) & 0x7f;
- plen = (r < 112) ? (112 - r) : (240 - r);
- SHA512_Update(ctx, PAD, (size_t)plen);
- /* Add the terminating bit-count */
- SHA512_Update(ctx, len, 16);
+ /* Pad to 112 mod 128, transforming if we finish a block en route. */
+ if (r < 112) {
+ /* Pad to 112 mod 128. */
+ memcpy(&ctx->buf[r], PAD, 112 - r);
+ } else {
+ /* Finish the current block and mix. */
+ memcpy(&ctx->buf[r], PAD, 128 - r);
+ SHA512_Transform(ctx->state, ctx->buf);
+
+ /* The start of the final block is all zeroes. */
+ memset(&ctx->buf[0], 0, 112);
+ }
+
+ /* Add the terminating bit-count. */
+ be64enc_vect(&ctx->buf[112], ctx->count, 16);
+
+ /* Mix in the final block. */
+ SHA512_Transform(ctx->state, ctx->buf);
}
/* SHA-512 initialization. Begins a SHA-512 operation. */
@@ -324,6 +334,88 @@ SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH], SHA512_CTX *ctx)
memset(ctx, 0, sizeof(*ctx));
}
+/*** SHA-512t: *********************************************************/
+/*
+ * the SHA512t transforms are identical to SHA512 so reuse the existing function
+ */
+void
+SHA512_224_Init(SHA512_CTX * ctx)
+{
+
+ /* Zero bits processed so far */
+ ctx->count[0] = ctx->count[1] = 0;
+
+ /* Magic initialization constants */
+ ctx->state[0] = 0x8c3d37c819544da2ULL;
+ ctx->state[1] = 0x73e1996689dcd4d6ULL;
+ ctx->state[2] = 0x1dfab7ae32ff9c82ULL;
+ ctx->state[3] = 0x679dd514582f9fcfULL;
+ ctx->state[4] = 0x0f6d2b697bd44da8ULL;
+ ctx->state[5] = 0x77e36f7304c48942ULL;
+ ctx->state[6] = 0x3f9d85a86a1d36c8ULL;
+ ctx->state[7] = 0x1112e6ad91d692a1ULL;
+}
+
+void
+SHA512_224_Update(SHA512_CTX * ctx, const void *in, size_t len)
+{
+
+ SHA512_Update(ctx, in, len);
+}
+
+void
+SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH], SHA512_CTX * ctx)
+{
+
+ /* Add padding */
+ SHA512_Pad(ctx);
+
+ /* Write the hash */
+ be64enc_vect(digest, ctx->state, SHA512_224_DIGEST_LENGTH);
+
+ /* Clear the context state */
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+void
+SHA512_256_Init(SHA512_CTX * ctx)
+{
+
+ /* Zero bits processed so far */
+ ctx->count[0] = ctx->count[1] = 0;
+
+ /* Magic initialization constants */
+ ctx->state[0] = 0x22312194fc2bf72cULL;
+ ctx->state[1] = 0x9f555fa3c84c64c2ULL;
+ ctx->state[2] = 0x2393b86b6f53b151ULL;
+ ctx->state[3] = 0x963877195940eabdULL;
+ ctx->state[4] = 0x96283ee2a88effe3ULL;
+ ctx->state[5] = 0xbe5e1e2553863992ULL;
+ ctx->state[6] = 0x2b0199fc2c85b8aaULL;
+ ctx->state[7] = 0x0eb72ddc81c52ca2ULL;
+}
+
+void
+SHA512_256_Update(SHA512_CTX * ctx, const void *in, size_t len)
+{
+
+ SHA512_Update(ctx, in, len);
+}
+
+void
+SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH], SHA512_CTX * ctx)
+{
+
+ /* Add padding */
+ SHA512_Pad(ctx);
+
+ /* Write the hash */
+ be64enc_vect(digest, ctx->state, SHA512_256_DIGEST_LENGTH);
+
+ /* Clear the context state */
+ memset(ctx, 0, sizeof(*ctx));
+}
+
/*** SHA-384: *********************************************************/
/*
* the SHA384 and SHA512 transforms are identical, so SHA384 is skipped
@@ -388,6 +480,20 @@ __weak_reference(_libmd_SHA512_Final, SHA512_Final);
#undef SHA512_Transform
__weak_reference(_libmd_SHA512_Transform, SHA512_Transform);
+#undef SHA512_224_Init
+__weak_reference(_libmd_SHA512_224_Init, SHA512_224_Init);
+#undef SHA512_224_Update
+__weak_reference(_libmd_SHA512_224_Update, SHA512_224_Update);
+#undef SHA512_224_Final
+__weak_reference(_libmd_SHA512_224_Final, SHA512_224_Final);
+
+#undef SHA512_256_Init
+__weak_reference(_libmd_SHA512_256_Init, SHA512_256_Init);
+#undef SHA512_256_Update
+__weak_reference(_libmd_SHA512_256_Update, SHA512_256_Update);
+#undef SHA512_256_Final
+__weak_reference(_libmd_SHA512_256_Final, SHA512_256_Final);
+
#undef SHA384_Init
__weak_reference(_libmd_SHA384_Init, SHA384_Init);
#undef SHA384_Update
diff --git a/sys/crypto/sha2/sha512t.h b/sys/crypto/sha2/sha512t.h
new file mode 100644
index 0000000..3f0c921
--- /dev/null
+++ b/sys/crypto/sha2/sha512t.h
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SHA512T_H_
+#define _SHA512T_H_
+
+#include "sha512.h"
+
+#ifndef _KERNEL
+#include <sys/types.h>
+#endif
+
+#define SHA512_224_DIGEST_LENGTH 28
+#define SHA512_224_DIGEST_STRING_LENGTH (SHA512_224_DIGEST_LENGTH * 2 + 1)
+#define SHA512_256_DIGEST_LENGTH 32
+#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1)
+
+__BEGIN_DECLS
+
+/* Ensure libmd symbols do not clash with libcrypto */
+#ifndef SHA512_224_Init
+#define SHA512_224_Init _libmd_SHA512_224_Init
+#endif
+#ifndef SHA512_224_Update
+#define SHA512_224_Update _libmd_SHA512_224_Update
+#endif
+#ifndef SHA512_224_Final
+#define SHA512_224_Final _libmd_SHA512_224_Final
+#endif
+#ifndef SHA512_224_End
+#define SHA512_224_End _libmd_SHA512_224_End
+#endif
+#ifndef SHA512_224_File
+#define SHA512_224_File _libmd_SHA512_224_File
+#endif
+#ifndef SHA512_224_FileChunk
+#define SHA512_224_FileChunk _libmd_SHA512_224_FileChunk
+#endif
+#ifndef SHA512_224_Data
+#define SHA512_224_Data _libmd_SHA512_224_Data
+#endif
+
+#ifndef SHA512_224_Transform
+#define SHA512_224_Transform _libmd_SHA512_224_Transform
+#endif
+#ifndef SHA512_224_version
+#define SHA512_224_version _libmd_SHA512_224_version
+#endif
+
+#ifndef SHA512_256_Init
+#define SHA512_256_Init _libmd_SHA512_256_Init
+#endif
+#ifndef SHA512_256_Update
+#define SHA512_256_Update _libmd_SHA512_256_Update
+#endif
+#ifndef SHA512_256_Final
+#define SHA512_256_Final _libmd_SHA512_256_Final
+#endif
+#ifndef SHA512_256_End
+#define SHA512_256_End _libmd_SHA512_256_End
+#endif
+#ifndef SHA512_256_File
+#define SHA512_256_File _libmd_SHA512_256_File
+#endif
+#ifndef SHA512_256_FileChunk
+#define SHA512_256_FileChunk _libmd_SHA512_256_FileChunk
+#endif
+#ifndef SHA512_256_Data
+#define SHA512_256_Data _libmd_SHA512_256_Data
+#endif
+
+#ifndef SHA512_256_Transform
+#define SHA512_256_Transform _libmd_SHA512_256_Transform
+#endif
+#ifndef SHA512_256_version
+#define SHA512_256_version _libmd_SHA512_256_version
+#endif
+
+void SHA512_224_Init(SHA512_CTX *);
+void SHA512_224_Update(SHA512_CTX *, const void *, size_t);
+void SHA512_224_Final(unsigned char [static SHA512_224_DIGEST_LENGTH], SHA512_CTX *);
+#ifndef _KERNEL
+char *SHA512_224_End(SHA512_CTX *, char *);
+char *SHA512_224_Data(const void *, unsigned int, char *);
+char *SHA512_224_File(const char *, char *);
+char *SHA512_224_FileChunk(const char *, char *, off_t, off_t);
+#endif
+void SHA512_256_Init(SHA512_CTX *);
+void SHA512_256_Update(SHA512_CTX *, const void *, size_t);
+void SHA512_256_Final(unsigned char [static SHA512_256_DIGEST_LENGTH], SHA512_CTX *);
+#ifndef _KERNEL
+char *SHA512_256_End(SHA512_CTX *, char *);
+char *SHA512_256_Data(const void *, unsigned int, char *);
+char *SHA512_256_File(const char *, char *);
+char *SHA512_256_FileChunk(const char *, char *, off_t, off_t);
+#endif
+
+__END_DECLS
+
+#endif /* !_SHA512T_H_ */
diff --git a/sys/crypto/skein/amd64/skein_block_asm.s b/sys/crypto/skein/amd64/skein_block_asm.s
new file mode 100644
index 0000000..b2d0a83
--- /dev/null
+++ b/sys/crypto/skein/amd64/skein_block_asm.s
@@ -0,0 +1,1328 @@
+#
+#----------------------------------------------------------------
+# 64-bit x86 assembler code (gnu as) for Skein block functions
+#
+# Author: Doug Whiting, Hifn/Exar
+#
+# This code is released to the public domain.
+#----------------------------------------------------------------
+#
+ .text
+ .altmacro
+ .psize 0,128 #list file has no page boundaries
+#
+_MASK_ALL_ = (256+512+1024) #all three algorithm bits
+_MAX_FRAME_ = 240
+#
+#################
+.ifndef SKEIN_USE_ASM
+_USE_ASM_ = _MASK_ALL_
+.else
+_USE_ASM_ = SKEIN_USE_ASM
+.endif
+#################
+.ifndef SKEIN_LOOP #configure loop unrolling
+_SKEIN_LOOP = 2 #default is fully unrolled for 256/512, twice for 1024
+.else
+_SKEIN_LOOP = SKEIN_LOOP
+ .irp _NN_,%_SKEIN_LOOP #only display loop unrolling if default changed on command line
+.print "+++ SKEIN_LOOP = \_NN_"
+ .endr
+.endif
+# the unroll counts (0 --> fully unrolled)
+SKEIN_UNROLL_256 = (_SKEIN_LOOP / 100) % 10
+SKEIN_UNROLL_512 = (_SKEIN_LOOP / 10) % 10
+SKEIN_UNROLL_1024 = (_SKEIN_LOOP ) % 10
+#
+SKEIN_ASM_UNROLL = 0
+ .irp _NN_,256,512,1024
+ .if (SKEIN_UNROLL_\_NN_) == 0
+SKEIN_ASM_UNROLL = SKEIN_ASM_UNROLL + \_NN_
+ .endif
+ .endr
+#################
+#
+.ifndef SKEIN_ROUNDS
+ROUNDS_256 = 72
+ROUNDS_512 = 72
+ROUNDS_1024 = 80
+.else
+ROUNDS_256 = 8*((((SKEIN_ROUNDS / 100) + 5) % 10) + 5)
+ROUNDS_512 = 8*((((SKEIN_ROUNDS / 10) + 5) % 10) + 5)
+ROUNDS_1024 = 8*((((SKEIN_ROUNDS ) + 5) % 10) + 5)
+# only display rounds if default size is changed on command line
+.irp _NN_,256,512,1024
+ .if _USE_ASM_ && \_NN_
+ .irp _RR_,%(ROUNDS_\_NN_)
+ .if _NN_ < 1024
+.print "+++ SKEIN_ROUNDS_\_NN_ = \_RR_"
+ .else
+.print "+++ SKEIN_ROUNDS_\_NN_ = \_RR_"
+ .endif
+ .endr
+ .endif
+.endr
+.endif
+#################
+#
+.ifdef SKEIN_CODE_SIZE
+_SKEIN_CODE_SIZE = (1)
+.else
+.ifdef SKEIN_PERF #use code size if SKEIN_PERF is defined
+_SKEIN_CODE_SIZE = (1)
+.else
+_SKEIN_CODE_SIZE = (0)
+.endif
+.endif
+#
+#################
+#
+.ifndef SKEIN_DEBUG
+_SKEIN_DEBUG = 0
+.else
+_SKEIN_DEBUG = 1
+.endif
+#################
+#
+# define offsets of fields in hash context structure
+#
+HASH_BITS = 0 #bits of hash output
+BCNT = 8 + HASH_BITS #number of bytes in BUFFER[]
+TWEAK = 8 + BCNT #tweak values[0..1]
+X_VARS = 16 + TWEAK #chaining vars
+#
+#(Note: buffer[] in context structure is NOT needed here :-)
+#
+KW_PARITY = 0x1BD11BDAA9FC1A22 #overall parity of key schedule words
+FIRST_MASK = ~ (1 << 6)
+FIRST_MASK64= ~ (1 << 62)
+#
+# rotation constants for Skein
+#
+RC_256_0_0 = 14
+RC_256_0_1 = 16
+
+RC_256_1_0 = 52
+RC_256_1_1 = 57
+
+RC_256_2_0 = 23
+RC_256_2_1 = 40
+
+RC_256_3_0 = 5
+RC_256_3_1 = 37
+
+RC_256_4_0 = 25
+RC_256_4_1 = 33
+
+RC_256_5_0 = 46
+RC_256_5_1 = 12
+
+RC_256_6_0 = 58
+RC_256_6_1 = 22
+
+RC_256_7_0 = 32
+RC_256_7_1 = 32
+
+RC_512_0_0 = 46
+RC_512_0_1 = 36
+RC_512_0_2 = 19
+RC_512_0_3 = 37
+
+RC_512_1_0 = 33
+RC_512_1_1 = 27
+RC_512_1_2 = 14
+RC_512_1_3 = 42
+
+RC_512_2_0 = 17
+RC_512_2_1 = 49
+RC_512_2_2 = 36
+RC_512_2_3 = 39
+
+RC_512_3_0 = 44
+RC_512_3_1 = 9
+RC_512_3_2 = 54
+RC_512_3_3 = 56
+
+RC_512_4_0 = 39
+RC_512_4_1 = 30
+RC_512_4_2 = 34
+RC_512_4_3 = 24
+
+RC_512_5_0 = 13
+RC_512_5_1 = 50
+RC_512_5_2 = 10
+RC_512_5_3 = 17
+
+RC_512_6_0 = 25
+RC_512_6_1 = 29
+RC_512_6_2 = 39
+RC_512_6_3 = 43
+
+RC_512_7_0 = 8
+RC_512_7_1 = 35
+RC_512_7_2 = 56
+RC_512_7_3 = 22
+
+RC_1024_0_0 = 24
+RC_1024_0_1 = 13
+RC_1024_0_2 = 8
+RC_1024_0_3 = 47
+RC_1024_0_4 = 8
+RC_1024_0_5 = 17
+RC_1024_0_6 = 22
+RC_1024_0_7 = 37
+
+RC_1024_1_0 = 38
+RC_1024_1_1 = 19
+RC_1024_1_2 = 10
+RC_1024_1_3 = 55
+RC_1024_1_4 = 49
+RC_1024_1_5 = 18
+RC_1024_1_6 = 23
+RC_1024_1_7 = 52
+
+RC_1024_2_0 = 33
+RC_1024_2_1 = 4
+RC_1024_2_2 = 51
+RC_1024_2_3 = 13
+RC_1024_2_4 = 34
+RC_1024_2_5 = 41
+RC_1024_2_6 = 59
+RC_1024_2_7 = 17
+
+RC_1024_3_0 = 5
+RC_1024_3_1 = 20
+RC_1024_3_2 = 48
+RC_1024_3_3 = 41
+RC_1024_3_4 = 47
+RC_1024_3_5 = 28
+RC_1024_3_6 = 16
+RC_1024_3_7 = 25
+
+RC_1024_4_0 = 41
+RC_1024_4_1 = 9
+RC_1024_4_2 = 37
+RC_1024_4_3 = 31
+RC_1024_4_4 = 12
+RC_1024_4_5 = 47
+RC_1024_4_6 = 44
+RC_1024_4_7 = 30
+
+RC_1024_5_0 = 16
+RC_1024_5_1 = 34
+RC_1024_5_2 = 56
+RC_1024_5_3 = 51
+RC_1024_5_4 = 4
+RC_1024_5_5 = 53
+RC_1024_5_6 = 42
+RC_1024_5_7 = 41
+
+RC_1024_6_0 = 31
+RC_1024_6_1 = 44
+RC_1024_6_2 = 47
+RC_1024_6_3 = 46
+RC_1024_6_4 = 19
+RC_1024_6_5 = 42
+RC_1024_6_6 = 44
+RC_1024_6_7 = 25
+
+RC_1024_7_0 = 9
+RC_1024_7_1 = 48
+RC_1024_7_2 = 35
+RC_1024_7_3 = 52
+RC_1024_7_4 = 23
+RC_1024_7_5 = 31
+RC_1024_7_6 = 37
+RC_1024_7_7 = 20
+#
+# Input: reg
+# Output: <reg> <<< RC_BlkSize_roundNum_mixNum, BlkSize=256/512/1024
+#
+.macro RotL64 reg,BLK_SIZE,ROUND_NUM,MIX_NUM
+_RCNT_ = RC_\BLK_SIZE&_\ROUND_NUM&_\MIX_NUM
+ .if _RCNT_ #is there anything to do?
+ rolq $_RCNT_,%\reg
+ .endif
+.endm
+#
+#----------------------------------------------------------------
+#
+# MACROS: define local vars and configure stack
+#
+#----------------------------------------------------------------
+# declare allocated space on the stack
+.macro StackVar localName,localSize
+\localName = _STK_OFFS_
+_STK_OFFS_ = _STK_OFFS_+(\localSize)
+.endm #StackVar
+#
+#----------------------------------------------------------------
+#
+# MACRO: Configure stack frame, allocate local vars
+#
+.macro Setup_Stack BLK_BITS,KS_CNT,debugCnt
+ WCNT = (\BLK_BITS)/64
+#
+_PushCnt_ = 0 #save nonvolatile regs on stack
+ .irp _reg_,rbp,rbx,r12,r13,r14,r15
+ pushq %\_reg_
+_PushCnt_ = _PushCnt_ + 1 #track count to keep alignment
+ .endr
+#
+_STK_OFFS_ = 0 #starting offset from rsp
+ #---- local variables #<-- rsp
+ StackVar X_stk ,8*(WCNT) #local context vars
+ StackVar ksTwk ,8*3 #key schedule: tweak words
+ StackVar ksKey ,8*(WCNT)+8 #key schedule: key words
+ .if (SKEIN_ASM_UNROLL && (\BLK_BITS)) == 0
+ StackVar ksRot ,16*(\KS_CNT) #leave space for "rotation" to happen
+ .endif
+ StackVar Wcopy ,8*(WCNT) #copy of input block
+ .if _SKEIN_DEBUG
+ .if \debugCnt + 0 #temp location for debug X[] info
+ StackVar xDebug_\BLK_BITS ,8*(\debugCnt)
+ .endif
+ .endif
+ .if ((8*_PushCnt_ + _STK_OFFS_) % 8) == 0
+ StackVar align16,8 #keep 16-byte aligned (adjust for retAddr?)
+tmpStk_\BLK_BITS = align16 #use this
+ .endif
+ #---- saved caller parameters (from regs rdi, rsi, rdx, rcx)
+ StackVar ctxPtr ,8 #context ptr
+ StackVar blkPtr ,8 #pointer to block data
+ StackVar blkCnt ,8 #number of full blocks to process
+ StackVar bitAdd ,8 #bit count to add to tweak
+LOCAL_SIZE = _STK_OFFS_ #size of "local" vars
+ #----
+ StackVar savRegs,8*_PushCnt_ #saved registers
+ StackVar retAddr,8 #return address
+ #---- caller's stack frame (aligned mod 16)
+#
+# set up the stack frame pointer (rbp)
+#
+FRAME_OFFS = ksTwk + 128 #allow short (negative) offset to ksTwk, kwKey
+ .if FRAME_OFFS > _STK_OFFS_ #keep rbp in the "locals" range
+FRAME_OFFS = _STK_OFFS_
+ .endif
+F_O = -FRAME_OFFS
+#
+ #put some useful defines in the .lst file (for grep)
+__STK_LCL_SIZE_\BLK_BITS = LOCAL_SIZE
+__STK_TOT_SIZE_\BLK_BITS = _STK_OFFS_
+__STK_FRM_OFFS_\BLK_BITS = FRAME_OFFS
+#
+# Notes on stack frame setup:
+# * the most frequently used variable is X_stk[], based at [rsp+0]
+# * the next most used is the key schedule arrays, ksKey and ksTwk
+# so rbp is "centered" there, allowing short offsets to the key
+# schedule even in 1024-bit Skein case
+# * the Wcopy variables are infrequently accessed, but they have long
+# offsets from both rsp and rbp only in the 1024-bit case.
+# * all other local vars and calling parameters can be accessed
+# with short offsets, except in the 1024-bit case
+#
+ subq $LOCAL_SIZE,%rsp #make room for the locals
+ leaq FRAME_OFFS(%rsp),%rbp #maximize use of short offsets
+ movq %rdi, ctxPtr+F_O(%rbp) #save caller's parameters on the stack
+ movq %rsi, blkPtr+F_O(%rbp)
+ movq %rdx, blkCnt+F_O(%rbp)
+ movq %rcx, bitAdd+F_O(%rbp)
+#
+.endm #Setup_Stack
+#
+#----------------------------------------------------------------
+#
+.macro Reset_Stack
+ addq $LOCAL_SIZE,%rsp #get rid of locals (wipe??)
+ .irp _reg_,r15,r14,r13,r12,rbx,rbp
+ popq %\_reg_ #restore caller's regs
+_PushCnt_ = _PushCnt_ - 1
+ .endr
+ .if _PushCnt_
+ .error "Mismatched push/pops?"
+ .endif
+.endm # Reset_Stack
+#
+#----------------------------------------------------------------
+# macros to help debug internals
+#
+.if _SKEIN_DEBUG
+ .extern Skein_Show_Block #calls to C routines
+ .extern Skein_Show_Round
+#
+SKEIN_RND_SPECIAL = 1000
+SKEIN_RND_KEY_INITIAL = SKEIN_RND_SPECIAL+0
+SKEIN_RND_KEY_INJECT = SKEIN_RND_SPECIAL+1
+SKEIN_RND_FEED_FWD = SKEIN_RND_SPECIAL+2
+#
+.macro Skein_Debug_Block BLK_BITS
+#
+#void Skein_Show_Block(uint_t bits,const Skein_Ctxt_Hdr_t *h,const u64b_t *X,
+# const u08b_t *blkPtr, const u64b_t *wPtr,
+# const u64b_t *ksPtr,const u64b_t *tsPtr)
+#
+_NN_ = 0
+ .irp _reg_,rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11
+ pushq %\_reg_ #save all volatile regs on tack before the call
+_NN_ = _NN_ + 1
+ .endr
+ # get and push call parameters
+ movq $\BLK_BITS ,%rdi #bits
+ movq ctxPtr+F_O(%rbp),%rsi #h (pointer)
+ leaq X_VARS (%rsi),%rdx #X (pointer)
+ movq blkPtr+F_O(%rbp),%rcx #blkPtr
+ leaq Wcopy +F_O(%rbp),%r8 #wPtr
+ leaq ksKey +F_O(%rbp),%r9 #key pointer
+ leaq ksTwk +F_O(%rbp),%rax #tweak pointer
+ pushq %rax # (pass on the stack)
+ call Skein_Show_Block #call external debug handler
+ addq $8*1,%rsp #discard parameters on stack
+ .if (_NN_ % 2 ) == 0 #check stack alignment
+ .error "Stack misalignment problem in Skein_Debug_Block_\_BLK_BITS"
+ .endif
+ .irp _reg_,r11,r10,r9,r8,rdi,rsi,rdx,rcx,rax
+ popq %\_reg_ #restore regs
+_NN_ = _NN_ - 1
+ .endr
+ .if _NN_
+ .error "Push/pop mismatch problem in Skein_Debug_Block_\_BLK_BITS"
+ .endif
+.endm # Skein_Debug_Block
+#
+# the macro to "call" to debug a round
+#
+.macro Skein_Debug_Round BLK_BITS,R,RDI_OFFS,afterOp
+ # call the appropriate (local) debug "function"
+ pushq %rdx #save rdx, so we can use it for round "number"
+ .if (SKEIN_ASM_UNROLL && \BLK_BITS) || (\R >= SKEIN_RND_SPECIAL)
+ movq $\R,%rdx
+ .else #compute round number using edi
+_rOffs_ = \RDI_OFFS + 0
+ .if \BLK_BITS == 1024
+ movq rIdx_offs+8(%rsp),%rdx #get rIdx off the stack (adjust for pushq rdx above)
+ leaq 1+(((\R)-1) && 3)+_rOffs_(,%rdx,4),%rdx
+ .else
+ leaq 1+(((\R)-1) && 3)+_rOffs_(,%rdi,4),%rdx
+ .endif
+ .endif
+ call Skein_Debug_Round_\BLK_BITS
+ popq %rdx #restore origianl rdx value
+#
+ afterOp
+.endm # Skein_Debug_Round
+.else #------- _SKEIN_DEBUG (dummy macros if debug not enabled)
+.macro Skein_Debug_Block BLK_BITS
+.endm
+#
+.macro Skein_Debug_Round BLK_BITS,R,RDI_OFFS,afterOp
+.endm
+#
+.endif # _SKEIN_DEBUG
+#
+#----------------------------------------------------------------
+#
+.macro addReg dstReg,srcReg_A,srcReg_B,useAddOp,immOffs
+ .if \immOffs + 0
+ leaq \immOffs(%\srcReg_A\srcReg_B,%\dstReg),%\dstReg
+ .elseif ((\useAddOp + 0) == 0)
+ .ifndef ASM_NO_LEA #lea seems to be faster on Core 2 Duo CPUs!
+ leaq (%\srcReg_A\srcReg_B,%\dstReg),%\dstReg
+ .else
+ addq %\srcReg_A\srcReg_B,%\dstReg
+ .endif
+ .else
+ addq %\srcReg_A\srcReg_B,%\dstReg
+ .endif
+.endm
+
+# keep Intel-style ordering here, to match addReg
+.macro xorReg dstReg,srcReg_A,srcReg_B
+ xorq %\srcReg_A\srcReg_B,%\dstReg
+.endm
+#
+#----------------------------------------------------------------
+#
+.macro C_label lName
+ \lName: #use both "genders" to work across linkage conventions
+_\lName:
+ .global \lName
+ .global _\lName
+.endm
+#
+#=================================== Skein_256 =============================================
+#
+.if _USE_ASM_ & 256
+#
+# void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t bitcntAdd)#
+#
+#################
+#
+# code
+#
+C_label Skein_256_Process_Block
+ Setup_Stack 256,((ROUNDS_256/8)+1)
+ movq TWEAK+8(%rdi),%r14
+ jmp Skein_256_block_loop
+ .p2align 4
+ # main hash loop for Skein_256
+Skein_256_block_loop:
+ #
+ # general register usage:
+ # RAX..RDX = X0..X3
+ # R08..R12 = ks[0..4]
+ # R13..R15 = ts[0..2]
+ # RSP, RBP = stack/frame pointers
+ # RDI = round counter or context pointer
+ # RSI = temp
+ #
+ movq TWEAK+0(%rdi) ,%r13
+ addq bitAdd+F_O(%rbp) ,%r13 #computed updated tweak value T0
+ movq %r14 ,%r15
+ xorq %r13 ,%r15 #now %r13.%r15 is set as the tweak
+
+ movq $KW_PARITY ,%r12
+ movq X_VARS+ 0(%rdi),%r8
+ movq X_VARS+ 8(%rdi),%r9
+ movq X_VARS+16(%rdi),%r10
+ movq X_VARS+24(%rdi),%r11
+ movq %r13,TWEAK+0(%rdi) #save updated tweak value ctx->h.T[0]
+ xorq %r8 ,%r12 #start accumulating overall parity
+
+ movq blkPtr +F_O(%rbp) ,%rsi #esi --> input block
+ xorq %r9 ,%r12
+ movq 0(%rsi) ,%rax #get X[0..3]
+ xorq %r10 ,%r12
+ movq 8(%rsi) ,%rbx
+ xorq %r11 ,%r12
+ movq 16(%rsi) ,%rcx
+ movq 24(%rsi) ,%rdx
+
+ movq %rax,Wcopy+ 0+F_O(%rbp) #save copy of input block
+ movq %rbx,Wcopy+ 8+F_O(%rbp)
+ movq %rcx,Wcopy+16+F_O(%rbp)
+ movq %rdx,Wcopy+24+F_O(%rbp)
+
+ addq %r8 ,%rax #initial key injection
+ addq %r9 ,%rbx
+ addq %r10,%rcx
+ addq %r11,%rdx
+ addq %r13,%rbx
+ addq %r14,%rcx
+
+.if _SKEIN_DEBUG
+ movq %r14,TWEAK+ 8(%rdi) #save updated tweak T[1] (start bit cleared?)
+ movq %r8 ,ksKey+ 0+F_O(%rbp) #save key schedule on stack for Skein_Debug_Block
+ movq %r9 ,ksKey+ 8+F_O(%rbp)
+ movq %r10,ksKey+16+F_O(%rbp)
+ movq %r11,ksKey+24+F_O(%rbp)
+ movq %r12,ksKey+32+F_O(%rbp)
+
+ movq %r13,ksTwk+ 0+F_O(%rbp)
+ movq %r14,ksTwk+ 8+F_O(%rbp)
+ movq %r15,ksTwk+16+F_O(%rbp)
+
+ movq %rax,X_stk + 0(%rsp) #save X[] on stack for Skein_Debug_Block
+ movq %rbx,X_stk + 8(%rsp)
+ movq %rcx,X_stk +16(%rsp)
+ movq %rdx,X_stk +24(%rsp)
+
+ Skein_Debug_Block 256 #debug dump
+ Skein_Debug_Round 256,SKEIN_RND_KEY_INITIAL
+.endif
+#
+.if ((SKEIN_ASM_UNROLL & 256) == 0)
+ movq %r8 ,ksKey+40+F_O(%rbp) #save key schedule on stack for looping code
+ movq %r9 ,ksKey+ 8+F_O(%rbp)
+ movq %r10,ksKey+16+F_O(%rbp)
+ movq %r11,ksKey+24+F_O(%rbp)
+ movq %r12,ksKey+32+F_O(%rbp)
+
+ movq %r13,ksTwk+24+F_O(%rbp)
+ movq %r14,ksTwk+ 8+F_O(%rbp)
+ movq %r15,ksTwk+16+F_O(%rbp)
+.endif
+ addq $WCNT*8,%rsi #skip the block
+ movq %rsi,blkPtr +F_O(%rbp) #update block pointer
+ #
+ # now the key schedule is computed. Start the rounds
+ #
+.if SKEIN_ASM_UNROLL & 256
+_UNROLL_CNT = ROUNDS_256/8
+.else
+_UNROLL_CNT = SKEIN_UNROLL_256
+ .if ((ROUNDS_256/8) % _UNROLL_CNT)
+ .error "Invalid SKEIN_UNROLL_256"
+ .endif
+ xorq %rdi,%rdi #rdi = iteration count
+Skein_256_round_loop:
+.endif
+_Rbase_ = 0
+.rept _UNROLL_CNT*2
+ # all X and ks vars in regs # (ops to "rotate" ks vars, via mem, if not unrolled)
+ # round 4*_RBase_ + 0
+ addReg rax, rbx
+ RotL64 rbx, 256,%((4*_Rbase_+0) % 8),0
+ addReg rcx, rdx
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ movq ksKey+8*1+F_O(%rbp,%rdi,8),%r8
+ .endif
+ xorReg rbx, rax
+ RotL64 rdx, 256,%((4*_Rbase_+0) % 8),1
+ xorReg rdx, rcx
+ .if SKEIN_ASM_UNROLL & 256
+ .irp _r0_,%( 8+(_Rbase_+3) % 5)
+ .irp _r1_,%(13+(_Rbase_+2) % 3)
+ leaq (%r\_r0_,%r\_r1_),%rdi #precompute key injection value for %rcx
+ .endr
+ .endr
+ .endif
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ movq ksTwk+8*1+F_O(%rbp,%rdi,8),%r13
+ .endif
+ Skein_Debug_Round 256,%(4*_Rbase_+1)
+
+ # round 4*_Rbase_ + 1
+ addReg rax, rdx
+ RotL64 rdx, 256,%((4*_Rbase_+1) % 8),0
+ xorReg rdx, rax
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ movq ksKey+8*2+F_O(%rbp,%rdi,8),%r9
+ .endif
+ addReg rcx, rbx
+ RotL64 rbx, 256,%((4*_Rbase_+1) % 8),1
+ xorReg rbx, rcx
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ movq ksKey+8*4+F_O(%rbp,%rdi,8),%r11
+ .endif
+ Skein_Debug_Round 256,%(4*_Rbase_+2)
+ .if SKEIN_ASM_UNROLL & 256
+ .irp _r0_,%( 8+(_Rbase_+2) % 5)
+ .irp _r1_,%(13+(_Rbase_+1) % 3)
+ leaq (%r\_r0_,%r\_r1_),%rsi #precompute key injection value for %rbx
+ .endr
+ .endr
+ .endif
+ # round 4*_Rbase_ + 2
+ addReg rax, rbx
+ RotL64 rbx, 256,%((4*_Rbase_+2) % 8),0
+ addReg rcx, rdx
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ movq ksKey+8*3+F_O(%rbp,%rdi,8),%r10
+ .endif
+ xorReg rbx, rax
+ RotL64 rdx, 256,%((4*_Rbase_+2) % 8),1
+ xorReg rdx, rcx
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ movq %r8,ksKey+8*6+F_O(%rbp,%rdi,8) #"rotate" the key
+ leaq 1(%r11,%rdi),%r11 #precompute key + tweak
+ .endif
+ Skein_Debug_Round 256,%(4*_Rbase_+3)
+ # round 4*_Rbase_ + 3
+ addReg rax, rdx
+ RotL64 rdx, 256,%((4*_Rbase_+3) % 8),0
+ addReg rcx, rbx
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ addq ksTwk+8*2+F_O(%rbp,%rdi,8),%r10 #precompute key + tweak
+ movq %r13,ksTwk+8*4+F_O(%rbp,%rdi,8) #"rotate" the tweak
+ .endif
+ xorReg rdx, rax
+ RotL64 rbx, 256,%((4*_Rbase_+3) % 8),1
+ xorReg rbx, rcx
+ Skein_Debug_Round 256,%(4*_Rbase_+4)
+ .if (SKEIN_ASM_UNROLL & 256) == 0
+ addReg r9 ,r13 #precompute key+tweak
+ .endif
+ #inject key schedule words
+_Rbase_ = _Rbase_+1
+ .if SKEIN_ASM_UNROLL & 256
+ addReg rax,r,%(8+((_Rbase_+0) % 5))
+ addReg rbx,rsi
+ addReg rcx,rdi
+ addReg rdx,r,%(8+((_Rbase_+3) % 5)),,_Rbase_
+ .else
+ incq %rdi
+ addReg rax,r8
+ addReg rcx,r10
+ addReg rbx,r9
+ addReg rdx,r11
+ .endif
+ Skein_Debug_Round 256,SKEIN_RND_KEY_INJECT
+.endr #rept _UNROLL_CNT
+#
+.if (SKEIN_ASM_UNROLL & 256) == 0
+ cmpq $2*(ROUNDS_256/8),%rdi
+ jb Skein_256_round_loop
+.endif # (SKEIN_ASM_UNROLL & 256) == 0
+ movq ctxPtr +F_O(%rbp),%rdi #restore rdi --> context
+
+ #----------------------------
+ # feedforward: ctx->X[i] = X[i] ^ w[i], {i=0..3}
+ movq $FIRST_MASK64 ,%r14
+ xorq Wcopy + 0+F_O (%rbp),%rax
+ xorq Wcopy + 8+F_O (%rbp),%rbx
+ xorq Wcopy +16+F_O (%rbp),%rcx
+ xorq Wcopy +24+F_O (%rbp),%rdx
+ andq TWEAK + 8 (%rdi),%r14
+ movq %rax,X_VARS+ 0(%rdi) #store final result
+ movq %rbx,X_VARS+ 8(%rdi)
+ movq %rcx,X_VARS+16(%rdi)
+ movq %rdx,X_VARS+24(%rdi)
+
+ Skein_Debug_Round 256,SKEIN_RND_FEED_FWD
+
+ # go back for more blocks, if needed
+ decq blkCnt+F_O(%rbp)
+ jnz Skein_256_block_loop
+ movq %r14,TWEAK + 8(%rdi)
+ Reset_Stack
+ ret
+Skein_256_Process_Block_End:
+
+ .if _SKEIN_DEBUG
+Skein_Debug_Round_256: #here with rdx == round "number" from macro
+ pushq %rsi #save two regs for BLK_BITS-specific parms
+ pushq %rdi
+ movq 24(%rsp),%rdi #get back original rdx (pushed on stack in macro call) to rdi
+ movq %rax,X_stk+ 0+F_O(%rbp) #save X[] state on stack so debug routines can access it
+ movq %rbx,X_stk+ 8+F_O(%rbp) #(use FP_ since rsp has changed!)
+ movq %rcx,X_stk+16+F_O(%rbp)
+ movq %rdi,X_stk+24+F_O(%rbp)
+
+ movq ctxPtr+F_O(%rbp),%rsi #ctx_hdr_ptr
+ movq $256,%rdi #now <rdi,rsi,rdx> are set for the call
+ jmp Skein_Debug_Round_Common
+ .endif
+#
+.if _SKEIN_CODE_SIZE
+C_label Skein_256_Process_Block_CodeSize
+ movq $(Skein_256_Process_Block_End-Skein_256_Process_Block),%rax
+ ret
+#
+C_label Skein_256_Unroll_Cnt
+ .if _UNROLL_CNT <> ROUNDS_256/8
+ movq $_UNROLL_CNT,%rax
+ .else
+ xorq %rax,%rax
+ .endif
+ ret
+.endif
+#
+.endif #_USE_ASM_ & 256
+#
+#=================================== Skein_512 =============================================
+#
+.if _USE_ASM_ & 512
+#
+# void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t bitcntAdd)
+#
+# X[i] == %r[8+i] #register assignments for X[] values during rounds (i=0..7)
+#
+#################
+# MACRO: one round for 512-bit blocks
+#
+.macro R_512_OneRound rn0,rn1,rn2,rn3,rn4,rn5,rn6,rn7,_Rn_,op1,op2,op3,op4
+#
+ addReg r\rn0, r\rn1
+ RotL64 r\rn1, 512,%((_Rn_) % 8),0
+ xorReg r\rn1, r\rn0
+ op1
+ addReg r\rn2, r\rn3
+ RotL64 r\rn3, 512,%((_Rn_) % 8),1
+ xorReg r\rn3, r\rn2
+ op2
+ addReg r\rn4, r\rn5
+ RotL64 r\rn5, 512,%((_Rn_) % 8),2
+ xorReg r\rn5, r\rn4
+ op3
+ addReg r\rn6, r\rn7
+ RotL64 r\rn7, 512,%((_Rn_) % 8),3
+ xorReg r\rn7, r\rn6
+ op4
+ Skein_Debug_Round 512,%(_Rn_+1),-4
+#
+.endm #R_512_OneRound
+#
+#################
+# MACRO: eight rounds for 512-bit blocks
+#
+.macro R_512_FourRounds _RR_ #RR = base round number (0 % 8)
+ .if (SKEIN_ASM_UNROLL && 512)
+ # here for fully unrolled case.
+ _II_ = ((_RR_)/4) + 1 #key injection counter
+ R_512_OneRound 8, 9,10,11,12,13,14,15,%((_RR_)+0),<movq ksKey+8*(((_II_)+3) % 9)+F_O(%rbp),%rax>,,<movq ksKey+8*(((_II_)+4) % 9)+F_O(%rbp),%rbx>
+ R_512_OneRound 10, 9,12,15,14,13, 8,11,%((_RR_)+1),<movq ksKey+8*(((_II_)+5) % 9)+F_O(%rbp),%rcx>,,<movq ksKey+8*(((_II_)+6) % 9)+F_O(%rbp),%rdx>
+ R_512_OneRound 12, 9,14,11, 8,13,10,15,%((_RR_)+2),<movq ksKey+8*(((_II_)+7) % 9)+F_O(%rbp),%rsi>,,<addq ksTwk+8*(((_II_)+0) % 3)+F_O(%rbp),%rcx>
+ R_512_OneRound 14, 9, 8,15,10,13,12,11,%((_RR_)+3),<addq ksTwk+8*(((_II_)+1) % 3)+F_O(%rbp),%rdx>,
+ # inject the key schedule
+ addq ksKey+8*(((_II_)+0)%9)+F_O(%rbp),%r8
+ addReg r11, rax
+ addq ksKey+8*(((_II_)+1)%9)+F_O(%rbp),%r9
+ addReg r12, rbx
+ addq ksKey+8*(((_II_)+2)%9)+F_O(%rbp),%r10
+ addReg r13, rcx
+ addReg r14, rdx
+ addReg r15, rsi,,,(_II_)
+ .else
+ # here for looping case #"rotate" key/tweak schedule (move up on stack)
+ incq %rdi #bump key injection counter
+ R_512_OneRound 8, 9,10,11,12,13,14,15,%((_RR_)+0),<movq ksKey+8*6+F_O(%rbp,%rdi,8),%rdx>,<movq ksTwk-8*1+F_O(%rbp,%rdi,8),%rax>,<movq ksKey-8*1+F_O(%rbp,%rdi,8),%rsi>
+ R_512_OneRound 10, 9,12,15,14,13, 8,11,%((_RR_)+1),<movq ksKey+8*5+F_O(%rbp,%rdi,8),%rcx>,<movq %rax,ksTwk+8*2+F_O(%rbp,%rdi,8) >,<movq %rsi,ksKey+8*8+F_O(%rbp,%rdi,8)>
+ R_512_OneRound 12, 9,14,11, 8,13,10,15,%((_RR_)+2),<movq ksKey+8*4+F_O(%rbp,%rdi,8),%rbx>,<addq ksTwk+8*1+F_O(%rbp,%rdi,8),%rdx>,<movq ksKey+8*7+F_O(%rbp,%rdi,8),%rsi>
+ R_512_OneRound 14, 9, 8,15,10,13,12,11,%((_RR_)+3),<movq ksKey+8*3+F_O(%rbp,%rdi,8),%rax>,<addq ksTwk+8*0+F_O(%rbp,%rdi,8),%rcx>
+ # inject the key schedule
+ addq ksKey+8*0+F_O(%rbp,%rdi,8),%r8
+ addReg r11, rax
+ addReg r12, rbx
+ addq ksKey+8*1+F_O(%rbp,%rdi,8),%r9
+ addReg r13, rcx
+ addReg r14, rdx
+ addq ksKey+8*2+F_O(%rbp,%rdi,8),%r10
+ addReg r15, rsi
+ addReg r15, rdi #inject the round number
+ .endif
+
+ #show the result of the key injection
+ Skein_Debug_Round 512,SKEIN_RND_KEY_INJECT
+.endm #R_512_EightRounds
+#
+#################
+# instantiated code
+#
+C_label Skein_512_Process_Block
+ Setup_Stack 512,ROUNDS_512/8
+ movq TWEAK+ 8(%rdi),%rbx
+ jmp Skein_512_block_loop
+ .p2align 4
+ # main hash loop for Skein_512
+Skein_512_block_loop:
+ # general register usage:
+ # RAX..RDX = temps for key schedule pre-loads
+ # R8 ..R15 = X0..X7
+ # RSP, RBP = stack/frame pointers
+ # RDI = round counter or context pointer
+ # RSI = temp
+ #
+ movq TWEAK + 0(%rdi),%rax
+ addq bitAdd+F_O(%rbp),%rax #computed updated tweak value T0
+ movq %rbx,%rcx
+ xorq %rax,%rcx #%rax/%rbx/%rcx = tweak schedule
+ movq %rax,TWEAK+ 0 (%rdi) #save updated tweak value ctx->h.T[0]
+ movq %rax,ksTwk+ 0+F_O(%rbp)
+ movq $KW_PARITY,%rdx
+ movq blkPtr +F_O(%rbp),%rsi #%rsi --> input block
+ movq %rbx,ksTwk+ 8+F_O(%rbp)
+ movq %rcx,ksTwk+16+F_O(%rbp)
+ .irp _Rn_,8,9,10,11,12,13,14,15
+ movq X_VARS+8*(_Rn_-8)(%rdi),%r\_Rn_
+ xorq %r\_Rn_,%rdx #compute overall parity
+ movq %r\_Rn_,ksKey+8*(_Rn_-8)+F_O(%rbp)
+ .endr #load state into %r8 ..%r15, compute parity
+ movq %rdx,ksKey+8*(8)+F_O(%rbp)#save key schedule parity
+
+ addReg r13,rax #precompute key injection for tweak
+ addReg r14, rbx
+.if _SKEIN_DEBUG
+ movq %rbx,TWEAK+ 8(%rdi) #save updated tweak value ctx->h.T[1] for Skein_Debug_Block below
+.endif
+ movq 0(%rsi),%rax #load input block
+ movq 8(%rsi),%rbx
+ movq 16(%rsi),%rcx
+ movq 24(%rsi),%rdx
+ addReg r8 , rax #do initial key injection
+ addReg r9 , rbx
+ movq %rax,Wcopy+ 0+F_O(%rbp) #keep local copy for feedforward
+ movq %rbx,Wcopy+ 8+F_O(%rbp)
+ addReg r10, rcx
+ addReg r11, rdx
+ movq %rcx,Wcopy+16+F_O(%rbp)
+ movq %rdx,Wcopy+24+F_O(%rbp)
+
+ movq 32(%rsi),%rax
+ movq 40(%rsi),%rbx
+ movq 48(%rsi),%rcx
+ movq 56(%rsi),%rdx
+ addReg r12, rax
+ addReg r13, rbx
+ addReg r14, rcx
+ addReg r15, rdx
+ movq %rax,Wcopy+32+F_O(%rbp)
+ movq %rbx,Wcopy+40+F_O(%rbp)
+ movq %rcx,Wcopy+48+F_O(%rbp)
+ movq %rdx,Wcopy+56+F_O(%rbp)
+
+.if _SKEIN_DEBUG
+ .irp _Rn_,8,9,10,11,12,13,14,15 #save values on stack for debug output
+ movq %r\_Rn_,X_stk+8*(_Rn_-8)(%rsp)
+ .endr
+
+ Skein_Debug_Block 512 #debug dump
+ Skein_Debug_Round 512,SKEIN_RND_KEY_INITIAL
+.endif
+ addq $8*WCNT,%rsi #skip the block
+ movq %rsi,blkPtr+F_O(%rbp) #update block pointer
+ #
+ #################
+ # now the key schedule is computed. Start the rounds
+ #
+.if SKEIN_ASM_UNROLL & 512
+_UNROLL_CNT = ROUNDS_512/8
+.else
+_UNROLL_CNT = SKEIN_UNROLL_512
+ .if ((ROUNDS_512/8) % _UNROLL_CNT)
+ .err "Invalid SKEIN_UNROLL_512"
+ .endif
+ xorq %rdi,%rdi #rdi = round counter
+Skein_512_round_loop:
+.endif
+#
+_Rbase_ = 0
+.rept _UNROLL_CNT*2
+ R_512_FourRounds %(4*_Rbase_+00)
+_Rbase_ = _Rbase_+1
+.endr #rept _UNROLL_CNT
+#
+.if (SKEIN_ASM_UNROLL & 512) == 0
+ cmpq $2*(ROUNDS_512/8),%rdi
+ jb Skein_512_round_loop
+ movq ctxPtr +F_O(%rbp),%rdi #restore rdi --> context
+.endif
+ # end of rounds
+ #################
+ # feedforward: ctx->X[i] = X[i] ^ w[i], {i=0..7}
+ .irp _Rn_,8,9,10,11,12,13,14,15
+ .if (_Rn_ == 8)
+ movq $FIRST_MASK64,%rbx
+ .endif
+ xorq Wcopy+8*(_Rn_-8)+F_O(%rbp),%r\_Rn_ #feedforward XOR
+ movq %r\_Rn_,X_VARS+8*(_Rn_-8)(%rdi) #and store result
+ .if (_Rn_ == 14)
+ andq TWEAK+ 8(%rdi),%rbx
+ .endif
+ .endr
+ Skein_Debug_Round 512,SKEIN_RND_FEED_FWD
+
+ # go back for more blocks, if needed
+ decq blkCnt+F_O(%rbp)
+ jnz Skein_512_block_loop
+ movq %rbx,TWEAK + 8(%rdi)
+
+ Reset_Stack
+ ret
+Skein_512_Process_Block_End:
+#
+ .if _SKEIN_DEBUG
+# call here with rdx = "round number"
+Skein_Debug_Round_512:
+ pushq %rsi #save two regs for BLK_BITS-specific parms
+ pushq %rdi
+ .irp _Rn_,8,9,10,11,12,13,14,15 #save X[] state on stack so debug routines can access it
+ movq %r\_Rn_,X_stk+8*(_Rn_-8)+F_O(%rbp)
+ .endr
+ movq ctxPtr+F_O(%rbp),%rsi #ctx_hdr_ptr
+ movq $512,%rdi #now <rdi,rsi,rdx> are set for the call
+ jmp Skein_Debug_Round_Common
+ .endif
+#
+.if _SKEIN_CODE_SIZE
+C_label Skein_512_Process_Block_CodeSize
+ movq $(Skein_512_Process_Block_End-Skein_512_Process_Block),%rax
+ ret
+#
+C_label Skein_512_Unroll_Cnt
+ .if _UNROLL_CNT <> (ROUNDS_512/8)
+ movq $_UNROLL_CNT,%rax
+ .else
+ xorq %rax,%rax
+ .endif
+ ret
+.endif
+#
+.endif # _USE_ASM_ & 512
+#
+#=================================== Skein1024 =============================================
+.if _USE_ASM_ & 1024
+#
+# void Skein1024_Process_Block(Skein_1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t bitcntAdd)#
+#
+#################
+# use details of permutation to make register assignments
+#
+o1K_rdi = 0 #offsets in X[] associated with each register
+o1K_rsi = 1
+o1K_rbp = 2
+o1K_rax = 3
+o1K_rcx = 4 #rcx is "shared" with X6, since X4/X6 alternate
+o1K_rbx = 5
+o1K_rdx = 7
+o1K_r8 = 8
+o1K_r9 = 9
+o1K_r10 = 10
+o1K_r11 = 11
+o1K_r12 = 12
+o1K_r13 = 13
+o1K_r14 = 14
+o1K_r15 = 15
+#
+rIdx_offs = tmpStk_1024
+#
+.macro r1024_Mix w0,w1,reg0,reg1,_RN0_,_Rn1_,op1
+ addReg \reg0 , \reg1 #perform the MIX
+ RotL64 \reg1 , 1024,%((_RN0_) % 8),_Rn1_
+ xorReg \reg1 , \reg0
+.if ((_RN0_) && 3) == 3 #time to do key injection?
+ .if _SKEIN_DEBUG
+ movq %\reg0 , xDebug_1024+8*w0(%rsp) #save intermediate values for Debug_Round
+ movq %\reg1 , xDebug_1024+8*w1(%rsp) # (before inline key injection)
+ .endif
+_II_ = ((_RN0_)/4)+1 #injection count
+ .if SKEIN_ASM_UNROLL && 1024 #here to do fully unrolled key injection
+ addq ksKey+ 8*((_II_+w0) % 17)(%rsp),%\reg0
+ addq ksKey+ 8*((_II_+w1) % 17)(%rsp),%\reg1
+ .if w1 == 13 #tweak injection
+ addq ksTwk+ 8*((_II_+ 0) % 3)(%rsp),%\reg1
+ .elseif w0 == 14
+ addq ksTwk+ 8*((_II_+ 1) % 3)(%rsp),%\reg0
+ .elseif w1 == 15
+ addq $_II_, %\reg1 #(injection counter)
+ .endif
+ .else #here to do looping key injection
+ .if (w0 == 0)
+ movq %rdi, X_stk+8*w0(%rsp) #if so, store N0 so we can use reg as index
+ movq rIdx_offs(%rsp),%rdi #get the injection counter index into rdi
+ .else
+ addq ksKey+8+8*w0(%rsp,%rdi,8),%\reg0 #even key injection
+ .endif
+ .if w1 == 13 #tweak injection
+ addq ksTwk+8+8* 0(%rsp,%rdi,8),%\reg1
+ .elseif w0 == 14
+ addq ksTwk+8+8* 1(%rsp,%rdi,8),%\reg0
+ .elseif w1 == 15
+ addReg \reg1,rdi,,,1 #(injection counter)
+ .endif
+ addq ksKey+8+8*w1(%rsp,%rdi,8),%\reg1 #odd key injection
+ .endif
+.endif
+ # insert the op provided, .if any
+ op1
+.endm
+#################
+# MACRO: four rounds for 1024-bit blocks
+#
+.macro r1024_FourRounds _RR_ #RR = base round number (0 mod 4)
+ # should be here with X4 set properly, X6 stored on stack
+_Rn_ = (_RR_) + 0
+ r1024_Mix 0, 1,rdi,rsi,_Rn_,0
+ r1024_Mix 2, 3,rbp,rax,_Rn_,1
+ r1024_Mix 4, 5,rcx,rbx,_Rn_,2,<movq %rcx,X_stk+8*4(%rsp)> #save X4 on stack (x4/x6 alternate)
+ r1024_Mix 8, 9,r8 ,r9 ,_Rn_,4,<movq X_stk+8*6(%rsp),%rcx> #load X6 from stack
+ r1024_Mix 10,11,r10,r11,_Rn_,5
+ r1024_Mix 12,13,r12,r13,_Rn_,6
+ r1024_Mix 6, 7,rcx,rdx,_Rn_,3
+ r1024_Mix 14,15,r14,r15,_Rn_,7
+ .if _SKEIN_DEBUG
+ Skein_Debug_Round 1024,%(_Rn_+1)
+ .endif
+_Rn_ = (_RR_) + 1
+ r1024_Mix 0, 9,rdi,r9 ,_Rn_,0
+ r1024_Mix 2,13,rbp,r13,_Rn_,1
+ r1024_Mix 6,11,rcx,r11,_Rn_,2,<movq %rcx,X_stk+8*6(%rsp)> #save X6 on stack (x4/x6 alternate)
+ r1024_Mix 10, 7,r10,rdx,_Rn_,4,<movq X_stk+8*4(%rsp),%rcx> #load X4 from stack
+ r1024_Mix 12, 3,r12,rax,_Rn_,5
+ r1024_Mix 14, 5,r14,rbx,_Rn_,6
+ r1024_Mix 4,15,rcx,r15,_Rn_,3
+ r1024_Mix 8, 1,r8 ,rsi,_Rn_,7
+ .if _SKEIN_DEBUG
+ Skein_Debug_Round 1024,%(_Rn_+1)
+ .endif
+_Rn_ = (_RR_) + 2
+ r1024_Mix 0, 7,rdi,rdx,_Rn_,0
+ r1024_Mix 2, 5,rbp,rbx,_Rn_,1
+ r1024_Mix 4, 3,rcx,rax,_Rn_,2,<movq %rcx,X_stk+8*4(%rsp)> #save X4 on stack (x4/x6 alternate)
+ r1024_Mix 12,15,r12,r15,_Rn_,4,<movq X_stk+8*6(%rsp),%rcx> #load X6 from stack
+ r1024_Mix 14,13,r14,r13,_Rn_,5
+ r1024_Mix 8,11,r8 ,r11,_Rn_,6
+ r1024_Mix 6, 1,rcx,rsi,_Rn_,3
+ r1024_Mix 10, 9,r10,r9 ,_Rn_,7
+ .if _SKEIN_DEBUG
+ Skein_Debug_Round 1024,%(_Rn_+1)
+ .endif
+_Rn_ = (_RR_) + 3
+ r1024_Mix 0,15,rdi,r15,_Rn_,0
+ r1024_Mix 2,11,rbp,r11,_Rn_,1
+ r1024_Mix 6,13,rcx,r13,_Rn_,2,<movq %rcx,X_stk+8*6(%rsp)> #save X6 on stack (x4/x6 alternate)
+ r1024_Mix 14, 1,r14,rsi,_Rn_,4,<movq X_stk+8*4(%rsp),%rcx> #load X4 from stack
+ r1024_Mix 8, 5,r8 ,rbx,_Rn_,5
+ r1024_Mix 10, 3,r10,rax,_Rn_,6
+ r1024_Mix 4, 9,rcx,r9 ,_Rn_,3
+ r1024_Mix 12, 7,r12,rdx,_Rn_,7
+ .if _SKEIN_DEBUG
+ Skein_Debug_Round 1024,%(_Rn_+1)
+ .endif
+
+ .if (SKEIN_ASM_UNROLL && 1024) == 0 #here with rdi == rIdx, X0 on stack
+ #"rotate" the key schedule on the stack
+i8 = o1K_r8
+i0 = o1K_rdi
+ movq %r8 , X_stk+8*i8(%rsp) #free up a register (save it on the stack)
+ movq ksKey+8* 0(%rsp,%rdi,8),%r8 #get key word
+ movq %r8 , ksKey+8*17(%rsp,%rdi,8) #rotate key (must do key first or tweak clobbers it!)
+ movq ksTwk+8* 0(%rsp,%rdi,8),%r8 #get tweak word
+ movq %r8 , ksTwk+8* 3(%rsp,%rdi,8) #rotate tweak (onto the stack)
+ movq X_stk+8*i8(%rsp) ,%r8 #get the reg back
+ incq %rdi #bump the index
+ movq %rdi, rIdx_offs (%rsp) #save rdi again
+ movq ksKey+8*i0(%rsp,%rdi,8),%rdi #get the key schedule word for X0 back
+ addq X_stk+8*i0(%rsp) ,%rdi #perform the X0 key injection
+ .endif
+ #show the result of the key injection
+ Skein_Debug_Round 1024,SKEIN_RND_KEY_INJECT
+.endm #r1024_FourRounds
+#
+################
+# code
+#
+C_label Skein1024_Process_Block
+#
+ Setup_Stack 1024,ROUNDS_1024/8,WCNT
+ movq TWEAK+ 8(%rdi),%r9
+ jmp Skein1024_block_loop
+ # main hash loop for Skein1024
+ .p2align 4
+Skein1024_block_loop:
+ # general register usage:
+ # RSP = stack pointer
+ # RAX..RDX,RSI,RDI = X1, X3..X7 (state words)
+ # R8 ..R15 = X8..X15 (state words)
+ # RBP = temp (used for X0 and X2)
+ #
+ .if (SKEIN_ASM_UNROLL & 1024) == 0
+ xorq %rax,%rax #init loop index on the stack
+ movq %rax,rIdx_offs(%rsp)
+ .endif
+ movq TWEAK+ 0(%rdi),%r8
+ addq bitAdd+ F_O(%rbp),%r8 #computed updated tweak value T0
+ movq %r9 ,%r10
+ xorq %r8 ,%r10 #%rax/%rbx/%rcx = tweak schedule
+ movq %r8 ,TWEAK+ 0(%rdi) #save updated tweak value ctx->h.T[0]
+ movq %r8 ,ksTwk+ 0+F_O(%rbp)
+ movq %r9 ,ksTwk+ 8+F_O(%rbp) #keep values in %r8 ,%r9 for initial tweak injection below
+ movq %r10,ksTwk+16+F_O(%rbp)
+ .if _SKEIN_DEBUG
+ movq %r9 ,TWEAK+ 8(%rdi) #save updated tweak value ctx->h.T[1] for Skein_Debug_Block
+ .endif
+ movq blkPtr +F_O(%rbp),%rsi # rsi --> input block
+ movq $KW_PARITY ,%rax #overall key schedule parity
+
+ # the logic here assumes the set {rdi,rsi,rbp,rax} = X[0,1,2,3]
+ .irp _rN_,0,1,2,3,4,6 #process the "initial" words, using r14/r15 as temps
+ movq X_VARS+8*_rN_(%rdi),%r14 #get state word
+ movq 8*_rN_(%rsi),%r15 #get msg word
+ xorq %r14,%rax #update key schedule overall parity
+ movq %r14,ksKey +8*_rN_+F_O(%rbp) #save key schedule word on stack
+ movq %r15,Wcopy +8*_rN_+F_O(%rbp) #save local msg Wcopy
+ addq %r15,%r14 #do the initial key injection
+ movq %r14,X_stk +8*_rN_ (%rsp) #save initial state var on stack
+ .endr
+ # now process the rest, using the "real" registers
+ # (MUST do it in reverse order to inject tweaks r8/r9 first)
+ .irp _rr_,r15,r14,r13,r12,r11,r10,r9,r8,rdx,rbx
+_oo_ = o1K_\_rr_ #offset assocated with the register
+ movq X_VARS+8*_oo_(%rdi),%\_rr_ #get key schedule word from context
+ movq 8*_oo_(%rsi),%rcx #get next input msg word
+ movq %\_rr_, ksKey +8*_oo_(%rsp) #save key schedule on stack
+ xorq %\_rr_, %rax #accumulate key schedule parity
+ movq %rcx,Wcopy+8*_oo_+F_O(%rbp) #save copy of msg word for feedforward
+ addq %rcx,%\_rr_ #do the initial key injection
+ .if _oo_ == 13 #do the initial tweak injection
+ addReg _rr_,r8 # (only in words 13/14)
+ .elseif _oo_ == 14
+ addReg _rr_,r9
+ .endif
+ .endr
+ movq %rax,ksKey+8*WCNT+F_O(%rbp) #save key schedule parity
+.if _SKEIN_DEBUG
+ Skein_Debug_Block 1024 #initial debug dump
+.endif
+ addq $8*WCNT,%rsi #bump the msg ptr
+ movq %rsi,blkPtr+F_O(%rbp) #save bumped msg ptr
+ # re-load words 0..4 from stack, enter the main loop
+ .irp _rr_,rdi,rsi,rbp,rax,rcx #(no need to re-load x6, already on stack)
+ movq X_stk+8*o1K_\_rr_(%rsp),%\_rr_ #re-load state and get ready to go!
+ .endr
+.if _SKEIN_DEBUG
+ Skein_Debug_Round 1024,SKEIN_RND_KEY_INITIAL #show state after initial key injection
+.endif
+ #
+ #################
+ # now the key schedule is computed. Start the rounds
+ #
+.if SKEIN_ASM_UNROLL & 1024
+_UNROLL_CNT = ROUNDS_1024/8
+.else
+_UNROLL_CNT = SKEIN_UNROLL_1024
+ .if ((ROUNDS_1024/8) % _UNROLL_CNT)
+ .error "Invalid SKEIN_UNROLL_1024"
+ .endif
+Skein1024_round_loop:
+.endif
+#
+_Rbase_ = 0
+.rept _UNROLL_CNT*2 #implement the rounds, 4 at a time
+ r1024_FourRounds %(4*_Rbase_+00)
+_Rbase_ = _Rbase_+1
+.endr #rept _UNROLL_CNT
+#
+.if (SKEIN_ASM_UNROLL & 1024) == 0
+ cmpq $2*(ROUNDS_1024/8),tmpStk_1024(%rsp) #see .if we are done
+ jb Skein1024_round_loop
+.endif
+ # end of rounds
+ #################
+ #
+ # feedforward: ctx->X[i] = X[i] ^ w[i], {i=0..15}
+ movq %rdx,X_stk+8*o1K_rdx(%rsp) #we need a register. x6 already on stack
+ movq ctxPtr(%rsp),%rdx
+
+ .irp _rr_,rdi,rsi,rbp,rax,rcx,rbx,r8,r9,r10,r11,r12,r13,r14,r15 #do all but x6,x7
+_oo_ = o1K_\_rr_
+ xorq Wcopy +8*_oo_(%rsp),%\_rr_ #feedforward XOR
+ movq %\_rr_,X_VARS+8*_oo_(%rdx) #save result into context
+ .if (_oo_ == 9)
+ movq $FIRST_MASK64 ,%r9
+ .endif
+ .if (_oo_ == 14)
+ andq TWEAK+ 8(%rdx),%r9
+ .endif
+ .endr
+ #
+ movq X_stk +8*6(%rsp),%rax #now process x6,x7 (skipped in .irp above)
+ movq X_stk +8*7(%rsp),%rbx
+ xorq Wcopy +8*6(%rsp),%rax
+ xorq Wcopy +8*7(%rsp),%rbx
+ movq %rax,X_VARS+8*6(%rdx)
+ decq blkCnt(%rsp) #set zero flag iff done
+ movq %rbx,X_VARS+8*7(%rdx)
+
+ Skein_Debug_Round 1024,SKEIN_RND_FEED_FWD,,<cmpq $0,blkCnt(%rsp)>
+ # go back for more blocks, if needed
+ movq ctxPtr(%rsp),%rdi #don't muck with the flags here!
+ lea FRAME_OFFS(%rsp),%rbp
+ jnz Skein1024_block_loop
+ movq %r9 ,TWEAK+ 8(%rdx)
+ Reset_Stack
+ ret
+#
+Skein1024_Process_Block_End:
+#
+.if _SKEIN_DEBUG
+Skein_Debug_Round_1024:
+ # call here with rdx = "round number",
+_SP_OFFS_ = 8*2 #stack "offset" here: rdx, return addr
+ #
+ #save rest of X[] state on stack so debug routines can access it
+ .irp _rr_,rsi,rbp,rax,rbx,r8,r9,r10,r11,r12,r13,r14,r15
+ movq %\_rr_,X_stk+8*o1K_\_rr_+_SP_OFFS_(%rsp)
+ .endr
+ # Figure out what to do with x0 (rdi). When rdx == 0 mod 4, it's already on stack
+ cmpq $SKEIN_RND_SPECIAL,%rdx #special rounds always save
+ jae save_x0
+ testq $3,%rdx #otherwise only if rdx != 0 mod 4
+ jz save_x0_not
+save_x0:
+ movq %rdi,X_stk+8*o1K_rdi+_SP_OFFS_(%rsp)
+save_x0_not:
+ #figure out the x4/x6 swapping state and save the correct one!
+ cmpq $SKEIN_RND_SPECIAL,%rdx #special rounds always do x4
+ jae save_x4
+ testq $1,%rdx #and even ones have r4 as well
+ jz save_x4
+ movq %rcx,X_stk+8*6+_SP_OFFS_(%rsp)
+ jmp debug_1024_go
+save_x4:
+ movq %rcx,X_stk+8*4+_SP_OFFS_(%rsp)
+debug_1024_go:
+ #now all is saved in Xstk[] except for rdx
+ push %rsi #save two regs for BLK_BITS-specific parms
+ push %rdi
+_SP_OFFS_ = _SP_OFFS_ + 16 #adjust stack offset accordingly (now 32)
+
+ movq _SP_OFFS_-8(%rsp),%rsi #get back original %rdx (pushed on stack in macro call)
+ movq %rsi,X_stk+8*o1K_rdx+_SP_OFFS_(%rsp) #and save it in its rightful place in X_stk[]
+
+ movq ctxPtr+_SP_OFFS_(%rsp),%rsi #rsi = ctx_hdr_ptr
+ movq $1024,%rdi #rdi = block size
+ jmp Skein_Debug_Round_Common
+.endif
+#
+.if _SKEIN_CODE_SIZE
+C_label Skein1024_Process_Block_CodeSize
+ movq $(Skein1024_Process_Block_End-Skein1024_Process_Block),%rax
+ ret
+#
+C_label Skein1024_Unroll_Cnt
+ .if _UNROLL_CNT <> (ROUNDS_1024/8)
+ movq $_UNROLL_CNT,%rax
+ .else
+ xorq %rax,%rax
+ .endif
+ ret
+.endif
+#
+.endif # _USE_ASM_ and 1024
+#
+.if _SKEIN_DEBUG
+#----------------------------------------------------------------
+#local debug routine to set up for calls to:
+# void Skein_Show_Round(uint_t bits,const Skein_Ctxt_Hdr_t *h,int r,const u64b_t *X)
+# [ rdi rsi rdx rcx]
+#
+# here with %rdx = round number
+# %rsi = ctx_hdr_ptr
+# %rdi = block size (256/512/1024)
+# on stack: saved rdi, saved rsi, retAddr, saved rdx
+#
+Skein_Debug_Round_Common:
+_SP_OFFS_ = 32 #account for four words on stack already
+ .irp _rr_,rax,rbx,rcx,rbp,r8,r9,r10,r11,r12,r13,r14,r15 #save the rest of the regs
+ pushq %\_rr_
+_SP_OFFS_ = _SP_OFFS_+8
+ .endr
+ .if (_SP_OFFS_ % 16) # make sure stack is still 16-byte aligned here
+ .error "Debug_Round_Common: stack alignment"
+ .endif
+ # compute %rcx = ptr to the X[] array on the stack (final parameter to call)
+ leaq X_stk+_SP_OFFS_(%rsp),%rcx #adjust for reg pushes, return address
+ cmpq $SKEIN_RND_FEED_FWD,%rdx #special handling for feedforward "round"?
+ jnz _got_rcxA
+ leaq X_VARS(%rsi),%rcx
+_got_rcxA:
+ .if _USE_ASM_ & 1024
+ # special handling for 1024-bit case
+ # (for rounds right before with key injection:
+ # use xDebug_1024[] instead of X_stk[])
+ cmpq $SKEIN_RND_SPECIAL,%rdx
+ jae _got_rcxB #must be a normal round
+ orq %rdx,%rdx
+ jz _got_rcxB #just before key injection
+ test $3,%rdx
+ jne _got_rcxB
+ cmp $1024,%rdi #only 1024-bit(s) for now
+ jne _got_rcxB
+ leaq xDebug_1024+_SP_OFFS_(%rsp),%rcx
+_got_rcxB:
+ .endif
+ call Skein_Show_Round #call external debug handler
+
+ .irp _rr_,r15,r14,r13,r12,r11,r10,r9,r8,rbp,rcx,rbx,rax #restore regs
+ popq %\_rr_
+_SP_OFFS_ = _SP_OFFS_-8
+ .endr
+ .if _SP_OFFS_ - 32
+ .error "Debug_Round_Common: push/pop misalignment!"
+ .endif
+ popq %rdi
+ popq %rsi
+ ret
+.endif
+#----------------------------------------------------------------
+ .end
diff --git a/sys/crypto/skein/skein.c b/sys/crypto/skein/skein.c
new file mode 100644
index 0000000..b8d5905
--- /dev/null
+++ b/sys/crypto/skein/skein.c
@@ -0,0 +1,858 @@
+/***********************************************************************
+**
+** Implementation of the Skein hash function.
+**
+** Source code author: Doug Whiting, 2008.
+**
+** This algorithm and source code is released to the public domain.
+**
+************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+#include <sys/types.h>
+
+/* get the memcpy/memset functions */
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+
+#define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */
+
+#include "skein.h" /* get the Skein API definitions */
+#include "skein_iv.h" /* get precomputed IVs */
+
+/*****************************************************************/
+/* External function to process blkCnt (nonzero) full block(s) of data. */
+void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
+void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
+void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
+
+/*****************************************************************/
+/* 256-bit Skein */
+/*****************************************************************/
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* init the context for a straight hashing operation */
+int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
+ {
+ union
+ {
+ u08b_t b[SKEIN_256_STATE_BYTES];
+ u64b_t w[SKEIN_256_STATE_WORDS];
+ } cfg; /* config block */
+
+ Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
+ ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
+
+ switch (hashBitLen)
+ { /* use pre-computed values, where available */
+#ifndef SKEIN_NO_PRECOMP
+ case 256: memcpy(ctx->X,SKEIN_256_IV_256,sizeof(ctx->X)); break;
+ case 224: memcpy(ctx->X,SKEIN_256_IV_224,sizeof(ctx->X)); break;
+ case 160: memcpy(ctx->X,SKEIN_256_IV_160,sizeof(ctx->X)); break;
+ case 128: memcpy(ctx->X,SKEIN_256_IV_128,sizeof(ctx->X)); break;
+#endif
+ default:
+ /* here if there is no precomputed IV value available */
+ /* build/process the config block, type == CONFIG (could be precomputed) */
+ Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
+
+ cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
+ cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
+ cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
+ memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
+
+ /* compute the initial chaining values from config block */
+ memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
+ Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
+ break;
+ }
+ /* The chaining vars ctx->X are now initialized for the given hashBitLen. */
+ /* Set up to process the data message portion of the hash (default) */
+ Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* init the context for a MAC and/or tree hash operation */
+/* [identical to Skein_256_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */
+int Skein_256_InitExt(Skein_256_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)
+ {
+ union
+ {
+ u08b_t b[SKEIN_256_STATE_BYTES];
+ u64b_t w[SKEIN_256_STATE_WORDS];
+ } cfg; /* config block */
+
+ Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
+ Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
+
+ /* compute the initial chaining values ctx->X[], based on key */
+ if (keyBytes == 0) /* is there a key? */
+ {
+ memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
+ }
+ else /* here to pre-process a key */
+ {
+ Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));
+ /* do a mini-Init right here */
+ ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */
+ Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */
+ memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */
+ Skein_256_Update(ctx,key,keyBytes); /* hash the key */
+ Skein_256_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */
+ memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */
+#if SKEIN_NEED_SWAP
+ {
+ uint_t i;
+ for (i=0;i<SKEIN_256_STATE_WORDS;i++) /* convert key bytes to context words */
+ ctx->X[i] = Skein_Swap64(ctx->X[i]);
+ }
+#endif
+ }
+ /* build/process the config block, type == CONFIG (could be precomputed for each key) */
+ ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
+ Skein_Start_New_Type(ctx,CFG_FINAL);
+
+ memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */
+ cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
+ cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
+ cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
+
+ Skein_Show_Key(256,&ctx->h,key,keyBytes);
+
+ /* compute the initial chaining values from config block */
+ Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
+
+ /* The chaining vars ctx->X are now initialized */
+ /* Set up to process the data message portion of the hash (default) */
+ ctx->h.bCnt = 0; /* buffer b[] starts out empty */
+ Skein_Start_New_Type(ctx,MSG);
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* process the input bytes */
+int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
+ {
+ size_t n;
+
+ Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ /* process full blocks, if any */
+ if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES)
+ {
+ if (ctx->h.bCnt) /* finish up any buffered message data */
+ {
+ n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
+ if (n)
+ {
+ Skein_assert(n < msgByteCnt); /* check on our logic here */
+ memcpy(&ctx->b[ctx->h.bCnt],msg,n);
+ msgByteCnt -= n;
+ msg += n;
+ ctx->h.bCnt += n;
+ }
+ Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
+ Skein_256_Process_Block(ctx,ctx->b,1,SKEIN_256_BLOCK_BYTES);
+ ctx->h.bCnt = 0;
+ }
+ /* now process any remaining full blocks, directly from input message data */
+ if (msgByteCnt > SKEIN_256_BLOCK_BYTES)
+ {
+ n = (msgByteCnt-1) / SKEIN_256_BLOCK_BYTES; /* number of full blocks to process */
+ Skein_256_Process_Block(ctx,msg,n,SKEIN_256_BLOCK_BYTES);
+ msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;
+ msg += n * SKEIN_256_BLOCK_BYTES;
+ }
+ Skein_assert(ctx->h.bCnt == 0);
+ }
+
+ /* copy any remaining source message data bytes into b[] */
+ if (msgByteCnt)
+ {
+ Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);
+ memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
+ ctx->h.bCnt += msgByteCnt;
+ }
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* finalize the hash computation and output the result */
+int Skein_256_Final(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ size_t i,n,byteCnt;
+ u64b_t X[SKEIN_256_STATE_WORDS];
+ Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
+ if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */
+ memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
+
+ Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
+
+ /* now output the result */
+ byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
+
+ /* run Threefish in "counter mode" to generate output */
+ memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
+ memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
+ for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++)
+ {
+ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
+ Skein_Start_New_Type(ctx,OUT_FINAL);
+ Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
+ n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */
+ if (n >= SKEIN_256_BLOCK_BYTES)
+ n = SKEIN_256_BLOCK_BYTES;
+ Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
+ Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES);
+ memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
+ }
+ return SKEIN_SUCCESS;
+ }
+
+#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
+size_t Skein_256_API_CodeSize(void)
+ {
+ return ((u08b_t *) Skein_256_API_CodeSize) -
+ ((u08b_t *) Skein_256_Init);
+ }
+#endif
+
+/*****************************************************************/
+/* 512-bit Skein */
+/*****************************************************************/
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* init the context for a straight hashing operation */
+int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
+ {
+ union
+ {
+ u08b_t b[SKEIN_512_STATE_BYTES];
+ u64b_t w[SKEIN_512_STATE_WORDS];
+ } cfg; /* config block */
+
+ Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
+ ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
+
+ switch (hashBitLen)
+ { /* use pre-computed values, where available */
+#ifndef SKEIN_NO_PRECOMP
+ case 512: memcpy(ctx->X,SKEIN_512_IV_512,sizeof(ctx->X)); break;
+ case 384: memcpy(ctx->X,SKEIN_512_IV_384,sizeof(ctx->X)); break;
+ case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break;
+ case 224: memcpy(ctx->X,SKEIN_512_IV_224,sizeof(ctx->X)); break;
+#endif
+ default:
+ /* here if there is no precomputed IV value available */
+ /* build/process the config block, type == CONFIG (could be precomputed) */
+ Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
+
+ cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
+ cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
+ cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
+ memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
+
+ /* compute the initial chaining values from config block */
+ memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
+ Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
+ break;
+ }
+
+ /* The chaining vars ctx->X are now initialized for the given hashBitLen. */
+ /* Set up to process the data message portion of the hash (default) */
+ Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* init the context for a MAC and/or tree hash operation */
+/* [identical to Skein_512_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */
+int Skein_512_InitExt(Skein_512_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)
+ {
+ union
+ {
+ u08b_t b[SKEIN_512_STATE_BYTES];
+ u64b_t w[SKEIN_512_STATE_WORDS];
+ } cfg; /* config block */
+
+ Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
+ Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
+
+ /* compute the initial chaining values ctx->X[], based on key */
+ if (keyBytes == 0) /* is there a key? */
+ {
+ memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
+ }
+ else /* here to pre-process a key */
+ {
+ Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));
+ /* do a mini-Init right here */
+ ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */
+ Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */
+ memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */
+ Skein_512_Update(ctx,key,keyBytes); /* hash the key */
+ Skein_512_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */
+ memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */
+#if SKEIN_NEED_SWAP
+ {
+ uint_t i;
+ for (i=0;i<SKEIN_512_STATE_WORDS;i++) /* convert key bytes to context words */
+ ctx->X[i] = Skein_Swap64(ctx->X[i]);
+ }
+#endif
+ }
+ /* build/process the config block, type == CONFIG (could be precomputed for each key) */
+ ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
+ Skein_Start_New_Type(ctx,CFG_FINAL);
+
+ memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */
+ cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
+ cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
+ cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
+
+ Skein_Show_Key(512,&ctx->h,key,keyBytes);
+
+ /* compute the initial chaining values from config block */
+ Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
+
+ /* The chaining vars ctx->X are now initialized */
+ /* Set up to process the data message portion of the hash (default) */
+ ctx->h.bCnt = 0; /* buffer b[] starts out empty */
+ Skein_Start_New_Type(ctx,MSG);
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* process the input bytes */
+int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
+ {
+ size_t n;
+
+ Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ /* process full blocks, if any */
+ if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
+ {
+ if (ctx->h.bCnt) /* finish up any buffered message data */
+ {
+ n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
+ if (n)
+ {
+ Skein_assert(n < msgByteCnt); /* check on our logic here */
+ memcpy(&ctx->b[ctx->h.bCnt],msg,n);
+ msgByteCnt -= n;
+ msg += n;
+ ctx->h.bCnt += n;
+ }
+ Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
+ Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);
+ ctx->h.bCnt = 0;
+ }
+ /* now process any remaining full blocks, directly from input message data */
+ if (msgByteCnt > SKEIN_512_BLOCK_BYTES)
+ {
+ n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */
+ Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES);
+ msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
+ msg += n * SKEIN_512_BLOCK_BYTES;
+ }
+ Skein_assert(ctx->h.bCnt == 0);
+ }
+
+ /* copy any remaining source message data bytes into b[] */
+ if (msgByteCnt)
+ {
+ Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
+ memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
+ ctx->h.bCnt += msgByteCnt;
+ }
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* finalize the hash computation and output the result */
+int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ size_t i,n,byteCnt;
+ u64b_t X[SKEIN_512_STATE_WORDS];
+ Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
+ if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */
+ memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
+
+ Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
+
+ /* now output the result */
+ byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
+
+ /* run Threefish in "counter mode" to generate output */
+ memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
+ memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
+ for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
+ {
+ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
+ Skein_Start_New_Type(ctx,OUT_FINAL);
+ Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
+ n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */
+ if (n >= SKEIN_512_BLOCK_BYTES)
+ n = SKEIN_512_BLOCK_BYTES;
+ Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
+ Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);
+ memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
+ }
+ return SKEIN_SUCCESS;
+ }
+
+#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
+size_t Skein_512_API_CodeSize(void)
+ {
+ return ((u08b_t *) Skein_512_API_CodeSize) -
+ ((u08b_t *) Skein_512_Init);
+ }
+#endif
+
+/*****************************************************************/
+/* 1024-bit Skein */
+/*****************************************************************/
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* init the context for a straight hashing operation */
+int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
+ {
+ union
+ {
+ u08b_t b[SKEIN1024_STATE_BYTES];
+ u64b_t w[SKEIN1024_STATE_WORDS];
+ } cfg; /* config block */
+
+ Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
+ ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
+
+ switch (hashBitLen)
+ { /* use pre-computed values, where available */
+#ifndef SKEIN_NO_PRECOMP
+ case 512: memcpy(ctx->X,SKEIN1024_IV_512 ,sizeof(ctx->X)); break;
+ case 384: memcpy(ctx->X,SKEIN1024_IV_384 ,sizeof(ctx->X)); break;
+ case 1024: memcpy(ctx->X,SKEIN1024_IV_1024,sizeof(ctx->X)); break;
+#endif
+ default:
+ /* here if there is no precomputed IV value available */
+ /* build/process the config block, type == CONFIG (could be precomputed) */
+ Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
+
+ cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
+ cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
+ cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
+ memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
+
+ /* compute the initial chaining values from config block */
+ memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
+ Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
+ break;
+ }
+
+ /* The chaining vars ctx->X are now initialized for the given hashBitLen. */
+ /* Set up to process the data message portion of the hash (default) */
+ Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* init the context for a MAC and/or tree hash operation */
+/* [identical to Skein1024_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */
+int Skein1024_InitExt(Skein1024_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)
+ {
+ union
+ {
+ u08b_t b[SKEIN1024_STATE_BYTES];
+ u64b_t w[SKEIN1024_STATE_WORDS];
+ } cfg; /* config block */
+
+ Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
+ Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
+
+ /* compute the initial chaining values ctx->X[], based on key */
+ if (keyBytes == 0) /* is there a key? */
+ {
+ memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
+ }
+ else /* here to pre-process a key */
+ {
+ Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));
+ /* do a mini-Init right here */
+ ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */
+ Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */
+ memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */
+ Skein1024_Update(ctx,key,keyBytes); /* hash the key */
+ Skein1024_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */
+ memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */
+#if SKEIN_NEED_SWAP
+ {
+ uint_t i;
+ for (i=0;i<SKEIN1024_STATE_WORDS;i++) /* convert key bytes to context words */
+ ctx->X[i] = Skein_Swap64(ctx->X[i]);
+ }
+#endif
+ }
+ /* build/process the config block, type == CONFIG (could be precomputed for each key) */
+ ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
+ Skein_Start_New_Type(ctx,CFG_FINAL);
+
+ memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */
+ cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
+ cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
+ cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
+
+ Skein_Show_Key(1024,&ctx->h,key,keyBytes);
+
+ /* compute the initial chaining values from config block */
+ Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
+
+ /* The chaining vars ctx->X are now initialized */
+ /* Set up to process the data message portion of the hash (default) */
+ ctx->h.bCnt = 0; /* buffer b[] starts out empty */
+ Skein_Start_New_Type(ctx,MSG);
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* process the input bytes */
+int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
+ {
+ size_t n;
+
+ Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ /* process full blocks, if any */
+ if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES)
+ {
+ if (ctx->h.bCnt) /* finish up any buffered message data */
+ {
+ n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
+ if (n)
+ {
+ Skein_assert(n < msgByteCnt); /* check on our logic here */
+ memcpy(&ctx->b[ctx->h.bCnt],msg,n);
+ msgByteCnt -= n;
+ msg += n;
+ ctx->h.bCnt += n;
+ }
+ Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
+ Skein1024_Process_Block(ctx,ctx->b,1,SKEIN1024_BLOCK_BYTES);
+ ctx->h.bCnt = 0;
+ }
+ /* now process any remaining full blocks, directly from input message data */
+ if (msgByteCnt > SKEIN1024_BLOCK_BYTES)
+ {
+ n = (msgByteCnt-1) / SKEIN1024_BLOCK_BYTES; /* number of full blocks to process */
+ Skein1024_Process_Block(ctx,msg,n,SKEIN1024_BLOCK_BYTES);
+ msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;
+ msg += n * SKEIN1024_BLOCK_BYTES;
+ }
+ Skein_assert(ctx->h.bCnt == 0);
+ }
+
+ /* copy any remaining source message data bytes into b[] */
+ if (msgByteCnt)
+ {
+ Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
+ memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
+ ctx->h.bCnt += msgByteCnt;
+ }
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* finalize the hash computation and output the result */
+int Skein1024_Final(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ size_t i,n,byteCnt;
+ u64b_t X[SKEIN1024_STATE_WORDS];
+ Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
+ if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */
+ memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
+
+ Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
+
+ /* now output the result */
+ byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
+
+ /* run Threefish in "counter mode" to generate output */
+ memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
+ memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
+ for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++)
+ {
+ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
+ Skein_Start_New_Type(ctx,OUT_FINAL);
+ Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
+ n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */
+ if (n >= SKEIN1024_BLOCK_BYTES)
+ n = SKEIN1024_BLOCK_BYTES;
+ Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
+ Skein_Show_Final(1024,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES);
+ memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
+ }
+ return SKEIN_SUCCESS;
+ }
+
+#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
+size_t Skein1024_API_CodeSize(void)
+ {
+ return ((u08b_t *) Skein1024_API_CodeSize) -
+ ((u08b_t *) Skein1024_Init);
+ }
+#endif
+
+/**************** Functions to support MAC/tree hashing ***************/
+/* (this code is identical for Optimized and Reference versions) */
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* finalize the hash computation and output the block, no OUTPUT stage */
+int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
+ if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */
+ memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
+ Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
+
+ Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_256_BLOCK_BYTES); /* "output" the state bytes */
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* finalize the hash computation and output the block, no OUTPUT stage */
+int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
+ if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */
+ memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
+ Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
+
+ Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_512_BLOCK_BYTES); /* "output" the state bytes */
+
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* finalize the hash computation and output the block, no OUTPUT stage */
+int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
+ if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */
+ memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
+ Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
+
+ Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN1024_BLOCK_BYTES); /* "output" the state bytes */
+
+ return SKEIN_SUCCESS;
+ }
+
+#if SKEIN_TREE_HASH
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* just do the OUTPUT stage */
+int Skein_256_Output(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ size_t i,n,byteCnt;
+ u64b_t X[SKEIN_256_STATE_WORDS];
+ Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ /* now output the result */
+ byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
+
+ /* run Threefish in "counter mode" to generate output */
+ memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
+ memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
+ for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++)
+ {
+ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
+ Skein_Start_New_Type(ctx,OUT_FINAL);
+ Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
+ n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */
+ if (n >= SKEIN_256_BLOCK_BYTES)
+ n = SKEIN_256_BLOCK_BYTES;
+ Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
+ Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES);
+ memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
+ }
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* just do the OUTPUT stage */
+int Skein_512_Output(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ size_t i,n,byteCnt;
+ u64b_t X[SKEIN_512_STATE_WORDS];
+ Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ /* now output the result */
+ byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
+
+ /* run Threefish in "counter mode" to generate output */
+ memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
+ memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
+ for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
+ {
+ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
+ Skein_Start_New_Type(ctx,OUT_FINAL);
+ Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
+ n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */
+ if (n >= SKEIN_512_BLOCK_BYTES)
+ n = SKEIN_512_BLOCK_BYTES;
+ Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
+ Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);
+ memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
+ }
+ return SKEIN_SUCCESS;
+ }
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+/* just do the OUTPUT stage */
+int Skein1024_Output(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
+ {
+ size_t i,n,byteCnt;
+ u64b_t X[SKEIN1024_STATE_WORDS];
+ Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
+
+ /* now output the result */
+ byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
+
+ /* run Threefish in "counter mode" to generate output */
+ memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
+ memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
+ for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++)
+ {
+ ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
+ Skein_Start_New_Type(ctx,OUT_FINAL);
+ Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
+ n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */
+ if (n >= SKEIN1024_BLOCK_BYTES)
+ n = SKEIN1024_BLOCK_BYTES;
+ Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
+ Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES);
+ memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
+ }
+ return SKEIN_SUCCESS;
+ }
+
+
+/* Adapt the functions to match the prototype expected by libmd */
+void
+SKEIN256_Init(SKEIN256_CTX * ctx)
+{
+
+ Skein_256_Init(ctx, 256);
+}
+
+void
+SKEIN512_Init(SKEIN512_CTX * ctx)
+{
+
+ Skein_512_Init(ctx, 512);
+}
+
+void
+SKEIN1024_Init(SKEIN1024_CTX * ctx)
+{
+
+ Skein1024_Init(ctx, 1024);
+}
+
+void
+SKEIN256_Update(SKEIN256_CTX * ctx, const void *in, size_t len)
+{
+
+ Skein_256_Update(ctx, in, len);
+}
+
+void
+SKEIN512_Update(SKEIN512_CTX * ctx, const void *in, size_t len)
+{
+
+ Skein_512_Update(ctx, in, len);
+}
+
+void
+SKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len)
+{
+
+ Skein1024_Update(ctx, in, len);
+}
+
+void
+SKEIN256_Final(unsigned char digest[static SKEIN_256_BLOCK_BYTES], SKEIN256_CTX *ctx)
+{
+
+ Skein_256_Final(ctx, digest);
+}
+
+void
+SKEIN512_Final(unsigned char digest[static SKEIN_512_BLOCK_BYTES], SKEIN512_CTX *ctx)
+{
+
+ Skein_512_Final(ctx, digest);
+}
+
+void
+SKEIN1024_Final(unsigned char digest[static SKEIN1024_BLOCK_BYTES], SKEIN1024_CTX *ctx)
+{
+
+ Skein1024_Final(ctx, digest);
+}
+
+#ifdef WEAK_REFS
+/* When building libmd, provide weak references. Note: this is not
+ activated in the context of compiling these sources for internal
+ use in libcrypt.
+ */
+#undef SKEIN256_Init
+__weak_reference(_libmd_SKEIN256_Init, SKEIN256_Init);
+#undef SKEIN256_Update
+__weak_reference(_libmd_SKEIN256_Update, SKEIN256_Update);
+#undef SKEIN256_Final
+__weak_reference(_libmd_SKEIN256_Final, SKEIN256_Final);
+
+#undef SKEIN512_Init
+__weak_reference(_libmd_SKEIN512_Init, SKEIN512_Init);
+#undef SKEIN512_Update
+__weak_reference(_libmd_SKEIN512_Update, SKEIN512_Update);
+#undef SKEIN512_Final
+__weak_reference(_libmd_SKEIN512_Final, SKEIN512_Final);
+
+#undef SKEIN1024_Init
+__weak_reference(_libmd_SKEIN1024_Init, SKEIN1024_Init);
+#undef SKEIN1024_Update
+__weak_reference(_libmd_SKEIN1024_Update, SKEIN1024_Update);
+#undef SKEIN1024_Final
+__weak_reference(_libmd_SKEIN1024_Final, SKEIN1024_Final);
+#endif
+
+#endif
diff --git a/sys/crypto/skein/skein.h b/sys/crypto/skein/skein.h
new file mode 100644
index 0000000..ca919ac
--- /dev/null
+++ b/sys/crypto/skein/skein.h
@@ -0,0 +1,333 @@
+/* $FreeBSD$ */
+#ifndef _SKEIN_H_
+#define _SKEIN_H_ 1
+/**************************************************************************
+**
+** Interface declarations and internal definitions for Skein hashing.
+**
+** Source code author: Doug Whiting, 2008.
+**
+** This algorithm and source code is released to the public domain.
+**
+***************************************************************************
+**
+** The following compile-time switches may be defined to control some
+** tradeoffs between speed, code size, error checking, and security.
+**
+** The "default" note explains what happens when the switch is not defined.
+**
+** SKEIN_DEBUG -- make callouts from inside Skein code
+** to examine/display intermediate values.
+** [default: no callouts (no overhead)]
+**
+** SKEIN_ERR_CHECK -- how error checking is handled inside Skein
+** code. If not defined, most error checking
+** is disabled (for performance). Otherwise,
+** the switch value is interpreted as:
+** 0: use assert() to flag errors
+** 1: return SKEIN_FAIL to flag errors
+**
+***************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef _KERNEL
+#include <stddef.h> /* get size_t definition */
+#endif
+#include "skein_port.h" /* get platform-specific definitions */
+
+enum
+ {
+ SKEIN_SUCCESS = 0, /* return codes from Skein calls */
+ SKEIN_FAIL = 1,
+ SKEIN_BAD_HASHLEN = 2
+ };
+
+#define SKEIN_MODIFIER_WORDS ( 2) /* number of modifier (tweak) words */
+
+#define SKEIN_256_STATE_WORDS ( 4)
+#define SKEIN_512_STATE_WORDS ( 8)
+#define SKEIN1024_STATE_WORDS (16)
+#define SKEIN_MAX_STATE_WORDS (16)
+
+#define SKEIN_256_STATE_BYTES ( 8*SKEIN_256_STATE_WORDS)
+#define SKEIN_512_STATE_BYTES ( 8*SKEIN_512_STATE_WORDS)
+#define SKEIN1024_STATE_BYTES ( 8*SKEIN1024_STATE_WORDS)
+
+#define SKEIN_256_STATE_BITS (64*SKEIN_256_STATE_WORDS)
+#define SKEIN_512_STATE_BITS (64*SKEIN_512_STATE_WORDS)
+#define SKEIN1024_STATE_BITS (64*SKEIN1024_STATE_WORDS)
+
+#define SKEIN_256_BLOCK_BYTES ( 8*SKEIN_256_STATE_WORDS)
+#define SKEIN_512_BLOCK_BYTES ( 8*SKEIN_512_STATE_WORDS)
+#define SKEIN1024_BLOCK_BYTES ( 8*SKEIN1024_STATE_WORDS)
+
+typedef struct
+ {
+ size_t hashBitLen; /* size of hash result, in bits */
+ size_t bCnt; /* current byte count in buffer b[] */
+ u64b_t T[SKEIN_MODIFIER_WORDS]; /* tweak words: T[0]=byte cnt, T[1]=flags */
+ } Skein_Ctxt_Hdr_t;
+
+typedef struct /* 256-bit Skein hash context structure */
+ {
+ Skein_Ctxt_Hdr_t h; /* common header context variables */
+ u64b_t X[SKEIN_256_STATE_WORDS]; /* chaining variables */
+ u08b_t b[SKEIN_256_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */
+ } Skein_256_Ctxt_t;
+
+typedef struct /* 512-bit Skein hash context structure */
+ {
+ Skein_Ctxt_Hdr_t h; /* common header context variables */
+ u64b_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */
+ u08b_t b[SKEIN_512_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */
+ } Skein_512_Ctxt_t;
+
+typedef struct /* 1024-bit Skein hash context structure */
+ {
+ Skein_Ctxt_Hdr_t h; /* common header context variables */
+ u64b_t X[SKEIN1024_STATE_WORDS]; /* chaining variables */
+ u08b_t b[SKEIN1024_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */
+ } Skein1024_Ctxt_t;
+
+/* Skein APIs for (incremental) "straight hashing" */
+int Skein_256_Init (Skein_256_Ctxt_t *ctx, size_t hashBitLen);
+int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen);
+int Skein1024_Init (Skein1024_Ctxt_t *ctx, size_t hashBitLen);
+
+int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt);
+int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt);
+int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt);
+
+int Skein_256_Final (Skein_256_Ctxt_t *ctx, u08b_t * hashVal);
+int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
+int Skein1024_Final (Skein1024_Ctxt_t *ctx, u08b_t * hashVal);
+
+/*
+** Skein APIs for "extended" initialization: MAC keys, tree hashing.
+** After an InitExt() call, just use Update/Final calls as with Init().
+**
+** Notes: Same parameters as _Init() calls, plus treeInfo/key/keyBytes.
+** When keyBytes == 0 and treeInfo == SKEIN_SEQUENTIAL,
+** the results of InitExt() are identical to calling Init().
+** The function Init() may be called once to "precompute" the IV for
+** a given hashBitLen value, then by saving a copy of the context
+** the IV computation may be avoided in later calls.
+** Similarly, the function InitExt() may be called once per MAC key
+** to precompute the MAC IV, then a copy of the context saved and
+** reused for each new MAC computation.
+**/
+int Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, u64b_t treeInfo, const u08b_t *key, size_t keyBytes);
+int Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, u64b_t treeInfo, const u08b_t *key, size_t keyBytes);
+int Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, u64b_t treeInfo, const u08b_t *key, size_t keyBytes);
+
+/*
+** Skein APIs for MAC and tree hash:
+** Final_Pad: pad, do final block, but no OUTPUT type
+** Output: do just the output stage
+*/
+int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t * hashVal);
+int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
+int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t * hashVal);
+
+#ifndef SKEIN_TREE_HASH
+#define SKEIN_TREE_HASH (1)
+#endif
+#if SKEIN_TREE_HASH
+int Skein_256_Output (Skein_256_Ctxt_t *ctx, u08b_t * hashVal);
+int Skein_512_Output (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
+int Skein1024_Output (Skein1024_Ctxt_t *ctx, u08b_t * hashVal);
+#endif
+
+/*****************************************************************
+** "Internal" Skein definitions
+** -- not needed for sequential hashing API, but will be
+** helpful for other uses of Skein (e.g., tree hash mode).
+** -- included here so that they can be shared between
+** reference and optimized code.
+******************************************************************/
+
+/* tweak word T[1]: bit field starting positions */
+#define SKEIN_T1_BIT(BIT) ((BIT) - 64) /* offset 64 because it's the second word */
+
+#define SKEIN_T1_POS_TREE_LVL SKEIN_T1_BIT(112) /* bits 112..118: level in hash tree */
+#define SKEIN_T1_POS_BIT_PAD SKEIN_T1_BIT(119) /* bit 119 : partial final input byte */
+#define SKEIN_T1_POS_BLK_TYPE SKEIN_T1_BIT(120) /* bits 120..125: type field */
+#define SKEIN_T1_POS_FIRST SKEIN_T1_BIT(126) /* bits 126 : first block flag */
+#define SKEIN_T1_POS_FINAL SKEIN_T1_BIT(127) /* bit 127 : final block flag */
+
+/* tweak word T[1]: flag bit definition(s) */
+#define SKEIN_T1_FLAG_FIRST (((u64b_t) 1 ) << SKEIN_T1_POS_FIRST)
+#define SKEIN_T1_FLAG_FINAL (((u64b_t) 1 ) << SKEIN_T1_POS_FINAL)
+#define SKEIN_T1_FLAG_BIT_PAD (((u64b_t) 1 ) << SKEIN_T1_POS_BIT_PAD)
+
+/* tweak word T[1]: tree level bit field mask */
+#define SKEIN_T1_TREE_LVL_MASK (((u64b_t)0x7F) << SKEIN_T1_POS_TREE_LVL)
+#define SKEIN_T1_TREE_LEVEL(n) (((u64b_t) (n)) << SKEIN_T1_POS_TREE_LVL)
+
+/* tweak word T[1]: block type field */
+#define SKEIN_BLK_TYPE_KEY ( 0) /* key, for MAC and KDF */
+#define SKEIN_BLK_TYPE_CFG ( 4) /* configuration block */
+#define SKEIN_BLK_TYPE_PERS ( 8) /* personalization string */
+#define SKEIN_BLK_TYPE_PK (12) /* public key (for digital signature hashing) */
+#define SKEIN_BLK_TYPE_KDF (16) /* key identifier for KDF */
+#define SKEIN_BLK_TYPE_NONCE (20) /* nonce for PRNG */
+#define SKEIN_BLK_TYPE_MSG (48) /* message processing */
+#define SKEIN_BLK_TYPE_OUT (63) /* output stage */
+#define SKEIN_BLK_TYPE_MASK (63) /* bit field mask */
+
+#define SKEIN_T1_BLK_TYPE(T) (((u64b_t) (SKEIN_BLK_TYPE_##T)) << SKEIN_T1_POS_BLK_TYPE)
+#define SKEIN_T1_BLK_TYPE_KEY SKEIN_T1_BLK_TYPE(KEY) /* key, for MAC and KDF */
+#define SKEIN_T1_BLK_TYPE_CFG SKEIN_T1_BLK_TYPE(CFG) /* configuration block */
+#define SKEIN_T1_BLK_TYPE_PERS SKEIN_T1_BLK_TYPE(PERS) /* personalization string */
+#define SKEIN_T1_BLK_TYPE_PK SKEIN_T1_BLK_TYPE(PK) /* public key (for digital signature hashing) */
+#define SKEIN_T1_BLK_TYPE_KDF SKEIN_T1_BLK_TYPE(KDF) /* key identifier for KDF */
+#define SKEIN_T1_BLK_TYPE_NONCE SKEIN_T1_BLK_TYPE(NONCE)/* nonce for PRNG */
+#define SKEIN_T1_BLK_TYPE_MSG SKEIN_T1_BLK_TYPE(MSG) /* message processing */
+#define SKEIN_T1_BLK_TYPE_OUT SKEIN_T1_BLK_TYPE(OUT) /* output stage */
+#define SKEIN_T1_BLK_TYPE_MASK SKEIN_T1_BLK_TYPE(MASK) /* field bit mask */
+
+#define SKEIN_T1_BLK_TYPE_CFG_FINAL (SKEIN_T1_BLK_TYPE_CFG | SKEIN_T1_FLAG_FINAL)
+#define SKEIN_T1_BLK_TYPE_OUT_FINAL (SKEIN_T1_BLK_TYPE_OUT | SKEIN_T1_FLAG_FINAL)
+
+#define SKEIN_VERSION (1)
+
+#ifndef SKEIN_ID_STRING_LE /* allow compile-time personalization */
+#define SKEIN_ID_STRING_LE (0x33414853) /* "SHA3" (little-endian)*/
+#endif
+
+#define SKEIN_MK_64(hi32,lo32) ((lo32) + (((u64b_t) (hi32)) << 32))
+#define SKEIN_SCHEMA_VER SKEIN_MK_64(SKEIN_VERSION,SKEIN_ID_STRING_LE)
+#define SKEIN_KS_PARITY SKEIN_MK_64(0x1BD11BDA,0xA9FC1A22)
+
+#define SKEIN_CFG_STR_LEN (4*8)
+
+/* bit field definitions in config block treeInfo word */
+#define SKEIN_CFG_TREE_LEAF_SIZE_POS ( 0)
+#define SKEIN_CFG_TREE_NODE_SIZE_POS ( 8)
+#define SKEIN_CFG_TREE_MAX_LEVEL_POS (16)
+
+#define SKEIN_CFG_TREE_LEAF_SIZE_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_LEAF_SIZE_POS)
+#define SKEIN_CFG_TREE_NODE_SIZE_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_NODE_SIZE_POS)
+#define SKEIN_CFG_TREE_MAX_LEVEL_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_MAX_LEVEL_POS)
+
+#define SKEIN_CFG_TREE_INFO(leaf,node,maxLvl) \
+ ( (((u64b_t)(leaf )) << SKEIN_CFG_TREE_LEAF_SIZE_POS) | \
+ (((u64b_t)(node )) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \
+ (((u64b_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS) )
+
+#define SKEIN_CFG_TREE_INFO_SEQUENTIAL SKEIN_CFG_TREE_INFO(0,0,0) /* use as treeInfo in InitExt() call for sequential processing */
+
+/*
+** Skein macros for getting/setting tweak words, etc.
+** These are useful for partial input bytes, hash tree init/update, etc.
+**/
+#define Skein_Get_Tweak(ctxPtr,TWK_NUM) ((ctxPtr)->h.T[TWK_NUM])
+#define Skein_Set_Tweak(ctxPtr,TWK_NUM,tVal) {(ctxPtr)->h.T[TWK_NUM] = (tVal);}
+
+#define Skein_Get_T0(ctxPtr) Skein_Get_Tweak(ctxPtr,0)
+#define Skein_Get_T1(ctxPtr) Skein_Get_Tweak(ctxPtr,1)
+#define Skein_Set_T0(ctxPtr,T0) Skein_Set_Tweak(ctxPtr,0,T0)
+#define Skein_Set_T1(ctxPtr,T1) Skein_Set_Tweak(ctxPtr,1,T1)
+
+/* set both tweak words at once */
+#define Skein_Set_T0_T1(ctxPtr,T0,T1) \
+ { \
+ Skein_Set_T0(ctxPtr,(T0)); \
+ Skein_Set_T1(ctxPtr,(T1)); \
+ }
+
+#define Skein_Set_Type(ctxPtr,BLK_TYPE) \
+ Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE)
+
+/* set up for starting with a new type: h.T[0]=0; h.T[1] = NEW_TYPE; h.bCnt=0; */
+#define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \
+ { Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; }
+
+#define Skein_Clear_First_Flag(hdr) { (hdr).T[1] &= ~SKEIN_T1_FLAG_FIRST; }
+#define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; }
+
+#define Skein_Set_Tree_Level(hdr,height) { (hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height);}
+
+/*****************************************************************
+** "Internal" Skein definitions for debugging and error checking
+******************************************************************/
+#ifdef SKEIN_DEBUG /* examine/display intermediate values? */
+#include "skein_debug.h"
+#else /* default is no callouts */
+#define Skein_Show_Block(bits,ctx,X,blkPtr,wPtr,ksEvenPtr,ksOddPtr)
+#define Skein_Show_Round(bits,ctx,r,X)
+#define Skein_Show_R_Ptr(bits,ctx,r,X_ptr)
+#define Skein_Show_Final(bits,ctx,cnt,outPtr)
+#define Skein_Show_Key(bits,ctx,key,keyBytes)
+#endif
+
+#ifndef SKEIN_ERR_CHECK /* run-time checks (e.g., bad params, uninitialized context)? */
+#define Skein_Assert(x,retCode)/* default: ignore all Asserts, for performance */
+#define Skein_assert(x)
+#elif defined(SKEIN_ASSERT)
+#include <assert.h>
+#define Skein_Assert(x,retCode) assert(x)
+#define Skein_assert(x) assert(x)
+#else
+#include <assert.h>
+#define Skein_Assert(x,retCode) { if (!(x)) return retCode; } /* caller error */
+#define Skein_assert(x) assert(x) /* internal error */
+#endif
+
+/*****************************************************************
+** Skein block function constants (shared across Ref and Opt code)
+******************************************************************/
+enum
+ {
+ /* Skein_256 round rotation constants */
+ R_256_0_0=14, R_256_0_1=16,
+ R_256_1_0=52, R_256_1_1=57,
+ R_256_2_0=23, R_256_2_1=40,
+ R_256_3_0= 5, R_256_3_1=37,
+ R_256_4_0=25, R_256_4_1=33,
+ R_256_5_0=46, R_256_5_1=12,
+ R_256_6_0=58, R_256_6_1=22,
+ R_256_7_0=32, R_256_7_1=32,
+
+ /* Skein_512 round rotation constants */
+ R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37,
+ R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42,
+ R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39,
+ R_512_3_0=44, R_512_3_1= 9, R_512_3_2=54, R_512_3_3=56,
+ R_512_4_0=39, R_512_4_1=30, R_512_4_2=34, R_512_4_3=24,
+ R_512_5_0=13, R_512_5_1=50, R_512_5_2=10, R_512_5_3=17,
+ R_512_6_0=25, R_512_6_1=29, R_512_6_2=39, R_512_6_3=43,
+ R_512_7_0= 8, R_512_7_1=35, R_512_7_2=56, R_512_7_3=22,
+
+ /* Skein1024 round rotation constants */
+ R1024_0_0=24, R1024_0_1=13, R1024_0_2= 8, R1024_0_3=47, R1024_0_4= 8, R1024_0_5=17, R1024_0_6=22, R1024_0_7=37,
+ R1024_1_0=38, R1024_1_1=19, R1024_1_2=10, R1024_1_3=55, R1024_1_4=49, R1024_1_5=18, R1024_1_6=23, R1024_1_7=52,
+ R1024_2_0=33, R1024_2_1= 4, R1024_2_2=51, R1024_2_3=13, R1024_2_4=34, R1024_2_5=41, R1024_2_6=59, R1024_2_7=17,
+ R1024_3_0= 5, R1024_3_1=20, R1024_3_2=48, R1024_3_3=41, R1024_3_4=47, R1024_3_5=28, R1024_3_6=16, R1024_3_7=25,
+ R1024_4_0=41, R1024_4_1= 9, R1024_4_2=37, R1024_4_3=31, R1024_4_4=12, R1024_4_5=47, R1024_4_6=44, R1024_4_7=30,
+ R1024_5_0=16, R1024_5_1=34, R1024_5_2=56, R1024_5_3=51, R1024_5_4= 4, R1024_5_5=53, R1024_5_6=42, R1024_5_7=41,
+ R1024_6_0=31, R1024_6_1=44, R1024_6_2=47, R1024_6_3=46, R1024_6_4=19, R1024_6_5=42, R1024_6_6=44, R1024_6_7=25,
+ R1024_7_0= 9, R1024_7_1=48, R1024_7_2=35, R1024_7_3=52, R1024_7_4=23, R1024_7_5=31, R1024_7_6=37, R1024_7_7=20
+ };
+
+#ifndef SKEIN_ROUNDS
+#define SKEIN_256_ROUNDS_TOTAL (72) /* number of rounds for the different block sizes */
+#define SKEIN_512_ROUNDS_TOTAL (72)
+#define SKEIN1024_ROUNDS_TOTAL (80)
+#else /* allow command-line define in range 8*(5..14) */
+#define SKEIN_256_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS/100) + 5) % 10) + 5))
+#define SKEIN_512_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS/ 10) + 5) % 10) + 5))
+#define SKEIN1024_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS ) + 5) % 10) + 5))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Pull in FreeBSD specific shims */
+#include "skein_freebsd.h"
+
+#endif /* ifndef _SKEIN_H_ */
diff --git a/sys/crypto/skein/skein_block.c b/sys/crypto/skein/skein_block.c
new file mode 100644
index 0000000..c924550
--- /dev/null
+++ b/sys/crypto/skein/skein_block.c
@@ -0,0 +1,706 @@
+/***********************************************************************
+**
+** Implementation of the Skein block functions.
+**
+** Source code author: Doug Whiting, 2008.
+**
+** This algorithm and source code is released to the public domain.
+**
+** Compile-time switches:
+**
+** SKEIN_USE_ASM -- set bits (256/512/1024) to select which
+** versions use ASM code for block processing
+** [default: use C for all block sizes]
+**
+************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+#include <sys/types.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+
+#include "skein.h"
+
+#ifndef SKEIN_USE_ASM
+#define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */
+#endif
+
+#ifndef SKEIN_LOOP
+#define SKEIN_LOOP 001 /* default: unroll 256 and 512, but not 1024 */
+#endif
+
+#define BLK_BITS (WCNT*64) /* some useful definitions for code here */
+#define KW_TWK_BASE (0)
+#define KW_KEY_BASE (3)
+#define ks (kw + KW_KEY_BASE)
+#define ts (kw + KW_TWK_BASE)
+
+#ifdef SKEIN_DEBUG
+#define DebugSaveTweak(ctx) { ctx->h.T[0] = ts[0]; ctx->h.T[1] = ts[1]; }
+#else
+#define DebugSaveTweak(ctx)
+#endif
+
+/*****************************************************************/
+/* functions to process blkCnt (nonzero) full block(s) of data. */
+void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
+void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
+void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
+
+/***************************** Skein_256 ******************************/
+#if !(SKEIN_USE_ASM & 256)
+void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd)
+ { /* do it in C */
+ enum
+ {
+ WCNT = SKEIN_256_STATE_WORDS
+ };
+#undef RCNT
+#define RCNT (SKEIN_256_ROUNDS_TOTAL/8)
+
+#ifdef SKEIN_LOOP /* configure how much to unroll the loop */
+#define SKEIN_UNROLL_256 (((SKEIN_LOOP)/100)%10)
+#else
+#define SKEIN_UNROLL_256 (0)
+#endif
+
+#if SKEIN_UNROLL_256
+#if (RCNT % SKEIN_UNROLL_256)
+#error "Invalid SKEIN_UNROLL_256" /* sanity check on unroll count */
+#endif
+ size_t r;
+ u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/
+#else
+ u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
+#endif
+ u64b_t X0,X1,X2,X3; /* local copy of context vars, for speed */
+ u64b_t w [WCNT]; /* local copy of input block */
+#ifdef SKEIN_DEBUG
+ const u64b_t *Xptr[4]; /* use for debugging (help compiler put Xn in registers) */
+ Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3;
+#endif
+ Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
+ ts[0] = ctx->h.T[0];
+ ts[1] = ctx->h.T[1];
+ do {
+ /* this implementation only supports 2**64 input bytes (no carry out here) */
+ ts[0] += byteCntAdd; /* update processed length */
+
+ /* precompute the key schedule for this block */
+ ks[0] = ctx->X[0];
+ ks[1] = ctx->X[1];
+ ks[2] = ctx->X[2];
+ ks[3] = ctx->X[3];
+ ks[4] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ SKEIN_KS_PARITY;
+
+ ts[2] = ts[0] ^ ts[1];
+
+ Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */
+ DebugSaveTweak(ctx);
+ Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts);
+
+ X0 = w[0] + ks[0]; /* do the first full key injection */
+ X1 = w[1] + ks[1] + ts[0];
+ X2 = w[2] + ks[2] + ts[1];
+ X3 = w[3] + ks[3];
+
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr); /* show starting state values */
+
+ blkPtr += SKEIN_256_BLOCK_BYTES;
+
+ /* run the rounds */
+
+#define Round256(p0,p1,p2,p3,ROT,rNum) \
+ X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \
+ X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \
+
+#if SKEIN_UNROLL_256 == 0
+#define R256(p0,p1,p2,p3,ROT,rNum) /* fully unrolled */ \
+ Round256(p0,p1,p2,p3,ROT,rNum) \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr);
+
+#define I256(R) \
+ X0 += ks[((R)+1) % 5]; /* inject the key schedule value */ \
+ X1 += ks[((R)+2) % 5] + ts[((R)+1) % 3]; \
+ X2 += ks[((R)+3) % 5] + ts[((R)+2) % 3]; \
+ X3 += ks[((R)+4) % 5] + (R)+1; \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
+#else /* looping version */
+#define R256(p0,p1,p2,p3,ROT,rNum) \
+ Round256(p0,p1,p2,p3,ROT,rNum) \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr);
+
+#define I256(R) \
+ X0 += ks[r+(R)+0]; /* inject the key schedule value */ \
+ X1 += ks[r+(R)+1] + ts[r+(R)+0]; \
+ X2 += ks[r+(R)+2] + ts[r+(R)+1]; \
+ X3 += ks[r+(R)+3] + r+(R) ; \
+ ks[r + (R)+4 ] = ks[r+(R)-1]; /* rotate key schedule */\
+ ts[r + (R)+2 ] = ts[r+(R)-1]; \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
+
+ for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_256) /* loop thru it */
+#endif
+ {
+#define R256_8_rounds(R) \
+ R256(0,1,2,3,R_256_0,8*(R) + 1); \
+ R256(0,3,2,1,R_256_1,8*(R) + 2); \
+ R256(0,1,2,3,R_256_2,8*(R) + 3); \
+ R256(0,3,2,1,R_256_3,8*(R) + 4); \
+ I256(2*(R)); \
+ R256(0,1,2,3,R_256_4,8*(R) + 5); \
+ R256(0,3,2,1,R_256_5,8*(R) + 6); \
+ R256(0,1,2,3,R_256_6,8*(R) + 7); \
+ R256(0,3,2,1,R_256_7,8*(R) + 8); \
+ I256(2*(R)+1);
+
+ R256_8_rounds( 0);
+
+#define R256_Unroll_R(NN) ((SKEIN_UNROLL_256 == 0 && SKEIN_256_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_256 > (NN)))
+
+ #if R256_Unroll_R( 1)
+ R256_8_rounds( 1);
+ #endif
+ #if R256_Unroll_R( 2)
+ R256_8_rounds( 2);
+ #endif
+ #if R256_Unroll_R( 3)
+ R256_8_rounds( 3);
+ #endif
+ #if R256_Unroll_R( 4)
+ R256_8_rounds( 4);
+ #endif
+ #if R256_Unroll_R( 5)
+ R256_8_rounds( 5);
+ #endif
+ #if R256_Unroll_R( 6)
+ R256_8_rounds( 6);
+ #endif
+ #if R256_Unroll_R( 7)
+ R256_8_rounds( 7);
+ #endif
+ #if R256_Unroll_R( 8)
+ R256_8_rounds( 8);
+ #endif
+ #if R256_Unroll_R( 9)
+ R256_8_rounds( 9);
+ #endif
+ #if R256_Unroll_R(10)
+ R256_8_rounds(10);
+ #endif
+ #if R256_Unroll_R(11)
+ R256_8_rounds(11);
+ #endif
+ #if R256_Unroll_R(12)
+ R256_8_rounds(12);
+ #endif
+ #if R256_Unroll_R(13)
+ R256_8_rounds(13);
+ #endif
+ #if R256_Unroll_R(14)
+ R256_8_rounds(14);
+ #endif
+ #if (SKEIN_UNROLL_256 > 14)
+#error "need more unrolling in Skein_256_Process_Block"
+ #endif
+ }
+ /* do the final "feedforward" xor, update context chaining vars */
+ ctx->X[0] = X0 ^ w[0];
+ ctx->X[1] = X1 ^ w[1];
+ ctx->X[2] = X2 ^ w[2];
+ ctx->X[3] = X3 ^ w[3];
+
+ Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X);
+
+ ts[1] &= ~SKEIN_T1_FLAG_FIRST;
+ }
+ while (--blkCnt);
+ ctx->h.T[0] = ts[0];
+ ctx->h.T[1] = ts[1];
+ }
+
+#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
+size_t Skein_256_Process_Block_CodeSize(void)
+ {
+ return ((u08b_t *) Skein_256_Process_Block_CodeSize) -
+ ((u08b_t *) Skein_256_Process_Block);
+ }
+uint_t Skein_256_Unroll_Cnt(void)
+ {
+ return SKEIN_UNROLL_256;
+ }
+#endif
+#endif
+
+/***************************** Skein_512 ******************************/
+#if !(SKEIN_USE_ASM & 512)
+void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd)
+ { /* do it in C */
+ enum
+ {
+ WCNT = SKEIN_512_STATE_WORDS
+ };
+#undef RCNT
+#define RCNT (SKEIN_512_ROUNDS_TOTAL/8)
+
+#ifdef SKEIN_LOOP /* configure how much to unroll the loop */
+#define SKEIN_UNROLL_512 (((SKEIN_LOOP)/10)%10)
+#else
+#define SKEIN_UNROLL_512 (0)
+#endif
+
+#if SKEIN_UNROLL_512
+#if (RCNT % SKEIN_UNROLL_512)
+#error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */
+#endif
+ size_t r;
+ u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/
+#else
+ u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
+#endif
+ u64b_t X0,X1,X2,X3,X4,X5,X6,X7; /* local copy of vars, for speed */
+ u64b_t w [WCNT]; /* local copy of input block */
+#ifdef SKEIN_DEBUG
+ const u64b_t *Xptr[8]; /* use for debugging (help compiler put Xn in registers) */
+ Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3;
+ Xptr[4] = &X4; Xptr[5] = &X5; Xptr[6] = &X6; Xptr[7] = &X7;
+#endif
+
+ Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
+ ts[0] = ctx->h.T[0];
+ ts[1] = ctx->h.T[1];
+ do {
+ /* this implementation only supports 2**64 input bytes (no carry out here) */
+ ts[0] += byteCntAdd; /* update processed length */
+
+ /* precompute the key schedule for this block */
+ ks[0] = ctx->X[0];
+ ks[1] = ctx->X[1];
+ ks[2] = ctx->X[2];
+ ks[3] = ctx->X[3];
+ ks[4] = ctx->X[4];
+ ks[5] = ctx->X[5];
+ ks[6] = ctx->X[6];
+ ks[7] = ctx->X[7];
+ ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^
+ ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY;
+
+ ts[2] = ts[0] ^ ts[1];
+
+ Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */
+ DebugSaveTweak(ctx);
+ Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts);
+
+ X0 = w[0] + ks[0]; /* do the first full key injection */
+ X1 = w[1] + ks[1];
+ X2 = w[2] + ks[2];
+ X3 = w[3] + ks[3];
+ X4 = w[4] + ks[4];
+ X5 = w[5] + ks[5] + ts[0];
+ X6 = w[6] + ks[6] + ts[1];
+ X7 = w[7] + ks[7];
+
+ blkPtr += SKEIN_512_BLOCK_BYTES;
+
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr);
+ /* run the rounds */
+#define Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
+ X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \
+ X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \
+ X##p4 += X##p5; X##p5 = RotL_64(X##p5,ROT##_2); X##p5 ^= X##p4; \
+ X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \
+
+#if SKEIN_UNROLL_512 == 0
+#define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) /* unrolled */ \
+ Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr);
+
+#define I512(R) \
+ X0 += ks[((R)+1) % 9]; /* inject the key schedule value */ \
+ X1 += ks[((R)+2) % 9]; \
+ X2 += ks[((R)+3) % 9]; \
+ X3 += ks[((R)+4) % 9]; \
+ X4 += ks[((R)+5) % 9]; \
+ X5 += ks[((R)+6) % 9] + ts[((R)+1) % 3]; \
+ X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \
+ X7 += ks[((R)+8) % 9] + (R)+1; \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
+#else /* looping version */
+#define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
+ Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr);
+
+#define I512(R) \
+ X0 += ks[r+(R)+0]; /* inject the key schedule value */ \
+ X1 += ks[r+(R)+1]; \
+ X2 += ks[r+(R)+2]; \
+ X3 += ks[r+(R)+3]; \
+ X4 += ks[r+(R)+4]; \
+ X5 += ks[r+(R)+5] + ts[r+(R)+0]; \
+ X6 += ks[r+(R)+6] + ts[r+(R)+1]; \
+ X7 += ks[r+(R)+7] + r+(R) ; \
+ ks[r + (R)+8] = ks[r+(R)-1]; /* rotate key schedule */ \
+ ts[r + (R)+2] = ts[r+(R)-1]; \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
+
+ for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_512) /* loop thru it */
+#endif /* end of looped code definitions */
+ {
+#define R512_8_rounds(R) /* do 8 full rounds */ \
+ R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \
+ R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \
+ R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \
+ R512(6,1,0,7,2,5,4,3,R_512_3,8*(R)+ 4); \
+ I512(2*(R)); \
+ R512(0,1,2,3,4,5,6,7,R_512_4,8*(R)+ 5); \
+ R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \
+ R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \
+ R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \
+ I512(2*(R)+1); /* and key injection */
+
+ R512_8_rounds( 0);
+
+#define R512_Unroll_R(NN) ((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_512 > (NN)))
+
+ #if R512_Unroll_R( 1)
+ R512_8_rounds( 1);
+ #endif
+ #if R512_Unroll_R( 2)
+ R512_8_rounds( 2);
+ #endif
+ #if R512_Unroll_R( 3)
+ R512_8_rounds( 3);
+ #endif
+ #if R512_Unroll_R( 4)
+ R512_8_rounds( 4);
+ #endif
+ #if R512_Unroll_R( 5)
+ R512_8_rounds( 5);
+ #endif
+ #if R512_Unroll_R( 6)
+ R512_8_rounds( 6);
+ #endif
+ #if R512_Unroll_R( 7)
+ R512_8_rounds( 7);
+ #endif
+ #if R512_Unroll_R( 8)
+ R512_8_rounds( 8);
+ #endif
+ #if R512_Unroll_R( 9)
+ R512_8_rounds( 9);
+ #endif
+ #if R512_Unroll_R(10)
+ R512_8_rounds(10);
+ #endif
+ #if R512_Unroll_R(11)
+ R512_8_rounds(11);
+ #endif
+ #if R512_Unroll_R(12)
+ R512_8_rounds(12);
+ #endif
+ #if R512_Unroll_R(13)
+ R512_8_rounds(13);
+ #endif
+ #if R512_Unroll_R(14)
+ R512_8_rounds(14);
+ #endif
+ #if (SKEIN_UNROLL_512 > 14)
+#error "need more unrolling in Skein_512_Process_Block"
+ #endif
+ }
+
+ /* do the final "feedforward" xor, update context chaining vars */
+ ctx->X[0] = X0 ^ w[0];
+ ctx->X[1] = X1 ^ w[1];
+ ctx->X[2] = X2 ^ w[2];
+ ctx->X[3] = X3 ^ w[3];
+ ctx->X[4] = X4 ^ w[4];
+ ctx->X[5] = X5 ^ w[5];
+ ctx->X[6] = X6 ^ w[6];
+ ctx->X[7] = X7 ^ w[7];
+ Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X);
+
+ ts[1] &= ~SKEIN_T1_FLAG_FIRST;
+ }
+ while (--blkCnt);
+ ctx->h.T[0] = ts[0];
+ ctx->h.T[1] = ts[1];
+ }
+
+#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
+size_t Skein_512_Process_Block_CodeSize(void)
+ {
+ return ((u08b_t *) Skein_512_Process_Block_CodeSize) -
+ ((u08b_t *) Skein_512_Process_Block);
+ }
+uint_t Skein_512_Unroll_Cnt(void)
+ {
+ return SKEIN_UNROLL_512;
+ }
+#endif
+#endif
+
+/***************************** Skein1024 ******************************/
+#if !(SKEIN_USE_ASM & 1024)
+void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd)
+ { /* do it in C, always looping (unrolled is bigger AND slower!) */
+ enum
+ {
+ WCNT = SKEIN1024_STATE_WORDS
+ };
+#undef RCNT
+#define RCNT (SKEIN1024_ROUNDS_TOTAL/8)
+
+#ifdef SKEIN_LOOP /* configure how much to unroll the loop */
+#define SKEIN_UNROLL_1024 ((SKEIN_LOOP)%10)
+#else
+#define SKEIN_UNROLL_1024 (0)
+#endif
+
+#if (SKEIN_UNROLL_1024 != 0)
+#if (RCNT % SKEIN_UNROLL_1024)
+#error "Invalid SKEIN_UNROLL_1024" /* sanity check on unroll count */
+#endif
+ size_t r;
+ u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/
+#else
+ u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
+#endif
+
+ u64b_t X00,X01,X02,X03,X04,X05,X06,X07, /* local copy of vars, for speed */
+ X08,X09,X10,X11,X12,X13,X14,X15;
+ u64b_t w [WCNT]; /* local copy of input block */
+#ifdef SKEIN_DEBUG
+ const u64b_t *Xptr[16]; /* use for debugging (help compiler put Xn in registers) */
+ Xptr[ 0] = &X00; Xptr[ 1] = &X01; Xptr[ 2] = &X02; Xptr[ 3] = &X03;
+ Xptr[ 4] = &X04; Xptr[ 5] = &X05; Xptr[ 6] = &X06; Xptr[ 7] = &X07;
+ Xptr[ 8] = &X08; Xptr[ 9] = &X09; Xptr[10] = &X10; Xptr[11] = &X11;
+ Xptr[12] = &X12; Xptr[13] = &X13; Xptr[14] = &X14; Xptr[15] = &X15;
+#endif
+
+ Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
+ ts[0] = ctx->h.T[0];
+ ts[1] = ctx->h.T[1];
+ do {
+ /* this implementation only supports 2**64 input bytes (no carry out here) */
+ ts[0] += byteCntAdd; /* update processed length */
+
+ /* precompute the key schedule for this block */
+ ks[ 0] = ctx->X[ 0];
+ ks[ 1] = ctx->X[ 1];
+ ks[ 2] = ctx->X[ 2];
+ ks[ 3] = ctx->X[ 3];
+ ks[ 4] = ctx->X[ 4];
+ ks[ 5] = ctx->X[ 5];
+ ks[ 6] = ctx->X[ 6];
+ ks[ 7] = ctx->X[ 7];
+ ks[ 8] = ctx->X[ 8];
+ ks[ 9] = ctx->X[ 9];
+ ks[10] = ctx->X[10];
+ ks[11] = ctx->X[11];
+ ks[12] = ctx->X[12];
+ ks[13] = ctx->X[13];
+ ks[14] = ctx->X[14];
+ ks[15] = ctx->X[15];
+ ks[16] = ks[ 0] ^ ks[ 1] ^ ks[ 2] ^ ks[ 3] ^
+ ks[ 4] ^ ks[ 5] ^ ks[ 6] ^ ks[ 7] ^
+ ks[ 8] ^ ks[ 9] ^ ks[10] ^ ks[11] ^
+ ks[12] ^ ks[13] ^ ks[14] ^ ks[15] ^ SKEIN_KS_PARITY;
+
+ ts[2] = ts[0] ^ ts[1];
+
+ Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */
+ DebugSaveTweak(ctx);
+ Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts);
+
+ X00 = w[ 0] + ks[ 0]; /* do the first full key injection */
+ X01 = w[ 1] + ks[ 1];
+ X02 = w[ 2] + ks[ 2];
+ X03 = w[ 3] + ks[ 3];
+ X04 = w[ 4] + ks[ 4];
+ X05 = w[ 5] + ks[ 5];
+ X06 = w[ 6] + ks[ 6];
+ X07 = w[ 7] + ks[ 7];
+ X08 = w[ 8] + ks[ 8];
+ X09 = w[ 9] + ks[ 9];
+ X10 = w[10] + ks[10];
+ X11 = w[11] + ks[11];
+ X12 = w[12] + ks[12];
+ X13 = w[13] + ks[13] + ts[0];
+ X14 = w[14] + ks[14] + ts[1];
+ X15 = w[15] + ks[15];
+
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr);
+
+#define Round1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rNum) \
+ X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \
+ X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \
+ X##p4 += X##p5; X##p5 = RotL_64(X##p5,ROT##_2); X##p5 ^= X##p4; \
+ X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \
+ X##p8 += X##p9; X##p9 = RotL_64(X##p9,ROT##_4); X##p9 ^= X##p8; \
+ X##pA += X##pB; X##pB = RotL_64(X##pB,ROT##_5); X##pB ^= X##pA; \
+ X##pC += X##pD; X##pD = RotL_64(X##pD,ROT##_6); X##pD ^= X##pC; \
+ X##pE += X##pF; X##pF = RotL_64(X##pF,ROT##_7); X##pF ^= X##pE; \
+
+#if SKEIN_UNROLL_1024 == 0
+#define R1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \
+ Round1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rn,Xptr);
+
+#define I1024(R) \
+ X00 += ks[((R)+ 1) % 17]; /* inject the key schedule value */ \
+ X01 += ks[((R)+ 2) % 17]; \
+ X02 += ks[((R)+ 3) % 17]; \
+ X03 += ks[((R)+ 4) % 17]; \
+ X04 += ks[((R)+ 5) % 17]; \
+ X05 += ks[((R)+ 6) % 17]; \
+ X06 += ks[((R)+ 7) % 17]; \
+ X07 += ks[((R)+ 8) % 17]; \
+ X08 += ks[((R)+ 9) % 17]; \
+ X09 += ks[((R)+10) % 17]; \
+ X10 += ks[((R)+11) % 17]; \
+ X11 += ks[((R)+12) % 17]; \
+ X12 += ks[((R)+13) % 17]; \
+ X13 += ks[((R)+14) % 17] + ts[((R)+1) % 3]; \
+ X14 += ks[((R)+15) % 17] + ts[((R)+2) % 3]; \
+ X15 += ks[((R)+16) % 17] + (R)+1; \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
+#else /* looping version */
+#define R1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \
+ Round1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rn,Xptr);
+
+#define I1024(R) \
+ X00 += ks[r+(R)+ 0]; /* inject the key schedule value */ \
+ X01 += ks[r+(R)+ 1]; \
+ X02 += ks[r+(R)+ 2]; \
+ X03 += ks[r+(R)+ 3]; \
+ X04 += ks[r+(R)+ 4]; \
+ X05 += ks[r+(R)+ 5]; \
+ X06 += ks[r+(R)+ 6]; \
+ X07 += ks[r+(R)+ 7]; \
+ X08 += ks[r+(R)+ 8]; \
+ X09 += ks[r+(R)+ 9]; \
+ X10 += ks[r+(R)+10]; \
+ X11 += ks[r+(R)+11]; \
+ X12 += ks[r+(R)+12]; \
+ X13 += ks[r+(R)+13] + ts[r+(R)+0]; \
+ X14 += ks[r+(R)+14] + ts[r+(R)+1]; \
+ X15 += ks[r+(R)+15] + r+(R) ; \
+ ks[r + (R)+16] = ks[r+(R)-1]; /* rotate key schedule */ \
+ ts[r + (R)+ 2] = ts[r+(R)-1]; \
+ Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
+
+ for (r=1;r <= 2*RCNT;r+=2*SKEIN_UNROLL_1024) /* loop thru it */
+#endif
+ {
+#define R1024_8_rounds(R) /* do 8 full rounds */ \
+ R1024(00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,R1024_0,8*(R) + 1); \
+ R1024(00,09,02,13,06,11,04,15,10,07,12,03,14,05,08,01,R1024_1,8*(R) + 2); \
+ R1024(00,07,02,05,04,03,06,01,12,15,14,13,08,11,10,09,R1024_2,8*(R) + 3); \
+ R1024(00,15,02,11,06,13,04,09,14,01,08,05,10,03,12,07,R1024_3,8*(R) + 4); \
+ I1024(2*(R)); \
+ R1024(00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,R1024_4,8*(R) + 5); \
+ R1024(00,09,02,13,06,11,04,15,10,07,12,03,14,05,08,01,R1024_5,8*(R) + 6); \
+ R1024(00,07,02,05,04,03,06,01,12,15,14,13,08,11,10,09,R1024_6,8*(R) + 7); \
+ R1024(00,15,02,11,06,13,04,09,14,01,08,05,10,03,12,07,R1024_7,8*(R) + 8); \
+ I1024(2*(R)+1);
+
+ R1024_8_rounds( 0);
+
+#define R1024_Unroll_R(NN) ((SKEIN_UNROLL_1024 == 0 && SKEIN1024_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_1024 > (NN)))
+
+ #if R1024_Unroll_R( 1)
+ R1024_8_rounds( 1);
+ #endif
+ #if R1024_Unroll_R( 2)
+ R1024_8_rounds( 2);
+ #endif
+ #if R1024_Unroll_R( 3)
+ R1024_8_rounds( 3);
+ #endif
+ #if R1024_Unroll_R( 4)
+ R1024_8_rounds( 4);
+ #endif
+ #if R1024_Unroll_R( 5)
+ R1024_8_rounds( 5);
+ #endif
+ #if R1024_Unroll_R( 6)
+ R1024_8_rounds( 6);
+ #endif
+ #if R1024_Unroll_R( 7)
+ R1024_8_rounds( 7);
+ #endif
+ #if R1024_Unroll_R( 8)
+ R1024_8_rounds( 8);
+ #endif
+ #if R1024_Unroll_R( 9)
+ R1024_8_rounds( 9);
+ #endif
+ #if R1024_Unroll_R(10)
+ R1024_8_rounds(10);
+ #endif
+ #if R1024_Unroll_R(11)
+ R1024_8_rounds(11);
+ #endif
+ #if R1024_Unroll_R(12)
+ R1024_8_rounds(12);
+ #endif
+ #if R1024_Unroll_R(13)
+ R1024_8_rounds(13);
+ #endif
+ #if R1024_Unroll_R(14)
+ R1024_8_rounds(14);
+ #endif
+ #if (SKEIN_UNROLL_1024 > 14)
+#error "need more unrolling in Skein_1024_Process_Block"
+ #endif
+ }
+ /* do the final "feedforward" xor, update context chaining vars */
+
+ ctx->X[ 0] = X00 ^ w[ 0];
+ ctx->X[ 1] = X01 ^ w[ 1];
+ ctx->X[ 2] = X02 ^ w[ 2];
+ ctx->X[ 3] = X03 ^ w[ 3];
+ ctx->X[ 4] = X04 ^ w[ 4];
+ ctx->X[ 5] = X05 ^ w[ 5];
+ ctx->X[ 6] = X06 ^ w[ 6];
+ ctx->X[ 7] = X07 ^ w[ 7];
+ ctx->X[ 8] = X08 ^ w[ 8];
+ ctx->X[ 9] = X09 ^ w[ 9];
+ ctx->X[10] = X10 ^ w[10];
+ ctx->X[11] = X11 ^ w[11];
+ ctx->X[12] = X12 ^ w[12];
+ ctx->X[13] = X13 ^ w[13];
+ ctx->X[14] = X14 ^ w[14];
+ ctx->X[15] = X15 ^ w[15];
+
+ Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X);
+
+ ts[1] &= ~SKEIN_T1_FLAG_FIRST;
+ blkPtr += SKEIN1024_BLOCK_BYTES;
+ }
+ while (--blkCnt);
+ ctx->h.T[0] = ts[0];
+ ctx->h.T[1] = ts[1];
+ }
+
+#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
+size_t Skein1024_Process_Block_CodeSize(void)
+ {
+ return ((u08b_t *) Skein1024_Process_Block_CodeSize) -
+ ((u08b_t *) Skein1024_Process_Block);
+ }
+uint_t Skein1024_Unroll_Cnt(void)
+ {
+ return SKEIN_UNROLL_1024;
+ }
+#endif
+#endif
diff --git a/sys/crypto/skein/skein_debug.c b/sys/crypto/skein/skein_debug.c
new file mode 100644
index 0000000..fac5038
--- /dev/null
+++ b/sys/crypto/skein/skein_debug.c
@@ -0,0 +1,247 @@
+/***********************************************************************
+**
+** Debug output functions for Skein hashing.
+**
+** Source code author: Doug Whiting, 2008.
+**
+** This algorithm and source code is released to the public domain.
+**
+************************************************************************/
+#include <stdio.h>
+
+#ifdef SKEIN_DEBUG /* only instantiate this code if SKEIN_DEBUG is on */
+#include "skein.h"
+
+static const char INDENT[] = " "; /* how much to indent on new line */
+
+uint_t skein_DebugFlag = 0; /* off by default. Must be set externally */
+
+static void Show64_step(size_t cnt,const u64b_t *X,size_t step)
+ {
+ size_t i,j;
+ for (i=j=0;i < cnt;i++,j+=step)
+ {
+ if (i % 4 == 0) printf(INDENT);
+ printf(" %08X.%08X ",(uint_32t)(X[j] >> 32),(uint_32t)X[j]);
+ if (i % 4 == 3 || i==cnt-1) printf("\n");
+ fflush(stdout);
+ }
+ }
+
+#define Show64(cnt,X) Show64_step(cnt,X,1)
+
+static void Show64_flag(size_t cnt,const u64b_t *X)
+ {
+ size_t xptr = (size_t) X;
+ size_t step = (xptr & 1) ? 2 : 1;
+ if (step != 1)
+ {
+ X = (const u64b_t *) (xptr & ~1);
+ }
+ Show64_step(cnt,X,step);
+ }
+
+static void Show08(size_t cnt,const u08b_t *b)
+ {
+ size_t i;
+ for (i=0;i < cnt;i++)
+ {
+ if (i %16 == 0) printf(INDENT);
+ else if (i % 4 == 0) printf(" ");
+ printf(" %02X",b[i]);
+ if (i %16 == 15 || i==cnt-1) printf("\n");
+ fflush(stdout);
+ }
+ }
+
+static const char *AlgoHeader(uint_t bits)
+ {
+ if (skein_DebugFlag & SKEIN_DEBUG_THREEFISH)
+ switch (bits)
+ {
+ case 256: return ":Threefish-256: ";
+ case 512: return ":Threefish-512: ";
+ case 1024: return ":Threefish-1024:";
+ }
+ else
+ switch (bits)
+ {
+ case 256: return ":Skein-256: ";
+ case 512: return ":Skein-512: ";
+ case 1024: return ":Skein-1024:";
+ }
+ return NULL;
+ }
+
+void Skein_Show_Final(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t cnt,const u08b_t *outPtr)
+ {
+ if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
+ if (skein_DebugFlag & SKEIN_DEBUG_FINAL)
+ {
+ printf("\n%s Final output=\n",AlgoHeader(bits));
+ Show08(cnt,outPtr);
+ printf(" ++++++++++\n");
+ fflush(stdout);
+ }
+ }
+
+/* show state after a round (or "pseudo-round") */
+void Skein_Show_Round(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t r,const u64b_t *X)
+ {
+ static uint_t injectNum=0; /* not multi-thread safe! */
+
+ if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
+ if (skein_DebugFlag)
+ {
+ if (r >= SKEIN_RND_SPECIAL)
+ { /* a key injection (or feedforward) point */
+ injectNum = (r == SKEIN_RND_KEY_INITIAL) ? 0 : injectNum+1;
+ if ( skein_DebugFlag & SKEIN_DEBUG_INJECT ||
+ ((skein_DebugFlag & SKEIN_DEBUG_FINAL) && r == SKEIN_RND_FEED_FWD))
+ {
+ printf("\n%s",AlgoHeader(bits));
+ switch (r)
+ {
+ case SKEIN_RND_KEY_INITIAL:
+ printf(" [state after initial key injection]");
+ break;
+ case SKEIN_RND_KEY_INJECT:
+ printf(" [state after key injection #%02d]",injectNum);
+ break;
+ case SKEIN_RND_FEED_FWD:
+ printf(" [state after plaintext feedforward]");
+ injectNum = 0;
+ break;
+ }
+ printf("=\n");
+ Show64(bits/64,X);
+ if (r== SKEIN_RND_FEED_FWD)
+ printf(" ----------\n");
+ }
+ }
+ else if (skein_DebugFlag & SKEIN_DEBUG_ROUNDS)
+ {
+ uint_t j;
+ u64b_t p[SKEIN_MAX_STATE_WORDS];
+ const u08b_t *perm;
+ const static u08b_t PERM_256 [4][ 4] = { { 0,1,2,3 }, { 0,3,2,1 }, { 0,1,2,3 }, { 0,3,2,1 } };
+ const static u08b_t PERM_512 [4][ 8] = { { 0,1,2,3,4,5,6,7 },
+ { 2,1,4,7,6,5,0,3 },
+ { 4,1,6,3,0,5,2,7 },
+ { 6,1,0,7,2,5,4,3 }
+ };
+ const static u08b_t PERM_1024[4][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 },
+ { 0, 9, 2,13, 6,11, 4,15,10, 7,12, 3,14, 5, 8, 1 },
+ { 0, 7, 2, 5, 4, 3, 6, 1,12,15,14,13, 8,11,10, 9 },
+ { 0,15, 2,11, 6,13, 4, 9,14, 1, 8, 5,10, 3,12, 7 }
+ };
+
+ if ((skein_DebugFlag & SKEIN_DEBUG_PERMUTE) && (r & 3))
+ {
+ printf("\n%s [state after round %2d (permuted)]=\n",AlgoHeader(bits),(int)r);
+ switch (bits)
+ {
+ case 256: perm = PERM_256 [r&3]; break;
+ case 512: perm = PERM_512 [r&3]; break;
+ default: perm = PERM_1024[r&3]; break;
+ }
+ for (j=0;j<bits/64;j++)
+ p[j] = X[perm[j]];
+ Show64(bits/64,p);
+ }
+ else
+ {
+ printf("\n%s [state after round %2d]=\n",AlgoHeader(bits),(int)r);
+ Show64(bits/64,X);
+ }
+ }
+ }
+ }
+
+/* show state after a round (or "pseudo-round"), given a list of pointers */
+void Skein_Show_R_Ptr(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t r,const u64b_t *X_ptr[])
+ {
+ uint_t i;
+ u64b_t X[SKEIN_MAX_STATE_WORDS];
+
+ for (i=0;i<bits/64;i++) /* copy over the words */
+ X[i] = X_ptr[i][0];
+ Skein_Show_Round(bits,h,r,X);
+ }
+
+
+/* show the state at the start of a block */
+void Skein_Show_Block(uint_t bits,const Skein_Ctxt_Hdr_t *h,const u64b_t *X,const u08b_t *blkPtr,
+ const u64b_t *wPtr, const u64b_t *ksPtr, const u64b_t *tsPtr)
+ {
+ uint_t n;
+ if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
+ if (skein_DebugFlag)
+ {
+ if (skein_DebugFlag & SKEIN_DEBUG_HDR)
+ {
+ printf("\n%s Block: outBits=%4d. T0=%06X.",AlgoHeader(bits),(uint_t) h->hashBitLen,(uint_t)h->T[0]);
+ printf(" Type=");
+ n = (uint_t) ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) >> SKEIN_T1_POS_BLK_TYPE);
+ switch (n)
+ {
+ case SKEIN_BLK_TYPE_KEY: printf("KEY. "); break;
+ case SKEIN_BLK_TYPE_CFG: printf("CFG. "); break;
+ case SKEIN_BLK_TYPE_PERS: printf("PERS."); break;
+ case SKEIN_BLK_TYPE_PK : printf("PK. "); break;
+ case SKEIN_BLK_TYPE_KDF: printf("KDF. "); break;
+ case SKEIN_BLK_TYPE_MSG: printf("MSG. "); break;
+ case SKEIN_BLK_TYPE_OUT: printf("OUT. "); break;
+ default: printf("0x%02X.",n); break;
+ }
+ printf(" Flags=");
+ printf((h->T[1] & SKEIN_T1_FLAG_FIRST) ? " First":" ");
+ printf((h->T[1] & SKEIN_T1_FLAG_FINAL) ? " Final":" ");
+ printf((h->T[1] & SKEIN_T1_FLAG_BIT_PAD) ? " Pad" :" ");
+ n = (uint_t) ((h->T[1] & SKEIN_T1_TREE_LVL_MASK) >> SKEIN_T1_POS_TREE_LVL);
+ if (n)
+ printf(" TreeLevel = %02X",n);
+ printf("\n");
+ fflush(stdout);
+ }
+ if (skein_DebugFlag & SKEIN_DEBUG_TWEAK)
+ {
+ printf(" Tweak:\n");
+ Show64(2,h->T);
+ }
+ if (skein_DebugFlag & SKEIN_DEBUG_STATE)
+ {
+ printf(" %s words:\n",(skein_DebugFlag & SKEIN_DEBUG_THREEFISH)?"Key":"State");
+ Show64(bits/64,X);
+ }
+ if (skein_DebugFlag & SKEIN_DEBUG_KEYSCHED)
+ {
+ printf(" Tweak schedule:\n");
+ Show64_flag(3,tsPtr);
+ printf(" Key schedule:\n");
+ Show64_flag((bits/64)+1,ksPtr);
+ }
+ if (skein_DebugFlag & SKEIN_DEBUG_INPUT_64)
+ {
+ printf(" Input block (words):\n");
+ Show64(bits/64,wPtr);
+ }
+ if (skein_DebugFlag & SKEIN_DEBUG_INPUT_08)
+ {
+ printf(" Input block (bytes):\n");
+ Show08(bits/8,blkPtr);
+ }
+ }
+ }
+
+void Skein_Show_Key(uint_t bits,const Skein_Ctxt_Hdr_t *h,const u08b_t *key,size_t keyBytes)
+ {
+ if (keyBytes)
+ if (skein_DebugFlag & SKEIN_DEBUG_CONFIG || ((h->T[1] & SKEIN_T1_BLK_TYPE_MASK) != SKEIN_T1_BLK_TYPE_CFG))
+ if (skein_DebugFlag & SKEIN_DEBUG_KEY)
+ {
+ printf("\n%s MAC key = %4u bytes\n",AlgoHeader(bits),(unsigned) keyBytes);
+ Show08(keyBytes,key);
+ }
+ }
+#endif
diff --git a/sys/crypto/skein/skein_debug.h b/sys/crypto/skein/skein_debug.h
new file mode 100644
index 0000000..7775c016
--- /dev/null
+++ b/sys/crypto/skein/skein_debug.h
@@ -0,0 +1,48 @@
+#ifndef _SKEIN_DEBUG_H_
+#define _SKEIN_DEBUG_H_
+/***********************************************************************
+**
+** Interface definitions for Skein hashing debug output.
+**
+** Source code author: Doug Whiting, 2008.
+**
+** This algorithm and source code is released to the public domain.
+**
+************************************************************************/
+
+#ifdef SKEIN_DEBUG
+/* callout functions used inside Skein code */
+void Skein_Show_Block(uint_t bits,const Skein_Ctxt_Hdr_t *h,const u64b_t *X,const u08b_t *blkPtr,
+ const u64b_t *wPtr,const u64b_t *ksPtr,const u64b_t *tsPtr);
+void Skein_Show_Round(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t r,const u64b_t *X);
+void Skein_Show_R_Ptr(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t r,const u64b_t *X_ptr[]);
+void Skein_Show_Final(uint_t bits,const Skein_Ctxt_Hdr_t *h,size_t cnt,const u08b_t *outPtr);
+void Skein_Show_Key (uint_t bits,const Skein_Ctxt_Hdr_t *h,const u08b_t *key,size_t keyBytes);
+
+extern uint_t skein_DebugFlag; /* flags to control debug output (0 --> none) */
+
+#define SKEIN_RND_SPECIAL (1000u)
+#define SKEIN_RND_KEY_INITIAL (SKEIN_RND_SPECIAL+0u)
+#define SKEIN_RND_KEY_INJECT (SKEIN_RND_SPECIAL+1u)
+#define SKEIN_RND_FEED_FWD (SKEIN_RND_SPECIAL+2u)
+
+/* flag bits: skein_DebugFlag */
+#define SKEIN_DEBUG_KEY (1u << 1) /* show MAC key */
+#define SKEIN_DEBUG_CONFIG (1u << 2) /* show config block processing */
+#define SKEIN_DEBUG_STATE (1u << 3) /* show input state during Show_Block() */
+#define SKEIN_DEBUG_TWEAK (1u << 4) /* show input state during Show_Block() */
+#define SKEIN_DEBUG_KEYSCHED (1u << 5) /* show expanded key schedule */
+#define SKEIN_DEBUG_INPUT_64 (1u << 6) /* show input block as 64-bit words */
+#define SKEIN_DEBUG_INPUT_08 (1u << 7) /* show input block as 8-bit bytes */
+#define SKEIN_DEBUG_INJECT (1u << 8) /* show state after key injection & feedforward points */
+#define SKEIN_DEBUG_ROUNDS (1u << 9) /* show state after all rounds */
+#define SKEIN_DEBUG_FINAL (1u <<10) /* show final output of Skein */
+#define SKEIN_DEBUG_HDR (1u <<11) /* show block header */
+#define SKEIN_DEBUG_THREEFISH (1u <<12) /* use Threefish name instead of Skein */
+#define SKEIN_DEBUG_PERMUTE (1u <<13) /* use word permutations */
+#define SKEIN_DEBUG_ALL ((~0u) & ~(SKEIN_DEBUG_THREEFISH | SKEIN_DEBUG_PERMUTE))
+#define THREEFISH_DEBUG_ALL (SKEIN_DEBUG_ALL | SKEIN_DEBUG_THREEFISH)
+
+#endif /* SKEIN_DEBUG */
+
+#endif /* _SKEIN_DEBUG_H_ */
diff --git a/sys/crypto/skein/skein_freebsd.h b/sys/crypto/skein/skein_freebsd.h
new file mode 100644
index 0000000..935fa09
--- /dev/null
+++ b/sys/crypto/skein/skein_freebsd.h
@@ -0,0 +1,79 @@
+/*-
+ * Copyright 2016 Allan Jude
+ * 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 _SKEIN_FREEBSD_H_
+#define _SKEIN_FREEBSD_H_
+
+#define SKEIN_256_BLOCK_BYTES ( 8*SKEIN_256_STATE_WORDS)
+#define SKEIN_512_BLOCK_BYTES ( 8*SKEIN_512_STATE_WORDS)
+#define SKEIN1024_BLOCK_BYTES ( 8*SKEIN1024_STATE_WORDS)
+
+#define SKEIN256_BLOCK_LENGTH SKEIN_256_BLOCK_BYTES
+#define SKEIN256_DIGEST_LENGTH 32
+#define SKEIN256_DIGEST_STRING_LENGTH (SKEIN256_DIGEST_LENGTH * 2 + 1)
+#define SKEIN512_BLOCK_LENGTH SKEIN_512_BLOCK_BYTES
+#define SKEIN512_DIGEST_LENGTH 64
+#define SKEIN512_DIGEST_STRING_LENGTH (SKEIN512_DIGEST_LENGTH * 2 + 1)
+#define SKEIN1024_BLOCK_LENGTH SKEIN1024_BLOCK_BYTES
+#define SKEIN1024_DIGEST_LENGTH 128
+#define SKEIN1024_DIGEST_STRING_LENGTH (SKEIN1024_DIGEST_LENGTH * 2 + 1)
+
+/* Make the context types look like the other hashes on FreeBSD */
+typedef Skein_256_Ctxt_t SKEIN256_CTX;
+typedef Skein_512_Ctxt_t SKEIN512_CTX;
+typedef Skein1024_Ctxt_t SKEIN1024_CTX;
+
+/* Make the prototypes look like the other hashes */
+void SKEIN256_Init (SKEIN256_CTX *ctx);
+void SKEIN512_Init (SKEIN512_CTX *ctx);
+void SKEIN1024_Init (SKEIN1024_CTX *ctx);
+
+void SKEIN256_Update(SKEIN256_CTX *ctx, const void *in, size_t len);
+void SKEIN512_Update(SKEIN512_CTX *ctx, const void *in, size_t len);
+void SKEIN1024_Update(SKEIN1024_CTX *ctx, const void *in, size_t len);
+
+void SKEIN256_Final(unsigned char digest[static SKEIN256_DIGEST_LENGTH], SKEIN256_CTX *ctx);
+void SKEIN512_Final(unsigned char digest[static SKEIN512_DIGEST_LENGTH], SKEIN512_CTX *ctx);
+void SKEIN1024_Final(unsigned char digest[static SKEIN1024_DIGEST_LENGTH], SKEIN1024_CTX *ctx);
+
+#ifndef _KERNEL
+char *SKEIN256_End(SKEIN256_CTX *, char *);
+char *SKEIN512_End(SKEIN512_CTX *, char *);
+char *SKEIN1024_End(SKEIN1024_CTX *, char *);
+char *SKEIN256_Data(const void *, unsigned int, char *);
+char *SKEIN512_Data(const void *, unsigned int, char *);
+char *SKEIN1024_Data(const void *, unsigned int, char *);
+char *SKEIN256_File(const char *, char *);
+char *SKEIN512_File(const char *, char *);
+char *SKEIN1024_File(const char *, char *);
+char *SKEIN256_FileChunk(const char *, char *, off_t, off_t);
+char *SKEIN512_FileChunk(const char *, char *, off_t, off_t);
+char *SKEIN1024_FileChunk(const char *, char *, off_t, off_t);
+#endif
+
+#endif /* ifndef _SKEIN_FREEBSD_H_ */
diff --git a/sys/crypto/skein/skein_iv.h b/sys/crypto/skein/skein_iv.h
new file mode 100644
index 0000000..6e66166
--- /dev/null
+++ b/sys/crypto/skein/skein_iv.h
@@ -0,0 +1,200 @@
+/* $FreeBSD$ */
+#ifndef _SKEIN_IV_H_
+#define _SKEIN_IV_H_
+
+#include "skein.h" /* get Skein macros and types */
+
+/*
+***************** Pre-computed Skein IVs *******************
+**
+** NOTE: these values are not "magic" constants, but
+** are generated using the Threefish block function.
+** They are pre-computed here only for speed; i.e., to
+** avoid the need for a Threefish call during Init().
+**
+** The IV for any fixed hash length may be pre-computed.
+** Only the most common values are included here.
+**
+************************************************************
+**/
+
+#define MK_64 SKEIN_MK_64
+
+/* blkSize = 256 bits. hashSize = 128 bits */
+const u64b_t SKEIN_256_IV_128[] =
+ {
+ MK_64(0xE1111906,0x964D7260),
+ MK_64(0x883DAAA7,0x7C8D811C),
+ MK_64(0x10080DF4,0x91960F7A),
+ MK_64(0xCCF7DDE5,0xB45BC1C2)
+ };
+
+/* blkSize = 256 bits. hashSize = 160 bits */
+const u64b_t SKEIN_256_IV_160[] =
+ {
+ MK_64(0x14202314,0x72825E98),
+ MK_64(0x2AC4E9A2,0x5A77E590),
+ MK_64(0xD47A5856,0x8838D63E),
+ MK_64(0x2DD2E496,0x8586AB7D)
+ };
+
+/* blkSize = 256 bits. hashSize = 224 bits */
+const u64b_t SKEIN_256_IV_224[] =
+ {
+ MK_64(0xC6098A8C,0x9AE5EA0B),
+ MK_64(0x876D5686,0x08C5191C),
+ MK_64(0x99CB88D7,0xD7F53884),
+ MK_64(0x384BDDB1,0xAEDDB5DE)
+ };
+
+/* blkSize = 256 bits. hashSize = 256 bits */
+const u64b_t SKEIN_256_IV_256[] =
+ {
+ MK_64(0xFC9DA860,0xD048B449),
+ MK_64(0x2FCA6647,0x9FA7D833),
+ MK_64(0xB33BC389,0x6656840F),
+ MK_64(0x6A54E920,0xFDE8DA69)
+ };
+
+/* blkSize = 512 bits. hashSize = 128 bits */
+const u64b_t SKEIN_512_IV_128[] =
+ {
+ MK_64(0xA8BC7BF3,0x6FBF9F52),
+ MK_64(0x1E9872CE,0xBD1AF0AA),
+ MK_64(0x309B1790,0xB32190D3),
+ MK_64(0xBCFBB854,0x3F94805C),
+ MK_64(0x0DA61BCD,0x6E31B11B),
+ MK_64(0x1A18EBEA,0xD46A32E3),
+ MK_64(0xA2CC5B18,0xCE84AA82),
+ MK_64(0x6982AB28,0x9D46982D)
+ };
+
+/* blkSize = 512 bits. hashSize = 160 bits */
+const u64b_t SKEIN_512_IV_160[] =
+ {
+ MK_64(0x28B81A2A,0xE013BD91),
+ MK_64(0xC2F11668,0xB5BDF78F),
+ MK_64(0x1760D8F3,0xF6A56F12),
+ MK_64(0x4FB74758,0x8239904F),
+ MK_64(0x21EDE07F,0x7EAF5056),
+ MK_64(0xD908922E,0x63ED70B8),
+ MK_64(0xB8EC76FF,0xECCB52FA),
+ MK_64(0x01A47BB8,0xA3F27A6E)
+ };
+
+/* blkSize = 512 bits. hashSize = 224 bits */
+const u64b_t SKEIN_512_IV_224[] =
+ {
+ MK_64(0xCCD06162,0x48677224),
+ MK_64(0xCBA65CF3,0xA92339EF),
+ MK_64(0x8CCD69D6,0x52FF4B64),
+ MK_64(0x398AED7B,0x3AB890B4),
+ MK_64(0x0F59D1B1,0x457D2BD0),
+ MK_64(0x6776FE65,0x75D4EB3D),
+ MK_64(0x99FBC70E,0x997413E9),
+ MK_64(0x9E2CFCCF,0xE1C41EF7)
+ };
+
+/* blkSize = 512 bits. hashSize = 256 bits */
+const u64b_t SKEIN_512_IV_256[] =
+ {
+ MK_64(0xCCD044A1,0x2FDB3E13),
+ MK_64(0xE8359030,0x1A79A9EB),
+ MK_64(0x55AEA061,0x4F816E6F),
+ MK_64(0x2A2767A4,0xAE9B94DB),
+ MK_64(0xEC06025E,0x74DD7683),
+ MK_64(0xE7A436CD,0xC4746251),
+ MK_64(0xC36FBAF9,0x393AD185),
+ MK_64(0x3EEDBA18,0x33EDFC13)
+ };
+
+/* blkSize = 512 bits. hashSize = 384 bits */
+const u64b_t SKEIN_512_IV_384[] =
+ {
+ MK_64(0xA3F6C6BF,0x3A75EF5F),
+ MK_64(0xB0FEF9CC,0xFD84FAA4),
+ MK_64(0x9D77DD66,0x3D770CFE),
+ MK_64(0xD798CBF3,0xB468FDDA),
+ MK_64(0x1BC4A666,0x8A0E4465),
+ MK_64(0x7ED7D434,0xE5807407),
+ MK_64(0x548FC1AC,0xD4EC44D6),
+ MK_64(0x266E1754,0x6AA18FF8)
+ };
+
+/* blkSize = 512 bits. hashSize = 512 bits */
+const u64b_t SKEIN_512_IV_512[] =
+ {
+ MK_64(0x4903ADFF,0x749C51CE),
+ MK_64(0x0D95DE39,0x9746DF03),
+ MK_64(0x8FD19341,0x27C79BCE),
+ MK_64(0x9A255629,0xFF352CB1),
+ MK_64(0x5DB62599,0xDF6CA7B0),
+ MK_64(0xEABE394C,0xA9D5C3F4),
+ MK_64(0x991112C7,0x1A75B523),
+ MK_64(0xAE18A40B,0x660FCC33)
+ };
+
+/* blkSize = 1024 bits. hashSize = 384 bits */
+const u64b_t SKEIN1024_IV_384[] =
+ {
+ MK_64(0x5102B6B8,0xC1894A35),
+ MK_64(0xFEEBC9E3,0xFE8AF11A),
+ MK_64(0x0C807F06,0xE32BED71),
+ MK_64(0x60C13A52,0xB41A91F6),
+ MK_64(0x9716D35D,0xD4917C38),
+ MK_64(0xE780DF12,0x6FD31D3A),
+ MK_64(0x797846B6,0xC898303A),
+ MK_64(0xB172C2A8,0xB3572A3B),
+ MK_64(0xC9BC8203,0xA6104A6C),
+ MK_64(0x65909338,0xD75624F4),
+ MK_64(0x94BCC568,0x4B3F81A0),
+ MK_64(0x3EBBF51E,0x10ECFD46),
+ MK_64(0x2DF50F0B,0xEEB08542),
+ MK_64(0x3B5A6530,0x0DBC6516),
+ MK_64(0x484B9CD2,0x167BBCE1),
+ MK_64(0x2D136947,0xD4CBAFEA)
+ };
+
+/* blkSize = 1024 bits. hashSize = 512 bits */
+const u64b_t SKEIN1024_IV_512[] =
+ {
+ MK_64(0xCAEC0E5D,0x7C1B1B18),
+ MK_64(0xA01B0E04,0x5F03E802),
+ MK_64(0x33840451,0xED912885),
+ MK_64(0x374AFB04,0xEAEC2E1C),
+ MK_64(0xDF25A0E2,0x813581F7),
+ MK_64(0xE4004093,0x8B12F9D2),
+ MK_64(0xA662D539,0xC2ED39B6),
+ MK_64(0xFA8B85CF,0x45D8C75A),
+ MK_64(0x8316ED8E,0x29EDE796),
+ MK_64(0x053289C0,0x2E9F91B8),
+ MK_64(0xC3F8EF1D,0x6D518B73),
+ MK_64(0xBDCEC3C4,0xD5EF332E),
+ MK_64(0x549A7E52,0x22974487),
+ MK_64(0x67070872,0x5B749816),
+ MK_64(0xB9CD28FB,0xF0581BD1),
+ MK_64(0x0E2940B8,0x15804974)
+ };
+
+/* blkSize = 1024 bits. hashSize = 1024 bits */
+const u64b_t SKEIN1024_IV_1024[] =
+ {
+ MK_64(0xD593DA07,0x41E72355),
+ MK_64(0x15B5E511,0xAC73E00C),
+ MK_64(0x5180E5AE,0xBAF2C4F0),
+ MK_64(0x03BD41D3,0xFCBCAFAF),
+ MK_64(0x1CAEC6FD,0x1983A898),
+ MK_64(0x6E510B8B,0xCDD0589F),
+ MK_64(0x77E2BDFD,0xC6394ADA),
+ MK_64(0xC11E1DB5,0x24DCB0A3),
+ MK_64(0xD6D14AF9,0xC6329AB5),
+ MK_64(0x6A9B0BFC,0x6EB67E0D),
+ MK_64(0x9243C60D,0xCCFF1332),
+ MK_64(0x1A1F1DDE,0x743F02D4),
+ MK_64(0x0996753C,0x10ED0BB8),
+ MK_64(0x6572DD22,0xF2B4969A),
+ MK_64(0x61FD3062,0xD00A579A),
+ MK_64(0x1DE0536E,0x8682E539)
+ };
+
+#endif /* _SKEIN_IV_H_ */
diff --git a/sys/crypto/skein/skein_port.h b/sys/crypto/skein/skein_port.h
new file mode 100644
index 0000000..7025a51
--- /dev/null
+++ b/sys/crypto/skein/skein_port.h
@@ -0,0 +1,158 @@
+/* $FreeBSD$ */
+#ifndef _SKEIN_PORT_H_
+#define _SKEIN_PORT_H_
+/*******************************************************************
+**
+** Platform-specific definitions for Skein hash function.
+**
+** Source code author: Doug Whiting, 2008.
+**
+** This algorithm and source code is released to the public domain.
+**
+** Many thanks to Brian Gladman for his portable header files.
+**
+** To port Skein to an "unsupported" platform, change the definitions
+** in this file appropriately.
+**
+********************************************************************/
+
+#include <sys/endian.h>
+#include <sys/types.h>
+
+#ifndef _OPENSOLARIS_SYS_TYPES_H_ /* Avoid redefining this typedef */
+typedef unsigned int uint_t; /* native unsigned integer */
+#endif
+typedef u_int8_t u08b_t; /* 8-bit unsigned integer */
+typedef u_int32_t uint_32t; /* 32-bit unsigned integer */
+typedef u_int64_t u64b_t; /* 64-bit unsigned integer */
+
+#ifndef RotL_64
+#define RotL_64(x,N) (((x) << (N)) | ((x) >> (64-(N))))
+#endif
+
+__BEGIN_DECLS
+
+/*
+ * Skein is "natively" little-endian (unlike SHA-xxx), for optimal
+ * performance on x86 CPUs. The Skein code requires the following
+ * definitions for dealing with endianness:
+ *
+ * SKEIN_NEED_SWAP: 0 for little-endian, 1 for big-endian
+ * Skein_Put64_LSB_First
+ * Skein_Get64_LSB_First
+ * Skein_Swap64
+ *
+ * If SKEIN_NEED_SWAP is defined at compile time, it is used here
+ * along with the portable versions of Put64/Get64/Swap64, which
+ * are slow in general.
+ *
+ * Otherwise, an "auto-detect" of endianness is attempted below.
+ * If the default handling doesn't work well, the user may insert
+ * platform-specific code instead (e.g., for big-endian CPUs).
+ *
+ */
+#ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */
+
+#if BYTE_ORDER == BIG_ENDIAN
+ /* here for big-endian CPUs */
+#define SKEIN_NEED_SWAP (1)
+#ifdef SKEIN_PORT_CODE
+void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt);
+void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt);
+#endif /* ifdef SKEIN_PORT_CODE */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+ /* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
+#define SKEIN_NEED_SWAP (0)
+#define Skein_Put64_LSB_First(dst08,src64,bCnt) memcpy(dst08,src64,bCnt)
+#define Skein_Get64_LSB_First(dst64,src08,wCnt) memcpy(dst64,src08,8*(wCnt))
+#else
+#error "Skein needs endianness setting!"
+#endif
+
+#endif /* ifndef SKEIN_NEED_SWAP */
+
+/*
+ ******************************************************************
+ * Provide any definitions still needed.
+ ******************************************************************
+ */
+#ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */
+#if SKEIN_NEED_SWAP
+#define Skein_Swap64(w64) bswap64(w64)
+#else
+#define Skein_Swap64(w64) (w64)
+#endif
+#endif /* ifndef Skein_Swap64 */
+
+
+#ifndef Skein_Put64_LSB_First
+void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt)
+#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */
+{
+ size_t n;
+
+ for (n = 0; n < bCnt / 8; n++)
+ le64enc(dst + n * 8, src[n]);
+}
+#else
+; /* output only the function prototype */
+#endif
+#endif /* ifndef Skein_Put64_LSB_First */
+
+
+#ifndef Skein_Get64_LSB_First
+void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt)
+#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */
+{
+ size_t n;
+
+ for (n = 0; n < wCnt; n++)
+ dst[n] = le64dec(src + n * 8);
+}
+#else
+; /* output only the function prototype */
+#endif
+#endif /* ifndef Skein_Get64_LSB_First */
+
+/* Start FreeBSD libmd shims */
+
+/* Ensure libmd symbols do not clash with libcrypto */
+#ifndef SKEIN256_Init
+#define SKEIN256_Init _libmd_SKEIN256_Init
+#define SKEIN512_Init _libmd_SKEIN512_Init
+#define SKEIN1024_Init _libmd_SKEIN1024_Init
+#endif
+#ifndef SKEIN256_Update
+#define SKEIN256_Update _libmd_SKEIN256_Update
+#define SKEIN512_Update _libmd_SKEIN512_Update
+#define SKEIN1024_Update _libmd_SKEIN1024_Update
+#endif
+#ifndef SKEIN256_Final
+#define SKEIN256_Final _libmd_SKEIN256_Final
+#define SKEIN512_Final _libmd_SKEIN512_Final
+#define SKEIN1024_Final _libmd_SKEIN1024_Final
+#endif
+#ifndef SKEIN256_End
+#define SKEIN256_End _libmd_SKEIN256_End
+#define SKEIN512_End _libmd_SKEIN512_End
+#define SKEIN1024_End _libmd_SKEIN1024_End
+#endif
+#ifndef SKEIN256_File
+#define SKEIN256_File _libmd_SKEIN256_File
+#define SKEIN512_File _libmd_SKEIN512_File
+#define SKEIN1024_File _libmd_SKEIN1024_File
+#endif
+#ifndef SKEIN256_FileChunk
+#define SKEIN256_FileChunk _libmd_SKEIN256_FileChunk
+#define SKEIN512_FileChunk _libmd_SKEIN512_FileChunk
+#define SKEIN1024_FileChunk _libmd_SKEIN1024_FileChunk
+#endif
+#ifndef SKEIN256_Data
+#define SKEIN256_Data _libmd_SKEIN256_Data
+#define SKEIN512_Data _libmd_SKEIN512_Data
+#define SKEIN1024_Data _libmd_SKEIN1024_Data
+#endif
+
+__END_DECLS
+
+#endif /* ifndef _SKEIN_PORT_H_ */
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index cb98888..ecf2227 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -1097,137 +1097,7 @@ typedef enum {
/*
* BT Co-existence definitions
*/
-typedef enum {
- HAL_BT_MODULE_CSR_BC4 = 0, /* CSR BlueCore v4 */
- HAL_BT_MODULE_JANUS = 1, /* Kite + Valkyrie combo */
- HAL_BT_MODULE_HELIUS = 2, /* Kiwi + Valkyrie combo */
- HAL_MAX_BT_MODULES
-} HAL_BT_MODULE;
-
-typedef struct {
- HAL_BT_MODULE bt_module;
- u_int8_t bt_coex_config;
- u_int8_t bt_gpio_bt_active;
- u_int8_t bt_gpio_bt_priority;
- u_int8_t bt_gpio_wlan_active;
- u_int8_t bt_active_polarity;
- HAL_BOOL bt_single_ant;
- u_int8_t bt_dutyCycle;
- u_int8_t bt_isolation;
- u_int8_t bt_period;
-} HAL_BT_COEX_INFO;
-
-typedef enum {
- HAL_BT_COEX_MODE_LEGACY = 0, /* legacy rx_clear mode */
- HAL_BT_COEX_MODE_UNSLOTTED = 1, /* untimed/unslotted mode */
- HAL_BT_COEX_MODE_SLOTTED = 2, /* slotted mode */
- HAL_BT_COEX_MODE_DISALBED = 3, /* coexistence disabled */
-} HAL_BT_COEX_MODE;
-
-typedef enum {
- HAL_BT_COEX_CFG_NONE, /* No bt coex enabled */
- HAL_BT_COEX_CFG_2WIRE_2CH, /* 2-wire with 2 chains */
- HAL_BT_COEX_CFG_2WIRE_CH1, /* 2-wire with ch1 */
- HAL_BT_COEX_CFG_2WIRE_CH0, /* 2-wire with ch0 */
- HAL_BT_COEX_CFG_3WIRE, /* 3-wire */
- HAL_BT_COEX_CFG_MCI /* MCI */
-} HAL_BT_COEX_CFG;
-
-typedef enum {
- HAL_BT_COEX_SET_ACK_PWR = 0, /* Change ACK power setting */
- HAL_BT_COEX_LOWER_TX_PWR, /* Change transmit power */
- HAL_BT_COEX_ANTENNA_DIVERSITY, /* Enable RX diversity for Kite */
- HAL_BT_COEX_MCI_MAX_TX_PWR, /* Set max tx power for concurrent tx */
- HAL_BT_COEX_MCI_FTP_STOMP_RX, /* Use a different weight for stomp low */
-} HAL_BT_COEX_SET_PARAMETER;
-
-#define HAL_BT_COEX_FLAG_LOW_ACK_PWR 0x00000001
-#define HAL_BT_COEX_FLAG_LOWER_TX_PWR 0x00000002
-/* Check Rx Diversity is allowed */
-#define HAL_BT_COEX_FLAG_ANT_DIV_ALLOW 0x00000004
-/* Check Diversity is on or off */
-#define HAL_BT_COEX_FLAG_ANT_DIV_ENABLE 0x00000008
-
-#define HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE 0x0b
-/* main: LNA1, alt: LNA2 */
-#define HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE 0x09
-#define HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A 0x04
-#define HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A 0x09
-#define HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B 0x02
-#define HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B 0x06
-
-#define HAL_BT_COEX_ISOLATION_FOR_NO_COEX 30
-
-#define HAL_BT_COEX_ANT_DIV_SWITCH_COM 0x66666666
-
-#define HAL_BT_COEX_HELIUS_CHAINMASK 0x02
-
-#define HAL_BT_COEX_LOW_ACK_POWER 0x0
-#define HAL_BT_COEX_HIGH_ACK_POWER 0x3f3f3f
-
-typedef enum {
- HAL_BT_COEX_NO_STOMP = 0,
- HAL_BT_COEX_STOMP_ALL,
- HAL_BT_COEX_STOMP_LOW,
- HAL_BT_COEX_STOMP_NONE,
- HAL_BT_COEX_STOMP_ALL_FORCE,
- HAL_BT_COEX_STOMP_LOW_FORCE,
-} HAL_BT_COEX_STOMP_TYPE;
-
-typedef struct {
- /* extend rx_clear after tx/rx to protect the burst (in usec). */
- u_int8_t bt_time_extend;
-
- /*
- * extend rx_clear as long as txsm is
- * transmitting or waiting for ack.
- */
- HAL_BOOL bt_txstate_extend;
-
- /*
- * extend rx_clear so that when tx_frame
- * is asserted, rx_clear will drop.
- */
- HAL_BOOL bt_txframe_extend;
-
- /*
- * coexistence mode
- */
- HAL_BT_COEX_MODE bt_mode;
-
- /*
- * treat BT high priority traffic as
- * a quiet collision
- */
- HAL_BOOL bt_quiet_collision;
-
- /*
- * invert rx_clear as WLAN_ACTIVE
- */
- HAL_BOOL bt_rxclear_polarity;
-
- /*
- * slotted mode only. indicate the time in usec
- * from the rising edge of BT_ACTIVE to the time
- * BT_PRIORITY can be sampled to indicate priority.
- */
- u_int8_t bt_priority_time;
-
- /*
- * slotted mode only. indicate the time in usec
- * from the rising edge of BT_ACTIVE to the time
- * BT_PRIORITY can be sampled to indicate tx/rx and
- * BT_FREQ is sampled.
- */
- u_int8_t bt_first_slot_time;
-
- /*
- * slotted mode only. rx_clear and bt_ant decision
- * will be held the entire time that BT_ACTIVE is asserted,
- * otherwise the decision is made before every slot boundary.
- */
- HAL_BOOL bt_hold_rxclear;
-} HAL_BT_COEX_CONFIG;
+#include "ath_hal/ah_btcoex.h"
struct hal_bb_panic_info {
u_int32_t status;
@@ -1643,7 +1513,7 @@ struct ath_hal {
HAL_BOOL, HAL_BOOL);
uint32_t __ahdecl(*ah_btMciGetInterrupt)(struct ath_hal *,
uint32_t *, uint32_t *);
- uint32_t __ahdecl(*ah_btMciGetState)(struct ath_hal *,
+ uint32_t __ahdecl(*ah_btMciState)(struct ath_hal *,
uint32_t, uint32_t *);
void __ahdecl(*ah_btMciDetach)(struct ath_hal *);
diff --git a/sys/dev/ath/ath_hal/ah_btcoex.h b/sys/dev/ath/ath_hal/ah_btcoex.h
new file mode 100644
index 0000000..de23455
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ah_btcoex.h
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+#ifndef __ATH_HAL_BTCOEX_H__
+#define __ATH_HAL_BTCOEX_H__
+
+/*
+ * General BT coexistence definitions.
+ */
+typedef enum {
+ HAL_BT_MODULE_CSR_BC4 = 0, /* CSR BlueCore v4 */
+ HAL_BT_MODULE_JANUS = 1, /* Kite + Valkyrie combo */
+ HAL_BT_MODULE_HELIUS = 2, /* Kiwi + Valkyrie combo */
+ HAL_MAX_BT_MODULES
+} HAL_BT_MODULE;
+
+typedef struct {
+ HAL_BT_MODULE bt_module;
+ u_int8_t bt_coex_config;
+ u_int8_t bt_gpio_bt_active;
+ u_int8_t bt_gpio_bt_priority;
+ u_int8_t bt_gpio_wlan_active;
+ u_int8_t bt_active_polarity;
+ HAL_BOOL bt_single_ant;
+ u_int8_t bt_dutyCycle;
+ u_int8_t bt_isolation;
+ u_int8_t bt_period;
+} HAL_BT_COEX_INFO;
+
+typedef enum {
+ HAL_BT_COEX_MODE_LEGACY = 0, /* legacy rx_clear mode */
+ HAL_BT_COEX_MODE_UNSLOTTED = 1, /* untimed/unslotted mode */
+ HAL_BT_COEX_MODE_SLOTTED = 2, /* slotted mode */
+ HAL_BT_COEX_MODE_DISALBED = 3, /* coexistence disabled */
+} HAL_BT_COEX_MODE;
+
+typedef enum {
+ HAL_BT_COEX_CFG_NONE, /* No bt coex enabled */
+ HAL_BT_COEX_CFG_2WIRE_2CH, /* 2-wire with 2 chains */
+ HAL_BT_COEX_CFG_2WIRE_CH1, /* 2-wire with ch1 */
+ HAL_BT_COEX_CFG_2WIRE_CH0, /* 2-wire with ch0 */
+ HAL_BT_COEX_CFG_3WIRE, /* 3-wire */
+ HAL_BT_COEX_CFG_MCI /* MCI */
+} HAL_BT_COEX_CFG;
+
+typedef enum {
+ HAL_BT_COEX_SET_ACK_PWR = 0, /* Change ACK power setting */
+ HAL_BT_COEX_LOWER_TX_PWR, /* Change transmit power */
+ HAL_BT_COEX_ANTENNA_DIVERSITY, /* Enable RX diversity for Kite */
+ HAL_BT_COEX_MCI_MAX_TX_PWR, /* Set max tx power for concurrent tx */
+ HAL_BT_COEX_MCI_FTP_STOMP_RX, /* Use a different weight for stomp low */
+} HAL_BT_COEX_SET_PARAMETER;
+
+/*
+ * MCI specific coexistence definitions.
+ */
+
+#define HAL_BT_COEX_FLAG_LOW_ACK_PWR 0x00000001
+#define HAL_BT_COEX_FLAG_LOWER_TX_PWR 0x00000002
+/* Check Rx Diversity is allowed */
+#define HAL_BT_COEX_FLAG_ANT_DIV_ALLOW 0x00000004
+/* Check Diversity is on or off */
+#define HAL_BT_COEX_FLAG_ANT_DIV_ENABLE 0x00000008
+
+#define HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE 0x0b
+/* main: LNA1, alt: LNA2 */
+#define HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE 0x09
+#define HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A 0x04
+#define HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A 0x09
+#define HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B 0x02
+#define HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B 0x06
+
+#define HAL_BT_COEX_ISOLATION_FOR_NO_COEX 30
+
+#define HAL_BT_COEX_ANT_DIV_SWITCH_COM 0x66666666
+
+#define HAL_BT_COEX_HELIUS_CHAINMASK 0x02
+
+#define HAL_BT_COEX_LOW_ACK_POWER 0x0
+#define HAL_BT_COEX_HIGH_ACK_POWER 0x3f3f3f
+
+typedef enum {
+ HAL_BT_COEX_NO_STOMP = 0,
+ HAL_BT_COEX_STOMP_ALL,
+ HAL_BT_COEX_STOMP_LOW,
+ HAL_BT_COEX_STOMP_NONE,
+ HAL_BT_COEX_STOMP_ALL_FORCE,
+ HAL_BT_COEX_STOMP_LOW_FORCE,
+} HAL_BT_COEX_STOMP_TYPE;
+
+typedef struct {
+ /* extend rx_clear after tx/rx to protect the burst (in usec). */
+ u_int8_t bt_time_extend;
+
+ /*
+ * extend rx_clear as long as txsm is
+ * transmitting or waiting for ack.
+ */
+ HAL_BOOL bt_txstate_extend;
+
+ /*
+ * extend rx_clear so that when tx_frame
+ * is asserted, rx_clear will drop.
+ */
+ HAL_BOOL bt_txframe_extend;
+
+ /*
+ * coexistence mode
+ */
+ HAL_BT_COEX_MODE bt_mode;
+
+ /*
+ * treat BT high priority traffic as
+ * a quiet collision
+ */
+ HAL_BOOL bt_quiet_collision;
+
+ /*
+ * invert rx_clear as WLAN_ACTIVE
+ */
+ HAL_BOOL bt_rxclear_polarity;
+
+ /*
+ * slotted mode only. indicate the time in usec
+ * from the rising edge of BT_ACTIVE to the time
+ * BT_PRIORITY can be sampled to indicate priority.
+ */
+ u_int8_t bt_priority_time;
+
+ /*
+ * slotted mode only. indicate the time in usec
+ * from the rising edge of BT_ACTIVE to the time
+ * BT_PRIORITY can be sampled to indicate tx/rx and
+ * BT_FREQ is sampled.
+ */
+ u_int8_t bt_first_slot_time;
+
+ /*
+ * slotted mode only. rx_clear and bt_ant decision
+ * will be held the entire time that BT_ACTIVE is asserted,
+ * otherwise the decision is made before every slot boundary.
+ */
+ HAL_BOOL bt_hold_rxclear;
+} HAL_BT_COEX_CONFIG;
+
+#define HAL_BT_COEX_FLAG_LOW_ACK_PWR 0x00000001
+#define HAL_BT_COEX_FLAG_LOWER_TX_PWR 0x00000002
+#define HAL_BT_COEX_FLAG_ANT_DIV_ALLOW 0x00000004 /* Check Rx Diversity is allowed */
+#define HAL_BT_COEX_FLAG_ANT_DIV_ENABLE 0x00000008 /* Check Diversity is on or off */
+#define HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR 0x00000010
+#define HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX 0x00000020
+
+#define HAL_MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */
+
+typedef enum mci_message_header {
+ MCI_LNA_CTRL = 0x10, /* len = 0 */
+ MCI_CONT_NACK = 0x20, /* len = 0 */
+ MCI_CONT_INFO = 0x30, /* len = 4 */
+ MCI_CONT_RST = 0x40, /* len = 0 */
+ MCI_SCHD_INFO = 0x50, /* len = 16 */
+ MCI_CPU_INT = 0x60, /* len = 4 */
+ MCI_SYS_WAKING = 0x70, /* len = 0 */
+ MCI_GPM = 0x80, /* len = 16 */
+ MCI_LNA_INFO = 0x90, /* len = 1 */
+ MCI_LNA_STATE = 0x94,
+ MCI_LNA_TAKE = 0x98,
+ MCI_LNA_TRANS = 0x9c,
+ MCI_SYS_SLEEPING = 0xa0, /* len = 0 */
+ MCI_REQ_WAKE = 0xc0, /* len = 0 */
+ MCI_DEBUG_16 = 0xfe, /* len = 2 */
+ MCI_REMOTE_RESET = 0xff /* len = 16 */
+} MCI_MESSAGE_HEADER;
+
+/* Default remote BT device MCI COEX version */
+#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3
+#define MCI_GPM_COEX_MINOR_VERSION_DEFAULT 0
+/* Local WLAN MCI COEX version */
+#define MCI_GPM_COEX_MAJOR_VERSION_WLAN 3
+#define MCI_GPM_COEX_MINOR_VERSION_WLAN 0
+
+typedef enum mci_gpm_subtype {
+ MCI_GPM_BT_CAL_REQ = 0,
+ MCI_GPM_BT_CAL_GRANT = 1,
+ MCI_GPM_BT_CAL_DONE = 2,
+ MCI_GPM_WLAN_CAL_REQ = 3,
+ MCI_GPM_WLAN_CAL_GRANT = 4,
+ MCI_GPM_WLAN_CAL_DONE = 5,
+ MCI_GPM_COEX_AGENT = 0x0C,
+ MCI_GPM_RSVD_PATTERN = 0xFE,
+ MCI_GPM_RSVD_PATTERN32 = 0xFEFEFEFE,
+ MCI_GPM_BT_DEBUG = 0xFF
+} MCI_GPM_SUBTYPE_T;
+
+typedef enum mci_gpm_coex_opcode {
+ MCI_GPM_COEX_VERSION_QUERY = 0,
+ MCI_GPM_COEX_VERSION_RESPONSE = 1,
+ MCI_GPM_COEX_STATUS_QUERY = 2,
+ MCI_GPM_COEX_HALT_BT_GPM = 3,
+ MCI_GPM_COEX_WLAN_CHANNELS = 4,
+ MCI_GPM_COEX_BT_PROFILE_INFO = 5,
+ MCI_GPM_COEX_BT_STATUS_UPDATE = 6,
+ MCI_GPM_COEX_BT_UPDATE_FLAGS = 7
+} MCI_GPM_COEX_OPCODE_T;
+
+typedef enum mci_gpm_coex_query_type {
+ /* WLAN information */
+ MCI_GPM_COEX_QUERY_WLAN_ALL_INFO = 0x01,
+ /* BT information */
+ MCI_GPM_COEX_QUERY_BT_ALL_INFO = 0x01,
+ MCI_GPM_COEX_QUERY_BT_TOPOLOGY = 0x02,
+ MCI_GPM_COEX_QUERY_BT_DEBUG = 0x04
+} MCI_GPM_COEX_QUERY_TYPE_T;
+
+typedef enum mci_gpm_coex_halt_bt_gpm {
+ MCI_GPM_COEX_BT_GPM_UNHALT = 0,
+ MCI_GPM_COEX_BT_GPM_HALT = 1
+} MCI_GPM_COEX_HALT_BT_GPM_T;
+
+typedef enum mci_gpm_coex_profile_type {
+ MCI_GPM_COEX_PROFILE_UNKNOWN = 0,
+ MCI_GPM_COEX_PROFILE_RFCOMM = 1,
+ MCI_GPM_COEX_PROFILE_A2DP = 2,
+ MCI_GPM_COEX_PROFILE_HID = 3,
+ MCI_GPM_COEX_PROFILE_BNEP = 4,
+ MCI_GPM_COEX_PROFILE_VOICE = 5,
+ MCI_GPM_COEX_PROFILE_MAX
+} MCI_GPM_COEX_PROFILE_TYPE_T;
+
+typedef enum mci_gpm_coex_profile_state {
+ MCI_GPM_COEX_PROFILE_STATE_END = 0,
+ MCI_GPM_COEX_PROFILE_STATE_START = 1
+} MCI_GPM_COEX_PROFILE_STATE_T;
+
+typedef enum mci_gpm_coex_profile_role {
+ MCI_GPM_COEX_PROFILE_SLAVE = 0,
+ MCI_GPM_COEX_PROFILE_MASTER = 1
+} MCI_GPM_COEX_PROFILE_ROLE_T;
+
+typedef enum mci_gpm_coex_bt_status_type {
+ MCI_GPM_COEX_BT_NONLINK_STATUS = 0,
+ MCI_GPM_COEX_BT_LINK_STATUS = 1
+} MCI_GPM_COEX_BT_STATUS_TYPE_T;
+
+typedef enum mci_gpm_coex_bt_status_state {
+ MCI_GPM_COEX_BT_NORMAL_STATUS = 0,
+ MCI_GPM_COEX_BT_CRITICAL_STATUS = 1
+} MCI_GPM_COEX_BT_STATUS_STATE_T;
+
+#define MCI_GPM_INVALID_PROFILE_HANDLE 0xff
+
+typedef enum mci_gpm_coex_bt_updata_flags_op {
+ MCI_GPM_COEX_BT_FLAGS_READ = 0x00,
+ MCI_GPM_COEX_BT_FLAGS_SET = 0x01,
+ MCI_GPM_COEX_BT_FLAGS_CLEAR = 0x02
+} MCI_GPM_COEX_BT_FLAGS_OP_T;
+
+/* MCI GPM/Coex opcode/type definitions */
+enum {
+ MCI_GPM_COEX_W_GPM_PAYLOAD = 1,
+ MCI_GPM_COEX_B_GPM_TYPE = 4,
+ MCI_GPM_COEX_B_GPM_OPCODE = 5,
+ /* MCI_GPM_WLAN_CAL_REQ, MCI_GPM_WLAN_CAL_DONE */
+ MCI_GPM_WLAN_CAL_W_SEQUENCE = 2,
+ /* MCI_GPM_COEX_VERSION_QUERY */
+ /* MCI_GPM_COEX_VERSION_RESPONSE */
+ MCI_GPM_COEX_B_MAJOR_VERSION = 6,
+ MCI_GPM_COEX_B_MINOR_VERSION = 7,
+ /* MCI_GPM_COEX_STATUS_QUERY */
+ MCI_GPM_COEX_B_BT_BITMAP = 6,
+ MCI_GPM_COEX_B_WLAN_BITMAP = 7,
+ /* MCI_GPM_COEX_HALT_BT_GPM */
+ MCI_GPM_COEX_B_HALT_STATE = 6,
+ /* MCI_GPM_COEX_WLAN_CHANNELS */
+ MCI_GPM_COEX_B_CHANNEL_MAP = 6,
+ /* MCI_GPM_COEX_BT_PROFILE_INFO */
+ MCI_GPM_COEX_B_PROFILE_TYPE = 6,
+ MCI_GPM_COEX_B_PROFILE_LINKID = 7,
+ MCI_GPM_COEX_B_PROFILE_STATE = 8,
+ MCI_GPM_COEX_B_PROFILE_ROLE = 9,
+ MCI_GPM_COEX_B_PROFILE_RATE = 10,
+ MCI_GPM_COEX_B_PROFILE_VOTYPE = 11,
+ MCI_GPM_COEX_H_PROFILE_T = 12,
+ MCI_GPM_COEX_B_PROFILE_W = 14,
+ MCI_GPM_COEX_B_PROFILE_A = 15,
+ /* MCI_GPM_COEX_BT_STATUS_UPDATE */
+ MCI_GPM_COEX_B_STATUS_TYPE = 6,
+ MCI_GPM_COEX_B_STATUS_LINKID = 7,
+ MCI_GPM_COEX_B_STATUS_STATE = 8,
+ /* MCI_GPM_COEX_BT_UPDATE_FLAGS */
+ MCI_GPM_COEX_B_BT_FLAGS_OP = 10,
+ MCI_GPM_COEX_W_BT_FLAGS = 6
+};
+
+#define MCI_GPM_RECYCLE(_p_gpm) \
+ { \
+ *(((u_int32_t *)(_p_gpm)) + MCI_GPM_COEX_W_GPM_PAYLOAD) = MCI_GPM_RSVD_PATTERN32; \
+ }
+#define MCI_GPM_TYPE(_p_gpm) \
+ (*(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) & 0xff)
+#define MCI_GPM_OPCODE(_p_gpm) \
+ (*(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) & 0xff)
+
+#define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type) \
+ { \
+ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_cal_type) & 0xff; \
+ }
+#define MCI_GPM_SET_TYPE_OPCODE(_p_gpm, _type, _opcode) \
+ { \
+ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_type) & 0xff; \
+ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) = (_opcode) & 0xff; \
+ }
+#define MCI_GPM_IS_CAL_TYPE(_type) ((_type) <= MCI_GPM_WLAN_CAL_DONE)
+
+#define MCI_NUM_BT_CHANNELS 79
+
+#define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \
+ { \
+ if (_bt_chan < MCI_NUM_BT_CHANNELS) { \
+ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
+ (_bt_chan / 8)) |= 1 << (_bt_chan & 7); \
+ } \
+ }
+
+#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \
+ { \
+ if (_bt_chan < MCI_NUM_BT_CHANNELS) { \
+ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
+ (_bt_chan / 8)) &= ~(1 << (_bt_chan & 7)); \
+ } \
+ }
+
+#define HAL_MCI_INTERRUPT_SW_MSG_DONE 0x00000001
+#define HAL_MCI_INTERRUPT_CPU_INT_MSG 0x00000002
+#define HAL_MCI_INTERRUPT_RX_CHKSUM_FAIL 0x00000004
+#define HAL_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008
+#define HAL_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010
+#define HAL_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020
+#define HAL_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080
+#define HAL_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100
+#define HAL_MCI_INTERRUPT_RX_MSG 0x00000200
+#define HAL_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400
+#define HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000
+#define HAL_MCI_INTERRUPT_MSG_FAIL_MASK ( HAL_MCI_INTERRUPT_RX_HW_MSG_FAIL | \
+ HAL_MCI_INTERRUPT_RX_SW_MSG_FAIL | \
+ HAL_MCI_INTERRUPT_TX_HW_MSG_FAIL | \
+ HAL_MCI_INTERRUPT_TX_SW_MSG_FAIL )
+
+#define HAL_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
+#define HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
+#define HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
+#define HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
+#define HAL_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
+#define HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
+#define HAL_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
+#define HAL_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
+#define HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
+#define HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
+#define HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
+#define HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
+#define HAL_MCI_INTERRUPT_RX_MSG_MONITOR (HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \
+ HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
+ HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
+ HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
+ HAL_MCI_INTERRUPT_RX_MSG_CONT_RST)
+
+typedef enum mci_bt_state {
+ MCI_BT_SLEEP,
+ MCI_BT_AWAKE,
+ MCI_BT_CAL_START,
+ MCI_BT_CAL
+} MCI_BT_STATE_T;
+
+/* Type of state query */
+typedef enum mci_state_type {
+ HAL_MCI_STATE_ENABLE,
+ HAL_MCI_STATE_INIT_GPM_OFFSET,
+ HAL_MCI_STATE_NEXT_GPM_OFFSET,
+ HAL_MCI_STATE_LAST_GPM_OFFSET,
+ HAL_MCI_STATE_BT,
+ HAL_MCI_STATE_SET_BT_SLEEP,
+ HAL_MCI_STATE_SET_BT_AWAKE,
+ HAL_MCI_STATE_SET_BT_CAL_START,
+ HAL_MCI_STATE_SET_BT_CAL,
+ HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET,
+ HAL_MCI_STATE_REMOTE_SLEEP,
+ HAL_MCI_STATE_CONT_RSSI_POWER,
+ HAL_MCI_STATE_CONT_PRIORITY,
+ HAL_MCI_STATE_CONT_TXRX,
+ HAL_MCI_STATE_RESET_REQ_WAKE,
+ HAL_MCI_STATE_SEND_WLAN_COEX_VERSION,
+ HAL_MCI_STATE_SET_BT_COEX_VERSION,
+ HAL_MCI_STATE_SEND_WLAN_CHANNELS,
+ HAL_MCI_STATE_SEND_VERSION_QUERY,
+ HAL_MCI_STATE_SEND_STATUS_QUERY,
+ HAL_MCI_STATE_NEED_FLUSH_BT_INFO,
+ HAL_MCI_STATE_SET_CONCUR_TX_PRI,
+ HAL_MCI_STATE_RECOVER_RX,
+ HAL_MCI_STATE_NEED_FTP_STOMP,
+ HAL_MCI_STATE_NEED_TUNING,
+ HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX,
+ HAL_MCI_STATE_DEBUG,
+ HAL_MCI_STATE_MAX
+} HAL_MCI_STATE_TYPE;
+
+#define HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG 1
+
+#define HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR 0x00000002
+#define HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR 0x00000004
+#define HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD 0x00000008
+#define HAL_MCI_BT_MCI_FLAGS_LNA_CTRL 0x00000010
+#define HAL_MCI_BT_MCI_FLAGS_DEBUG 0x00000020
+#define HAL_MCI_BT_MCI_FLAGS_SCHED_MSG 0x00000040
+#define HAL_MCI_BT_MCI_FLAGS_CONT_MSG 0x00000080
+#define HAL_MCI_BT_MCI_FLAGS_COEX_GPM 0x00000100
+#define HAL_MCI_BT_MCI_FLAGS_CPU_INT_MSG 0x00000200
+#define HAL_MCI_BT_MCI_FLAGS_MCI_MODE 0x00000400
+#define HAL_MCI_BT_MCI_FLAGS_EGRET_MODE 0x00000800
+#define HAL_MCI_BT_MCI_FLAGS_JUPITER_MODE 0x00001000
+#define HAL_MCI_BT_MCI_FLAGS_OTHER 0x00010000
+
+#define HAL_MCI_DEFAULT_BT_MCI_FLAGS 0x00011dde
+/*
+ HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR = 1
+ HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR = 1
+ HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD = 1
+ HAL_MCI_BT_MCI_FLAGS_LNA_CTRL = 1
+ HAL_MCI_BT_MCI_FLAGS_DEBUG = 0
+ HAL_MCI_BT_MCI_FLAGS_SCHED_MSG = 1
+ HAL_MCI_BT_MCI_FLAGS_CONT_MSG = 1
+ HAL_MCI_BT_MCI_FLAGS_COEX_GPM = 1
+ HAL_MCI_BT_MCI_FLAGS_CPU_INT_MSG = 0
+ HAL_MCI_BT_MCI_FLAGS_MCI_MODE = 1
+ HAL_MCI_BT_MCI_FLAGS_EGRET_MODE = 1
+ HAL_MCI_BT_MCI_FLAGS_JUPITER_MODE = 1
+ HAL_MCI_BT_MCI_FLAGS_OTHER = 1
+*/
+
+#define HAL_MCI_TOGGLE_BT_MCI_FLAGS \
+ ( HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR | \
+ HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR | \
+ HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD | \
+ HAL_MCI_BT_MCI_FLAGS_MCI_MODE )
+
+#define HAL_MCI_2G_FLAGS_CLEAR_MASK 0x00000000
+#define HAL_MCI_2G_FLAGS_SET_MASK HAL_MCI_TOGGLE_BT_MCI_FLAGS
+#define HAL_MCI_2G_FLAGS HAL_MCI_DEFAULT_BT_MCI_FLAGS
+
+#define HAL_MCI_5G_FLAGS_CLEAR_MASK HAL_MCI_TOGGLE_BT_MCI_FLAGS
+#define HAL_MCI_5G_FLAGS_SET_MASK 0x00000000
+#define HAL_MCI_5G_FLAGS (HAL_MCI_DEFAULT_BT_MCI_FLAGS & \
+ ~HAL_MCI_TOGGLE_BT_MCI_FLAGS)
+
+#define HAL_MCI_GPM_NOMORE 0
+#define HAL_MCI_GPM_MORE 1
+#define HAL_MCI_GPM_INVALID 0xffffffff
+
+#define ATH_AIC_MAX_BT_CHANNEL 79
+
+/*
+ * Default value for Jupiter is 0x00002201
+ * Default value for Aphrodite is 0x00002282
+ */
+#define ATH_MCI_CONFIG_CONCUR_TX 0x00000003
+#define ATH_MCI_CONFIG_MCI_OBS_MCI 0x00000004
+#define ATH_MCI_CONFIG_MCI_OBS_TXRX 0x00000008
+#define ATH_MCI_CONFIG_MCI_OBS_BT 0x00000010
+#define ATH_MCI_CONFIG_DISABLE_MCI_CAL 0x00000020
+#define ATH_MCI_CONFIG_DISABLE_OSLA 0x00000040
+#define ATH_MCI_CONFIG_DISABLE_FTP_STOMP 0x00000080
+#define ATH_MCI_CONFIG_AGGR_THRESH 0x00000700
+#define ATH_MCI_CONFIG_AGGR_THRESH_S 8
+#define ATH_MCI_CONFIG_DISABLE_AGGR_THRESH 0x00000800
+#define ATH_MCI_CONFIG_CLK_DIV 0x00003000
+#define ATH_MCI_CONFIG_CLK_DIV_S 12
+#define ATH_MCI_CONFIG_DISABLE_TUNING 0x00004000
+#define ATH_MCI_CONFIG_DISABLE_AIC 0x00008000
+#define ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN 0x007f0000
+#define ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN_S 16
+#define ATH_MCI_CONFIG_NO_QUIET_ACK 0x00800000
+#define ATH_MCI_CONFIG_NO_QUIET_ACK_S 23
+#define ATH_MCI_CONFIG_ANT_ARCH 0x07000000
+#define ATH_MCI_CONFIG_ANT_ARCH_S 24
+#define ATH_MCI_CONFIG_FORCE_QUIET_ACK 0x08000000
+#define ATH_MCI_CONFIG_FORCE_QUIET_ACK_S 27
+#define ATH_MCI_CONFIG_FORCE_2CHAIN_ACK 0x10000000
+#define ATH_MCI_CONFIG_MCI_STAT_DBG 0x20000000
+#define ATH_MCI_CONFIG_MCI_WEIGHT_DBG 0x40000000
+#define ATH_MCI_CONFIG_DISABLE_MCI 0x80000000
+
+#define ATH_MCI_CONFIG_MCI_OBS_MASK ( ATH_MCI_CONFIG_MCI_OBS_MCI | \
+ ATH_MCI_CONFIG_MCI_OBS_TXRX | \
+ ATH_MCI_CONFIG_MCI_OBS_BT )
+#define ATH_MCI_CONFIG_MCI_OBS_GPIO 0x0000002F
+
+#define ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_NON_SHARED 0x00
+#define ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED 0x01
+#define ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_NON_SHARED 0x02
+#define ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_SHARED 0x03
+#define ATH_MCI_ANT_ARCH_3_ANT 0x04
+
+#define MCI_ANT_ARCH_PA_LNA_SHARED(c) \
+ ((MS(c, ATH_MCI_CONFIG_ANT_ARCH) == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED) || \
+ (MS(c, ATH_MCI_CONFIG_ANT_ARCH) == ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_SHARED))
+
+#define ATH_MCI_CONCUR_TX_SHARED_CHN 0x01
+#define ATH_MCI_CONCUR_TX_UNSHARED_CHN 0x02
+#define ATH_MCI_CONCUR_TX_DEBUG 0x03
+
+#endif
diff --git a/sys/dev/ath/ath_hal/ah_desc.h b/sys/dev/ath/ath_hal/ah_desc.h
index 9f58dce..151bb2c 100644
--- a/sys/dev/ath/ath_hal/ah_desc.h
+++ b/sys/dev/ath/ath_hal/ah_desc.h
@@ -280,7 +280,8 @@ struct ath_desc_status {
#define HAL_TXDESC_EXT_AND_CTL 0x0100 /* send on ext + ctl channels (11n) */
#define HAL_TXDESC_VMF 0x0200 /* virtual more frag */
#define HAL_TXDESC_LOWRXCHAIN 0x0400 /* switch to low RX chain */
-#define HAL_TXDESC_LDPC 0x1000
+#define HAL_TXDESC_LDPC 0x1000 /* Set LDPC TX for all rates */
+#define HAL_TXDESC_HWTS 0x2000 /* Request Azimuth Timestamp in TX payload */
/* flags passed to rx descriptor setup methods */
#define HAL_RXDESC_INTREQ 0x0020 /* enable per-descriptor interrupt */
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
index 88ba2b3..6fba375 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
@@ -352,6 +352,7 @@ ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
/*
* XXX For now, just assume that this isn't a HT40 frame.
+ * It'll get over-ridden by the multi-rate TX power setup.
*/
if (AH5212(ah)->ah_tpcEnabled) {
txPower = ar5416GetTxRatePower(ah, txRate0,
@@ -368,6 +369,7 @@ ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
;
ads->ds_ctl1 = (type << AR_FrameType_S)
| (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
+ | (flags & HAL_TXDESC_HWTS ? AR_InsertTS : 0)
;
ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0)
| (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEn : 0)
@@ -450,6 +452,10 @@ ar5416SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
return AH_TRUE;
}
+/*
+ * XXX TODO: Figure out if AR_InsertTS is required on all sub-frames
+ * of a TX descriptor.
+ */
HAL_BOOL
ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId,
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 87daaf3..949c7d5 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_ath_tx_edma.h>
#include <dev/ath/if_ath_beacon.h>
#include <dev/ath/if_ath_btcoex.h>
+#include <dev/ath/if_ath_btcoex_mci.h>
#include <dev/ath/if_ath_spectral.h>
#include <dev/ath/if_ath_lna_div.h>
#include <dev/ath/if_athdfs.h>
@@ -475,6 +476,10 @@ ath_setup_hal_config(struct ath_softc *sc, HAL_OPS_CONFIG *ah_config)
if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT)
device_printf(sc->sc_dev, "WB335 2-ANT card detected\n");
+ if (sc->sc_pci_devinfo & ATH_PCI_BT_ANT_DIV)
+ device_printf(sc->sc_dev,
+ "Bluetooth Antenna Diversity card detected\n");
+
if (sc->sc_pci_devinfo & ATH_PCI_KILLER)
device_printf(sc->sc_dev, "Killer Wireless card detected\n");
@@ -2254,6 +2259,9 @@ ath_intr(void *arg)
device_printf(sc->sc_dev, "%s: TSFOOR\n", __func__);
sc->sc_syncbeacon = 1;
}
+ if (status & HAL_INT_MCI) {
+ ath_btcoex_mci_intr(sc);
+ }
}
ATH_PCU_LOCK(sc);
sc->sc_intr_cnt--;
@@ -2549,6 +2557,12 @@ ath_init(struct ath_softc *sc)
sc->sc_imask |= HAL_INT_RXEOL;
/*
+ * Enable MCI interrupt for MCI devices.
+ */
+ if (sc->sc_btcoex_mci)
+ sc->sc_imask |= HAL_INT_MCI;
+
+ /*
* Enable MIB interrupts when there are hardware phy counters.
* Note we only do this (at the moment) for station mode.
*/
diff --git a/sys/dev/ath/if_ath_btcoex.c b/sys/dev/ath/if_ath_btcoex.c
index b78f866..ddd1c91 100644
--- a/sys/dev/ath/if_ath_btcoex.c
+++ b/sys/dev/ath/if_ath_btcoex.c
@@ -47,9 +47,9 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/errno.h>
-
#include <machine/bus.h>
#include <machine/resource.h>
+
#include <sys/bus.h>
#include <sys/socket.h>
@@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_athvar.h>
#include <dev/ath/if_ath_btcoex.h>
+#include <dev/ath/if_ath_btcoex_mci.h>
+
+MALLOC_DECLARE(M_ATHDEV);
/*
* Initial AR9285 / (WB195) bluetooth coexistence settings,
@@ -188,14 +191,8 @@ ath_btcoex_cfg_wb225(struct ath_softc *sc)
return (0);
}
-/*
- * Initial AR9462 / (WB222) bluetooth coexistence settings,
- * just for experimentation.
- *
- * Return 0 for OK; errno for error.
- */
static int
-ath_btcoex_cfg_wb222(struct ath_softc *sc)
+ath_btcoex_cfg_mci(struct ath_softc *sc, uint32_t mci_cfg, int do_btdiv)
{
HAL_BT_COEX_INFO btinfo;
HAL_BT_COEX_CONFIG btconfig;
@@ -207,7 +204,12 @@ ath_btcoex_cfg_wb222(struct ath_softc *sc)
bzero(&btinfo, sizeof(btinfo));
bzero(&btconfig, sizeof(btconfig));
- device_printf(sc->sc_dev, "Enabling WB222 BTCOEX\n");
+ sc->sc_ah->ah_config.ath_hal_mci_config = mci_cfg;
+
+ if (ath_btcoex_mci_attach(sc) != 0) {
+ device_printf(sc->sc_dev, "Failed to setup btcoex\n");
+ return (EINVAL);
+ }
btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */
btinfo.bt_coex_config = HAL_BT_COEX_CFG_MCI;
@@ -227,9 +229,13 @@ ath_btcoex_cfg_wb222(struct ath_softc *sc)
btinfo.bt_gpio_wlan_active = 5;
btinfo.bt_active_polarity = 1; /* XXX not used */
- btinfo.bt_single_ant = 0; /* 2 antenna on WB222 */
+ btinfo.bt_single_ant = 0; /* 2 antenna on WB335 */
btinfo.bt_isolation = 0; /* in dB, not used */
+ /* Implement a default dutycycle/period */
+ btinfo.bt_dutyCycle = 55;
+ btinfo.bt_period = 40;
+
ath_hal_btcoex_set_info(ah, &btinfo);
btconfig.bt_time_extend = 0;
@@ -244,16 +250,72 @@ ath_btcoex_cfg_wb222(struct ath_softc *sc)
ath_hal_btcoex_set_config(ah, &btconfig);
+ /* Enable */
+ ath_hal_btcoex_enable(sc->sc_ah);
+
+ /* Stomp */
+ ath_hal_btcoex_set_weights(ah, HAL_BT_COEX_STOMP_NONE);
+
/*
* Enable antenna diversity.
*/
- ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1);
+ ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY,
+ do_btdiv);
return (0);
}
+/*
+ * Initial AR9462 / (WB222) bluetooth coexistence settings.
+ *
+ * Return 0 for OK; errno for error.
+ */
+static int
+ath_btcoex_cfg_wb222(struct ath_softc *sc)
+{
+
+ device_printf(sc->sc_dev, "Enabling WB222 BTCOEX\n");
+ /* XXX from ath9k */
+ return (ath_btcoex_cfg_mci(sc, 0x2201, 1));
+}
+/*
+ * Initial QCA9565 / (WB335B) bluetooth coexistence settings.
+ *
+ * Return 0 for OK; errno for error.
+ */
+static int
+ath_btcoex_cfg_wb335b(struct ath_softc *sc)
+{
+ uint32_t flags;
+ int do_btdiv = 0;
+ /* ath9k default */
+ flags = 0xa4c1;
+
+ /* 1-ant and 2-ant AR9565 */
+ /*
+ * XXX TODO: ensure these actually make it down to the
+ * HAL correctly!
+ */
+ if (sc->sc_pci_devinfo & ATH_PCI_AR9565_1ANT) {
+ flags &= ~ATH_MCI_CONFIG_ANT_ARCH;
+ flags |= ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED <<
+ ATH_MCI_CONFIG_ANT_ARCH_S;
+ } else if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT) {
+ flags &= ~ATH_MCI_CONFIG_ANT_ARCH;
+ flags |= ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_NON_SHARED <<
+ ATH_MCI_CONFIG_ANT_ARCH_S;
+ }
+
+ if (sc->sc_pci_devinfo & ATH_PCI_BT_ANT_DIV) {
+ do_btdiv = 1;
+ }
+
+ device_printf(sc->sc_dev, "Enabling WB335 BTCOEX\n");
+ /* XXX from ath9k */
+ return (ath_btcoex_cfg_mci(sc, flags, do_btdiv));
+}
#if 0
/*
@@ -313,6 +375,8 @@ ath_btcoex_attach(struct ath_softc *sc)
ret = ath_btcoex_cfg_wb222(sc);
} else if (strncmp(profname, "wb225", 5) == 0) {
ret = ath_btcoex_cfg_wb225(sc);
+ } else if (strncmp(profname, "wb335", 5) == 0) {
+ ret = ath_btcoex_cfg_wb335b(sc);
} else {
return (0);
}
@@ -332,6 +396,9 @@ ath_btcoex_attach(struct ath_softc *sc)
int
ath_btcoex_detach(struct ath_softc *sc)
{
+ if (sc->sc_btcoex_mci) {
+ ath_btcoex_mci_detach(sc);
+ }
return (0);
}
@@ -348,6 +415,9 @@ ath_btcoex_detach(struct ath_softc *sc)
int
ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *chan)
{
+ if (sc->sc_btcoex_mci) {
+ ath_btcoex_mci_enable(sc, chan);
+ }
return (0);
}
diff --git a/sys/dev/ath/if_ath_btcoex.h b/sys/dev/ath/if_ath_btcoex.h
index 8b175d2..b35665b 100644
--- a/sys/dev/ath/if_ath_btcoex.h
+++ b/sys/dev/ath/if_ath_btcoex.h
@@ -31,6 +31,10 @@
#ifndef __IF_ATH_BTCOEX_H__
#define __IF_ATH_BTCOEX_H__
+typedef enum {
+ ATH_COEX_EVENT_BT_NOOP,
+} ATH_BT_COEX_EVENT;
+
extern int ath_btcoex_attach(struct ath_softc *sc);
extern int ath_btcoex_detach(struct ath_softc *sc);
extern int ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad);
diff --git a/sys/dev/ath/if_ath_btcoex_mci.c b/sys/dev/ath/if_ath_btcoex_mci.c
new file mode 100644
index 0000000..2953eed
--- /dev/null
+++ b/sys/dev/ath/if_ath_btcoex_mci.c
@@ -0,0 +1,655 @@
+/*-
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016 Adrian Chadd <adrian@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This implements the MCI bluetooth coexistence handling.
+ */
+#include "opt_ath.h"
+#include "opt_inet.h"
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/errno.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/bus.h>
+
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h> /* XXX for ether_sprintf */
+
+#include <net80211/ieee80211_var.h>
+
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <dev/ath/if_athvar.h>
+#include <dev/ath/if_ath_debug.h>
+#include <dev/ath/if_ath_descdma.h>
+#include <dev/ath/if_ath_btcoex.h>
+
+#include <dev/ath/if_ath_btcoex_mci.h>
+
+MALLOC_DECLARE(M_ATHDEV);
+
+#define ATH_MCI_GPM_MAX_ENTRY 16
+#define ATH_MCI_GPM_BUF_SIZE (ATH_MCI_GPM_MAX_ENTRY * 16)
+#define ATH_MCI_SCHED_BUF_SIZE (16 * 16) /* 16 entries, 4 dword each */
+
+static void ath_btcoex_mci_update_wlan_channels(struct ath_softc *sc);
+
+int
+ath_btcoex_mci_attach(struct ath_softc *sc)
+{
+ int buflen, error;
+
+ buflen = ATH_MCI_GPM_BUF_SIZE + ATH_MCI_SCHED_BUF_SIZE;
+ error = ath_descdma_alloc_desc(sc, &sc->sc_btcoex.buf, NULL,
+ "MCI bufs", buflen, 1);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: failed to alloc MCI RAM\n",
+ __func__);
+ return (error);
+ }
+
+ /* Yes, we're going to do bluetooth MCI coex */
+ sc->sc_btcoex_mci = 1;
+
+ /* Initialise the wlan channel mapping */
+ sc->sc_btcoex.wlan_channels[0] = 0x00000000;
+ sc->sc_btcoex.wlan_channels[1] = 0xffffffff;
+ sc->sc_btcoex.wlan_channels[2] = 0xffffffff;
+ sc->sc_btcoex.wlan_channels[3] = 0x7fffffff;
+
+ /*
+ * Ok, so the API is a bit odd. It assumes sched_addr is
+ * after gpm_addr, and it does math to figure out the right
+ * sched_buf pointer.
+ *
+ * So, set gpm_addr to buf, sched_addr to gpm_addr + ATH_MCI_GPM_BUF_SIZE,
+ * the HAL call with do (gpm_buf + (sched_addr - gpm_addr)) to
+ * set sched_buf, and we're "golden".
+ *
+ * Note, it passes in 'len' here (gpm_len) as
+ * ATH_MCI_GPM_BUF_SIZE >> 4. My guess is that it's 16
+ * bytes per entry and we're storing 16 entries.
+ */
+ sc->sc_btcoex.gpm_buf = (void *) sc->sc_btcoex.buf.dd_desc;
+ sc->sc_btcoex.sched_buf = sc->sc_btcoex.gpm_buf +
+ ATH_MCI_GPM_BUF_SIZE;
+
+ sc->sc_btcoex.gpm_paddr = sc->sc_btcoex.buf.dd_desc_paddr;
+ sc->sc_btcoex.sched_paddr = sc->sc_btcoex.gpm_paddr +
+ ATH_MCI_GPM_BUF_SIZE;
+
+ /* memset the gpm buffer with MCI_GPM_RSVD_PATTERN */
+ memset(sc->sc_btcoex.gpm_buf, 0xfe, buflen);
+
+ /*
+ * This is an unfortunate x86'ism in the HAL - the
+ * HAL code expects the passed in buffer to be
+ * coherent, and doesn't implement /any/ kind
+ * of buffer sync operations at all.
+ *
+ * So, this code will only work on dma coherent buffers
+ * and will behave poorly on non-coherent systems.
+ * Fixing this would require some HAL surgery so it
+ * actually /did/ the buffer flushing as appropriate.
+ */
+ ath_hal_btcoex_mci_setup(sc->sc_ah,
+ sc->sc_btcoex.gpm_paddr,
+ sc->sc_btcoex.gpm_buf,
+ ATH_MCI_GPM_BUF_SIZE >> 4,
+ sc->sc_btcoex.sched_paddr);
+
+ return (0);
+}
+
+/*
+ * Detach btcoex from the given interface
+ */
+int
+ath_btcoex_mci_detach(struct ath_softc *sc)
+{
+
+ ath_hal_btcoex_mci_detach(sc->sc_ah);
+ ath_descdma_cleanup(sc, &sc->sc_btcoex.buf, NULL);
+ return (0);
+}
+
+/*
+ * Configure or disable bluetooth coexistence on the given channel.
+ *
+ * For MCI, we just use the top-level enable/disable flag, and
+ * then the MCI reset / channel update path will configure things
+ * appropriately based on the current band.
+ */
+int
+ath_btcoex_mci_enable(struct ath_softc *sc,
+ const struct ieee80211_channel *chan)
+{
+
+ /*
+ * Always reconfigure stomp-all for now, so wlan wins.
+ *
+ * The default weights still don't allow beacons to win,
+ * so unless you set net.wlan.X.bmiss_max to something higher,
+ * net80211 will disconnect you during a HCI INQUIRY command.
+ *
+ * The longer-term solution is to dynamically adjust whether
+ * bmiss happens based on bluetooth requirements, and look at
+ * making the individual stomp bits configurable.
+ */
+ ath_hal_btcoex_set_weights(sc->sc_ah, HAL_BT_COEX_STOMP_ALL);
+
+ /*
+ * update wlan channels so the firmware knows what channels it
+ * can/can't use.
+ */
+ ath_btcoex_mci_update_wlan_channels(sc);
+
+ return (0);
+}
+
+/*
+ * XXX TODO: turn into general btcoex, and then make this
+ * the MCI specific bits.
+ */
+static void
+ath_btcoex_mci_event(struct ath_softc *sc, ATH_BT_COEX_EVENT nevent,
+ void *param)
+{
+
+ if (! sc->sc_btcoex_mci)
+ return;
+
+ /*
+ * Check whether we need to flush our local profile cache.
+ * If we do, then at (XXX TODO) we should flush our state,
+ * then wait for the MCI response with the updated profile list.
+ */
+ if (ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_NEED_FLUSH_BT_INFO, NULL) != 0) {
+ uint32_t data = 0;
+
+ if (ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_ENABLE, NULL) != 0) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Flush BT profile\n");
+ /*
+ * XXX TODO: flush profile state on the ath(4)
+ * driver side; subsequent messages will come
+ * through with the current list of active
+ * profiles.
+ */
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_NEED_FLUSH_BT_INFO, &data);
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SEND_STATUS_QUERY, NULL);
+ }
+ }
+ if (nevent == ATH_COEX_EVENT_BT_NOOP) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) BT_NOOP\n");
+ return;
+ }
+}
+
+static void
+ath_btcoex_mci_send_gpm(struct ath_softc *sc, uint32_t *payload)
+{
+
+ ath_hal_btcoex_mci_send_message(sc->sc_ah, MCI_GPM, 0, payload, 16,
+ AH_FALSE, AH_TRUE);
+}
+
+/*
+ * This starts a BT calibration. It requires a chip reset.
+ */
+static int
+ath_btcoex_mci_bt_cal_do(struct ath_softc *sc, int tx_timeout, int rx_timeout)
+{
+
+ device_printf(sc->sc_dev, "%s: TODO!\n", __func__);
+ return (0);
+}
+
+static void
+ath_btcoex_mci_cal_msg(struct ath_softc *sc, uint8_t opcode,
+ uint8_t *rx_payload)
+{
+ uint32_t payload[4] = {0, 0, 0, 0};
+
+ switch (opcode) {
+ case MCI_GPM_BT_CAL_REQ:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) receive BT_CAL_REQ\n");
+ if (ath_hal_btcoex_mci_state(sc->sc_ah, HAL_MCI_STATE_BT,
+ NULL) == MCI_BT_AWAKE) {
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SET_BT_CAL_START, NULL);
+ ath_btcoex_mci_bt_cal_do(sc, 1000, 1000);
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) State mismatches: %d\n",
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_BT, NULL));
+ }
+ break;
+ case MCI_GPM_BT_CAL_DONE:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) receive BT_CAL_DONE\n");
+ if (ath_hal_btcoex_mci_state(sc->sc_ah, HAL_MCI_STATE_BT,
+ NULL) == MCI_BT_CAL) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) ERROR ILLEGAL!\n");
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) BT not in CAL state.\n");
+ }
+ break;
+ case MCI_GPM_BT_CAL_GRANT:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) receive BT_CAL_GRANT\n");
+ /* Send WLAN_CAL_DONE for now */
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) Send WLAN_CAL_DONE\n");
+ MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE);
+ ath_btcoex_mci_send_gpm(sc, &payload[0]);
+ break;
+ default:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Unknown GPM CAL message.\n");
+ break;
+ }
+}
+
+/*
+ * Update the bluetooth channel map.
+ *
+ * This map tells the bluetooth device which bluetooth channels
+ * are available for data.
+ *
+ * For 5GHz, all channels are available.
+ * For 2GHz, the current wifi channel range is blocked out,
+ * and the rest are available.
+ *
+ * This narrows which frequencies are used by the device when
+ * it initiates a transfer, thus hopefully reducing the chances
+ * of collisions (both hopefully on the current device and
+ * other devices in the same channel.)
+ */
+static void
+ath_btcoex_mci_update_wlan_channels(struct ath_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_channel *chan = ic->ic_curchan;
+ uint32_t channel_info[4] =
+ { 0x00000000, 0xffffffff, 0xffffffff, 0x7fffffff };
+ int32_t wl_chan, bt_chan, bt_start = 0, bt_end = 79;
+
+ /* BT channel frequency is 2402 + k, k = 0 ~ 78 */
+ if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+ wl_chan = chan->ic_freq - 2402;
+ if (IEEE80211_IS_CHAN_HT40U(chan)) {
+ bt_start = wl_chan - 10;
+ bt_end = wl_chan + 30;
+ } else if (IEEE80211_IS_CHAN_HT40D(chan)) {
+ bt_start = wl_chan - 30;
+ bt_end = wl_chan + 10;
+ } else {
+ /* Assume 20MHz */
+ bt_start = wl_chan - 10;
+ bt_end = wl_chan + 10;
+ }
+
+ bt_start -= 7;
+ bt_end += 7;
+
+ if (bt_start < 0) {
+ bt_start = 0;
+ }
+ if (bt_end > MCI_NUM_BT_CHANNELS) {
+ bt_end = MCI_NUM_BT_CHANNELS;
+ }
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) WLAN use channel %d\n",
+ chan->ic_freq);
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) mask BT channel %d - %d\n", bt_start, bt_end);
+ for (bt_chan = bt_start; bt_chan < bt_end; bt_chan++) {
+ MCI_GPM_CLR_CHANNEL_BIT(&channel_info[0], bt_chan);
+ }
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) WLAN not use any 2G channel, unmask all for BT\n");
+ }
+ ath_hal_btcoex_mci_state(sc->sc_ah, HAL_MCI_STATE_SEND_WLAN_CHANNELS,
+ &channel_info[0]);
+}
+
+static void
+ath_btcoex_mci_coex_msg(struct ath_softc *sc, uint8_t opcode,
+ uint8_t *rx_payload)
+{
+ uint32_t version;
+ uint8_t major;
+ uint8_t minor;
+ uint32_t seq_num;
+
+ switch (opcode) {
+ case MCI_GPM_COEX_VERSION_QUERY:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Recv GPM COEX Version Query.\n");
+ version = ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SEND_WLAN_COEX_VERSION, NULL);
+ break;
+
+ case MCI_GPM_COEX_VERSION_RESPONSE:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Recv GPM COEX Version Response.\n");
+ major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION);
+ minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION);
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) BT Coex version: %d.%d\n", major, minor);
+ version = (major << 8) + minor;
+ version = ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SET_BT_COEX_VERSION, &version);
+ break;
+
+ case MCI_GPM_COEX_STATUS_QUERY:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Recv GPM COEX Status Query = 0x%02x.\n",
+ *(rx_payload + MCI_GPM_COEX_B_WLAN_BITMAP));
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SEND_WLAN_CHANNELS, NULL);
+ break;
+
+ case MCI_GPM_COEX_BT_PROFILE_INFO:
+ /*
+ * XXX TODO: here is where we'd parse active profile
+ * info and make driver/stack choices as appropriate.
+ */
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) TODO: Recv GPM COEX BT_Profile_Info.\n");
+ break;
+
+ case MCI_GPM_COEX_BT_STATUS_UPDATE:
+ seq_num = *((uint32_t *)(rx_payload + 12));
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Recv GPM COEX BT_Status_Update: SEQ=%d\n",
+ seq_num);
+ break;
+
+ default:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Unknown GPM COEX message = 0x%02x\n", opcode);
+ break;
+ }
+}
+
+void
+ath_btcoex_mci_intr(struct ath_softc *sc)
+{
+ uint32_t mciInt, mciIntRxMsg;
+ uint32_t offset, subtype, opcode;
+ uint32_t *pGpm;
+ uint32_t more_data = HAL_MCI_GPM_MORE;
+ int8_t value_dbm;
+ bool skip_gpm = false;
+
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: called\n", __func__);
+
+ ath_hal_btcoex_mci_get_interrupt(sc->sc_ah, &mciInt, &mciIntRxMsg);
+
+ if (ath_hal_btcoex_mci_state(sc->sc_ah, HAL_MCI_STATE_ENABLE,
+ NULL) == 0) {
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_INIT_GPM_OFFSET, NULL);
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) INTR but MCI_disabled\n");
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) MCI interrupt: mciInt = 0x%x, mciIntRxMsg = 0x%x\n",
+ mciInt, mciIntRxMsg);
+ return;
+ }
+
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE) {
+ uint32_t payload4[4] = { 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffff00};
+
+ /*
+ * The following REMOTE_RESET and SYS_WAKING used to sent
+ * only when BT wake up. Now they are always sent, as a
+ * recovery method to reset BT MCI's RX alignment.
+ */
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 1. INTR Send REMOTE_RESET\n");
+ ath_hal_btcoex_mci_send_message(sc->sc_ah,
+ MCI_REMOTE_RESET, 0, payload4, 16, AH_TRUE, AH_FALSE);
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 1. INTR Send SYS_WAKING\n");
+ ath_hal_btcoex_mci_send_message(sc->sc_ah,
+ MCI_SYS_WAKING, 0, NULL, 0, AH_TRUE, AH_FALSE);
+
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE;
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_RESET_REQ_WAKE, NULL);
+
+ /* always do this for recovery and 2G/5G toggling and LNA_TRANS */
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 1. Set BT state to AWAKE.\n");
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SET_BT_AWAKE, NULL);
+ }
+
+ /* Processing SYS_WAKING/SYS_SLEEPING */
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING;
+ if (ath_hal_btcoex_mci_state(sc->sc_ah, HAL_MCI_STATE_BT,
+ NULL) == MCI_BT_SLEEP) {
+ if (ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_REMOTE_SLEEP, NULL) == MCI_BT_SLEEP) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 2. BT stays in SLEEP mode.\n");
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 2. Set BT state to AWAKE.\n");
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SET_BT_AWAKE, NULL);
+ }
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 2. BT stays in AWAKE mode.\n");
+ }
+ }
+
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING;
+ if (ath_hal_btcoex_mci_state(sc->sc_ah, HAL_MCI_STATE_BT,
+ NULL) == MCI_BT_AWAKE) {
+ if (ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_REMOTE_SLEEP, NULL) == MCI_BT_AWAKE) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 3. BT stays in AWAKE mode.\n");
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 3. Set BT state to SLEEP.\n");
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_SET_BT_SLEEP, NULL);
+ }
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) 3. BT stays in SLEEP mode.\n");
+ }
+ }
+
+ /*
+ * Recover from out-of-order / wrong-offset GPM messages.
+ */
+ if ((mciInt & HAL_MCI_INTERRUPT_RX_INVALID_HDR) ||
+ (mciInt & HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) MCI RX broken, skip GPM messages\n");
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_RECOVER_RX, NULL);
+ skip_gpm = true;
+ }
+
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
+ offset = ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET, NULL);
+ }
+
+ /*
+ * Parse GPM messages.
+ */
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_GPM) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_GPM;
+
+ while (more_data == HAL_MCI_GPM_MORE) {
+ pGpm = (void *) sc->sc_btcoex.gpm_buf;
+ offset = ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
+
+ if (offset == HAL_MCI_GPM_INVALID)
+ break;
+ pGpm += (offset >> 2);
+ /*
+ * The first DWORD is a timer.
+ * The real data starts from the second DWORD.
+ */
+ subtype = MCI_GPM_TYPE(pGpm);
+ opcode = MCI_GPM_OPCODE(pGpm);
+
+ if (!skip_gpm) {
+ if (MCI_GPM_IS_CAL_TYPE(subtype)) {
+ ath_btcoex_mci_cal_msg(sc, subtype,
+ (uint8_t*) pGpm);
+ } else {
+ switch (subtype) {
+ case MCI_GPM_COEX_AGENT:
+ ath_btcoex_mci_coex_msg(sc,
+ opcode, (uint8_t*) pGpm);
+ break;
+ case MCI_GPM_BT_DEBUG:
+ device_printf(sc->sc_dev,
+ "(MCI) TODO: GPM_BT_DEBUG!\n");
+ break;
+ default:
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Unknown GPM message.\n");
+ break;
+ }
+ }
+ }
+ MCI_GPM_RECYCLE(pGpm);
+ }
+ }
+
+ /*
+ * This is monitoring/management information messages, so the driver
+ * layer can hook in and dynamically adjust things like aggregation
+ * size, expected bluetooth/wifi traffic throughput, etc.
+ *
+ * None of that is done right now; it just passes off the values
+ * to the HAL so it can update its internal state as appropriate.
+ * This code just prints out the values for debugging purposes.
+ */
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_MONITOR) {
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL;
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) LNA_CONTROL\n");
+ }
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO;
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) LNA_INFO\n");
+ }
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
+ value_dbm = ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_CONT_RSSI_POWER, NULL);
+
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO;
+ if (ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_CONT_TXRX, NULL)) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) CONT_INFO: (tx) pri = %d, pwr = %d dBm\n",
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_CONT_PRIORITY, NULL),
+ value_dbm);
+ } else {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) CONT_INFO: (rx) pri = %d, rssi = %d dBm\n",
+ ath_hal_btcoex_mci_state(sc->sc_ah,
+ HAL_MCI_STATE_CONT_PRIORITY, NULL),
+ value_dbm);
+ }
+ }
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK;
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) CONT_NACK\n");
+ }
+ if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_CONT_RST) {
+ mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_CONT_RST;
+ DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) CONT_RST\n");
+ }
+ }
+
+ /*
+ * Recover the state engine if we hit an invalid header/timeout.
+ * This is the final part of GPT out-of-sync recovery.
+ */
+ if ((mciInt & HAL_MCI_INTERRUPT_RX_INVALID_HDR) ||
+ (mciInt & HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
+ ath_btcoex_mci_event(sc, ATH_COEX_EVENT_BT_NOOP, NULL);
+ mciInt &= ~(HAL_MCI_INTERRUPT_RX_INVALID_HDR |
+ HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT);
+ }
+
+ if (mciIntRxMsg & 0xfffffffe) {
+ DPRINTF(sc, ATH_DEBUG_BTCOEX,
+ "(MCI) Not processed IntRxMsg = 0x%x\n", mciIntRxMsg);
+ }
+}
diff --git a/sys/dev/ath/if_ath_btcoex_mci.h b/sys/dev/ath/if_ath_btcoex_mci.h
new file mode 100644
index 0000000..3db3804
--- /dev/null
+++ b/sys/dev/ath/if_ath_btcoex_mci.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2016 Adrian Chadd <adrian@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#ifndef __IF_ATH_BTCOEX_MCI_H__
+#define __IF_ATH_BTCOEX_MCI_H__
+
+#define ATH_MCI_NUM_BT_CHANNELS 79
+
+extern int ath_btcoex_mci_attach(struct ath_softc *sc);
+extern int ath_btcoex_mci_detach(struct ath_softc *sc);
+extern int ath_btcoex_mci_enable(struct ath_softc *sc,
+ const struct ieee80211_channel *chan);
+extern void ath_btcoex_mci_intr(struct ath_softc *sc);
+
+#endif /* __IF_ATH_BTCOEX_MCI_H__ */
diff --git a/sys/dev/ath/if_ath_debug.h b/sys/dev/ath/if_ath_debug.h
index 5d47139..8a04790 100644
--- a/sys/dev/ath/if_ath_debug.h
+++ b/sys/dev/ath/if_ath_debug.h
@@ -69,6 +69,7 @@ enum {
ATH_DEBUG_NODE_PWRSAVE = 0x800000000ULL, /* node powersave */
ATH_DEBUG_DIVERSITY = 0x1000000000ULL, /* Diversity logic */
ATH_DEBUG_PWRSAVE = 0x2000000000ULL,
+ ATH_DEBUG_BTCOEX = 0x4000000000ULL, /* BT Coex */
ATH_DEBUG_ANY = 0xffffffffffffffffULL
};
@@ -92,9 +93,9 @@ enum {
extern uint64_t ath_debug;
#define IFF_DUMPPKTS(sc, m) (sc->sc_debug & (m))
-#define DPRINTF(sc, m, fmt, ...) do { \
+#define DPRINTF(sc, m, ...) do { \
if (sc->sc_debug & (m)) \
- device_printf(sc->sc_dev, fmt, __VA_ARGS__); \
+ device_printf(sc->sc_dev, __VA_ARGS__); \
} while (0)
#define KEYPRINTF(sc, ix, hk, mac) do { \
if (sc->sc_debug & ATH_DEBUG_KEYCACHE) \
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index d08df69..d2b1d85 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -1738,6 +1738,15 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
}
#endif
+#if 0
+ /*
+ * Placeholder: if you want to transmit with the azimuth
+ * timestamp in the end of the payload, here's where you
+ * should set the TXDESC field.
+ */
+ flags |= HAL_TXDESC_HWTS;
+#endif
+
/*
* Determine if a tx interrupt should be generated for
* this descriptor. We take a tx interrupt to reap
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 9052ebe..036b609 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -656,7 +656,8 @@ struct ath_softc {
sc_has_ldpc : 1,
sc_hasenforcetxop : 1, /* support enforce TxOP */
sc_hasdivcomb : 1, /* RX diversity combining */
- sc_rx_lnamixer : 1; /* RX using LNA mixing */
+ sc_rx_lnamixer : 1, /* RX using LNA mixing */
+ sc_btcoex_mci : 1; /* MCI bluetooth coex */
int sc_cabq_enable; /* Enable cabq transmission */
@@ -908,6 +909,19 @@ struct ath_softc {
/* ATH_PCI_* flags */
uint32_t sc_pci_devinfo;
+
+ /* BT coex */
+ struct {
+ struct ath_descdma buf;
+
+ /* gpm/sched buffer, saved pointers */
+ char *sched_buf;
+ bus_addr_t sched_paddr;
+ char *gpm_buf;
+ bus_addr_t gpm_paddr;
+
+ uint32_t wlan_channels[4];
+ } sc_btcoex;
};
#define ATH_LOCK_INIT(_sc) \
@@ -1488,8 +1502,6 @@ void ath_intr(void *);
((*(_ah)->ah_btCoexSetQcuThresh)((_ah), (_qcuid)))
#define ath_hal_btcoex_set_weights(_ah, _weight) \
((*(_ah)->ah_btCoexSetWeights)((_ah), (_weight)))
-#define ath_hal_btcoex_set_weights(_ah, _weight) \
- ((*(_ah)->ah_btCoexSetWeights)((_ah), (_weight)))
#define ath_hal_btcoex_set_bmiss_thresh(_ah, _thr) \
((*(_ah)->ah_btCoexSetBmissThresh)((_ah), (_thr)))
#define ath_hal_btcoex_set_parameter(_ah, _attrib, _val) \
@@ -1499,6 +1511,17 @@ void ath_intr(void *);
#define ath_hal_btcoex_disable(_ah) \
((*(_ah)->ah_btCoexDisable)((_ah)))
+#define ath_hal_btcoex_mci_setup(_ah, _gp, _gb, _gl, _sp) \
+ ((*(_ah)->ah_btMciSetup)((_ah), (_gp), (_gb), (_gl), (_sp)))
+#define ath_hal_btcoex_mci_send_message(_ah, _h, _f, _p, _l, _wd, _cbt) \
+ ((*(_ah)->ah_btMciSendMessage)((_ah), (_h), (_f), (_p), (_l), (_wd), (_cbt)))
+#define ath_hal_btcoex_mci_get_interrupt(_ah, _mi, _mm) \
+ ((*(_ah)->ah_btMciGetInterrupt)((_ah), (_mi), (_mm)))
+#define ath_hal_btcoex_mci_state(_ah, _st, _pd) \
+ ((*(_ah)->ah_btMciState)((_ah), (_st), (_pd)))
+#define ath_hal_btcoex_mci_detach(_ah) \
+ ((*(_ah)->ah_btMciDetach)((_ah)))
+
#define ath_hal_div_comb_conf_get(_ah, _conf) \
((*(_ah)->ah_divLnaConfGet)((_ah), (_conf)))
#define ath_hal_div_comb_conf_set(_ah, _conf) \
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 007ec63..929bedc 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -171,6 +171,7 @@ static const struct bge_type {
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5715 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5715S },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5717 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM5717C },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5718 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5719 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5720 },
@@ -311,6 +312,7 @@ static const struct bge_revision {
{ BGE_CHIPID_BCM5715_A3, "BCM5715 A3" },
{ BGE_CHIPID_BCM5717_A0, "BCM5717 A0" },
{ BGE_CHIPID_BCM5717_B0, "BCM5717 B0" },
+ { BGE_CHIPID_BCM5717_C0, "BCM5717 C0" },
{ BGE_CHIPID_BCM5719_A0, "BCM5719 A0" },
{ BGE_CHIPID_BCM5720_A0, "BCM5720 A0" },
{ BGE_CHIPID_BCM5755_A0, "BCM5755 A0" },
@@ -2698,6 +2700,10 @@ bge_chipid(device_t dev)
* registers.
*/
switch (pci_get_device(dev)) {
+ case BCOM_DEVICEID_BCM5717C:
+ /* 5717 C0 seems to belong to 5720 line. */
+ id = BGE_CHIPID_BCM5720_A0;
+ break;
case BCOM_DEVICEID_BCM5717:
case BCOM_DEVICEID_BCM5718:
case BCOM_DEVICEID_BCM5719:
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index 37b0459..0cf9ca1 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -329,6 +329,7 @@
#define BGE_CHIPID_BCM57780_A1 0x57780001
#define BGE_CHIPID_BCM5717_A0 0x05717000
#define BGE_CHIPID_BCM5717_B0 0x05717100
+#define BGE_CHIPID_BCM5717_C0 0x05717200
#define BGE_CHIPID_BCM5719_A0 0x05719000
#define BGE_CHIPID_BCM5720_A0 0x05720000
#define BGE_CHIPID_BCM5762_A0 0x05762000
@@ -2452,6 +2453,7 @@ struct bge_status_block {
#define BCOM_DEVICEID_BCM5715 0x1678
#define BCOM_DEVICEID_BCM5715S 0x1679
#define BCOM_DEVICEID_BCM5717 0x1655
+#define BCOM_DEVICEID_BCM5717C 0x1665
#define BCOM_DEVICEID_BCM5718 0x1656
#define BCOM_DEVICEID_BCM5719 0x1657
#define BCOM_DEVICEID_BCM5720_PP 0x1658 /* Not released to public. */
diff --git a/sys/dev/cesa/cesa.c b/sys/dev/cesa/cesa.c
index 4d71ae0..ec5a973 100644
--- a/sys/dev/cesa/cesa.c
+++ b/sys/dev/cesa/cesa.c
@@ -27,15 +27,15 @@
/*
* CESA SRAM Memory Map:
*
- * +------------------------+ <= sc->sc_sram_base + CESA_SRAM_SIZE
+ * +------------------------+ <= sc->sc_sram_base_va + CESA_SRAM_SIZE
* | |
* | DATA |
* | |
- * +------------------------+ <= sc->sc_sram_base + CESA_DATA(0)
+ * +------------------------+ <= sc->sc_sram_base_va + CESA_DATA(0)
* | struct cesa_sa_data |
* +------------------------+
* | struct cesa_sa_hdesc |
- * +------------------------+ <= sc->sc_sram_base
+ * +------------------------+ <= sc->sc_sram_base_va
*/
#include <sys/cdefs.h>
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/resource.h>
+#include <machine/fdt.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
@@ -62,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/md5.h>
#include <crypto/sha1.h>
+#include <crypto/sha2/sha256.h>
#include <crypto/rijndael/rijndael.h>
#include <opencrypto/cryptodev.h>
#include "cryptodev_if.h"
@@ -82,6 +84,7 @@ static int decode_win_cesa_setup(struct cesa_softc *sc);
static struct resource_spec cesa_res_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
{ -1, 0 }
};
@@ -373,7 +376,7 @@ static struct cesa_tdma_desc *
cesa_tdma_copyin_sa_data(struct cesa_softc *sc, struct cesa_request *cr)
{
- return (cesa_tdma_copy(sc, sc->sc_sram_base +
+ return (cesa_tdma_copy(sc, sc->sc_sram_base_pa +
sizeof(struct cesa_sa_hdesc), cr->cr_csd_paddr,
sizeof(struct cesa_sa_data)));
}
@@ -382,7 +385,7 @@ static struct cesa_tdma_desc *
cesa_tdma_copyout_sa_data(struct cesa_softc *sc, struct cesa_request *cr)
{
- return (cesa_tdma_copy(sc, cr->cr_csd_paddr, sc->sc_sram_base +
+ return (cesa_tdma_copy(sc, cr->cr_csd_paddr, sc->sc_sram_base_pa +
sizeof(struct cesa_sa_hdesc), sizeof(struct cesa_sa_data)));
}
@@ -390,7 +393,7 @@ static struct cesa_tdma_desc *
cesa_tdma_copy_sdesc(struct cesa_softc *sc, struct cesa_sa_desc *csd)
{
- return (cesa_tdma_copy(sc, sc->sc_sram_base, csd->csd_cshd_paddr,
+ return (cesa_tdma_copy(sc, sc->sc_sram_base_pa, csd->csd_cshd_paddr,
sizeof(struct cesa_sa_hdesc)));
}
@@ -447,6 +450,7 @@ cesa_set_mkey(struct cesa_session *cs, int alg, const uint8_t *mkey, int mklen)
uint8_t ipad[CESA_MAX_HMAC_BLOCK_LEN];
uint8_t opad[CESA_MAX_HMAC_BLOCK_LEN];
SHA1_CTX sha1ctx;
+ SHA256_CTX sha256ctx;
MD5_CTX md5ctx;
uint32_t *hout;
uint32_t *hin;
@@ -479,6 +483,14 @@ cesa_set_mkey(struct cesa_session *cs, int alg, const uint8_t *mkey, int mklen)
SHA1Update(&sha1ctx, opad, SHA1_HMAC_BLOCK_LEN);
memcpy(hout, sha1ctx.h.b32, sizeof(sha1ctx.h.b32));
break;
+ case CRYPTO_SHA2_256_HMAC:
+ SHA256_Init(&sha256ctx);
+ SHA256_Update(&sha256ctx, ipad, SHA2_256_HMAC_BLOCK_LEN);
+ memcpy(hin, sha256ctx.state, sizeof(sha256ctx.state));
+ SHA256_Init(&sha256ctx);
+ SHA256_Update(&sha256ctx, opad, SHA2_256_HMAC_BLOCK_LEN);
+ memcpy(hout, sha256ctx.state, sizeof(sha256ctx.state));
+ break;
default:
return (EINVAL);
}
@@ -539,6 +551,7 @@ cesa_is_hash(int alg)
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1:
case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA2_256_HMAC:
return (1);
default:
return (0);
@@ -566,14 +579,14 @@ cesa_fill_packet(struct cesa_softc *sc, struct cesa_packet *cp,
bsize = MIN(seg->ds_len, cp->cp_size - cp->cp_offset);
if (bsize > 0) {
- ctd = cesa_tdma_copy(sc, sc->sc_sram_base +
+ ctd = cesa_tdma_copy(sc, sc->sc_sram_base_pa +
CESA_DATA(cp->cp_offset), seg->ds_addr, bsize);
if (!ctd)
return (-ENOMEM);
STAILQ_INSERT_TAIL(&cp->cp_copyin, ctd, ctd_stq);
- ctd = cesa_tdma_copy(sc, seg->ds_addr, sc->sc_sram_base +
+ ctd = cesa_tdma_copy(sc, seg->ds_addr, sc->sc_sram_base_pa +
CESA_DATA(cp->cp_offset), bsize);
if (!ctd)
return (-ENOMEM);
@@ -939,8 +952,12 @@ cesa_execute(struct cesa_softc *sc)
cr = STAILQ_FIRST(&sc->sc_queued_requests);
ctd = STAILQ_FIRST(&cr->cr_tdesc);
- CESA_WRITE(sc, CESA_TDMA_ND, ctd->ctd_cthd_paddr);
- CESA_WRITE(sc, CESA_SA_CMD, CESA_SA_CMD_ACTVATE);
+ CESA_TDMA_WRITE(sc, CESA_TDMA_ND, ctd->ctd_cthd_paddr);
+#if defined (SOC_MV_ARMADA38X)
+ CESA_REG_WRITE(sc, CESA_SA_CMD, CESA_SA_CMD_ACTVATE | CESA_SA_CMD_SHA2);
+#else
+ CESA_REG_WRITE(sc, CESA_SA_CMD, CESA_SA_CMD_ACTVATE);
+#endif
CESA_UNLOCK(sc, requests);
}
@@ -950,22 +967,33 @@ cesa_setup_sram(struct cesa_softc *sc)
{
phandle_t sram_node;
ihandle_t sram_ihandle;
- pcell_t sram_handle, sram_reg;
+ pcell_t sram_handle, sram_reg[2];
+ int rv;
- if (OF_getprop(ofw_bus_get_node(sc->sc_dev), "sram-handle",
- (void *)&sram_handle, sizeof(sram_handle)) <= 0)
- return (ENXIO);
+ rv = OF_getprop(ofw_bus_get_node(sc->sc_dev), "sram-handle",
+ (void *)&sram_handle, sizeof(sram_handle));
+ if (rv <= 0)
+ return (rv);
sram_ihandle = (ihandle_t)sram_handle;
sram_ihandle = fdt32_to_cpu(sram_ihandle);
sram_node = OF_instance_to_package(sram_ihandle);
- if (OF_getprop(sram_node, "reg", (void *)&sram_reg,
- sizeof(sram_reg)) <= 0)
- return (ENXIO);
+ rv = OF_getprop(sram_node, "reg", (void *)sram_reg, sizeof(sram_reg));
+ if (rv <= 0)
+ return (rv);
- sc->sc_sram_base = fdt32_to_cpu(sram_reg);
+ sc->sc_sram_base_pa = fdt32_to_cpu(sram_reg[0]);
+ /* Store SRAM size to be able to unmap in detach() */
+ sc->sc_sram_size = fdt32_to_cpu(sram_reg[1]);
+#if defined(SOC_MV_ARMADA38X)
+ /* SRAM memory was not mapped in platform_sram_devmap(), map it now */
+ rv = bus_space_map(fdtbus_bs_tag, sc->sc_sram_base_pa, sc->sc_sram_size,
+ 0, &(sc->sc_sram_base_va));
+ if (rv != 0)
+ return (rv);
+#endif
return (0);
}
@@ -1015,6 +1043,7 @@ cesa_attach(device_t dev)
switch (d) {
case MV_DEV_88F6281:
case MV_DEV_88F6282:
+ case MV_DEV_88F6828:
sc->sc_tperr = 0;
break;
case MV_DEV_MV78100:
@@ -1044,9 +1073,6 @@ cesa_attach(device_t dev)
goto err0;
}
- sc->sc_bsh = rman_get_bushandle(*(sc->sc_res));
- sc->sc_bst = rman_get_bustag(*(sc->sc_res));
-
/* Setup CESA decoding windows */
error = decode_win_cesa_setup(sc);
if (error) {
@@ -1062,11 +1088,11 @@ cesa_attach(device_t dev)
}
/* Setup interrupt handler */
- error = bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_NET | INTR_MPSAFE,
- NULL, cesa_intr, sc, &(sc->sc_icookie));
+ error = bus_setup_intr(dev, sc->sc_res[RES_CESA_IRQ], INTR_TYPE_NET |
+ INTR_MPSAFE, NULL, cesa_intr, sc, &(sc->sc_icookie));
if (error) {
device_printf(dev, "could not setup engine completion irq\n");
- goto err1;
+ goto err2;
}
/* Create DMA tag for processed data */
@@ -1081,13 +1107,13 @@ cesa_attach(device_t dev)
NULL, NULL, /* lockfunc, lockfuncarg */
&sc->sc_data_dtag); /* dmat */
if (error)
- goto err2;
+ goto err3;
/* Initialize data structures: TDMA Descriptors Pool */
error = cesa_alloc_dma_mem(sc, &sc->sc_tdesc_cdm,
CESA_TDMA_DESCRIPTORS * sizeof(struct cesa_tdma_hdesc));
if (error)
- goto err3;
+ goto err4;
STAILQ_INIT(&sc->sc_free_tdesc);
for (i = 0; i < CESA_TDMA_DESCRIPTORS; i++) {
@@ -1103,7 +1129,7 @@ cesa_attach(device_t dev)
error = cesa_alloc_dma_mem(sc, &sc->sc_sdesc_cdm,
CESA_SA_DESCRIPTORS * sizeof(struct cesa_sa_hdesc));
if (error)
- goto err4;
+ goto err5;
STAILQ_INIT(&sc->sc_free_sdesc);
for (i = 0; i < CESA_SA_DESCRIPTORS; i++) {
@@ -1119,7 +1145,7 @@ cesa_attach(device_t dev)
error = cesa_alloc_dma_mem(sc, &sc->sc_requests_cdm,
CESA_REQUESTS * sizeof(struct cesa_sa_data));
if (error)
- goto err5;
+ goto err6;
STAILQ_INIT(&sc->sc_free_requests);
STAILQ_INIT(&sc->sc_ready_requests);
@@ -1141,7 +1167,7 @@ cesa_attach(device_t dev)
sc->sc_requests[i].cr_dmap);
} while (i--);
- goto err6;
+ goto err7;
}
STAILQ_INSERT_TAIL(&sc->sc_free_requests, &sc->sc_requests[i],
@@ -1162,8 +1188,12 @@ cesa_attach(device_t dev)
* - Outstanding reads enabled,
* - No byte-swap.
*/
- CESA_WRITE(sc, CESA_TDMA_CR, CESA_TDMA_CR_DBL128 | CESA_TDMA_CR_SBL128 |
- CESA_TDMA_CR_ORDEN | CESA_TDMA_CR_NBS | CESA_TDMA_CR_ENABLE);
+ CESA_TDMA_WRITE(sc, CESA_TDMA_CR, CESA_TDMA_CR_DBL128 |
+ CESA_TDMA_CR_SBL128 | CESA_TDMA_CR_ORDEN | CESA_TDMA_CR_NBS |
+#if defined (SOC_MV_ARMADA38X)
+ CESA_TDMA_NUM_OUTSTAND |
+#endif
+ CESA_TDMA_CR_ENABLE);
/*
* Initialize SA:
@@ -1171,23 +1201,23 @@ cesa_attach(device_t dev)
* - Multi-packet chain mode,
* - Cooperation with TDMA enabled.
*/
- CESA_WRITE(sc, CESA_SA_DPR, 0);
- CESA_WRITE(sc, CESA_SA_CR, CESA_SA_CR_ACTIVATE_TDMA |
+ CESA_REG_WRITE(sc, CESA_SA_DPR, 0);
+ CESA_REG_WRITE(sc, CESA_SA_CR, CESA_SA_CR_ACTIVATE_TDMA |
CESA_SA_CR_WAIT_FOR_TDMA | CESA_SA_CR_MULTI_MODE);
/* Unmask interrupts */
- CESA_WRITE(sc, CESA_ICR, 0);
- CESA_WRITE(sc, CESA_ICM, CESA_ICM_ACCTDMA | sc->sc_tperr);
- CESA_WRITE(sc, CESA_TDMA_ECR, 0);
- CESA_WRITE(sc, CESA_TDMA_EMR, CESA_TDMA_EMR_MISS |
+ CESA_REG_WRITE(sc, CESA_ICR, 0);
+ CESA_REG_WRITE(sc, CESA_ICM, CESA_ICM_ACCTDMA | sc->sc_tperr);
+ CESA_TDMA_WRITE(sc, CESA_TDMA_ECR, 0);
+ CESA_TDMA_WRITE(sc, CESA_TDMA_EMR, CESA_TDMA_EMR_MISS |
CESA_TDMA_EMR_DOUBLE_HIT | CESA_TDMA_EMR_BOTH_HIT |
CESA_TDMA_EMR_DATA_ERROR);
/* Register in OCF */
sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
- if (sc->sc_cid) {
+ if (sc->sc_cid < 0) {
device_printf(dev, "could not get crypto driver id\n");
- goto err7;
+ goto err8;
}
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
@@ -1197,22 +1227,27 @@ cesa_attach(device_t dev)
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
+ crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0);
return (0);
-err7:
+err8:
for (i = 0; i < CESA_REQUESTS; i++)
bus_dmamap_destroy(sc->sc_data_dtag,
sc->sc_requests[i].cr_dmap);
-err6:
+err7:
cesa_free_dma_mem(&sc->sc_requests_cdm);
-err5:
+err6:
cesa_free_dma_mem(&sc->sc_sdesc_cdm);
-err4:
+err5:
cesa_free_dma_mem(&sc->sc_tdesc_cdm);
-err3:
+err4:
bus_dma_tag_destroy(sc->sc_data_dtag);
+err3:
+ bus_teardown_intr(dev, sc->sc_res[RES_CESA_IRQ], sc->sc_icookie);
err2:
- bus_teardown_intr(dev, sc->sc_res[1], sc->sc_icookie);
+#if defined(SOC_MV_ARMADA38X)
+ bus_space_unmap(fdtbus_bs_tag, sc->sc_sram_base_va, sc->sc_sram_size);
+#endif
err1:
bus_release_resources(dev, cesa_res_spec, sc->sc_res);
err0:
@@ -1235,8 +1270,8 @@ cesa_detach(device_t dev)
/* TODO: Wait for queued requests completion before shutdown. */
/* Mask interrupts */
- CESA_WRITE(sc, CESA_ICM, 0);
- CESA_WRITE(sc, CESA_TDMA_EMR, 0);
+ CESA_REG_WRITE(sc, CESA_ICM, 0);
+ CESA_TDMA_WRITE(sc, CESA_TDMA_EMR, 0);
/* Unregister from OCF */
crypto_unregister_all(sc->sc_cid);
@@ -1255,11 +1290,15 @@ cesa_detach(device_t dev)
bus_dma_tag_destroy(sc->sc_data_dtag);
/* Stop interrupt */
- bus_teardown_intr(dev, sc->sc_res[1], sc->sc_icookie);
+ bus_teardown_intr(dev, sc->sc_res[RES_CESA_IRQ], sc->sc_icookie);
/* Relase I/O and IRQ resources */
bus_release_resources(dev, cesa_res_spec, sc->sc_res);
+#if defined(SOC_MV_ARMADA38X)
+ /* Unmap SRAM memory */
+ bus_space_unmap(fdtbus_bs_tag, sc->sc_sram_base_va, sc->sc_sram_size);
+#endif
/* Destroy mutexes */
mtx_destroy(&sc->sc_sessions_lock);
mtx_destroy(&sc->sc_requests_lock);
@@ -1282,10 +1321,10 @@ cesa_intr(void *arg)
sc = arg;
/* Ack interrupt */
- ecr = CESA_READ(sc, CESA_TDMA_ECR);
- CESA_WRITE(sc, CESA_TDMA_ECR, 0);
- icr = CESA_READ(sc, CESA_ICR);
- CESA_WRITE(sc, CESA_ICR, 0);
+ ecr = CESA_TDMA_READ(sc, CESA_TDMA_ECR);
+ CESA_TDMA_WRITE(sc, CESA_TDMA_ECR, 0);
+ icr = CESA_REG_READ(sc, CESA_ICR);
+ CESA_REG_WRITE(sc, CESA_ICR, 0);
/* Check for TDMA errors */
if (ecr & CESA_TDMA_ECR_MISS) {
@@ -1432,24 +1471,38 @@ cesa_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri)
if (!error && mac) {
switch (mac->cri_alg) {
case CRYPTO_MD5:
- cs->cs_config |= CESA_CSHD_MD5;
cs->cs_mblen = 1;
- cs->cs_hlen = MD5_HASH_LEN;
+ cs->cs_hlen = (mac->cri_mlen == 0) ? MD5_HASH_LEN :
+ mac->cri_mlen;
+ cs->cs_config |= CESA_CSHD_MD5;
break;
case CRYPTO_MD5_HMAC:
- cs->cs_config |= CESA_CSHD_MD5_HMAC;
cs->cs_mblen = MD5_HMAC_BLOCK_LEN;
- cs->cs_hlen = CESA_HMAC_HASH_LENGTH;
+ cs->cs_hlen = (mac->cri_mlen == 0) ? MD5_HASH_LEN :
+ mac->cri_mlen;
+ cs->cs_config |= CESA_CSHD_MD5_HMAC;
+ if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN)
+ cs->cs_config |= CESA_CSHD_96_BIT_HMAC;
break;
case CRYPTO_SHA1:
- cs->cs_config |= CESA_CSHD_SHA1;
cs->cs_mblen = 1;
- cs->cs_hlen = SHA1_HASH_LEN;
+ cs->cs_hlen = (mac->cri_mlen == 0) ? SHA1_HASH_LEN :
+ mac->cri_mlen;
+ cs->cs_config |= CESA_CSHD_SHA1;
break;
case CRYPTO_SHA1_HMAC:
- cs->cs_config |= CESA_CSHD_SHA1_HMAC;
cs->cs_mblen = SHA1_HMAC_BLOCK_LEN;
- cs->cs_hlen = CESA_HMAC_HASH_LENGTH;
+ cs->cs_hlen = (mac->cri_mlen == 0) ? SHA1_HASH_LEN :
+ mac->cri_mlen;
+ cs->cs_config |= CESA_CSHD_SHA1_HMAC;
+ if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN)
+ cs->cs_config |= CESA_CSHD_96_BIT_HMAC;
+ break;
+ case CRYPTO_SHA2_256_HMAC:
+ cs->cs_mblen = SHA2_256_HMAC_BLOCK_LEN;
+ cs->cs_hlen = (mac->cri_mlen == 0) ? SHA2_256_HASH_LEN :
+ mac->cri_mlen;
+ cs->cs_config |= CESA_CSHD_SHA2_256_HMAC;
break;
default:
error = EINVAL;
@@ -1656,8 +1709,8 @@ decode_win_cesa_setup(struct cesa_softc *sc)
/* Disable and clear all CESA windows */
for (i = 0; i < MV_WIN_CESA_MAX; i++) {
- CESA_WRITE(sc, MV_WIN_CESA_BASE(i), 0);
- CESA_WRITE(sc, MV_WIN_CESA_CTRL(i), 0);
+ CESA_TDMA_WRITE(sc, MV_WIN_CESA_BASE(i), 0);
+ CESA_TDMA_WRITE(sc, MV_WIN_CESA_CTRL(i), 0);
}
/* Fill CESA TDMA decoding windows with information acquired from DTS */
@@ -1671,8 +1724,8 @@ decode_win_cesa_setup(struct cesa_softc *sc)
(MV_WIN_DDR_ATTR(i) << MV_WIN_CPU_ATTR_SHIFT) |
(MV_WIN_DDR_TARGET << MV_WIN_CPU_TARGET_SHIFT) |
MV_WIN_CPU_ENABLE_BIT);
- CESA_WRITE(sc, MV_WIN_CESA_BASE(i), br);
- CESA_WRITE(sc, MV_WIN_CESA_CTRL(i), cr);
+ CESA_TDMA_WRITE(sc, MV_WIN_CESA_BASE(i), br);
+ CESA_TDMA_WRITE(sc, MV_WIN_CESA_CTRL(i), cr);
}
}
diff --git a/sys/dev/cesa/cesa.h b/sys/dev/cesa/cesa.h
index 28536d5..4819d3d 100644
--- a/sys/dev/cesa/cesa.h
+++ b/sys/dev/cesa/cesa.h
@@ -68,17 +68,15 @@
#define CESA_TDMA_DESCRIPTORS (CESA_TDMA_DESC_PER_REQ * CESA_REQUESTS)
/* Useful constants */
-#define CESA_HMAC_HASH_LENGTH 12
+#define CESA_HMAC_TRUNC_LEN 12
#define CESA_MAX_FRAGMENTS 64
#define CESA_SRAM_SIZE 2048
/*
* CESA_MAX_HASH_LEN is maximum length of hash generated by CESA.
- * As CESA suports only MD5 and SHA1 this equals to 20 bytes.
- * However we increase the value to 24 bytes to meet alignment
- * requirements in cesa_sa_data structure.
+ * As CESA supports MD5, SHA1 and SHA-256 this equals to 32 bytes.
*/
-#define CESA_MAX_HASH_LEN 24
+#define CESA_MAX_HASH_LEN 32
#define CESA_MAX_KEY_LEN 32
#define CESA_MAX_IV_LEN 16
#define CESA_MAX_HMAC_BLOCK_LEN 64
@@ -93,10 +91,15 @@
mtx_assert(&(sc)->sc_ ## what ## _lock, MA_OWNED)
/* Registers read/write macros */
-#define CESA_READ(sc, reg) \
- bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
-#define CESA_WRITE(sc, reg, val) \
- bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define CESA_REG_READ(sc, reg) \
+ bus_read_4((sc)->sc_res[RES_CESA_REGS], (reg))
+#define CESA_REG_WRITE(sc, reg, val) \
+ bus_write_4((sc)->sc_res[RES_CESA_REGS], (reg), (val))
+
+#define CESA_TDMA_READ(sc, reg) \
+ bus_read_4((sc)->sc_res[RES_TDMA_REGS], (reg))
+#define CESA_TDMA_WRITE(sc, reg, val) \
+ bus_write_4((sc)->sc_res[RES_TDMA_REGS], (reg), (val))
/* Generic allocator for objects */
#define CESA_GENERIC_ALLOC_LOCKED(sc, obj, pool) do { \
@@ -126,6 +129,14 @@
#define CESA_DATA(offset) \
(sizeof(struct cesa_sa_hdesc) + sizeof(struct cesa_sa_data) + offset)
+/* CESA memory and IRQ resources */
+enum cesa_res_type {
+ RES_TDMA_REGS,
+ RES_CESA_REGS,
+ RES_CESA_IRQ,
+ RES_CESA_NUM
+};
+
struct cesa_tdma_hdesc {
uint16_t cthd_byte_count;
uint16_t cthd_flags;
@@ -220,11 +231,9 @@ struct cesa_packet {
struct cesa_softc {
device_t sc_dev;
int32_t sc_cid;
- struct resource *sc_res[2];
+ struct resource *sc_res[RES_CESA_NUM];
void *sc_icookie;
bus_dma_tag_t sc_data_dtag;
- bus_space_tag_t sc_bst;
- bus_space_handle_t sc_bsh;
int sc_error;
int sc_tperr;
@@ -257,7 +266,9 @@ struct cesa_softc {
STAILQ_HEAD(, cesa_session) sc_free_sessions;
/* CESA SRAM Address */
- bus_addr_t sc_sram_base;
+ bus_addr_t sc_sram_base_pa;
+ bus_space_handle_t sc_sram_base_va;
+ bus_size_t sc_sram_size;
};
struct cesa_chain_info {
@@ -280,8 +291,12 @@ struct cesa_chain_info {
#define CESA_CSHD_MD5 (4 << 4)
#define CESA_CSHD_SHA1 (5 << 4)
-#define CESA_CSHD_MD5_HMAC ((6 << 4) | (1 << 7))
-#define CESA_CSHD_SHA1_HMAC ((7 << 4) | (1 << 7))
+#define CESA_CSHD_SHA2_256 (1 << 4)
+#define CESA_CSHD_MD5_HMAC (6 << 4)
+#define CESA_CSHD_SHA1_HMAC (7 << 4)
+#define CESA_CSHD_SHA2_256_HMAC (3 << 4)
+
+#define CESA_CSHD_96_BIT_HMAC (1 << 7)
#define CESA_CSHD_DES (1 << 8)
#define CESA_CSHD_3DES (2 << 8)
@@ -301,11 +316,11 @@ struct cesa_chain_info {
#define CESA_CSHD_FRAG_MIDDLE (3U << 30)
/* CESA registers definitions */
-#define CESA_ICR 0xDE20
+#define CESA_ICR 0x0E20
#define CESA_ICR_ACCTDMA (1 << 7)
#define CESA_ICR_TPERR (1 << 12)
-#define CESA_ICM 0xDE24
+#define CESA_ICM 0x0E24
#define CESA_ICM_ACCTDMA CESA_ICR_ACCTDMA
#define CESA_ICM_TPERR CESA_ICR_TPERR
@@ -321,6 +336,10 @@ struct cesa_chain_info {
#define CESA_TDMA_CR_FETCHND (1 << 13)
#define CESA_TDMA_CR_ACTIVE (1 << 14)
+#if defined (SOC_MV_ARMADA38X)
+#define CESA_TDMA_NUM_OUTSTAND (2 << 16)
+#endif
+
#define CESA_TDMA_ECR 0x08C8
#define CESA_TDMA_ECR_MISS (1 << 0)
#define CESA_TDMA_ECR_DOUBLE_HIT (1 << 1)
@@ -339,17 +358,21 @@ struct cesa_chain_info {
#define MV_WIN_CESA_MAX 4
/* CESA SA registers definitions */
-#define CESA_SA_CMD 0xDE00
+#define CESA_SA_CMD 0x0E00
#define CESA_SA_CMD_ACTVATE (1 << 0)
-#define CESA_SA_DPR 0xDE04
+#if defined (SOC_MV_ARMADA38X)
+#define CESA_SA_CMD_SHA2 (1 << 31)
+#endif
+
+#define CESA_SA_DPR 0x0E04
-#define CESA_SA_CR 0xDE08
+#define CESA_SA_CR 0x0E08
#define CESA_SA_CR_WAIT_FOR_TDMA (1 << 7)
#define CESA_SA_CR_ACTIVATE_TDMA (1 << 9)
#define CESA_SA_CR_MULTI_MODE (1 << 11)
-#define CESA_SA_SR 0xDE0C
+#define CESA_SA_SR 0x0E0C
#define CESA_SA_SR_ACTIVE (1 << 0)
#endif
diff --git a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
index dbb8b75..d0e7f39 100644
--- a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
+++ b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
@@ -850,7 +850,7 @@ icl_cxgbei_load(void)
refcount_init(&icl_cxgbei_ncons, 0);
- error = icl_register("cxgbei", false, 100, icl_cxgbei_limits,
+ error = icl_register("cxgbei", false, -100, icl_cxgbei_limits,
icl_cxgbei_new_conn);
KASSERT(error == 0, ("failed to register"));
diff --git a/sys/dev/cxgbe/iw_cxgbe/cm.c b/sys/dev/cxgbe/iw_cxgbe/cm.c
index 3759140..dc5617d 100644
--- a/sys/dev/cxgbe/iw_cxgbe/cm.c
+++ b/sys/dev/cxgbe/iw_cxgbe/cm.c
@@ -1861,14 +1861,16 @@ process_mpa_request(struct c4iw_ep *ep)
/* drive upcall */
mutex_lock(&ep->parent_ep->com.mutex);
if (ep->parent_ep->com.state != DEAD) {
- if(connect_request_upcall(ep))
- goto err_out;
- }else {
- goto err_out;
- }
+ if (connect_request_upcall(ep))
+ goto err_unlock_parent;
+ } else
+ goto err_unlock_parent;
mutex_unlock(&ep->parent_ep->com.mutex);
return 0;
+err_unlock_parent:
+ mutex_unlock(&ep->parent_ep->com.mutex);
+ goto err_out;
err_stop_timer:
STOP_EP_TIMER(ep);
err_out:
diff --git a/sys/dev/cxgbe/iw_cxgbe/ev.c b/sys/dev/cxgbe/iw_cxgbe/ev.c
index b0a9e13..f4ea0c7 100644
--- a/sys/dev/cxgbe/iw_cxgbe/ev.c
+++ b/sys/dev/cxgbe/iw_cxgbe/ev.c
@@ -194,13 +194,22 @@ int c4iw_ev_handler(struct sge_iq *iq, const struct rsp_ctrl *rc)
struct c4iw_cq *chp;
unsigned long flag;
+ spin_lock_irqsave(&dev->lock, flag);
chp = get_chp(dev, qid);
if (chp) {
+ atomic_inc(&chp->refcnt);
+ spin_unlock_irqrestore(&dev->lock, flag);
+
spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
- } else
+ if (atomic_dec_and_test(&chp->refcnt))
+ wake_up(&chp->wait);
+ } else {
CTR2(KTR_IW_CXGBE, "%s unknown cqid 0x%x", __func__, qid);
+ spin_unlock_irqrestore(&dev->lock, flag);
+ }
+
return 0;
}
#endif
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 4710977..7f85250 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -1417,7 +1417,11 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
ddp_placed = be32toh(cpl->seq) - tp->rcv_nxt;
tp->rcv_nxt += len;
- KASSERT(tp->rcv_wnd >= len, ("%s: negative window size", __func__));
+ if (tp->rcv_wnd < len) {
+ KASSERT(toep->ulp_mode != ULP_MODE_RDMA,
+ ("%s: negative window size", __func__));
+ }
+
tp->rcv_wnd -= len;
tp->t_rcvtime = ticks;
diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c
index 10f27ad..d727455 100644
--- a/sys/dev/filemon/filemon.c
+++ b/sys/dev/filemon/filemon.c
@@ -89,6 +89,7 @@ MALLOC_DEFINE(M_FILEMON, "filemon", "File access monitor");
struct filemon {
struct sx lock; /* Lock for this filemon. */
struct file *fp; /* Output file pointer. */
+ struct ucred *cred; /* Credential of tracer. */
char fname1[MAXPATHLEN]; /* Temporary filename buffer. */
char fname2[MAXPATHLEN]; /* Temporary filename buffer. */
char msgbufr[1024]; /* Output message buffer. */
@@ -125,6 +126,8 @@ filemon_release(struct filemon *filemon)
*/
sx_assert(&filemon->lock, SA_UNLOCKED);
+ if (filemon->cred != NULL)
+ crfree(filemon->cred);
sx_destroy(&filemon->lock);
free(filemon, M_FILEMON);
}
@@ -188,7 +191,7 @@ filemon_drop(struct filemon *filemon)
#include "filemon_wrapper.c"
static void
-filemon_comment(struct filemon *filemon)
+filemon_write_header(struct filemon *filemon)
{
int len;
struct timeval now;
@@ -308,6 +311,9 @@ filemon_attach_proc(struct filemon *filemon, struct proc *p)
KASSERT((p->p_flag & P_WEXIT) == 0,
("%s: filemon %p attaching to exiting process %p",
__func__, filemon, p));
+ KASSERT((p->p_flag & P_INEXEC) == 0,
+ ("%s: filemon %p attaching to execing process %p",
+ __func__, filemon, p));
if (p->p_filemon == filemon)
return (0);
@@ -377,7 +383,7 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
&filemon->fp);
if (error == 0)
/* Write the file header. */
- filemon_comment(filemon);
+ filemon_write_header(filemon);
break;
/* Set the monitored process ID. */
@@ -385,8 +391,8 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
/* Invalidate any existing processes already set. */
filemon_untrack_processes(filemon);
- error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT,
- &p);
+ error = pget(*((pid_t *)data),
+ PGET_CANDEBUG | PGET_NOTWEXIT | PGET_NOTINEXEC, &p);
if (error == 0) {
KASSERT(p->p_filemon != filemon,
("%s: proc %p didn't untrack filemon %p",
@@ -407,7 +413,7 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
static int
filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
- struct thread *td __unused)
+ struct thread *td)
{
int error;
struct filemon *filemon;
@@ -416,6 +422,7 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
M_WAITOK | M_ZERO);
sx_init(&filemon->lock, "filemon");
refcount_init(&filemon->refcnt, 1);
+ filemon->cred = crhold(td->td_ucred);
error = devfs_set_cdevpriv(filemon, filemon_dtr);
if (error != 0)
diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c
index e03c237..1b304d2 100644
--- a/sys/dev/filemon/filemon_wrapper.c
+++ b/sys/dev/filemon/filemon_wrapper.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/eventhandler.h>
#include <sys/filedesc.h>
#include <sys/imgact.h>
+#include <sys/priv.h>
#include <sys/sx.h>
#include <sys/vnode.h>
@@ -64,8 +65,8 @@ filemon_output(struct filemon *filemon, char *msg, size_t len)
if (filemon->fp->f_type == DTYPE_VNODE)
bwillwrite();
- error = fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
- if (error != 0)
+ error = fo_write(filemon->fp, &auio, filemon->cred, 0, curthread);
+ if (error != 0 && filemon->error == 0)
filemon->error = error;
}
@@ -112,6 +113,24 @@ filemon_event_process_exec(void *arg __unused, struct proc *p,
filemon_output(filemon, filemon->msgbufr, len);
+ /* If the credentials changed then cease tracing. */
+ if (imgp->newcred != NULL &&
+ imgp->credential_setid &&
+ priv_check_cred(filemon->cred,
+ PRIV_DEBUG_DIFFCRED, 0) != 0) {
+ /*
+ * It may have changed to NULL already, but
+ * will not be re-attached by anything else.
+ */
+ if (p->p_filemon != NULL) {
+ KASSERT(p->p_filemon == filemon,
+ ("%s: proc %p didn't have expected"
+ " filemon %p", __func__, p, filemon));
+ filemon_proc_drop(p);
+ }
+ }
+
+
filemon_drop(filemon);
}
}
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 48bb23e..55dc499 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -4199,6 +4199,7 @@ pmc_capture_user_callchain(int cpu, int ring, struct trapframe *tf)
struct pmc_samplebuffer *psb;
#ifdef INVARIANTS
int ncallchains;
+ int nfree;
#endif
psb = pmc_pcpu[cpu]->pc_sb[ring];
@@ -4210,6 +4211,7 @@ pmc_capture_user_callchain(int cpu, int ring, struct trapframe *tf)
#ifdef INVARIANTS
ncallchains = 0;
+ nfree = 0;
#endif
/*
@@ -4221,6 +4223,10 @@ pmc_capture_user_callchain(int cpu, int ring, struct trapframe *tf)
ps = psb->ps_read;
ps_end = psb->ps_write;
do {
+#ifdef INVARIANTS
+ if (ps->ps_pmc->pm_state != PMC_STATE_RUNNING)
+ nfree++;
+#endif
if (ps->ps_nsamples != PMC_SAMPLE_INUSE)
goto next;
if (ps->ps_td != td)
@@ -4256,7 +4262,7 @@ next:
ps = psb->ps_samples;
} while (ps != ps_end);
- KASSERT(ncallchains > 0,
+ KASSERT(ncallchains > 0 || nfree > 0,
("[pmc,%d] cpu %d didn't find a sample to collect", __LINE__,
cpu));
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index d5166f6..44ed516 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -121,10 +121,12 @@ typedef uint8_t hv_bool_uint8_t;
HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT )
typedef struct hv_guid {
- unsigned char data[16];
+ uint8_t data[16];
} __packed hv_guid;
-int snprintf_hv_guid(char *, size_t, const hv_guid *);
+#define HYPERV_GUID_STRLEN 40
+
+int hyperv_guid2str(const struct hv_guid *, char *, size_t);
#define HV_NIC_GUID \
.data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, \
diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c
index c39083a..e681f61 100644
--- a/sys/dev/hyperv/utilities/hv_kvp.c
+++ b/sys/dev/hyperv/utilities/hv_kvp.c
@@ -58,7 +58,10 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/mutex.h>
+
+#include <net/if.h>
#include <net/if_arp.h>
+#include <net/if_var.h>
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/netvsc/hv_net_vsc.h>
@@ -306,8 +309,7 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg,
int UNUSED_FLAG = 1;
struct hv_device *hv_dev; /* GUID Data Structure */
hn_softc_t *sc; /* hn softc structure */
- char if_name[4];
- char buf[39];
+ char buf[HYPERV_GUID_STRLEN];
device_t *devs;
int devcnt;
@@ -335,11 +337,12 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg,
/* Trying to find GUID of Network Device */
hv_dev = sc->hn_dev_obj;
- snprintf_hv_guid(buf, sizeof(buf), &hv_dev->device_id);
- sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt]));
+ hyperv_guid2str(&hv_dev->device_id, buf, sizeof(buf));
- if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) {
- strcpy((char *)umsg->body.kvp_ip_val.adapter_id, if_name);
+ if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id,
+ HYPERV_GUID_STRLEN - 1) == 0) {
+ strlcpy((char *)umsg->body.kvp_ip_val.adapter_id,
+ sc->hn_ifp->if_xname, MAX_ADAPTER_ID_SIZE);
break;
}
}
diff --git a/sys/dev/hyperv/vmbus/amd64/hv_vector.S b/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S
index 2594483..8d09e24 100644
--- a/sys/dev/hyperv/vmbus/amd64/hv_vector.S
+++ b/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S
@@ -37,10 +37,10 @@
*/
.text
SUPERALIGN_TEXT
-IDTVEC(hv_vmbus_callback)
+IDTVEC(vmbus_isr)
PUSH_FRAME
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
- call hv_vector_handler
+ call vmbus_handle_intr
MEXITCOUNT
jmp doreti
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index aa3d2d8..df0b350 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -33,6 +33,7 @@
#include <sys/mutex.h>
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
/*
@@ -301,6 +302,12 @@ vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu)
{
KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpu %d", cpu));
+ if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 ||
+ hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) {
+ /* Only cpu0 is supported */
+ cpu = 0;
+ }
+
chan->target_cpu = cpu;
chan->target_vcpu = VMBUS_PCPU_GET(vmbus_get_softc(), vcpuid, cpu);
@@ -358,9 +365,7 @@ vmbus_channel_select_defcpu(struct hv_vmbus_channel *channel)
}
}
- if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
- (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) ||
- (!is_perf_channel)) {
+ if (!is_perf_channel) {
/* Stick to cpu0 */
vmbus_channel_cpu_set(channel, 0);
return;
@@ -713,8 +718,8 @@ hv_vmbus_release_unattached_channels(void)
}
hv_vmbus_free_vmbus_channel(channel);
}
- bzero(hv_vmbus_g_connection.channels,
- sizeof(hv_vmbus_channel*) * HV_CHANNEL_MAX_COUNT);
+ bzero(hv_vmbus_g_connection.channels,
+ sizeof(hv_vmbus_channel*) * VMBUS_CHAN_MAX);
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
}
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index 14780db..668914c 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -39,6 +39,7 @@
#include <vm/pmap.h>
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
/*
@@ -209,8 +210,7 @@ hv_vmbus_connect(void)
M_DEVBUF, M_WAITOK | M_ZERO);
hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) *
- HV_CHANNEL_MAX_COUNT,
- M_DEVBUF, M_WAITOK | M_ZERO);
+ VMBUS_CHAN_MAX, M_DEVBUF, M_WAITOK | M_ZERO);
/*
* Find the highest vmbus version number we can support.
*/
@@ -292,20 +292,20 @@ hv_vmbus_disconnect(void)
}
static __inline void
-vmbus_event_flags_proc(unsigned long *event_flags, int flag_cnt)
+vmbus_event_flags_proc(volatile u_long *event_flags, int flag_cnt)
{
int f;
for (f = 0; f < flag_cnt; ++f) {
uint32_t rel_id_base;
- unsigned long flags;
+ u_long flags;
int bit;
if (event_flags[f] == 0)
continue;
flags = atomic_swap_long(&event_flags[f], 0);
- rel_id_base = f << HV_CHANNEL_ULONG_SHIFT;
+ rel_id_base = f << VMBUS_EVTFLAG_SHIFT;
while ((bit = ffsl(flags)) != 0) {
struct hv_vmbus_channel *channel;
@@ -331,27 +331,27 @@ vmbus_event_flags_proc(unsigned long *event_flags, int flag_cnt)
void
vmbus_event_proc(struct vmbus_softc *sc, int cpu)
{
- hv_vmbus_synic_event_flags *event;
+ struct vmbus_evtflags *eventf;
/*
* On Host with Win8 or above, the event page can be checked directly
* to get the id of the channel that has the pending interrupt.
*/
- event = VMBUS_PCPU_GET(sc, event_flag, cpu) + HV_VMBUS_MESSAGE_SINT;
- vmbus_event_flags_proc(event->flagsul,
- VMBUS_PCPU_GET(sc, event_flag_cnt, cpu));
+ eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
+ vmbus_event_flags_proc(eventf->evt_flags,
+ VMBUS_PCPU_GET(sc, event_flags_cnt, cpu));
}
void
vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu)
{
- hv_vmbus_synic_event_flags *event;
+ struct vmbus_evtflags *eventf;
- event = VMBUS_PCPU_GET(sc, event_flag, cpu) + HV_VMBUS_MESSAGE_SINT;
- if (atomic_testandclear_int(&event->flags32[0], 0)) {
+ eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
+ if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) {
vmbus_event_flags_proc(
hv_vmbus_g_connection.recv_interrupt_page,
- HV_MAX_NUM_CHANNELS_SUPPORTED >> HV_CHANNEL_ULONG_SHIFT);
+ VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT);
}
}
@@ -414,8 +414,8 @@ vmbus_on_channel_open(const struct hv_vmbus_channel *chan)
volatile int *flag_cnt_ptr;
int flag_cnt;
- flag_cnt = (chan->offer_msg.child_rel_id / HV_CHANNEL_ULONG_LEN) + 1;
- flag_cnt_ptr = VMBUS_PCPU_PTR(vmbus_get_softc(), event_flag_cnt,
+ flag_cnt = (chan->offer_msg.child_rel_id / VMBUS_EVTFLAG_LEN) + 1;
+ flag_cnt_ptr = VMBUS_PCPU_PTR(vmbus_get_softc(), event_flags_cnt,
chan->target_cpu);
for (;;) {
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 4251ff0..a66ae3e 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -51,28 +51,6 @@ typedef uint16_t hv_vmbus_status;
#define HV_ANY_VP (0xFFFFFFFF)
/*
- * Synthetic interrupt controller flag constants.
- */
-
-#define HV_EVENT_FLAGS_COUNT (256 * 8)
-#define HV_EVENT_FLAGS_BYTE_COUNT (256)
-#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(uint32_t))
-#define HV_EVENT_FLAGS_ULONG_COUNT (256 / sizeof(unsigned long))
-
-/**
- * max channel count <== event_flags_dword_count * bit_of_dword
- */
-#ifdef __LP64__
-#define HV_CHANNEL_ULONG_LEN (64)
-#define HV_CHANNEL_ULONG_SHIFT (6)
-#else
-#define HV_CHANNEL_ULONG_LEN (32)
-#define HV_CHANNEL_ULONG_SHIFT (5)
-#endif
-#define HV_CHANNEL_DWORD_LEN (32)
-#define HV_CHANNEL_MAX_COUNT \
- ((HV_EVENT_FLAGS_DWORD_COUNT) * HV_CHANNEL_DWORD_LEN)
-/*
* MessageId: HV_STATUS_INSUFFICIENT_BUFFERS
* MessageText:
* You did not supply enough message buffers to send a message.
@@ -189,17 +167,12 @@ enum {
HV_VMBUS_EVENT_PORT_ID = 2,
HV_VMBUS_MONITOR_CONNECTION_ID = 3,
HV_VMBUS_MONITOR_PORT_ID = 3,
- HV_VMBUS_MESSAGE_SINT = 2,
- HV_VMBUS_TIMER_SINT = 4,
};
#define HV_PRESENT_BIT 0x80000000
#define HV_HYPERCALL_PARAM_ALIGN sizeof(uint64_t)
-struct vmbus_message;
-union vmbus_event_flags;
-
/*
* Define hypervisor message types
*/
@@ -253,59 +226,9 @@ typedef union _hv_vmbus_port_id {
} u ;
} hv_vmbus_port_id;
-/*
- * Define synthetic interrupt controller message flag
- */
-typedef union {
- uint8_t as_uint8_t;
- struct {
- uint8_t message_pending:1;
- uint8_t reserved:7;
- } u;
-} hv_vmbus_msg_flags;
-
typedef uint64_t hv_vmbus_partition_id;
/*
- * Define synthetic interrupt controller message header
- */
-typedef struct {
- hv_vmbus_msg_type message_type;
- uint8_t payload_size;
- hv_vmbus_msg_flags message_flags;
- uint8_t reserved[2];
- union {
- hv_vmbus_partition_id sender;
- hv_vmbus_port_id port;
- } u;
-} hv_vmbus_msg_header;
-
-/*
- * Define synthetic interrupt controller message format
- */
-typedef struct vmbus_message {
- hv_vmbus_msg_header header;
- union {
- uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
- } u ;
-} hv_vmbus_message;
-
-/*
- * Maximum channels is determined by the size of the interrupt
- * page which is PAGE_SIZE. 1/2 of PAGE_SIZE is for
- * send endpoint interrupt and the other is receive
- * endpoint interrupt.
- *
- * Note: (PAGE_SIZE >> 1) << 3 allocates 16348 channels
- */
-#define HV_MAX_NUM_CHANNELS (PAGE_SIZE >> 1) << 3
-
-/*
- * (The value here must be in multiple of 32)
- */
-#define HV_MAX_NUM_CHANNELS_SUPPORTED 256
-
-/*
* VM Bus connection states
*/
typedef enum {
@@ -428,16 +351,6 @@ typedef struct {
} hv_vmbus_input_post_message;
/*
- * Define the synthetic interrupt controller event flags format
- */
-typedef union vmbus_event_flags {
- uint8_t flags8[HV_EVENT_FLAGS_BYTE_COUNT];
- uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
- unsigned long flagsul[HV_EVENT_FLAGS_ULONG_COUNT];
-} hv_vmbus_synic_event_flags;
-CTASSERT(sizeof(hv_vmbus_synic_event_flags) == HV_EVENT_FLAGS_BYTE_COUNT);
-
-/*
* Declare the various hypercall operations
*/
typedef enum {
@@ -542,12 +455,6 @@ int hv_vmbus_disconnect(void);
int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(hv_vmbus_channel *channel);
-/**
- * Event Timer interfaces
- */
-void hv_et_init(void);
-void hv_et_intr(struct trapframe*);
-
/* Wait for device creation */
void vmbus_scan(void);
diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hyperv.c
index b286fac..ac18889 100644
--- a/sys/dev/hyperv/vmbus/hv_hv.c
+++ b/sys/dev/hyperv/vmbus/hyperv.c
@@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/hyperv_var.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
-#define HV_NANOSECONDS_PER_SEC 1000000000L
-
#define HYPERV_FREEBSD_BUILD 0ULL
#define HYPERV_FREEBSD_VERSION ((uint64_t)__FreeBSD_version)
#define HYPERV_FREEBSD_OSID 0ULL
@@ -87,7 +85,7 @@ static struct timecounter hyperv_timecounter = {
.tc_get_timecount = hyperv_get_timecount,
.tc_poll_pps = NULL,
.tc_counter_mask = 0xffffffff,
- .tc_frequency = HV_NANOSECONDS_PER_SEC/100,
+ .tc_frequency = HYPERV_TIMER_FREQ,
.tc_name = "Hyper-V",
.tc_quality = 2000,
.tc_flags = 0,
@@ -204,6 +202,18 @@ hv_vmbus_signal_event(void *con_id)
return (status);
}
+int
+hyperv_guid2str(const struct hv_guid *guid, char *buf, size_t sz)
+{
+ const uint8_t *d = guid->data;
+
+ return snprintf(buf, sz, "%02x%02x%02x%02x-"
+ "%02x%02x-%02x%02x-%02x%02x-"
+ "%02x%02x%02x%02x%02x%02x",
+ d[3], d[2], d[1], d[0],
+ d[5], d[4], d[7], d[6], d[8], d[9],
+ d[10], d[11], d[12], d[13], d[14], d[15]);
+}
static bool
hyperv_identify(void)
diff --git a/sys/dev/hyperv/vmbus/hyperv_var.h b/sys/dev/hyperv/vmbus/hyperv_var.h
index 0803bef..9d7a877 100644
--- a/sys/dev/hyperv/vmbus/hyperv_var.h
+++ b/sys/dev/hyperv/vmbus/hyperv_var.h
@@ -29,6 +29,12 @@
#ifndef _HYPERV_VAR_H_
#define _HYPERV_VAR_H_
+#ifndef NANOSEC
+#define NANOSEC 1000000000ULL
+#endif
+#define HYPERV_TIMER_NS_FACTOR 100ULL
+#define HYPERV_TIMER_FREQ (NANOSEC / HYPERV_TIMER_NS_FACTOR)
+
extern u_int hyperv_features;
extern u_int hyperv_recommends;
diff --git a/sys/dev/hyperv/vmbus/i386/hv_vector.S b/sys/dev/hyperv/vmbus/i386/vmbus_vector.S
index 55a2613..b9ea849 100644
--- a/sys/dev/hyperv/vmbus/i386/hv_vector.S
+++ b/sys/dev/hyperv/vmbus/i386/vmbus_vector.S
@@ -35,15 +35,15 @@
* This is the Hyper-V vmbus channel direct callback interrupt.
* Only used when it is running on Hyper-V.
*/
- .text
- SUPERALIGN_TEXT
-IDTVEC(hv_vmbus_callback)
- PUSH_FRAME
- SET_KERNEL_SREGS
- cld
- FAKE_MCOUNT(TF_EIP(%esp))
- pushl %esp
- call hv_vector_handler
- add $4, %esp
- MEXITCOUNT
- jmp doreti
+ .text
+ SUPERALIGN_TEXT
+IDTVEC(vmbus_isr)
+ PUSH_FRAME
+ SET_KERNEL_SREGS
+ cld
+ FAKE_MCOUNT(TF_EIP(%esp))
+ pushl %esp
+ call vmbus_handle_intr
+ add $4, %esp
+ MEXITCOUNT
+ jmp doreti
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/vmbus.c
index cdb400f..6d1445d 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
#include <dev/hyperv/vmbus/hyperv_reg.h>
#include <dev/hyperv/vmbus/hyperv_var.h>
+#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
#include <contrib/dev/acpica/include/acpi.h>
@@ -70,26 +71,26 @@ __FBSDID("$FreeBSD$");
struct vmbus_softc *vmbus_sc;
-static char *vmbus_ids[] = { "VMBUS", NULL };
-
-extern inthand_t IDTVEC(hv_vmbus_callback);
+extern inthand_t IDTVEC(vmbus_isr);
static void
vmbus_msg_task(void *xsc, int pending __unused)
{
struct vmbus_softc *sc = xsc;
- hv_vmbus_message *msg;
+ volatile struct vmbus_message *msg;
- msg = VMBUS_PCPU_GET(sc, message, curcpu) + HV_VMBUS_MESSAGE_SINT;
+ msg = VMBUS_PCPU_GET(sc, message, curcpu) + VMBUS_SINT_MESSAGE;
for (;;) {
const hv_vmbus_channel_msg_table_entry *entry;
hv_vmbus_channel_msg_header *hdr;
hv_vmbus_channel_msg_type msg_type;
- if (msg->header.message_type == HV_MESSAGE_TYPE_NONE)
+ if (msg->msg_type == VMBUS_MSGTYPE_NONE)
break; /* no message */
- hdr = (hv_vmbus_channel_msg_header *)msg->u.payload;
+ /* XXX: update messageHandler interface */
+ hdr = __DEVOLATILE(hv_vmbus_channel_msg_header *,
+ msg->msg_data);
msg_type = hdr->message_type;
if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) {
@@ -101,20 +102,20 @@ vmbus_msg_task(void *xsc, int pending __unused)
if (entry->messageHandler)
entry->messageHandler(hdr);
handled:
- msg->header.message_type = HV_MESSAGE_TYPE_NONE;
+ msg->msg_type = VMBUS_MSGTYPE_NONE;
/*
- * Make sure the write to message_type (ie set to
- * HV_MESSAGE_TYPE_NONE) happens before we read the
- * message_pending and EOMing. Otherwise, the EOMing will
- * not deliver any more messages
- * since there is no empty slot
+ * Make sure the write to msg_type (i.e. set to
+ * VMBUS_MSGTYPE_NONE) happens before we read the
+ * msg_flags and EOMing. Otherwise, the EOMing will
+ * not deliver any more messages since there is no
+ * empty slot
*
* NOTE:
* mb() is used here, since atomic_thread_fence_seq_cst()
* will become compiler fence on UP kernel.
*/
mb();
- if (msg->header.message_flags.u.message_pending) {
+ if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
/*
* This will cause message queue rescan to possibly
* deliver another msg from the hypervisor
@@ -124,49 +125,38 @@ handled:
}
}
-/**
- * @brief Interrupt filter routine for VMBUS.
- *
- * The purpose of this routine is to determine the type of VMBUS protocol
- * message to process - an event or a channel message.
- */
-static inline int
-hv_vmbus_isr(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
+static __inline int
+vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
{
- hv_vmbus_message *msg, *msg_base;
+ volatile struct vmbus_message *msg;
+ struct vmbus_message *msg_base;
- /*
- * The Windows team has advised that we check for events
- * before checking for messages. This is the way they do it
- * in Windows when running as a guest in Hyper-V
- */
- sc->vmbus_event_proc(sc, cpu);
-
- /* Check if there are actual msgs to be process */
msg_base = VMBUS_PCPU_GET(sc, message, cpu);
- msg = msg_base + HV_VMBUS_TIMER_SINT;
- /* we call eventtimer process the message */
- if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
- msg->header.message_type = HV_MESSAGE_TYPE_NONE;
+ /*
+ * Check event timer.
+ *
+ * TODO: move this to independent IDT vector.
+ */
+ msg = msg_base + VMBUS_SINT_TIMER;
+ if (msg->msg_type == VMBUS_MSGTYPE_TIMER_EXPIRED) {
+ msg->msg_type = VMBUS_MSGTYPE_NONE;
- /* call intrrupt handler of event timer */
- hv_et_intr(frame);
+ vmbus_et_intr(frame);
/*
- * Make sure the write to message_type (ie set to
- * HV_MESSAGE_TYPE_NONE) happens before we read the
- * message_pending and EOMing. Otherwise, the EOMing will
- * not deliver any more messages
- * since there is no empty slot
+ * Make sure the write to msg_type (i.e. set to
+ * VMBUS_MSGTYPE_NONE) happens before we read the
+ * msg_flags and EOMing. Otherwise, the EOMing will
+ * not deliver any more messages since there is no
+ * empty slot
*
* NOTE:
* mb() is used here, since atomic_thread_fence_seq_cst()
* will become compiler fence on UP kernel.
*/
mb();
-
- if (msg->header.message_flags.u.message_pending) {
+ if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
/*
* This will cause message queue rescan to possibly
* deliver another msg from the hypervisor
@@ -175,8 +165,20 @@ hv_vmbus_isr(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
}
}
- msg = msg_base + HV_VMBUS_MESSAGE_SINT;
- if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
+ /*
+ * Check events. Hot path for network and storage I/O data; high rate.
+ *
+ * NOTE:
+ * As recommended by the Windows guest fellows, we check events before
+ * checking messages.
+ */
+ sc->vmbus_event_proc(sc, cpu);
+
+ /*
+ * Check messages. Mainly management stuffs; ultra low rate.
+ */
+ msg = msg_base + VMBUS_SINT_MESSAGE;
+ if (__predict_false(msg->msg_type != VMBUS_MSGTYPE_NONE)) {
taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu),
VMBUS_PCPU_PTR(sc, message_task, cpu));
}
@@ -185,7 +187,7 @@ hv_vmbus_isr(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
}
void
-hv_vector_handler(struct trapframe *trap_frame)
+vmbus_handle_intr(struct trapframe *trap_frame)
{
struct vmbus_softc *sc = vmbus_get_softc();
int cpu = curcpu;
@@ -200,7 +202,7 @@ hv_vector_handler(struct trapframe *trap_frame)
*/
(*VMBUS_PCPU_GET(sc, intr_cnt, cpu))++;
- hv_vmbus_isr(sc, trap_frame, cpu);
+ vmbus_handle_intr1(sc, trap_frame, cpu);
/*
* Enable preemption.
@@ -246,15 +248,15 @@ vmbus_synic_setup(void *xsc)
*/
orig = rdmsr(MSR_HV_SIEFP);
val = MSR_HV_SIEFP_ENABLE | (orig & MSR_HV_SIEFP_RSVD_MASK) |
- ((VMBUS_PCPU_GET(sc, event_flag_dma.hv_paddr, cpu) >> PAGE_SHIFT) <<
- MSR_HV_SIEFP_PGSHIFT);
+ ((VMBUS_PCPU_GET(sc, event_flags_dma.hv_paddr, cpu)
+ >> PAGE_SHIFT) << MSR_HV_SIEFP_PGSHIFT);
wrmsr(MSR_HV_SIEFP, val);
/*
* Configure and unmask SINT for message and event flags.
*/
- sint = MSR_HV_SINT0 + HV_VMBUS_MESSAGE_SINT;
+ sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
orig = rdmsr(sint);
val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
(orig & MSR_HV_SINT_RSVD_MASK);
@@ -263,7 +265,7 @@ vmbus_synic_setup(void *xsc)
/*
* Configure and unmask SINT for timer.
*/
- sint = MSR_HV_SINT0 + HV_VMBUS_TIMER_SINT;
+ sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
orig = rdmsr(sint);
val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
(orig & MSR_HV_SINT_RSVD_MASK);
@@ -292,14 +294,14 @@ vmbus_synic_teardown(void *arg)
/*
* Mask message and event flags SINT.
*/
- sint = MSR_HV_SINT0 + HV_VMBUS_MESSAGE_SINT;
+ sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
orig = rdmsr(sint);
wrmsr(sint, orig | MSR_HV_SINT_MASKED);
/*
* Mask timer SINT.
*/
- sint = MSR_HV_SINT0 + HV_VMBUS_TIMER_SINT;
+ sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
orig = rdmsr(sint);
wrmsr(sint, orig | MSR_HV_SINT_MASKED);
@@ -337,11 +339,11 @@ vmbus_dma_alloc(struct vmbus_softc *sc)
ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
PAGE_SIZE, 0, PAGE_SIZE,
- VMBUS_PCPU_PTR(sc, event_flag_dma, cpu),
+ VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
BUS_DMA_WAITOK | BUS_DMA_ZERO);
if (ptr == NULL)
return ENOMEM;
- VMBUS_PCPU_GET(sc, event_flag, cpu) = ptr;
+ VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr;
}
return 0;
}
@@ -358,11 +360,11 @@ vmbus_dma_free(struct vmbus_softc *sc)
VMBUS_PCPU_GET(sc, message, cpu));
VMBUS_PCPU_GET(sc, message, cpu) = NULL;
}
- if (VMBUS_PCPU_GET(sc, event_flag, cpu) != NULL) {
+ if (VMBUS_PCPU_GET(sc, event_flags, cpu) != NULL) {
hyperv_dmamem_free(
- VMBUS_PCPU_PTR(sc, event_flag_dma, cpu),
- VMBUS_PCPU_GET(sc, event_flag, cpu));
- VMBUS_PCPU_GET(sc, event_flag, cpu) = NULL;
+ VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
+ VMBUS_PCPU_GET(sc, event_flags, cpu));
+ VMBUS_PCPU_GET(sc, event_flags, cpu) = NULL;
}
}
}
@@ -410,7 +412,7 @@ vmbus_intr_setup(struct vmbus_softc *sc)
* All Hyper-V ISR required resources are setup, now let's find a
* free IDT vector for Hyper-V ISR and set it up.
*/
- sc->vmbus_idtvec = lapic_ipi_alloc(IDTVEC(hv_vmbus_callback));
+ sc->vmbus_idtvec = lapic_ipi_alloc(IDTVEC(vmbus_isr));
if (sc->vmbus_idtvec < 0) {
device_printf(sc->vmbus_dev, "cannot find free IDT vector\n");
return ENXIO;
@@ -453,16 +455,19 @@ vmbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
switch (index) {
case HV_VMBUS_IVAR_TYPE:
- *result = (uintptr_t) &child_dev_ctx->class_id;
+ *result = (uintptr_t)&child_dev_ctx->class_id;
return (0);
+
case HV_VMBUS_IVAR_INSTANCE:
- *result = (uintptr_t) &child_dev_ctx->device_id;
+ *result = (uintptr_t)&child_dev_ctx->device_id;
return (0);
+
case HV_VMBUS_IVAR_DEVCTX:
- *result = (uintptr_t) child_dev_ctx;
+ *result = (uintptr_t)child_dev_ctx;
return (0);
+
case HV_VMBUS_IVAR_NODE:
- *result = (uintptr_t) child_dev_ctx->device;
+ *result = (uintptr_t)child_dev_ctx->device;
return (0);
}
return (ENOENT);
@@ -485,18 +490,18 @@ vmbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
static int
vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
{
- char guidbuf[40];
struct hv_device *dev_ctx = device_get_ivars(child);
+ char guidbuf[HYPERV_GUID_STRLEN];
if (dev_ctx == NULL)
return (0);
strlcat(buf, "classid=", buflen);
- snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->class_id);
+ hyperv_guid2str(&dev_ctx->class_id, guidbuf, sizeof(guidbuf));
strlcat(buf, guidbuf, buflen);
strlcat(buf, " deviceid=", buflen);
- snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->device_id);
+ hyperv_guid2str(&dev_ctx->device_id, guidbuf, sizeof(guidbuf));
strlcat(buf, guidbuf, buflen);
return (0);
@@ -521,30 +526,19 @@ hv_vmbus_child_device_create(hv_guid type, hv_guid instance,
}
int
-snprintf_hv_guid(char *buf, size_t sz, const hv_guid *guid)
-{
- int cnt;
- const unsigned char *d = guid->data;
-
- cnt = snprintf(buf, sz,
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
- d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
- return (cnt);
-}
-
-int
hv_vmbus_child_device_register(struct hv_device *child_dev)
{
- device_t child;
+ device_t child, parent;
+ parent = vmbus_get_device();
if (bootverbose) {
- char name[40];
- snprintf_hv_guid(name, sizeof(name), &child_dev->class_id);
- printf("VMBUS: Class ID: %s\n", name);
+ char name[HYPERV_GUID_STRLEN];
+
+ hyperv_guid2str(&child_dev->class_id, name, sizeof(name));
+ device_printf(parent, "add device, classid: %s\n", name);
}
- child = device_add_child(vmbus_get_device(), NULL, -1);
+ child = device_add_child(parent, NULL, -1);
child_dev->device = child;
device_set_ivars(child, child_dev);
@@ -568,7 +562,9 @@ hv_vmbus_child_device_unregister(struct hv_device *child_dev)
static int
vmbus_probe(device_t dev)
{
- if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL ||
+ char *id[] = { "VMBUS", NULL };
+
+ if (ACPI_ID_PROBE(device_get_parent(dev), dev, id) == NULL ||
device_get_unit(dev) != 0 || vm_guest != VM_GUEST_HV ||
(hyperv_features & CPUID_HV_MSR_SYNIC) == 0)
return (ENXIO);
diff --git a/sys/dev/hyperv/vmbus/hv_et.c b/sys/dev/hyperv/vmbus/vmbus_et.c
index 4999bc2..6e3fbfd 100644
--- a/sys/dev/hyperv/vmbus/hv_et.c
+++ b/sys/dev/hyperv/vmbus/vmbus_et.c
@@ -37,16 +37,14 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/timeet.h>
-#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
#include <dev/hyperv/vmbus/hyperv_reg.h>
#include <dev/hyperv/vmbus/hyperv_var.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
-#define HV_TIMER_FREQUENCY (10 * 1000 * 1000LL) /* 100ns period */
-#define HV_MAX_DELTA_TICKS 0xffffffffLL
-#define HV_MIN_DELTA_TICKS 1LL
+#define VMBUS_ET_NAME "hvet"
#define MSR_HV_STIMER0_CFG_SINT \
- ((((uint64_t)HV_VMBUS_TIMER_SINT) << MSR_HV_STIMER_CFG_SINT_SHIFT) & \
+ ((((uint64_t)VMBUS_SINT_TIMER) << MSR_HV_STIMER_CFG_SINT_SHIFT) & \
MSR_HV_STIMER_CFG_SINT_MASK)
/*
@@ -59,117 +57,140 @@ __FBSDID("$FreeBSD$");
CPUID_HV_MSR_SYNIC | \
CPUID_HV_MSR_SYNTIMER)
-static struct eventtimer *et;
+static struct eventtimer vmbus_et;
-static inline uint64_t
-sbintime2tick(sbintime_t time)
+static __inline uint64_t
+hyperv_sbintime2count(sbintime_t time)
{
struct timespec val;
val = sbttots(time);
- return val.tv_sec * HV_TIMER_FREQUENCY + val.tv_nsec / 100;
+ return (val.tv_sec * HYPERV_TIMER_FREQ) +
+ (val.tv_nsec / HYPERV_TIMER_NS_FACTOR);
}
static int
-hv_et_start(struct eventtimer *et, sbintime_t firsttime, sbintime_t periodtime)
+vmbus_et_start(struct eventtimer *et __unused, sbintime_t first,
+ sbintime_t period __unused)
{
- uint64_t current, config;
-
- config = MSR_HV_STIMER_CFG_AUTOEN | MSR_HV_STIMER0_CFG_SINT;
+ uint64_t current;
current = rdmsr(MSR_HV_TIME_REF_COUNT);
- current += sbintime2tick(firsttime);
-
- wrmsr(MSR_HV_STIMER0_CONFIG, config);
+ current += hyperv_sbintime2count(first);
wrmsr(MSR_HV_STIMER0_COUNT, current);
return (0);
}
-static int
-hv_et_stop(struct eventtimer *et)
-{
- wrmsr(MSR_HV_STIMER0_CONFIG, 0);
- wrmsr(MSR_HV_STIMER0_COUNT, 0);
-
- return (0);
-}
-
void
-hv_et_intr(struct trapframe *frame)
+vmbus_et_intr(struct trapframe *frame)
{
struct trapframe *oldframe;
struct thread *td;
- if (et->et_active) {
+ if (vmbus_et.et_active) {
td = curthread;
td->td_intr_nesting_level++;
oldframe = td->td_intr_frame;
td->td_intr_frame = frame;
- et->et_event_cb(et, et->et_arg);
+ vmbus_et.et_event_cb(&vmbus_et, vmbus_et.et_arg);
td->td_intr_frame = oldframe;
td->td_intr_nesting_level--;
}
}
static void
-hv_et_identify(driver_t *driver, device_t parent)
+vmbus_et_identify(driver_t *driver, device_t parent)
{
- if (device_find_child(parent, "hv_et", -1) != NULL ||
+ if (device_get_unit(parent) != 0 ||
+ device_find_child(parent, VMBUS_ET_NAME, -1) != NULL ||
(hyperv_features & CPUID_HV_ET_MASK) != CPUID_HV_ET_MASK)
return;
- device_add_child(parent, "hv_et", -1);
+ device_add_child(parent, VMBUS_ET_NAME, -1);
}
static int
-hv_et_probe(device_t dev)
+vmbus_et_probe(device_t dev)
{
+ if (resource_disabled(VMBUS_ET_NAME, 0))
+ return (ENXIO);
+
device_set_desc(dev, "Hyper-V event timer");
return (BUS_PROBE_NOWILDCARD);
}
+static void
+vmbus_et_config(void *arg __unused)
+{
+ /*
+ * Make sure that STIMER0 is really disabled before writing
+ * to STIMER0_CONFIG.
+ *
+ * "Writing to the configuration register of a timer that
+ * is already enabled may result in undefined behaviour."
+ */
+ for (;;) {
+ uint64_t val;
+
+ /* Stop counting, and this also implies disabling STIMER0 */
+ wrmsr(MSR_HV_STIMER0_COUNT, 0);
+
+ val = rdmsr(MSR_HV_STIMER0_CONFIG);
+ if ((val & MSR_HV_STIMER_CFG_ENABLE) == 0)
+ break;
+ cpu_spinwait();
+ }
+ wrmsr(MSR_HV_STIMER0_CONFIG,
+ MSR_HV_STIMER_CFG_AUTOEN | MSR_HV_STIMER0_CFG_SINT);
+}
+
static int
-hv_et_attach(device_t dev)
+vmbus_et_attach(device_t dev)
{
- /* XXX: need allocate SINT and remove global et */
- et = device_get_softc(dev);
-
- et->et_name = "Hyper-V";
- et->et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
- et->et_quality = 1000;
- et->et_frequency = HV_TIMER_FREQUENCY;
- et->et_min_period = HV_MIN_DELTA_TICKS * ((1LL << 32) / HV_TIMER_FREQUENCY);
- et->et_max_period = HV_MAX_DELTA_TICKS * ((1LL << 32) / HV_TIMER_FREQUENCY);
- et->et_start = hv_et_start;
- et->et_stop = hv_et_stop;
- et->et_priv = dev;
-
- return (et_register(et));
+ /* TODO: use independent IDT vector */
+
+ vmbus_et.et_name = "Hyper-V";
+ vmbus_et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
+ vmbus_et.et_quality = 1000;
+ vmbus_et.et_frequency = HYPERV_TIMER_FREQ;
+ vmbus_et.et_min_period = (0x00000001ULL << 32) / HYPERV_TIMER_FREQ;
+ vmbus_et.et_max_period = (0xfffffffeULL << 32) / HYPERV_TIMER_FREQ;
+ vmbus_et.et_start = vmbus_et_start;
+
+ /*
+ * Delay a bit to make sure that MSR_HV_TIME_REF_COUNT will
+ * not return 0, since writing 0 to STIMER0_COUNT will disable
+ * STIMER0.
+ */
+ DELAY(100);
+ smp_rendezvous(NULL, vmbus_et_config, NULL, NULL);
+
+ return (et_register(&vmbus_et));
}
static int
-hv_et_detach(device_t dev)
+vmbus_et_detach(device_t dev)
{
- return (et_deregister(et));
+ return (et_deregister(&vmbus_et));
}
-static device_method_t hv_et_methods[] = {
- DEVMETHOD(device_identify, hv_et_identify),
- DEVMETHOD(device_probe, hv_et_probe),
- DEVMETHOD(device_attach, hv_et_attach),
- DEVMETHOD(device_detach, hv_et_detach),
+static device_method_t vmbus_et_methods[] = {
+ DEVMETHOD(device_identify, vmbus_et_identify),
+ DEVMETHOD(device_probe, vmbus_et_probe),
+ DEVMETHOD(device_attach, vmbus_et_attach),
+ DEVMETHOD(device_detach, vmbus_et_detach),
DEVMETHOD_END
};
-static driver_t hv_et_driver = {
- "hv_et",
- hv_et_methods,
- sizeof(struct eventtimer)
+static driver_t vmbus_et_driver = {
+ VMBUS_ET_NAME,
+ vmbus_et_methods,
+ 0
};
-static devclass_t hv_et_devclass;
-DRIVER_MODULE(hv_et, vmbus, hv_et_driver, hv_et_devclass, NULL, 0);
+static devclass_t vmbus_et_devclass;
+DRIVER_MODULE(hv_et, vmbus, vmbus_et_driver, vmbus_et_devclass, NULL, NULL);
MODULE_VERSION(hv_et, 1);
diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h
new file mode 100644
index 0000000..465dced
--- /dev/null
+++ b/sys/dev/hyperv/vmbus/vmbus_reg.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * 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 unmodified, 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 ``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 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 _VMBUS_REG_H_
+#define _VMBUS_REG_H_
+
+#include <sys/param.h>
+
+/*
+ * Hyper-V SynIC message format.
+ */
+
+#define VMBUS_MSG_DSIZE_MAX 240
+#define VMBUS_MSG_SIZE 256
+
+struct vmbus_message {
+ uint32_t msg_type; /* VMBUS_MSGTYPE_ */
+ uint8_t msg_dsize; /* data size */
+ uint8_t msg_flags; /* VMBUS_MSGFLAG_ */
+ uint16_t msg_rsvd;
+ uint64_t msg_id;
+ uint8_t msg_data[VMBUS_MSG_DSIZE_MAX];
+} __packed;
+CTASSERT(sizeof(struct vmbus_message) == VMBUS_MSG_SIZE);
+
+#define VMBUS_MSGTYPE_NONE 0
+#define VMBUS_MSGTYPE_TIMER_EXPIRED 0x80000010
+
+#define VMBUS_MSGFLAG_PENDING 0x01
+
+/*
+ * Hyper-V SynIC event flags
+ */
+
+#ifdef __LP64__
+#define VMBUS_EVTFLAGS_MAX 32
+#define VMBUS_EVTFLAG_SHIFT 6
+#else
+#define VMBUS_EVTFLAGS_MAX 64
+#define VMBUS_EVTFLAG_SHIFT 5
+#endif
+#define VMBUS_EVTFLAG_LEN (1 << VMBUS_EVTFLAG_SHIFT)
+#define VMBUS_EVTFLAGS_SIZE 256
+
+struct vmbus_evtflags {
+ u_long evt_flags[VMBUS_EVTFLAGS_MAX];
+} __packed;
+CTASSERT(sizeof(struct vmbus_evtflags) == VMBUS_EVTFLAGS_SIZE);
+
+/*
+ * Channel
+ */
+
+#define VMBUS_CHAN_MAX_COMPAT 256
+#define VMBUS_CHAN_MAX (VMBUS_EVTFLAG_LEN * VMBUS_EVTFLAGS_MAX)
+
+#endif /* !_VMBUS_REG_H_ */
diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h
index 982e7a1..8cc070f 100644
--- a/sys/dev/hyperv/vmbus/vmbus_var.h
+++ b/sys/dev/hyperv/vmbus/vmbus_var.h
@@ -31,18 +31,31 @@
#include <sys/param.h>
#include <sys/bus_dma.h>
+#include <sys/taskqueue.h>
+
#include <dev/hyperv/include/hyperv_busdma.h>
+/*
+ * NOTE: DO NOT CHANGE THIS.
+ */
+#define VMBUS_SINT_MESSAGE 2
+/*
+ * NOTE:
+ * - DO NOT set it to the same value as VMBUS_SINT_MESSAGE.
+ * - DO NOT set it to 0.
+ */
+#define VMBUS_SINT_TIMER 4
+
struct vmbus_pcpu_data {
u_long *intr_cnt; /* Hyper-V interrupt counter */
struct vmbus_message *message; /* shared messages */
uint32_t vcpuid; /* virtual cpuid */
- int event_flag_cnt; /* # of event flags */
- union vmbus_event_flags *event_flag; /* shared event flags */
+ int event_flags_cnt;/* # of event flags */
+ struct vmbus_evtflags *event_flags; /* shared event flags */
/* Rarely used fields */
struct hyperv_dma message_dma; /* busdma glue */
- struct hyperv_dma event_flag_dma; /* busdma glue */
+ struct hyperv_dma event_flags_dma;/* busdma glue */
struct taskqueue *event_tq; /* event taskq */
struct taskqueue *message_tq; /* message taskq */
struct task message_task; /* message task */
@@ -78,8 +91,14 @@ vmbus_get_device(void)
#define VMBUS_PCPU_GET(sc, field, cpu) (sc)->vmbus_pcpu[(cpu)].field
#define VMBUS_PCPU_PTR(sc, field, cpu) &(sc)->vmbus_pcpu[(cpu)].field
+struct hv_vmbus_channel;
+struct trapframe;
+
void vmbus_on_channel_open(const struct hv_vmbus_channel *);
void vmbus_event_proc(struct vmbus_softc *, int);
void vmbus_event_proc_compat(struct vmbus_softc *, int);
+void vmbus_handle_intr(struct trapframe *);
+
+void vmbus_et_intr(struct trapframe *);
#endif /* !_VMBUS_VAR_H_ */
diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c
index ff27da2..44bc64e 100644
--- a/sys/dev/ichiic/ig4_iic.c
+++ b/sys/dev/ichiic/ig4_iic.c
@@ -108,6 +108,17 @@ set_controller(ig4iic_softc_t *sc, uint32_t ctl)
int error;
uint32_t v;
+ /*
+ * When the controller is enabled, interrupt on STOP detect
+ * or receive character ready and clear pending interrupts.
+ */
+ if (ctl & IG4_I2C_ENABLE) {
+ reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
+ IG4_INTR_RX_FULL);
+ reg_read(sc, IG4_REG_CLR_INTR);
+ } else
+ reg_write(sc, IG4_REG_INTR_MASK, 0);
+
reg_write(sc, IG4_REG_I2C_EN, ctl);
error = SMB_ETIMEOUT;
@@ -553,11 +564,6 @@ ig4iic_attach(ig4iic_softc_t *sc)
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT);
#endif
- /*
- * Interrupt on STOP detect or receive character ready
- */
- reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
- IG4_INTR_RX_FULL);
mtx_lock(&sc->io_lock);
if (set_controller(sc, 0))
device_printf(sc->dev, "controller error during attach-1\n");
@@ -574,7 +580,8 @@ ig4iic_attach(ig4iic_softc_t *sc)
sc->enum_hook.ich_func = ig4iic_start;
sc->enum_hook.ich_arg = sc->dev;
- /* We have to wait until interrupts are enabled. I2C read and write
+ /*
+ * We have to wait until interrupts are enabled. I2C read and write
* only works if the interrupts are available.
*/
if (config_intrhook_establish(&sc->enum_hook) != 0)
@@ -628,7 +635,6 @@ ig4iic_detach(ig4iic_softc_t *sc)
sc->smb = NULL;
sc->intr_handle = NULL;
reg_write(sc, IG4_REG_INTR_MASK, 0);
- reg_read(sc, IG4_REG_CLR_INTR);
set_controller(sc, 0);
mtx_unlock(&sc->io_lock);
@@ -917,6 +923,7 @@ ig4iic_intr(void *cookie)
mtx_lock(&sc->io_lock);
/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/
+ reg_read(sc, IG4_REG_CLR_INTR);
status = reg_read(sc, IG4_REG_I2C_STA);
while (status & IG4_STATUS_RX_NOTEMPTY) {
sc->rbuf[sc->rnext & IG4_RBUFMASK] =
@@ -924,7 +931,6 @@ ig4iic_intr(void *cookie)
++sc->rnext;
status = reg_read(sc, IG4_REG_I2C_STA);
}
- reg_read(sc, IG4_REG_CLR_INTR);
wakeup(sc);
mtx_unlock(&sc->io_lock);
}
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index 25f3a91..e335dc7 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -406,6 +406,11 @@ iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
KASSERT(STAILQ_EMPTY(&is->is_postponed),
("destroying session with postponed PDUs"));
+ if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) {
+ ISCSI_SESSION_UNLOCK(is);
+ return;
+ }
+
/*
* Request immediate reconnection from iscsid(8).
*/
@@ -549,6 +554,9 @@ iscsi_callout(void *context)
callout_schedule(&is->is_callout, 1 * hz);
+ if (is->is_conf.isc_enable == 0)
+ goto out;
+
is->is_timeout++;
if (is->is_waiting_for_iscsid) {
@@ -1311,6 +1319,11 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
for (;;) {
TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
ISCSI_SESSION_LOCK(is);
+ if (is->is_conf.isc_enable == 0 &&
+ is->is_conf.isc_discovery == 0) {
+ ISCSI_SESSION_UNLOCK(is);
+ continue;
+ }
if (is->is_waiting_for_iscsid)
break;
ISCSI_SESSION_UNLOCK(is);
@@ -1826,17 +1839,22 @@ iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
+ ISCSI_SESSION_LOCK(is);
/*
- * Trigger immediate reconnection.
+ * Don't notify iscsid(8) if the session is disabled and it's not
+ * a discovery session,
*/
- ISCSI_SESSION_LOCK(is);
+ if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) {
+ ISCSI_SESSION_UNLOCK(is);
+ sx_xunlock(&sc->sc_lock);
+ return (0);
+ }
+
is->is_waiting_for_iscsid = true;
strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
ISCSI_SESSION_UNLOCK(is);
cv_signal(&sc->sc_cv);
-
sx_xunlock(&sc->sc_lock);
-
return (0);
}
diff --git a/sys/dev/iscsi/iscsi_ioctl.h b/sys/dev/iscsi/iscsi_ioctl.h
index 1dd7b0a..38d905d 100644
--- a/sys/dev/iscsi/iscsi_ioctl.h
+++ b/sys/dev/iscsi/iscsi_ioctl.h
@@ -67,7 +67,8 @@ struct iscsi_session_conf {
int isc_data_digest;
int isc_iser;
char isc_offload[ISCSI_OFFLOAD_LEN];
- int isc_spare[2];
+ int isc_enable;
+ int isc_spare[1];
};
/*
diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index d622d3f..b60d053 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -163,6 +163,7 @@ __FBSDID("$FreeBSD$");
#include <dev/iwm/if_iwm_scan.h>
#include <dev/iwm/if_iwm_pcie_trans.h>
+#include <dev/iwm/if_iwm_led.h>
const uint8_t iwm_nvm_channels[] = {
/* 2.4 GHz */
@@ -224,6 +225,7 @@ static void iwm_free_kw(struct iwm_softc *);
static int iwm_alloc_ict(struct iwm_softc *);
static void iwm_free_ict(struct iwm_softc *);
static int iwm_alloc_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
+static void iwm_disable_rx_dma(struct iwm_softc *);
static void iwm_reset_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
static void iwm_free_rx_ring(struct iwm_softc *, struct iwm_rx_ring *);
static int iwm_alloc_tx_ring(struct iwm_softc *, struct iwm_tx_ring *,
@@ -263,7 +265,6 @@ static int iwm_firmware_load_chunk(struct iwm_softc *, uint32_t,
const uint8_t *, uint32_t);
static int iwm_load_firmware(struct iwm_softc *, enum iwm_ucode_type);
static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type);
-static int iwm_fw_alive(struct iwm_softc *, uint32_t);
static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t);
static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *,
@@ -880,7 +881,7 @@ fail: iwm_free_rx_ring(sc, ring);
}
static void
-iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
+iwm_disable_rx_dma(struct iwm_softc *sc)
{
/* XXX print out if we can't lock the NIC? */
@@ -889,6 +890,11 @@ iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
(void) iwm_pcie_rx_stop(sc);
iwm_nic_unlock(sc);
}
+}
+
+static void
+iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring)
+{
/* Reset the ring state */
ring->cur = 0;
memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat));
@@ -1151,6 +1157,7 @@ iwm_stop_device(struct iwm_softc *sc)
}
iwm_nic_unlock(sc);
}
+ iwm_disable_rx_dma(sc);
/* Stop RX ring. */
iwm_reset_rx_ring(sc, &sc->rxq);
@@ -1240,7 +1247,7 @@ iwm_nic_rx_init(struct iwm_softc *sc)
memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat));
/* stop DMA */
- IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ iwm_disable_rx_dma(sc);
IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0);
IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0);
IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_RDPTR, 0);
@@ -1345,14 +1352,6 @@ iwm_nic_init(struct iwm_softc *sc)
return 0;
}
-enum iwm_mvm_tx_fifo {
- IWM_MVM_TX_FIFO_BK = 0,
- IWM_MVM_TX_FIFO_BE,
- IWM_MVM_TX_FIFO_VI,
- IWM_MVM_TX_FIFO_VO,
- IWM_MVM_TX_FIFO_MCAST = 5,
-};
-
const uint8_t iwm_mvm_ac_to_tx_fifo[] = {
IWM_MVM_TX_FIFO_VO,
IWM_MVM_TX_FIFO_VI,
@@ -1765,22 +1764,12 @@ iwm_parse_nvm_data(struct iwm_softc *sc,
data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg);
data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg);
data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg);
- data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
- data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
sku = le16_to_cpup(nvm_sw + IWM_SKU);
data->sku_cap_band_24GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_24GHZ;
data->sku_cap_band_52GHz_enable = sku & IWM_NVM_SKU_CAP_BAND_52GHZ;
data->sku_cap_11n_enable = 0;
- if (!data->valid_tx_ant || !data->valid_rx_ant) {
- device_printf(sc->sc_dev,
- "%s: invalid antennas (0x%x, 0x%x)\n",
- __func__, data->valid_tx_ant,
- data->valid_rx_ant);
- return EINVAL;
- }
-
data->n_hw_addrs = le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS);
data->xtal_calib[0] = *(nvm_calib + IWM_XTAL_CALIB);
@@ -1997,12 +1986,6 @@ iwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
}
static int
-iwm_fw_alive(struct iwm_softc *sc, uint32_t sched_base)
-{
- return iwm_post_alive(sc);
-}
-
-static int
iwm_send_tx_ant_cfg(struct iwm_softc *sc, uint8_t valid_tx_ant)
{
struct iwm_tx_ant_cfg_cmd tx_ant_cmd = {
@@ -2050,7 +2033,7 @@ iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc,
return error;
}
- return iwm_fw_alive(sc, sc->sched_base);
+ return iwm_post_alive(sc);
}
/*
@@ -2074,8 +2057,10 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)
sc->sc_init_complete = 0;
if ((error = iwm_mvm_load_ucode_wait_alive(sc,
- IWM_UCODE_TYPE_INIT)) != 0)
+ IWM_UCODE_TYPE_INIT)) != 0) {
+ device_printf(sc->sc_dev, "failed to load init firmware\n");
return error;
+ }
if (justnvm) {
if ((error = iwm_nvm_init(sc)) != 0) {
@@ -3014,13 +2999,7 @@ iwm_mvm_sta_send_to_fw(struct iwm_softc *sc, struct iwm_node *in, int update)
static int
iwm_mvm_add_sta(struct iwm_softc *sc, struct iwm_node *in)
{
- int ret;
-
- ret = iwm_mvm_sta_send_to_fw(sc, in, 0);
- if (ret)
- return ret;
-
- return 0;
+ return iwm_mvm_sta_send_to_fw(sc, in, 0);
}
static int
@@ -3515,6 +3494,10 @@ iwm_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_state_name[nstate]);
IEEE80211_UNLOCK(ic);
IWM_LOCK(sc);
+
+ if (vap->iv_state == IEEE80211_S_SCAN && nstate != vap->iv_state)
+ iwm_led_blink_stop(sc);
+
/* disable beacon filtering if we're hopping out of RUN */
if (vap->iv_state == IEEE80211_S_RUN && nstate != vap->iv_state) {
iwm_mvm_disable_beacon_filter(sc);
@@ -3637,7 +3620,8 @@ iwm_endscan_cb(void *arg, int pending)
done = 0;
if ((error = iwm_mvm_scan_request(sc,
IEEE80211_CHAN_5GHZ, 0, NULL, 0)) != 0) {
- device_printf(sc->sc_dev, "could not initiate scan\n");
+ device_printf(sc->sc_dev,
+ "could not initiate 5 GHz scan\n");
done = 1;
}
} else {
@@ -3829,6 +3813,7 @@ iwm_stop(struct iwm_softc *sc)
sc->sc_flags |= IWM_FLAG_STOPPED;
sc->sc_generation++;
sc->sc_scanband = 0;
+ iwm_led_blink_stop(sc);
sc->sc_tx_timer = 0;
iwm_stop_device(sc);
}
@@ -4600,6 +4585,7 @@ iwm_attach(device_t dev)
IWM_LOCK_INIT(sc);
mbufq_init(&sc->sc_snd, ifqmaxlen);
callout_init_mtx(&sc->sc_watchdog_to, &sc->sc_mtx, 0);
+ callout_init_mtx(&sc->sc_led_blink_to, &sc->sc_mtx, 0);
TASK_INIT(&sc->sc_es_task, 0, iwm_endscan_cb, sc);
sc->sc_tq = taskqueue_create("iwm_taskq", M_WAITOK,
taskqueue_thread_enqueue, &sc->sc_tq);
@@ -4876,16 +4862,27 @@ iwm_scan_start(struct ieee80211com *ic)
IWM_LOCK(sc);
error = iwm_mvm_scan_request(sc, IEEE80211_CHAN_2GHZ, 0, NULL, 0);
if (error) {
- device_printf(sc->sc_dev, "could not initiate scan\n");
+ device_printf(sc->sc_dev, "could not initiate 2 GHz scan\n");
IWM_UNLOCK(sc);
ieee80211_cancel_scan(vap);
- } else
+ sc->sc_scanband = 0;
+ } else {
+ iwm_led_blink_start(sc);
IWM_UNLOCK(sc);
+ }
}
static void
iwm_scan_end(struct ieee80211com *ic)
{
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct iwm_softc *sc = ic->ic_softc;
+
+ IWM_LOCK(sc);
+ iwm_led_blink_stop(sc);
+ if (vap->iv_state == IEEE80211_S_RUN)
+ iwm_mvm_led_enable(sc);
+ IWM_UNLOCK(sc);
}
static void
@@ -4982,6 +4979,7 @@ iwm_detach_local(struct iwm_softc *sc, int do_net80211)
taskqueue_drain_all(sc->sc_tq);
taskqueue_free(sc->sc_tq);
}
+ callout_drain(&sc->sc_led_blink_to);
callout_drain(&sc->sc_watchdog_to);
iwm_stop_device(sc);
if (do_net80211)
diff --git a/sys/dev/iwm/if_iwm_led.c b/sys/dev/iwm/if_iwm_led.c
new file mode 100644
index 0000000..53a3857
--- /dev/null
+++ b/sys/dev/iwm/if_iwm_led.c
@@ -0,0 +1,182 @@
+/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
+
+/*
+ * Copyright (c) 2014 genua mbh <info@genua.de>
+ * Copyright (c) 2014 Fixup Software Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Based on BSD-licensed source modules in the Linux iwlwifi driver,
+ * which were used as the reference documentation for this implementation.
+ *
+ * Driver version we are currently based off of is
+ * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
+ *
+ ***********************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name Intel Corporation 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/firmware.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/linker.h>
+
+#include <machine/endian.h>
+#include <machine/bus.h>
+
+#include <net/bpf.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_ratectl.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/iwm/if_iwmreg.h>
+#include <dev/iwm/if_iwmvar.h>
+#include <dev/iwm/if_iwm_debug.h>
+#include <dev/iwm/if_iwm_util.h>
+#include <dev/iwm/if_iwm_led.h>
+
+/* Set led register on */
+void
+iwm_mvm_led_enable(struct iwm_softc *sc)
+{
+ IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_ON);
+}
+
+/* Set led register off */
+void
+iwm_mvm_led_disable(struct iwm_softc *sc)
+{
+ IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_OFF);
+}
+
+int
+iwm_mvm_led_is_enabled(struct iwm_softc *sc)
+{
+ return (IWM_READ(sc, IWM_CSR_LED_REG) == IWM_CSR_LED_REG_TURN_ON);
+}
+
+void
+iwm_led_blink_timeout(void *arg)
+{
+ struct iwm_softc *sc = arg;
+
+ if (iwm_mvm_led_is_enabled(sc))
+ iwm_mvm_led_disable(sc);
+ else
+ iwm_mvm_led_enable(sc);
+
+ callout_reset(&sc->sc_led_blink_to, (200 * hz) / 1000,
+ iwm_led_blink_timeout, sc);
+}
+
+void
+iwm_led_blink_start(struct iwm_softc *sc)
+{
+ callout_reset(&sc->sc_led_blink_to, 0, iwm_led_blink_timeout, sc);
+}
+
+void
+iwm_led_blink_stop(struct iwm_softc *sc)
+{
+ callout_drain(&sc->sc_led_blink_to);
+ iwm_mvm_led_disable(sc);
+}
diff --git a/sys/dev/iwm/if_iwm_led.h b/sys/dev/iwm/if_iwm_led.h
new file mode 100644
index 0000000..b5c7d1c
--- /dev/null
+++ b/sys/dev/iwm/if_iwm_led.h
@@ -0,0 +1,101 @@
+/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
+
+/*
+ * Copyright (c) 2014 genua mbh <info@genua.de>
+ * Copyright (c) 2014 Fixup Software Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Based on BSD-licensed source modules in the Linux iwlwifi driver,
+ * which were used as the reference documentation for this implementation.
+ *
+ * Driver version we are currently based off of is
+ * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
+ *
+ ***********************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name Intel Corporation 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 __IF_IWM_LED_H__
+#define __IF_IWM_LED_H__
+
+void iwm_mvm_led_enable(struct iwm_softc *);
+void iwm_mvm_led_disable(struct iwm_softc *);
+int iwm_mvm_led_is_enabled(struct iwm_softc *);
+void iwm_led_blink_timeout(void *);
+void iwm_led_blink_start(struct iwm_softc *);
+void iwm_led_blink_stop(struct iwm_softc *);
+
+#endif /* __IF_IWM_LED_H__ */
diff --git a/sys/dev/iwm/if_iwm_pcie_trans.c b/sys/dev/iwm/if_iwm_pcie_trans.c
index 63c1576..8f2f728 100644
--- a/sys/dev/iwm/if_iwm_pcie_trans.c
+++ b/sys/dev/iwm/if_iwm_pcie_trans.c
@@ -363,6 +363,8 @@ iwm_prepare_card_hw(struct iwm_softc *sc)
if (iwm_set_hw_ready(sc))
goto out;
+ DELAY(100);
+
/* If HW is not ready, prepare the conditions to check again */
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
@@ -456,7 +458,7 @@ iwm_apm_init(struct iwm_softc *sc)
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
device_printf(sc->sc_dev,
"timeout waiting for clock stabilization\n");
-
+ error = ETIMEDOUT;
goto out;
}
diff --git a/sys/dev/iwm/if_iwm_phy_db.h b/sys/dev/iwm/if_iwm_phy_db.h
index 98eb60b..a1de220 100644
--- a/sys/dev/iwm/if_iwm_phy_db.h
+++ b/sys/dev/iwm/if_iwm_phy_db.h
@@ -106,41 +106,6 @@
#ifndef __IF_IWM_PHY_DB_H__
#define __IF_IWM_PHY_DB_H__
-enum iwm_phy_db_section_type {
- IWM_PHY_DB_CFG = 1,
- IWM_PHY_DB_CALIB_NCH,
- IWM_PHY_DB_UNUSED,
- IWM_PHY_DB_CALIB_CHG_PAPD,
- IWM_PHY_DB_CALIB_CHG_TXP,
- IWM_PHY_DB_MAX
-};
-
-#define IWM_PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
-
-/*
- * phy db - configure operational ucode
- */
-struct iwm_phy_db_cmd {
- uint16_t type;
- uint16_t length;
- uint8_t data[];
-} __packed;
-
-/* for parsing of tx power channel group data that comes from the firmware*/
-struct iwm_phy_db_chg_txp {
- uint32_t space;
- uint16_t max_channel_idx;
-} __packed;
-
-/*
- * phy db - Receive phy db chunk after calibrations
- */
-struct iwm_calib_res_notif_phy_db {
- uint16_t type;
- uint16_t length;
- uint8_t data[];
-} __packed;
-
extern int iwm_phy_db_set_section(struct iwm_softc *sc,
struct iwm_calib_res_notif_phy_db *phy_db_notif);
extern int iwm_send_phy_db_data(struct iwm_softc *sc);
diff --git a/sys/dev/iwm/if_iwm_power.c b/sys/dev/iwm/if_iwm_power.c
index 93352ae..6503756 100644
--- a/sys/dev/iwm/if_iwm_power.c
+++ b/sys/dev/iwm/if_iwm_power.c
@@ -233,30 +233,6 @@ iwm_mvm_power_log(struct iwm_softc *sc, struct iwm_mac_power_cmd *cmd)
"Disable power management\n");
return;
}
- KASSERT(0, ("unhandled power management"));
-
-#if 0
- DPRINTF(mvm, "Rx timeout = %u usec\n",
- le32_to_cpu(cmd->rx_data_timeout));
- DPRINTF(mvm, "Tx timeout = %u usec\n",
- le32_to_cpu(cmd->tx_data_timeout));
- if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK))
- DPRINTF(mvm, "DTIM periods to skip = %u\n",
- cmd->skip_dtim_periods);
- if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_LPRX_ENA_MSK))
- DPRINTF(mvm, "LP RX RSSI threshold = %u\n",
- cmd->lprx_rssi_threshold);
- if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
- DPRINTF(mvm, "uAPSD enabled\n");
- DPRINTF(mvm, "Rx timeout (uAPSD) = %u usec\n",
- le32_to_cpu(cmd->rx_data_timeout_uapsd));
- DPRINTF(mvm, "Tx timeout (uAPSD) = %u usec\n",
- le32_to_cpu(cmd->tx_data_timeout_uapsd));
- DPRINTF(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
- DPRINTF(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
- DPRINTF(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
- }
-#endif
}
static void
diff --git a/sys/dev/iwm/if_iwm_scan.c b/sys/dev/iwm/if_iwm_scan.c
index ebcadf7..6d68601 100644
--- a/sys/dev/iwm/if_iwm_scan.c
+++ b/sys/dev/iwm/if_iwm_scan.c
@@ -443,7 +443,6 @@ iwm_mvm_scan_request(struct iwm_softc *sc, int flags,
* to allocate the time events. Warn on it, but maybe we
* should try to send the command again with different params.
*/
- sc->sc_scanband = 0;
ret = EIO;
}
return ret;
diff --git a/sys/dev/iwm/if_iwm_util.c b/sys/dev/iwm/if_iwm_util.c
index d4327a3..99002a1 100644
--- a/sys/dev/iwm/if_iwm_util.c
+++ b/sys/dev/iwm/if_iwm_util.c
@@ -224,7 +224,10 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
"large command paylen=%u len0=%u\n",
paylen, hcmd->len[0]);
/* Command is too large */
- if (sizeof(cmd->hdr) + paylen > IWM_RBUF_SIZE) {
+ if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {
+ device_printf(sc->sc_dev,
+ "firmware command too long (%zd bytes)\n",
+ paylen + sizeof(cmd->hdr));
error = EINVAL;
goto out;
}
@@ -269,7 +272,7 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
(unsigned long) (hcmd->len[0] + hcmd->len[1] + sizeof(cmd->hdr)),
async ? " (async)" : "");
- if (hcmd->len[0] > sizeof(cmd->data)) {
+ if (paylen > sizeof(cmd->data)) {
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_PREWRITE);
} else {
diff --git a/sys/dev/iwm/if_iwmreg.h b/sys/dev/iwm/if_iwmreg.h
index bbfb36ee..12cfd96 100644
--- a/sys/dev/iwm/if_iwmreg.h
+++ b/sys/dev/iwm/if_iwmreg.h
@@ -539,7 +539,7 @@ enum iwm_dtd_diode_reg {
*/
/**
- * enum iwl_ucode_tlv_flag - ucode API flags
+ * enum iwm_ucode_tlv_flag - ucode API flags
* @IWM_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
* was a separate TLV but moved here to save space.
* @IWM_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
@@ -1519,7 +1519,14 @@ enum {
IWM_MVM_CMD_QUEUE = 9,
};
-#define IWM_MVM_CMD_FIFO 7
+enum iwm_mvm_tx_fifo {
+ IWM_MVM_TX_FIFO_BK = 0,
+ IWM_MVM_TX_FIFO_BE,
+ IWM_MVM_TX_FIFO_VI,
+ IWM_MVM_TX_FIFO_VO,
+ IWM_MVM_TX_FIFO_MCAST = 5,
+ IWM_MVM_TX_FIFO_CMD = 7,
+};
#define IWM_MVM_STATION_COUNT 16
@@ -1741,6 +1748,45 @@ struct iwm_phy_cfg_cmd {
#define IWM_PHY_CFG_RX_CHAIN_B (1 << 13)
#define IWM_PHY_CFG_RX_CHAIN_C (1 << 14)
+/*
+ * PHY db
+ */
+
+enum iwm_phy_db_section_type {
+ IWM_PHY_DB_CFG = 1,
+ IWM_PHY_DB_CALIB_NCH,
+ IWM_PHY_DB_UNUSED,
+ IWM_PHY_DB_CALIB_CHG_PAPD,
+ IWM_PHY_DB_CALIB_CHG_TXP,
+ IWM_PHY_DB_MAX
+};
+
+#define IWM_PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
+
+/*
+ * phy db - configure operational ucode
+ */
+struct iwm_phy_db_cmd {
+ uint16_t type;
+ uint16_t length;
+ uint8_t data[];
+} __packed;
+
+/* for parsing of tx power channel group data that comes from the firmware */
+struct iwm_phy_db_chg_txp {
+ uint32_t space;
+ uint16_t max_channel_idx;
+} __packed;
+
+/*
+ * phy db - Receive phy db chunk after calibrations
+ */
+struct iwm_calib_res_notif_phy_db {
+ uint16_t type;
+ uint16_t length;
+ uint8_t data[];
+} __packed;
+
/* Target of the IWM_NVM_ACCESS_CMD */
enum {
@@ -5243,6 +5289,7 @@ enum iwm_power_scheme {
};
#define IWM_DEF_CMD_PAYLOAD_SIZE 320
+#define IWM_MAX_CMD_PAYLOAD_SIZE ((4096 - 4) - sizeof(struct iwm_cmd_header))
#define IWM_CMD_FAILED_MSK 0x40
struct iwm_device_cmd {
diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h
index 894dd80..ef2eac4 100644
--- a/sys/dev/iwm/if_iwmvar.h
+++ b/sys/dev/iwm/if_iwmvar.h
@@ -412,6 +412,7 @@ struct iwm_softc {
struct intr_config_hook sc_preinit_hook;
struct callout sc_watchdog_to;
+ struct callout sc_led_blink_to;
struct task init_task;
diff --git a/sys/dev/ixl/i40e_prototype.h b/sys/dev/ixl/i40e_prototype.h
index ab981e2..c53945f 100644
--- a/sys/dev/ixl/i40e_prototype.h
+++ b/sys/dev/ixl/i40e_prototype.h
@@ -501,6 +501,4 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw, u8 page,
enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
-enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
- u32 time, u32 interval);
#endif /* _I40E_PROTOTYPE_H_ */
diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c
index 71219be..1873958 100644
--- a/sys/dev/mrsas/mrsas.c
+++ b/sys/dev/mrsas/mrsas.c
@@ -188,6 +188,8 @@ MRSAS_CTLR_ID device_table[] = {
{0x1000, MRSAS_FURY, 0xffff, 0xffff, "AVAGO Fury SAS Controller"},
{0x1000, MRSAS_INTRUDER, 0xffff, 0xffff, "AVAGO Intruder SAS Controller"},
{0x1000, MRSAS_INTRUDER_24, 0xffff, 0xffff, "AVAGO Intruder_24 SAS Controller"},
+ {0x1000, MRSAS_CUTLASS_52, 0xffff, 0xffff, "AVAGO Cutlass_52 SAS Controller"},
+ {0x1000, MRSAS_CUTLASS_53, 0xffff, 0xffff, "AVAGO Cutlass_53 SAS Controller"},
{0, 0, 0, 0, NULL}
};
@@ -1630,7 +1632,9 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24))
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53))
mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8],
((MSIxIndex & 0x7) << 24) |
sc->last_reply_idx[MSIxIndex]);
@@ -1654,7 +1658,9 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8],
((MSIxIndex & 0x7) << 24) |
sc->last_reply_idx[MSIxIndex]);
@@ -2455,7 +2461,9 @@ mrsas_ioc_init(struct mrsas_softc *sc)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
init_frame->driver_operations.
mfi_capabilities.support_additional_msix = 1;
}
@@ -3491,7 +3499,9 @@ mrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cm
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
pMpi25IeeeSgeChain64_t sgl_ptr_end = (pMpi25IeeeSgeChain64_t)&io_req->SGL;
sgl_ptr_end += sc->max_sge_in_main_msg - 1;
diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h
index 4d19b4f..2c2a341 100644
--- a/sys/dev/mrsas/mrsas.h
+++ b/sys/dev/mrsas/mrsas.h
@@ -82,6 +82,8 @@ __FBSDID("$FreeBSD$");
#define MRSAS_FURY 0x005f
#define MRSAS_INTRUDER 0x00ce
#define MRSAS_INTRUDER_24 0x00cf
+#define MRSAS_CUTLASS_52 0x0052
+#define MRSAS_CUTLASS_53 0x0053
#define MRSAS_PCI_BAR0 0x10
#define MRSAS_PCI_BAR1 0x14
#define MRSAS_PCI_BAR2 0x1C
diff --git a/sys/dev/mrsas/mrsas_cam.c b/sys/dev/mrsas/mrsas_cam.c
index 0cf00376..e52e26d 100644
--- a/sys/dev/mrsas/mrsas_cam.c
+++ b/sys/dev/mrsas/mrsas_cam.c
@@ -880,7 +880,9 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
cmd->request_desc->SCSIIO.RequestFlags =
(MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
@@ -912,7 +914,9 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
cmd->request_desc->SCSIIO.RequestFlags =
(MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
@@ -1191,7 +1195,9 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
pMpi25IeeeSgeChain64_t sgl_ptr_end = sgl_ptr;
sgl_ptr_end += sc->max_sge_in_main_msg - 1;
@@ -1205,7 +1211,9 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
if (i == nseg - 1)
sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
}
@@ -1218,7 +1226,9 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24)) {
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53)) {
if ((cmd->io_request->IoFlags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
!= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
cmd->io_request->ChainOffset = sc->chain_offset_io_request;
@@ -1230,7 +1240,9 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24))
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53))
sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
else
sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
diff --git a/sys/dev/mrsas/mrsas_fp.c b/sys/dev/mrsas/mrsas_fp.c
index 470b0f7..f83d52b 100644
--- a/sys/dev/mrsas/mrsas_fp.c
+++ b/sys/dev/mrsas/mrsas_fp.c
@@ -752,7 +752,9 @@ mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripR
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24))
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53))
do_invader = 1;
/* Get row and span from io_info for Uneven Span IO. */
@@ -966,7 +968,9 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info,
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24))
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53))
pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
else
pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
@@ -1454,7 +1458,9 @@ MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld,
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY) ||
(sc->device_id == MRSAS_INTRUDER) ||
- (sc->device_id == MRSAS_INTRUDER_24))
+ (sc->device_id == MRSAS_INTRUDER_24) ||
+ (sc->device_id == MRSAS_CUTLASS_52) ||
+ (sc->device_id == MRSAS_CUTLASS_53))
do_invader = 1;
row = mega_div64_32(stripRow, raid->rowDataSize);
diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c
index bf58e96..ef18146 100644
--- a/sys/dev/pci/pci_host_generic.c
+++ b/sys/dev/pci/pci_host_generic.c
@@ -181,6 +181,29 @@ pci_host_generic_attach(device_t dev)
if (generic_pcie_ofw_bus_attach(dev) != 0)
return (ENXIO);
+ node = ofw_bus_get_node(dev);
+ if (sc->coherent == 0) {
+ sc->coherent = OF_hasprop(node, "dma-coherent");
+ }
+ if (bootverbose)
+ device_printf(dev, "Bus is%s cache-coherent\n",
+ sc->coherent ? "" : " not");
+
+ /* Create the parent DMA tag to pass down the coherent flag */
+ error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
+ 1, 0, /* alignment, bounds */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE, /* maxsize */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
+ BUS_SPACE_MAXSIZE, /* maxsegsize */
+ sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->dmat);
+ if (error != 0)
+ return (error);
+
rid = 0;
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (sc->res == NULL) {
@@ -232,7 +255,6 @@ pci_host_generic_attach(device_t dev)
}
}
- node = ofw_bus_get_node(dev);
ofw_bus_setup_iinfo(node, &sc->pci_iinfo, sizeof(cell_t));
device_add_child(dev, "pci", -1);
@@ -682,6 +704,15 @@ generic_pcie_deactivate_resource(device_t dev, device_t child, int type, int rid
return (res);
}
+static bus_dma_tag_t
+generic_pcie_get_dma_tag(device_t dev, device_t child)
+{
+ struct generic_pcie_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (sc->dmat);
+}
+
static int
generic_pcie_alloc_msi(device_t pci, device_t child, int count, int maxcount,
int *irqs)
@@ -798,6 +829,8 @@ static device_method_t generic_pcie_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_get_dma_tag, generic_pcie_get_dma_tag),
+
/* pcib interface */
DEVMETHOD(pcib_maxslots, generic_pcie_maxslots),
DEVMETHOD(pcib_route_interrupt, generic_pcie_route_interrupt),
diff --git a/sys/dev/pci/pci_host_generic.h b/sys/dev/pci/pci_host_generic.h
index 2f8bd83..3b307b4 100644
--- a/sys/dev/pci/pci_host_generic.h
+++ b/sys/dev/pci/pci_host_generic.h
@@ -49,6 +49,7 @@ struct pcie_range {
struct generic_pcie_softc {
struct pcie_range ranges[MAX_RANGES_TUPLES];
int nranges;
+ int coherent;
struct rman mem_rman;
struct rman io_rman;
struct resource *res;
@@ -58,6 +59,7 @@ struct generic_pcie_softc {
bus_space_handle_t bsh;
device_t dev;
bus_space_handle_t ioh;
+ bus_dma_tag_t dmat;
#ifdef FDT
struct ofw_bus_iinfo pci_iinfo;
#endif
diff --git a/sys/dev/sfxge/common/ef10_ev.c b/sys/dev/sfxge/common/ef10_ev.c
index f21666d..b641cd4 100644
--- a/sys/dev/sfxge/common/ef10_ev.c
+++ b/sys/dev/sfxge/common/ef10_ev.c
@@ -92,8 +92,10 @@ efx_mcdi_init_evq(
__in unsigned int instance,
__in efsys_mem_t *esmp,
__in size_t nevs,
- __in uint32_t irq)
+ __in uint32_t irq,
+ __in uint32_t us)
{
+ efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
efx_mcdi_req_t req;
uint8_t payload[
MAX(MC_CMD_INIT_EVQ_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_MAXNEVS)),
@@ -141,10 +143,26 @@ efx_mcdi_init_evq(
INIT_EVQ_IN_FLAG_RX_MERGE, 1,
INIT_EVQ_IN_FLAG_TX_MERGE, 1);
- MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
- MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
- MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0);
- MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0);
+ if (us == 0) {
+ MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
+ MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
+ MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0);
+ MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0);
+ } else {
+ uint32_t timer_val;
+
+ /* Calculate the timer value in quanta */
+ timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns;
+
+ /* Moderation value is base 0 so we need to deduct 1 */
+ if (timer_val > 0)
+ timer_val--;
+
+ MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
+ MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF);
+ MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, timer_val);
+ MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, timer_val);
+ }
MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_MODE,
MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS);
@@ -246,6 +264,7 @@ ef10_ev_qcreate(
__in efsys_mem_t *esmp,
__in size_t n,
__in uint32_t id,
+ __in uint32_t us,
__in efx_evq_t *eep)
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
@@ -266,6 +285,11 @@ ef10_ev_qcreate(
goto fail2;
}
+ if (us > encp->enc_evq_timer_max_us) {
+ rc = EINVAL;
+ goto fail3;
+ }
+
/* Set up the handler table */
eep->ee_rx = ef10_ev_rx;
eep->ee_tx = ef10_ev_tx;
@@ -280,11 +304,13 @@ ef10_ev_qcreate(
* Interrupts may be raised for events immediately after the queue is
* created. See bug58606.
*/
- if ((rc = efx_mcdi_init_evq(enp, index, esmp, n, irq)) != 0)
- goto fail3;
+ if ((rc = efx_mcdi_init_evq(enp, index, esmp, n, irq, us)) != 0)
+ goto fail4;
return (0);
+fail4:
+ EFSYS_PROBE(fail4);
fail3:
EFSYS_PROBE(fail3);
fail2:
diff --git a/sys/dev/sfxge/common/ef10_impl.h b/sys/dev/sfxge/common/ef10_impl.h
index 3b850d2..68329c0 100644
--- a/sys/dev/sfxge/common/ef10_impl.h
+++ b/sys/dev/sfxge/common/ef10_impl.h
@@ -84,6 +84,7 @@ ef10_ev_qcreate(
__in efsys_mem_t *esmp,
__in size_t n,
__in uint32_t id,
+ __in uint32_t us,
__in efx_evq_t *eep);
void
diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h
index 32a3dfa..366dc13 100644
--- a/sys/dev/sfxge/common/efx.h
+++ b/sys/dev/sfxge/common/efx.h
@@ -1602,6 +1602,7 @@ efx_ev_qcreate(
__in efsys_mem_t *esmp,
__in size_t n,
__in uint32_t id,
+ __in uint32_t us,
__deref_out efx_evq_t **eepp);
extern void
diff --git a/sys/dev/sfxge/common/efx_ev.c b/sys/dev/sfxge/common/efx_ev.c
index 5e3bc40..47fa9aa 100644
--- a/sys/dev/sfxge/common/efx_ev.c
+++ b/sys/dev/sfxge/common/efx_ev.c
@@ -70,6 +70,7 @@ siena_ev_qcreate(
__in efsys_mem_t *esmp,
__in size_t n,
__in uint32_t id,
+ __in uint32_t us,
__in efx_evq_t *eep);
static void
@@ -226,6 +227,7 @@ efx_ev_qcreate(
__in efsys_mem_t *esmp,
__in size_t n,
__in uint32_t id,
+ __in uint32_t us,
__deref_out efx_evq_t **eepp)
{
const efx_ev_ops_t *eevop = enp->en_eevop;
@@ -262,7 +264,7 @@ efx_ev_qcreate(
enp->en_ev_qcount++;
*eepp = eep;
- if ((rc = eevop->eevo_qcreate(enp, index, esmp, n, id, eep)) != 0)
+ if ((rc = eevop->eevo_qcreate(enp, index, esmp, n, id, us, eep)) != 0)
goto fail2;
return (0);
@@ -347,7 +349,6 @@ efx_ev_qprefetch(
__in efx_evq_t *eep,
__in unsigned int count)
{
- efx_nic_t *enp = eep->ee_enp;
unsigned int offset;
EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
@@ -1257,6 +1258,7 @@ siena_ev_qcreate(
__in efsys_mem_t *esmp,
__in size_t n,
__in uint32_t id,
+ __in uint32_t us,
__in efx_evq_t *eep)
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
@@ -1312,6 +1314,9 @@ siena_ev_qcreate(
EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, index, &oword, B_TRUE);
+ /* Set initial interrupt moderation */
+ siena_ev_qmoderate(eep, us);
+
return (0);
fail4:
diff --git a/sys/dev/sfxge/common/efx_impl.h b/sys/dev/sfxge/common/efx_impl.h
index 43e9492..18812a5 100644
--- a/sys/dev/sfxge/common/efx_impl.h
+++ b/sys/dev/sfxge/common/efx_impl.h
@@ -95,7 +95,7 @@ typedef struct efx_ev_ops_s {
void (*eevo_fini)(efx_nic_t *);
efx_rc_t (*eevo_qcreate)(efx_nic_t *, unsigned int,
efsys_mem_t *, size_t, uint32_t,
- efx_evq_t *);
+ uint32_t, efx_evq_t *);
void (*eevo_qdestroy)(efx_evq_t *);
efx_rc_t (*eevo_qprime)(efx_evq_t *, unsigned int);
void (*eevo_qpost)(efx_evq_t *, uint16_t);
diff --git a/sys/dev/sfxge/common/efx_lic.c b/sys/dev/sfxge/common/efx_lic.c
index 127ead95..c1c05e2 100644
--- a/sys/dev/sfxge/common/efx_lic.c
+++ b/sys/dev/sfxge/common/efx_lic.c
@@ -506,7 +506,7 @@ efx_lic_v1v2_find_key(
_NOTE(ARGUNUSED(enp))
- if((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
+ if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
goto fail1;
tlv_type = __LE_TO_CPU_16(((uint16_t*)&bufferp[offset])[0]);
@@ -534,8 +534,6 @@ efx_lic_v1v2_validate_key(
__in uint32_t length
)
{
- const efx_lic_ops_t *elop = enp->en_elop;
- efx_rc_t rc;
uint16_t tlv_type;
uint16_t tlv_length;
@@ -548,7 +546,7 @@ efx_lic_v1v2_validate_key(
tlv_type = __LE_TO_CPU_16(((uint16_t*)keyp)[0]);
tlv_length = __LE_TO_CPU_16(((uint16_t*)keyp)[1]);
- if(tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
+ if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
goto fail2;
}
if (tlv_type == 0) {
@@ -658,7 +656,6 @@ efx_lic_v1v2_delete_key(
__out uint32_t *deltap
)
{
- efx_rc_t rc;
uint32_t move_start = offset + length;
uint32_t move_length = end - move_start;
@@ -1158,7 +1155,6 @@ efx_lic_v3_validate_key(
)
{
// Check key is a valid V3 key
- efx_rc_t rc;
uint8_t key_type;
uint8_t key_length;
@@ -1396,8 +1392,6 @@ efx_lic_check_support(
efx_lic_fini(
__in efx_nic_t *enp)
{
- const efx_lic_ops_t *elop = enp->en_elop;
-
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
@@ -1573,7 +1567,6 @@ efx_lic_find_key(
)
{
const efx_lic_ops_t *elop = enp->en_elop;
- boolean_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
@@ -1599,8 +1592,6 @@ efx_lic_validate_key(
{
const efx_lic_ops_t *elop = enp->en_elop;
boolean_t rc;
- uint16_t tlv_type;
- uint16_t tlv_length;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c
index e7e5f94..d50e7c7 100644
--- a/sys/dev/sfxge/common/efx_mcdi.c
+++ b/sys/dev/sfxge/common/efx_mcdi.c
@@ -795,7 +795,6 @@ efx_mcdi_get_proxy_handle(
__in efx_mcdi_req_t *emrp,
__out uint32_t *handlep)
{
- efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
efx_rc_t rc;
/*
diff --git a/sys/dev/sfxge/common/efx_regs_mcdi.h b/sys/dev/sfxge/common/efx_regs_mcdi.h
index c851aa3..a3d5a3e 100644
--- a/sys/dev/sfxge/common/efx_regs_mcdi.h
+++ b/sys/dev/sfxge/common/efx_regs_mcdi.h
@@ -5115,16 +5115,20 @@
#define MC_CMD_POLL_BIST_MEM_BUS_MC 0x0
/* enum: CSR IREG bus. */
#define MC_CMD_POLL_BIST_MEM_BUS_CSR 0x1
-/* enum: RX DPCPU bus. */
+/* enum: RX0 DPCPU bus. */
#define MC_CMD_POLL_BIST_MEM_BUS_DPCPU_RX 0x2
/* enum: TX0 DPCPU bus. */
#define MC_CMD_POLL_BIST_MEM_BUS_DPCPU_TX0 0x3
/* enum: TX1 DPCPU bus. */
#define MC_CMD_POLL_BIST_MEM_BUS_DPCPU_TX1 0x4
-/* enum: RX DICPU bus. */
+/* enum: RX0 DICPU bus. */
#define MC_CMD_POLL_BIST_MEM_BUS_DICPU_RX 0x5
/* enum: TX DICPU bus. */
#define MC_CMD_POLL_BIST_MEM_BUS_DICPU_TX 0x6
+/* enum: RX1 DPCPU bus. */
+#define MC_CMD_POLL_BIST_MEM_BUS_DPCPU_RX1 0x7
+/* enum: RX1 DICPU bus. */
+#define MC_CMD_POLL_BIST_MEM_BUS_DICPU_RX1 0x8
/* Pattern written to RAM / register */
#define MC_CMD_POLL_BIST_OUT_MEM_EXPECT_OFST 16
/* Actual value read from RAM / register */
@@ -6094,6 +6098,8 @@
#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_WIDTH 1
#define MC_CMD_NVRAM_INFO_OUT_TLV_LBN 1
#define MC_CMD_NVRAM_INFO_OUT_TLV_WIDTH 1
+#define MC_CMD_NVRAM_INFO_OUT_CMAC_LBN 6
+#define MC_CMD_NVRAM_INFO_OUT_CMAC_WIDTH 1
#define MC_CMD_NVRAM_INFO_OUT_A_B_LBN 7
#define MC_CMD_NVRAM_INFO_OUT_A_B_WIDTH 1
#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16
@@ -6887,6 +6893,8 @@
* the command will fail with MC_CMD_ERR_FILTERS_PRESENT.
*/
#define MC_CMD_WORKAROUND_BUG26807 0x6
+/* enum: Bug 61265 work around (broken EVQ TMR writes). */
+#define MC_CMD_WORKAROUND_BUG61265 0x7
/* 0 = disable the workaround indicated by TYPE; any non-zero value = enable
* the workaround
*/
@@ -7865,8 +7873,10 @@
#define NVRAM_PARTITION_TYPE_SPARE_1 0x1100
/* enum: Spare partition 2 */
#define NVRAM_PARTITION_TYPE_SPARE_2 0x1200
-/* enum: Spare partition 3 */
-#define NVRAM_PARTITION_TYPE_SPARE_3 0x1300
+/* enum: Manufacturing partition. Used during manufacture to pass information
+ * between XJTAG and Manftest.
+ */
+#define NVRAM_PARTITION_TYPE_MANUFACTURING 0x1300
/* enum: Spare partition 4 */
#define NVRAM_PARTITION_TYPE_SPARE_4 0x1400
/* enum: Spare partition 5 */
@@ -7901,6 +7911,8 @@
#define LICENSED_APP_ID_CAPTURE_SOLARSYSTEM 0x40
/* enum: Network Access Control */
#define LICENSED_APP_ID_NETWORK_ACCESS_CONTROL 0x80
+/* enum: TCP Direct */
+#define LICENSED_APP_ID_TCP_DIRECT 0x100
#define LICENSED_APP_ID_ID_LBN 0
#define LICENSED_APP_ID_ID_WIDTH 32
@@ -7957,6 +7969,12 @@
#define LICENSED_V3_APPS_CAPTURE_SOLARSYSTEM_WIDTH 1
#define LICENSED_V3_APPS_NETWORK_ACCESS_CONTROL_LBN 7
#define LICENSED_V3_APPS_NETWORK_ACCESS_CONTROL_WIDTH 1
+#define LICENSED_V3_APPS_TCP_DIRECT_LBN 8
+#define LICENSED_V3_APPS_TCP_DIRECT_WIDTH 1
+#define LICENSED_V3_APPS_LOW_LATENCY_LBN 9
+#define LICENSED_V3_APPS_LOW_LATENCY_WIDTH 1
+#define LICENSED_V3_APPS_SOLARCAPTURE_TAP_LBN 10
+#define LICENSED_V3_APPS_SOLARCAPTURE_TAP_WIDTH 1
#define LICENSED_V3_APPS_MASK_LBN 0
#define LICENSED_V3_APPS_MASK_WIDTH 64
@@ -7985,6 +8003,8 @@
#define LICENSED_V3_FEATURES_TX_SNIFF_WIDTH 1
#define LICENSED_V3_FEATURES_PROXY_FILTER_OPS_LBN 8
#define LICENSED_V3_FEATURES_PROXY_FILTER_OPS_WIDTH 1
+#define LICENSED_V3_FEATURES_EVENT_CUT_THROUGH_LBN 9
+#define LICENSED_V3_FEATURES_EVENT_CUT_THROUGH_WIDTH 1
#define LICENSED_V3_FEATURES_MASK_LBN 0
#define LICENSED_V3_FEATURES_MASK_WIDTH 64
@@ -8142,6 +8162,109 @@
/* Only valid if INTRFLAG was true */
#define MC_CMD_INIT_EVQ_OUT_IRQ_OFST 0
+/* MC_CMD_INIT_EVQ_V2_IN msgrequest */
+#define MC_CMD_INIT_EVQ_V2_IN_LENMIN 44
+#define MC_CMD_INIT_EVQ_V2_IN_LENMAX 548
+#define MC_CMD_INIT_EVQ_V2_IN_LEN(num) (36+8*(num))
+/* Size, in entries */
+#define MC_CMD_INIT_EVQ_V2_IN_SIZE_OFST 0
+/* Desired instance. Must be set to a specific instance, which is a function
+ * local queue index.
+ */
+#define MC_CMD_INIT_EVQ_V2_IN_INSTANCE_OFST 4
+/* The initial timer value. The load value is ignored if the timer mode is DIS.
+ */
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_LOAD_OFST 8
+/* The reload value is ignored in one-shot modes */
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_RELOAD_OFST 12
+/* tbd */
+#define MC_CMD_INIT_EVQ_V2_IN_FLAGS_OFST 16
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_INTERRUPTING_LBN 0
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_INTERRUPTING_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_RPTR_DOS_LBN 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_RPTR_DOS_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_INT_ARMD_LBN 2
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_INT_ARMD_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_CUT_THRU_LBN 3
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_CUT_THRU_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_RX_MERGE_LBN 4
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_RX_MERGE_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TX_MERGE_LBN 5
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TX_MERGE_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_USE_TIMER_LBN 6
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_USE_TIMER_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LBN 7
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_WIDTH 4
+/* enum: All initialisation flags specified by host. */
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_MANUAL 0x0
+/* enum: MEDFORD only. Certain initialisation flags specified by host may be
+ * over-ridden by firmware based on licenses and firmware variant in order to
+ * provide the lowest latency achievable. See
+ * MC_CMD_INIT_EVQ_V2/MC_CMD_INIT_EVQ_V2_OUT/FLAGS for list of affected flags.
+ */
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LOW_LATENCY 0x1
+/* enum: MEDFORD only. Certain initialisation flags specified by host may be
+ * over-ridden by firmware based on licenses and firmware variant in order to
+ * provide the best throughput achievable. See
+ * MC_CMD_INIT_EVQ_V2/MC_CMD_INIT_EVQ_V2_OUT/FLAGS for list of affected flags.
+ */
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_THROUGHPUT 0x2
+/* enum: MEDFORD only. Certain initialisation flags may be over-ridden by
+ * firmware based on licenses and firmware variant. See
+ * MC_CMD_INIT_EVQ_V2/MC_CMD_INIT_EVQ_V2_OUT/FLAGS for list of affected flags.
+ */
+#define MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO 0x3
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_OFST 20
+/* enum: Disabled */
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS 0x0
+/* enum: Immediate */
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_IMMED_START 0x1
+/* enum: Triggered */
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_TRIG_START 0x2
+/* enum: Hold-off */
+#define MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF 0x3
+/* Target EVQ for wakeups if in wakeup mode. */
+#define MC_CMD_INIT_EVQ_V2_IN_TARGET_EVQ_OFST 24
+/* Target interrupt if in interrupting mode (note union with target EVQ). Use
+ * MC_CMD_RESOURCE_INSTANCE_ANY unless a specific one required for test
+ * purposes.
+ */
+#define MC_CMD_INIT_EVQ_V2_IN_IRQ_NUM_OFST 24
+/* Event Counter Mode. */
+#define MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_OFST 28
+/* enum: Disabled */
+#define MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS 0x0
+/* enum: Disabled */
+#define MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_RX 0x1
+/* enum: Disabled */
+#define MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_TX 0x2
+/* enum: Disabled */
+#define MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_RXTX 0x3
+/* Event queue packet count threshold. */
+#define MC_CMD_INIT_EVQ_V2_IN_COUNT_THRSHLD_OFST 32
+/* 64-bit address of 4k of 4k-aligned host memory buffer */
+#define MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_OFST 36
+#define MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_LEN 8
+#define MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_LO_OFST 36
+#define MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_HI_OFST 40
+#define MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_MINNUM 1
+#define MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_MAXNUM 64
+
+/* MC_CMD_INIT_EVQ_V2_OUT msgresponse */
+#define MC_CMD_INIT_EVQ_V2_OUT_LEN 8
+/* Only valid if INTRFLAG was true */
+#define MC_CMD_INIT_EVQ_V2_OUT_IRQ_OFST 0
+/* Actual configuration applied on the card */
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAGS_OFST 4
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_CUT_THRU_LBN 0
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_CUT_THRU_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_RX_MERGE_LBN 1
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_RX_MERGE_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_TX_MERGE_LBN 2
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_TX_MERGE_WIDTH 1
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_RXQ_FORCE_EV_MERGING_LBN 3
+#define MC_CMD_INIT_EVQ_V2_OUT_FLAG_RXQ_FORCE_EV_MERGING_WIDTH 1
+
/* QUEUE_CRC_MODE structuredef */
#define QUEUE_CRC_MODE_LEN 1
#define QUEUE_CRC_MODE_MODE_LBN 0
@@ -8206,8 +8329,8 @@
#define MC_CMD_INIT_RXQ_IN_FLAG_PREFIX_WIDTH 1
#define MC_CMD_INIT_RXQ_IN_FLAG_DISABLE_SCATTER_LBN 9
#define MC_CMD_INIT_RXQ_IN_FLAG_DISABLE_SCATTER_WIDTH 1
-#define MC_CMD_INIT_RXQ_IN_FLAG_FORCE_EV_MERGING_LBN 10
-#define MC_CMD_INIT_RXQ_IN_FLAG_FORCE_EV_MERGING_WIDTH 1
+#define MC_CMD_INIT_RXQ_IN_UNUSED_LBN 10
+#define MC_CMD_INIT_RXQ_IN_UNUSED_WIDTH 1
/* Owner ID to use if in buffer mode (zero if physical) */
#define MC_CMD_INIT_RXQ_IN_OWNER_ID_OFST 20
/* The port ID associated with the v-adaptor which should contain this DMAQ. */
@@ -10427,6 +10550,12 @@
#define MC_CMD_GET_CAPABILITIES_V2_OUT_EVENT_CUT_THROUGH_WIDTH 1
#define MC_CMD_GET_CAPABILITIES_V2_OUT_RX_CUT_THROUGH_LBN 4
#define MC_CMD_GET_CAPABILITIES_V2_OUT_RX_CUT_THROUGH_WIDTH 1
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_TX_VFIFO_ULL_MODE_LBN 5
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_TX_VFIFO_ULL_MODE_WIDTH 1
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_MAC_STATS_40G_TX_SIZE_BINS_LBN 6
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_MAC_STATS_40G_TX_SIZE_BINS_WIDTH 1
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_LBN 7
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_WIDTH 1
/* Number of FATSOv2 contexts per datapath supported by this NIC. Not present
* on older firmware (check the length).
*/
@@ -11600,7 +11729,7 @@
#define MC_CMD_DUMP_BUFTBL_ENTRIES_OUT_LENMIN 12
#define MC_CMD_DUMP_BUFTBL_ENTRIES_OUT_LENMAX 252
#define MC_CMD_DUMP_BUFTBL_ENTRIES_OUT_LEN(num) (0+12*(num))
-/* Raw buffer table entries, laid out as BUFTBL_ENTRY. */
+/* Raw buffer table entries, layed out as BUFTBL_ENTRY. */
#define MC_CMD_DUMP_BUFTBL_ENTRIES_OUT_ENTRY_OFST 0
#define MC_CMD_DUMP_BUFTBL_ENTRIES_OUT_ENTRY_LEN 12
#define MC_CMD_DUMP_BUFTBL_ENTRIES_OUT_ENTRY_MINNUM 1
@@ -13013,29 +13142,39 @@
#define MC_CMD_0xd4_PRIVILEGE_CTG SRIOV_CTG_GENERAL
/* MC_CMD_LICENSED_V3_VALIDATE_APP_IN msgrequest */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_LEN 72
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_LEN 62
+/* challenge for validation (384 bits) */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_LEN 48
/* application ID expressed as a single bit mask */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_OFST 48
#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_LEN 8
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_LO_OFST 0
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_HI_OFST 4
-/* challenge for validation */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_OFST 8
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_LEN 64
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_LO_OFST 48
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_HI_OFST 52
+/* MAC address of the calling client MC_CMD_ERR_EPERM is returned if the
+ * calling client is not allowed to use this MAC address.
+ */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_MACADDR_OFST 56
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_MACADDR_LEN 6
/* MC_CMD_LICENSED_V3_VALIDATE_APP_OUT msgresponse */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_LEN 72
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_LEN 104
+/* validation response to challenge in the form of ECDSA signature consisting
+ * of two 384-bit integers, r and s, in big-endian order. The signature signs a
+ * SHA-384 digest of a message constructed from the concatenation of the input
+ * message and the remaining fields of this output message, e.g. challenge[48
+ * bytes] ... expiry_time[4 bytes] ...
+ */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_LEN 96
/* application expiry time */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_TIME_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_TIME_OFST 96
/* application expiry units */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNITS_OFST 4
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNITS_OFST 100
/* enum: expiry units are accounting units */
#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNIT_ACC 0x0
/* enum: expiry units are calendar days */
#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNIT_DAYS 0x1
-/* validation response to challenge */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_OFST 8
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_LEN 64
/***********************************/
@@ -13066,6 +13205,71 @@
/***********************************/
+/* MC_CMD_LICENSING_V3_TEMPORARY
+ * Perform operations to support installation of a single temporary license in
+ * the adapter, in addition to those found in the licensing partition. See
+ * SF-116124-SW for an overview of how this could be used. The license is
+ * stored in MC persistent data and so will survive a MC reboot, but will be
+ * erased when the adapter is power cycled
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY 0xd6
+#undef MC_CMD_0xd6_PRIVILEGE_CTG
+
+#define MC_CMD_0xd6_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_LEN 4
+/* operation code */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_OP_OFST 0
+/* enum: install a new license, overwriting any existing temporary license.
+ * This is an asynchronous operation owing to the time taken to validate an
+ * ECDSA license
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_SET 0x0
+/* enum: clear the license immediately rather than waiting for the next power
+ * cycle
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_CLEAR 0x1
+/* enum: get the status of the asynchronous MC_CMD_LICENSING_V3_TEMPORARY_SET
+ * operation
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS 0x2
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN_SET msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_LEN 164
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_OP_OFST 0
+/* ECDSA license and signature */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_LICENSE_OFST 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_LICENSE_LEN 160
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN_CLEAR msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_CLEAR_LEN 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_CLEAR_OP_OFST 0
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN_STATUS msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_STATUS_LEN 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_STATUS_OP_OFST 0
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS msgresponse */
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LEN 12
+/* status code */
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_STATUS_OFST 0
+/* enum: finished validating and installing license */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS_OK 0x0
+/* enum: license validation and installation in progress */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS_IN_PROGRESS 0x1
+/* enum: licensing error. More specific error messages are not provided to
+ * avoid exposing details of the licensing system to the client
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS_ERROR 0x2
+/* bitmask of licensed features */
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_OFST 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_LEN 8
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_LO_OFST 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_HI_OFST 8
+
+
+/***********************************/
/* MC_CMD_SET_PORT_SNIFF_CONFIG
* Configure RX port sniffing for the physical port associated with the calling
* function. Only a privileged function may change the port sniffing
@@ -13414,6 +13618,8 @@
#define MC_CMD_GET_WORKAROUNDS_OUT_BUG42008 0x20
/* enum: Bug 26807 features present in firmware (multicast filter chaining) */
#define MC_CMD_GET_WORKAROUNDS_OUT_BUG26807 0x40
+/* enum: Bug 61265 work around (broken EVQ TMR writes). */
+#define MC_CMD_GET_WORKAROUNDS_OUT_BUG61265 0x80
/***********************************/
@@ -14342,19 +14548,15 @@
#define MC_CMD_0x118_PRIVILEGE_CTG SRIOV_CTG_ADMIN
/* MC_CMD_RX_BALANCING_IN msgrequest */
-#define MC_CMD_RX_BALANCING_IN_LEN 4
+#define MC_CMD_RX_BALANCING_IN_LEN 16
/* The RX port whose upconverter table will be modified */
#define MC_CMD_RX_BALANCING_IN_PORT_OFST 0
-#define MC_CMD_RX_BALANCING_IN_PORT_LEN 1
/* The VLAN priority associated to the table index and vFIFO */
-#define MC_CMD_RX_BALANCING_IN_PRIORITY_OFST 1
-#define MC_CMD_RX_BALANCING_IN_PRIORITY_LEN 1
+#define MC_CMD_RX_BALANCING_IN_PRIORITY_OFST 4
/* The resulting bit of SRC^DST for indexing the table */
-#define MC_CMD_RX_BALANCING_IN_SRC_DST_OFST 2
-#define MC_CMD_RX_BALANCING_IN_SRC_DST_LEN 1
+#define MC_CMD_RX_BALANCING_IN_SRC_DST_OFST 8
/* The RX engine to which the vFIFO in the table entry will point to */
-#define MC_CMD_RX_BALANCING_IN_ENG_OFST 3
-#define MC_CMD_RX_BALANCING_IN_ENG_LEN 1
+#define MC_CMD_RX_BALANCING_IN_ENG_OFST 12
/* MC_CMD_RX_BALANCING_OUT msgresponse */
#define MC_CMD_RX_BALANCING_OUT_LEN 0
@@ -14368,6 +14570,9 @@
* available to host software.
*/
#define MC_CMD_TSA_BIND 0x119
+#undef MC_CMD_0x119_PRIVILEGE_CTG
+
+#define MC_CMD_0x119_PRIVILEGE_CTG SRIOV_CTG_ADMIN
/* MC_CMD_TSA_BIND_IN msgrequest: Protocol operation code */
#define MC_CMD_TSA_BIND_IN_LEN 4
@@ -14431,9 +14636,11 @@
#define MC_CMD_TSA_BIND_IN_SET_KEY_DATKEY_MAXNUM 248
/* MC_CMD_TSA_BIND_IN_UNBIND msgrequest: Asks for the un-binding procedure */
-#define MC_CMD_TSA_BIND_IN_UNBIND_LEN 6
+#define MC_CMD_TSA_BIND_IN_UNBIND_LEN 10
+/* The operation requested. */
+#define MC_CMD_TSA_BIND_IN_UNBIND_OP_OFST 0
/* TSAN unique identifier for the network adapter */
-#define MC_CMD_TSA_BIND_IN_UNBIND_TSANID_OFST 0
+#define MC_CMD_TSA_BIND_IN_UNBIND_TSANID_OFST 4
#define MC_CMD_TSA_BIND_IN_UNBIND_TSANID_LEN 6
/* MC_CMD_TSA_BIND_OUT_GET_ID msgresponse */
@@ -14550,4 +14757,291 @@
#define MC_CMD_MANAGE_SECURITY_RULESET_CACHE_OUT_VERSION_MINNUM 1
#define MC_CMD_MANAGE_SECURITY_RULESET_CACHE_OUT_VERSION_MAXNUM 248
+
+/***********************************/
+/* MC_CMD_NVRAM_PRIVATE_APPEND
+ * Append a single TLV to the MC_USAGE_TLV partition. Returns MC_CMD_ERR_EEXIST
+ * if the tag is already present.
+ */
+#define MC_CMD_NVRAM_PRIVATE_APPEND 0x11c
+#undef MC_CMD_0x11c_PRIVILEGE_CTG
+
+#define MC_CMD_0x11c_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_NVRAM_PRIVATE_APPEND_IN msgrequest */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LENMIN 9
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LENMAX 252
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LEN(num) (8+1*(num))
+/* The tag to be appended */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_TAG_OFST 0
+/* The length of the data */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LENGTH_OFST 4
+/* The data to be contained in the TLV structure */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_OFST 8
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_LEN 1
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_MINNUM 1
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_MAXNUM 244
+
+/* MC_CMD_NVRAM_PRIVATE_APPEND_OUT msgresponse */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_XPM_VERIFY_CONTENTS
+ * Verify that the contents of the XPM memory is correct (Medford only). This
+ * is used during manufacture to check that the XPM memory has been programmed
+ * correctly at ATE.
+ */
+#define MC_CMD_XPM_VERIFY_CONTENTS 0x11b
+#undef MC_CMD_0x11b_PRIVILEGE_CTG
+
+#define MC_CMD_0x11b_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_XPM_VERIFY_CONTENTS_IN msgrequest */
+#define MC_CMD_XPM_VERIFY_CONTENTS_IN_LEN 4
+/* Data type to be checked */
+#define MC_CMD_XPM_VERIFY_CONTENTS_IN_DATA_TYPE_OFST 0
+
+/* MC_CMD_XPM_VERIFY_CONTENTS_OUT msgresponse */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_LENMIN 12
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_LENMAX 252
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_LEN(num) (12+1*(num))
+/* Number of sectors found (test builds only) */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_NUM_SECTORS_OFST 0
+/* Number of bytes found (test builds only) */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_NUM_BYTES_OFST 4
+/* Length of signature */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIG_LENGTH_OFST 8
+/* Signature */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_OFST 12
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_LEN 1
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_MINNUM 0
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_MAXNUM 240
+
+
+/***********************************/
+/* MC_CMD_SET_EVQ_TMR
+ * Update the timer load, timer reload and timer mode values for a given EVQ.
+ * The requested timer values (in TMR_LOAD_REQ_NS and TMR_RELOAD_REQ_NS) will
+ * be rounded up to the granularity supported by the hardware, then truncated
+ * to the range supported by the hardware. The resulting value after the
+ * rounding and truncation will be returned to the caller (in TMR_LOAD_ACT_NS
+ * and TMR_RELOAD_ACT_NS).
+ */
+#define MC_CMD_SET_EVQ_TMR 0x120
+#undef MC_CMD_0x120_PRIVILEGE_CTG
+
+#define MC_CMD_0x120_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_SET_EVQ_TMR_IN msgrequest */
+#define MC_CMD_SET_EVQ_TMR_IN_LEN 16
+/* Function-relative queue instance */
+#define MC_CMD_SET_EVQ_TMR_IN_INSTANCE_OFST 0
+/* Requested value for timer load (in nanoseconds) */
+#define MC_CMD_SET_EVQ_TMR_IN_TMR_LOAD_REQ_NS_OFST 4
+/* Requested value for timer reload (in nanoseconds) */
+#define MC_CMD_SET_EVQ_TMR_IN_TMR_RELOAD_REQ_NS_OFST 8
+/* Timer mode. Meanings as per EVQ_TMR_REG.TC_TIMER_VAL */
+#define MC_CMD_SET_EVQ_TMR_IN_TMR_MODE_OFST 12
+#define MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_DIS 0x0 /* enum */
+#define MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_IMMED_START 0x1 /* enum */
+#define MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_TRIG_START 0x2 /* enum */
+#define MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_INT_HLDOFF 0x3 /* enum */
+
+/* MC_CMD_SET_EVQ_TMR_OUT msgresponse */
+#define MC_CMD_SET_EVQ_TMR_OUT_LEN 8
+/* Actual value for timer load (in nanoseconds) */
+#define MC_CMD_SET_EVQ_TMR_OUT_TMR_LOAD_ACT_NS_OFST 0
+/* Actual value for timer reload (in nanoseconds) */
+#define MC_CMD_SET_EVQ_TMR_OUT_TMR_RELOAD_ACT_NS_OFST 4
+
+
+/***********************************/
+/* MC_CMD_GET_EVQ_TMR_PROPERTIES
+ * Query properties about the event queue timers.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES 0x122
+#undef MC_CMD_0x122_PRIVILEGE_CTG
+
+#define MC_CMD_0x122_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_GET_EVQ_TMR_PROPERTIES_IN msgrequest */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_IN_LEN 0
+
+/* MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT msgresponse */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_LEN 36
+/* Reserved for future use. */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_FLAGS_OFST 0
+/* For timers updated via writes to EVQ_TMR_REG, this is the time interval (in
+ * nanoseconds) for each increment of the timer load/reload count. The
+ * requested duration of a timer is this value multiplied by the timer
+ * load/reload count.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_TMR_REG_NS_PER_COUNT_OFST 4
+/* For timers updated via writes to EVQ_TMR_REG, this is the maximum value
+ * allowed for timer load/reload counts.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_TMR_REG_MAX_COUNT_OFST 8
+/* For timers updated via writes to EVQ_TMR_REG, timer load/reload counts not a
+ * multiple of this step size will be rounded in an implementation defined
+ * manner.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_TMR_REG_STEP_OFST 12
+/* Maximum timer duration (in nanoseconds) for timers updated via MCDI. Only
+ * meaningful if MC_CMD_SET_EVQ_TMR is implemented.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_MCDI_TMR_MAX_NS_OFST 16
+/* Timer durations requested via MCDI that are not a multiple of this step size
+ * will be rounded up. Only meaningful if MC_CMD_SET_EVQ_TMR is implemented.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_MCDI_TMR_STEP_NS_OFST 20
+/* For timers updated using the bug35388 workaround, this is the time interval
+ * (in nanoseconds) for each increment of the timer load/reload count. The
+ * requested duration of a timer is this value multiplied by the timer
+ * load/reload count. This field is only meaningful if the bug35388 workaround
+ * is enabled.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_BUG35388_TMR_NS_PER_COUNT_OFST 24
+/* For timers updated using the bug35388 workaround, this is the maximum value
+ * allowed for timer load/reload counts. This field is only meaningful if the
+ * bug35388 workaround is enabled.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_BUG35388_TMR_MAX_COUNT_OFST 28
+/* For timers updated using the bug35388 workaround, timer load/reload counts
+ * not a multiple of this step size will be rounded in an implementation
+ * defined manner. This field is only meaningful if the bug35388 workaround is
+ * enabled.
+ */
+#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_BUG35388_TMR_STEP_OFST 32
+
+
+/***********************************/
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP
+ * When we use the TX_vFIFO_ULL mode, we can allocate common pools using the
+ * non used switch buffers.
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP 0x11d
+#undef MC_CMD_0x11d_PRIVILEGE_CTG
+
+#define MC_CMD_0x11d_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP_IN msgrequest */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_LEN 20
+/* Desired instance. Must be set to a specific instance, which is a function
+ * local queue index.
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_INSTANCE_OFST 0
+/* Will the common pool be used as TX_vFIFO_ULL (1) */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_MODE_OFST 4
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_ENABLED 0x1 /* enum */
+/* enum: Using this interface without TX_vFIFO_ULL is not supported for now */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_DISABLED 0x0
+/* Number of buffers to reserve for the common pool */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_SIZE_OFST 8
+/* TX datapath to which the Common Pool is connected to. */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_INGRESS_OFST 12
+/* enum: Extracts information from function */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_USE_FUNCTION_VALUE -0x1
+/* Network port or RX Engine to which the common pool connects. */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_EGRESS_OFST 16
+/* enum: Extracts information from function */
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_USE_FUNCTION_VALUE -0x1 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT0 0x0 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT1 0x1 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT2 0x2 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT3 0x3 /* enum */
+/* enum: To enable Switch loopback with Rx engine 0 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_RX_ENGINE0 0x4
+/* enum: To enable Switch loopback with Rx engine 1 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_RX_ENGINE1 0x5
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP_OUT msgresponse */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_OUT_LEN 4
+/* ID of the common pool allocated */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_OUT_CP_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_ALLOCATE_TX_VFIFO_VFIFO
+ * When we use the TX_vFIFO_ULL mode, we can allocate vFIFOs using the
+ * previously allocated common pools.
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO 0x11e
+#undef MC_CMD_0x11e_PRIVILEGE_CTG
+
+#define MC_CMD_0x11e_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN msgrequest */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_LEN 20
+/* Common pool previously allocated to which the new vFIFO will be associated
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_CP_OFST 0
+/* Port or RX engine to associate the vFIFO egress */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_EGRESS_OFST 4
+/* enum: Extracts information from common pool */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_USE_CP_VALUE -0x1
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT0 0x0 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT1 0x1 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT2 0x2 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT3 0x3 /* enum */
+/* enum: To enable Switch loopback with Rx engine 0 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_RX_ENGINE0 0x4
+/* enum: To enable Switch loopback with Rx engine 1 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_RX_ENGINE1 0x5
+/* Minimum number of buffers that the pool must have */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_SIZE_OFST 8
+/* enum: Do not check the space available */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_NO_MINIMUM 0x0
+/* Will the vFIFO be used as TX_vFIFO_ULL */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_MODE_OFST 12
+/* Network priority of the vFIFO,if applicable */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PRIORITY_OFST 16
+/* enum: Search for the lowest unused priority */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_LOWEST_AVAILABLE -0x1
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT msgresponse */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT_LEN 8
+/* Short vFIFO ID */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT_VID_OFST 0
+/* Network priority of the vFIFO */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT_PRIORITY_OFST 4
+
+
+/***********************************/
+/* MC_CMD_TEARDOWN_TX_VFIFO_VF
+ * This interface clears the configuration of the given vFIFO and leaves it
+ * ready to be re-used.
+ */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF 0x11f
+#undef MC_CMD_0x11f_PRIVILEGE_CTG
+
+#define MC_CMD_0x11f_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_TEARDOWN_TX_VFIFO_VF_IN msgrequest */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF_IN_LEN 4
+/* Short vFIFO ID */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF_IN_VFIFO_OFST 0
+
+/* MC_CMD_TEARDOWN_TX_VFIFO_VF_OUT msgresponse */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_DEALLOCATE_TX_VFIFO_CP
+ * This interface clears the configuration of the given common pool and leaves
+ * it ready to be re-used.
+ */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP 0x121
+#undef MC_CMD_0x121_PRIVILEGE_CTG
+
+#define MC_CMD_0x121_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_DEALLOCATE_TX_VFIFO_CP_IN msgrequest */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP_IN_LEN 4
+/* Common pool ID given when pool allocated */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP_IN_POOL_ID_OFST 0
+
+/* MC_CMD_DEALLOCATE_TX_VFIFO_CP_OUT msgresponse */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP_OUT_LEN 0
+
#endif /* _SIENA_MC_DRIVER_PCOL_H */
diff --git a/sys/dev/sfxge/sfxge.h b/sys/dev/sfxge/sfxge.h
index 7d66315..456c150 100644
--- a/sys/dev/sfxge/sfxge.h
+++ b/sys/dev/sfxge/sfxge.h
@@ -113,6 +113,43 @@
#define SFXGE_ETHERTYPE_LOOPBACK 0x9000 /* Xerox loopback */
+
+#define SFXGE_MAGIC_RESERVED 0x8000
+
+#define SFXGE_MAGIC_DMAQ_LABEL_WIDTH 6
+#define SFXGE_MAGIC_DMAQ_LABEL_MASK \
+ ((1 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH) - 1)
+
+enum sfxge_sw_ev {
+ SFXGE_SW_EV_RX_QFLUSH_DONE = 1,
+ SFXGE_SW_EV_RX_QFLUSH_FAILED,
+ SFXGE_SW_EV_RX_QREFILL,
+ SFXGE_SW_EV_TX_QFLUSH_DONE,
+};
+
+#define SFXGE_SW_EV_MAGIC(_sw_ev) \
+ (SFXGE_MAGIC_RESERVED | ((_sw_ev) << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
+
+static inline uint16_t
+sfxge_sw_ev_mk_magic(enum sfxge_sw_ev sw_ev, unsigned int label)
+{
+ KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
+ ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
+ return SFXGE_SW_EV_MAGIC(sw_ev) | label;
+}
+
+static inline uint16_t
+sfxge_sw_ev_rxq_magic(enum sfxge_sw_ev sw_ev, struct sfxge_rxq *rxq)
+{
+ return sfxge_sw_ev_mk_magic(sw_ev, 0);
+}
+
+static inline uint16_t
+sfxge_sw_ev_txq_magic(enum sfxge_sw_ev sw_ev, struct sfxge_txq *txq)
+{
+ return sfxge_sw_ev_mk_magic(sw_ev, txq->type);
+}
+
enum sfxge_evq_state {
SFXGE_EVQ_UNINITIALIZED = 0,
SFXGE_EVQ_INITIALIZED,
diff --git a/sys/dev/sfxge/sfxge_ev.c b/sys/dev/sfxge/sfxge_ev.c
index a470d7b..d3617d8 100644
--- a/sys/dev/sfxge/sfxge_ev.c
+++ b/sys/dev/sfxge/sfxge_ev.c
@@ -207,7 +207,6 @@ sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
struct sfxge_softc *sc;
struct sfxge_rxq *rxq;
unsigned int index;
- unsigned int label;
uint16_t magic;
evq = (struct sfxge_evq *)arg;
@@ -226,11 +225,7 @@ sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
}
evq = sc->evq[index];
-
- label = 0;
- KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
- ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level"));
- magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label;
+ magic = sfxge_sw_ev_rxq_magic(SFXGE_SW_EV_RX_QFLUSH_DONE, rxq);
KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
("evq not started"));
@@ -246,7 +241,6 @@ sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
struct sfxge_softc *sc;
struct sfxge_rxq *rxq;
unsigned int index;
- unsigned int label;
uint16_t magic;
evq = (struct sfxge_evq *)arg;
@@ -260,11 +254,7 @@ sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
/* Resend a software event on the correct queue */
index = rxq->index;
evq = sc->evq[index];
-
- label = 0;
- KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
- ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
- magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label;
+ magic = sfxge_sw_ev_rxq_magic(SFXGE_SW_EV_RX_QFLUSH_FAILED, rxq);
KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
("evq not started"));
@@ -331,7 +321,6 @@ sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
struct sfxge_evq *evq;
struct sfxge_softc *sc;
struct sfxge_txq *txq;
- unsigned int label;
uint16_t magic;
evq = (struct sfxge_evq *)arg;
@@ -351,11 +340,7 @@ sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
/* Resend a software event on the correct queue */
evq = sc->evq[txq->evq_index];
-
- label = txq->type;
- KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
- ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
- magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label;
+ magic = sfxge_sw_ev_txq_magic(SFXGE_SW_EV_TX_QFLUSH_DONE, txq);
KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
("evq not started"));
@@ -380,19 +365,19 @@ sfxge_ev_software(void *arg, uint16_t magic)
magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
switch (magic) {
- case SFXGE_MAGIC_RX_QFLUSH_DONE:
+ case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_RX_QFLUSH_DONE):
sfxge_rx_qflush_done(sfxge_get_rxq_by_label(evq, label));
break;
- case SFXGE_MAGIC_RX_QFLUSH_FAILED:
+ case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_RX_QFLUSH_FAILED):
sfxge_rx_qflush_failed(sfxge_get_rxq_by_label(evq, label));
break;
- case SFXGE_MAGIC_RX_QREFILL:
+ case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_RX_QREFILL):
sfxge_rx_qrefill(sfxge_get_rxq_by_label(evq, label));
break;
- case SFXGE_MAGIC_TX_QFLUSH_DONE: {
+ case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_TX_QFLUSH_DONE): {
struct sfxge_txq *txq = sfxge_get_txq_by_label(evq, label);
KASSERT(txq != NULL, ("txq == NULL"));
@@ -719,14 +704,11 @@ sfxge_ev_qstart(struct sfxge_softc *sc, unsigned int index)
/* Create the common code event queue. */
if ((rc = efx_ev_qcreate(sc->enp, index, esmp, evq->entries,
- evq->buf_base_id, &evq->common)) != 0)
+ evq->buf_base_id, sc->ev_moderation, &evq->common)) != 0)
goto fail;
SFXGE_EVQ_LOCK(evq);
- /* Set the default moderation */
- (void)efx_ev_qmoderate(evq->common, sc->ev_moderation);
-
/* Prime the event queue for interrupts */
if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
goto fail2;
diff --git a/sys/dev/sfxge/sfxge_rx.c b/sys/dev/sfxge/sfxge_rx.c
index 24415a1..bfeeed1 100644
--- a/sys/dev/sfxge/sfxge_rx.c
+++ b/sys/dev/sfxge/sfxge_rx.c
@@ -180,8 +180,7 @@ sfxge_rx_post_refill(void *arg)
sc = rxq->sc;
index = rxq->index;
evq = sc->evq[index];
-
- magic = SFXGE_MAGIC_RX_QREFILL | index;
+ magic = sfxge_sw_ev_rxq_magic(SFXGE_SW_EV_RX_QREFILL, rxq);
/* This is guaranteed due to the start/stop order of rx and ev */
KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
diff --git a/sys/dev/sfxge/sfxge_rx.h b/sys/dev/sfxge/sfxge_rx.h
index 3ef6e7e..2196c4e 100644
--- a/sys/dev/sfxge/sfxge_rx.h
+++ b/sys/dev/sfxge/sfxge_rx.h
@@ -43,24 +43,6 @@
#define SFXGE_LRO 1
#endif
-#define SFXGE_MAGIC_RESERVED 0x8000
-
-#define SFXGE_MAGIC_DMAQ_LABEL_WIDTH 6
-#define SFXGE_MAGIC_DMAQ_LABEL_MASK \
- ((1 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH) - 1)
-
-#define SFXGE_MAGIC_RX_QFLUSH_DONE \
- (SFXGE_MAGIC_RESERVED | (1 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
-
-#define SFXGE_MAGIC_RX_QFLUSH_FAILED \
- (SFXGE_MAGIC_RESERVED | (2 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
-
-#define SFXGE_MAGIC_RX_QREFILL \
- (SFXGE_MAGIC_RESERVED | (3 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
-
-#define SFXGE_MAGIC_TX_QFLUSH_DONE \
- (SFXGE_MAGIC_RESERVED | (4 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
-
#define SFXGE_RX_SCALE_MAX EFX_MAXRSS
struct sfxge_rx_sw_desc {
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 6329f81..3de87ae 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -657,6 +657,7 @@ static const struct usb_config
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = UMIDI_TX_BUFFER,
+ .flags = {.no_pipe_ok = 1},
.callback = &umidi_bulk_write_callback,
},
@@ -665,7 +666,7 @@ static const struct usb_config
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = 4, /* bytes */
- .flags = {.short_xfer_ok = 1,.proxy_buffer = 1,},
+ .flags = {.short_xfer_ok = 1,.proxy_buffer = 1,.no_pipe_ok = 1},
.callback = &umidi_bulk_read_callback,
},
};
@@ -5754,7 +5755,16 @@ umidi_start_write(struct usb_fifo *fifo)
{
struct umidi_chan *chan = usb_fifo_softc(fifo);
- usbd_transfer_start(chan->xfer[UMIDI_TX_TRANSFER]);
+ if (chan->xfer[UMIDI_TX_TRANSFER] == NULL) {
+ uint8_t buf[1];
+ int actlen;
+ do {
+ /* dump data */
+ usb_fifo_get_data_linear(fifo, buf, 1, &actlen, 0);
+ } while (actlen > 0);
+ } else {
+ usbd_transfer_start(chan->xfer[UMIDI_TX_TRANSFER]);
+ }
}
static void
@@ -5872,6 +5882,11 @@ umidi_probe(device_t dev)
DPRINTF("error=%s\n", usbd_errstr(error));
goto detach;
}
+ if (chan->xfer[UMIDI_TX_TRANSFER] == NULL &&
+ chan->xfer[UMIDI_RX_TRANSFER] == NULL) {
+ DPRINTF("no BULK or INTERRUPT MIDI endpoint(s) found\n");
+ goto detach;
+ }
/*
* Some USB MIDI device makers couldn't resist using
@@ -5885,7 +5900,8 @@ umidi_probe(device_t dev)
* and 64-byte maximum packet sizes for full-speed bulk
* endpoints and 512 bytes for high-speed bulk endpoints."
*/
- if (usbd_xfer_maxp_was_clamped(chan->xfer[UMIDI_TX_TRANSFER]))
+ if (chan->xfer[UMIDI_TX_TRANSFER] != NULL &&
+ usbd_xfer_maxp_was_clamped(chan->xfer[UMIDI_TX_TRANSFER]))
chan->single_command = 1;
if (chan->single_command != 0)
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index 8e6fc60..44cb78f 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -138,6 +138,8 @@ typedef u_int32_t u32;
#define MEMORY_BARRIER() dmb()
#elif defined __aarch64__
#define MEMORY_BARRIER() dmb(sy)
+#elif defined __riscv__
+#define MEMORY_BARRIER() fence()
#else
#error "Not supported platform"
#endif
diff --git a/sys/dev/urtwn/if_urtwn.c b/sys/dev/urtwn/if_urtwn.c
index d6ed4d7..2107fe1 100644
--- a/sys/dev/urtwn/if_urtwn.c
+++ b/sys/dev/urtwn/if_urtwn.c
@@ -2627,10 +2627,11 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
if (ic->ic_promisc == 0) {
reg = urtwn_read_4(sc, R92C_RCR);
- if (vap->iv_opmode != IEEE80211_M_HOSTAP)
+ if (vap->iv_opmode != IEEE80211_M_HOSTAP) {
reg |= R92C_RCR_CBSSID_DATA;
- if (vap->iv_opmode != IEEE80211_M_IBSS)
- reg |= R92C_RCR_CBSSID_BCN;
+ if (vap->iv_opmode != IEEE80211_M_IBSS)
+ reg |= R92C_RCR_CBSSID_BCN;
+ }
urtwn_write_4(sc, R92C_RCR, reg);
}
@@ -2955,8 +2956,7 @@ urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni,
switch (ic->ic_protmode) {
case IEEE80211_PROT_CTSONLY:
txd->txdw4 |= htole32(
- R92C_TXDW4_CTS2SELF |
- R92C_TXDW4_HWRTSEN);
+ R92C_TXDW4_CTS2SELF);
break;
case IEEE80211_PROT_RTSCTS:
txd->txdw4 |= htole32(
@@ -3117,11 +3117,10 @@ urtwn_tx_raw(struct urtwn_softc *sc, struct ieee80211_node *ni,
params->ibp_try0));
}
if (params->ibp_flags & IEEE80211_BPF_RTS)
- txd->txdw4 |= htole32(R92C_TXDW4_RTSEN);
+ txd->txdw4 |= htole32(R92C_TXDW4_RTSEN | R92C_TXDW4_HWRTSEN);
if (params->ibp_flags & IEEE80211_BPF_CTS)
txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF);
if (txd->txdw4 & htole32(R92C_TXDW4_RTSEN | R92C_TXDW4_CTS2SELF)) {
- txd->txdw4 |= htole32(R92C_TXDW4_HWRTSEN);
txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE,
URTWN_RIDX_OFDM24));
}
@@ -4723,7 +4722,8 @@ urtwn_scan_start(struct ieee80211com *ic)
URTWN_LOCK(sc);
/* Receive beacons / probe responses from any BSSID. */
- if (ic->ic_opmode != IEEE80211_M_IBSS)
+ if (ic->ic_opmode != IEEE80211_M_IBSS &&
+ ic->ic_opmode != IEEE80211_M_HOSTAP)
urtwn_set_rx_bssid_all(sc, 1);
/* Set gain for scanning. */
@@ -4738,7 +4738,9 @@ urtwn_scan_end(struct ieee80211com *ic)
URTWN_LOCK(sc);
/* Restore limitations. */
- if (ic->ic_promisc == 0 && ic->ic_opmode != IEEE80211_M_IBSS)
+ if (ic->ic_promisc == 0 &&
+ ic->ic_opmode != IEEE80211_M_IBSS &&
+ ic->ic_opmode != IEEE80211_M_HOSTAP)
urtwn_set_rx_bssid_all(sc, 0);
/* Set gain under link. */
@@ -4931,14 +4933,13 @@ urtwn_set_promisc(struct urtwn_softc *sc)
if (vap->iv_state == IEEE80211_S_RUN) {
switch (vap->iv_opmode) {
case IEEE80211_M_STA:
- mask2 |= R92C_RCR_CBSSID_DATA;
- /* FALLTHROUGH */
- case IEEE80211_M_HOSTAP:
mask2 |= R92C_RCR_CBSSID_BCN;
- break;
+ /* FALLTHROUGH */
case IEEE80211_M_IBSS:
mask2 |= R92C_RCR_CBSSID_DATA;
break;
+ case IEEE80211_M_HOSTAP:
+ break;
default:
device_printf(sc->sc_dev, "%s: undefined opmode %d\n",
__func__, vap->iv_opmode);
diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c
index 99b9c5f..c94e676 100644
--- a/sys/dev/usb/net/uhso.c
+++ b/sys/dev/usb/net/uhso.c
@@ -1225,6 +1225,7 @@ uhso_mux_write_callback(struct usb_xfer *xfer, usb_error_t error)
ht->ht_muxport);
/* FALLTHROUGH */
case USB_ST_SETUP:
+tr_setup:
pc = usbd_xfer_get_frame(xfer, 1);
if (ucom_get_data(&sc->sc_ucom[ht->ht_muxport], pc,
0, 32, &actlen)) {
@@ -1255,7 +1256,8 @@ uhso_mux_write_callback(struct usb_xfer *xfer, usb_error_t error)
UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
if (error == USB_ERR_CANCELLED)
break;
- break;
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
}
}
diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c
index 9d91281..1ab9f4a 100644
--- a/sys/dev/usb/wlan/if_urtw.c
+++ b/sys/dev/usb/wlan/if_urtw.c
@@ -1789,8 +1789,8 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
flags |= (urtw_rate2rtl(11) & 0xf) << URTW_TX_FLAG_RTSRATE_SHIFT;
tx->flag = htole32(flags);
tx->retry = 3; /* CW minimum */
- tx->retry = 7 << 4; /* CW maximum */
- tx->retry = URTW_TX_MAXRETRY << 8; /* retry limitation */
+ tx->retry |= 7 << 4; /* CW maximum */
+ tx->retry |= URTW_TX_MAXRETRY << 8; /* retry limitation */
m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(tx + 1));
}
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 356445c..d28f656 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -77,6 +77,8 @@ __FBSDID("$FreeBSD$");
#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
+#define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1)
+
/*
* Should the driver do LRO on the RX end
* this can be toggled on the fly, but the
@@ -114,13 +116,14 @@ struct netfront_rx_info;
static void xn_txeof(struct netfront_txq *);
static void xn_rxeof(struct netfront_rxq *);
static void xn_alloc_rx_buffers(struct netfront_rxq *);
+static void xn_alloc_rx_buffers_callout(void *arg);
static void xn_release_rx_bufs(struct netfront_rxq *);
static void xn_release_tx_bufs(struct netfront_txq *);
-static void xn_rxq_intr(void *);
-static void xn_txq_intr(void *);
-static int xn_intr(void *);
+static void xn_rxq_intr(struct netfront_rxq *);
+static void xn_txq_intr(struct netfront_txq *);
+static void xn_intr(void *);
static inline int xn_count_frags(struct mbuf *m);
static int xn_assemble_tx_request(struct netfront_txq *, struct mbuf *);
static int xn_ioctl(struct ifnet *, u_long, caddr_t);
@@ -182,15 +185,10 @@ struct netfront_rxq {
grant_ref_t grant_ref[NET_TX_RING_SIZE + 1];
struct mbuf *mbufs[NET_RX_RING_SIZE + 1];
- struct mbufq batch; /* batch queue */
- int target;
-
- xen_pfn_t pfn_array[NET_RX_RING_SIZE];
struct lro_ctrl lro;
- struct taskqueue *tq;
- struct task intrtask;
+ struct callout rx_refill;
struct xn_rx_stats stats;
};
@@ -213,7 +211,6 @@ struct netfront_txq {
struct buf_ring *br;
struct taskqueue *tq;
- struct task intrtask;
struct task defrtask;
bool full;
@@ -233,12 +230,6 @@ struct netfront_info {
u_int carrier;
u_int maxfrags;
- /* Receive-ring batched refills. */
-#define RX_MIN_TARGET 32
-#define RX_MAX_TARGET NET_RX_RING_SIZE
- int rx_min_target;
- int rx_max_target;
-
device_t xbdev;
uint8_t mac[ETHER_ADDR_LEN];
@@ -246,7 +237,7 @@ struct netfront_info {
struct ifmedia sc_media;
- bool xn_resume;
+ bool xn_reset;
};
struct netfront_rx_info {
@@ -467,7 +458,6 @@ netfront_resume(device_t dev)
{
struct netfront_info *info = device_get_softc(dev);
- info->xn_resume = true;
netif_disconnect_backend(info);
return (0);
}
@@ -599,10 +589,19 @@ talk_to_backend(device_t dev, struct netfront_info *info)
message = "writing feature-sg";
goto abort_transaction;
}
- err = xs_printf(xst, node, "feature-gso-tcpv4", "%d", 1);
- if (err != 0) {
- message = "writing feature-gso-tcpv4";
- goto abort_transaction;
+ if ((info->xn_ifp->if_capenable & IFCAP_LRO) != 0) {
+ err = xs_printf(xst, node, "feature-gso-tcpv4", "%d", 1);
+ if (err != 0) {
+ message = "writing feature-gso-tcpv4";
+ goto abort_transaction;
+ }
+ }
+ if ((info->xn_ifp->if_capenable & IFCAP_RXCSUM) == 0) {
+ err = xs_printf(xst, node, "feature-no-csum-offload", "%d", 1);
+ if (err != 0) {
+ message = "writing feature-no-csum-offload";
+ goto abort_transaction;
+ }
}
err = xs_transaction_end(xst, 0);
@@ -626,9 +625,8 @@ talk_to_backend(device_t dev, struct netfront_info *info)
}
static void
-xn_rxq_tq_intr(void *xrxq, int pending)
+xn_rxq_intr(struct netfront_rxq *rxq)
{
- struct netfront_rxq *rxq = xrxq;
XN_RX_LOCK(rxq);
xn_rxeof(rxq);
@@ -647,9 +645,8 @@ xn_txq_start(struct netfront_txq *txq)
}
static void
-xn_txq_tq_intr(void *xtxq, int pending)
+xn_txq_intr(struct netfront_txq *txq)
{
- struct netfront_txq *txq = xtxq;
XN_TX_LOCK(txq);
if (RING_HAS_UNCONSUMED_RESPONSES(&txq->ring))
@@ -674,7 +671,7 @@ disconnect_rxq(struct netfront_rxq *rxq)
xn_release_rx_bufs(rxq);
gnttab_free_grant_references(rxq->gref_head);
- gnttab_end_foreign_access_ref(rxq->ring_ref);
+ gnttab_end_foreign_access(rxq->ring_ref, NULL);
/*
* No split event channel support at the moment, handle will
* be unbound in tx. So no need to call xen_intr_unbind here,
@@ -687,9 +684,8 @@ static void
destroy_rxq(struct netfront_rxq *rxq)
{
+ callout_drain(&rxq->rx_refill);
free(rxq->ring.sring, M_DEVBUF);
- taskqueue_drain_all(rxq->tq);
- taskqueue_free(rxq->tq);
}
static void
@@ -721,7 +717,6 @@ setup_rxqs(device_t dev, struct netfront_info *info,
rxq->id = q;
rxq->info = info;
- rxq->target = RX_MIN_TARGET;
rxq->ring_ref = GRANT_REF_INVALID;
rxq->ring.sring = NULL;
snprintf(rxq->name, XN_QUEUE_NAME_LEN, "xnrx_%u", q);
@@ -733,11 +728,9 @@ setup_rxqs(device_t dev, struct netfront_info *info,
rxq->grant_ref[i] = GRANT_REF_INVALID;
}
- mbufq_init(&rxq->batch, INT_MAX);
-
/* Start resources allocation */
- if (gnttab_alloc_grant_references(RX_MAX_TARGET,
+ if (gnttab_alloc_grant_references(NET_RX_RING_SIZE,
&rxq->gref_head) != 0) {
device_printf(dev, "allocating rx gref");
error = ENOMEM;
@@ -756,25 +749,11 @@ setup_rxqs(device_t dev, struct netfront_info *info,
goto fail_grant_ring;
}
- TASK_INIT(&rxq->intrtask, 0, xn_rxq_tq_intr, rxq);
- rxq->tq = taskqueue_create_fast(rxq->name, M_WAITOK,
- taskqueue_thread_enqueue, &rxq->tq);
-
- error = taskqueue_start_threads(&rxq->tq, 1, PI_NET,
- "%s rxq %d", device_get_nameunit(dev), rxq->id);
- if (error != 0) {
- device_printf(dev, "failed to start rx taskq %d\n",
- rxq->id);
- goto fail_start_thread;
- }
+ callout_init(&rxq->rx_refill, 1);
}
return (0);
-fail_start_thread:
- gnttab_end_foreign_access_ref(rxq->ring_ref);
- taskqueue_drain_all(rxq->tq);
- taskqueue_free(rxq->tq);
fail_grant_ring:
gnttab_free_grant_references(rxq->gref_head);
free(rxq->ring.sring, M_DEVBUF);
@@ -794,7 +773,7 @@ disconnect_txq(struct netfront_txq *txq)
xn_release_tx_bufs(txq);
gnttab_free_grant_references(txq->gref_head);
- gnttab_end_foreign_access_ref(txq->ring_ref);
+ gnttab_end_foreign_access(txq->ring_ref, NULL);
xen_intr_unbind(&txq->xen_intr_handle);
}
@@ -876,9 +855,8 @@ setup_txqs(device_t dev, struct netfront_info *info,
txq->br = buf_ring_alloc(NET_TX_RING_SIZE, M_DEVBUF,
M_WAITOK, &txq->lock);
TASK_INIT(&txq->defrtask, 0, xn_txq_tq_deferred, txq);
- TASK_INIT(&txq->intrtask, 0, xn_txq_tq_intr, txq);
- txq->tq = taskqueue_create_fast(txq->name, M_WAITOK,
+ txq->tq = taskqueue_create(txq->name, M_WAITOK,
taskqueue_thread_enqueue, &txq->tq);
error = taskqueue_start_threads(&txq->tq, 1, PI_NET,
@@ -890,10 +868,9 @@ setup_txqs(device_t dev, struct netfront_info *info,
}
error = xen_intr_alloc_and_bind_local_port(dev,
- xenbus_get_otherend_id(dev), xn_intr, /* handler */ NULL,
- &info->txq[q],
- INTR_TYPE_NET | INTR_MPSAFE | INTR_ENTROPY,
- &txq->xen_intr_handle);
+ xenbus_get_otherend_id(dev), /* filter */ NULL, xn_intr,
+ &info->txq[q], INTR_TYPE_NET | INTR_MPSAFE | INTR_ENTROPY,
+ &txq->xen_intr_handle);
if (error != 0) {
device_printf(dev, "xen_intr_alloc_and_bind_local_port failed\n");
@@ -908,7 +885,7 @@ fail_bind_port:
fail_start_thread:
buf_ring_free(txq->br, M_DEVBUF);
taskqueue_free(txq->tq);
- gnttab_end_foreign_access_ref(txq->ring_ref);
+ gnttab_end_foreign_access(txq->ring_ref, NULL);
fail_grant_ring:
gnttab_free_grant_references(txq->gref_head);
free(txq->ring.sring, M_DEVBUF);
@@ -991,7 +968,6 @@ netfront_backend_changed(device_t dev, XenbusState newstate)
case XenbusStateInitialising:
case XenbusStateInitialised:
case XenbusStateUnknown:
- case XenbusStateClosed:
case XenbusStateReconfigured:
case XenbusStateReconfiguring:
break;
@@ -1005,6 +981,13 @@ netfront_backend_changed(device_t dev, XenbusState newstate)
case XenbusStateClosing:
xenbus_set_state(dev, XenbusStateClosed);
break;
+ case XenbusStateClosed:
+ if (sc->xn_reset) {
+ netif_disconnect_backend(sc);
+ xenbus_set_state(dev, XenbusStateInitialising);
+ sc->xn_reset = false;
+ }
+ break;
case XenbusStateConnected:
#ifdef INET
netfront_send_fake_arp(dev, sc);
@@ -1058,119 +1041,88 @@ xn_release_tx_bufs(struct netfront_txq *txq)
}
}
-static void
-xn_alloc_rx_buffers(struct netfront_rxq *rxq)
+static struct mbuf *
+xn_alloc_one_rx_buffer(struct netfront_rxq *rxq)
{
- struct netfront_info *np = rxq->info;
- int otherend_id = xenbus_get_otherend_id(np->xbdev);
- unsigned short id;
- struct mbuf *m_new;
- int i, batch_target, notify;
- RING_IDX req_prod;
- grant_ref_t ref;
- netif_rx_request_t *req;
- vm_offset_t vaddr;
- u_long pfn;
+ struct mbuf *m;
- req_prod = rxq->ring.req_prod_pvt;
+ m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+ if (m == NULL)
+ return NULL;
+ m->m_len = m->m_pkthdr.len = MJUMPAGESIZE;
- if (__predict_false(np->carrier == 0))
- return;
+ return (m);
+}
- /*
- * Allocate mbufs greedily, even though we batch updates to the
- * receive ring. This creates a less bursty demand on the memory
- * allocator, and so should reduce the chance of failed allocation
- * requests both for ourself and for other kernel subsystems.
- *
- * Here we attempt to maintain rx_target buffers in flight, counting
- * buffers that we have yet to process in the receive ring.
- */
- batch_target = rxq->target - (req_prod - rxq->ring.rsp_cons);
- for (i = mbufq_len(&rxq->batch); i < batch_target; i++) {
- m_new = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
- if (m_new == NULL) {
- if (i != 0)
- goto refill;
- /* XXX set timer */
- break;
- }
- m_new->m_len = m_new->m_pkthdr.len = MJUMPAGESIZE;
+static void
+xn_alloc_rx_buffers(struct netfront_rxq *rxq)
+{
+ RING_IDX req_prod;
+ int notify;
- /* queue the mbufs allocated */
- mbufq_enqueue(&rxq->batch, m_new);
- }
+ XN_RX_LOCK_ASSERT(rxq);
- /*
- * If we've allocated at least half of our target number of entries,
- * submit them to the backend - we have enough to make the overhead
- * of submission worthwhile. Otherwise wait for more mbufs and
- * request entries to become available.
- */
- if (i < (rxq->target/2)) {
- if (req_prod > rxq->ring.sring->req_prod)
- goto push;
+ if (__predict_false(rxq->info->carrier == 0))
return;
- }
- /*
- * Double floating fill target if we risked having the backend
- * run out of empty buffers for receive traffic. We define "running
- * low" as having less than a fourth of our target buffers free
- * at the time we refilled the queue.
- */
- if ((req_prod - rxq->ring.sring->rsp_prod) < (rxq->target / 4)) {
- rxq->target *= 2;
- if (rxq->target > np->rx_max_target)
- rxq->target = np->rx_max_target;
- }
+ for (req_prod = rxq->ring.req_prod_pvt;
+ req_prod - rxq->ring.rsp_cons < NET_RX_RING_SIZE;
+ req_prod++) {
+ struct mbuf *m;
+ unsigned short id;
+ grant_ref_t ref;
+ struct netif_rx_request *req;
+ unsigned long pfn;
-refill:
- for (i = 0; ; i++) {
- if ((m_new = mbufq_dequeue(&rxq->batch)) == NULL)
+ m = xn_alloc_one_rx_buffer(rxq);
+ if (m == NULL)
break;
- m_new->m_ext.ext_arg1 = (vm_paddr_t *)(uintptr_t)(
- vtophys(m_new->m_ext.ext_buf) >> PAGE_SHIFT);
-
- id = xn_rxidx(req_prod + i);
+ id = xn_rxidx(req_prod);
KASSERT(rxq->mbufs[id] == NULL, ("non-NULL xn_rx_chain"));
- rxq->mbufs[id] = m_new;
+ rxq->mbufs[id] = m;
ref = gnttab_claim_grant_reference(&rxq->gref_head);
KASSERT(ref != GNTTAB_LIST_END,
- ("reserved grant references exhuasted"));
+ ("reserved grant references exhuasted"));
rxq->grant_ref[id] = ref;
- vaddr = mtod(m_new, vm_offset_t);
- pfn = vtophys(vaddr) >> PAGE_SHIFT;
- req = RING_GET_REQUEST(&rxq->ring, req_prod + i);
+ pfn = atop(vtophys(mtod(m, vm_offset_t)));
+ req = RING_GET_REQUEST(&rxq->ring, req_prod);
- gnttab_grant_foreign_access_ref(ref, otherend_id, pfn, 0);
+ gnttab_grant_foreign_access_ref(ref,
+ xenbus_get_otherend_id(rxq->info->xbdev), pfn, 0);
req->id = id;
req->gref = ref;
+ }
+
+ rxq->ring.req_prod_pvt = req_prod;
- rxq->pfn_array[i] =
- vtophys(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT;
+ /* Not enough requests? Try again later. */
+ if (req_prod - rxq->ring.rsp_cons < NET_RX_SLOTS_MIN) {
+ callout_reset_curcpu(&rxq->rx_refill, hz/10,
+ xn_alloc_rx_buffers_callout, rxq);
+ return;
}
- KASSERT(i, ("no mbufs processed")); /* should have returned earlier */
- KASSERT(mbufq_len(&rxq->batch) == 0, ("not all mbufs processed"));
- /*
- * We may have allocated buffers which have entries outstanding
- * in the page * update queue -- make sure we flush those first!
- */
- wmb();
+ wmb(); /* barrier so backend seens requests */
- /* Above is a suitable barrier to ensure backend will see requests. */
- rxq->ring.req_prod_pvt = req_prod + i;
-push:
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&rxq->ring, notify);
if (notify)
xen_intr_signal(rxq->xen_intr_handle);
}
+static void xn_alloc_rx_buffers_callout(void *arg)
+{
+ struct netfront_rxq *rxq;
+
+ rxq = (struct netfront_rxq *)arg;
+ XN_RX_LOCK(rxq);
+ xn_alloc_rx_buffers(rxq);
+ XN_RX_UNLOCK(rxq);
+}
+
static void
xn_release_rx_bufs(struct netfront_rxq *rxq)
{
@@ -1253,6 +1205,13 @@ xn_rxeof(struct netfront_rxq *rxq)
| CSUM_PSEUDO_HDR);
m->m_pkthdr.csum_data = 0xffff;
}
+ if ((rx->flags & NETRXF_extra_info) != 0 &&
+ (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type ==
+ XEN_NETIF_EXTRA_TYPE_GSO)) {
+ m->m_pkthdr.tso_segsz =
+ extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].u.gso.size;
+ m->m_pkthdr.csum_flags |= CSUM_TSO;
+ }
rxq->stats.rx_packets++;
rxq->stats.rx_bytes += m->m_pkthdr.len;
@@ -1385,28 +1344,11 @@ xn_txeof(struct netfront_txq *txq)
if (txq->full &&
((txq->ring.sring->req_prod - prod) < NET_TX_RING_SIZE)) {
txq->full = false;
- taskqueue_enqueue(txq->tq, &txq->intrtask);
+ xn_txq_start(txq);
}
}
-
static void
-xn_rxq_intr(void *xrxq)
-{
- struct netfront_rxq *rxq = xrxq;
-
- taskqueue_enqueue(rxq->tq, &rxq->intrtask);
-}
-
-static void
-xn_txq_intr(void *xtxq)
-{
- struct netfront_txq *txq = xtxq;
-
- taskqueue_enqueue(txq->tq, &txq->intrtask);
-}
-
-static int
xn_intr(void *xsc)
{
struct netfront_txq *txq = xsc;
@@ -1416,8 +1358,6 @@ xn_intr(void *xsc)
/* kick both tx and rx */
xn_rxq_intr(rxq);
xn_txq_intr(txq);
-
- return (FILTER_HANDLED);
}
static void
@@ -1778,15 +1718,19 @@ xn_ifinit_locked(struct netfront_info *np)
ifp = np->xn_ifp;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING || !netfront_carrier_ok(np))
return;
xn_stop(np);
for (i = 0; i < np->num_queues; i++) {
rxq = &np->rxq[i];
+ XN_RX_LOCK(rxq);
xn_alloc_rx_buffers(rxq);
rxq->ring.sring->rsp_event = rxq->ring.rsp_cons + 1;
+ if (RING_HAS_UNCONSUMED_RESPONSES(&rxq->ring))
+ xn_rxeof(rxq);
+ XN_RX_UNLOCK(rxq);
}
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -1809,11 +1753,14 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct netfront_info *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
+ device_t dev;
#ifdef INET
struct ifaddr *ifa = (struct ifaddr *)data;
#endif
-
int mask, error = 0;
+
+ dev = sc->xbdev;
+
switch(cmd) {
case SIOCSIFADDR:
#ifdef INET
@@ -1890,6 +1837,31 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifp->if_capenable ^= IFCAP_LRO;
}
+ /*
+ * We must reset the interface so the backend picks up the
+ * new features.
+ */
+ XN_LOCK(sc);
+ netfront_carrier_off(sc);
+ sc->xn_reset = true;
+ /*
+ * NB: the pending packet queue is not flushed, since
+ * the interface should still support the old options.
+ */
+ XN_UNLOCK(sc);
+ /*
+ * Delete the xenstore nodes that export features.
+ *
+ * NB: There's a xenbus state called
+ * "XenbusStateReconfiguring", which is what we should set
+ * here. Sadly none of the backends know how to handle it,
+ * and simply disconnect from the frontend, so we will just
+ * switch back to XenbusStateInitialising in order to force
+ * a reconnection.
+ */
+ xs_rm(XST_NIL, xenbus_get_node(dev), "feature-gso-tcpv4");
+ xs_rm(XST_NIL, xenbus_get_node(dev), "feature-no-csum-offload");
+ xenbus_set_state(dev, XenbusStateClosing);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
@@ -2002,7 +1974,9 @@ xn_connect(struct netfront_info *np)
XN_TX_LOCK(txq);
xn_txeof(txq);
XN_TX_UNLOCK(txq);
+ XN_RX_LOCK(rxq);
xn_alloc_rx_buffers(rxq);
+ XN_RX_UNLOCK(rxq);
}
return (0);
@@ -2035,6 +2009,20 @@ xn_query_features(struct netfront_info *np)
printf(" feature-gso-tcp4");
}
+ /*
+ * HW CSUM offload is assumed to be available unless
+ * feature-no-csum-offload is set in xenstore.
+ */
+ if (xs_scanf(XST_NIL, xenbus_get_otherend_path(np->xbdev),
+ "feature-no-csum-offload", NULL, "%d", &val) != 0)
+ val = 0;
+
+ np->xn_ifp->if_capabilities |= IFCAP_HWCSUM;
+ if (val) {
+ np->xn_ifp->if_capabilities &= ~(IFCAP_HWCSUM);
+ printf(" feature-no-csum-offload");
+ }
+
printf("\n");
}
@@ -2045,50 +2033,50 @@ xn_configure_features(struct netfront_info *np)
#if (defined(INET) || defined(INET6))
int i;
#endif
+ struct ifnet *ifp;
+ ifp = np->xn_ifp;
err = 0;
- if (np->xn_resume &&
- ((np->xn_ifp->if_capenable & np->xn_ifp->if_capabilities)
- == np->xn_ifp->if_capenable)) {
+ if ((ifp->if_capenable & ifp->if_capabilities) == ifp->if_capenable) {
/* Current options are available, no need to do anything. */
return (0);
}
/* Try to preserve as many options as possible. */
- if (np->xn_resume)
- cap_enabled = np->xn_ifp->if_capenable;
- else
- cap_enabled = UINT_MAX;
+ cap_enabled = ifp->if_capenable;
+ ifp->if_capenable = ifp->if_hwassist = 0;
#if (defined(INET) || defined(INET6))
- for (i = 0; i < np->num_queues; i++)
- if ((np->xn_ifp->if_capenable & IFCAP_LRO) ==
- (cap_enabled & IFCAP_LRO))
+ if ((cap_enabled & IFCAP_LRO) != 0)
+ for (i = 0; i < np->num_queues; i++)
tcp_lro_free(&np->rxq[i].lro);
-#endif
- np->xn_ifp->if_capenable =
- np->xn_ifp->if_capabilities & ~(IFCAP_LRO|IFCAP_TSO4) & cap_enabled;
- np->xn_ifp->if_hwassist &= ~CSUM_TSO;
-#if (defined(INET) || defined(INET6))
- for (i = 0; i < np->num_queues; i++) {
- if (xn_enable_lro && (np->xn_ifp->if_capabilities & IFCAP_LRO) ==
- (cap_enabled & IFCAP_LRO)) {
+ if (xn_enable_lro &&
+ (ifp->if_capabilities & cap_enabled & IFCAP_LRO) != 0) {
+ ifp->if_capenable |= IFCAP_LRO;
+ for (i = 0; i < np->num_queues; i++) {
err = tcp_lro_init(&np->rxq[i].lro);
if (err != 0) {
- device_printf(np->xbdev, "LRO initialization failed\n");
- } else {
- np->rxq[i].lro.ifp = np->xn_ifp;
- np->xn_ifp->if_capenable |= IFCAP_LRO;
+ device_printf(np->xbdev,
+ "LRO initialization failed\n");
+ ifp->if_capenable &= ~IFCAP_LRO;
+ break;
}
+ np->rxq[i].lro.ifp = ifp;
}
}
- if ((np->xn_ifp->if_capabilities & IFCAP_TSO4) ==
- (cap_enabled & IFCAP_TSO4)) {
- np->xn_ifp->if_capenable |= IFCAP_TSO4;
- np->xn_ifp->if_hwassist |= CSUM_TSO;
+ if ((ifp->if_capabilities & cap_enabled & IFCAP_TSO4) != 0) {
+ ifp->if_capenable |= IFCAP_TSO4;
+ ifp->if_hwassist |= CSUM_TSO;
}
#endif
+ if ((ifp->if_capabilities & cap_enabled & IFCAP_TXCSUM) != 0) {
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ ifp->if_hwassist |= CSUM_TCP|CSUM_UDP;
+ }
+ if ((ifp->if_capabilities & cap_enabled & IFCAP_RXCSUM) != 0)
+ ifp->if_capenable |= IFCAP_RXCSUM;
+
return (err);
}
@@ -2156,6 +2144,8 @@ xn_txq_mq_start(struct ifnet *ifp, struct mbuf *m)
np = ifp->if_softc;
npairs = np->num_queues;
+ KASSERT(npairs != 0, ("called with 0 available queues"));
+
/* check if flowid is set */
if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
i = m->m_pkthdr.flowid % npairs;
@@ -2218,9 +2208,6 @@ create_netdev(device_t dev)
ifmedia_add(&np->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
ifmedia_set(&np->sc_media, IFM_ETHER|IFM_MANUAL);
- np->rx_min_target = RX_MIN_TARGET;
- np->rx_max_target = RX_MAX_TARGET;
-
err = xen_net_read_mac(dev, np->mac);
if (err != 0)
goto error;
@@ -2238,7 +2225,9 @@ create_netdev(device_t dev)
ifp->if_init = xn_ifinit;
ifp->if_hwassist = XN_CSUM_FEATURES;
- ifp->if_capabilities = IFCAP_HWCSUM;
+ /* Enable all supported features at device creation. */
+ ifp->if_capenable = ifp->if_capabilities =
+ IFCAP_HWCSUM|IFCAP_TSO4|IFCAP_LRO;
ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
ifp->if_hw_tsomaxsegcount = MAX_TX_REQ_FRAGS;
ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
@@ -2273,9 +2262,9 @@ netif_free(struct netfront_info *np)
xn_stop(np);
XN_UNLOCK(np);
netif_disconnect_backend(np);
+ ether_ifdetach(np->xn_ifp);
free(np->rxq, M_DEVBUF);
free(np->txq, M_DEVBUF);
- ether_ifdetach(np->xn_ifp);
if_free(np->xn_ifp);
np->xn_ifp = NULL;
ifmedia_removeall(&np->sc_media);
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 379f615..d4f03e8 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -2989,7 +2989,8 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how)
sx_assert(&sc->sc_lock, SX_XLOCKED);
pp = sc->sc_provider;
- if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
+ if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0 ||
+ SCHEDULER_STOPPED())) {
switch (how) {
case G_MIRROR_DESTROY_SOFT:
G_MIRROR_DEBUG(1,
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index a361fda..35e270a 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -4276,7 +4276,7 @@ SYSCTL_PROC(_security_jail, OID_AUTO, vnet,
#if defined(INET) || defined(INET6)
SYSCTL_UINT(_security_jail, OID_AUTO, jail_max_af_ips, CTLFLAG_RW,
&jail_max_af_ips, 0,
- "Number of IP addresses a jail may have at most per address family");
+ "Number of IP addresses a jail may have at most per address family (deprecated)");
#endif
/*
@@ -4316,59 +4316,59 @@ sysctl_jail_default_allow(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_security_jail, OID_AUTO, set_hostname_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_SET_HOSTNAME, sysctl_jail_default_allow, "I",
- "Processes in jail can set their hostnames");
+ "Processes in jail can set their hostnames (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, socket_unixiproute_only,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
(void *)1, PR_ALLOW_SOCKET_AF, sysctl_jail_default_allow, "I",
- "Processes in jail are limited to creating UNIX/IP/route sockets only");
+ "Processes in jail are limited to creating UNIX/IP/route sockets only (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, sysvipc_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_SYSVIPC, sysctl_jail_default_allow, "I",
- "Processes in jail can use System V IPC primitives");
+ "Processes in jail can use System V IPC primitives (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, allow_raw_sockets,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_RAW_SOCKETS, sysctl_jail_default_allow, "I",
- "Prison root can create raw sockets");
+ "Prison root can create raw sockets (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, chflags_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_CHFLAGS, sysctl_jail_default_allow, "I",
- "Processes in jail can alter system file flags");
+ "Processes in jail can alter system file flags (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I",
- "Processes in jail can mount/unmount jail-friendly file systems");
+ "Processes in jail can mount/unmount jail-friendly file systems (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_devfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_DEVFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the devfs file system");
+ "Processes in jail can mount the devfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_fdescfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_FDESCFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the fdescfs file system");
+ "Processes in jail can mount the fdescfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_nullfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_NULLFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the nullfs file system");
+ "Processes in jail can mount the nullfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_procfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_PROCFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the procfs file system");
+ "Processes in jail can mount the procfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_linprocfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_LINPROCFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the linprocfs file system");
+ "Processes in jail can mount the linprocfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_linsysfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_LINSYSFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the linsysfs file system");
+ "Processes in jail can mount the linsysfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_tmpfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_TMPFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the tmpfs file system");
+ "Processes in jail can mount the tmpfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_zfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_ZFS, sysctl_jail_default_allow, "I",
- "Processes in jail can mount the zfs file system");
+ "Processes in jail can mount the zfs file system (deprecated)");
static int
sysctl_jail_default_level(SYSCTL_HANDLER_ARGS)
@@ -4389,13 +4389,13 @@ SYSCTL_PROC(_security_jail, OID_AUTO, enforce_statfs,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
&jail_default_enforce_statfs, offsetof(struct prison, pr_enforce_statfs),
sysctl_jail_default_level, "I",
- "Processes in jail cannot see all mounted file systems");
+ "Processes in jail cannot see all mounted file systems (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, devfs_ruleset,
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
&jail_default_devfs_rsnum, offsetof(struct prison, pr_devfs_rsnum),
sysctl_jail_default_level, "I",
- "Ruleset for the devfs filesystem in jail");
+ "Ruleset for the devfs filesystem in jail (deprecated)");
/*
* Nodes to describe jail parameters. Maximum length of string parameters
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index 34d7b34..1b10623 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -787,8 +787,10 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
break;
}
- while (!atomic_cmpset_acq_ptr(&lk->lk_lock, LK_UNLOCKED,
- tid)) {
+ for (;;) {
+ if (lk->lk_lock == LK_UNLOCKED &&
+ atomic_cmpset_acq_ptr(&lk->lk_lock, LK_UNLOCKED, tid))
+ break;
#ifdef HWPMC_HOOKS
PMC_SOFT_CALL( , , lock, failed);
#endif
@@ -1124,7 +1126,11 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
__func__, iwmesg, file, line);
}
- while (!atomic_cmpset_acq_ptr(&lk->lk_lock, LK_UNLOCKED, tid)) {
+ for (;;) {
+ if (lk->lk_lock == LK_UNLOCKED &&
+ atomic_cmpset_acq_ptr(&lk->lk_lock, LK_UNLOCKED, tid))
+ break;
+
#ifdef HWPMC_HOOKS
PMC_SOFT_CALL( , , lock, failed);
#endif
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
index 3f62d17..d167205 100644
--- a/sys/kern/kern_mutex.c
+++ b/sys/kern/kern_mutex.c
@@ -419,7 +419,9 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts,
all_time -= lockstat_nsecs(&m->lock_object);
#endif
- while (!_mtx_obtain_lock(m, tid)) {
+ for (;;) {
+ if (m->mtx_lock == MTX_UNOWNED && _mtx_obtain_lock(m, tid))
+ break;
#ifdef KDTRACE_HOOKS
spin_cnt++;
#endif
@@ -602,8 +604,9 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts,
#ifdef KDTRACE_HOOKS
spin_time -= lockstat_nsecs(&m->lock_object);
#endif
- while (!_mtx_obtain_lock(m, tid)) {
-
+ for (;;) {
+ if (m->mtx_lock == MTX_UNOWNED && _mtx_obtain_lock(m, tid))
+ break;
/* Give interrupts a chance while we spin. */
spinlock_exit();
while (m->mtx_lock != MTX_UNOWNED) {
@@ -675,7 +678,9 @@ retry:
m->lock_object.lo_name, file, line));
WITNESS_CHECKORDER(&m->lock_object,
opts | LOP_NEWORDER | LOP_EXCLUSIVE, file, line, NULL);
- while (!_mtx_obtain_lock(m, tid)) {
+ for (;;) {
+ if (m->mtx_lock == MTX_UNOWNED && _mtx_obtain_lock(m, tid))
+ break;
if (m->mtx_lock == tid) {
m->mtx_recurse++;
break;
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c
index 6541724..6a904d2 100644
--- a/sys/kern/kern_rwlock.c
+++ b/sys/kern/kern_rwlock.c
@@ -771,7 +771,9 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file,
all_time -= lockstat_nsecs(&rw->lock_object);
state = rw->rw_lock;
#endif
- while (!_rw_write_lock(rw, tid)) {
+ for (;;) {
+ if (rw->rw_lock == RW_UNLOCKED && _rw_write_lock(rw, tid))
+ break;
#ifdef KDTRACE_HOOKS
spin_cnt++;
#endif
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 7588d4c..db93e34 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -804,7 +804,7 @@ kproc_shutdown(void *arg, int howto)
return;
p = (struct proc *)arg;
- printf("Waiting (max %d seconds) for system process `%s' to stop...",
+ printf("Waiting (max %d seconds) for system process `%s' to stop... ",
kproc_shutdown_wait, p->p_comm);
error = kproc_suspend(p, kproc_shutdown_wait * hz);
@@ -824,7 +824,7 @@ kthread_shutdown(void *arg, int howto)
return;
td = (struct thread *)arg;
- printf("Waiting (max %d seconds) for system thread `%s' to stop...",
+ printf("Waiting (max %d seconds) for system thread `%s' to stop... ",
kproc_shutdown_wait, td->td_name);
error = kthread_suspend(td, kproc_shutdown_wait * hz);
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c
index 96e117b..2a81c04 100644
--- a/sys/kern/kern_sx.c
+++ b/sys/kern/kern_sx.c
@@ -544,7 +544,10 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
all_time -= lockstat_nsecs(&sx->lock_object);
state = sx->sx_lock;
#endif
- while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) {
+ for (;;) {
+ if (sx->sx_lock == SX_LOCK_UNLOCKED &&
+ atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid))
+ break;
#ifdef KDTRACE_HOOKS
spin_cnt++;
#endif
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
index 00cb46f..4be29f5 100644
--- a/sys/kern/subr_taskqueue.c
+++ b/sys/kern/subr_taskqueue.c
@@ -130,14 +130,16 @@ _taskqueue_create(const char *name, int mflags,
char *tq_name;
tq_name = malloc(TASKQUEUE_NAMELEN, M_TASKQUEUE, mflags | M_ZERO);
- if (!tq_name)
+ if (tq_name == NULL)
return (NULL);
- snprintf(tq_name, TASKQUEUE_NAMELEN, "%s", (name) ? name : "taskqueue");
-
queue = malloc(sizeof(struct taskqueue), M_TASKQUEUE, mflags | M_ZERO);
- if (!queue)
+ if (queue == NULL) {
+ free(tq_name, M_TASKQUEUE);
return (NULL);
+ }
+
+ snprintf(tq_name, TASKQUEUE_NAMELEN, "%s", (name) ? name : "taskqueue");
STAILQ_INIT(&queue->tq_queue);
TAILQ_INIT(&queue->tq_active);
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 211cfa1..a80b974 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -196,11 +196,7 @@ void
vnet_domain_uninit(void *arg)
{
struct domain *dp = arg;
- struct protosw *pr;
- for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
- if (pr->pr_destroy)
- (*pr->pr_destroy)();
if (dp->dom_destroy)
(*dp->dom_destroy)();
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index aa5322a..2767826 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2103,7 +2103,7 @@ sched_sync(void)
if (syncer_state != SYNCER_RUNNING &&
starttime != time_uptime) {
if (first_printf) {
- printf("\nSyncing disks, vnodes remaining...");
+ printf("\nSyncing disks, vnodes remaining... ");
first_printf = 0;
}
printf("%d ", net_worklist_len);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 11813fc..f2416e0 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -2068,6 +2068,7 @@ cvtstat(st, ost)
struct ostat *ost;
{
+ bzero(ost, sizeof(*ost));
ost->st_dev = st->st_dev;
ost->st_ino = st->st_ino;
ost->st_mode = st->st_mode;
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 67647a1..745d414 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -116,7 +116,7 @@ SUBDIR= \
fdc \
fdescfs \
${_fe} \
- ${_filemon} \
+ filemon \
firewire \
firmware \
fuse \
@@ -499,7 +499,7 @@ _txp= txp
.if ${MK_SOURCELESS_UCODE} != "no" && ${MACHINE_CPUARCH} != "arm" && \
${MACHINE_ARCH:C/mips(el)?/mips/} != "mips" && \
- ${MACHINE_ARCH} != "powerpc"
+ ${MACHINE_ARCH} != "powerpc" && ${MACHINE_CPUARCH} != "riscv"
_cxgbe= cxgbe
.endif
@@ -508,7 +508,8 @@ SUBDIR+= zfs
.endif
.if ${MACHINE_CPUARCH} != "aarch64" && ${MACHINE_CPUARCH} != "arm" && \
- ${MACHINE_CPUARCH} != "mips" && ${MACHINE_CPUARCH} != "powerpc"
+ ${MACHINE_CPUARCH} != "mips" && ${MACHINE_CPUARCH} != "powerpc" && \
+ ${MACHINE_CPUARCH} != "riscv"
_syscons= syscons
_vpo= vpo
.endif
@@ -548,7 +549,6 @@ _ep= ep
_et= et
_exca= exca
_fe= fe
-_filemon= filemon
.if ${MK_OFED} != "no" || defined(ALL_MODULES)
_ibcore= ibcore
.endif
diff --git a/sys/modules/ath/Makefile b/sys/modules/ath/Makefile
index d100532..332eb75 100644
--- a/sys/modules/ath/Makefile
+++ b/sys/modules/ath/Makefile
@@ -38,7 +38,7 @@ KMOD= if_ath
SRCS= if_ath.c if_ath_alq.c if_ath_debug.c if_ath_keycache.c if_ath_sysctl.c
SRCS+= if_ath_tx.c if_ath_tx_ht.c if_ath_led.c if_ath_rx.c if_ath_tdma.c
SRCS+= if_ath_beacon.c if_ath_rx_edma.c if_ath_tx_edma.c if_ath_spectral.c
-SRCS+= if_ath_btcoex.c if_ath_lna_div.c if_ath_ioctl.c if_ath_descdma.c
+SRCS+= if_ath_btcoex.c if_ath_btcoex_mci.c if_ath_lna_div.c if_ath_ioctl.c if_ath_descdma.c
# NB: v3 eeprom support used by both AR5211 and AR5212; just include it
SRCS+= ah_osdep.c ah.c ah_regdomain.c ah_eeprom_v3.c
SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h opt_wlan.h
diff --git a/sys/modules/crypto/Makefile b/sys/modules/crypto/Makefile
index b476571..35e533b 100644
--- a/sys/modules/crypto/Makefile
+++ b/sys/modules/crypto/Makefile
@@ -8,6 +8,7 @@
.PATH: ${.CURDIR}/../../crypto/rijndael
.PATH: ${.CURDIR}/../../crypto/sha2
.PATH: ${.CURDIR}/../../crypto/siphash
+.PATH: ${.CURDIR}/../../crypto/skein
KMOD = crypto
SRCS = crypto.c cryptodev_if.c
@@ -17,6 +18,13 @@ SRCS += skipjack.c bf_enc.c bf_ecb.c bf_skey.c
SRCS += camellia.c camellia-api.c
SRCS += des_ecb.c des_enc.c des_setkey.c
SRCS += sha1.c sha256c.c sha512c.c
+SRCS += skein.c skein_block.c
+.if exists(${MACHINE_ARCH}/skein_block_asm.s)
+.PATH: ${.CURDIR}/../../crypto/skein/${MACHINE_ARCH}
+SRCS += skein_block_asm.s
+CFLAGS += -DSKEIN_ASM -DSKEIN_USE_ASM=1792 # list of block functions to replace with assembly: 256+512+1024 = 1792
+ACFLAGS += -DELF -Wa,--noexecstack
+.endif
SRCS += siphash.c
SRCS += gmac.c gfmult.c
SRCS += opt_param.h cryptodev_if.h bus_if.h device_if.h
diff --git a/sys/modules/dummynet/Makefile b/sys/modules/dummynet/Makefile
index 4e9e2ea..877e01a 100644
--- a/sys/modules/dummynet/Makefile
+++ b/sys/modules/dummynet/Makefile
@@ -4,9 +4,9 @@
KMOD= dummynet
SRCS= ip_dummynet.c
SRCS+= ip_dn_glue.c ip_dn_io.c
-SRCS+= dn_aqm_codel.c
+SRCS+= dn_aqm_codel.c dn_aqm_pie.c
SRCS+= dn_heap.c dn_sched_fifo.c dn_sched_qfq.c dn_sched_rr.c dn_sched_wf2q.c
-SRCS+= dn_sched_prio.c dn_sched_fq_codel.c
+SRCS+= dn_sched_prio.c dn_sched_fq_codel.c dn_sched_fq_pie.c
SRCS+= opt_inet6.h
.include <bsd.kmod.mk>
diff --git a/sys/modules/gpio/Makefile b/sys/modules/gpio/Makefile
index 7256669..709b468 100644
--- a/sys/modules/gpio/Makefile
+++ b/sys/modules/gpio/Makefile
@@ -28,7 +28,7 @@
SUBDIR = gpiobus gpioiic gpioled gpiospi
.if !empty(OPT_FDT)
-SUBDIR += gpiopps
+SUBDIR += gpiokeys gpiopps
.endif
.include <bsd.subdir.mk>
diff --git a/sys/modules/hyperv/vmbus/Makefile b/sys/modules/hyperv/vmbus/Makefile
index cfbd2cf..d4c7d8b 100644
--- a/sys/modules/hyperv/vmbus/Makefile
+++ b/sys/modules/hyperv/vmbus/Makefile
@@ -7,21 +7,20 @@ KMOD= hv_vmbus
SRCS= hv_channel.c \
hv_channel_mgmt.c \
hv_connection.c \
- hv_et.c \
- hv_hv.c \
hv_ring_buffer.c \
- hv_vmbus_drv_freebsd.c \
- hv_vmbus_priv.h \
- hyperv_busdma.c
+ hyperv.c \
+ hyperv_busdma.c \
+ vmbus.c \
+ vmbus_et.c
SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h
# XXX: for assym.s
SRCS+= opt_kstack_pages.h opt_nfs.h opt_apic.h opt_hwpmc_hooks.h opt_compat.h
SRCS+= assym.s \
- hv_vector.S
+ vmbus_vector.S
-hv_vector.o:
+vmbus_vector.o:
${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
${.IMPSRC} -o ${.TARGET}
diff --git a/sys/modules/iwm/Makefile b/sys/modules/iwm/Makefile
index f37c747..aa7fc62 100644
--- a/sys/modules/iwm/Makefile
+++ b/sys/modules/iwm/Makefile
@@ -6,7 +6,7 @@ KMOD= if_iwm
# Main driver
SRCS= if_iwm.c if_iwm_binding.c if_iwm_util.c if_iwm_phy_db.c
SRCS+= if_iwm_mac_ctxt.c if_iwm_phy_ctxt.c if_iwm_time_event.c
-SRCS+= if_iwm_power.c if_iwm_scan.c
+SRCS+= if_iwm_power.c if_iwm_scan.c if_iwm_led.c
# bus layer
SRCS+= if_iwm_pcie_trans.c
SRCS+= device_if.h bus_if.h pci_if.h opt_wlan.h
diff --git a/sys/modules/zfs/Makefile b/sys/modules/zfs/Makefile
index a824422..eb33a5c 100644
--- a/sys/modules/zfs/Makefile
+++ b/sys/modules/zfs/Makefile
@@ -70,6 +70,9 @@ SRCS+= zutil.c
.PATH: ${SYSDIR}/crypto/sha2
SRCS+= sha256c.c sha512c.c
+.PATH: ${SYSDIR}/crypto/skein
+SRCS+= skein.c skein_block.c
+
.PATH: ${SUNW}/common/zfs
.include "${SUNW}/uts/common/Makefile.files"
.PATH: ${SUNW}/uts/common/fs/zfs
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
index 895b233..35aff00 100644
--- a/sys/net/flowtable.c
+++ b/sys/net/flowtable.c
@@ -696,13 +696,8 @@ flowtable_lookup(sa_family_t sa, struct mbuf *m, struct route *ro)
ro->ro_rt = fle->f_rt;
ro->ro_flags |= RT_NORTREF;
lle = fle->f_lle;
- if (lle != NULL && (lle->la_flags & LLE_VALID)) {
- ro->ro_prepend = lle->r_linkdata;
- ro->ro_plen = lle->r_hdrlen;
- ro->ro_flags |= RT_MAY_LOOP;
- if (lle->la_flags & LLE_IFADDR)
- ro->ro_flags |= RT_L2_ME;
- }
+ if (lle != NULL && (lle->la_flags & LLE_VALID))
+ ro->ro_lle = lle; /* share ref with fle->f_lle */
return (0);
}
diff --git a/sys/net/if.c b/sys/net/if.c
index c989007..6845bbf 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -821,8 +821,7 @@ if_attachdomain1(struct ifnet *ifp)
* Since dp->dom_ifattach calls malloc() with M_WAITOK, we
* cannot lock ifp->if_afdata initialization, entirely.
*/
- if (IF_AFDATA_TRYLOCK(ifp) == 0)
- return;
+ IF_AFDATA_LOCK(ifp);
if (ifp->if_afdata_initialized >= domain_init_status) {
IF_AFDATA_UNLOCK(ifp);
log(LOG_WARNING, "%s called more than once on %s\n",
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c
index ff38b68..3bf372b 100644
--- a/sys/net/if_arcsubr.c
+++ b/sys/net/if_arcsubr.c
@@ -129,7 +129,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
else if (ifp->if_flags & IFF_NOARP)
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
else {
- error = arpresolve(ifp, is_gw, m, dst, &adst, NULL);
+ error = arpresolve(ifp, is_gw, m, dst, &adst, NULL,
+ NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -170,7 +171,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
if ((m->m_flags & M_MCAST) != 0)
adst = arcbroadcastaddr; /* ARCnet broadcast address */
else {
- error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL);
+ error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL,
+ NULL);
if (error != 0)
return (error == EWOULDBLOCK ? 0 : error);
}
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index e4b5ed9..420d4c2 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -201,7 +201,7 @@ ether_requestencap(struct ifnet *ifp, struct if_encap_req *req)
static int
ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, struct route *ro, u_char *phdr,
- uint32_t *pflags)
+ uint32_t *pflags, struct llentry **plle)
{
struct ether_header *eh;
uint32_t lleflags = 0;
@@ -210,13 +210,16 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
uint16_t etype;
#endif
+ if (plle)
+ *plle = NULL;
eh = (struct ether_header *)phdr;
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if ((m->m_flags & (M_BCAST | M_MCAST)) == 0)
- error = arpresolve(ifp, 0, m, dst, phdr, &lleflags);
+ error = arpresolve(ifp, 0, m, dst, phdr, &lleflags,
+ plle);
else {
if (m->m_flags & M_BCAST)
memcpy(eh->ether_dhost, ifp->if_broadcastaddr,
@@ -235,7 +238,8 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
#ifdef INET6
case AF_INET6:
if ((m->m_flags & M_MCAST) == 0)
- error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags);
+ error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags,
+ plle);
else {
const struct in6_addr *a6;
a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr);
@@ -285,14 +289,40 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
int loop_copy = 1;
int hlen; /* link layer header length */
uint32_t pflags;
+ struct llentry *lle = NULL;
+ struct rtentry *rt0 = NULL;
+ int addref = 0;
phdr = NULL;
pflags = 0;
if (ro != NULL) {
- phdr = ro->ro_prepend;
- hlen = ro->ro_plen;
- pflags = ro->ro_flags;
+ /* XXX BPF uses ro_prepend */
+ if (ro->ro_prepend != NULL) {
+ phdr = ro->ro_prepend;
+ hlen = ro->ro_plen;
+ } else if (!(m->m_flags & (M_BCAST | M_MCAST))) {
+ if ((ro->ro_flags & RT_LLE_CACHE) != 0) {
+ lle = ro->ro_lle;
+ if (lle != NULL &&
+ (lle->la_flags & LLE_VALID) == 0) {
+ LLE_FREE(lle);
+ lle = NULL; /* redundant */
+ ro->ro_lle = NULL;
+ }
+ if (lle == NULL) {
+ /* if we lookup, keep cache */
+ addref = 1;
+ }
+ }
+ if (lle != NULL) {
+ phdr = lle->r_linkdata;
+ hlen = lle->r_hdrlen;
+ pflags = lle->r_flags;
+ }
+ }
+ rt0 = ro->ro_rt;
}
+
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error)
@@ -310,7 +340,10 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
/* No prepend data supplied. Try to calculate ourselves. */
phdr = linkhdr;
hlen = ETHER_HDR_LEN;
- error = ether_resolve_addr(ifp, m, dst, ro, phdr, &pflags);
+ error = ether_resolve_addr(ifp, m, dst, ro, phdr, &pflags,
+ addref ? &lle : NULL);
+ if (addref && lle != NULL)
+ ro->ro_lle = lle;
if (error != 0)
return (error == EWOULDBLOCK ? 0 : error);
}
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index 1ebd4da..b02901f 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -126,7 +126,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
switch (dst->sa_family) {
#ifdef INET
case AF_INET: {
- error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
+ error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -162,7 +162,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
+ error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IPV6);
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
index c2253d4..57f4256 100644
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -144,7 +144,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
* doesn't fit into the arp model.
*/
if (unicast) {
- error = arpresolve(ifp, is_gw, m, dst, (u_char *) destfw, NULL);
+ error = arpresolve(ifp, is_gw, m, dst,
+ (u_char *) destfw, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -174,7 +175,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
case AF_INET6:
if (unicast) {
error = nd6_resolve(fc->fc_ifp, is_gw, m, dst,
- (u_char *) destfw, NULL);
+ (u_char *) destfw, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index a96e2b9..8306154 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -254,7 +254,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
+ error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IP;
@@ -289,7 +289,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
+ error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IPV6;
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index b6111c6..51de726 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -138,7 +138,6 @@ struct llentry {
LLE_FREE_LOCKED(lle); \
} while (0)
-
typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
typedef struct llentry *(llt_alloc_t)(struct lltable *, u_int flags,
diff --git a/sys/net/route.c b/sys/net/route.c
index 4b191d0..26e3b85 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -207,6 +207,8 @@ rt_tables_get_gen(int table, int fam)
struct rib_head *rnh;
rnh = *rt_tables_get_rnh_ptr(table, fam);
+ KASSERT(rnh != NULL, ("%s: NULL rib_head pointer table %d fam %d",
+ __func__, table, fam));
return (rnh->rnh_gen);
}
diff --git a/sys/net/route.h b/sys/net/route.h
index e0ff6b4..46e2ace 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -50,6 +50,11 @@
*/
struct route {
struct rtentry *ro_rt;
+ struct llentry *ro_lle;
+ /*
+ * ro_prepend and ro_plen are only used for bpf to pass in a
+ * preformed header. They are not cacheable.
+ */
char *ro_prepend;
uint16_t ro_plen;
uint16_t ro_flags;
@@ -71,6 +76,7 @@ struct route {
#define RT_REJECT 0x0020 /* Destination is reject */
#define RT_BLACKHOLE 0x0040 /* Destination is blackhole */
#define RT_HAS_GW 0x0080 /* Destination has GW */
+#define RT_LLE_CACHE 0x0100 /* Cache link layer */
struct rt_metrics {
u_long rmx_locks; /* Kernel must leave these values alone */
@@ -399,6 +405,7 @@ struct rt_addrinfo {
if ((_ro)->ro_flags & RT_NORTREF) { \
(_ro)->ro_flags &= ~RT_NORTREF; \
(_ro)->ro_rt = NULL; \
+ (_ro)->ro_lle = NULL; \
} else { \
RT_LOCK((_ro)->ro_rt); \
RTFREE_LOCKED((_ro)->ro_rt); \
@@ -413,9 +420,11 @@ struct rt_addrinfo {
*/
#define RT_VALIDATE(ro, cookiep, fibnum) do { \
rt_gen_t cookie = RT_GEN(fibnum, (ro)->ro_dst.sa_family); \
- if (*(cookiep) != cookie && (ro)->ro_rt != NULL) { \
- RTFREE((ro)->ro_rt); \
- (ro)->ro_rt = NULL; \
+ if (*(cookiep) != cookie) { \
+ if ((ro)->ro_rt != NULL) { \
+ RTFREE((ro)->ro_rt); \
+ (ro)->ro_rt = NULL; \
+ } \
*(cookiep) = cookie; \
} \
} while (0)
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 3836ee5..e367ba2 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -227,9 +227,16 @@ ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace)
lwh = mtod(mfrag, struct ieee80211_frame *);
last_rxseq = le16toh(*(uint16_t *)lwh->i_seq);
/* NB: check seq # and frag together */
- if (rxseq != last_rxseq+1 ||
- !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
- !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
+ if (rxseq == last_rxseq+1 &&
+ IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) &&
+ IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
+ /* XXX clear MORE_FRAG bit? */
+ /* track last seqnum and fragno */
+ *(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq;
+
+ m_adj(m, hdrspace); /* strip header */
+ m_catpkt(mfrag, m); /* concatenate */
+ } else {
/*
* Unrelated fragment or no space for it,
* clear current fragments.
@@ -247,12 +254,6 @@ ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace)
return NULL;
}
mfrag = m;
- } else { /* concatenate */
- m_adj(m, hdrspace); /* strip header */
- m_catpkt(mfrag, m);
- /* track last seqnum and fragno */
- lwh = mtod(mfrag, struct ieee80211_frame *);
- *(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq;
}
if (more_frag) { /* more to come, save */
ni->ni_rxfragstamp = ticks;
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index dfde06a..1f49237 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1679,16 +1679,8 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0,
remainder = m0->m_pkthdr.len - off;
prev = m0;
do {
- fragsize = totalhdrsize + remainder;
- if (fragsize > mtu)
- fragsize = mtu;
- /* XXX fragsize can be >2048! */
- KASSERT(fragsize < MCLBYTES,
- ("fragment size %u too big!", fragsize));
- if (fragsize > MHLEN)
- m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- else
- m = m_gethdr(M_NOWAIT, MT_DATA);
+ fragsize = MIN(totalhdrsize + remainder, mtu);
+ m = m_get2(fragsize, M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL)
goto bad;
/* leave room to prepend any cipher header */
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index eac3c1d..48fae92 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -420,7 +420,8 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
*/
static int
arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
- const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
+ const struct sockaddr *dst, u_char *desten, uint32_t *pflags,
+ struct llentry **plle)
{
struct llentry *la = NULL, *la_tmp;
struct mbuf *curr = NULL;
@@ -431,6 +432,8 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
if (pflags != NULL)
*pflags = 0;
+ if (plle != NULL)
+ *plle = NULL;
if ((flags & LLE_CREATE) == 0) {
IF_AFDATA_RLOCK(ifp);
@@ -483,6 +486,10 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
}
if (pflags != NULL)
*pflags = la->la_flags & (LLE_VALID|LLE_IFADDR);
+ if (plle) {
+ LLE_ADDREF(la);
+ *plle = la;
+ }
LLE_WUNLOCK(la);
return (0);
}
@@ -548,12 +555,12 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
*/
int
arpresolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
- char *desten, uint32_t *pflags)
+ char *desten, uint32_t *pflags, struct llentry **plle)
{
int error;
flags |= LLE_ADDRONLY;
- error = arpresolve_full(ifp, 0, flags, NULL, dst, desten, pflags);
+ error = arpresolve_full(ifp, 0, flags, NULL, dst, desten, pflags, plle);
return (error);
}
@@ -576,12 +583,15 @@ arpresolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
*/
int
arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
- const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
+ const struct sockaddr *dst, u_char *desten, uint32_t *pflags,
+ struct llentry **plle)
{
struct llentry *la = NULL;
if (pflags != NULL)
*pflags = 0;
+ if (plle != NULL)
+ *plle = NULL;
if (m != NULL) {
if (m->m_flags & M_BCAST) {
@@ -616,7 +626,7 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
IF_AFDATA_RUNLOCK(ifp);
return (arpresolve_full(ifp, is_gw, la == NULL ? LLE_CREATE : 0, m, dst,
- desten, pflags));
+ desten, pflags, plle));
}
/*
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 06ec210..27e51f7 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -113,11 +113,14 @@ extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN];
extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
struct ifaddr;
+struct llentry;
int arpresolve_addr(struct ifnet *ifp, int flags,
- const struct sockaddr *dst, char *desten, uint32_t *pflags);
+ const struct sockaddr *dst, char *desten, uint32_t *pflags,
+ struct llentry **plle);
int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
- const struct sockaddr *dst, u_char *desten, uint32_t *pflags);
+ const struct sockaddr *dst, u_char *desten, uint32_t *pflags,
+ struct llentry **plle);
void arprequest(struct ifnet *, const struct in_addr *,
const struct in_addr *, u_char *);
void arp_ifinit(struct ifnet *, struct ifaddr *);
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 50e5d6e..7d5da0e 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/route.h>
#include <net/rss_config.h>
#include <net/vnet.h>
@@ -1302,6 +1303,8 @@ in_pcbfree(struct inpcb *inp)
RTFREE(inp->inp_route.ro_rt);
inp->inp_route.ro_rt = (struct rtentry *)NULL;
}
+ if (inp->inp_route.ro_lle)
+ LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */
inp->inp_vflag = 0;
inp->inp_flags2 |= INP_FREED;
@@ -2243,6 +2246,8 @@ in_losing(struct inpcb *inp)
RTFREE(inp->inp_route.ro_rt);
inp->inp_route.ro_rt = (struct rtentry *)NULL;
}
+ if (inp->inp_route.ro_lle)
+ LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */
return;
}
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 1d32caf..7403ec0 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -119,9 +119,6 @@ struct protosw inetsw[] = {
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_IP,
.pr_init = ip_init,
-#ifdef VIMAGE
- .pr_destroy = ip_destroy,
-#endif
.pr_slowtimo = ip_slowtimo,
.pr_drain = ip_drain,
.pr_usrreqs = &nousrreqs
@@ -135,9 +132,6 @@ struct protosw inetsw[] = {
.pr_ctlinput = udp_ctlinput,
.pr_ctloutput = udp_ctloutput,
.pr_init = udp_init,
-#ifdef VIMAGE
- .pr_destroy = udp_destroy,
-#endif
.pr_usrreqs = &udp_usrreqs
},
{
@@ -149,9 +143,6 @@ struct protosw inetsw[] = {
.pr_ctlinput = tcp_ctlinput,
.pr_ctloutput = tcp_ctloutput,
.pr_init = tcp_init,
-#ifdef VIMAGE
- .pr_destroy = tcp_destroy,
-#endif
.pr_slowtimo = tcp_slowtimo,
.pr_drain = tcp_drain,
.pr_usrreqs = &tcp_usrreqs
@@ -166,9 +157,6 @@ struct protosw inetsw[] = {
.pr_ctlinput = sctp_ctlinput,
.pr_ctloutput = sctp_ctloutput,
.pr_init = sctp_init,
-#ifdef VIMAGE
- .pr_destroy = sctp_finish,
-#endif
.pr_drain = sctp_drain,
.pr_usrreqs = &sctp_usrreqs
},
@@ -176,7 +164,7 @@ struct protosw inetsw[] = {
.pr_type = SOCK_STREAM,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
+ .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD,
.pr_input = sctp_input,
.pr_ctlinput = sctp_ctlinput,
.pr_ctloutput = sctp_ctloutput,
@@ -193,9 +181,6 @@ struct protosw inetsw[] = {
.pr_ctlinput = udplite_ctlinput,
.pr_ctloutput = udp_ctloutput,
.pr_init = udplite_init,
-#ifdef VIMAGE
- .pr_destroy = udplite_destroy,
-#endif
.pr_usrreqs = &udp_usrreqs
},
{
@@ -343,9 +328,6 @@ IPPROTOSPACER,
.pr_input = rip_input,
.pr_ctloutput = rip_ctloutput,
.pr_init = rip_init,
-#ifdef VIMAGE
- .pr_destroy = rip_destroy,
-#endif
.pr_usrreqs = &rip_usrreqs
},
};
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index cab7fc1..14b8995 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -162,11 +162,13 @@ div_init(void)
}
static void
-div_destroy(void)
+div_destroy(void *unused __unused)
{
in_pcbinfo_destroy(&V_divcbinfo);
}
+VNET_SYSUNINIT(divert, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY,
+ div_destroy, NULL);
/*
* IPPROTO_DIVERT is not in the real IP protocol number space; this
@@ -753,9 +755,6 @@ struct protosw div_protosw = {
.pr_ctlinput = div_ctlinput,
.pr_ctloutput = ip_ctloutput,
.pr_init = div_init,
-#ifdef VIMAGE
- .pr_destroy = div_destroy,
-#endif
.pr_usrreqs = &div_usrreqs
};
@@ -787,10 +786,6 @@ div_modevent(module_t mod, int type, void *unused)
err = EPERM;
break;
case MOD_UNLOAD:
-#ifdef VIMAGE
- err = EPERM;
- break;
-#else
/*
* Forced unload.
*
@@ -811,10 +806,11 @@ div_modevent(module_t mod, int type, void *unused)
ip_divert_ptr = NULL;
err = pf_proto_unregister(PF_INET, IPPROTO_DIVERT, SOCK_RAW);
INP_INFO_WUNLOCK(&V_divcbinfo);
- div_destroy();
+#ifndef VIMAGE
+ div_destroy(NULL);
+#endif
EVENTHANDLER_DEREGISTER(maxsockets_change, ip_divert_event_tag);
break;
-#endif /* !VIMAGE */
default:
err = EOPNOTSUPP;
break;
@@ -828,5 +824,6 @@ static moduledata_t ipdivertmod = {
0
};
-DECLARE_MODULE(ipdivert, ipdivertmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+DECLARE_MODULE(ipdivert, ipdivertmod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY);
+MODULE_DEPEND(ipdivert, ipfw, 3, 3, 3);
MODULE_VERSION(ipdivert, 1);
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index ff1d2a1..386a2a1 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -364,8 +364,8 @@ ip_init(void)
}
#ifdef VIMAGE
-void
-ip_destroy(void)
+static void
+ip_destroy(void *unused __unused)
{
int error;
@@ -391,6 +391,8 @@ ip_destroy(void)
/* Destroy IP reassembly queue. */
ipreass_destroy();
}
+
+VNET_SYSUNINIT(ip, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip_destroy, NULL);
#endif
#ifdef RSS
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index cb358c6..9fdd59d 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -244,7 +244,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
if (ro == NULL) {
ro = &iproute;
bzero(ro, sizeof (*ro));
- }
+ } else
+ ro->ro_flags |= RT_LLE_CACHE;
#ifdef FLOWTABLE
if (ro->ro_rt == NULL)
@@ -310,6 +311,9 @@ again:
dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
RTFREE(rte);
rte = ro->ro_rt = (struct rtentry *)NULL;
+ if (ro->ro_lle)
+ LLE_FREE(ro->ro_lle); /* zeros ro_lle */
+ ro->ro_lle = (struct llentry *)NULL;
}
ia = NULL;
have_ia_ref = 0;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index f4ad4ff..847704f 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -209,9 +209,6 @@ int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
u_long if_hwassist_flags);
void ip_forward(struct mbuf *m, int srcrt);
void ip_init(void);
-#ifdef VIMAGE
-void ip_destroy(void);
-#endif
extern int
(*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
struct ip_moptions *);
@@ -229,9 +226,6 @@ void ip_fillid(struct ip *);
int rip_ctloutput(struct socket *, struct sockopt *);
void rip_ctlinput(int, struct sockaddr *, void *);
void rip_init(void);
-#ifdef VIMAGE
-void rip_destroy(void);
-#endif
int rip_input(struct mbuf **, int *, int);
int rip_output(struct mbuf *, struct socket *, ...);
int ipip_input(struct mbuf **, int *, int);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 59540a5..6d40954 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -218,12 +218,13 @@ rip_init(void)
}
#ifdef VIMAGE
-void
-rip_destroy(void)
+static void
+rip_destroy(void *unused __unused)
{
in_pcbinfo_destroy(&V_ripcbinfo);
}
+VNET_SYSUNINIT(raw_ip, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, rip_destroy, NULL);
#endif
#ifdef INET
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 85ec065..a43f871 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -5686,7 +5686,7 @@ do_a_abort:
{
stc.addr_type = SCTP_IPV6_ADDRESS;
memcpy(&stc.address, &src6->sin6_addr, sizeof(struct in6_addr));
- stc.scope_id = in6_getscope(&src6->sin6_addr);
+ stc.scope_id = ntohs(in6_getscope(&src6->sin6_addr));
if (sctp_is_address_on_local_host(src, vrf_id)) {
stc.loopback_scope = 1;
stc.local_scope = 0;
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 7b65d53..6e5cbe3 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -89,13 +89,14 @@ sctp_init(void)
#endif
}
-void
-sctp_finish(void)
+#ifdef VIMAGE
+static void
+sctp_finish(void *unused __unused)
{
sctp_pcb_finish();
}
-
-
+VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL);
+#endif
void
sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index 8b4f7db..a4d2b99 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -344,7 +344,6 @@ void sctp_init(void);
void
sctp_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *,
uint8_t, uint8_t, uint16_t, uint16_t);
-void sctp_finish(void);
int sctp_flush(struct socket *, int);
int sctp_shutdown(struct socket *);
int
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index fdd1cfb..e1d9488 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -130,6 +130,16 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
"Max size of automatic send buffer");
+/*
+ * Make sure that either retransmit or persist timer is set for SYN, FIN and
+ * non-ACK.
+ */
+#define TCP_XMIT_TIMER_ASSERT(tp, len, th_flags) \
+ KASSERT(((len) == 0 && ((th_flags) & (TH_SYN | TH_FIN)) == 0) ||\
+ tcp_timer_active((tp), TT_REXMT) || \
+ tcp_timer_active((tp), TT_PERSIST), \
+ ("neither rexmt nor persist timer is set"))
+
static void inline hhook_run_tcp_est_out(struct tcpcb *tp,
struct tcphdr *th, struct tcpopt *to,
long len, int tso);
@@ -1545,9 +1555,7 @@ timer:
tp->t_softerror = error;
return (error);
case ENOBUFS:
- if (!tcp_timer_active(tp, TT_REXMT) &&
- !tcp_timer_active(tp, TT_PERSIST))
- tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+ TCP_XMIT_TIMER_ASSERT(tp, len, flags);
tp->snd_cwnd = tp->t_maxseg;
return (0);
case EMSGSIZE:
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 75dd3d7..7863f1c 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -728,8 +728,8 @@ tcp_init(void)
}
#ifdef VIMAGE
-void
-tcp_destroy(void)
+static void
+tcp_destroy(void *unused __unused)
{
int error;
@@ -772,6 +772,7 @@ tcp_destroy(void)
HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, error);
}
}
+VNET_SYSUNINIT(tcp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, tcp_destroy, NULL);
#endif
void
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 2bbd5e3..abfa21a 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -755,9 +755,6 @@ struct tcpcb *
tcp_drop(struct tcpcb *, int);
void tcp_drain(void);
void tcp_init(void);
-#ifdef VIMAGE
-void tcp_destroy(void);
-#endif
void tcp_fini(void *);
char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
const void *);
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 4bca16c..3354b01 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -451,12 +451,12 @@ toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
- rc = arpresolve(ifp, 0, NULL, sa, lladdr, NULL);
+ rc = arpresolve(ifp, 0, NULL, sa, lladdr, NULL, NULL);
break;
#endif
#ifdef INET6
case AF_INET6:
- rc = nd6_resolve(ifp, 0, NULL, sa, lladdr, NULL);
+ rc = nd6_resolve(ifp, 0, NULL, sa, lladdr, NULL, NULL);
break;
#endif
default:
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 503f059..a1d9a43 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -269,20 +269,23 @@ udp_discardcb(struct udpcb *up)
}
#ifdef VIMAGE
-void
-udp_destroy(void)
+static void
+udp_destroy(void *unused __unused)
{
in_pcbinfo_destroy(&V_udbinfo);
uma_zdestroy(V_udpcb_zone);
}
+VNET_SYSUNINIT(udp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, udp_destroy, NULL);
-void
-udplite_destroy(void)
+static void
+udplite_destroy(void *unused __unused)
{
in_pcbinfo_destroy(&V_ulitecbinfo);
}
+VNET_SYSUNINIT(udplite, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, udplite_destroy,
+ NULL);
#endif
#ifdef INET
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 6d19dee..9564da2 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -171,10 +171,6 @@ void udplite_ctlinput(int, struct sockaddr *, void *);
int udp_ctloutput(struct socket *, struct sockopt *);
void udp_init(void);
void udplite_init(void);
-#ifdef VIMAGE
-void udp_destroy(void);
-void udplite_destroy(void);
-#endif
int udp_input(struct mbuf **, int *, int);
void udplite_input(struct mbuf *, int);
struct inpcb *udp_notify(struct inpcb *inp, int errno);
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index ae049f0..c84881e 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -375,6 +375,11 @@ extern const struct in6_addr in6addr_linklocal_allv2routers;
#if __BSD_VISIBLE
struct route_in6 {
struct rtentry *ro_rt;
+ struct llentry *ro_lle;
+ /*
+ * ro_prepend and ro_plen are only used for bpf to pass in a
+ * preformed header. They are not cacheable.
+ */
char *ro_prepend;
uint16_t ro_plen;
uint16_t ro_flags;
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 98f4cd3..ff8813b 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
@@ -831,6 +832,8 @@ in6_losing(struct inpcb *in6p)
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;
}
@@ -846,6 +849,8 @@ in6_rtchange(struct inpcb *inp, int errno)
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 */
return inp;
}
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index acc3fe2..cfb7628 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -153,9 +153,6 @@ struct protosw inet6sw[] = {
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_IPV6,
.pr_init = ip6_init,
-#ifdef VIMAGE
- .pr_destroy = ip6_destroy,
-#endif
.pr_slowtimo = frag6_slowtimo,
.pr_drain = frag6_drain,
.pr_usrreqs = &nousrreqs,
@@ -207,7 +204,7 @@ struct protosw inet6sw[] = {
.pr_type = SOCK_STREAM,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
+ .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD,
.pr_input = sctp6_input,
.pr_ctlinput = sctp6_ctlinput,
.pr_ctloutput = sctp_ctloutput,
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 5329621..dc6b8f3 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -309,8 +309,8 @@ ip6proto_unregister(short ip6proto)
}
#ifdef VIMAGE
-void
-ip6_destroy()
+static void
+ip6_destroy(void *unused __unused)
{
int error;
@@ -333,6 +333,8 @@ ip6_destroy()
nd6_destroy();
in6_ifattach_destroy();
}
+
+VNET_SYSUNINIT(inet6, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_destroy, NULL);
#endif
static int
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index e12aee4..fde6710 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -500,7 +500,8 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
if (ro == NULL) {
ro = &ip6route;
bzero((caddr_t)ro, sizeof(*ro));
- }
+ } else
+ ro->ro_flags |= RT_LLE_CACHE;
ro_pmtu = ro;
if (opt && opt->ip6po_rthdr)
ro = &opt->ip6po_route;
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 8a45f55..e52a320 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -354,9 +354,6 @@ int icmp6_ctloutput(struct socket *, struct sockopt *sopt);
struct in6_ifaddr;
void ip6_init(void);
-#ifdef VIMAGE
-void ip6_destroy(void);
-#endif
int ip6proto_register(short);
int ip6proto_unregister(short);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 6db94fd..0585cd7 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -136,7 +136,7 @@ static void nd6_llinfo_settimer_locked(struct llentry *, long);
static void clear_llinfo_pqueue(struct llentry *);
static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int nd6_resolve_slow(struct ifnet *, int, struct mbuf *,
- const struct sockaddr_in6 *, u_char *, uint32_t *);
+ const struct sockaddr_in6 *, u_char *, uint32_t *, struct llentry **);
static int nd6_need_cache(struct ifnet *);
@@ -2175,7 +2175,8 @@ nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
*/
int
nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
- const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags)
+ const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags,
+ struct llentry **plle)
{
struct llentry *ln = NULL;
const struct sockaddr_in6 *dst6;
@@ -2227,7 +2228,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
}
IF_AFDATA_RUNLOCK(ifp);
- return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags));
+ return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags, plle));
}
@@ -2244,7 +2245,8 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
*/
static __noinline int
nd6_resolve_slow(struct ifnet *ifp, int flags, struct mbuf *m,
- const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
+ const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags,
+ struct llentry **plle)
{
struct llentry *lle = NULL, *lle_tmp;
struct in6_addr *psrc, src;
@@ -2331,6 +2333,10 @@ nd6_resolve_slow(struct ifnet *ifp, int flags, struct mbuf *m,
bcopy(lladdr, desten, ll_len);
if (pflags != NULL)
*pflags = lle->la_flags;
+ if (plle) {
+ LLE_ADDREF(lle);
+ *plle = lle;
+ }
LLE_WUNLOCK(lle);
return (0);
}
@@ -2405,7 +2411,7 @@ nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
flags |= LLE_ADDRONLY;
error = nd6_resolve_slow(ifp, flags, NULL,
- (const struct sockaddr_in6 *)dst, desten, pflags);
+ (const struct sockaddr_in6 *)dst, desten, pflags, NULL);
return (error);
}
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 0978f0d..ce98975 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -428,7 +428,7 @@ void nd6_purge(struct ifnet *);
int nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
char *desten, uint32_t *pflags);
int nd6_resolve(struct ifnet *, int, struct mbuf *,
- const struct sockaddr *, u_char *, uint32_t *);
+ const struct sockaddr *, u_char *, uint32_t *, struct llentry **);
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
char *, int, int, int);
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index d621b52..2ac1d7a 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1216,7 +1216,6 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
struct dadq *dp;
char ip6buf[INET6_ADDRSTRLEN];
- int send_ns;
/*
* If we don't need DAD, don't do it.
@@ -1290,12 +1289,7 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
refcount_init(&dp->dad_refcnt, 1);
nd6_dad_add(dp);
- send_ns = 0;
- if (delay == 0) {
- send_ns = 1;
- delay = (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000;
- }
- nd6_dad_starttimer(dp, delay, send_ns);
+ nd6_dad_starttimer(dp, delay, 0);
}
/*
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 988bf2b..8f19406 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/errno.h>
+#include <sys/rmlock.h>
#include <sys/rwlock.h>
#include <sys/syslog.h>
#include <sys/queue.h>
@@ -1437,12 +1438,13 @@ find_pfxlist_reachable_router(struct nd_prefix *pr)
* is no router around us.
*/
void
-pfxlist_onlink_check()
+pfxlist_onlink_check(void)
{
struct nd_prefix *pr;
struct in6_ifaddr *ifa;
struct nd_defrouter *dr;
struct nd_pfxrouter *pfxrtr = NULL;
+ struct rm_priotracker in6_ifa_tracker;
/*
* Check if there is a prefix that has a reachable advertising
@@ -1573,9 +1575,8 @@ pfxlist_onlink_check()
* detached. Note, however, that a manually configured address should
* always be attached.
* The precise detection logic is same as the one for prefixes.
- *
- * XXXRW: in6_ifaddrhead locking.
*/
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
TAILQ_FOREACH(ifa, &V_in6_ifaddrhead, ia_link) {
if (!(ifa->ia6_flags & IN6_IFF_AUTOCONF))
continue;
@@ -1610,8 +1611,7 @@ pfxlist_onlink_check()
ifa->ia6_flags |= IN6_IFF_DETACHED;
}
}
- }
- else {
+ } else {
TAILQ_FOREACH(ifa, &V_in6_ifaddrhead, ia_link) {
if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0)
continue;
@@ -1624,6 +1624,7 @@ pfxlist_onlink_check()
}
}
}
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
}
static int
diff --git a/sys/netpfil/ipfw/dn_aqm_pie.c b/sys/netpfil/ipfw/dn_aqm_pie.c
index d994986..c4b9401 100644
--- a/sys/netpfil/ipfw/dn_aqm_pie.c
+++ b/sys/netpfil/ipfw/dn_aqm_pie.c
@@ -244,20 +244,20 @@ calculate_drop_prob(void *x)
p *= (PIE_MAX_PROB << 12) / AQM_TIME_1S;
/* auto-tune drop probability */
- if (prob< PIE_MAX_PROB * 0.000001)
- p >>= 11 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.00001)
- p >>= 9 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.0001)
- p >>= 7 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.001)
- p >>= 5 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.01)
- p >>= 3 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.1)
- p >>= 1 + PIE_FIX_POINT_BITS+12;
+ if (prob < (PIE_MAX_PROB / 1000000)) /* 0.000001 */
+ p >>= 11 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 100000)) /* 0.00001 */
+ p >>= 9 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 10000)) /* 0.0001 */
+ p >>= 7 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 1000)) /* 0.001 */
+ p >>= 5 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 100)) /* 0.01 */
+ p >>= 3 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 10)) /* 0.1 */
+ p >>= 1 + PIE_FIX_POINT_BITS + 12;
else
- p >>= PIE_FIX_POINT_BITS+12;
+ p >>= PIE_FIX_POINT_BITS + 12;
oldprob = prob;
diff --git a/sys/netpfil/ipfw/dn_aqm_pie.h b/sys/netpfil/ipfw/dn_aqm_pie.h
index b045077..aa2fceb 100644
--- a/sys/netpfil/ipfw/dn_aqm_pie.h
+++ b/sys/netpfil/ipfw/dn_aqm_pie.h
@@ -132,11 +132,13 @@ drop_early(struct pie_status *pst, uint32_t qlen)
* if accu_prob < 0.85 -> enqueue
* if accu_prob>8.5 ->drop
* between 0.85 and 8.5 || !De-randomize --> drop on prob
+ *
+ * (0.85 = 17/20 ,8.5 = 17/2)
*/
if (pprms->flags & PIE_DERAND_ENABLED) {
- if(pst->accu_prob < (uint64_t) (PIE_MAX_PROB * 0.85))
+ if(pst->accu_prob < (uint64_t) (PIE_MAX_PROB * 17 / 20))
return ENQUE;
- if( pst->accu_prob >= (uint64_t) (PIE_MAX_PROB * 8.5))
+ if( pst->accu_prob >= (uint64_t) (PIE_MAX_PROB * 17 / 2))
return DROP;
}
diff --git a/sys/netpfil/ipfw/dn_sched_fq_pie.c b/sys/netpfil/ipfw/dn_sched_fq_pie.c
index 6b9628a..2883cf8 100644
--- a/sys/netpfil/ipfw/dn_sched_fq_pie.c
+++ b/sys/netpfil/ipfw/dn_sched_fq_pie.c
@@ -407,20 +407,20 @@ fq_calculate_drop_prob(void *x)
p *= (PIE_MAX_PROB << 12) / AQM_TIME_1S;
/* auto-tune drop probability */
- if (prob< PIE_MAX_PROB * 0.000001)
- p >>= 11 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.00001)
- p >>= 9 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.0001)
- p >>= 7 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.001)
- p >>= 5 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.01)
- p >>= 3 + PIE_FIX_POINT_BITS+12;
- else if (prob < PIE_MAX_PROB * 0.1)
- p >>= 1 + PIE_FIX_POINT_BITS+12;
+ if (prob < (PIE_MAX_PROB / 1000000)) /* 0.000001 */
+ p >>= 11 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 100000)) /* 0.00001 */
+ p >>= 9 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 10000)) /* 0.0001 */
+ p >>= 7 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 1000)) /* 0.001 */
+ p >>= 5 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 100)) /* 0.01 */
+ p >>= 3 + PIE_FIX_POINT_BITS + 12;
+ else if (prob < (PIE_MAX_PROB / 10)) /* 0.1 */
+ p >>= 1 + PIE_FIX_POINT_BITS + 12;
else
- p >>= PIE_FIX_POINT_BITS+12;
+ p >>= PIE_FIX_POINT_BITS + 12;
oldprob = prob;
diff --git a/sys/ofed/drivers/infiniband/core/addr.c b/sys/ofed/drivers/infiniband/core/addr.c
index 577ccc0..7a680ca 100644
--- a/sys/ofed/drivers/infiniband/core/addr.c
+++ b/sys/ofed/drivers/infiniband/core/addr.c
@@ -395,13 +395,13 @@ mcast:
#ifdef INET
case AF_INET:
error = arpresolve(ifp, is_gw, NULL,
- is_gw ? rte->rt_gateway : dst_in, edst, NULL);
+ is_gw ? rte->rt_gateway : dst_in, edst, NULL, NULL);
break;
#endif
#ifdef INET6
case AF_INET6:
error = nd6_resolve(ifp, is_gw, NULL,
- is_gw ? rte->rt_gateway : dst_in, edst, NULL);
+ is_gw ? rte->rt_gateway : dst_in, edst, NULL, NULL);
break;
#endif
default:
diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 5bef672..b2f5efe 100644
--- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1296,7 +1296,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
else if (m->m_flags & M_MCAST)
ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst);
else
- error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
+ error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -1334,7 +1334,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
else if (m->m_flags & M_MCAST)
ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst);
else
- error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
+ error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL);
if (error)
return error;
type = htons(ETHERTYPE_IPV6);
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index 861a3c4..13f595a4 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -23,7 +23,9 @@ ident GENERIC
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
# makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support
-makeoptions NO_MODULES=1 # We don't yet support modules on RISC-V
+
+# FIXME: linker error. "--relax and -r may not be used together"
+makeoptions WITHOUT_MODULES="usb otusfw mwlfw ispfw mwlfw ralfw rtwnfw urtwnfw"
options SCHED_ULE # ULE scheduler
options PREEMPTION # Enable kernel thread preemption
@@ -64,8 +66,8 @@ options AUDIT # Security event auditing
options CAPABILITY_MODE # Capsicum capability mode
options CAPABILITIES # Capsicum capabilities
options MAC # TrustedBSD MAC Framework
-# options KDTRACE_FRAME # Ensure frames are compiled in
-# options KDTRACE_HOOKS # Kernel DTrace hooks
+options KDTRACE_FRAME # Ensure frames are compiled in
+options KDTRACE_HOOKS # Kernel DTrace hooks
# options VFP # Floating-point support
options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
@@ -102,4 +104,9 @@ device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
device firmware # firmware assist module
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
options FDT
diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c
index 1e44801..c0c5a9f 100644
--- a/sys/riscv/riscv/elf_machdep.c
+++ b/sys/riscv/riscv/elf_machdep.c
@@ -1,6 +1,7 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2016 Yukishige Shibata <y-shibat@mtd.biglobe.ne.jp>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@@ -43,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/imgact.h>
#include <sys/linker.h>
#include <sys/proc.h>
+#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -123,19 +125,380 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
+static int debug_kld;
+SYSCTL_INT(_kern, OID_AUTO, debug_kld,
+ CTLFLAG_RW, &debug_kld, 0,
+ "Activate debug prints in elf_reloc_internal()");
+
+struct type2str_ent {
+ int type;
+ const char *str;
+};
+
void
elf64_dump_thread(struct thread *td, void *dst, size_t *off)
{
}
-/* Process one elf relocation with addend. */
+/*
+ * Following 4 functions are used to manupilate bits on 32bit interger value.
+ * FIXME: I implemetend for ease-to-understand rather than for well-optimized.
+ */
+static uint32_t
+gen_bitmask(int msb, int lsb)
+{
+ uint32_t mask;
+
+ if (msb == sizeof(mask) * 8 - 1)
+ mask = ~0;
+ else
+ mask = (1U << (msb + 1)) - 1;
+
+ if (lsb > 0)
+ mask &= ~((1U << lsb) - 1);
+
+ return (mask);
+}
+
+static uint32_t
+extract_bits(uint32_t x, int msb, int lsb)
+{
+ uint32_t mask;
+
+ mask = gen_bitmask(msb, lsb);
+
+ x &= mask;
+ x >>= lsb;
+
+ return (x);
+}
+
+static uint32_t
+insert_bits(uint32_t d, uint32_t s, int msb, int lsb)
+{
+ uint32_t mask;
+
+ mask = gen_bitmask(msb, lsb);
+
+ d &= ~mask;
+
+ s <<= lsb;
+ s &= mask;
+
+ return (d | s);
+}
+
+static uint32_t
+insert_imm(uint32_t insn, uint32_t imm, int imm_msb, int imm_lsb,
+ int insn_lsb)
+{
+ int insn_msb;
+ uint32_t v;
+
+ v = extract_bits(imm, imm_msb, imm_lsb);
+ insn_msb = (imm_msb - imm_lsb) + insn_lsb;
+
+ return (insert_bits(insn, v, insn_msb, insn_lsb));
+}
+
+/*
+ * The RISC-V ISA is designed so that all of immediate values are
+ * sign-extended.
+ * An immediate value is sometimes generated at runtime by adding
+ * 12bit sign integer and 20bit signed integer. This requests 20bit
+ * immediate value to be ajusted if the MSB of the 12bit immediate
+ * value is asserted (sign-extended value is treated as negative value).
+ *
+ * For example, 0x123800 can be calculated by adding upper 20 bit of
+ * 0x124000 and sign-extended 12bit immediate whose bit pattern is
+ * 0x800 as follows:
+ * 0x123800
+ * = 0x123000 + 0x800
+ * = (0x123000 + 0x1000) + (-0x1000 + 0x800)
+ * = (0x123000 + 0x1000) + (0xff...ff800)
+ * = 0x124000 + sign-extention(0x800)
+ */
+static uint32_t
+calc_hi20_imm(uint32_t value)
+{
+ /*
+ * There is the arithmetical hack that can remove conditional
+ * statement. But I implement it in straightforward way.
+ */
+ if ((value & 0x800) != 0)
+ value += 0x1000;
+ return (value & ~0xfff);
+}
+
+static const struct type2str_ent t2s[] = {
+ { R_RISCV_NONE, "R_RISCV_NONE" },
+ { R_RISCV_64, "R_RISCV_64" },
+ { R_RISCV_JUMP_SLOT, "R_RISCV_JUMP_SLOT" },
+ { R_RISCV_RELATIVE, "R_RISCV_RELATIVE" },
+ { R_RISCV_JAL, "R_RISCV_JAL" },
+ { R_RISCV_CALL, "R_RISCV_CALL" },
+ { R_RISCV_PCREL_HI20, "R_RISCV_PCREL_HI20" },
+ { R_RISCV_PCREL_LO12_I, "R_RISCV_PCREL_LO12_I" },
+ { R_RISCV_PCREL_LO12_S, "R_RISCV_PCREL_LO12_S" },
+ { R_RISCV_HI20, "R_RISCV_HI20" },
+ { R_RISCV_LO12_I, "R_RISCV_LO12_I" },
+ { R_RISCV_LO12_S, "R_RISCV_LO12_S" },
+};
+
+static const char *
+reloctype_to_str(int type)
+{
+ int i;
+
+ for (i = 0; i < sizeof(t2s) / sizeof(t2s[0]); ++i) {
+ if (type == t2s[i].type)
+ return t2s[i].str;
+ }
+
+ return "*unknown*";
+}
+
+/*
+ * Currently kernel loadable module for RISCV is compiled with -fPIC option.
+ * (see also additional CFLAGS definition for RISCV in sys/conf/kmod.mk)
+ * Only R_RISCV_64, R_RISCV_JUMP_SLOT and RISCV_RELATIVE are emitted in
+ * the module. Other relocations will be processed when kernel loadable
+ * modules are built in non-PIC.
+ *
+ * FIXME: only RISCV64 is supported.
+ */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
int type, int local, elf_lookup_fn lookup)
{
+ Elf_Size rtype, symidx;
+ const Elf_Rela *rela;
+ Elf_Addr val, addr;
+ Elf64_Addr *where;
+ Elf_Addr addend;
+ uint32_t before32_1;
+ uint32_t before32;
+ uint64_t before64;
+ uint32_t* insn32p;
+ uint32_t imm20;
+ int error;
+
+ switch (type) {
+ case ELF_RELOC_RELA:
+ rela = (const Elf_Rela *)data;
+ where = (Elf_Addr *)(relocbase + rela->r_offset);
+ insn32p = (uint32_t*)where;
+ addend = rela->r_addend;
+ rtype = ELF_R_TYPE(rela->r_info);
+ symidx = ELF_R_SYM(rela->r_info);
+ break;
+ default:
+ printf("%s:%d unknown reloc type %d\n",
+ __FUNCTION__, __LINE__, type);
+ return -1;
+ }
+
+ switch (rtype) {
+ case R_RISCV_NONE:
+ break;
+
+ case R_RISCV_64:
+ case R_RISCV_JUMP_SLOT:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+
+ val = addr;
+ before64 = *where;
+ if (*where != val)
+ *where = val;
+
+ if (debug_kld)
+ printf("%p %c %-24s %016lx -> %016lx\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before64, *where);
+ break;
+
+ case R_RISCV_RELATIVE:
+ val = relocbase + addend;
+
+ before64 = *where;
+ if (*where != val)
+ *where = val;
+
+ if (debug_kld)
+ printf("%p %c %-24s %016lx -> %016lx\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before64, *where);
+ break;
+
+ case R_RISCV_JAL:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+
+ val = addr - (Elf_Addr)where;
+ if ((val <= -(1UL << 20) || (1UL << 20) <= val)) {
+ printf("kldload: huge offset against R_RISCV_JAL\n");
+ return -1;
+ }
+
+ before32 = *insn32p;
+ *insn32p = insert_imm(*insn32p, val, 20, 20, 31);
+ *insn32p = insert_imm(*insn32p, val, 10, 1, 21);
+ *insn32p = insert_imm(*insn32p, val, 11, 11, 20);
+ *insn32p = insert_imm(*insn32p, val, 19, 12, 12);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ case R_RISCV_CALL:
+ /*
+ * R_RISCV_CALL relocates 8-byte region that consists
+ * of the sequence of AUIPC and JALR.
+ */
+ /* calculate and check the pc relative offset. */
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+ val = addr - (Elf_Addr)where;
+ if ((val <= -(1UL << 32) || (1UL << 32) <= val)) {
+ printf("kldload: huge offset against R_RISCV_CALL\n");
+ return -1;
+ }
+
+ /* Relocate AUIPC. */
+ before32 = insn32p[0];
+ imm20 = calc_hi20_imm(val);
+ insn32p[0] = insert_imm(insn32p[0], imm20, 31, 12, 12);
- panic("elf_reloc_internal");
+ /* Relocate JALR. */
+ before32_1 = insn32p[1];
+ insn32p[1] = insert_imm(insn32p[1], val, 11, 0, 20);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x %08x -> %08x %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, insn32p[0],
+ before32_1, insn32p[1]);
+ break;
+
+ case R_RISCV_PCREL_HI20:
+ val = addr - (Elf_Addr)where;
+ insn32p = (uint32_t*)where;
+ before32 = *insn32p;
+ imm20 = calc_hi20_imm(val);
+ *insn32p = insert_imm(*insn32p, imm20, 31, 12, 12);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ case R_RISCV_PCREL_LO12_I:
+ val = addr - (Elf_Addr)where;
+ insn32p = (uint32_t*)where;
+ before32 = *insn32p;
+ *insn32p = insert_imm(*insn32p, addr, 11, 0, 20);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ case R_RISCV_PCREL_LO12_S:
+ val = addr - (Elf_Addr)where;
+ insn32p = (uint32_t*)where;
+ before32 = *insn32p;
+ *insn32p = insert_imm(*insn32p, addr, 11, 5, 25);
+ *insn32p = insert_imm(*insn32p, addr, 4, 0, 7);
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ case R_RISCV_HI20:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+
+ insn32p = (uint32_t*)where;
+ before32 = *insn32p;
+ imm20 = calc_hi20_imm(val);
+ *insn32p = insert_imm(*insn32p, imm20, 31, 12, 12);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ case R_RISCV_LO12_I:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+
+ val = addr;
+ insn32p = (uint32_t*)where;
+ before32 = *insn32p;
+ *insn32p = insert_imm(*insn32p, addr, 11, 0, 20);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ case R_RISCV_LO12_S:
+ error = lookup(lf, symidx, 1, &addr);
+ if (error != 0)
+ return -1;
+
+ val = addr;
+ insn32p = (uint32_t*)where;
+ before32 = *insn32p;
+ *insn32p = insert_imm(*insn32p, addr, 11, 5, 25);
+ *insn32p = insert_imm(*insn32p, addr, 4, 0, 7);
+
+ if (debug_kld)
+ printf("%p %c %-24s %08x -> %08x\n",
+ where,
+ (local? 'l': 'g'),
+ reloctype_to_str(rtype),
+ before32, *insn32p);
+ break;
+
+ default:
+ printf("kldload: unexpected relocation type %ld\n", rtype);
+ return (-1);
+ }
+
+ return (0);
}
int
diff --git a/sys/sys/aio.h b/sys/sys/aio.h
index 0abee2d..3c6ed54 100644
--- a/sys/sys/aio.h
+++ b/sys/sys/aio.h
@@ -205,7 +205,8 @@ int aio_write(struct aiocb *);
* "acb_list" is an array of "nacb_listent" I/O control blocks.
* when all I/Os are complete, the optional signal "sig" is sent.
*/
-int lio_listio(int, struct aiocb * const [], int, struct sigevent *);
+int lio_listio(int, struct aiocb *__restrict const *__restrict, int,
+ struct sigevent *);
/*
* Get completion status
diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
index 11c4d1e..89516cf 100644
--- a/sys/sys/cdefs.h
+++ b/sys/sys/cdefs.h
@@ -275,7 +275,8 @@
#define _Alignof(x) __alignof(x)
#endif
-#if !__has_extension(c_atomic) && !__has_extension(cxx_atomic)
+#if !defined(__cplusplus) && !__has_extension(c_atomic) && \
+ !__has_extension(cxx_atomic)
/*
* No native support for _Atomic(). Place object in structure to prevent
* most forms of direct non-atomic access.
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index 6793d5f..f4017e7 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -1037,10 +1037,16 @@ typedef struct {
#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
#define R_MIPS_64 18 /* Direct 64 bit */
-#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */
-#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22 /* GOT HI 16 bit */
+#define R_MIPS_GOT_LO16 23 /* GOT LO 16 bit */
+#define R_MIPS_SUB 24
#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */
#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */
+#define R_MIPS_JALR 37
+#define R_MIPS_TLS_GD 42
#define R_PPC_NONE 0 /* No relocation. */
#define R_PPC_ADDR32 1
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index c6dd848..d3e2151 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -139,10 +139,13 @@ enum sysinit_sub_id {
SI_SUB_PSEUDO = 0x7000000, /* pseudo devices*/
SI_SUB_EXEC = 0x7400000, /* execve() handlers */
SI_SUB_PROTO_BEGIN = 0x8000000, /* VNET initialization */
+ SI_SUB_PROTO_PFIL = 0x8100000, /* Initialize pfil before FWs */
SI_SUB_PROTO_IF = 0x8400000, /* interfaces*/
SI_SUB_PROTO_DOMAININIT = 0x8600000, /* domain registration system */
+ SI_SUB_PROTO_MC = 0x8700000, /* Multicast */
SI_SUB_PROTO_DOMAIN = 0x8800000, /* domains (address families?)*/
- SI_SUB_PROTO_IFATTACHDOMAIN = 0x8800001, /* domain dependent data init*/
+ SI_SUB_PROTO_FIREWALL = 0x8806000, /* Firewalls */
+ SI_SUB_PROTO_IFATTACHDOMAIN = 0x8808000,/* domain dependent data init */
SI_SUB_PROTO_END = 0x8ffffff, /* VNET helper functions */
SI_SUB_KPROF = 0x9000000, /* kernel profiling*/
SI_SUB_KICK_SCHEDULER = 0xa000000, /* start the timeout events*/
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index ca867ab..4d59c7f 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -318,30 +318,41 @@ struct mbuf {
*
* Most NICs support RSS, which provides ordering and explicit affinity, and
* use the hash m_flag bits to indicate what header fields were covered by
- * the hash. M_HASHTYPE_OPAQUE can be set by non-RSS cards or configurations
- * that provide an opaque flow identifier, allowing for ordering and
- * distribution without explicit affinity.
+ * the hash. M_HASHTYPE_OPAQUE and M_HASHTYPE_OPAQUE_HASH can be set by non-
+ * RSS cards or configurations that provide an opaque flow identifier, allowing
+ * for ordering and distribution without explicit affinity. Additionally,
+ * M_HASHTYPE_OPAQUE_HASH indicates that the flow identifier has hash
+ * properties.
*/
+#define M_HASHTYPE_HASHPROP 0x80 /* has hash properties */
+#define M_HASHTYPE_HASH(t) (M_HASHTYPE_HASHPROP | (t))
/* Microsoft RSS standard hash types */
#define M_HASHTYPE_NONE 0
-#define M_HASHTYPE_RSS_IPV4 1 /* IPv4 2-tuple */
-#define M_HASHTYPE_RSS_TCP_IPV4 2 /* TCPv4 4-tuple */
-#define M_HASHTYPE_RSS_IPV6 3 /* IPv6 2-tuple */
-#define M_HASHTYPE_RSS_TCP_IPV6 4 /* TCPv6 4-tuple */
-#define M_HASHTYPE_RSS_IPV6_EX 5 /* IPv6 2-tuple + ext hdrs */
-#define M_HASHTYPE_RSS_TCP_IPV6_EX 6 /* TCPv6 4-tiple + ext hdrs */
+#define M_HASHTYPE_RSS_IPV4 M_HASHTYPE_HASH(1) /* IPv4 2-tuple */
+#define M_HASHTYPE_RSS_TCP_IPV4 M_HASHTYPE_HASH(2) /* TCPv4 4-tuple */
+#define M_HASHTYPE_RSS_IPV6 M_HASHTYPE_HASH(3) /* IPv6 2-tuple */
+#define M_HASHTYPE_RSS_TCP_IPV6 M_HASHTYPE_HASH(4) /* TCPv6 4-tuple */
+#define M_HASHTYPE_RSS_IPV6_EX M_HASHTYPE_HASH(5) /* IPv6 2-tuple +
+ * ext hdrs */
+#define M_HASHTYPE_RSS_TCP_IPV6_EX M_HASHTYPE_HASH(6) /* TCPv6 4-tiple +
+ * ext hdrs */
/* Non-standard RSS hash types */
-#define M_HASHTYPE_RSS_UDP_IPV4 7 /* IPv4 UDP 4-tuple */
-#define M_HASHTYPE_RSS_UDP_IPV4_EX 8 /* IPv4 UDP 4-tuple + ext hdrs */
-#define M_HASHTYPE_RSS_UDP_IPV6 9 /* IPv6 UDP 4-tuple */
-#define M_HASHTYPE_RSS_UDP_IPV6_EX 10 /* IPv6 UDP 4-tuple + ext hdrs */
+#define M_HASHTYPE_RSS_UDP_IPV4 M_HASHTYPE_HASH(7) /* IPv4 UDP 4-tuple*/
+#define M_HASHTYPE_RSS_UDP_IPV4_EX M_HASHTYPE_HASH(8) /* IPv4 UDP 4-tuple +
+ * ext hdrs */
+#define M_HASHTYPE_RSS_UDP_IPV6 M_HASHTYPE_HASH(9) /* IPv6 UDP 4-tuple*/
+#define M_HASHTYPE_RSS_UDP_IPV6_EX M_HASHTYPE_HASH(10)/* IPv6 UDP 4-tuple +
+ * ext hdrs */
-#define M_HASHTYPE_OPAQUE 255 /* ordering, not affinity */
+#define M_HASHTYPE_OPAQUE 63 /* ordering, not affinity */
+#define M_HASHTYPE_OPAQUE_HASH M_HASHTYPE_HASH(M_HASHTYPE_OPAQUE)
+ /* ordering+hash, not affinity*/
#define M_HASHTYPE_CLEAR(m) ((m)->m_pkthdr.rsstype = 0)
#define M_HASHTYPE_GET(m) ((m)->m_pkthdr.rsstype)
#define M_HASHTYPE_SET(m, v) ((m)->m_pkthdr.rsstype = (v))
#define M_HASHTYPE_TEST(m, v) (M_HASHTYPE_GET(m) == (v))
+#define M_HASHTYPE_ISHASH(m) (M_HASHTYPE_GET(m) & M_HASHTYPE_HASHPROP)
/*
* COS/QOS class and quality of service tags.
diff --git a/sys/sys/mutex.h b/sys/sys/mutex.h
index a9ec072..0443922 100644
--- a/sys/sys/mutex.h
+++ b/sys/sys/mutex.h
@@ -185,7 +185,7 @@ void thread_lock_flags_(struct thread *, int, const char *, int);
#define __mtx_lock(mp, tid, opts, file, line) do { \
uintptr_t _tid = (uintptr_t)(tid); \
\
- if (!_mtx_obtain_lock((mp), _tid)) \
+ if (((mp)->mtx_lock != MTX_UNOWNED || !_mtx_obtain_lock((mp), _tid)))\
_mtx_lock_sleep((mp), _tid, (opts), (file), (line)); \
else \
LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(adaptive__acquire, \
@@ -203,7 +203,7 @@ void thread_lock_flags_(struct thread *, int, const char *, int);
uintptr_t _tid = (uintptr_t)(tid); \
\
spinlock_enter(); \
- if (!_mtx_obtain_lock((mp), _tid)) { \
+ if (((mp)->mtx_lock != MTX_UNOWNED || !_mtx_obtain_lock((mp), _tid))) {\
if ((mp)->mtx_lock == _tid) \
(mp)->mtx_recurse++; \
else \
@@ -232,7 +232,7 @@ void thread_lock_flags_(struct thread *, int, const char *, int);
\
if ((mp)->mtx_recurse == 0) \
LOCKSTAT_PROFILE_RELEASE_LOCK(adaptive__release, mp); \
- if (!_mtx_release_lock((mp), _tid)) \
+ if ((mp)->mtx_lock != _tid || !_mtx_release_lock((mp), _tid)) \
_mtx_unlock_sleep((mp), (opts), (file), (line)); \
} while (0)
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 3ed2028..d7fa2c7 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1100114 /* Master, propagated to newvers */
+#define __FreeBSD_version 1100116 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h
index 2a44d80..896ec25 100644
--- a/sys/sys/protosw.h
+++ b/sys/sys/protosw.h
@@ -70,7 +70,6 @@ typedef int pr_output_t (struct mbuf *, struct socket *, ...);
typedef void pr_ctlinput_t (int, struct sockaddr *, void *);
typedef int pr_ctloutput_t (struct socket *, struct sockopt *);
typedef void pr_init_t (void);
-typedef void pr_destroy_t (void);
typedef void pr_fasttimo_t (void);
typedef void pr_slowtimo_t (void);
typedef void pr_drain_t (void);
@@ -87,7 +86,6 @@ struct protosw {
pr_ctloutput_t *pr_ctloutput; /* control output (from above) */
/* utility hooks */
pr_init_t *pr_init;
- pr_destroy_t *pr_destroy;
pr_fasttimo_t *pr_fasttimo; /* fast timeout (200ms) */
pr_slowtimo_t *pr_slowtimo; /* slow timeout (500ms) */
pr_drain_t *pr_drain; /* flush any excess space possible */
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
index 9d45e5c..91b1141 100644
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -37,6 +37,16 @@
#include <sys/_timeval.h>
#include <sys/_types.h>
+#ifndef _ID_T_DECLARED
+typedef __id_t id_t;
+#define _ID_T_DECLARED
+#endif
+
+#ifndef _RLIM_T_DECLARED
+typedef __rlim_t rlim_t;
+#define _RLIM_T_DECLARED
+#endif
+
/*
* Process priority specifications to get/setpriority.
*/
@@ -108,7 +118,7 @@ struct __wrusage {
#define RLIM_NLIMITS 15 /* number of resource limits */
-#define RLIM_INFINITY ((rlim_t)(((uint64_t)1 << 63) - 1))
+#define RLIM_INFINITY ((rlim_t)(((__uint64_t)1 << 63) - 1))
/* XXX Missing: RLIM_SAVED_MAX, RLIM_SAVED_CUR */
@@ -136,11 +146,6 @@ static const char *rlimit_ident[RLIM_NLIMITS] = {
};
#endif
-#ifndef _RLIM_T_DECLARED
-typedef __rlim_t rlim_t;
-#define _RLIM_T_DECLARED
-#endif
-
struct rlimit {
rlim_t rlim_cur; /* current (soft) limit */
rlim_t rlim_max; /* maximum value for rlim_cur */
diff --git a/sys/sys/rwlock.h b/sys/sys/rwlock.h
index f8947c5..6b4f505 100644
--- a/sys/sys/rwlock.h
+++ b/sys/sys/rwlock.h
@@ -96,7 +96,7 @@
#define __rw_wlock(rw, tid, file, line) do { \
uintptr_t _tid = (uintptr_t)(tid); \
\
- if (!_rw_write_lock((rw), _tid)) \
+ if ((rw)->rw_lock != RW_UNLOCKED || !_rw_write_lock((rw), _tid))\
_rw_wlock_hard((rw), _tid, (file), (line)); \
else \
LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(rw__acquire, rw, \
@@ -112,7 +112,7 @@
else { \
LOCKSTAT_PROFILE_RELEASE_RWLOCK(rw__release, rw, \
LOCKSTAT_WRITER); \
- if (!_rw_write_unlock((rw), _tid)) \
+ if ((rw)->rw_lock != _tid || !_rw_write_unlock((rw), _tid))\
_rw_wunlock_hard((rw), _tid, (file), (line)); \
} \
} while (0)
diff --git a/sys/sys/sched.h b/sys/sys/sched.h
index 7346244..576c8b1 100644
--- a/sys/sys/sched.h
+++ b/sys/sys/sched.h
@@ -222,6 +222,7 @@ struct sched_param {
*/
#ifndef _KERNEL
#include <sys/cdefs.h>
+#include <sys/_timespec.h>
#include <sys/_types.h>
#ifndef _PID_T_DECLARED
@@ -229,8 +230,6 @@ typedef __pid_t pid_t;
#define _PID_T_DECLARED
#endif
-struct timespec;
-
__BEGIN_DECLS
int sched_get_priority_max(int);
int sched_get_priority_min(int);
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index 455e858..abf5a85 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -43,6 +43,8 @@
#include <sys/ipc.h>
#include <sys/_types.h>
+#include <machine/param.h>
+
#define SHM_RDONLY 010000 /* Attach read-only (else read-write) */
#define SHM_RND 020000 /* Round attach address to SHMLBA */
#define SHMLBA PAGE_SIZE /* Segment low boundary address multiple */
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
index ab8fcf4..86a07e1 100644
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -45,6 +45,23 @@
#include <machine/_limits.h> /* __MINSIGSTKSZ */
#include <machine/signal.h> /* sig_atomic_t; trap codes; sigcontext */
+#if __POSIX_VISIBLE >= 200809
+
+#include <sys/_pthreadtypes.h>
+#include <sys/_timespec.h>
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#ifndef _UID_T_DECLARED
+typedef __uid_t uid_t;
+#define _UID_T_DECLARED
+#endif
+
+#endif /* __POSIX_VISIBLE >= 200809 */
+
/*
* System defined signals.
*/
@@ -160,6 +177,9 @@ union sigval {
#endif
#if __POSIX_VISIBLE >= 199309
+
+struct pthread_attr;
+
struct sigevent {
int sigev_notify; /* Notification type */
int sigev_signo; /* Signal number */
@@ -168,7 +188,7 @@ struct sigevent {
__lwpid_t _threadid;
struct {
void (*_function)(union sigval);
- void *_attribute; /* pthread_attr_t * */
+ struct pthread_attr **_attribute;
} _sigev_thread;
unsigned short _kevent_flags;
long __spare__[8];
@@ -190,6 +210,7 @@ struct sigevent {
#define SIGEV_KEVENT 3 /* Generate a kevent. */
#define SIGEV_THREAD_ID 4 /* Send signal to a kernel thread. */
#endif
+
#endif /* __POSIX_VISIBLE >= 199309 */
#if __POSIX_VISIBLE >= 199309 || __XSI_VISIBLE
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index 649ba00..f23b5f6 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -500,7 +500,7 @@ struct sockcred {
/* given pointer to struct cmsghdr, return pointer to next cmsghdr */
#define CMSG_NXTHDR(mhdr, cmsg) \
- ((char *)(cmsg) == NULL ? CMSG_FIRSTHDR(mhdr) : \
+ ((char *)(cmsg) == (char *)0 ? CMSG_FIRSTHDR(mhdr) : \
((char *)(cmsg) + _ALIGN(((struct cmsghdr *)(cmsg))->cmsg_len) + \
_ALIGN(sizeof(struct cmsghdr)) > \
(char *)(mhdr)->msg_control + (mhdr)->msg_controllen) ? \
@@ -515,7 +515,7 @@ struct sockcred {
#define CMSG_FIRSTHDR(mhdr) \
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
(struct cmsghdr *)(mhdr)->msg_control : \
- (struct cmsghdr *)NULL)
+ (struct cmsghdr *)0)
#if __BSD_VISIBLE
/* RFC 2292 additions */
diff --git a/sys/sys/sx.h b/sys/sys/sx.h
index 03b51d3..57a31d9 100644
--- a/sys/sys/sx.h
+++ b/sys/sys/sx.h
@@ -150,7 +150,8 @@ __sx_xlock(struct sx *sx, struct thread *td, int opts, const char *file,
uintptr_t tid = (uintptr_t)td;
int error = 0;
- if (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid))
+ if (sx->sx_lock != SX_LOCK_UNLOCKED ||
+ !atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid))
error = _sx_xlock_hard(sx, tid, opts, file, line);
else
LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire, sx,
@@ -168,7 +169,8 @@ __sx_xunlock(struct sx *sx, struct thread *td, const char *file, int line)
if (sx->sx_recurse == 0)
LOCKSTAT_PROFILE_RELEASE_RWLOCK(sx__release, sx,
LOCKSTAT_WRITER);
- if (!atomic_cmpset_rel_ptr(&sx->sx_lock, tid, SX_LOCK_UNLOCKED))
+ if (sx->sx_lock != tid ||
+ !atomic_cmpset_rel_ptr(&sx->sx_lock, tid, SX_LOCK_UNLOCKED))
_sx_xunlock_hard(sx, tid, file, line);
}
diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h
index 4c4044f..c986ffb 100644
--- a/sys/sys/taskqueue.h
+++ b/sys/sys/taskqueue.h
@@ -236,6 +236,21 @@ int taskqgroup_adjust(struct taskqgroup *qgroup, int cnt, int stride);
#define TASKQGROUP_DECLARE(name) \
extern struct taskqgroup *qgroup_##name
+#ifdef EARLY_AP_STARTUP
+#define TASKQGROUP_DEFINE(name, cnt, stride) \
+ \
+struct taskqgroup *qgroup_##name; \
+ \
+static void \
+taskqgroup_define_##name(void *arg) \
+{ \
+ qgroup_##name = taskqgroup_create(#name); \
+ taskqgroup_adjust(qgroup_##name, (cnt), (stride)); \
+} \
+ \
+SYSINIT(taskqgroup_##name, SI_SUB_INIT_IF, SI_ORDER_FIRST, \
+ taskqgroup_define_##name, NULL)
+#else
#define TASKQGROUP_DEFINE(name, cnt, stride) \
\
struct taskqgroup *qgroup_##name; \
@@ -259,6 +274,7 @@ SYSINIT(taskqgroup_adj_##name, SI_SUB_SMP, SI_ORDER_ANY, \
taskqgroup_adjust_##name, NULL); \
\
struct __hack
+#endif
TASKQGROUP_DECLARE(net);
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index bcc895e..0a56c55 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -2112,16 +2112,10 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
if (memguard_cmp_zone(zone)) {
item = memguard_alloc(zone->uz_size, flags);
if (item != NULL) {
- /*
- * Avoid conflict with the use-after-free
- * protecting infrastructure from INVARIANTS.
- */
if (zone->uz_init != NULL &&
- zone->uz_init != mtrash_init &&
zone->uz_init(item, zone->uz_size, flags) != 0)
return (NULL);
if (zone->uz_ctor != NULL &&
- zone->uz_ctor != mtrash_ctor &&
zone->uz_ctor(item, zone->uz_size, udata,
flags) != 0) {
zone->uz_fini(item, zone->uz_size);
@@ -2655,9 +2649,9 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
return;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(item)) {
- if (zone->uz_dtor != NULL && zone->uz_dtor != mtrash_dtor)
+ if (zone->uz_dtor != NULL)
zone->uz_dtor(item, zone->uz_size, udata);
- if (zone->uz_fini != NULL && zone->uz_fini != mtrash_fini)
+ if (zone->uz_fini != NULL)
zone->uz_fini(item, zone->uz_size);
memguard_free(item);
return;
diff --git a/sys/vm/uma_dbg.c b/sys/vm/uma_dbg.c
index dcef5c9..12067b1 100644
--- a/sys/vm/uma_dbg.c
+++ b/sys/vm/uma_dbg.c
@@ -33,6 +33,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_vm.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitset.h>
@@ -49,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <vm/uma_int.h>
#include <vm/uma_dbg.h>
+#include <vm/memguard.h>
static const uint32_t uma_junk = 0xdeadc0de;
@@ -57,7 +60,6 @@ static const uint32_t uma_junk = 0xdeadc0de;
* prior to subsequent reallocation.
*
* Complies with standard ctor arg/return
- *
*/
int
trash_ctor(void *mem, int size, void *arg, int flags)
@@ -65,6 +67,11 @@ trash_ctor(void *mem, int size, void *arg, int flags)
int cnt;
uint32_t *p;
+#ifdef DEBUG_MEMGUARD
+ if (is_memguard_addr(mem))
+ return (0);
+#endif
+
cnt = size / sizeof(uma_junk);
for (p = mem; cnt > 0; cnt--, p++)
@@ -93,6 +100,11 @@ trash_dtor(void *mem, int size, void *arg)
int cnt;
uint32_t *p;
+#ifdef DEBUG_MEMGUARD
+ if (is_memguard_addr(mem))
+ return;
+#endif
+
cnt = size / sizeof(uma_junk);
for (p = mem; cnt > 0; cnt--, p++)
@@ -131,6 +143,11 @@ mtrash_ctor(void *mem, int size, void *arg, int flags)
uint32_t *p = mem;
int cnt;
+#ifdef DEBUG_MEMGUARD
+ if (is_memguard_addr(mem))
+ return (0);
+#endif
+
size -= sizeof(struct malloc_type *);
ksp = (struct malloc_type **)mem;
ksp += size / sizeof(struct malloc_type *);
@@ -158,6 +175,11 @@ mtrash_dtor(void *mem, int size, void *arg)
int cnt;
uint32_t *p;
+#ifdef DEBUG_MEMGUARD
+ if (is_memguard_addr(mem))
+ return;
+#endif
+
size -= sizeof(struct malloc_type *);
cnt = size / sizeof(uma_junk);
@@ -176,6 +198,11 @@ mtrash_init(void *mem, int size, int flags)
{
struct malloc_type **ksp;
+#ifdef DEBUG_MEMGUARD
+ if (is_memguard_addr(mem))
+ return (0);
+#endif
+
mtrash_dtor(mem, size, NULL);
ksp = (struct malloc_type **)mem;
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 88bc593..2af4b79 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -2123,6 +2123,7 @@ vm_object_coalesce(vm_object_t prev_object, vm_ooffset_t prev_offset,
*/
if (!reserved && !swap_reserve_by_cred(ptoa(next_size),
prev_object->cred)) {
+ VM_OBJECT_WUNLOCK(prev_object);
return (FALSE);
}
prev_object->charge += ptoa(next_size);
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 7d7609c..5fa1f80 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -759,6 +759,22 @@ vm_page_trysbusy(vm_page_t m)
}
}
+static void
+vm_page_xunbusy_maybelocked(vm_page_t m)
+{
+ bool lockacq;
+
+ vm_page_assert_xbusied(m);
+
+ lockacq = !mtx_owned(vm_page_lockptr(m));
+ if (lockacq)
+ vm_page_lock(m);
+ vm_page_flash(m);
+ atomic_store_rel_int(&m->busy_lock, VPB_UNBUSIED);
+ if (lockacq)
+ vm_page_unlock(m);
+}
+
/*
* vm_page_xunbusy_hard:
*
@@ -1096,8 +1112,6 @@ static int
vm_page_insert_after(vm_page_t m, vm_object_t object, vm_pindex_t pindex,
vm_page_t mpred)
{
- vm_pindex_t sidx;
- vm_object_t sobj;
vm_page_t msucc;
VM_OBJECT_ASSERT_WLOCKED(object);
@@ -1118,8 +1132,6 @@ vm_page_insert_after(vm_page_t m, vm_object_t object, vm_pindex_t pindex,
/*
* Record the object/offset pair in this page
*/
- sobj = m->object;
- sidx = m->pindex;
m->object = object;
m->pindex = pindex;
@@ -1127,8 +1139,8 @@ vm_page_insert_after(vm_page_t m, vm_object_t object, vm_pindex_t pindex,
* Now link into the object's ordered list of backed pages.
*/
if (vm_radix_insert(&object->rtree, m)) {
- m->object = sobj;
- m->pindex = sidx;
+ m->object = NULL;
+ m->pindex = 0;
return (1);
}
vm_page_insert_radixdone(m, object, mpred);
@@ -1197,25 +1209,14 @@ void
vm_page_remove(vm_page_t m)
{
vm_object_t object;
- boolean_t lockacq;
if ((m->oflags & VPO_UNMANAGED) == 0)
- vm_page_lock_assert(m, MA_OWNED);
+ vm_page_assert_locked(m);
if ((object = m->object) == NULL)
return;
VM_OBJECT_ASSERT_WLOCKED(object);
- if (vm_page_xbusied(m)) {
- lockacq = FALSE;
- if ((m->oflags & VPO_UNMANAGED) != 0 &&
- !mtx_owned(vm_page_lockptr(m))) {
- lockacq = TRUE;
- vm_page_lock(m);
- }
- vm_page_flash(m);
- atomic_store_rel_int(&m->busy_lock, VPB_UNBUSIED);
- if (lockacq)
- vm_page_unlock(m);
- }
+ if (vm_page_xbusied(m))
+ vm_page_xunbusy_maybelocked(m);
/*
* Now remove from the object's list of backed pages.
@@ -1340,7 +1341,7 @@ vm_page_replace(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex)
TAILQ_REMOVE(&object->memq, mold, listq);
mold->object = NULL;
- vm_page_xunbusy(mold);
+ vm_page_xunbusy_maybelocked(mold);
/*
* The object's resident_page_count does not change because we have
@@ -1747,6 +1748,7 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
}
m->object = NULL;
m->oflags = VPO_UNMANAGED;
+ m->busy_lock = VPB_UNBUSIED;
vm_page_free(m);
return (NULL);
}
@@ -1948,6 +1950,7 @@ retry:
m->object = NULL;
m->oflags |= VPO_UNMANAGED;
}
+ m->busy_lock = VPB_UNBUSIED;
vm_page_free(m);
}
return (NULL);
diff --git a/sys/x86/include/_align.h b/sys/x86/include/_align.h
index 0d0981b..9f7b6b9 100644
--- a/sys/x86/include/_align.h
+++ b/sys/x86/include/_align.h
@@ -46,7 +46,7 @@
* for all data types (int, long, ...). The result is unsigned int
* and must be cast to any desired pointer type.
*/
-#define _ALIGNBYTES (sizeof(register_t) - 1)
-#define _ALIGN(p) (((uintptr_t)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
+#define _ALIGNBYTES (sizeof(__register_t) - 1)
+#define _ALIGN(p) (((__uintptr_t)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
#endif /* !_X86_INCLUDE__ALIGN_H_ */
diff --git a/sys/x86/include/_stdint.h b/sys/x86/include/_stdint.h
index d9ee316..c350534 100644
--- a/sys/x86/include/_stdint.h
+++ b/sys/x86/include/_stdint.h
@@ -40,6 +40,8 @@
#ifndef _MACHINE__STDINT_H_
#define _MACHINE__STDINT_H_
+#include <machine/_limits.h>
+
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
#define INT8_C(c) (c)
@@ -167,8 +169,8 @@
#define PTRDIFF_MAX INT64_MAX
/* Limits of sig_atomic_t. */
-#define SIG_ATOMIC_MIN LONG_MIN
-#define SIG_ATOMIC_MAX LONG_MAX
+#define SIG_ATOMIC_MIN __LONG_MIN
+#define SIG_ATOMIC_MAX __LONG_MAX
/* Limit of size_t. */
#define SIZE_MAX UINT64_MAX
diff --git a/sys/x86/include/_types.h b/sys/x86/include/_types.h
index b130be3..e6d1f60 100644
--- a/sys/x86/include/_types.h
+++ b/sys/x86/include/_types.h
@@ -43,6 +43,8 @@
#error this file needs sys/cdefs.h as a prerequisite
#endif
+#include <machine/_limits.h>
+
#define __NO_STRICT_ALIGNMENT
/*
diff --git a/sys/x86/include/apicvar.h b/sys/x86/include/apicvar.h
index 4326cac..1ddb69e 100644
--- a/sys/x86/include/apicvar.h
+++ b/sys/x86/include/apicvar.h
@@ -455,7 +455,6 @@ void lapic_handle_cmc(void);
void lapic_handle_error(void);
void lapic_handle_intr(int vector, struct trapframe *frame);
void lapic_handle_timer(struct trapframe *frame);
-void hv_vector_handler(struct trapframe *frame);
extern int x2apic_mode;
extern int lapic_eoi_suppression;
diff --git a/sys/xen/error.h b/sys/xen/error.h
index 66468bd..6f25b0a 100644
--- a/sys/xen/error.h
+++ b/sys/xen/error.h
@@ -29,130 +29,7 @@
#ifndef __XEN_ERROR_H__
#define __XEN_ERROR_H__
-/* List of Xen error codes */
-#define XEN_EPERM 1 /* Operation not permitted */
-#define XEN_ENOENT 2 /* No such file or directory */
-#define XEN_ESRCH 3 /* No such process */
-#define XEN_EINTR 4 /* Interrupted system call */
-#define XEN_EIO 5 /* I/O error */
-#define XEN_ENXIO 6 /* No such device or address */
-#define XEN_E2BIG 7 /* Arg list too long */
-#define XEN_ENOEXEC 8 /* Exec format error */
-#define XEN_EBADF 9 /* Bad file number */
-#define XEN_ECHILD 10 /* No child processes */
-#define XEN_EAGAIN 11 /* Try again */
-#define XEN_ENOMEM 12 /* Out of memory */
-#define XEN_EACCES 13 /* Permission denied */
-#define XEN_EFAULT 14 /* Bad address */
-#define XEN_ENOTBLK 15 /* Block device required */
-#define XEN_EBUSY 16 /* Device or resource busy */
-#define XEN_EEXIST 17 /* File exists */
-#define XEN_EXDEV 18 /* Cross-device link */
-#define XEN_ENODEV 19 /* No such device */
-#define XEN_ENOTDIR 20 /* Not a directory */
-#define XEN_EISDIR 21 /* Is a directory */
-#define XEN_EINVAL 22 /* Invalid argument */
-#define XEN_ENFILE 23 /* File table overflow */
-#define XEN_EMFILE 24 /* Too many open files */
-#define XEN_ENOTTY 25 /* Not a typewriter */
-#define XEN_ETXTBSY 26 /* Text file busy */
-#define XEN_EFBIG 27 /* File too large */
-#define XEN_ENOSPC 28 /* No space left on device */
-#define XEN_ESPIPE 29 /* Illegal seek */
-#define XEN_EROFS 30 /* Read-only file system */
-#define XEN_EMLINK 31 /* Too many links */
-#define XEN_EPIPE 32 /* Broken pipe */
-#define XEN_EDOM 33 /* Math argument out of domain of func */
-#define XEN_ERANGE 34 /* Math result not representable */
-#define XEN_EDEADLK 35 /* Resource deadlock would occur */
-#define XEN_ENAMETOOLONG 36 /* File name too long */
-#define XEN_ENOLCK 37 /* No record locks available */
-#define XEN_ENOSYS 38 /* Function not implemented */
-#define XEN_ENOTEMPTY 39 /* Directory not empty */
-#define XEN_ELOOP 40 /* Too many symbolic links encountered */
-#define XEN_ENOMSG 42 /* No message of desired type */
-#define XEN_EIDRM 43 /* Identifier removed */
-#define XEN_ECHRNG 44 /* Channel number out of range */
-#define XEN_EL2NSYNC 45 /* Level 2 not synchronized */
-#define XEN_EL3HLT 46 /* Level 3 halted */
-#define XEN_EL3RST 47 /* Level 3 reset */
-#define XEN_ELNRNG 48 /* Link number out of range */
-#define XEN_EUNATCH 49 /* Protocol driver not attached */
-#define XEN_ENOCSI 50 /* No CSI structure available */
-#define XEN_EL2HLT 51 /* Level 2 halted */
-#define XEN_EBADE 52 /* Invalid exchange */
-#define XEN_EBADR 53 /* Invalid request descriptor */
-#define XEN_EXFULL 54 /* Exchange full */
-#define XEN_ENOANO 55 /* No anode */
-#define XEN_EBADRQC 56 /* Invalid request code */
-#define XEN_EBADSLT 57 /* Invalid slot */
-#define XEN_EBFONT 59 /* Bad font file format */
-#define XEN_ENOSTR 60 /* Device not a stream */
-#define XEN_ENODATA 61 /* No data available */
-#define XEN_ETIME 62 /* Timer expired */
-#define XEN_ENOSR 63 /* Out of streams resources */
-#define XEN_ENONET 64 /* Machine is not on the network */
-#define XEN_ENOPKG 65 /* Package not installed */
-#define XEN_EREMOTE 66 /* Object is remote */
-#define XEN_ENOLINK 67 /* Link has been severed */
-#define XEN_EADV 68 /* Advertise error */
-#define XEN_ESRMNT 69 /* Srmount error */
-#define XEN_ECOMM 70 /* Communication error on send */
-#define XEN_EPROTO 71 /* Protocol error */
-#define XEN_EMULTIHOP 72 /* Multihop attempted */
-#define XEN_EDOTDOT 73 /* RFS specific error */
-#define XEN_EBADMSG 74 /* Not a data message */
-#define XEN_EOVERFLOW 75 /* Value too large for defined data type */
-#define XEN_ENOTUNIQ 76 /* Name not unique on network */
-#define XEN_EBADFD 77 /* File descriptor in bad state */
-#define XEN_EREMCHG 78 /* Remote address changed */
-#define XEN_ELIBACC 79 /* Can not access a needed shared library */
-#define XEN_ELIBBAD 80 /* Accessing a corrupted shared library */
-#define XEN_ELIBSCN 81 /* .lib section in a.out corrupted */
-#define XEN_ELIBMAX 82 /* Attempting to link in too many shared libraries */
-#define XEN_ELIBEXEC 83 /* Cannot exec a shared library directly */
-#define XEN_EILSEQ 84 /* Illegal byte sequence */
-#define XEN_ERESTART 85 /* Interrupted system call should be restarted */
-#define XEN_ESTRPIPE 86 /* Streams pipe error */
-#define XEN_EUSERS 87 /* Too many users */
-#define XEN_ENOTSOCK 88 /* Socket operation on non-socket */
-#define XEN_EDESTADDRREQ 89 /* Destination address required */
-#define XEN_EMSGSIZE 90 /* Message too long */
-#define XEN_EPROTOTYPE 91 /* Protocol wrong type for socket */
-#define XEN_ENOPROTOOPT 92 /* Protocol not available */
-#define XEN_EPROTONOSUPPORT 93 /* Protocol not supported */
-#define XEN_ESOCKTNOSUPPORT 94 /* Socket type not supported */
-#define XEN_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
-#define XEN_EPFNOSUPPORT 96 /* Protocol family not supported */
-#define XEN_EAFNOSUPPORT 97 /* Address family not supported by protocol */
-#define XEN_EADDRINUSE 98 /* Address already in use */
-#define XEN_EADDRNOTAVAIL 99 /* Cannot assign requested address */
-#define XEN_ENETDOWN 100 /* Network is down */
-#define XEN_ENETUNREACH 101 /* Network is unreachable */
-#define XEN_ENETRESET 102 /* Network dropped connection because of reset */
-#define XEN_ECONNABORTED 103 /* Software caused connection abort */
-#define XEN_ECONNRESET 104 /* Connection reset by peer */
-#define XEN_ENOBUFS 105 /* No buffer space available */
-#define XEN_EISCONN 106 /* Transport endpoint is already connected */
-#define XEN_ENOTCONN 107 /* Transport endpoint is not connected */
-#define XEN_ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
-#define XEN_ETOOMANYREFS 109 /* Too many references: cannot splice */
-#define XEN_ETIMEDOUT 110 /* Connection timed out */
-#define XEN_ECONNREFUSED 111 /* Connection refused */
-#define XEN_EHOSTDOWN 112 /* Host is down */
-#define XEN_EHOSTUNREACH 113 /* No route to host */
-#define XEN_EALREADY 114 /* Operation already in progress */
-#define XEN_EINPROGRESS 115 /* Operation now in progress */
-#define XEN_ESTALE 116 /* Stale NFS file handle */
-#define XEN_EUCLEAN 117 /* Structure needs cleaning */
-#define XEN_ENOTNAM 118 /* Not a XENIX named type file */
-#define XEN_ENAVAIL 119 /* No XENIX semaphores available */
-#define XEN_EISNAM 120 /* Is a named type file */
-#define XEN_EREMOTEIO 121 /* Remote I/O error */
-#define XEN_EDQUOT 122 /* Quota exceeded */
-
-#define XEN_ENOMEDIUM 123 /* No medium found */
-#define XEN_EMEDIUMTYPE 124 /* Wrong medium type */
+#include <xen/interface/errno.h>
/* Translation table */
static int xen_errors[] =
@@ -160,7 +37,6 @@ static int xen_errors[] =
[XEN_EPERM] = EPERM,
[XEN_ENOENT] = ENOENT,
[XEN_ESRCH] = ESRCH,
- [XEN_EINTR] = EINTR,
[XEN_EIO] = EIO,
[XEN_ENXIO] = ENXIO,
[XEN_E2BIG] = E2BIG,
@@ -171,114 +47,34 @@ static int xen_errors[] =
[XEN_ENOMEM] = ENOMEM,
[XEN_EACCES] = EACCES,
[XEN_EFAULT] = EFAULT,
- [XEN_ENOTBLK] = ENOTBLK,
[XEN_EBUSY] = EBUSY,
[XEN_EEXIST] = EEXIST,
[XEN_EXDEV] = EXDEV,
[XEN_ENODEV] = ENODEV,
- [XEN_ENOTDIR] = ENOTDIR,
- [XEN_EISDIR] = EISDIR,
[XEN_EINVAL] = EINVAL,
[XEN_ENFILE] = ENFILE,
[XEN_EMFILE] = EMFILE,
- [XEN_ENOTTY] = ENOTTY,
- [XEN_ETXTBSY] = ETXTBSY,
- [XEN_EFBIG] = EFBIG,
[XEN_ENOSPC] = ENOSPC,
- [XEN_ESPIPE] = ESPIPE,
- [XEN_EROFS] = EROFS,
[XEN_EMLINK] = EMLINK,
- [XEN_EPIPE] = EPIPE,
[XEN_EDOM] = EDOM,
[XEN_ERANGE] = ERANGE,
[XEN_EDEADLK] = EDEADLK,
[XEN_ENAMETOOLONG] = ENAMETOOLONG,
[XEN_ENOLCK] = ENOLCK,
[XEN_ENOSYS] = ENOSYS,
- [XEN_ENOTEMPTY] = ENOTEMPTY,
- [XEN_ELOOP] = ELOOP,
- [XEN_ENOMSG] = ENOMSG,
- [XEN_EIDRM] = EIDRM,
- [XEN_ECHRNG] = ERANGE,
- [XEN_EL2NSYNC] = EFAULT,
- [XEN_EL3HLT] = EFAULT,
- [XEN_EL3RST] = EFAULT,
- [XEN_ELNRNG] = ERANGE,
- [XEN_EUNATCH] = ENODEV,
- [XEN_ENOCSI] = ENODEV,
- [XEN_EL2HLT] = EFAULT,
- [XEN_EBADE] = ERANGE,
- [XEN_EBADR] = EINVAL,
- [XEN_EXFULL] = ENOBUFS,
- [XEN_ENOANO] = EINVAL,
- [XEN_EBADRQC] = EINVAL,
- [XEN_EBADSLT] = EINVAL,
- [XEN_EBFONT] = EFAULT,
- [XEN_ENOSTR] = EINVAL,
[XEN_ENODATA] = ENOENT,
[XEN_ETIME] = ETIMEDOUT,
- [XEN_ENOSR] = EFAULT,
- [XEN_ENONET] = ENETDOWN,
- [XEN_ENOPKG] = EINVAL,
- [XEN_EREMOTE] = EREMOTE,
- [XEN_ENOLINK] = ENOLINK,
- [XEN_EADV] = EFAULT,
- [XEN_ESRMNT] = EFAULT,
- [XEN_ECOMM] = EFAULT,
- [XEN_EPROTO] = EPROTO,
- [XEN_EMULTIHOP] = EMULTIHOP,
- [XEN_EDOTDOT] = EFAULT,
[XEN_EBADMSG] = EBADMSG,
[XEN_EOVERFLOW] = EOVERFLOW,
- [XEN_ENOTUNIQ] = EADDRINUSE,
- [XEN_EBADFD] = EBADF,
- [XEN_EREMCHG] = EHOSTDOWN,
- [XEN_ELIBACC] = EFAULT,
- [XEN_ELIBBAD] = EFAULT,
- [XEN_ELIBSCN] = EFAULT,
- [XEN_ELIBMAX] = EFAULT,
- [XEN_ELIBEXEC] = EFAULT,
[XEN_EILSEQ] = EILSEQ,
- [XEN_ERESTART] = EAGAIN,
- [XEN_ESTRPIPE] = EPIPE,
- [XEN_EUSERS] = EUSERS,
[XEN_ENOTSOCK] = ENOTSOCK,
- [XEN_EDESTADDRREQ] = EDESTADDRREQ,
- [XEN_EMSGSIZE] = EMSGSIZE,
- [XEN_EPROTOTYPE] = EPROTOTYPE,
- [XEN_ENOPROTOOPT] = ENOPROTOOPT,
- [XEN_EPROTONOSUPPORT] = EPROTONOSUPPORT,
- [XEN_ESOCKTNOSUPPORT] = ESOCKTNOSUPPORT,
[XEN_EOPNOTSUPP] = EOPNOTSUPP,
- [XEN_EPFNOSUPPORT] = EPFNOSUPPORT,
- [XEN_EAFNOSUPPORT] = EAFNOSUPPORT,
[XEN_EADDRINUSE] = EADDRINUSE,
[XEN_EADDRNOTAVAIL] = EADDRNOTAVAIL,
- [XEN_ENETDOWN] = ENETDOWN,
- [XEN_ENETUNREACH] = ENETUNREACH,
- [XEN_ENETRESET] = ENETRESET,
- [XEN_ECONNABORTED] = ECONNABORTED,
- [XEN_ECONNRESET] = ECONNRESET,
[XEN_ENOBUFS] = ENOBUFS,
[XEN_EISCONN] = EISCONN,
[XEN_ENOTCONN] = ENOTCONN,
- [XEN_ESHUTDOWN] = ESHUTDOWN,
- [XEN_ETOOMANYREFS] = ETOOMANYREFS,
[XEN_ETIMEDOUT] = ETIMEDOUT,
- [XEN_ECONNREFUSED] = ECONNREFUSED,
- [XEN_EHOSTDOWN] = EHOSTDOWN,
- [XEN_EHOSTUNREACH] = EHOSTUNREACH,
- [XEN_EALREADY] = EALREADY,
- [XEN_EINPROGRESS] = EINPROGRESS,
- [XEN_ESTALE] = ESTALE,
- [XEN_EUCLEAN] = EFAULT,
- [XEN_ENOTNAM] = EFAULT,
- [XEN_ENAVAIL] = EFAULT,
- [XEN_EISNAM] = EFAULT,
- [XEN_EREMOTEIO] = EIO,
- [XEN_EDQUOT] = EDQUOT,
- [XEN_ENOMEDIUM] = ENOENT,
- [XEN_EMEDIUMTYPE] = ENOENT,
};
static inline int
diff --git a/sys/xen/gnttab.h b/sys/xen/gnttab.h
index 9e82124..eb33dd6 100644
--- a/sys/xen/gnttab.h
+++ b/sys/xen/gnttab.h
@@ -35,6 +35,7 @@
*/
#ifndef __ASM_GNTTAB_H__
+#define __ASM_GNTTAB_H__
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 6343ec6..68ab86b 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -12,6 +12,33 @@ OLD_FILES+=usr/sbin/accton
OLD_FILES+=usr/sbin/sa
OLD_FILES+=usr/share/man/man8/accton.8.gz
OLD_FILES+=usr/share/man/man8/sa.8.gz
+OLD_FILES+=usr/tests/usr.sbin/sa/Kyuafile
+OLD_FILES+=usr/tests/usr.sbin/sa/legacy_test
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-amd64-sav.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-amd64-sav.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-amd64-u.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-amd64-usr.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-amd64-usr.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-i386-sav.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-i386-sav.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-i386-u.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-i386-usr.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-i386-usr.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-sparc64-sav.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-sparc64-sav.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-sparc64-u.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-sparc64-usr.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v1-sparc64-usr.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-amd64-sav.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-amd64-u.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-amd64-usr.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-i386-sav.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-i386-u.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-i386-usr.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-sparc64-sav.in
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-sparc64-u.out
+OLD_FILES+=usr/tests/usr.sbin/sa/v2-sparc64-usr.in
+OLD_FILES+=usr/tests/usr.sbin/sa
.endif
.if ${MK_ACPI} == no
@@ -404,6 +431,26 @@ OLD_FILES+=usr/share/man/man7/ldint.7.gz
OLD_FILES+=usr/share/man/man7/binutils.7.gz
.endif
+.if ${MK_BLACKLIST_SUPPORT} == no
+OLD_FILES+=etc/rc.d/blacklistd
+OLD_FILES+=usr/include/blacklist.h
+OLD_FILES+=usr/lib/libblacklist.a
+OLD_FILES+=usr/lib/libblacklist_p.a
+OLD_FILES+=usr/lib/libblacklist.so
+OLD_LIBS+=usr/lib/libblacklist.so.0
+OLD_FILES+=usr/libexec/blacklistd-helper
+OLD_FILES+=usr/sbin/blacklistctl
+OLD_FILES+=usr/sbin/blacklistd
+OLD_FILES+=usr/share/man/man3/blacklist.3.gz
+OLD_FILES+=usr/share/man/man3/blacklist_close.3.gz
+OLD_FILES+=usr/share/man/man3/blacklist_open.3.gz
+OLD_FILES+=usr/share/man/man3/blacklist_r.3.gz
+OLD_FILES+=usr/share/man/man3/blacklist_sa.3.gz
+OLD_FILES+=usr/share/man/man3/blacklist_sa_r.3.gz
+OLD_FILES+=usr/share/man/man8/blacklistctl.8.gz
+OLD_FILES+=usr/share/man/man8/blacklistd.8.gz
+.endif
+
.if ${MK_BLUETOOTH} == no
OLD_FILES+=etc/bluetooth/hcsecd.conf
OLD_FILES+=etc/bluetooth/hosts
@@ -851,6 +898,39 @@ OLD_FILES+=usr/share/calendar/uk_UA.KOI8-U/calendar.orthodox
OLD_DIRS+=usr/share/calendar/uk_UA.KOI8-U
OLD_DIRS+=usr/share/calendar
OLD_FILES+=usr/share/man/man1/calendar.1.gz
+OLD_FILES+=usr/tests/usr.bin/calendar/Kyuafile
+OLD_FILES+=usr/tests/usr.bin/calendar/calendar.calibrate
+OLD_FILES+=usr/tests/usr.bin/calendar/legacy_test
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.a1.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.a2.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.a3.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.a4.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.a5.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.b1.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.b2.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.b3.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.b4.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.b5.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.s1.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.s2.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.s3.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.s4.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.sh
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-1.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-2.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-3.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-4.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-5.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-6.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.w0-7.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-1.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-2.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-3.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-4.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-5.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-6.out
+OLD_FILES+=usr/tests/usr.bin/calendar/regress.wn-7.out
+OLD_DIRS+=usr/tests/usr.bin/calendar
.endif
.if ${MK_CASPER} == no
@@ -6759,6 +6839,15 @@ OLD_FILES+=usr/share/man/man1/rcsmerge.1.gz
OLD_FILES+=usr/share/man/man1/rlog.1.gz
OLD_FILES+=usr/share/man/man5/rcsfile.5.gz
OLD_FILES+=usr/share/man/man8/etcupdate.8.gz
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/Kyuafile
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/always_test
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/conflicts_test
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/fbsdid_test
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/ignore_test
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/preworld_test
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/tests_test
+OLD_FILES+=usr/tests/usr.sbin/etcupdate/tzsetup_test
+OLD_DIRS+=usr/tests/usr.sbin/etcupdate
.endif
#.if ${MK_RESCUE} == no
@@ -7940,6 +8029,7 @@ OLD_FILES+=usr/share/man/man1/ul.1.gz
.if ${MK_TOOLCHAIN} == no
OLD_FILES+=usr/bin/addr2line
OLD_FILES+=usr/bin/as
+OLD_FILES+=usr/bin/byacc
OLD_FILES+=usr/bin/cc
OLD_FILES+=usr/bin/c88
OLD_FILES+=usr/bin/c++
@@ -7951,6 +8041,7 @@ OLD_FILES+=usr/bin/readelf
OLD_FILES+=usr/bin/size
OLD_FILES+=usr/bin/strings
OLD_FILES+=usr/bin/strip
+OLD_FILES+=usr/bin/yacc
OLD_FILES+=usr/share/man/man1/addr2line.1.gz
OLD_FILES+=usr/share/man/man1/c++filt.1.gz
OLD_FILES+=usr/share/man/man1/nm.1.gz
@@ -7962,6 +8053,314 @@ OLD_FILES+=usr/share/man/man1/strip.1.gz
OLD_FILES+=usr/bin/objcopy
OLD_FILES+=usr/share/man/man1/objcopy.1.gz
.endif
+OLD_FILES+=usr/tests/usr.bin/yacc/Kyuafile
+OLD_FILES+=usr/tests/usr.bin/yacc/btyacc_calc1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/btyacc_demo.y
+OLD_FILES+=usr/tests/usr.bin/yacc/calc.y
+OLD_FILES+=usr/tests/usr.bin/yacc/calc1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/calc2.y
+OLD_FILES+=usr/tests/usr.bin/yacc/calc3.y
+OLD_FILES+=usr/tests/usr.bin/yacc/code_calc.y
+OLD_FILES+=usr/tests/usr.bin/yacc/code_debug.y
+OLD_FILES+=usr/tests/usr.bin/yacc/code_error.y
+OLD_FILES+=usr/tests/usr.bin/yacc/empty.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_inherit1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_inherit2.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_inherit3.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_inherit4.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_inherit5.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax10.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax11.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax12.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax13.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax14.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax15.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax16.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax17.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax18.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax19.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax2.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax20.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax21.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax22.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax23.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax24.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax25.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax26.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax27.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax3.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax4.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax5.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax6.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax7.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax7a.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax7b.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax8.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax8a.y
+OLD_FILES+=usr/tests/usr.bin/yacc/err_syntax9.y
+OLD_FILES+=usr/tests/usr.bin/yacc/error.y
+OLD_FILES+=usr/tests/usr.bin/yacc/grammar.y
+OLD_FILES+=usr/tests/usr.bin/yacc/inherit0.y
+OLD_FILES+=usr/tests/usr.bin/yacc/inherit1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/inherit2.y
+OLD_FILES+=usr/tests/usr.bin/yacc/ok_syntax1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/pure_calc.y
+OLD_FILES+=usr/tests/usr.bin/yacc/pure_error.y
+OLD_FILES+=usr/tests/usr.bin/yacc/quote_calc.y
+OLD_FILES+=usr/tests/usr.bin/yacc/quote_calc2.y
+OLD_FILES+=usr/tests/usr.bin/yacc/quote_calc3.y
+OLD_FILES+=usr/tests/usr.bin/yacc/quote_calc4.y
+OLD_FILES+=usr/tests/usr.bin/yacc/run_test
+OLD_FILES+=usr/tests/usr.bin/yacc/varsyntax_calc1.y
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/big_b.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/big_b.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/big_l.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/big_l.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc1.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc1.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc2.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc2.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc2.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc2.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc3.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc3.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc3.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/calc3.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_calc.code.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_calc.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_calc.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_calc.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_calc.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_error.code.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_error.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_error.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_error.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/code_error.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/empty.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/empty.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/empty.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/empty.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax1.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax1.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax10.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax10.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax10.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax10.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax11.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax11.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax11.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax11.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax12.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax12.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax12.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax12.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax13.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax13.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax13.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax13.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax14.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax14.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax14.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax14.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax15.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax15.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax15.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax15.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax16.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax16.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax16.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax16.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax17.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax17.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax17.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax17.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax18.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax18.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax18.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax18.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax19.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax19.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax19.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax19.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax2.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax2.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax2.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax2.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax20.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax20.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax20.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax20.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax21.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax21.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax21.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax21.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax22.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax22.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax22.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax22.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax23.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax23.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax23.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax23.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax24.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax24.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax24.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax24.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax25.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax25.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax25.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax25.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax26.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax26.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax26.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax26.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax27.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax27.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax27.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax27.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax3.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax3.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax3.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax3.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax4.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax4.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax4.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax4.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax5.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax5.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax5.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax5.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax6.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax6.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax6.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax6.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7a.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7a.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7a.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7a.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7b.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7b.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7b.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax7b.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8a.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8a.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8a.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax8a.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax9.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax9.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax9.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/err_syntax9.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/error.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/error.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/error.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/error.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/grammar.dot
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/grammar.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/grammar.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/grammar.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/grammar.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/help.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/help.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_b_opt.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_b_opt.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_b_opt1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_b_opt1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_code_c.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_code_c.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_defines.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_defines.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_graph.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_graph.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_include.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_include.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_opts.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_opts.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_output.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_output.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_output1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_output1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_output2.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_output2.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_p_opt.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_p_opt.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_p_opt1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_p_opt1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_verbose.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/no_verbose.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/nostdin.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/nostdin.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/ok_syntax1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/ok_syntax1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/ok_syntax1.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/ok_syntax1.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_calc.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_calc.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_calc.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_calc.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_error.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_error.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_error.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/pure_error.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc-s.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc-s.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc-s.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc-s.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2-s.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2-s.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2-s.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2-s.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc2.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3-s.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3-s.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3-s.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3-s.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc3.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4-s.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4-s.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4-s.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4-s.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/quote_calc4.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/rename_debug.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/rename_debug.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/rename_debug.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/rename_debug.i
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/rename_debug.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/varsyntax_calc1.error
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/varsyntax_calc1.output
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/varsyntax_calc1.tab.c
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc/varsyntax_calc1.tab.h
+OLD_FILES+=usr/tests/usr.bin/yacc/yacc_tests
+OLD_DIRS+=usr/tests/usr.bin/yacc
.endif
.if ${MK_TOOLCHAIN} == no || ${MK_ELFCOPY_AS_OBJCOPY} != no
OLD_FILES+=usr/bin/elfcopy
diff --git a/tools/tools/locale/tools/cldr2def.pl b/tools/tools/locale/tools/cldr2def.pl
index da94036..2dbdf2c 100755
--- a/tools/tools/locale/tools/cldr2def.pl
+++ b/tools/tools/locale/tools/cldr2def.pl
@@ -5,6 +5,7 @@ use strict;
use File::Copy;
use XML::Parser;
use Tie::IxHash;
+use Text::Iconv;
use Data::Dumper;
use Getopt::Long;
use Digest::SHA qw(sha1_hex);
@@ -69,6 +70,7 @@ my %callback = (
cformat => \&callback_cformat,
dtformat => \&callback_dtformat,
cbabmon => \&callback_abmon,
+ cbampm => \&callback_ampm,
data => undef,
);
@@ -183,7 +185,7 @@ if ($TYPE eq "timedef") {
"t_fmt" => "s",
"d_fmt" => "s",
"c_fmt" => "<cformat<d_t_fmt<s",
- "am_pm" => "as",
+ "am_pm" => "<cbampm<am_pm<as",
"d_fmt" => "s",
"d_t_fmt" => "<dtformat<d_t_fmt<s",
"altmon" => "<altmon<mon<as",
@@ -195,20 +197,44 @@ if ($TYPE eq "timedef") {
make_makefile();
}
+sub callback_ampm {
+ my $s = shift;
+ my $nl = $callback{data}{l} . "_" . $callback{data}{c};
+ my $enc = $callback{data}{e};
+ my $converter = Text::Iconv->new("utf-8", "$enc");
+
+ if ($nl eq 'ru_RU') {
+ if ($enc eq 'UTF-8') {
+ $s = 'дп;пп';
+ } else {
+ $s = $converter->convert("дп;пп");
+ }
+ }
+ return $s;
+}
+
sub callback_cformat {
- my $s = shift;
- $s =~ s/ %Z//;
- $s =~ s/ %z//;
- return $s;
+ my $s = shift;
+ my $nl = $callback{data}{l} . "_" . $callback{data}{c};
+
+ $s =~ s/\.,/\./;
+ $s =~ s/ %Z//;
+ $s =~ s/ %z//;
+ $s =~ s/^"(%B %e, )/"%A, $1/;
+ $s =~ s/^"(%e %B )/"%A $1/;
+ return $s;
};
sub callback_dtformat {
- my $s = shift;
+ my $s = shift;
my $nl = $callback{data}{l} . "_" . $callback{data}{c};
if ($nl eq 'ja_JP') {
- $s =~ s/(> )(%H)/$1%A $2/;
+ $s =~ s/(> )(%H)/$1%A $2/;
}
+ $s =~ s/\.,/\./;
+ $s =~ s/^"(%B %e, )/"%A, $1/;
+ $s =~ s/^"(%e %B )/"%A $1/;
return $s;
};
diff --git a/usr.bin/iscsictl/iscsi.conf.5 b/usr.bin/iscsictl/iscsi.conf.5
index be543e4..6d80392 100644
--- a/usr.bin/iscsictl/iscsi.conf.5
+++ b/usr.bin/iscsictl/iscsi.conf.5
@@ -125,6 +125,14 @@ must be defined.
Discovery sessions result in the initiator connecting to all the targets
returned by SendTargets iSCSI discovery with the defined
.Sy TargetAddress .
+.It Cm Enable
+Enable or disable the session.
+State can be either
+.Qq Ar On ,
+or
+.Qq Ar Off .
+Default is
+.Qq Ar On .
.It Cm Offload
Name of selected iSCSI hardware offload driver.
Default is
diff --git a/usr.bin/iscsictl/iscsictl.8 b/usr.bin/iscsictl/iscsictl.8
index 8c1b0ad..7360e6a 100644
--- a/usr.bin/iscsictl/iscsictl.8
+++ b/usr.bin/iscsictl/iscsictl.8
@@ -40,11 +40,13 @@
.Op Fl u Ar user Fl s Ar secret
.Op Fl w Ar timeout
.Op Fl r
+.Op Fl e Cm on | off
.Nm
.Fl A
.Fl d Ar discovery-host
.Op Fl u Ar user Fl s Ar secret
.Op Fl r
+.Op Fl e Cm on | off
.Nm
.Fl A
.Fl a Op Fl c Ar path
@@ -58,6 +60,7 @@
.Op Fl t Ar target
.Op Fl u Ar user
.Op Fl s Ar secret
+.Op Fl e Cm on | off
.Nm
.Fl M
.Fl i Ar session-id
@@ -110,6 +113,10 @@ Target host name or address used for SendTargets discovery.
When used, it will add a temporary discovery session.
After discovery is done, sessions will be added for each discovered target,
and the temporary discovery session will be removed.
+.It Fl e
+Enable or disable the session.
+This is ignored for discovery sessions, but gets passed down to normal
+sessions they add.
.It Fl i
Session ID, as displayed by
.Nm
@@ -189,6 +196,12 @@ utility exits 0 on success, and >0 if an error occurs.
Attach to target iqn.2012-06.com.example:target0, served by 192.168.1.1:
.Dl Nm Fl A Fl t Ar iqn.2012-06.com.example:target0 Fl p Ar 192.168.1.1
.Pp
+Perform discovery on 192.168.1.1, and add disabled sessions for each
+discovered target; use
+.Nm -M -e on
+to connect them:
+.Dl Nm Fl A Fl d Ar 192.168.1.1 Fl e Ar off
+.Pp
Disconnect all iSCSI sessions:
.Dl Nm Fl Ra
.Sh SEE ALSO
diff --git a/usr.bin/iscsictl/iscsictl.c b/usr.bin/iscsictl/iscsictl.c
index 840ee6c..fd05db3 100644
--- a/usr.bin/iscsictl/iscsictl.c
+++ b/usr.bin/iscsictl/iscsictl.c
@@ -98,7 +98,6 @@ target_delete(struct target *targ)
free(targ);
}
-
static char *
default_initiator_name(void)
{
@@ -152,6 +151,23 @@ valid_hex(const char ch)
}
}
+int
+parse_enable(const char *enable)
+{
+ if (enable == NULL)
+ return (ENABLE_UNSPECIFIED);
+
+ if (strcasecmp(enable, "on") == 0 ||
+ strcasecmp(enable, "yes") == 0)
+ return (ENABLE_ON);
+
+ if (strcasecmp(enable, "off") == 0 ||
+ strcasecmp(enable, "no") == 0)
+ return (ENABLE_OFF);
+
+ return (ENABLE_UNSPECIFIED);
+}
+
bool
valid_iscsi_name(const char *name)
{
@@ -325,6 +341,8 @@ conf_from_target(struct iscsi_session_conf *conf,
sizeof(conf->isc_mutual_secret));
if (targ->t_session_type == SESSION_TYPE_DISCOVERY)
conf->isc_discovery = 1;
+ if (targ->t_enable != ENABLE_OFF)
+ conf->isc_enable = 1;
if (targ->t_protocol == PROTOCOL_ISER)
conf->isc_iser = 1;
if (targ->t_offload != NULL)
@@ -371,7 +389,7 @@ kernel_modify(int iscsi_fd, unsigned int session_id, const struct target *targ)
static void
kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target,
- const char *target_addr, const char *user, const char *secret)
+ const char *target_addr, const char *user, const char *secret, int enable)
{
struct iscsi_session_state *states = NULL;
struct iscsi_session_state *state;
@@ -421,6 +439,10 @@ kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target,
strlcpy(conf->isc_user, user, sizeof(conf->isc_user));
if (secret != NULL)
strlcpy(conf->isc_secret, secret, sizeof(conf->isc_secret));
+ if (enable == ENABLE_ON)
+ conf->isc_enable = 1;
+ else if (enable == ENABLE_OFF)
+ conf->isc_enable = 0;
memset(&ism, 0, sizeof(ism));
ism.ism_session_id = session_id;
@@ -527,6 +549,9 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
xo_emit("{L:/%-18s}{V:type/%s}\n",
"Session type:",
conf->isc_discovery ? "Discovery" : "Normal");
+ xo_emit("{L:/%-18s}{V:enable/%s}\n",
+ "Enable:",
+ conf->isc_enable ? "Yes" : "No");
xo_emit("{L:/%-18s}{V:state/%s}\n",
"Session state:",
state->iss_connected ? "Connected" : "Disconnected");
@@ -575,6 +600,8 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
} else {
if (conf->isc_discovery) {
xo_emit("{V:state}\n", "Discovery");
+ } else if (conf->isc_enable == 0) {
+ xo_emit("{V:state}\n", "Disabled");
} else if (state->iss_connected) {
xo_emit("{V:state}: ", "Connected");
print_periphs(state->iss_id);
@@ -653,13 +680,13 @@ usage(void)
{
fprintf(stderr, "usage: iscsictl -A -p portal -t target "
- "[-u user -s secret] [-w timeout]\n");
+ "[-u user -s secret] [-w timeout] [-e on | off]\n");
fprintf(stderr, " iscsictl -A -d discovery-host "
- "[-u user -s secret]\n");
+ "[-u user -s secret] [-e on | off]\n");
fprintf(stderr, " iscsictl -A -a [-c path]\n");
fprintf(stderr, " iscsictl -A -n nickname [-c path]\n");
fprintf(stderr, " iscsictl -M -i session-id [-p portal] "
- "[-t target] [-u user] [-s secret]\n");
+ "[-t target] [-u user] [-s secret] [-e on | off]\n");
fprintf(stderr, " iscsictl -M -i session-id -n nickname "
"[-c path]\n");
fprintf(stderr, " iscsictl -R [-p portal] [-t target]\n");
@@ -687,8 +714,8 @@ main(int argc, char **argv)
rflag = 0, vflag = 0;
const char *conf_path = DEFAULT_CONFIG_PATH;
char *nickname = NULL, *discovery_host = NULL, *portal = NULL,
- *target = NULL, *user = NULL, *secret = NULL;
- int timeout = -1;
+ *target = NULL, *user = NULL, *secret = NULL;
+ int timeout = -1, enable = ENABLE_UNSPECIFIED;
long long session_id = -1;
char *end;
int ch, error, iscsi_fd, retval, saved_errno;
@@ -699,7 +726,7 @@ main(int argc, char **argv)
argc = xo_parse_args(argc, argv);
xo_open_container("iscsictl");
- while ((ch = getopt(argc, argv, "AMRLac:d:i:n:p:rt:u:s:vw:")) != -1) {
+ while ((ch = getopt(argc, argv, "AMRLac:d:e:i:n:p:rt:u:s:vw:")) != -1) {
switch (ch) {
case 'A':
Aflag = 1;
@@ -722,6 +749,13 @@ main(int argc, char **argv)
case 'd':
discovery_host = optarg;
break;
+ case 'e':
+ enable = parse_enable(optarg);
+ if (enable == ENABLE_UNSPECIFIED) {
+ xo_errx(1, "invalid argument to -e, "
+ "must be either \"on\" or \"off\"");
+ }
+ break;
case 'i':
session_id = strtol(optarg, &end, 10);
if ((size_t)(end - optarg) != strlen(optarg))
@@ -781,6 +815,8 @@ main(int argc, char **argv)
*/
if (Aflag != 0) {
if (aflag != 0) {
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-a and -e and mutually exclusive");
if (portal != NULL)
xo_errx(1, "-a and -p and mutually exclusive");
if (target != NULL)
@@ -796,6 +832,8 @@ main(int argc, char **argv)
if (rflag != 0)
xo_errx(1, "-a and -r and mutually exclusive");
} else if (nickname != NULL) {
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-n and -e and mutually exclusive");
if (portal != NULL)
xo_errx(1, "-n and -p and mutually exclusive");
if (target != NULL)
@@ -837,11 +875,9 @@ main(int argc, char **argv)
if (session_id == -1)
xo_errx(1, "-M requires -i");
- if (discovery_host != NULL)
- xo_errx(1, "-M and -d are mutually exclusive");
- if (aflag != 0)
- xo_errx(1, "-M and -a are mutually exclusive");
if (nickname != NULL) {
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-n and -e and mutually exclusive");
if (portal != NULL)
xo_errx(1, "-n and -p and mutually exclusive");
if (target != NULL)
@@ -852,6 +888,10 @@ main(int argc, char **argv)
xo_errx(1, "-n and -s and mutually exclusive");
}
+ if (aflag != 0)
+ xo_errx(1, "-a cannot be used with -M");
+ if (discovery_host != NULL)
+ xo_errx(1, "-d cannot be used with -M");
if (rflag != 0)
xo_errx(1, "-r cannot be used with -M");
if (vflag != 0)
@@ -860,13 +900,6 @@ main(int argc, char **argv)
xo_errx(1, "-w cannot be used with -M");
} else if (Rflag != 0) {
- if (user != NULL)
- xo_errx(1, "-R and -u are mutually exclusive");
- if (secret != NULL)
- xo_errx(1, "-R and -s are mutually exclusive");
- if (discovery_host != NULL)
- xo_errx(1, "-R and -d are mutually exclusive");
-
if (aflag != 0) {
if (portal != NULL)
xo_errx(1, "-a and -p and mutually exclusive");
@@ -883,10 +916,18 @@ main(int argc, char **argv)
xo_errx(1, "must specify either -a, -n, -t, or -p");
}
+ if (discovery_host != NULL)
+ xo_errx(1, "-d cannot be used with -R");
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-e cannot be used with -R");
if (session_id != -1)
xo_errx(1, "-i cannot be used with -R");
if (rflag != 0)
xo_errx(1, "-r cannot be used with -R");
+ if (user != NULL)
+ xo_errx(1, "-u cannot be used with -R");
+ if (secret != NULL)
+ xo_errx(1, "-s cannot be used with -R");
if (vflag != 0)
xo_errx(1, "-v cannot be used with -R");
if (timeout != -1)
@@ -895,23 +936,22 @@ main(int argc, char **argv)
} else {
assert(Lflag != 0);
+ if (discovery_host != NULL)
+ xo_errx(1, "-d cannot be used with -L");
+ if (session_id != -1)
+ xo_errx(1, "-i cannot be used with -L");
+ if (nickname != NULL)
+ xo_errx(1, "-n cannot be used with -L");
if (portal != NULL)
- xo_errx(1, "-L and -p and mutually exclusive");
+ xo_errx(1, "-p cannot be used with -L");
+ if (rflag != 0)
+ xo_errx(1, "-r cannot be used with -L");
if (target != NULL)
- xo_errx(1, "-L and -t and mutually exclusive");
+ xo_errx(1, "-t cannot be used with -L");
if (user != NULL)
- xo_errx(1, "-L and -u and mutually exclusive");
+ xo_errx(1, "-u cannot be used with -L");
if (secret != NULL)
- xo_errx(1, "-L and -s and mutually exclusive");
- if (nickname != NULL)
- xo_errx(1, "-L and -n and mutually exclusive");
- if (discovery_host != NULL)
- xo_errx(1, "-L and -d and mutually exclusive");
- if (rflag != 0)
- xo_errx(1, "-L and -r and mutually exclusive");
-
- if (session_id != -1)
- xo_errx(1, "-i cannot be used with -L");
+ xo_errx(1, "-s cannot be used with -L");
}
iscsi_fd = open(ISCSI_PATH, O_RDWR);
@@ -948,7 +988,7 @@ main(int argc, char **argv)
failed += kernel_list(iscsi_fd, targ, vflag);
} else if (Mflag != 0) {
kernel_modify_some(iscsi_fd, session_id, target, portal,
- user, secret);
+ user, secret, enable);
} else {
if (Aflag != 0 && target != NULL) {
if (valid_iscsi_name(target) == false)
@@ -967,6 +1007,7 @@ main(int argc, char **argv)
targ->t_session_type = SESSION_TYPE_NORMAL;
targ->t_address = portal;
}
+ targ->t_enable = enable;
if (rflag != 0)
targ->t_protocol = PROTOCOL_ISER;
targ->t_user = user;
diff --git a/usr.bin/iscsictl/iscsictl.h b/usr.bin/iscsictl/iscsictl.h
index 727e8ae..18300a1 100644
--- a/usr.bin/iscsictl/iscsictl.h
+++ b/usr.bin/iscsictl/iscsictl.h
@@ -58,6 +58,10 @@
#define PROTOCOL_ISCSI 1
#define PROTOCOL_ISER 2
+#define ENABLE_UNSPECIFIED 0
+#define ENABLE_ON 1
+#define ENABLE_OFF 2
+
struct target {
TAILQ_ENTRY(target) t_next;
struct conf *t_conf;
@@ -71,6 +75,7 @@ struct target {
int t_data_digest;
int t_auth_method;
int t_session_type;
+ int t_enable;
int t_protocol;
char *t_offload;
char *t_user;
@@ -113,5 +118,6 @@ void print_periphs(int session_id);
char *checked_strdup(const char *);
bool valid_iscsi_name(const char *name);
+int parse_enable(const char *enable);
#endif /* !ISCSICTL_H */
diff --git a/usr.bin/iscsictl/parse.y b/usr.bin/iscsictl/parse.y
index 9941904..84c05b8 100644
--- a/usr.bin/iscsictl/parse.y
+++ b/usr.bin/iscsictl/parse.y
@@ -56,7 +56,7 @@ extern void yyrestart(FILE *);
%}
-%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
+%token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET
@@ -118,6 +118,8 @@ target_entry:
|
session_type
|
+ enable
+ |
offload
|
protocol
@@ -253,6 +255,17 @@ session_type: SESSION_TYPE EQUALS STR
}
;
+enable: ENABLE EQUALS STR
+ {
+ if (target->t_enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "duplicated enable at line %d", lineno);
+ target->t_enable = parse_enable($3);
+ if (target->t_enable == ENABLE_UNSPECIFIED)
+ xo_errx(1, "invalid enable at line %d; "
+ "must be either \"on\" or \"off\"", lineno);
+ }
+ ;
+
offload: OFFLOAD EQUALS STR
{
if (target->t_offload != NULL)
diff --git a/usr.bin/iscsictl/token.l b/usr.bin/iscsictl/token.l
index 8cf2fec..c9e3e72 100644
--- a/usr.bin/iscsictl/token.l
+++ b/usr.bin/iscsictl/token.l
@@ -62,6 +62,7 @@ tgtChapName { return MUTUAL_USER; }
tgtChapSecret { return MUTUAL_SECRET; }
AuthMethod { return AUTH_METHOD; }
SessionType { return SESSION_TYPE; }
+enable { return ENABLE; }
protocol { return PROTOCOL; }
offload { return OFFLOAD; }
port { return IGNORED; }
diff --git a/usr.bin/mkimg/image.c b/usr.bin/mkimg/image.c
index a3bec63..2527f28 100644
--- a/usr.bin/mkimg/image.c
+++ b/usr.bin/mkimg/image.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
+#include <err.h>
#include <errno.h>
#include <limits.h>
#include <paths.h>
@@ -315,6 +316,8 @@ image_file_unmap(void *buffer, size_t sz)
unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz;
sz = (sz + unit - 1) & ~(unit - 1);
+ if (madvise(buffer, sz, MADV_DONTNEED) != 0)
+ warn("madvise");
munmap(buffer, sz);
return (0);
}
diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c
index 5c883c4..b70a492 100644
--- a/usr.bin/sed/process.c
+++ b/usr.bin/sed/process.c
@@ -394,7 +394,7 @@ substitute(struct s_command *cp)
linenum, fname, cp->u.s->maxbref);
}
}
- if (!regexec_e(re, s, 0, 0, 0, psl))
+ if (!regexec_e(re, ps, 0, 0, 0, psl))
return (0);
SS.len = 0; /* Clean substitute space. */
@@ -404,7 +404,7 @@ substitute(struct s_command *cp)
do {
/* Copy the leading retained string. */
- if (n <= 1 && match[0].rm_so - le)
+ if (n <= 1 && (match[0].rm_so > le))
cspace(&SS, s, match[0].rm_so - le, APPEND);
/* Skip zero-length matches right after other matches. */
@@ -425,8 +425,8 @@ substitute(struct s_command *cp)
}
/* Move past this match. */
- s += (match[0].rm_eo - le);
- slen -= (match[0].rm_eo - le);
+ s = ps + match[0].rm_eo;
+ slen = psl - match[0].rm_eo;
le = match[0].rm_eo;
/*
@@ -446,7 +446,8 @@ substitute(struct s_command *cp)
} else
lastempty = 0;
- } while (n >= 0 && slen >= 0 && regexec_e(re, ps, 0, 0, le, psl));
+ } while (n >= 0 && slen >= 0 &&
+ regexec_e(re, ps, REG_NOTBOL, 0, le, psl));
/* Did not find the requested number of matches. */
if (n > 1)
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
index 98d86b5..7d533d0 100644
--- a/usr.bin/sockstat/sockstat.c
+++ b/usr.bin/sockstat/sockstat.c
@@ -390,7 +390,7 @@ gather_sctp(void)
if (sock->family == AF_INET)
sock->laddr->address.ss_len = sizeof(struct sockaddr_in);
else
- sock->laddr->address.ss_len = sizeof(struct sockaddr_in);
+ sock->laddr->address.ss_len = sizeof(struct sockaddr_in6);
local_all_loopback = 0;
}
if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL)
@@ -399,7 +399,7 @@ gather_sctp(void)
if (sock->family == AF_INET)
sock->faddr->address.ss_len = sizeof(struct sockaddr_in);
else
- sock->faddr->address.ss_len = sizeof(struct sockaddr_in);
+ sock->faddr->address.ss_len = sizeof(struct sockaddr_in6);
no_stcb = 1;
while (offset < len) {
xstcb = (struct xsctp_tcb *)(void *)(buf + offset);
diff --git a/usr.bin/xlint/llib/Makefile b/usr.bin/xlint/llib/Makefile
index bcf93c4..df79a75 100644
--- a/usr.bin/xlint/llib/Makefile
+++ b/usr.bin/xlint/llib/Makefile
@@ -16,6 +16,15 @@ llib-lstdc.ln: llib-lstdc
.include <bsd.prog.mk>
-.if ${MK_DIRDEPS_BUILD} == "yes"
+.if !empty(STAGE_INCLUDEDIR)
LINTFLAGS+= -I${STAGE_INCLUDEDIR}
+.else
+.if ${CFLAGS:M--sysroot=*} != ""
+_sysroot?= ${CFLAGS:M--sysroot=*:[1]:C,^--sysroot=,,}
+.elif ${CC:M--sysroot=*} != ""
+_sysroot?= ${CC:M--sysroot=*:[1]:C,^--sysroot=,,}
+.endif
+.if !empty(_sysroot)
+LINTFLAGS+= -I${_sysroot}/usr/include
+.endif
.endif
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 8dfe327..8c80266 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -113,6 +113,10 @@ SUBDIR.${MK_AUDIT}+= auditreduce
SUBDIR.${MK_AUDIT}+= praudit
SUBDIR.${MK_AUTHPF}+= authpf
SUBDIR.${MK_AUTOFS}+= autofs
+.if ${MK_BLACKLIST_SUPPORT} != "no"
+SUBDIR.${MK_BLACKLIST_SUPPORT}+= blacklistctl
+SUBDIR.${MK_BLACKLIST_SUPPORT}+= blacklistd
+.endif
SUBDIR.${MK_BLUETOOTH}+= bluetooth
SUBDIR.${MK_BOOTPARAMD}+= bootparamd
SUBDIR.${MK_BSDINSTALL}+= bsdinstall
diff --git a/usr.sbin/blacklistctl/Makefile b/usr.sbin/blacklistctl/Makefile
new file mode 100644
index 0000000..fd63b85
--- /dev/null
+++ b/usr.sbin/blacklistctl/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+BLACKLIST_DIR=${SRCTOP}/contrib/blacklist
+.PATH: ${BLACKLIST_DIR}/bin ${BLACKLIST_DIR}/port
+
+PROG= blacklistctl
+SRCS= blacklistctl.c conf.c state.c support.c internal.c \
+ sockaddr_snprintf.c pidfile.c strtoi.c popenve.c
+MAN= blacklistctl.8
+
+LDFLAGS+=-L${LIBBLACKLISTDIR}
+LIBADD+= blacklist util
+
+CFLAGS+=-I${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \
+ -D_PATH_BLCONTROL=\"/usr/libexec/blacklistd-helper\" \
+ -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \
+ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_FPARSELN \
+ -DHAVE_GETPROGNAME -DHAVE_STRLCAT -DHAVE_STRLCPY \
+ -DHAVE_STRUCT_SOCKADDR_SA_LEN
+# CFLAGS+= -D_REENTRANT
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/blacklistd/Makefile b/usr.sbin/blacklistd/Makefile
new file mode 100644
index 0000000..f509b8a
--- /dev/null
+++ b/usr.sbin/blacklistd/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+BLACKLIST_DIR=${SRCTOP}/contrib/blacklist
+.PATH: ${BLACKLIST_DIR}/bin ${BLACKLIST_DIR}/port
+
+PROG= blacklistd
+SRCS= blacklistd.c conf.c run.c state.c support.c internal.c \
+ sockaddr_snprintf.c pidfile.c strtoi.c popenve.c
+MAN= blacklistd.8
+
+LDFLAGS+=-L${LIBBLACKLISTDIR}
+LIBADD+= blacklist util
+
+CFLAGS+=-I${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \
+ -D_PATH_BLCONTROL=\"/usr/libexec/blacklistd-helper\" \
+ -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \
+ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_FPARSELN \
+ -DHAVE_GETPROGNAME -DHAVE_STRLCAT -DHAVE_STRLCPY \
+ -DHAVE_STRUCT_SOCKADDR_SA_LEN
+# CFLAGS+= -D_REENTRANT
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/ctld/ctl.conf.5 b/usr.sbin/ctld/ctl.conf.5
index 80b2f9e..cb624c5 100644
--- a/usr.sbin/ctld/ctl.conf.5
+++ b/usr.sbin/ctld/ctl.conf.5
@@ -226,6 +226,8 @@ An IPv4 or IPv6 address and port to listen on for incoming connections.
.It Ic offload Ar driver
Define iSCSI hardware offload driver to use for this
.Sy portal-group .
+The default is
+.Qq Ar none .
.It Ic option Ar name Ar value
The CTL-specific port options passed to the kernel.
.It Ic redirect Ar address
diff --git a/usr.sbin/keyserv/crypt_server.c b/usr.sbin/keyserv/crypt_server.c
index b4c6036..a97c2e1 100644
--- a/usr.sbin/keyserv/crypt_server.c
+++ b/usr.sbin/keyserv/crypt_server.c
@@ -180,12 +180,13 @@ void load_des(warn, libpath)
{
char dlpath[MAXPATHLEN];
- if (libpath == NULL) {
- snprintf(dlpath, sizeof(dlpath), "%s/%s", _PATH_USRLIB, LIBCRYPTO);
- } else
+ if (libpath == NULL)
+ snprintf(dlpath, sizeof(dlpath), "%s/%s", _PATH_USRLIB,
+ LIBCRYPTO);
+ else
snprintf(dlpath, sizeof(dlpath), "%s", libpath);
- if (dlpath != NULL && (dlhandle = dlopen(dlpath, 0444)) != NULL)
+ if ((dlhandle = dlopen(dlpath, 0444)) != NULL)
_my_crypt = (int (*)())dlsym(dlhandle, "_des_crypt");
if (_my_crypt == NULL) {
diff --git a/usr.sbin/rpc.statd/statd.c b/usr.sbin/rpc.statd/statd.c
index 256f58d..1a79ac2 100644
--- a/usr.sbin/rpc.statd/statd.c
+++ b/usr.sbin/rpc.statd/statd.c
@@ -72,9 +72,9 @@ static int create_service(struct netconfig *nconf);
static void complete_service(struct netconfig *nconf, char *port_str);
static void clearout_service(void);
static void handle_sigchld(int sig);
-void out_of_mem(void);
+void out_of_mem(void) __dead2;
-static void usage(void);
+static void usage(void) __dead2;
int
main(int argc, char **argv)
@@ -613,7 +613,7 @@ clearout_service(void)
}
static void
-usage()
+usage(void)
{
fprintf(stderr, "usage: rpc.statd [-d] [-h <bindip>] [-p <port>]\n");
exit(1);
@@ -647,7 +647,7 @@ static void handle_sigchld(int sig __unused)
* Out of memory, fatal
*/
void
-out_of_mem()
+out_of_mem(void)
{
syslog(LOG_ERR, "out of memory");
diff --git a/usr.sbin/rpcbind/check_bound.c b/usr.sbin/rpcbind/check_bound.c
index 23c38bc..b08979d 100644
--- a/usr.sbin/rpcbind/check_bound.c
+++ b/usr.sbin/rpcbind/check_bound.c
@@ -219,8 +219,7 @@ mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
uaddr, m_uaddr);
#endif
- if (allocated_uaddr != NULL)
- free(allocated_uaddr);
+ free(allocated_uaddr);
return (m_uaddr);
}
diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c
index 67c7f7b..b248bd3 100644
--- a/usr.sbin/rpcbind/rpcbind.c
+++ b/usr.sbin/rpcbind/rpcbind.c
@@ -85,7 +85,7 @@ rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
#define RPCBINDDLOCK "/var/run/rpcbind.lock"
-int runasdaemon = 0;
+static int runasdaemon = 0;
int insecure = 0;
int oldstyle_local = 0;
#ifdef LIBWRAP
@@ -93,12 +93,12 @@ int libwrap = 0;
#endif
int verboselog = 0;
-char **hosts = NULL;
-struct sockaddr **bound_sa;
-int ipv6_only = 0;
-int nhosts = 0;
-int on = 1;
-int rpcbindlockfd;
+static char **hosts = NULL;
+static struct sockaddr **bound_sa;
+static int ipv6_only = 0;
+static int nhosts = 0;
+static int on = 1;
+static int rpcbindlockfd;
#ifdef WARMSTART
/* Local Variable */
diff --git a/usr.sbin/rpcbind/util.c b/usr.sbin/rpcbind/util.c
index 25adcfc..1539b18 100644
--- a/usr.sbin/rpcbind/util.c
+++ b/usr.sbin/rpcbind/util.c
@@ -293,8 +293,7 @@ found:
ret = taddr2uaddr(nconf, &tbuf);
freeit:
- if (caller_uaddr != NULL)
- free(caller_uaddr);
+ free(caller_uaddr);
if (hint_nbp != NULL) {
free(hint_nbp->buf);
free(hint_nbp);
@@ -336,8 +335,10 @@ network_init(void)
if (local_in4 == NULL) {
if (debugging)
fprintf(stderr, "can't alloc local ip4 addr\n");
+ exit(1);
}
memcpy(local_in4, res->ai_addr, sizeof *local_in4);
+ freeaddrinfo(res);
}
#ifdef INET6
@@ -351,8 +352,10 @@ network_init(void)
if (local_in6 == NULL) {
if (debugging)
fprintf(stderr, "can't alloc local ip6 addr\n");
+ exit(1);
}
memcpy(local_in6, res->ai_addr, sizeof *local_in6);
+ freeaddrinfo(res);
}
/*
@@ -365,6 +368,11 @@ network_init(void)
inet_pton(AF_INET6, RPCB_MULTICAST_ADDR, &mreq6.ipv6mr_multiaddr);
s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1) {
+ if (debugging)
+ fprintf(stderr, "couldn't create ip6 socket");
+ goto done_inet6;
+ }
/*
* Loop through all interfaces. For each IPv6 multicast-capable
@@ -386,6 +394,8 @@ network_init(void)
if (debugging)
perror("setsockopt v6 multicast");
}
+done_inet6:
+ freeifaddrs(ifp);
#endif
/* close(s); */
diff --git a/usr.sbin/services_mkdb/services_mkdb.c b/usr.sbin/services_mkdb/services_mkdb.c
index fe23355..7a992c3 100644
--- a/usr.sbin/services_mkdb/services_mkdb.c
+++ b/usr.sbin/services_mkdb/services_mkdb.c
@@ -92,7 +92,7 @@ main(int argc, char *argv[])
size_t cnt = 0;
StringList *sl, ***svc;
size_t port, proto;
- char *dbname_dir;
+ char *dbname_dir, *dbname_dirbuf;
int dbname_dir_fd = -1;
setprogname(argv[0]);
@@ -172,7 +172,8 @@ main(int argc, char *argv[])
* fsync() to the directory where file lies
*/
if (rename(tname, dbname) == -1 ||
- (dbname_dir = dirname(dbname)) == NULL ||
+ (dbname_dirbuf = strdup(dbname)) == NULL ||
+ (dbname_dir = dirname(dbname_dirbuf)) == NULL ||
(dbname_dir_fd = open(dbname_dir, O_RDONLY|O_DIRECTORY)) == -1 ||
fsync(dbname_dir_fd) != 0) {
if (dbname_dir_fd != -1)
diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c
index ce9e148..4f0f2d0 100644
--- a/usr.sbin/tzsetup/tzsetup.c
+++ b/usr.sbin/tzsetup/tzsetup.c
@@ -199,6 +199,7 @@ static char *chrootenv = NULL;
static void usage(void);
static int confirm_zone(const char *filename);
static int continent_country_menu(dialogMenuItem *);
+static int install_zoneinfo(const char *zoneinfo);
static int install_zoneinfo_file(const char *zoneinfo_file);
static int set_zone_multi(dialogMenuItem *);
static int set_zone_whole_country(dialogMenuItem *);
@@ -633,13 +634,13 @@ set_zone_menu(dialogMenuItem *dmi)
return (DITEM_LEAVE_MENU);
}
-int
+static int
set_zone_utc(void)
{
if (!confirm_zone(NULL))
return (DITEM_FAILURE | DITEM_RECREATE);
- return (install_zoneinfo_file(NULL));
+ return (install_zoneinfo("UTC"));
}
static int
OpenPOWER on IntegriCloud